Installing MCP Bundle

Installing MCP Bundle

Requirements for version 1.x: PHP >= 8.4, Symfony ^7.2 or ^8.0, ufo-tech/json-rpc-bundle ^10.4.3, mcp/sdk ^0.8.1. The JsonRpcBundle server must already be installed.

Step 1: Installation

composer require ufo-tech/mcp-bundle

Step 2: Registering the bundle

Add the bundle to config/bundles.php next to JsonRpcBundle:

return [
    // ...
    Ufo\JsonRpcBundle\UfoJsonRpcBundle::class => ['all' => true],
    Ufo\McpBundle\UfoMcpBundle::class => ['all' => true],
];

Step 3: Configuration

There is no Symfony Flex recipe for the bundle yet: the configuration files are copied by hand.

Copy vendor/ufo-tech/mcp-bundle/install/packages/ufo_mcp.yaml to config/packages/. Minimal configuration:

# config/packages/ufo_mcp.yaml
ufo_mcp:
    enabled: true
    mcp_server_info:
        name: 'io.github.your-org/your-app'
        title: 'Your App MCP Server'

Without the file the bundle runs on defaults. All parameters are on the Configuration page.

Step 4: Registering routes

Copy vendor/ufo-tech/mcp-bundle/install/routes/ufo_mcp.yaml to config/routes/:

# config/routes/ufo_mcp.yaml
ufo_mcp:
    resource: ../../vendor/ufo-tech/mcp-bundle/config/router.yaml
    prefix: /mcp
    defaults: { api_group: mcp }

One import is one MCP endpoint serving one API group (api_group). To add another endpoint, import the same router.yaml again with a different prefix and api_group; see Routes.

Step 5: Methods for MCP

Add RPC methods to the endpoint's group with the #[RPC\APIGroups] attribute:

use Ufo\JsonRpcBundle\ApiMethod\Interfaces\IRpcService;
use Ufo\McpBundle\Attribute\McpTool;
use Ufo\RpcObject\RPC;

#[RPC\Info('Catalog')]
#[RPC\APIGroups(['mcp'], withDefault: false)]   // only /mcp, not /rpc
final class CatalogProcedure implements IRpcService
{
    /** Search products by name. */
    #[McpTool(readOnlyHint: true)]
    public function search(string $query, int $limit = 10): array
    {
        // ...
    }
}

withDefault: false removes the methods from the default group (/rpc); without it the methods are available both on /rpc and on /mcp.

#[McpTool] is optional: it only adds hints for the agent. Every method of the group becomes a tool; see Tools.

Verification

Request What it returns
POST /mcp The MCP endpoint (Streamable HTTP)
GET /mcp/manifest/claude.json A connection config for Claude Code (also cursor, gemini, openai)
GET /mcp/server.json The document for the MCP Registry

The Claude Code manifest:

Request:

curl https://example.com/mcp/manifest/claude.json

Response:

{
    "mcpServers": {
        "mcp": {
            "type": "http",
            "url": "https://example.com/mcp",
            "headers": {"Ufo-RPC-Token": "${UFO_MCP_TOKEN}"}
        }
    }
}

If protected_doc is enabled in JsonRpcBundle, add the token header to the request. Save the response as the project's .mcp.json and set the UFO_MCP_TOKEN environment variable: Claude Code will see the group's tools.

To list the tools without an AI client, use MCP Inspector:

npx -y @modelcontextprotocol/inspector --cli https://example.com/mcp \
    --transport http --header "Ufo-RPC-Token: change-me" --method tools/list

What next?