MCP Bundle

← MCP Bundle

Ashterix

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

en/docs/api/mcp-bundle/README.md new file +93 āˆ’0

1 + # MCP Bundle
2 +
3 + :::block class="floatinginfobox"
4 + <include>(docs/api/mcp-bundle/.info.md)
5 + :::
6 +
7 + An MCP server ([Model Context Protocol](https://modelcontextprotocol.io)) for [JsonRpcBundle](/docs/api/json-rpc-bundle): the methods of your JSON-RPC API become tools that AI agents (Claude Code, Cursor, Gemini CLI, OpenAI) call over Streamable HTTP.
8 +
9 + It is a thin adapter, like [REST Bundle](/docs/api/rest-bundle): business logic stays in the RPC services, and every tool call is a regular RPC request executed by JsonRpcBundle. Parameter conversion, DTOs, validation, caching, locking, events and the error format are the same as on `/rpc`.
10 +
11 + ## From method to tool
12 +
13 + ::::columns
14 + :::col
15 + **Your code**
16 +
17 + ```php
18 + use Ufo\JsonRpcBundle\ApiMethod\Interfaces\IRpcService;
19 + use Ufo\McpBundle\Attribute\McpTool;
20 + use Ufo\RpcObject\RPC;
21 +
22 + #[RPC\Info('Catalog')]
23 + #[RPC\APIGroups(['mcp'], withDefault: false)]
24 + final class CatalogProcedure implements IRpcService
25 + {
26 + /**
27 + * Search products by name.
28 + * @param string $query Part of the product name
29 + */
30 + #[McpTool(readOnlyHint: true)]
31 + public function search(string $query, int $limit = 10): array
32 + {
33 + // ...
34 + }
35 + }
36 + ```
37 + :::
38 +
39 + :::col
40 + **`tools/list` on `/mcp`** (abridged)
41 +
42 + ```json
43 + {
44 + "name": "Catalog.search",
45 + "description": "Search products by name.",
46 + "inputSchema": {
47 + "type": "object",
48 + "properties": {
49 + "query": {"type": "string", "description": "Part of the product name"},
50 + "limit": {"type": "integer", "default": 10}
51 + },
52 + "additionalProperties": false,
53 + "required": ["query"]
54 + },
55 + "annotations": {"readOnlyHint": true}
56 + }
57 + ```
58 + :::
59 + ::::
60 +
61 + Nothing else to write:
62 +
63 + * `POST /mcp` is an MCP server with the `Catalog.search` tool, protected by the RPC token;
64 + * `GET /mcp/manifest/claude.json` returns a ready Claude Code connection config (likewise `cursor`, `gemini`, `openai`);
65 + * `GET /mcp/server.json` is the document for publishing in the MCP Registry.
66 +
67 + ## Features
68 +
69 + * **The API group decides what becomes a tool.** Every method of a [group](/docs/api/json-rpc-bundle/functionality/groups) is a tool named after the RPC method. Several endpoints (`/mcp`, `/mcp/internal`, …) side by side, each with its own methods ([Configuration](/docs/api/mcp-bundle/config)).
70 + * **API versions.** `/mcp/v2` serves [version](/docs/api/json-rpc-bundle/functionality/versions) 2 of the group.
71 + * **The core does the work.** A tool call goes through the JsonRpcBundle `RpcExecutor` ([Tools](/docs/api/mcp-bundle/tools)).
72 + * **Schemas and texts for agents.** `inputSchema` / `outputSchema` from method metadata; titles and descriptions from the core translations by `Accept-Language`, including per group; `#[McpTool]` hints.
73 + * **Both MCP protocol eras** on one URL: session-based (sessions in the core cache pool) and stateless 2026-07-28 ([HTTP and security](/docs/api/mcp-bundle/http_security)).
74 + * **The same security.** Core RPC tokens (401/403), 404 for a disabled group or a missing version, CORS, DNS rebinding protection, request body limit.
75 + * **Discovery.** `server.json` for the MCP Registry and client manifests ([server.json and manifests](/docs/api/mcp-bundle/discovery)).
76 + * **Extensibility.** Availability check, access policy, custom client manifests ([For developers](/docs/api/mcp-bundle/developers/extensions)).
77 +
78 + ## Limitations
79 +
80 + * No OAuth: access is the RPC token in a header ([HTTP and security](/docs/api/mcp-bundle/http_security)).
81 + * Tools only: no MCP resources or prompts. The SDK declares the `logging` and `completions` capabilities by default, but the bundle does not use them.
82 + * No server-initiated messages (`GET` on the endpoint answers 405) and no [asynchronous](/docs/api/json-rpc-bundle/functionality/async) or [webhook](/docs/api/json-rpc-bundle/functionality/callback) calls through MCP.
83 +
84 + :::info
85 + <include>(change_log/latest.md)
86 + :::
87 +
88 + ## Getting started
89 +
90 + 1. [Install the bundle](/docs/api/mcp-bundle/installation) and add the MCP routes.
91 + 2. Add RPC methods to the endpoint's group and check `tools/list`.
92 + 3. Configure the [group's server](/docs/api/mcp-bundle/config) and, if needed, [CORS and hosts](/docs/api/mcp-bundle/http_security).
93 + 4. Connect a client using a [manifest](/docs/api/mcp-bundle/discovery).

en/docs/api/mcp-bundle/.info.md new file +65 āˆ’0

1 + :::::columns border="1" zebra="1"
2 + ::::row
3 + :::col width="40%"
4 + Download
5 + :::
6 +
7 + :::col
8 + [Packagist](https://packagist.org/packages/ufo-tech/mcp-bundle)<br>
9 + [GitHub](https://github.com/UFO-Tech/mcp-bundle)
10 + :::
11 + ::::
12 +
13 + ::::row
14 + :::col width="40%"
15 + Current version
16 + :::
17 +
18 + :::col
19 + [![](https://img.shields.io/github/v/tag/ufo-tech/mcp-bundle?color=blue&label=&logo=Packagist&logoColor=white&labelColor=7b8185)](https://packagist.org/packages/ufo-tech/mcp-bundle)
20 + :::
21 + ::::
22 +
23 + ::::row
24 + :::col width="40%"
25 + Category
26 + :::
27 +
28 + :::col
29 + API
30 + :::
31 + ::::
32 +
33 + ::::row
34 + :::col width="40%"
35 + Type
36 + :::
37 +
38 + :::col
39 + Symfony Bundle
40 + :::
41 + ::::
42 +
43 + ::::row
44 + :::col width="40%"
45 + Dependencies
46 + :::
47 +
48 + :::col
49 + ![php_version](https://img.shields.io/packagist/dependency-v/ufo-tech/mcp-bundle/php?logo=PHP&logoColor=white)
50 + ![json_rpc_bundle](https://img.shields.io/packagist/dependency-v/ufo-tech/mcp-bundle/ufo-tech/json-rpc-bundle?label=JsonRpcBundle)
51 + ![mcp_sdk](https://img.shields.io/packagist/dependency-v/ufo-tech/mcp-bundle/mcp/sdk?label=mcp/sdk)
52 + :::
53 + ::::
54 +
55 + ::::row
56 + :::col width="40%"
57 + Other information
58 + :::
59 +
60 + :::col
61 + ![License](https://img.shields.io/badge/license-MIT-green?labelColor=7b8185)
62 + ![Size](https://img.shields.io/github/repo-size/ufo-tech/mcp-bundle?label=Size%20of%20the%20repository)
63 + :::
64 + ::::
65 + :::::

en/docs/api/mcp-bundle/change_log/latest.md new file +1 āˆ’0

1 + <include>(1.0.0.md)

en/docs/api/mcp-bundle/change_log/1.0.0.md new file +25 āˆ’0

1 + ## Version 1.0 (2026-10-19)
2 +
3 + First release: the RPC methods of an API group as MCP tools over Streamable HTTP.
4 +
5 + ### Key changes
6 +
7 + * [An endpoint per route import](/docs/api/mcp-bundle/config): `api_group` is the core API group, `/mcp/v2` is API version 2; route names contain the group (`mcp_ufo_mcp_endpoint`, …).
8 + * [Tools](/docs/api/mcp-bundle/tools): every method of the group; titles and descriptions from the core translations (including `translations/rpc/<group>.<locale>.yaml`) by `Accept-Language`; self-contained `inputSchema` / `outputSchema`; `#[McpTool]` hints.
9 + * `tools/call` through the core `RpcExecutor`: `structuredContent: {"result": …}` plus the same JSON as text; errors are the core RPC error with `isError: true`; `rpc.post_response` after the response is sent, once per call (also in a batch).
10 + * [HTTP and security](/docs/api/mcp-bundle/http_security): the session-based protocol (sessions in the core cache pool) and stateless 2026-07-28 on one URL; core tokens (401/403); 404 for a disabled group or a missing version; CORS, DNS rebinding protection, `max_body_bytes`.
11 + * [Discovery](/docs/api/mcp-bundle/discovery): `server.json` for the MCP Registry, manifests for Claude Code, Cursor, Gemini CLI, OpenAI.
12 +
13 + ### What to keep in mind
14 +
15 + Only applies to applications that used the bundle from `dev-main` before 1.0.0:
16 +
17 + * The `session_directory` option (bundle-wide and per group) was removed, sessions live in the core cache pool; remove the key, otherwise "Unrecognized option". `groups` may now be empty.
18 + * Route names contain the group (`<group>_ufo_mcp_endpoint`); a manual `name_prefix` in YAML imports is no longer needed.
19 + * Titles and descriptions come only from the core translations: `ToolTextResolverInterface` and `Ufo\McpBundle\I18n\*` were removed.
20 + * Classes moved from `Ufo\McpBundle\Services\*` to `Server\*`, `Server\Transport\*`, `Tool\*`; the group, availability and token checks moved from `McpController` to `EventListener\McpRequestListener`.
21 +
22 + ### Environment changes
23 +
24 + * PHP >= 8.4, Symfony ^7.2 | ^8.0 (through JsonRpcBundle).
25 + * `ufo-tech/json-rpc-bundle` ^10.4.3, `mcp/sdk` ^0.8.1, `symfony/psr-http-message-bridge` ^7.2 | ^8.0, `symfony/yaml` ^7.2 | ^8.0, `nyholm/psr7` ^1.8.