Title: Revisit FastMCP context injection to reduce “magic” and improve type-safety · Issue #1695 · modelcontextprotocol/python-sdk · GitHub
Open Graph Title: Revisit FastMCP context injection to reduce “magic” and improve type-safety · Issue #1695 · modelcontextprotocol/python-sdk
X Title: Revisit FastMCP context injection to reduce “magic” and improve type-safety · Issue #1695 · modelcontextprotocol/python-sdk
Description: Description Summary FastMCP currently uses introspection to automatically inject a Context parameter into tools/resources when it detects a parameter with the right name/type. This is convenient but “magic”: it relies on parameter naming...
Open Graph Description: Description Summary FastMCP currently uses introspection to automatically inject a Context parameter into tools/resources when it detects a parameter with the right name/type. This is convenient bu...
X Description: Description Summary FastMCP currently uses introspection to automatically inject a Context parameter into tools/resources when it detects a parameter with the right name/type. This is convenient bu...
Opengraph URL: https://github.com/modelcontextprotocol/python-sdk/issues/1695
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Revisit FastMCP context injection to reduce “magic” and improve type-safety","articleBody":"### Description\n\n## Summary\n\nFastMCP currently uses introspection to automatically inject a `Context` parameter into tools/resources when it detects a parameter with the right name/type. This is convenient but “magic”:\n\n- it relies on parameter naming/type hints,\n- it’s invisible in function signatures (from a caller’s perspective),\n- it can break silently after refactors.\n\nThis issue proposes making context injection **more explicit and type-safe**, while preserving ergonomics.\n\n## Problems\n\n- **Brittle conventions:** Renaming the parameter or changing the import path of `Context` can silently break injection.\n- **Type checker mismatch:** Type hints show a required parameter, but at runtime the SDK auto-populates it, which can confuse static analysis and IDEs.\n- **New user confusion:** It’s not obvious from examples why a parameter is populated or how to opt into/opt out of it.\n\n## Proposal\n\n1. **Introduce explicit opt-in for context injection**\n\n For example:\n\n - Via decorator argument:\n\n ```python\n @mcp.tool(inject_context=True)\n async def my_tool(ctx: Context, ...) -\u003e ...:\n ...\n ```\n\n - Or via a dedicated “injected” marker type, e.g. `ctx: Injected[Context]`.\n\n2. **Document a single, clear convention**\n\n - If conventions are used (e.g., `_mcp_context` parameter name), make them explicit and heavily documented:\n - “If you define a parameter named `_mcp_context` with type `Context`, FastMCP will inject it.”\n\n3. **Migration path**\n\n - Support both the old introspection behavior and the new explicit pattern for at least one minor release.\n - Add warnings or docs guiding users towards the explicit pattern.\n\n## Why this matters\n\n- **Predictability:** Less “magic” makes it easier to reason about what the SDK is doing.\n- **Tooling:** IDEs and static analyzers can more accurately represent what parameters are expected.\n- **Refactoring safety:** Users are less likely to accidentally break context injection when renaming parameters or types.\n\n## Acceptance criteria\n\n- [ ] There is an explicit, documented way to opt into context injection (decorator flag or marker type).\n- [ ] The existing introspection mechanism is either deprecated or clearly described as legacy.\n- [ ] Examples and docs use the explicit pattern as the recommended approach.\n- [ ] Type checkers can understand the pattern without special configuration.\n\n\n### References\n\n_No response_","author":{"url":"https://github.com/dgenio","@type":"Person","name":"dgenio"},"datePublished":"2025-11-28T14:52:45.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":1},"url":"https://github.com/1695/python-sdk/issues/1695"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:5626b95c-3dca-9332-c8fd-c0b3d7d13242 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | C25E:28C7B7:1D8A:279F:6A616376 |
| html-safe-nonce | fb6160501135c94a5a2f0b3f2ad67b878ccb1f397fb5818ea119bba1e2fb4f5c |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJDMjVFOjI4QzdCNzoxRDhBOjI3OUY6NkE2MTYzNzYiLCJ2aXNpdG9yX2lkIjoiMzUyMjYwNDM3MjYyMjE0MDI3OCIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | e2110037371fecabd1ec8fdf39d3f18ac56b614d6ddcd638334fd304fe63765a |
| hovercard-subject-tag | issue:3675175578 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/modelcontextprotocol/python-sdk/1695/issue_layout |
| twitter:image | https://opengraph.githubassets.com/6fc91607b031bc21c5d933df6799c405ced3c2bfb008e27667f000c2a8368bd8/modelcontextprotocol/python-sdk/issues/1695 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/6fc91607b031bc21c5d933df6799c405ced3c2bfb008e27667f000c2a8368bd8/modelcontextprotocol/python-sdk/issues/1695 |
| og:image:alt | Description Summary FastMCP currently uses introspection to automatically inject a Context parameter into tools/resources when it detects a parameter with the right name/type. This is convenient bu... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | dgenio |
| hostname | github.com |
| expected-hostname | github.com |
| None | c258d2b06b498220e3b94af28b26bbbf58f4203a6373725f779afcc867afd263 |
| turbo-cache-control | no-preview |
| go-import | github.com/modelcontextprotocol/python-sdk git https://github.com/modelcontextprotocol/python-sdk.git |
| octolytics-dimension-user_id | 182288589 |
| octolytics-dimension-user_login | modelcontextprotocol |
| octolytics-dimension-repository_id | 862584018 |
| octolytics-dimension-repository_nwo | modelcontextprotocol/python-sdk |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 862584018 |
| octolytics-dimension-repository_network_root_nwo | modelcontextprotocol/python-sdk |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 5f67bc431418961e0814f1eb30a4231250e4726d |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width