Expose the middleware chain on MCPServer and stop sending unrequested change notifications (#3201)
This commit is contained in:
parent
528e366558
commit
c9c431b71a
1 changed files with 234 additions and 28 deletions
38
docs_src/subscriptions/tutorial006.py
Normal file
38
docs_src/subscriptions/tutorial006.py
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
from mcp_types import INVALID_REQUEST, SubscriptionsListenRequestParams
|
||||
|
||||
from mcp.server.auth.middleware.auth_context import get_access_token
|
||||
from mcp.server.context import CallNext, HandlerResult, ServerRequestContext
|
||||
from mcp.server.mcpserver import MCPServer
|
||||
from mcp.shared.exceptions import MCPError
|
||||
|
||||
# Who may see each file. Replace this table with a database or your RBAC system.
|
||||
ACCESS = {
|
||||
"files://report.pdf": {"alice", "bob"},
|
||||
"files://payroll.csv": {"carol"},
|
||||
}
|
||||
|
||||
|
||||
def can_access(user: str | None, uri: str) -> bool:
|
||||
return user is not None and user in ACCESS.get(uri, set())
|
||||
|
||||
|
||||
async def gate_subscriptions(ctx: ServerRequestContext, call_next: CallNext) -> HandlerResult:
|
||||
if ctx.method == "subscriptions/listen":
|
||||
params = SubscriptionsListenRequestParams.model_validate(ctx.params or {}, by_name=False)
|
||||
token = get_access_token()
|
||||
user = token.subject if token else None
|
||||
if not all(can_access(user, uri) for uri in params.notifications.resource_subscriptions or ()):
|
||||
raise MCPError(INVALID_REQUEST, "not permitted to watch the requested resources")
|
||||
return await call_next(ctx)
|
||||
|
||||
|
||||
mcp = MCPServer("Reports", middleware=[gate_subscriptions])
|
||||
|
||||
|
||||
@mcp.resource("files://{name}")
|
||||
def file(name: str) -> str:
|
||||
uri = f"files://{name}"
|
||||
token = get_access_token()
|
||||
if not can_access(token.subject if token else None, uri):
|
||||
raise MCPError(INVALID_REQUEST, f"Unknown resource: {uri}")
|
||||
return f"contents of {name}"
|
||||
Loading…
Reference in a new issue