Налаштування MCP Bundle

← Налаштування MCP Bundle

Ashterix

docs: rewrite JsonRpcBundle docs, add SDK docs, move them under docs/api

uk/docs/api/mcp-bundle/config.md новий файл +112 −0

1 + # Налаштування MCP Bundle
2 +
3 + Налаштування складається з двох частин: **маршрути** визначають, які ендпоінти існують, яку групу і версію API кожен обслуговує; **конфігурація** `ufo_mcp` лише налаштовує сервер групи. Конфігурація ніколи не вирішує, які методи стають інструментами і яка версія обслуговується.
4 +
5 + ## Маршрути: один імпорт на ендпоінт
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` — [група API](/docs/api/json-rpc-bundle/functionality/groups) ядра, яку обслуговує ендпоінт. Без нього — типова група ядра `general`.
21 + * Кожен імпорт отримує власні назви маршрутів (`mcp_ufo_mcp_endpoint`, `internal_ufo_mcp_endpoint`, …), тож `name_prefix` не потрібен. Це робить завантажувач маршрутів ядра для YAML-імпортів; у конфігурації маршрутів на PHP чи XML задавайте `name_prefix` вручну.
22 +
23 + Кожен імпорт обслуговує:
24 +
25 + | Маршрут | Назва | Методи HTTP |
26 + | --- | --- | --- |
27 + | `<prefix>`, `<prefix>/{ver}` | `<group>_ufo_mcp_endpoint` | `POST`, `DELETE`, `OPTIONS`; `GET` відповідає 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}` — `v1`, `v2`, …; без нього — `v1`.
32 +
33 + ## Довідник конфігурації
34 +
35 + Файл `config/packages/ufo_mcp.yaml`, кореневий ключ `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 + | Параметр | За замовчуванням | Опис |
60 + | --- | --- | --- |
61 + | `enabled` | `true` | Чи відповідає ендпоінт; інакше 404. Підтримує `'%env(bool:MCP_ENABLED)%'` |
62 + | `instructions` | `null` | Поле `instructions` у відповіді `initialize` — підказка агенту, як користуватися сервером |
63 + | `max_body_bytes` | `4194304` | Ліміт тіла запиту в байтах, >= 1; більше тіло — 413 |
64 + | `session_ttl` | `3600` | Скільки секунд живе сесія протоколу із сесіями, >= 1 |
65 + | `mcp_server_info.name` | `null` | Ідентифікатор сервера у форматі reverse-DNS для MCP Registry; `serverInfo.name` в `initialize`. Якщо не задано — `ufo-rpc` в `initialize` і поле відсутнє в `server.json` |
66 + | `mcp_server_info.title` | `null` | `serverInfo.title` в `initialize` і `title` у `server.json` |
67 + | `mcp_server_info.description` | `null` | Лише для `server.json` |
68 + | `mcp_server_info.icons[]` | `[]` | Лише для `server.json`: `src` (обов'язковий), `mime_type`, `sizes`, `theme` (`light` \| `dark`) |
69 + | `groups.<group>` | — | Необов'язкові перевизначення для групи: ті самі поля `enabled`, `instructions`, `max_body_bytes`, `session_ttl`, `mcp_server_info` |
70 +
71 + * **`groups` — необов'язковий.** Групу визначає маршрут; група без власного запису працює на загальних налаштуваннях бандла. Запис лише перевизначає їх поле за полем: незадане (або `~`) поле успадковує загальне значення, `mcp_server_info` теж (група може задати лише `name`).
72 + * **Налаштування версії немає.** `serverInfo.version` в `initialize` і `version` у `server.json` — це завжди `{ver}` запиту.
73 + * Опції попередніх збірок (`session_directory`, `server_name`, `server_version`, `methods`) прибрано; з ними конфігурація падає з «Unrecognized option».
74 +
75 + :::warning
76 + Для групи `max_body_bytes` і `session_ttl` не перевіряються конфігурацією так, як загальні значення. Задавайте цілі числа >= 1 — див. [Актуальні помилки](/docs/api/mcp-bundle/developers/known_issues/open).
77 + :::
78 +
79 + ## Групи API
80 +
81 + Які методи стають інструментами, визначає атрибут ядра `#[RPC\APIGroups]` на класі чи методі:
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 і /mcp/internal, не /rpc */ }
89 +
90 + #[RPC\Info('Admin')]
91 + #[RPC\APIGroups(['internal'], withDefault: false)]
92 + final class AdminProcedure implements IRpcService { /* лише /mcp/internal */ }
93 + ```
94 +
95 + Ту саму групу можуть одночасно обслуговувати `/rpc/...` (JsonRpcBundle) і `/mcp/...` (цей бандл). Перевірка токенів для групи (`ufo_json_rpc.security.providers`) діє і для MCP.
96 +
97 + ## Версії API
98 +
99 + `/mcp` і `/mcp/v1` обслуговують версію 1, `/mcp/v2` — версію 2 групи в ядрі (`#[RPC\Info('Catalog', version: 2, removedMethods: [...])]`; версія успадковує попередню, див. [Версії API](/docs/api/json-rpc-bundle/functionality/versions)). Версія, якої в групи немає, відповідає 404. Група без жодного методу теж відповідає 404.
100 +
101 + ## Сесії та спільний кеш
102 +
103 + Клієнти протоколу із сесіями (до 2026-07-28) отримують `Mcp-Session-Id`. Сесія зберігається в пулі кешу ядра під ключем `ufo_mcp_<group>_<session id>` з `session_ttl` групи. Типово це локальний пул на файловій системі; коли MCP обслуговують кілька хостів, спрямуйте його на спільне сховище, інакше сесія, створена на одному хості, буде невідома на іншому:
104 +
105 + ```yaml
106 + # config/packages/ufo_json_rpc.yaml
107 + ufo_json_rpc:
108 + cache:
109 + pool: 'cache.app' # наприклад, спільний Redis
110 + ```
111 +
112 + Stateless-клієнтам протоколу 2026-07-28 сховище сесій не потрібне.