Uh oh!
There was an error while loading. Please reload this page.
Added support for raw request injection in RequestContext. - #380
Added support for raw request injection in RequestContext.#380ylassoued wants to merge 10 commits into
Conversation
ylassoued
commented
Mar 31, 2025
@dsp-ant, I am not sure how the reviewing process works here. I was not able to add reviewers to this PR. Will somebody eventually be assigned as reviewer to this PR? |
pls merge this it's really essential to develop professional remote mcp servers! |
ylassoued
commented
Apr 2, 2025
Thank you @georg-ort! I am hoping that someone will review it and approve it so that I may merge the PR. |
georg-ort
commented
Apr 2, 2025
Well I have to thank you @ylassoued! I'm currently using your fork in order to progress since I do need authentication context in my tool calls or our product wouldn't work. |
ylassoued
commented
Apr 2, 2025
Oh brilliant. Thank you @georg-ort for supporting this. I am glad somebody if finding it useful :-). |
emilioflc
commented
Apr 2, 2025
Thank you so much for this, @ylassoued! This looks incredibly useful across a variety of contexts. I actually ran into the exact same situation where I needed authentication context in my tool calls and came across your PR. Really appreciate you putting this together. Fingers crossed it gets reviewed and merged soon! |
ylassoued
commented
Apr 2, 2025
Thank you very much @emilioflc. My pleasure :-). |
null-crafter
commented
Apr 7, 2025
is this good to merge? this pull request is very helpful to me. |
bjb2010
commented
Apr 8, 2025
@dsp-ant Please take some time to check whether this can be merged? |
albertocalderari
commented
Apr 8, 2025
Hey, we sort of would like to get this too as we ended up implementing the same thing |
rem-lag
commented
Apr 8, 2025
I'd just spent some time poking around trying to figure out if this could be done with the sdk as is so I'm happy to see there's already a PR for it, I hope it can be merged in because this functionality would make my life a lot easier! Thanks for putting the work in @ylassoued |
wbeard
commented
Apr 8, 2025
Thank you for the contribution! I'm using your branch locally and see the headers I need. Would love to see this merged. |
samirbajaj
commented
Apr 8, 2025
Can we please get a review on this PR? I would love to see it merged. Thank you. |
281743556
commented
Apr 9, 2025
When are you planning to launch? We urgently need this feature |
kelvin1804
commented
Apr 10, 2025
Please merge. This feature is essential for all remote MCPs |
JorgeRuizITCL
commented
Apr 10, 2025
Seems good, even implements generics for requests different than Starlette. |
hi @ylassoued, This pr looks like it injects the header of the first /sse request for all subsequent /messages requests, but if the user needs the header of subsequent requests what do they need to do, such as tools/call and tools/list requests, is there any way for the user to get the header information? I want to carry tracer information in the header of each subsequent /messages related http request and get the related tracer information in tools. |
wenxuwan
commented
Apr 22, 2025
I looked at the client-related code and found that there is now no parameter allowing the user to carry a header in subsequent requests 😭 |
toughnoah
commented
Apr 22, 2025
Please merge!!! It is really useful for tools authorization!! |
samirbajaj
commented
Apr 22, 2025
I imagined that I'd associate a header value with the |
wenxuwan
commented
Apr 23, 2025
All subsequent requests (e.g. tools/call and tools/list) are a separate http request, which should allow the developer to customise the header of each request, but the Python client doesn't have this ability right now |
ylassoued
commented
Apr 23, 2025
Hi @wenxuwan, @samirbajaj, apologies for the delay in getting back to you. I have to admit, I have not fully understood your concern with carrying the request headers for all subsequent /messages requests. I assumed that when you initialised a client with headers, then it would inject the headers in every request. Am I wrong in assuming so? |
wenxuwan
commented
Apr 23, 2025
hi @ylassoued ,thanks for the reply, what I mean is that apart from the header information in the initialisation phase, I would like to be able to inject some other custom header information, such as the tracer information, in subsequent requests (the trace_id and span_id should be different for each subsequent http request) |
ylassoued
commented
Apr 23, 2025
Thanks @wenxuwan! Any chance you could write some sample code to illustrate the use case? For example, by writing how ideally the user can make use of the header in the subsequent calls. |
I think the basic idea is that an MCP client could send different data (be it headers / different header values or whatever else) for the requests it submits for your tools / resources / prompts. Those headers could contain information unique to each request, like a trace_id as @wenxuwan mentioned. These could in turn be used on the MCP server side for observability (e.g use Grafana, CloudWatch etc to monitor your applications and data processes). Unless I'm missing something, the solution in this PR doesn't account for that fact, and reuses the same initial request that was submitted when an MCP client connected to the /sse endpoint, which is also a bit misleading since you're basically caching it in the request_context, which is supposed to pertain to the actual current request. |
hi @ylassoued , It's not easy to write a demo because the current python sdk doesn't have this capability, but as @quitrk said, each http request should have its own request_context, and currently your implementation is that all subsequent requests share the request_context of the /sse request, which may solve some of the problems (like the This may solve some of the problems (e.g., authentication of tools), but it's not really right. We should carry the authentication information in the request_context of subsequent requests instead of sharing the request_context of the /sse request. |
ylassoued
commented
Apr 23, 2025
OK, I see what you mean. Yes, I confirm that in this implementation, it is the initial request that is injected in the context. This was sufficient to solve the authentication issue as you mentioned it already. But I do understand your concern, and I believe now that this implementation is misleading. Instead of injecting the request, I should have simply injected the session-wide initial request headers. But, as you suggested, it would be cleaner to inject the current request for each call instead of injecting the initial one. I'll have to dig into the code again to figure this out... Thanks @wenxuwan, @samirbajaj, and @quitrk! |
wenxuwan
commented
Apr 24, 2025
hi @ylassoued ,Currently, all subsequent requests except /sse are handled inside mcp.server.sse.SseServerTransport.handle_post_message, which transforms the request and sends it via writer.send(message) to the mcp.shared.session.BaseSession._receive_loop. This is where the problem occurs, handle_post_message converts the http request to a message while processing the request, resulting in the header information of the http request being lost 😣. Therefore, we can try to stuff the request_context into the message at the time of conversion and make sure that subsequent conversions will carry the request_context. |
How are we supposed to pass in the correct headers from the mcp client |
jlowin
commented
May 2, 2025
This is super useful -- since I'm sure the low-level server is in flux with things like Streamable HTTP coming into focus, I've added support for accessing the current Starlette request in the standalone FastMCP repo, without modifying the low-level MCP server. Would welcome thoughts for enhancement there: PrefectHQ/fastmcp#302 |
related #216 |
ronald0samuel
commented
May 16, 2025
to reiterate, suppose i have a chatbot application which has an mcp client connecting to some remote mcp server. Suppose there are multiple users using this application, each user has an ID to identify themselves and the response from the server at any time depends on the which user has made a request. I don't want to give the user ID in the tool schema since its not upto the chatbot to keep track of user IDs, all i need is a way to pass custom metadata per tool call so that the server returns information pertaining to a particular user. This PR doesn't help with that since the headers are finalised while initialising the client and cannot be changed after app startup |
ihrpr
commented
May 28, 2025
thank you so much @ylassoued for working on this, we have merge #816 based on this work! |
ylassoued
commented
May 30, 2025
This is great new!!! Thank you very much @ihrpr!!!!! :-) |
closes#195
Added support for injecting the raw request into the
RequestContext.Motivation and Context
In real-life applications, authentication may rely on request headers. In the case where the MCP server needs to act on behalf of the client to retrieve resources from a remote server or DB, thus requiring to authenticate on behalf of the client, getting the request headers is essential.
With the solution implemented in this PR, you may access the raw request from any end point as follows:
How Has This Been Tested?
Breaking Changes
The only breaking change is in typing. As a matter of fact the following generic classes have now an additional type argument
RequestT(raw request type):class RequestContext(Generic[SessionT, LifespanContextT, RequestT])class Server(Generic[LifespanResultT, RequestT])Types of changes
Checklist
Additional context