Skip to content

Conversation

dsp-ant
Copy link
Member

@dsp-ant dsp-ant commented Sep 2, 2025

Summary

This PR fixes issue #244 where @app.resource() and @app.prompt() decorators were not properly handling Context parameters, causing validation errors when handlers tried to access the request context.

Problem

Previously, when defining resources or prompts with a Context parameter:

@mcp.resource("schema://records")
async def get_logfire_records_schema(ctx: Context) -> str: ...

The validation logic would fail with:

ValueError: Mismatch between URI parameters set() and function parameters {'ctx'}

This occurred because the Context parameter was being incorrectly treated as a URI parameter during validation.

Solution

This PR implements automatic context injection for resources and prompts, following the same pattern already established for tools:

  1. Context Detection: Automatically detect Context-typed parameters in handler functions
  2. Validation Fix: Exclude Context parameters from URI parameter validation
  3. Runtime Injection: Pass the request context to handlers at runtime when a Context parameter is present
  4. Refactoring: Extract common context injection logic into a shared utility module to ensure consistency across tools, resources, and prompts

Changes

  • Add context parameter detection to ResourceTemplate and Prompt classes
  • Update func_metadata calls to exclude Context parameters from generated schemas
  • Modify resource_manager.get_resource() and prompt.render() to pass context through
  • Update server validation logic to ignore Context parameters when checking URI parameters
  • Extract common injection pattern into utilities/context_injection.py module
  • Add comprehensive test coverage for all context injection scenarios

Testing

Added extensive tests covering:

  • Resources with and without context parameters
  • Prompts with and without context parameters
  • Custom parameter names for context injection
  • Validation of proper context passing at runtime

Fixes #244

@dsp-ant dsp-ant requested a review from a team September 2, 2025 20:24
@dsp-ant dsp-ant self-assigned this Sep 2, 2025
@dsp-ant dsp-ant force-pushed the fix/context-injection-prompts-resources branch 2 times, most recently from 77da03d to 17738fb Compare September 2, 2025 20:40
@dsp-ant dsp-ant force-pushed the fix/context-injection-prompts-resources branch from f8733f1 to ea7cd8f Compare September 9, 2025 18:55
@dsp-ant dsp-ant requested review from Kludex and dmontagu September 9, 2025 18:55
@dsp-ant dsp-ant force-pushed the fix/context-injection-prompts-resources branch from d3a240f to b300250 Compare September 9, 2025 18:57
Comment on lines 1074 to 1082
else:
# Context was not injected
pytest.skip("Prompt context injection not yet implemented")
except Exception as e:
if "Missing required arguments" in str(e) and "ctx" in str(e):
# Context injection not working - expected for now
pytest.skip("Prompt context injection not yet implemented")
else:
raise
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But this is not running, is it?

And if it's, you should use xfail, which shows the intent that it's failing for now (https://docs.pytest.org/en/stable/how-to/skipping.html).

…prompts

Add test cases to verify that:
- Resources can receive Context parameters with automatic injection
- Resources work normally without context parameters
- Custom context parameter names are detected correctly
- Prompts can receive Context parameters (currently not implemented)
- Prompts work normally without context parameters

These tests establish the expected behavior for context injection
across both resources and prompts in the FastMCP framework.
This adds automatic context injection support for both resources and prompts
in the FastMCP framework, allowing these handlers to receive the request
context without explicitly passing it as an argument.

Changes:
- Add context parameter detection in ResourceTemplate and Prompt classes
- Use func_metadata utility to generate schemas while excluding Context params
- Pass context through resource_manager.get_resource() and prompt.render()
- Update server validation to exclude Context params from URI parameter checks
- Add comprehensive test coverage for context injection scenarios

The implementation follows the same pattern already used for tools,
ensuring consistency across all FastMCP handler types.
Eliminated code duplication across tools, resources, and prompts by creating
a centralized context injection utility module.

Changes:
- Add context_injection.py utility with find_context_parameter() and inject_context()
- Refactor tool, resource, and prompt implementations to use the shared utility
- Remove duplicated context detection logic from all three implementations
- Maintain backward compatibility with all existing tests passing

This refactoring reduces code duplication and makes the context injection
pattern consistent and maintainable across all FastMCP handler types.
- Enhanced context injection utilities to better handle prompts and resources
- Fixed parameter handling and context propagation

Github-Issue: #1129
@dsp-ant dsp-ant force-pushed the fix/context-injection-prompts-resources branch from b300250 to b3cef34 Compare September 10, 2025 11:08
@dsp-ant dsp-ant requested review from a team and ochafik and removed request for dmontagu September 10, 2025 11:08
- Use find_context_parameter utility in server.py for cleaner code
- Simplify test assertions to check for context injection consistently
- Remove conditional checks and try-catch blocks in tests
- Improve readability by removing unnecessary complexity

Co-Authored-By: David S <[email protected]>
@dsp-ant dsp-ant force-pushed the fix/context-injection-prompts-resources branch from b3cef34 to 426fb8a Compare September 10, 2025 12:28
@@ -0,0 +1,2 @@
# Generated
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this supposed to be commited?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

@dsp-ant dsp-ant merged commit c3717e7 into main Sep 11, 2025
21 checks passed
@dsp-ant dsp-ant deleted the fix/context-injection-prompts-resources branch September 11, 2025 13:30
rbehal pushed a commit to gumloop/gumloop-mcp that referenced this pull request Sep 25, 2025
* Add regression test for stateless request memory cleanup (modelcontextprotocol#1140)

* Implement RFC9728 - Support WWW-Authenticate header by MCP client (modelcontextprotocol#1071)

* Add streamable HTTP starlette example to Python SDK docs (modelcontextprotocol#1111)

* fix markdown error in README in main (modelcontextprotocol#1147)

* README - replace code snippets with examples - add lowlevel to snippets (modelcontextprotocol#1150)

* README - replace code snippets with examples - streamable http (modelcontextprotocol#1155)

* chore: don't allow users to create issues outside the templates (modelcontextprotocol#1163)

* Tests(cli): Add coverage for helper functions (modelcontextprotocol#635)

* Docs: Update CallToolResult parsing in README (modelcontextprotocol#812)

Co-authored-by: Felix Weinberger <[email protected]>

* docs: add pre-commit install guide on CONTRIBUTING.md (modelcontextprotocol#995)

Co-authored-by: Felix Weinberger <[email protected]>

* fix flaky fix-test_streamablehttp_client_resumption test (modelcontextprotocol#1166)

* README - replace code snippets with examples -- auth examples (modelcontextprotocol#1164)

* Support falling back to OIDC metadata for auth (modelcontextprotocol#1061)

* Add CODEOWNERS file for sdk (modelcontextprotocol#1169)

* fix flaky test test_88_random_error (modelcontextprotocol#1171)

* Make sure `RequestId` is not coerced as `int` (modelcontextprotocol#1178)

* Fix: Replace threading.Lock with anyio.Lock for Ray deployment compatibility (modelcontextprotocol#1151)

* fix: fix OAuth flow request object handling (modelcontextprotocol#1174)

* update codeowners group (modelcontextprotocol#1191)

* fix: perform auth server metadata discovery fallbacks on any 4xx (modelcontextprotocol#1193)

* server: skip duplicate response on CancelledError (modelcontextprotocol#1153)

Co-authored-by: ihrpr <[email protected]>

* Unpack settings in FastMCP (modelcontextprotocol#1198)

* chore: Remove unused prompt_manager.py file (modelcontextprotocol#1229)

Co-authored-by: Tapan Chugh <[email protected]>

* Improved supported for ProtectedResourceMetadata (modelcontextprotocol#1235)

Co-authored-by: Paul Carleton <[email protected]>

* chore: Remove unused variable notification_options (modelcontextprotocol#1238)

* Improve README around the Context object (modelcontextprotocol#1203)

* fix: allow to pass `list[str]` to `token_endpoint_auth_signing_alg_values_supported` (modelcontextprotocol#1226)

* Remove strict validation on `response_modes_supported` member of `OAuthMetadata` (modelcontextprotocol#1243)

* Add pyright strict mode on the whole project (modelcontextprotocol#1254)

* Consistent casing for default headers Accept and Content-Type (modelcontextprotocol#1263)

* Update dependencies and fix type issues (modelcontextprotocol#1268)

Co-authored-by: Marcelo Trylesinski <[email protected]>

* fix: prevent async generator cleanup errors in StreamableHTTP transport (modelcontextprotocol#1271)

Co-authored-by: David Soria Parra <[email protected]>

* chore: uncomment .idea/ in .gitignore (modelcontextprotocol#1287)

Co-authored-by: Claude <[email protected]>

* docs: clarify streamable_http_path configuration when mounting servers (modelcontextprotocol#1172)

* feat: Add CORS configuration for browser-based MCP clients (modelcontextprotocol#1059)

Co-authored-by: Marcelo Trylesinski <[email protected]>
Co-authored-by: Felix Weinberger <[email protected]>

* Added Audio to FastMCP (modelcontextprotocol#1130)

* fix: avoid uncessary retries in OAuth authenticated requests (modelcontextprotocol#1206)

Co-authored-by: Felix Weinberger <[email protected]>

* Add PATHEXT to default STDIO env vars in windows (modelcontextprotocol#1256)

* fix: error too many values to unpack (expected 2) (modelcontextprotocol#1279)

Signed-off-by: San Nguyen <[email protected]>
Co-authored-by: Felix Weinberger <[email protected]>
Co-authored-by: Felix Weinberger <[email protected]>

* SDK Parity: Avoid Parsing Server Response for non-JsonRPCMessage Requests (modelcontextprotocol#1290)

* types: Setting default value for method: Literal (modelcontextprotocol#1292)

* changes structured temperature to not deadly (modelcontextprotocol#1328)

* Update simple-resource example to use non-deprecated read_resource return type (modelcontextprotocol#1331)

Co-authored-by: Claude <[email protected]>

* docs: Update README to include link to API docs for modelcontextprotocol#1329 (modelcontextprotocol#1330)

* Allow ping requests before initialization (modelcontextprotocol#1312)

* Python lint: Ruff rules for pylint and code complexity (modelcontextprotocol#525)

* Fix context injection for resources and prompts (modelcontextprotocol#1336)

* fix(fastmcp): propagate mimeType in resource template list (modelcontextprotocol#1186)

Co-authored-by: Felix Weinberger <[email protected]>

* fix: allow elicitations accepted without content (modelcontextprotocol#1285)

Co-authored-by: Olivier Schiavo <[email protected]>

* Use --frozen in pre-commit config (modelcontextprotocol#1375)

* Return HTTP 403 for invalid Origin headers (modelcontextprotocol#1353)

* Add test for ProtectedResourceMetadataParsing (modelcontextprotocol#1236)

Co-authored-by: Paul Carleton <[email protected]>
Co-authored-by: Marcelo Trylesinski <[email protected]>
Co-authored-by: Felix Weinberger <[email protected]>

* Fastmcp logging progress example (modelcontextprotocol#1270)

Co-authored-by: Felix Weinberger <[email protected]>

* feat: add paginated list decorators for prompts, resources, and tools (modelcontextprotocol#1286)

Co-authored-by: Claude <[email protected]>

* Remove "unconditionally" from conditional description (modelcontextprotocol#1289)

* Use streamable-http consistently in examples (modelcontextprotocol#1389)

* feat: Add SDK support for SEP-1034 default values in elicitation schemas (modelcontextprotocol#1337)

Co-authored-by: Tapan Chugh <[email protected]>
Co-authored-by: Felix Weinberger <[email protected]>

* Implementation of SEP 973 - Additional metadata + icons support (modelcontextprotocol#1357)

* Merge upstream/main with custom filtering

---------

Signed-off-by: San Nguyen <[email protected]>
Co-authored-by: Felix Weinberger <[email protected]>
Co-authored-by: yurikunash <[email protected]>
Co-authored-by: Pamela Fox <[email protected]>
Co-authored-by: Inna Harper <[email protected]>
Co-authored-by: Marcelo Trylesinski <[email protected]>
Co-authored-by: Ian Davenport <[email protected]>
Co-authored-by: Dagang Wei <[email protected]>
Co-authored-by: Felix Weinberger <[email protected]>
Co-authored-by: Stanley Law <[email protected]>
Co-authored-by: Luca Chang <[email protected]>
Co-authored-by: leweng <[email protected]>
Co-authored-by: Clare Liguori <[email protected]>
Co-authored-by: lukacf <[email protected]>
Co-authored-by: ihrpr <[email protected]>
Co-authored-by: Tapan Chugh <[email protected]>
Co-authored-by: Tapan Chugh <[email protected]>
Co-authored-by: Yann Jouanin <[email protected]>
Co-authored-by: Paul Carleton <[email protected]>
Co-authored-by: Sreenath Somarajapuram <[email protected]>
Co-authored-by: Omer Korner <[email protected]>
Co-authored-by: joesavage-silabs <[email protected]>
Co-authored-by: Gregory L <[email protected]>
Co-authored-by: David Soria Parra <[email protected]>
Co-authored-by: Moustapha Ebnou <[email protected]>
Co-authored-by: Max Isbey <[email protected]>
Co-authored-by: Claude <[email protected]>
Co-authored-by: Jerome <[email protected]>
Co-authored-by: xavier <[email protected]>
Co-authored-by: keurcien <[email protected]>
Co-authored-by: Tim Esler <[email protected]>
Co-authored-by: San Nguyen <[email protected]>
Co-authored-by: Justin Wang <[email protected]>
Co-authored-by: jess <[email protected]>
Co-authored-by: Peter Alexander <[email protected]>
Co-authored-by: Reid Geyer <[email protected]>
Co-authored-by: Eleftheria Stein-Kousathana <[email protected]>
Co-authored-by: Christian Clauss <[email protected]>
Co-authored-by: pchoudhury22 <[email protected]>
Co-authored-by: owengo <[email protected]>
Co-authored-by: Olivier Schiavo <[email protected]>
Co-authored-by: Steve Billings <[email protected]>
Co-authored-by: Mike Salvatore <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@app.resource() does not accept ctx: Context

3 participants