SESSION TOOL SCOPING
Same server, different customers
One MCP gateway, one tool backend, N isolated views. Per-session allow and deny rules with wildcards — enforced at the gateway layer and updatable mid-conversation.
WHAT IT LOOKS LIKE
One server. Three sessions. Three different worlds.
Shared backend
VIVI knowledge-base server
500 knowledge-base tools · one deployment · one set of credentials
3
visible tools
- ▸VIVI__kb_finance
- ▸VIVI__kb_hr
- ▸VIVI__kb_legal
12
visible tools
- ▸VIVI__kb_pricing
- ▸VIVI__kb_catalog
- ▸VIVI__kb_support_*
- ▸…9 more
497
visible tools
- ▸VIVI__*
- ▸—
- ▸denied: VIVI__internal_debug
- ▸denied: VIVI__beta_*
All three sessions hit the same server. The gateway filters tools/list, SEARCH_TOOLS, and tools/call per session — the agent never sees tools that aren't in scope.
HOW IT WORKS
Four primitives. One line of Python.
Allow and deny lists with wildcards
Two optional fields on every session: allowed_tool_names (allowlist) and denied_tool_names (denylist). Both accept exact names or whole-server wildcards like HUBSPOT__*. Deny always wins, so you can allow an entire server and carve out a single internal tool in one line.
Three scope levels
Every session is scoped to the authenticated user. Beyond that, you can narrow to a specific server or a specific bundle. The allow and deny filters then apply within whichever universe you chose. Passing both server_id and bundle_id is rejected — they are mutually exclusive.
server_id | bundle_id | Scope | Tool universe |
|---|---|---|---|
| null | null | Gateway-wide | All tools across all connected servers |
| uuid | null | Server-scoped | Only tools from that one server |
| null | uuid | Bundle-scoped | Only tools from that one bundle |
Change scope mid-conversation
PATCH the session at any time to tighten or loosen the rules. Only the fields you provide are changed — omit allowed_tool_names to leave it unchanged, or pass null to clear it. Useful for progressive disclosure: start lean, unlock specialized tools as the user's intent reveals itself, revoke access the moment the conversation ends.
Filtered at every tool surface
Session scope applies uniformly to tools/list in LIST mode, SEARCH_TOOLS and EXECUTE_TOOL in SEARCH_EXECUTE mode, and direct tools/call. Three documented exceptions: gateway SYSTEM__* builtins are always visible, direct connections to a single server via /mcp/servers/{server_id} bypass scoping by design, and the stateless REST endpoint /api/v1/tools/search has no session context.
| Surface | Scoped? | Behavior |
|---|---|---|
| tools/list (LIST mode) | Yes | Only allowed tools appear |
| SEARCH_TOOLS | Yes | Vector search results filtered after scoring |
| EXECUTE_TOOL | Yes | Rejects calls outside scope |
| tools/call (direct) | Yes | Same enforcement path |
| SYSTEM__* builtins | No | Gateway meta-tools — always visible |
| /mcp/servers/{server_id} | No | Direct server connection — bypasses by design |
| POST /api/v1/tools/search | No | Stateless REST — no session context |
RESOLUTION ORDER
Three rules. Evaluated in order.
Deny always wins
If a tool matches any deny pattern, it's blocked — even if it also matches an allow pattern.
No allow list = allow all
If allowed_tool_names is null, every tool that survives the deny list is visible.
With an allow list, match is required
If allowed_tool_names is set, a tool must match at least one entry (exact or wildcard) to be visible.
CUSTOMER: VIVI
One server, hundreds of tenants, zero cross-contamination. Session scoping is how we go from "AI assistant in a demo" to "AI assistant each customer actually trusts with their data."
INDUSTRY CONTEXT
Every platform filters tools. The level matters.
The MCP spec does not define per-session tool filtering — SEP-1300 was rejected and closed. So every major platform implements it at its own layer. MCP Gateway is session-level, which means the scope can change during a conversation with a single PATCH.
| Platform | Approach | Level |
|---|---|---|
| MCP Gateway | allowed/denied_tool_names per session | Gateway |
| OpenAI | allowed_tools per API request | Client API |
| AWS Bedrock | Cedar policies per principal | Gateway |
| Kong AI Gateway | Consumer Group ACLs | Gateway |
| LiteLLM | Allowlists per API key / team | Proxy |
| CrewAI | get_mcp_tools() per agent | Framework |
WHERE IT FITS
Use cases
Multi-tenant SaaS
One MCP server, 500 knowledge-base tools, N customers. Each customer's agent is scoped to only their data — no cross-contamination, no separate deployments.
Role-based access
Support agents see customer-facing tools. Admin agents see internal tools. Same backend, different session scopes — no RBAC rewiring required.
Progressive disclosure
Start the session with a lean toolset. As the user's intent reveals itself, PATCH in more specific tools. Keeps the tool list tight and the context window lean.
Context optimization
Fewer tools = better tool selection accuracy. Anthropic's research shows tool accuracy degrades past 30–50 tools; session scoping is how you stay under the cliff.
What's next
Ship multi-tenant agents this week
Session scoping ships with every MCP Gateway deployment. Create a scoped session in one call, change it mid-conversation, or strip it back to unrestricted — all through the same Python SDK.