ADR 0006: Standardize the tool namespace control plane
- Status: Accepted
- Date: 2026-08-09
Context
SharedOS already required a capability grant before an agent could discover or
invoke a tool. Hosts additionally group tools into user-configurable namespaces
such as calendar, email, github, or a user-connected notion MCP server.
That second mechanism answers a different question: which families of tools
should exist in this user's current tool surface at all?
Without a shared contract, every host would recreate catalog metadata, enable/disable behavior, MCP aggregation, and execution-time checks. The common process-global mutable registry pattern would also allow one user's MCP reload to remove or replace another user's tools under concurrent requests.
Three concepts called “namespace” must remain distinct:
AccessContext.namespaceIdisolates a tenant, sandbox, or experiment world.ResourceRef.namespaceidentifies the capability authority domain, such asfilesorcalendar.ToolDefinition.namespacegroups tools for discovery and user/product enablement, such ascalendarornotion.
They may use the same text in simple integrations, but they have different security meanings and must not be inferred from one another.
Decision
Every SharedOS tool definition declares:
- a logical
namespace; - a host-extensible
source, such assharedos,native,mcp, orcomposio; - a conservative
readWritecatalog classification; - its existing exact
requiredCapability.
Every trusted AccessContext declares its effective
enabledToolNamespaces. An empty selection means all tool namespaces are off.
A tool is usable only when all three conditions hold:
registered for this context
AND tool namespace enabled
AND required capability allowed
The kernel applies the namespace check during filtered discovery and repeats it
during invocation before capability authorization. Namespace enablement never
creates authority, and source, readWrite, descriptions, annotations, and
tool names are metadata rather than permission evidence.
SharedOS exposes a context-specific namespace catalog and an idempotent patch
contract with enable and disable lists. A host-owned
ToolNamespaceSettingsStore applies that patch atomically against fresh state,
enforces any product or organization ceiling, persists it, and returns the
authoritative effective selection. The standard HTTP/client adapter exposes
this as GET and PUT /v1/tools/namespaces. Embedded hosts can call the same
kernel methods directly.
Static tools use the ordinary registry. User-specific MCP servers and other
dynamic catalogs use ContextToolProvider, which resolves handlers for exactly
one trusted access context. The kernel merges those handlers into an ephemeral
registry for that operation and rejects duplicate names. A dynamic provider
must not mutate a singleton registry shared by concurrent users.
SharedOS owns the contracts, deterministic patch semantics, catalog aggregation, and enforcement. Each host continues to own:
- authentication and consent UI;
- namespace-setting persistence and policy ceilings;
- OAuth tokens, MCP credentials, server connections, and refresh lifecycle;
- connector egress controls and concrete tool implementations.
For example, importing a Notion MCP server remains a host operation. The host
supplies that user's Notion handlers through a context provider with
namespace: "notion" and source: "mcp". SharedOS then lists and toggles the
namespace consistently, but a Notion capability grant is still required for
each visible or executed operation.
Consequences
Positive
- Product and evaluation hosts share one catalog and enablement model without importing product code into SharedOS.
- Disabled namespaces disappear from model-visible discovery and fail closed at invocation even when a caller guesses a tool name.
- Capability grants remain the sole source of operation authority.
- User-specific MCP catalogs are isolated across concurrent requests.
- Hosts can use different databases and connector SDKs behind the same control plane.
Costs
- This is a breaking
0.xprotocol change: every tool definition and access context must declare its namespace fields explicitly. - Hosts must implement the settings port to support the standard PUT endpoint.
- Hosts must map their stored setting into every newly resolved access context; mutating one context object is intentionally insufficient.
- A namespace is intentionally coarse. Fine-grained calendar, Notion, file, or account access still requires capability scopes and host connector policy.
Rejected alternatives
Infer the tool namespace from its name. Rejected because names such as
mcp_notion_search are conventions, not stable authority or grouping data.
Use capabilities alone. Rejected because users and products need a coarse, default-off tool-surface switch independent of fine-grained resource authority.
Treat namespace enablement as authority. Rejected because enabling
calendar must not imply permission to create, delete, or read every calendar.
Use a mutable singleton MCP registry. Rejected because concurrent users can overwrite one another's catalogs and because a host-specific loading strategy does not belong in SharedOS.