-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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 validate JWT, Certs, or TEE Attestation before executing the function.
Authentication should be bidirectional - we need to verify both:
- Client authentication - Is the client authorized to use the tool?
- Tool/Server authentication - Is the tool legitimate and trustworthy?
If authentication fails, return a proper MCP Error (e.g. 403 Forbidden).
- Key Negotiation Mechanism
Client provides a public key (PK) or session token.
Server performs Diffie-Hellman (ECDH) or TLS/mTLS handshake to derive a session key.
Session key is stored in context and used for symmetric encryption/decryption of I/O.
- Unified Secure Interface
Developers could write secure MCP functions like this:
@mcp.secure_tool(auth=verify_identity, encrypt=True)
async def trade(symbol: str, amount: float) -> str:
return f"Trade {amount} {symbol} executed"
And the same approach could apply to resource and prompt.
πΉ Example Implementation
import functools
from mcp.server.fastmcp import FastMCP, tool, resource, prompt
from mcp.server.models import Error
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os, base64
mcp = FastMCP("SecureApp")
# ========== Simple Key Management ==========
SESSION_KEY = AESGCM.generate_key(bit_length=128)
aesgcm = AESGCM(SESSION_KEY)
NONCE_SIZE = 12
def encrypt(data: str) -> str:
nonce = os.urandom(NONCE_SIZE)
ct = aesgcm.encrypt(nonce, data.encode(), None)
return base64.b64encode(nonce + ct).decode()
def decrypt(token: str) -> str:
raw = base64.b64decode(token)
nonce, ct = raw[:NONCE_SIZE], raw[NONCE_SIZE:]
pt = aesgcm.decrypt(nonce, ct, None)
return pt.decode()
# ========== Auth Function ==========
def verify_identity() -> bool:
# TODO: implement JWT / CERT / Attestation validation
return True
# ========== Decorator Factory ==========
def secure_wrapper(deco, auth=None, encrypt_io=False, *args, **kwargs):
def decorator(func):
@deco(*args, **kwargs) # wrap original MCP decorator
@functools.wraps(func)
async def wrapper(*f_args, **f_kwargs):
# Auth check
if auth and not auth():
raise Error(code=403, message="Authentication failed")
# Decrypt inputs
if encrypt_io:
f_kwargs = {k: decrypt(v) if isinstance(v, str) else v
for k, v in f_kwargs.items()}
# Execute
result = await func(*f_args, **f_kwargs) if callable(func) else func
# Encrypt outputs
if encrypt_io and isinstance(result, str):
result = encrypt(result)
return result
return wrapper
return decorator
# Three secure variants
def secure_tool(auth=None, encrypt_io=False, *args, **kwargs):
return secure_wrapper(tool, auth, encrypt_io, *args, **kwargs)
def secure_resource(auth=None, encrypt_io=False, *args, **kwargs):
return secure_wrapper(resource, auth, encrypt_io, *args, **kwargs)
def secure_prompt(auth=None, encrypt_io=False, *args, **kwargs):
return secure_wrapper(prompt, auth, encrypt_io, *args, **kwargs)
# ========== Usage Example ==========
@secure_tool(auth=verify_identity, encrypt_io=True)
async def add(a: int, b: int) -> str:
return f"sum={a+b}"
@secure_resource("secure://greet/{name}", auth=verify_identity, encrypt_io=True)
def greeting(name: str) -> str:
return f"Hello, {name}!"
@secure_prompt(auth=verify_identity, encrypt_io=True)
def greet_user(name: str) -> str:
return f"Write a secure greeting for {name}"
πΉ Encrypted I/O Flow
Input: client encrypts arguments with session key β sends
Server: decrypts args β executes function
Output: result encrypted β returned to client
Client: decrypts result with the same session key
β Summary
tool, resource, and prompt can all uniformly support auth + encrypted I/O.
Implemented via decorator factory pattern, keeping code clean.
Supports pluggable JWT, Cert, TEE Attestation validation.
Session key negotiation can use TLS/mTLS or ECDH.
This would make MCP safer to use in environments where sensitive data and secure tool execution are required.