docs: rewrite JsonRpcBundle docs, add SDK docs, move them under docs/api
en/docs/api/json-rpc-bundle/developers/README.md
new file +122
ā0
1
+
# For developers
2
+
3
+
JsonRpcBundle is not a closed "all-in-one" product but a core on which you can build your own solutions. It covers the foundation of any RPC API: receiving requests, the method map, validation, data conversion, security, caching and documentation. Everything beyond that ā new transports, protocols, integrations, tools ā is meant to be an extension.
4
+
5
+
This section is for those who want to understand how the bundle works internally and extend it: in their own project or as a separate package for the community.
6
+
7
+
## Principles the bundle is built on
8
+
9
+
**Code is the single source of truth.** API methods are ordinary PHP methods. Names, types, PHPDoc, attributes and validation constraints define both behavior and documentation at once, so the two never diverge.
10
+
11
+
**Minimal configuration.** Implementing `IRpcService` is enough ā the bundle derives the rest itself: the method map, parameter and result schemas, type conversion. Configuration is needed only where there is a real choice.
12
+
13
+
**Transport independence.** A procedure does not know where the request came from: HTTP, the console, a message queue, REST or MCP via an extension. Validation, security, caching and events are the same for all.
14
+
15
+
**Open for extension.** Key processing stages are events, and the main mechanisms are interfaces with autoconfiguration: parameter converters, schema generators, method sources, batch strategies, token validators, route loaders. New behavior is added without changing the core.
16
+
17
+
**Native Symfony mechanisms.** DI container, EventDispatcher, Messenger, Lock, Validator, Cache, Translation ā the bundle does not reinvent its own counterparts, so extensions are written in the usual Symfony ways.
18
+
19
+
**Standards compliance.** The protocol is [JSON-RPC 2.0](https://www.jsonrpc.org/specification), the documentation is [OpenRPC](https://spec.open-rpc.org/). Clients and tools that support these standards work with the API without adaptation.
20
+
21
+
**Performance without sacrifices.** The method map and metadata are built at container compile time, documentation is cached, and expensive work is moved to after the response has been sent.
22
+
23
+
## What is in this section
24
+
25
+
* [Lifecycle](/docs/api/json-rpc-bundle/developers/lifecycle) ā how a request passes through the bundle for each entry point and at which moment each event is fired.
26
+
* [Extensions](/docs/api/json-rpc-bundle/developers/extensions) ā a list of available extensions.
27
+
* [Lifecycle events](/docs/api/json-rpc-bundle/functionality/events) ā each event in detail, with listener examples.
28
+
* [Rules for AI assistants](/docs/api/json-rpc-bundle/developers/ai) ā instruction files for Claude Code, Codex, Cursor, Copilot that plug into your existing rules.
29
+
* [Known issues](/docs/api/json-rpc-bundle/developers/known_issues/open) ā what does not work as expected and how to work around it.
30
+
31
+
## General guidelines for extensions
32
+
33
+
1. **Do not duplicate the core.** An extension should not have its own method map, validation or error format. Methods come from `ServiceMap` / `IServiceHolder`, execution goes through `RpcExecutor`, errors through `rpc.error`. Then `#[RPC\Assertions]`, `#[RPC\Cache]`, `#[RPC\Lock]`, converters and events work for your transport automatically.
34
+
2. **Respect API groups and versions.** Determine the [group](/docs/api/json-rpc-bundle/functionality/groups) from the route or configuration and write it to `ApiGroupContext`; pass the version in `RpcRequest`.
35
+
3. **Check the token yourself.** `RpcExecutor` does not check the token. Use `IRpcSecurity` with an appropriate token holder ā this way the same `security.providers` apply as for the main API.
36
+
4. **Register routes via the core import.** Then each import for a separate group gets unique route names.
37
+
5. **Core dependency ā `ufo-tech/json-rpc-bundle: ^10.4.2`** or newer, if you use `RpcExecutor` and `IApiRouteImport`.
38
+
6. **Components created at compile time** (`IServiceFiller`, `IConstraintGenerator`, `IParamConvertor`) are instantiated by the bundle itself while building the container. Their constructors may accept only services available at compile time or tagged collections ā not scalar parameters.
39
+
40
+
## Extension points
41
+
42
+
| What | How | What for |
43
+
| --- | --- | --- |
44
+
| `Routing\IApiRouteImport` | autoconfiguration, tag `ufo.rpc.route_import` | Load the extension's `router.yaml` separately for each API group: `getResource()`, `getRouteNamePrefixAttribute()` |
45
+
| `Routing\RpcYamlFileLoader` / `ApiYamlFileLoader` | inheritance, tag `routing.loader` | Older way of writing a custom route loader |
46
+
| `Server\RpcExecutor` | autowiring | `execute(IRpcRequestCarrier): RpcResponse` ā execute a request through the full core cycle |
47
+
| `Server\RequestPrepare\IRpcRequestCarrier` / `IRpcHttpCarrier` | implementation | Wrapper for your incoming request. `IRpcHttpCarrier::getHttpRequest()` binds `rpc.post_response` to the HTTP request and enables detached execution of notifications |
48
+
| `Server\ServiceMap\IServiceHolder` | tag `rpc.service_holder` (manual) | Custom method source or a filter on top of `ServiceMap` |
49
+
| `Security\Interfaces\IRpcSecurity`, `IRpcTokenHolder` | alias / implementation | Token check from your source (header, parameter, message) |
50
+
| `Security\Interfaces\ITokenValidator` | alias or `security.providers` | Custom token validation |
51
+
| `ParamConvertors\IParamConvertor` | autoconfiguration, tag `rpc.param_convertor` | Conversion of custom parameter and result types |
52
+
| `...\Reflections\Fillers\AbstractServiceFiller` | autoconfiguration, tag `ufo-rpc.service-iterator` | Reading custom method attributes into `Service` metadata |
53
+
| `...\Generate\Interfaces\IConstraintGenerator` | tag `rpc.constraint` | JSON Schema for custom validation constraints |
54
+
| `Server\Batch\IBatchStrategy` | autoconfiguration, tag `rpc.batch_strategy` | Custom batch execution strategy |
55
+
| `DocAdapters\Outputs\AbstractPostmanAdapter` | inheritance | Postman collection for your transport |
56
+
| `Server\RpcLocaleNegotiator` | autowiring | Language selection from `Accept-Language` for custom documentation |
57
+
| `translations.paths` | `prependExtensionConfig()` | Translations of method names and descriptions shipped by the extension |
58
+
| [Events](/docs/api/json-rpc-bundle/functionality/events) | `#[AsEventListener]` | Behavior around method execution |
59
+
60
+
### Minimal adapter
61
+
62
+
```php
63
+
// extension routes for each API group
64
+
final class AcmeRouteImport implements IApiRouteImport
65
+
{
66
+
public function getResource(): string { return __DIR__.'/../../config/router.yaml'; }
67
+
public function getRouteNamePrefixAttribute(): string { return '_acme_name_prefix'; }
68
+
}
69
+
70
+
// extension controller
71
+
final class AcmeController
72
+
{
73
+
public function __construct(
74
+
private RpcExecutor $executor,
75
+
private IRpcSecurity $security,
76
+
) {}
77
+
78
+
public function __invoke(Request $request): JsonResponse
79
+
{
80
+
$this->security->setTokenHolder(new HttpTokenHolder(/* ... */));
81
+
$this->security->isValidApiRequest();
82
+
83
+
$response = $this->executor->execute(new RpcFromAcme($request));
84
+
85
+
return new JsonResponse(/* serialized $response */);
86
+
}
87
+
}
88
+
```
89
+
90
+
```php
91
+
// translations shipped by the extension
92
+
public function prepend(ContainerBuilder $container): void
93
+
{
94
+
$container->prependExtensionConfig('ufo_json_rpc', [
95
+
'translations' => ['paths' => [__DIR__.'/../../translations']],
96
+
]);
97
+
}
98
+
```
99
+
100
+
Working examples are in the code of `mcp-bundle` and `rest-bundle` (see [Extensions](/docs/api/json-rpc-bundle/developers/extensions)).
101
+
102
+
## Growing the ecosystem
103
+
104
+
We strongly encourage the growth of the ecosystem around the bundle. Every new transport, adapter or tool makes JSON-RPC on Symfony more convenient for everyone.
105
+
106
+
**Write extensions.** If you are missing an integration ā with a message broker, a protocol, a monitoring system or a client generator ā package it separately following the general guidelines above. Tell us about it, and we will add it to the [list of extensions](/docs/api/json-rpc-bundle/developers/extensions).
107
+
108
+
**Report problems.** Found a bug or a mismatch with the documentation? Create an issue in the [bundle repository](https://github.com/UFO-Tech/json-rpc-bundle/issues). We describe confirmed problems in the [Known issues](/docs/api/json-rpc-bundle/developers/known_issues/open) section.
109
+
110
+
**Propose changes to the core.** If an extension lacks an extension point, that is a signal it should be added to the core. The contribution process is described in [CONTRIBUTING.md](https://github.com/UFO-Tech/json-rpc-bundle/blob/main/CONTRIBUTING.md):
111
+
112
+
1. Fork the repository and create a separate branch.
113
+
2. Before starting, check the issue tracker; if there is no discussion yet, create an issue with your proposal.
114
+
3. Follow the project's code style.
115
+
4. Add tests for new features; all existing tests must pass.
116
+
5. Describe in the pull request what problem is solved or what is added, and be ready for discussion.
117
+
118
+
By participating in the project, you agree to follow the [code of conduct](https://github.com/UFO-Tech/json-rpc-bundle/blob/main/CODE_OF_CONDUCT.md).
119
+
120
+
:::info
121
+
Report security vulnerabilities not through public issues but via the contact in the repository's [SECURITY.md](https://github.com/UFO-Tech/json-rpc-bundle/blob/main/SECURITY.md).
122
+
:::