Skip to content

ResponseCachingMiddleware breaks imported/mounted server prefixes #2300

@wipash

Description

@wipash

Description

When using ResponseCachingMiddleware, prefixes of imported/mounted MCP servers are not returned in response to tools/list.
The tools still require the prefix in order to be called though.

Everything works fine when not using ResponseCachingMiddleware.

// List tools

curl -X POST http://localhost:8000/mcp \
                  -H "Content-Type: application/json" \
                  -H "Accept: text/event-stream, application/json" \
                  -d '{
                    "jsonrpc": "2.0",
                    "id": "1",
                    "method": "tools/list",
                    "params": {}
                  }' \
           | grep '^data: ' \
           | sed 's/^data: //' \
           | jq '.result'

// Response
{
  "tools": [
    {
      "name": "example_user_tool",
      "inputSchema": {
        "properties": {},
        "type": "object"
      },
      "_meta": {
        "_fastmcp": {
          "tags": []
        }
      }
    },
    {
      "name": "example_incident_tool",
      "inputSchema": {
        "properties": {},
        "type": "object"
      },
      "_meta": {
        "_fastmcp": {
          "tags": []
        }
      }
    },
    {
      "name": "example_knowledgebase_tool",
      "inputSchema": {
        "properties": {},
        "type": "object"
      },
      "_meta": {
        "_fastmcp": {
          "tags": []
        }
      }
    }
  ]
}


// Call example_user_tool
curl -X POST http://localhost:8000/mcp \
                  -H "Content-Type: application/json" \
                  -H "Accept: text/event-stream, application/json" \
                  -d '{
                    "jsonrpc": "2.0",
                    "id": "1",
                    "method": "tools/call",
                    "params": {
                      "name": "example_user_tool"
                    }
                  }' \
           | grep '^data: ' \
           | sed 's/^data: //' \
           | jq '.result.content[0].text'

// Response
"Unknown tool: example_user_tool"

// Call user_example_user_tool
curl -X POST http://localhost:8000/mcp \
                  -H "Content-Type: application/json" \
                  -H "Accept: text/event-stream, application/json" \
                  -d '{
                    "jsonrpc": "2.0",
                    "id": "1",
                    "method": "tools/call",
                    "params": {
                      "name": "user_example_user_tool"
                    }
                  }' \
           | grep '^data: ' \
           | sed 's/^data: //' \
           | jq '.result.content[0].text'

// Response
"This is an example user tool."

Example Code

import asyncio

import uvicorn
from fastmcp import FastMCP
from fastmcp.server.middleware.caching import ResponseCachingMiddleware

mcp = FastMCP(name="Main MCP", stateless_http=True)  # Stateless to make the cURL demo easier, same symptoms without this.

user_mcp = FastMCP(name="User MCP")
incident_mcp = FastMCP(name="Incident MCP")
knowledgebase_mcp = FastMCP(name="Knowledgebase MCP")


@user_mcp.tool
def example_user_tool():
    return "This is an example user tool."


@incident_mcp.tool
def example_incident_tool():
    return "This is an example incident tool."


@knowledgebase_mcp.tool
def example_knowledgebase_tool():
    return "This is an example knowledgebase tool."


async def import_servers():
    await mcp.import_server(user_mcp, prefix="user")
    await mcp.import_server(incident_mcp, prefix="incident")
    await mcp.import_server(knowledgebase_mcp, prefix="knowledgebase")


mcp.add_middleware(ResponseCachingMiddleware())

http_app = mcp.http_app()


if __name__ == "__main__":
    asyncio.run(import_servers())
    uvicorn.run(http_app, host="0.0.0.0", port=8000)

Version Information

FastMCP version:                                                              2.13.0.2
MCP version:                                                                    1.19.0
Python version:                                                                 3.13.9
Platform:               Linux-5.15.167.4-microsoft-standard-WSL2-x86_64-with-glibc2.39
FastMCP root path: /home/seanmcgrath/servicenow-mcp/.venv/lib/python3.13/site-packages

Metadata

Metadata

Assignees

Labels

bugSomething isn't working. Reports of errors, unexpected behavior, or broken functionality.serverRelated to FastMCP server implementation or server-side functionality.triage-martianA label that can be applied by a developer (not an AI Agent) to trigger triage from the martian

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions