Title: Feature Proposal: Secure Tool/Resource/Prompt Decorators with Auth + Encrypted I/O · Issue #1305 · modelcontextprotocol/python-sdk · GitHub
Open Graph Title: Feature Proposal: Secure Tool/Resource/Prompt Decorators with Auth + Encrypted I/O · Issue #1305 · modelcontextprotocol/python-sdk
X Title: Feature Proposal: Secure Tool/Resource/Prompt Decorators with Auth + Encrypted I/O · Issue #1305 · modelcontextprotocol/python-sdk
Description: Description 🚀 Feature Request I would like to propose adding a secure wrapper layer to @mcp.tool, @mcp.resource, and @mcp.prompt that supports: Authentication (Auth) Ability to pass an auth function (e.g. verify_identity()) that can vali...
Open Graph Description: Description 🚀 Feature Request I would like to propose adding a secure wrapper layer to @mcp.tool, @mcp.resource, and @mcp.prompt that supports: Authentication (Auth) Ability to pass an auth functio...
X Description: Description 🚀 Feature Request I would like to propose adding a secure wrapper layer to @mcp.tool, @mcp.resource, and @mcp.prompt that supports: Authentication (Auth) Ability to pass an auth functio...
Opengraph URL: https://github.com/modelcontextprotocol/python-sdk/issues/1305
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Feature Proposal: Secure Tool/Resource/Prompt Decorators with Auth + Encrypted I/O","articleBody":"### Description\n\n🚀 Feature Request\n\nI would like to propose adding a secure wrapper layer to @mcp.tool, @mcp.resource, and @mcp.prompt that supports:\n\n1. Authentication (Auth)\n\nAbility to pass an auth function (e.g. verify_identity()) that can validate JWT, Certs, or TEE Attestation before executing the function.\n\nAuthentication should be bidirectional - we need to verify both:\n 1. Client authentication - Is the client authorized to use the tool?\n 2. Tool/Server authentication - Is the tool legitimate and trustworthy?\n\n\nIf authentication fails, return a proper MCP Error (e.g. 403 Forbidden).\n\n2. Key Negotiation Mechanism\n\nClient provides a public key (PK) or session token.\n\nServer performs Diffie-Hellman (ECDH) or TLS/mTLS handshake to derive a session key.\n\nSession key is stored in context and used for symmetric encryption/decryption of I/O.\n\n3. Unified Secure Interface\n\nDevelopers could write secure MCP functions like this:\n\n```\n@mcp.secure_tool(auth=verify_identity, encrypt=True)\nasync def trade(symbol: str, amount: float) -\u003e str:\n return f\"Trade {amount} {symbol} executed\"\n\n```\nAnd the same approach could apply to resource and prompt.\n\n🔹 Example Implementation\n\n```\nimport functools\nfrom mcp.server.fastmcp import FastMCP, tool, resource, prompt\nfrom mcp.server.models import Error\nfrom cryptography.hazmat.primitives.ciphers.aead import AESGCM\nimport os, base64\n\nmcp = FastMCP(\"SecureApp\")\n\n# ========== Simple Key Management ==========\nSESSION_KEY = AESGCM.generate_key(bit_length=128)\naesgcm = AESGCM(SESSION_KEY)\nNONCE_SIZE = 12\n\ndef encrypt(data: str) -\u003e str:\n nonce = os.urandom(NONCE_SIZE)\n ct = aesgcm.encrypt(nonce, data.encode(), None)\n return base64.b64encode(nonce + ct).decode()\n\ndef decrypt(token: str) -\u003e str:\n raw = base64.b64decode(token)\n nonce, ct = raw[:NONCE_SIZE], raw[NONCE_SIZE:]\n pt = aesgcm.decrypt(nonce, ct, None)\n return pt.decode()\n\n# ========== Auth Function ==========\ndef verify_identity() -\u003e bool:\n # TODO: implement JWT / CERT / Attestation validation\n return True\n\n# ========== Decorator Factory ==========\ndef secure_wrapper(deco, auth=None, encrypt_io=False, *args, **kwargs):\n def decorator(func):\n @deco(*args, **kwargs) # wrap original MCP decorator\n @functools.wraps(func)\n async def wrapper(*f_args, **f_kwargs):\n # Auth check\n if auth and not auth():\n raise Error(code=403, message=\"Authentication failed\")\n\n # Decrypt inputs\n if encrypt_io:\n f_kwargs = {k: decrypt(v) if isinstance(v, str) else v \n for k, v in f_kwargs.items()}\n\n # Execute\n result = await func(*f_args, **f_kwargs) if callable(func) else func\n\n # Encrypt outputs\n if encrypt_io and isinstance(result, str):\n result = encrypt(result)\n\n return result\n return wrapper\n return decorator\n\n# Three secure variants\ndef secure_tool(auth=None, encrypt_io=False, *args, **kwargs):\n return secure_wrapper(tool, auth, encrypt_io, *args, **kwargs)\n\ndef secure_resource(auth=None, encrypt_io=False, *args, **kwargs):\n return secure_wrapper(resource, auth, encrypt_io, *args, **kwargs)\n\ndef secure_prompt(auth=None, encrypt_io=False, *args, **kwargs):\n return secure_wrapper(prompt, auth, encrypt_io, *args, **kwargs)\n\n# ========== Usage Example ==========\n@secure_tool(auth=verify_identity, encrypt_io=True)\nasync def add(a: int, b: int) -\u003e str:\n return f\"sum={a+b}\"\n\n@secure_resource(\"secure://greet/{name}\", auth=verify_identity, encrypt_io=True)\ndef greeting(name: str) -\u003e str:\n return f\"Hello, {name}!\"\n\n@secure_prompt(auth=verify_identity, encrypt_io=True)\ndef greet_user(name: str) -\u003e str:\n return f\"Write a secure greeting for {name}\"\n\n```\n\n🔹 Encrypted I/O Flow\n\nInput: client encrypts arguments with session key → sends\n\nServer: decrypts args → executes function\n\nOutput: result encrypted → returned to client\n\nClient: decrypts result with the same session key\n\n\n✅ Summary\n\ntool, resource, and prompt can all uniformly support auth + encrypted I/O.\n\nImplemented via decorator factory pattern, keeping code clean.\n\nSupports pluggable JWT, Cert, TEE Attestation validation.\n\nSession key negotiation can use TLS/mTLS or ECDH.\n\nThis would make MCP safer to use in environments where sensitive data and secure tool execution are required.\n\n\n\n### References\n\n[_MR_](https://github.com/modelcontextprotocol/python-sdk/pull/1309) https://github.com/modelcontextprotocol/python-sdk/pull/1309","author":{"url":"https://github.com/wenhuizhang","@type":"Person","name":"wenhuizhang"},"datePublished":"2025-08-25T03:58:23.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":2},"url":"https://github.com/1305/python-sdk/issues/1305"}
| 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:c8470d79-ff36-e5b2-a066-381a0fd973b4 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | D710:C6842:10DA77:16BFA9:6A626B1C |
| html-safe-nonce | daeb696b7aaf384c53571cc57c72182416b315d2ffcd3b0bf26fd5870e683300 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJENzEwOkM2ODQyOjEwREE3NzoxNkJGQTk6NkE2MjZCMUMiLCJ2aXNpdG9yX2lkIjoiMTgxNTIwODIwMjUwNzY2MTA5IiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | 95b379ef01988696e61632ed2c0004d4dd772c7e31ba835f47570be3e7752ff2 |
| hovercard-subject-tag | issue:3350320551 |
| 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/1305/issue_layout |
| twitter:image | https://opengraph.githubassets.com/e938bb6b9c48aaf9f672194fcd136c1cd7ac703fdb79390a090351e2e4898916/modelcontextprotocol/python-sdk/issues/1305 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/e938bb6b9c48aaf9f672194fcd136c1cd7ac703fdb79390a090351e2e4898916/modelcontextprotocol/python-sdk/issues/1305 |
| og:image:alt | Description 🚀 Feature Request I would like to propose adding a secure wrapper layer to @mcp.tool, @mcp.resource, and @mcp.prompt that supports: Authentication (Auth) Ability to pass an auth functio... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | wenhuizhang |
| hostname | github.com |
| expected-hostname | github.com |
| None | 19769ef9d383a84eeab48bb9b309078c20f4532b73eae2f9713b18406513e0ad |
| 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 | 76dc6b11f13eaeec1329217c9f16c262ade27a1e |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width