-
Notifications
You must be signed in to change notification settings - Fork 324
Open
Labels
enhancementNew feature or requestNew feature or requesttriageIssues / Features awaiting triageIssues / Features awaiting triage
Milestone
Description
🧭 Type of Feature
Please select the most appropriate category:
- Enhancement to existing functionality
- New feature or capability
- New MCP-compliant server
- New component or integration
- Developer tooling or test improvement
- Packaging, automation and deployment (ex: pypi, docker, quay.io, kubernetes, terraform)
- Other (please describe below)
🚀 Summary
This Feature is meant to implement the authentication pre/post hooks for the MCP gateway. Below is a possible way to implement authentication. I've made the hooks more generic to represent general http modifications. This is so that these hooks could represent other types of plugins that require http header modification but are not authentication related.
📓 Notes
The current implementation would build the plugin hooks as follows:
async def http_pre_forwarding_call(self, payload: HttpHeaderPayload, context: PluginContext) -> HttpHeaderPayloadResult:
"""Plugin hook run before a forwarding HTTP call is made to a tool or gateway.
Args:
payload: The HTTP headers that can be checked or modified .
context: Contextual information about the hook call.
Raises:
NotImplementedError: needs to be implemented by sub class.
"""
raise NotImplementedError(
f"""'http_pre_forwarding_call' not implemented for plugin {self._config.name}
of plugin type {type(self)}
"""
)
async def http_post_forwarding_call(self, payload: HttpHeaderPayload, context: PluginContext) -> HttpHeaderPayloadResult:
"""Plugin hook run after a forwarding HTTP call is made to a tool or gateway.
Args:
payload: The HTTP headers that can be checked or modified .
context: Contextual information about the hook call.
Raises:
NotImplementedError: needs to be implemented by sub class.
"""
raise NotImplementedError(
f"""'http_post_forwarding_call' not implemented for plugin {self._config.name}
of plugin type {type(self)}
"""
)
where the payloads are as follows:
class HttpHeaderPayload(RootModel[dict[str, str]]):
"""An HTTP dictionary of headers used in the pre/post HTTP forwarding hooks."""
def __iter__(self):
"""Custom iterator function to override root attribute."""
return iter(self.root)
def __getitem__(self, item: str) -> str:
"""Custom getitem function to override root attribute."""
return self.root[item]
HttpHeaderPayloadResult = PluginResult[HttpHeaderPayload]
The context could pass in information about the tools or gateway forwarding where this is called including gateway/tool oauth information that is stored in the MCP Context Forge's database.
Where it would be called:
- before and after tool invocations.
- before and after tool list_tool invocations.
- before and after gateway forwarding requests?
- Do we need to call this before prompts, resources? etc.?
Questions:
- Would this be better as a pluggable FASTAPI middleware piece or called from within a pluggable middleware rather at the sight of each function described above? The advantage of doing it there is that you get access to all the raw headers, and the code would be in one spot. The disadvantage is that each tool, gateway, prompt, etc. has it's own database table, and a middleware would have to parse each request, figure out whether it's a tool call, gateway call, etc, and then parse the request, access the db for information about the tool/gateway etc, add the http headers and pass inside. So there would be multiple db calls, etc...
- Do we need any other information to make authentication decisions within the gateway? How do we pass that in?
- I notice gateway forwarding does provide pass through headers while invoke tool does. Do we need to provide pass through headers for gateway forwarding calls?
- Do we need to have these hooks called before prompts, resources? What other spots?
- What kind of meta data should we pass into this?
- Do we need some sort of header field masking so we don't leak authentication information across plugins? and if so, how? We could have markable private fields as part of the payload.
- Anything we are missing or need to consider?
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or requesttriageIssues / Features awaiting triageIssues / Features awaiting triage