MCP Bundle

← MCP Bundle

Ashterix

docs: English JsonRpcBundle docs, REST and MCP Bundle sections, package cards

en/docs/api/mcp-bundle/README.md +1 −1

MCP Bundle

<include>(docs/api/mcp-bundle/.info.md)

<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 /mcp is an MCP server with the Catalog.search tool, protected by the RPC token;
  • GET /mcp/manifest/claude.json returns a ready Claude Code connection config (likewise cursor, gemini, openai);
  • GET /mcp/server.json is 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/v2 serves 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 / outputSchema from method metadata; titles and descriptions from the core translations by Accept-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.json for 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 logging and completions capabilities by default, but the bundle does not use them.
  • No server-initiated messages (GET on the endpoint answers 405) and no asynchronous or webhook calls through MCP.

<include>(change_log/latest.md)

Getting started

  1. Install the bundle and add the MCP routes.
  2. Add RPC methods to the endpoint's group and check tools/list.
  3. Configure the group's server and, if needed, CORS and hosts.
  4. Connect a client using a manifest.

en/docs/api/mcp-bundle/.info.md +17 −62

Current version

Category

API

Type

Symfony Bundle

Dependencies

php_version json_rpc_bundle mcp_sdk

Other information

License Size

Version Downloads Stars

composer require ufo-tech/mcp-bundle
  • PHP 8.4+
  • Symfony 7.2+ · 8
  • Built on JsonRpcBundle 10.4.3+ · mcp/sdk 0.8
  • Protocol MCP · Streamable HTTP
  • Type Symfony Bundle
  • Category API · AI
  • License MIT