docs: rewrite JsonRpcBundle docs, add SDK docs, move them under docs/api
en/docs/api/mcp-bundle/README.md
new file +93
−0
MCP Bundle
<include>(docs/api/mcp-bundle/.info.md)
An MCP server (Model Context Protocol) for JsonRpcBundle: the methods of your JSON-RPC API become tools that AI agents (Claude Code, Cursor, Gemini CLI, OpenAI) call over Streamable HTTP.
It is a thin adapter, like 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.
From method to tool
Your code
use Ufo\JsonRpcBundle\ApiMethod\Interfaces\IRpcService;
use Ufo\McpBundle\Attribute\McpTool;
use Ufo\RpcObject\RPC;
#[RPC\Info('Catalog')]
#[RPC\APIGroups(['mcp'], withDefault: false)]
final class CatalogProcedure implements IRpcService
{
/**
* Search products by name.
* @param string $query Part of the product name
*/
#[McpTool(readOnlyHint: true)]
public function search(string $query, int $limit = 10): array
{
// ...
}
}
tools/list on /mcp (abridged)
{
"name": "Catalog.search",
"description": "Search products by name.",
"inputSchema": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "Part of the product name"},
"limit": {"type": "integer", "default": 10}
},
"additionalProperties": false,
"required": ["query"]
},
"annotations": {"readOnlyHint": true}
}
Nothing else to write:
POST /mcpis an MCP server with theCatalog.searchtool, protected by the RPC token;GET /mcp/manifest/claude.jsonreturns a ready Claude Code connection config (likewisecursor,gemini,openai);GET /mcp/server.jsonis the document for publishing in the MCP Registry.
Features
- The API group decides what becomes a tool. Every method of a group is a tool named after the RPC method. Several endpoints (
/mcp,/mcp/internal, …) side by side, each with its own methods (Configuration). - API versions.
/mcp/v2serves version 2 of the group. - The core does the work. A tool call goes through the JsonRpcBundle
RpcExecutor(Tools). - Schemas and texts for agents.
inputSchema/outputSchemafrom method metadata; titles and descriptions from the core translations byAccept-Language, including per group;#[McpTool]hints. - Both MCP protocol eras on one URL: session-based (sessions in the core cache pool) and stateless 2026-07-28 (HTTP and security).
- The same security. Core RPC tokens (401/403), 404 for a disabled group or a missing version, CORS, DNS rebinding protection, request body limit.
- Discovery.
server.jsonfor the MCP Registry and client manifests (server.json and manifests). - Extensibility. Availability check, access policy, custom client manifests (For developers).
Limitations
- No OAuth: access is the RPC token in a header (HTTP and security).
- Tools only: no MCP resources or prompts. The SDK declares the
loggingandcompletionscapabilities by default, but the bundle does not use them. - No server-initiated messages (
GETon the endpoint answers 405) and no asynchronous or webhook calls through MCP.
<include>(change_log/latest.md)
Getting started
- Install the bundle and add the MCP routes.
- Add RPC methods to the endpoint's group and check
tools/list. - Configure the group's server and, if needed, CORS and hosts.
- Connect a client using a manifest.
en/docs/api/mcp-bundle/.info.md
new file +65
−0
en/docs/api/mcp-bundle/change_log/latest.md
new file +1
−0
<include>(1.0.0.md)
en/docs/api/mcp-bundle/change_log/1.0.0.md
new file +25
−0
Version 1.0 (2026-10-19)
First release: the RPC methods of an API group as MCP tools over Streamable HTTP.
Key changes
- An endpoint per route import:
api_groupis the core API group,/mcp/v2is API version 2; route names contain the group (mcp_ufo_mcp_endpoint, …). - Tools: every method of the group; titles and descriptions from the core translations (including
translations/rpc/<group>.<locale>.yaml) byAccept-Language; self-containedinputSchema/outputSchema;#[McpTool]hints. tools/callthrough the coreRpcExecutor:structuredContent: {"result": …}plus the same JSON as text; errors are the core RPC error withisError: true;rpc.post_responseafter the response is sent, once per call (also in a batch).- HTTP and 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. - Discovery:
server.jsonfor the MCP Registry, manifests for Claude Code, Cursor, Gemini CLI, OpenAI.
What to keep in mind
Only applies to applications that used the bundle from dev-main before 1.0.0:
- The
session_directoryoption (bundle-wide and per group) was removed, sessions live in the core cache pool; remove the key, otherwise "Unrecognized option".groupsmay now be empty. - Route names contain the group (
<group>_ufo_mcp_endpoint); a manualname_prefixin YAML imports is no longer needed. - Titles and descriptions come only from the core translations:
ToolTextResolverInterfaceandUfo\McpBundle\I18n\*were removed. - Classes moved from
Ufo\McpBundle\Services\*toServer\*,Server\Transport\*,Tool\*; the group, availability and token checks moved fromMcpControllertoEventListener\McpRequestListener.
Environment changes
- PHP >= 8.4, Symfony ^7.2 | ^8.0 (through JsonRpcBundle).
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.