Agno community!
I’m working on a multi-tenant agent using Agno with MCP (Model Context Protocol) tools, and I’m facing a challenging issue with dynamic header updates that I hope someone can help me solve.
Background & Setup
-
Framework: Agno Agent with MCPTools
-
Transport: streamable-http
-
Use Case: Multi-tenant application where each request needs different App-User-Id headers
-
Architecture: FastAPI middleware extracts user context from request headers and updates agent context per request
The Problem
I need MCP tools to use request-scoped headers (different App-User-Id for each user), but I’m struggling with the connection/header management:
-
During agent initialization: MCP tools are created with a placeholder App-User-Id: "PLACEHOLDER"
-
Per request: I call agent.update_context() to set the actual user ID (e.g., "CP")
-
Issue: MCP requests still use the original “PLACEHOLDER” header instead of the updated user ID
Specific Questions
-
Best Practice: What’s the recommended approach for request-scoped headers in MCP tools?
-
Should I recreate MCP tools per request?
-
Is there a way to update headers on existing connections?
-
Should I use a connection pool keyed by user_id?
-
Agent Tools Management: When I update self.agent.tools, the agent seems to lose access to MCP tools. What’s the correct way to update an agent’s tools dynamically?
-
MCP Connection Lifecycle: Does MCPTools maintain persistent connections? If so, how can I ensure header updates are reflected in actual HTTP requests?
-
Performance Considerations: Creating new MCP connections per request seems expensive. Is there a more efficient pattern?
Expected Behavior
Each request should use MCP tools with the correct App-User-Id header for that specific user, enabling proper multi-tenant isolation at the MCP server level.
Hey Im Uzair from Agno,
MCP transport headers are frozen at connection initialization and cannot be updated dynamically.
update_context() won’t Work beacuse the Agent context updates don’t pass on to MCP tool connection parameters. When MCPTools.connect() is called, The headers are frozen in the
StreamableHTTPClientParams object.
Think of it like: Once you open a TCP or a long-lived connection with specific HTTP headers, those headers are part of that connection. You can’t change them, mid-flight, you need to reconnect with new headers.
You can create a wrapper class around the Agno’s agno.tools.mcp.MCP class and update the headers before connection. You need to override the connect method.
Hope this helps, Please feel free to ask further questions!
This is more like reconnecting the MCP with a new set of headers, right? I think it adds additional overhead to my agent. For every user request, if the agent needs the MCP, it has to reconnect, correct? I’ve tried this approach before, but in that case, my agent failed to fetch the MCP tools. What are your thoughts on this?
Yes when you reconnect the agent needs to re-build its tool registry.
his happens automatically only if you set refresh_connection=True on your MCPTools instance. Without this flag, the agent checks if the connection is alive, and only reconnects if it’s dead.
can you check the logs and other relevant places why your agent fails to fetch MCP tool? my guess is that agent might have stale tool references.
Also i think you can try connection pooling on a per user basis. Instead of reconnecting, maintain one connection per user ID and reuse it
Or a workaround approach would be to apply user based routing at MCP server level.
```
response = await agent.arun(
f"[USER:{app_user_id}] {query}", # inject user ID in query
session_id=app_user_id # Or use session_id for routing
)
return {“response”: response.content}
```
You can also try adding proxy for your MCP server if you can and then call implement the user based routing via the proxy.