-
Notifications
You must be signed in to change notification settings - Fork 614
[FEATURE][API]: Support _meta for all RPC methods #2332
Description
📋 Feature: Support _meta for All RPC Methods
Goal
Extend _meta support to all MCP RPC methods (tools/list, resources/list, prompts/list, resources/read, prompts/get) to achieve full compliance with MCP specification 2025-11-25. The gateway should propagate _meta from client requests to upstream MCP servers.
Why Now?
- MCP Compliance: Spec 2025-11-25 reserves
_metafor protocol-level metadata on all methods - User Context: Servers need user identity/context to filter results appropriately
- Dynamic Responses: Enable tools/resources that change based on
_metacontext - Dependency: Issue [FEATURE]: Dynamic tools/resources based on user context and server-side signals #2171 (dynamic tools) and [FEATURE]: Bypass DB/cache lookup option for gateways #2344 (direct proxy) rely on
_metapropagation
📖 User Stories
US-1: MCP Server Developer - Receive User Context in All Methods
As an MCP Server developer
I want to receive _meta in all RPC methods
So that I can customize responses based on user context
Acceptance Criteria:
Scenario: tools/list receives _meta
Given a client sends tools/list with _meta containing user_id
When the request reaches the upstream MCP server
Then the server should receive the exact _meta object
And can filter tools based on user_id
Scenario: resources/list receives _meta
Given a client sends resources/list with _meta containing workspace_id
When the request reaches the upstream MCP server
Then the server should receive the _meta object
And can return workspace-specific resources
Scenario: prompts/get receives _meta
Given a client sends prompts/get with _meta containing locale
When the request reaches the upstream MCP server
Then the server should receive the _meta object
And can return localized prompt contentTechnical Requirements:
- Accept
_metaparameter in all list/get endpoints - Forward
_metato upstream MCP server in JSON-RPC request - Preserve all fields within
_meta
US-2: Developer - Consistent _meta Handling
As a Developer using the gateway API
I want consistent _meta handling across all methods
So that I don't have to handle different methods differently
Acceptance Criteria:
Scenario: All methods accept _meta in same format
Given these RPC methods:
| Method | Params |
| tools/list | {} |
| tools/call | {name, arguments} |
| resources/list | {} |
| resources/read | {uri} |
| prompts/list | {} |
| prompts/get | {name, arguments} |
When I add _meta to any method's params
Then the gateway should accept it
And forward it to the upstream server
Scenario: _meta is optional everywhere
Given any RPC method
When I omit _meta from params
Then the request should succeed
And no _meta should be forwarded (or empty object)US-3: Platform - Inject Gateway-Level Context
As a Platform Operator
I want the gateway to optionally inject context into _meta
So that upstream servers receive gateway-level information
Acceptance Criteria:
Scenario: Gateway injects authenticated user info
Given authentication is enabled
And a client authenticates as user@example.com
When the client sends tools/list without _meta
Then the upstream should receive _meta with:
| Field | Value |
| gateway.user_email | user@example.com |
| gateway.user_teams | ["team-1"] |
Scenario: Client _meta preserved alongside gateway injection
Given client sends _meta with {custom_field: "value"}
When request is processed
Then upstream receives _meta with:
| Field | Value |
| custom_field | value |
| gateway.user_email | user@example.com |
And client fields are not overwrittenTechnical Requirements:
- Optional: Inject authenticated user info into
_meta.gateway - Preserve client-provided
_metafields - Use
gateway.prefix for injected fields to avoid collisions
🏗 Architecture
_meta Flow
sequenceDiagram
participant Client
participant Gateway
participant MCP Server
Client->>Gateway: tools/list {_meta: {user_id: "123"}}
Gateway->>Gateway: Extract _meta from params
Gateway->>Gateway: Optionally inject gateway context
Gateway->>MCP Server: tools/list {_meta: {user_id: "123", gateway: {...}}}
MCP Server->>MCP Server: Filter based on _meta
MCP Server-->>Gateway: {tools: [...]}
Gateway-->>Client: {tools: [...]}
Methods to Update
| Method | Current _meta Support | Status |
|---|---|---|
tools/call |
✅ Partial (Issue #2094) | Needs verification |
tools/list |
❌ Not implemented | New |
resources/list |
❌ Not implemented | New |
resources/read |
❌ Not implemented | New |
prompts/list |
❌ Not implemented | New |
prompts/get |
❌ Not implemented | New |
completion/complete |
❌ Not implemented | New |
Schema Updates
# mcpgateway/schemas.py
class ToolsListRequest(BaseModel):
_meta: Optional[Dict[str, Any]] = Field(None, alias="_meta")
class ResourcesListRequest(BaseModel):
_meta: Optional[Dict[str, Any]] = Field(None, alias="_meta")
class PromptsListRequest(BaseModel):
_meta: Optional[Dict[str, Any]] = Field(None, alias="_meta")
# Similar for read/get methods📋 Implementation Tasks
Phase 1: Schema Updates
- Add
_metafield toToolsListRequestschema - Add
_metafield toResourcesListRequestschema - Add
_metafield toResourcesReadRequestschema - Add
_metafield toPromptsListRequestschema - Add
_metafield toPromptsGetRequestschema - Add
_metafield toCompletionCompleteRequestschema
Phase 2: RPC Handler Updates
- Modify
tools/listhandler to accept and forward_meta - Modify
resources/listhandler to accept and forward_meta - Modify
resources/readhandler to accept and forward_meta - Modify
prompts/listhandler to accept and forward_meta - Modify
prompts/gethandler to accept and forward_meta - Verify
tools/callforwards_metacorrectly
Phase 3: Transport Layer
- Ensure SSE transport forwards
_meta - Ensure Streamable HTTP transport forwards
_meta - Ensure WebSocket transport forwards
_meta - Ensure stdio transport forwards
_meta
Phase 4: Gateway Context Injection (Optional)
- Add configuration:
INJECT_USER_META=true - Inject authenticated user info into
_meta.gateway - Preserve client
_metafields - Document injected fields
Phase 5: Testing
- Unit tests for _meta schema fields
- Integration tests for each method with _meta
- Test _meta preservation through transports
- Test gateway context injection
- Test with missing _meta (should work)
⚙️ Configuration Example
# Optional: Inject gateway context into _meta
INJECT_USER_META=false
# When enabled, upstream receives:
# _meta: {
# ...client_fields...,
# gateway: {
# user_email: "user@example.com",
# user_teams: ["team-1"],
# timestamp: "2026-01-25T10:00:00Z"
# }
# }✅ Success Criteria
- All RPC methods accept
_metaparameter -
_metais forwarded to upstream MCP server unchanged - Missing
_metadoesn't break any method - All transports (SSE, HTTP, WS, stdio) forward
_meta - Gateway context injection works when enabled
- OpenAPI docs show
_metaparameter on all methods - All tests passing
🏁 Definition of Done
- Schemas updated with
_metafields - All RPC handlers forward
_meta - All transports propagate
_meta - Optional context injection implemented
- Unit tests written and passing
- Integration tests written and passing
- Code passes
make verify - API documentation updated
- PR reviewed and approved
📝 Additional Notes
MCP Specification Reference
From MCP Base Protocol (2025-06-18):
"The
_metaproperty/parameter is reserved by MCP to allow clients and servers to attach additional metadata to their interactions."
Compatibility Notes
_metais optional in all methods- Servers that don't use
_metasimply ignore it - Gateway should never fail if
_metais missing - Client-provided
_metatakes precedence over gateway injection (except forgateway.prefix)
🔗 Related Issues
- Issue [FEATURE]: Support _meta field propagation in MCP tool calls #2094 - Add
_metato tools/call (partial implementation) - Issue [FEATURE]: Dynamic tools/resources based on user context and server-side signals #2171 - Dynamic tools based on user context
- Issue [FEATURE]: Bypass DB/cache lookup option for gateways #2344 - Bypass DB/cache lookup (depends on
_meta)