docs: rewrite JsonRpcBundle docs, add SDK docs, move them under docs/api
en/docs/api/mcp-bundle/config.md
new file +112
ā0
1
+
# MCP Bundle configuration
2
+
3
+
Configuration has two parts: **routes** define which endpoints exist and which API group and version each one serves; the **`ufo_mcp` configuration** only tunes the group's server. The configuration never decides which methods become tools or which version is served.
4
+
5
+
## Routes: one import per endpoint
6
+
7
+
```yaml
8
+
# config/routes/ufo_mcp.yaml
9
+
ufo_mcp:
10
+
resource: ../../vendor/ufo-tech/mcp-bundle/config/router.yaml
11
+
prefix: /mcp
12
+
defaults: { api_group: mcp }
13
+
14
+
ufo_mcp_internal:
15
+
resource: ../../vendor/ufo-tech/mcp-bundle/config/router.yaml
16
+
prefix: /mcp/internal
17
+
defaults: { api_group: internal }
18
+
```
19
+
20
+
* `api_group` is the core [API group](/docs/api/json-rpc-bundle/functionality/groups) the endpoint serves. Without it, the core default group `general` is used.
21
+
* Every import gets its own route names (`mcp_ufo_mcp_endpoint`, `internal_ufo_mcp_endpoint`, ā¦), so `name_prefix` is not needed. The core route loader does this for YAML imports; in PHP or XML route configuration set `name_prefix` by hand.
22
+
23
+
Every import serves:
24
+
25
+
| Route | Name | HTTP methods |
26
+
| --- | --- | --- |
27
+
| `<prefix>`, `<prefix>/{ver}` | `<group>_ufo_mcp_endpoint` | `POST`, `DELETE`, `OPTIONS`; `GET` answers 405 |
28
+
| `<prefix>/server.json`, `<prefix>/{ver}/server.json` | `<group>_ufo_mcp_server_json`, `<group>_ufo_mcp_server_json_ver` | `GET` |
29
+
| `<prefix>/manifest/{aiName}.json`, `<prefix>/{ver}/manifest/{aiName}.json` | `<group>_ufo_mcp_manifest`, `<group>_ufo_mcp_manifest_ver` | `GET` |
30
+
31
+
`{ver}` is `v1`, `v2`, ā¦; without it, `v1`.
32
+
33
+
## Configuration reference
34
+
35
+
File `config/packages/ufo_mcp.yaml`, root key `ufo_mcp`.
36
+
37
+
```yaml
38
+
ufo_mcp:
39
+
enabled: true
40
+
instructions: ~
41
+
max_body_bytes: 4194304
42
+
session_ttl: 3600
43
+
mcp_server_info:
44
+
name: 'io.github.your-org/your-app'
45
+
title: 'Your App MCP Server'
46
+
description: 'Exposes Your App RPC services as MCP tools.'
47
+
icons:
48
+
- src: 'https://example.com/icon.png'
49
+
mime_type: 'image/png'
50
+
sizes: ['128x128']
51
+
theme: ~
52
+
groups:
53
+
internal:
54
+
instructions: 'Internal tools.'
55
+
mcp_server_info:
56
+
name: 'io.github.your-org/your-app-internal'
57
+
```
58
+
59
+
| Parameter | Default | Description |
60
+
| --- | --- | --- |
61
+
| `enabled` | `true` | Whether the endpoint answers; otherwise 404. Supports `'%env(bool:MCP_ENABLED)%'` |
62
+
| `instructions` | `null` | The `instructions` field of the `initialize` response: a hint to the agent on how to use the server |
63
+
| `max_body_bytes` | `4194304` | Request body limit in bytes, >= 1; a larger body gets 413 |
64
+
| `session_ttl` | `3600` | How many seconds a session of the session-based protocol lives, >= 1 |
65
+
| `mcp_server_info.name` | `null` | Server id in reverse-DNS format for the MCP Registry; `serverInfo.name` in `initialize`. If unset: `ufo-rpc` in `initialize`, and the field is absent from `server.json` |
66
+
| `mcp_server_info.title` | `null` | `serverInfo.title` in `initialize` and `title` in `server.json` |
67
+
| `mcp_server_info.description` | `null` | `server.json` only |
68
+
| `mcp_server_info.icons[]` | `[]` | `server.json` only: `src` (required), `mime_type`, `sizes`, `theme` (`light` \| `dark`) |
69
+
| `groups.<group>` | ā | Optional per-group overrides: the same fields `enabled`, `instructions`, `max_body_bytes`, `session_ttl`, `mcp_server_info` |
70
+
71
+
* **`groups` is optional.** The route defines the group; a group without its own entry runs on the bundle-wide settings. An entry only overrides them field by field: an unset (or `~`) field inherits the bundle-wide value, `mcp_server_info` too (a group may set only `name`).
72
+
* **There is no version setting.** `serverInfo.version` in `initialize` and `version` in `server.json` are always the request's `{ver}`.
73
+
* Options of earlier builds (`session_directory`, `server_name`, `server_version`, `methods`) were removed; with them the configuration fails with "Unrecognized option".
74
+
75
+
:::warning
76
+
For a group, `max_body_bytes` and `session_ttl` are not validated by the configuration the way the bundle-wide values are. Set integers >= 1; see [Open issues](/docs/api/mcp-bundle/developers/known_issues/open).
77
+
:::
78
+
79
+
## API groups
80
+
81
+
The core `#[RPC\APIGroups]` attribute on a class or method decides which methods become tools:
82
+
83
+
```php
84
+
use Ufo\RpcObject\RPC;
85
+
86
+
#[RPC\Info('Catalog')]
87
+
#[RPC\APIGroups(['mcp', 'internal'], withDefault: false)]
88
+
final class CatalogProcedure implements IRpcService { /* /mcp and /mcp/internal, not /rpc */ }
89
+
90
+
#[RPC\Info('Admin')]
91
+
#[RPC\APIGroups(['internal'], withDefault: false)]
92
+
final class AdminProcedure implements IRpcService { /* only /mcp/internal */ }
93
+
```
94
+
95
+
The same group can be served by `/rpc/...` (JsonRpcBundle) and `/mcp/...` (this bundle) at the same time. Token checks for the group (`ufo_json_rpc.security.providers`) apply to MCP as well.
96
+
97
+
## API versions
98
+
99
+
`/mcp` and `/mcp/v1` serve version 1, `/mcp/v2` serves version 2 of the group in the core (`#[RPC\Info('Catalog', version: 2, removedMethods: [...])]`; a version inherits the previous one, see [API versions](/docs/api/json-rpc-bundle/functionality/versions)). A version the group does not have answers 404. A group without any method answers 404 too.
100
+
101
+
## Sessions and a shared cache
102
+
103
+
Clients of the session-based protocol (before 2026-07-28) get an `Mcp-Session-Id`. The session is stored in the core cache pool under the key `ufo_mcp_<group>_<session id>` with the group's `session_ttl`. By default this is a local filesystem pool; when several hosts serve MCP, point it to a shared store, otherwise a session created on one host is unknown on another:
104
+
105
+
```yaml
106
+
# config/packages/ufo_json_rpc.yaml
107
+
ufo_json_rpc:
108
+
cache:
109
+
pool: 'cache.app' # e.g. a shared Redis
110
+
```
111
+
112
+
Stateless clients of the 2026-07-28 protocol do not need session storage.