🔌

MCP

P0 · Foundation Planned · spec-2025-11-25 pinned · ships parallel with AUTH Wave 2 close Owner: CTO seat → interim CEO

The external-agent door. Claude / Cursor / Codex / Cline / any MCP-2025-11-25 client sees one server. Inside, 22 modules' tool catalogues are federated, capability-gated, persona-stamped, and audit-chained — without the external agent ever knowing about the federation.

MCP Gateway plays three strategic roles simultaneously. Role 1 — external-client federation: 22 module-level MCP servers (cyberos.brain, cyberos.skill, cyberos.proj, …) collapse to a single discovery endpoint at https://mcp.cyberos.com; external agents see one server with one OAuth flow. Role 2 — capability broker: OAuth 2.1 + PKCE audience-bound tokens + AUTH scope_grants + tool annotations (destructive / readOnly / idempotent / openWorld) gate every invocation; destructive ops require human-confirm or Elicitation flow; persona-version is stamped on every call so "the AI did it" is replayable. Role 3 — tool-discovery surface: the registry external agents introspect — tools/list returns the SEP-986-named verbs, prompt templates land in prompts/list, long-running work is tracked via the Tasks primitive. Built on MCP spec 2025-11-25 (Streamable HTTP transport, OAuth 2.1 with PRM, Elicitation, Tasks). The planned implementation lives at cyberos/services/mcp-gateway/.

MCP Gateway is the tool federation layer that turns CyberOS's 22 modules into a single, coherent MCP server. Each module publishes a per-server (named cyberos.brain, cyberos.skill, cyberos.crm, …) that exposes its verbs as tools (brain.put_memory, skill.invoke_skill, crm.update_account, …); the gateway aggregates these into a federated surface that Claude / Codex / Cursor / Cline / any 2025-11-25-spec client sees as one server. OAuth 2.1 + PKCE (RFC 7636) gates every tool call; the audience claim pins the call to a specific module; the RBAC predicate from AUTH enforces who can do what; the persona-version stamp captures which agent authored the call. Tool annotations (destructive · readOnly · idempotent · openWorld) drive human-confirm gating. Tasks primitive handles long-running work; Elicitation reverses control mid-execution to ask the user a question.

Strategic role
External-agent door
22 modules → one MCP server
Status
Planned
P0 · design phase · P0 · slice 3
Spec compliance
MCP 2025-11-25
Streamable HTTP · Tasks · Elicitation
External clients (target)
Claude · Cursor · Codex · Cline
all 2025-11-25 compliant clients
Transports
Streamable HTTP · SSE
RFC 9112 chunked + EventSource
Auth
OAuth 2.1 PKCE
RFC 7636 · audience-bound · PRM
Tools at P0 (est.)
~80
BRAIN · Skill · AUTH · AI
Tools at P3 (est.)
~300+
22 modules × ~15 verbs each
Destructive-op gating
Human-confirm
via Elicitation or explicit token
Persona stamp coverage
100%
on every audit row
Depends on
AUTH · BRAIN · OBS
+ AI Gateway (P0 · slice 1)
Naming convention
SEP-986
cyberos.{module}.{verb}_{noun}
0

The bigger picture — three strategic roles

MCP Gateway is "the external-agent door." That sentence does a lot of work. Without this module, every external agent (Claude Code on a Member's laptop, Cursor on an engineer's IDE, Codex in CI) would need 22 separate OAuth flows + 22 separate discovery loops + 22 separate audit emissions. The naive design — "one MCP server per module, agents figure it out" — is intractable past 3 modules. MCP Gateway collapses 22 to 1 at the edge while keeping per-module ownership intact behind the federation.

Role 1 · External-client federation
22 modules → one MCP server

Claude Code, Cursor, Codex, Cline, and any 2025-11-25 spec client hit a single discovery endpoint at https://mcp.cyberos.com/.well-known/mcp. The gateway aggregates per-module tool catalogues via SEP-986 naming (cyberos.brain.put_memory, cyberos.proj.create_issue, etc.) so external agents see one server. Per-module servers stay separate behind the edge; federation only happens at the surface. This means Members can use the AI tools they already trust without learning a new orchestrator.

Role 2 · Capability broker
Every external invocation gated

Audience-bound OAuth 2.1 + PKCE tokens carry tenant_id + agent_persona + scope_grants per AUTH §2.7. Tool annotations (destructive / readOnly / idempotent / openWorld) drive gating: destructive ops require either an explicit confirmation token in the request or an Elicitation flow that asks the user. The persona stamp on every audit row makes "external agent X did Y" replayable down to which Claude/Cursor session authored it.

Role 3 · Tool-discovery surface
The registry external agents introspect

tools/list returns ~80 tools at P0 (~300+ at P3); prompts/list exposes module-specific prompt templates; resources/list exposes BRAIN paths the agent can read. Long-running work (KB ingestion, big migrations, bulk imports) is tracked via the Tasks primitive — the agent can start a task, poll status, get a streaming progress update, and resume on reconnect. Elicitation reverses control mid-execution to ask "should I proceed with the destructive step?".

MCP Gateway in the runtime — federation map

flowchart TB subgraph clients["External MCP clients (2025-11-25)"] CC["Claude Code"] CURSOR["Cursor"] CODEX["Codex / GPT-5 agent"] CLINE["Cline"] OTHER["any compliant agent"] end MCPGW["🔌 MCP Gateway
OAuth 2.1 · Streamable HTTP · Tasks · Elicitation"] subgraph perm["Per-module MCP servers (internal)"] BRSV["cyberos.brain"] SKSV["cyberos.skill"] PRSV["cyberos.proj"] CRMSV["cyberos.crm"] KBSV["cyberos.kb"] N["… 17 more"] end subgraph dep["Platform deps"] AUTH["🔐 AUTH
scope_grants check"] AIGW["⚡ AI Gateway
persona stamp resolution"] BRAIN["🧠 BRAIN
audit chain"] OBS["👁 OBS
traces"] end CC --> MCPGW CURSOR --> MCPGW CODEX --> MCPGW CLINE --> MCPGW OTHER --> MCPGW MCPGW -. "JWT audience verify".-> AUTH MCPGW -. "fetch persona-version".-> AIGW MCPGW --> BRSV MCPGW --> SKSV MCPGW --> PRSV MCPGW --> CRMSV MCPGW --> KBSV MCPGW --> N MCPGW --> BRAIN MCPGW --> OBS classDef hub fill:#cffafe,stroke:#0e7490,stroke-width:3px,color:#164e63 classDef client fill:#e0e7ff,stroke:#3730a3 classDef internal fill:#f5ede6,stroke:#45210e classDef dep fill:#fef6e0,stroke:#9c750a class MCPGW hub class CC,CURSOR,CODEX,CLINE,OTHER client class BRSV,SKSV,PRSV,CRMSV,KBSV,N internal class AUTH,AIGW,BRAIN,OBS dep

External clients never reach per-module servers directly. The gateway is the only external surface; this is the protocol-level guarantee that auth + audit + persona-stamp are uniformly applied.

Auto vs human-in-loop operations matrix

OperationHow it happensWhy this split
Tool discovery (tools/list)Auto — filtered by client's scope_grantsAgent only sees tools it could invoke; reduces surface area shown.
Read-only tool call (annotation: readOnly)Auto when scope_grants permitRead is low-risk; latency-sensitive; agent flow shouldn't break.
Idempotent write (annotation: idempotent)Auto with idempotency-keyRetry-safe; idempotency-key prevents double-write on transport retry.
Non-idempotent write (default)Auto with scope check + audit emitStandard write path; broker checks scope + writes pre/post audit rows.
Destructive op (annotation: destructive)Human-confirm always — explicit token or ElicitationEU AI Act Art. 14 + safety policy; cannot be auto-invoked regardless of confidence.
Long-running work (Tasks primitive)Auto-start, polled by agent, resumable on reconnectBig ingests, migrations, bulk imports — must survive network blips.
Mid-execution question (Elicitation)Server-initiated; agent forwards to userReverses control: server asks "should I proceed?" mid-call.
Tool catalogue update (list_changed notification)Auto; pushed to subscribed clientsNew tools appear without client re-poll; old tools removed live.
OAuth token refreshAuto via standard refresh-token flowSession continuity for long-lived agent sessions.
1

Why MCP Gateway exists

Per-module MCP servers create N integration points where every AI agent has to negotiate auth, discover tools, and handle errors. As N grows to 22, the agent's job becomes intractable. The gateway pattern collapses N into 1: agents see a single MCP server with one OAuth flow, one tool catalogue, one discovery endpoint. The 22 modules continue to publish their per-server tools; the gateway federates them. Naming (cyberos.brain.put_memory) preserves the module origin so audit + revocation remain per-module.

🌐
One discovery, all tools

Agents hit /.well-known/mcp once and discover every module's tools. Per-module servers stay separate; federation is at the edge.

🛡
OAuth-protected, RBAC-evaluated

PKCE-only OAuth 2.1; every tool call audience-bound; every call evaluated by AUTH RBAC; destructive calls human-gated.

Long-running work, first-class

The Tasks primitive supports operations that exceed the request timeout — gateway polls underlying server and reports progress to caller.

The bet: pay the cost of one good federation once. Without MCP Gateway, every agent client (Claude Desktop, Cursor, Cline, custom) has to maintain its own list of N module URLs, N OAuth registrations, N rate-limit handlings. With MCP Gateway, that list collapses to one URL — and replacing a module is a federation-registry update, not a client release.

2

What it does — 5W1H2C5M

+ §9.8 give the full spec. This table is the working summary.

AxisQuestionAnswer
5W · WhatWhat is MCP Gateway?A Rust-axum service that implements the MCP 2025-11-25 spec on the edge, federates tool calls to per-module backends, enforces OAuth 2.1 PRM, applies tool annotations, manages Tasks for long-running work, proxies Elicitation prompts, and emits one audit row per call.
5W · WhoWho calls it?External agents (Claude Desktop / Cursor / Cline / Codex) and internal agents (CUO when invoking Skill, scheduled tasks). Owner: CTO seat (interim CEO).
5W · WhenWhen is it hit?(a) at agent session start (discovery + auth); (b) on every tool call. P0 expected RPS: ~20/s peak; P3+: ~200/s peak.
5W · WhereWhere does it run?Fargate task in SG-1 (P0); multi-region active-active at P3+. TLS terminated at ALB; mTLS to per-module backends.
5W · WhyWhy a gateway?Because N agent clients × N modules = N² OAuth registrations otherwise. Federation collapses to N+1.
1H · HowHow does it work?Agent does OAuth 2.1 PKCE → gateway issues audience-bound token → agent calls tools/list → gateway aggregates from federated servers → agent calls a tool → gateway validates audience + scope + annotation → forwards via mTLS gRPC to module → streams response back → audit row written.
2C · CostCost?Negligible — Fargate task ~$30/month at P0. The gateway adds ~3 ms per tool call; the audit write is the main cost.
2C · ConstraintsConstraints?(a) MCP 2025-11-25 spec compliance. (b) PKCE-only (no implicit grant). (c) Destructive tools MUST require human-confirm. (d) Persona-version MUST be stamped in audit ((FR pending)). (e) Tool names MUST follow SEP-986 verbNoun.dotted.
5M · MaterialsStack?Rust 1.81 · axum 0.7 · rmcp (Rust MCP SDK) · tonic (gRPC to per-module servers) · OAuth via AUTH service · OpenTelemetry · serde_json for spec serialisation.
5M · MethodsMethod choices?Streamable HTTP transport (chunked transfer). SSE for server→client events. Tasks primitive over polling endpoint. Elicitation as inline request/response interrupt. Tool registry as DB-backed catalogue + in-memory cache.
5M · MachinesDeployment?Fargate (2 CPU · 4 GB); behind ALB with WAF. Per-module backends are also Fargate, addressed by Cloud Map service-discovery.
5M · ManpowerWho maintains?0.3 FTE CTO + 0.2 FTE CSO at P0. Each module owner extends the tool catalogue for their module.
5M · MeasurementHow measured?N(FR pending) (read tool p95 ≤ 500 ms) + N(FR pending) (write tool p95 ≤ 1 s). Spec compliance via the MCP conformance test suite. Audit completeness at 100%.
2.5

External-client federation — 22 modules behind one surface

An external agent never knows it's talking to 22 modules. From the agent's perspective, https://mcp.cyberos.com is one MCP server with ~80 tools at P0 (~300+ at P3). The federation is at the edge — per-module servers (cyberos.brain, cyberos.skill, etc.) stay separate inside the cluster, but the gateway is the only thing external clients reach. This section locks the federation contract.

SEP-986 naming convention (per-module ownership preserved)

Tool names follow cyberos.{module}.{verb}_{noun} SEP-986 convention. The module prefix preserves ownership for audit + revocation; the verb_noun form aligns with MCP convention.

PatternExampleWhat it doesOwning module
cyberos.{module}.put_*cyberos.brain.put_memoryCreate or replace a resourceBRAIN
cyberos.{module}.get_*cyberos.brain.get_memoryRead a resourceBRAIN
cyberos.{module}.list_*cyberos.proj.list_issuesList resources (paginated)PROJ
cyberos.{module}.create_*cyberos.proj.create_issueCreate a new entityPROJ
cyberos.{module}.update_*cyberos.crm.update_accountMutate an existing entityCRM
cyberos.{module}.invoke_*cyberos.skill.invoke_skillTrigger a skill / actionSkill
cyberos.{module}.delete_*cyberos.proj.delete_issueTombstone an entity (destructive)PROJ
cyberos.{module}.export_*cyberos.brain.export_dsarExport bulk data (destructive sensitivity)BRAIN

Per-module server registration flow

Each module's MCP server registers itself with the gateway at startup. Registration carries its tool catalogue (with annotations), prompt templates, and resource paths. The gateway maintains a versioned catalogue and pushes list_changed notifications to subscribed clients when modules deploy.

sequenceDiagram autonumber participant M as cyberos.brain (per-module server) participant G as MCP Gateway participant DB as Catalogue DB participant CL as Subscribed clients (Claude, Cursor) participant BR as 🧠 BRAIN audit M->>G: register_module(name, tools[], prompts[], resources[], version) G->>DB: upsert module record + tool catalogue G->>BR: emit mcp.module_registered audit row G->>CL: notification: tools/list_changed Note over G,CL: subscribed agents re-fetch tools/list G-->>M: registered (catalogue_version, registration_token) M->>G: heartbeat every 30s (keep-alive) Note over G: missed 3 heartbeats → module marked unhealthy → tools removed from federation

External client compatibility matrix

ClientMCP spec versionOAuth 2.1Streamable HTTPTasksElicitation
Claude Code2025-11-25
Claude Desktop2025-11-25
Cursor2025-11-25
Codex / GPT-5 agent2025-11-25partial
Cline2025-11-25partial
Older 2024-11-05 clients2024-11-05partialSSE-only

Gateway negotiates the highest mutual version at session init. Older clients fall back to SSE transport + bearer-token auth (no PKCE). Older-client tool surface excludes Tasks and Elicitation features.

2.6

Capability broker — every external invocation gated

The threat model is precise: an external agent (running in Claude Code on a Member's laptop) carries an OAuth token; the agent is fundamentally untrusted (the user might have approved a malicious tool, the agent process might be compromised, the prompt might be injected). The capability broker is the protocol-level guarantee that even a fully-compromised agent cannot escape the bounds of the user's authorised scope.

Tool annotations — what drives gating

AnnotationMeaningGating behaviourExample tools
readOnly: trueNo state mutation. Idempotent always.Auto-invoke if scope permits; no confirm neededcyberos.brain.get_memory, cyberos.proj.list_issues, cyberos.kb.search
idempotent: trueWrite that can be safely retried with same args + idempotency-keyAuto-invoke if scope permits; idempotency-key requiredcyberos.proj.update_issue, cyberos.crm.upsert_account
destructive: trueIrreversible: purge / delete / send-money / public-postHuman confirmation required — explicit confirmation_token in args OR Elicitation flowcyberos.brain.delete_memory{mode: purge}, cyberos.proj.delete_engagement, cyberos.email.send
openWorld: trueReaches external systems (third-party APIs, web fetch)Auto-invoke with additional rate limit + content filtercyberos.web.fetch_url, cyberos.zoominfo.enrich_contact
longRunning: trueReturns a task_id; agent polls for completionAuto-start as Task; agent polls; timeout default 1 hcyberos.kb.ingest_corpus, cyberos.brain.export_dsar
elicits: trueServer may ask agent for additional input mid-callAgent must support Elicitation; falls back to user promptcyberos.cuo.route_with_clarification, cyberos.crm.create_deal_interactive

Audience-bound OAuth — the broker's auth contract

{
  "iss": "https://auth.cyberos.io/<tenant>",
  "sub": "user:stephen@cyberskill.world",
  "aud": "mcp.cyberos.com",          // ← audience-bound: this token is ONLY valid at MCP Gateway
  "iat": 1763112131,
  "exp": 1763115731,
  "tenant_id": "org:cyberskill",
  "agent_persona": "claude-code@user-stephen",  // ← which external agent is calling
  "scope_grants": [
    {"resource": "brain", "actions": ["read", "write"], "sync_class_max": "shareable"},
    {"resource": "proj",  "actions": ["read", "write"], "engagements": ["acme-q3"]},
    {"resource": "kb",    "actions": ["read"]}
  ],
  "client_id": "claude-code-vsce-extension",   // ← which MCP client requested the token
  "code_challenge": "sha256:…",                // ← PKCE binding
  "jti": "01HZK…"
}

The aud claim is the protocol-level guarantee: a token issued for mcp.cyberos.com cannot be replayed against api.cyberos.com. PKCE binding prevents code interception during the auth flow. The scope_grants are checked per-tool-call against the tool's required resource + action.

Destructive-op confirmation flow (Elicitation example)

// Agent calls a destructive tool
→ {"method": "tools/call", "params": {"name": "cyberos.brain.delete_memory", "arguments": {"path": "…/draft.md", "mode": "purge"}}}

// Gateway intercepts: annotation destructive=true, no confirmation_token in args
← {"method": "elicitation/create", "params": {
    "message": "Are you sure you want to PURGE this memory? This is irreversible.",
    "schema": {"type": "object", "properties": {"confirm": {"type": "boolean"}, "reason": {"type": "string"}}, "required": ["confirm", "reason"]}
  }}

// Agent forwards to user; user responds in client UI
→ {"method": "elicitation/response", "params": {"confirm": true, "reason": "Outdated draft superseded by v2"}}

// Gateway forwards original call with confirmation context
// Audit row records BOTH the elicitation prompt AND the user's response
{"op": "put", "path": "meta/mcp-invocations/…", "extra": {"tool": "cyberos.brain.delete_memory", "elicitation": {"prompt": "…", "user_confirmed": true, "reason": "Outdated draft superseded by v2"}}}
2.7

Tool-discovery surface — the registry agents introspect

An agent's effectiveness is bounded by what it can discover. MCP Gateway is the registry external agents use to introspect what CyberOS can do: tools/list (verbs), prompts/list (templated workflows), resources/list (readable data paths), and capabilities (which MCP features are supported). This section locks the discovery surface contracts.

Discovery endpoints

EndpointWhat it returnsFilter / scopingCadence
/.well-known/mcpDiscovery doc · OAuth Protected Resource Metadata (PRM) · transport endpointspublicstatic (cached 1 h)
capabilitiesSupported MCP features (Tasks, Elicitation, sampling, etc.)noneper-session init
tools/listTools available to the calling token's scope_grantsfiltered by JWT scope_grantsper-call + list_changed push
prompts/listPrompt templates for common workflows ("Find the right CUO persona", "Draft a cycle review")filtered by scopeper-call
resources/listBRAIN paths / KB documents the calling token can readfiltered by sync_class + scopeper-call
resources/templates/listURI templates for resource lookup (e.g. brain://memories/decisions/{slug})filtered by scopeper-call

Tasks primitive — long-running work

For operations that take > 30 s (KB corpus ingestion, BRAIN export, bulk migrations), MCP Gateway returns a Task immediately and lets the agent poll for status. The agent can disconnect and reconnect; the Task persists in Postgres.

Task fieldTypePurpose
task_idUUIDStable handle; agent polls tasks/get?id=…
statuspending · running · waiting_for_input · completed · failed · cancelledDrives agent's polling cadence + UI
progress0.0 - 1.0 OR nullIf determinate, agent can render a progress bar
messagestring (streamed)Latest human-readable status; SSE-streamed if agent subscribes
resultJSON · null until completedFinal response; matches the tool's result schema
error{code, message, retriable}If failed; agent decides retry behaviour
created_at / updated_at / expires_attimestampsTasks expire after 24 h default; per-tool override
brain_chainhashReferences the audit row that recorded task start

Prompt templates — pre-canned workflows

Prompts are MCP-defined templated workflows the agent can use. They reduce hallucination by giving the agent a known-good way to invoke a multi-step CyberOS operation.

Prompt namePurposeBound tools
cyberos.weekly_briefGenerate the user's weekly brief from BRAIN + PROJ + CALbrain.list_recent · proj.list_my_issues · cal.list_events
cyberos.decision_to_issuesConvert a BRAIN decision memory into parent + child issuesbrain.get_memory · cuo.invoke_skill (cuo.cpo.decision-to-issues@1) · proj.create_issue
cyberos.draft_cycle_reviewGenerate cycle review from issues + comments + historyproj.get_cycle · proj.list_cycle_issues · ai.chat_complete (with CUO/COO persona)
cyberos.deal_to_engagementConvert a won CRM deal to a PROJ Engagement with rate cardcrm.get_deal · proj.create_engagement · brain.put_memory (audit decision)
cyberos.find_brain_citationsGiven an Issue, suggest BRAIN memories to citeproj.get_issue · brain.semantic_search · proj.create_brain_link

Each prompt is a versioned, audit-anchored workflow; the agent receives the prompt and the bound tool names; the gateway audits prompt invocations separately from individual tool calls.

3

Architecture

Three layers: an edge that speaks the MCP spec to agents, a federation router that fans tool calls out to per-module gRPC backends, and an audit + observability bridge. The 22 modules each run a per-server (e.g. cyberos.brain) that registers itself with the gateway at startup.

graph TB subgraph CLIENTS ["Agents (MCP 2025-11-25 clients)"] CL_D["Claude Desktop"] CL_C["Claude Code CLI"] CUR["Cursor / Cline / Codex"] CUO["🎯 CUO (internal)"] end subgraph GATEWAY ["MCP Gateway (Rust axum + rmcp)"] WK["well_known.rs
/.well-known/mcp
/.well-known/oauth-protected-resource (PRM)"] AUTH_E["oauth_edge.rs
OAuth 2.1 PKCE handshake
(delegates to AUTH service)"] DISC["discovery.rs
tools/list aggregation"] ROUT["federation.rs
tool name → backend server"] ANN["annotations.rs
destructive · readOnly · idempotent"] GATE["gate.rs
RBAC + human-confirm + audience check"] TASKS["tasks.rs
long-running primitive"] ELI["elicitation.rs
mid-execution prompt proxy"] AUD["audit.rs
per-call BRAIN write"] end subgraph BACKENDS ["Per-module MCP servers (mTLS gRPC)"] BR["cyberos.brain
put_memory · view · search · …"] SK["cyberos.skill
invoke_skill · list_skills · …"] AU["cyberos.auth
whoami · check_permission · …"] AI["cyberos.ai
complete · embed · usage_mtd"] CRM["cyberos.crm
(planned · 16 more modules)"] end subgraph SINKS AUTHSVC["🔐 AUTH service
token issuance + RBAC.Check"] BRAIN["🧠 BRAIN
mcp.invocation rows"] OBS["👁 OBS
traces + metrics"] end CL_D --> WK CL_C --> WK CUR --> WK CUO --> WK WK --> AUTH_E AUTH_E --> AUTHSVC WK --> DISC DISC --> ROUT CL_D -->|tools/call| ROUT CUR -->|tools/call| ROUT ROUT --> ANN ANN --> GATE GATE --> AUTHSVC GATE --> BR GATE --> SK GATE --> AU GATE --> AI GATE --> CRM ROUT --> TASKS GATE --> ELI GATE --> AUD AUD --> BRAIN GATEWAY --> OBS classDef planned fill:#e0f2fe,stroke:#0369a1 classDef backend fill:#cffafe,stroke:#0891b2 classDef sink fill:#f5ede6,stroke:#45210e class WK,AUTH_E,DISC,ROUT,ANN,GATE,TASKS,ELI,AUD,CL_D,CL_C,CUR,CUO planned class BR,SK,AU,AI,CRM backend class AUTHSVC,BRAIN,OBS sink

Internal components

ComponentPath (planned)Responsibility
well_known.rsservices/mcp-gateway/src/well_known.rsServes /.well-known/mcp discovery document + /.well-known/oauth-protected-resource (PRM, RFC 9728).
oauth_edge.rsservices/mcp-gateway/src/oauth_edge.rsHandles OAuth 2.1 + PKCE handshake with the agent client. Delegates issuance to AUTH service over gRPC.
discovery.rsservices/mcp-gateway/src/discovery.rsAggregates tools/list across federated backends. Caches catalogue with 60 s TTL; invalidated on backend register.
federation.rsservices/mcp-gateway/src/federation.rsRoutes a tool call (cyberos.brain.put_memory) to the right backend server via mTLS gRPC. Caches resolved endpoints in-memory.
annotations.rsservices/mcp-gateway/src/annotations.rsParses tool annotations from backend manifest. Enforces destructive → human-confirm; readOnly → fast-path RBAC; idempotent → safe-retry; openWorld → strict scope check.
gate.rsservices/mcp-gateway/src/gate.rsComposite gate — verifies audience claim, calls AUTH RBAC.Check, validates idempotency-key, applies rate-limit token bucket.
tasks.rsservices/mcp-gateway/src/tasks.rsTasks primitive ((FR pending)) — long-running tool invocations get a task_id; clients poll for status / result; results streamed via SSE.
elicitation.rsservices/mcp-gateway/src/elicitation.rsElicitation ((FR pending)) — mid-execution, a backend can request user input; gateway proxies that back to the agent client with content-safety filter.
tool_registry.rsservices/mcp-gateway/src/tool_registry.rsPostgres-backed registry. Each backend registers its tools with annotations; collisions rejected at register time ((FR pending)).
rate_limit.rsservices/mcp-gateway/src/rate_limit.rsPer-tool + per-tenant token-bucket rate limit; circuit-breaker on backend errors.
idempotency.rsservices/mcp-gateway/src/idempotency.rsReplay safety via Idempotency-Key header ((FR pending)).
audit.rsservices/mcp-gateway/src/audit.rsEmits one mcp.invocation row per call: agent · tool · args_hash · RBAC-decision · latency · outcome · persona-version.
streamable_http.rsservices/mcp-gateway/src/streamable_http.rsRFC 9112 chunked-transfer HTTP transport per MCP 2025-11-25.
conformance.rsservices/mcp-gateway/tests/conformance.rsMCP conformance test suite runner. Gating CI test ((FR pending)).
4

Data model

The gateway is mostly stateless. Postgres holds the tool registry, Redis caches tool catalogues and Tasks status, BRAIN absorbs the audit rows.

erDiagram SERVER ||--o{ TOOL_DEFINITION: "publishes" TOOL_DEFINITION ||--o{ ANNOTATION: "has" TOOL_DEFINITION ||--o{ TOOL_INVOCATION: "fulfils" TOOL_DEFINITION ||--o{ ELICITATION: "may trigger" TOOL_INVOCATION ||--o{ TASK: "may spawn" TASK ||--o{ TASK_STATUS_UPDATE: "emits" AGENT_CLIENT ||--o{ TOOL_INVOCATION: "calls" AGENT_CLIENT ||--o| OAUTH_REGISTRATION: "registered as" SERVER { string id PK "cyberos.brain" string display_name string endpoint "grpc:/brain.internal:8081" string version string status "active | draining | offline" timestamp registered_at } TOOL_DEFINITION { string name PK "cyberos.brain.put_memory" string server_id FK string description obj input_schema "JSON Schema" obj output_schema string scope_required "brain.put" } ANNOTATION { string tool_name FK string key "destructive | readOnly | idempotent | openWorld | titleHuman | requiresConfirm" string value } AGENT_CLIENT { uuid id PK string display_name "Claude Desktop · Cursor · …" string redirect_uri string client_type "public (PKCE) | confidential" } OAUTH_REGISTRATION { uuid client_id FK string scopes timestamp registered_at } TOOL_INVOCATION { uuid id PK string tool_name FK uuid agent_id FK uuid subject_id "on_behalf_of" string persona_version string args_hash "SHA-256(canonical)" string idempotency_key string outcome "ok | denied | error | task_created" int latency_ms string brain_chain timestamp ts } TASK { uuid id PK uuid invocation_id FK string status "queued | running | completed | failed | cancelled" obj progress "fraction · stage · message" obj result timestamp created_at timestamp completed_at } TASK_STATUS_UPDATE { uuid id PK uuid task_id FK string status obj progress timestamp ts } ELICITATION { uuid id PK uuid invocation_id FK string prompt obj response_schema obj user_response timestamp asked_at timestamp answered_at }

Tool naming convention (SEP-986)

All tool names follow cyberos.{module}.{verb}_{noun}. Verbs match the canonical six (put · view · move · delete) for memory-shaped resources; other modules pick verbs from a shared catalogue.

Example tool nameVerb classAnnotations
cyberos.brain.put_memorywritedestructive=false · idempotent=true · scope=brain.put
cyberos.brain.view_memoryreadreadOnly=true · idempotent=true · scope=brain.read
cyberos.brain.delete_memorydeletedestructive=true · requiresConfirm=true · scope=brain.delete
cyberos.brain.search_memoryqueryreadOnly=true · scope=brain.read
cyberos.skill.invoke_skillexecutedestructive=true · requiresConfirm=conditional · scope=skill.invoke
cyberos.skill.list_skillsreadreadOnly=true · scope=skill.read
cyberos.auth.check_permissionqueryreadOnly=true · scope=auth.read
cyberos.auth.revoke_sessiondestructivedestructive=true · requiresConfirm=true · scope=auth.session_revoke
cyberos.ai.complete_chatexecutedestructive=false · openWorld=true · scope=ai.invoke
cyberos.crm.create_accountwritedestructive=false · idempotent=false · scope=crm.write
5

API surface

The gateway speaks MCP 2025-11-25 to agents and gRPC to backends. A small admin REST surface lets operators inspect the registry and replay invocations.

MCP surface (canonical)

MethodMCP primitivePurpose
GET/.well-known/mcpMCP server discovery doc per spec 2025-11-25.
GET/.well-known/oauth-protected-resourcePRM (RFC 9728) — auth-server URL, scopes, audience.
POST/mcpSingle streamable-HTTP endpoint for all MCP JSON-RPC calls.
JSON-RPCinitializeClient capability negotiation.
JSON-RPCtools/listDiscovery — returns federated tool catalogue.
JSON-RPCtools/callInvoke a tool with arguments.
JSON-RPCresources/listList MCP resources (files, URIs).
JSON-RPCresources/readRead a resource.
JSON-RPCprompts/listList prompt templates.
JSON-RPCprompts/getMaterialise a prompt template.
JSON-RPCcompletion/completeTool-arg autocomplete.
JSON-RPCtasks/getPoll long-running task status.
JSON-RPCtasks/cancelCancel running task.
JSON-RPCelicitation/respondReply to a server-initiated elicitation.
JSON-RPCsampling/createMessageServer-initiated LLM sampling (rate-limited, (FR pending)).
JSON-RPClogging/setLevelServer log-level config.
JSON-RPCroots/listList filesystem roots.
JSON-RPCnotifications/initializedCapability acknowledgement.
JSON-RPCnotifications/progressStreaming progress events.

Backend gRPC surface (per-module servers)

syntax = "proto3";
package cyberos.mcp.backend.v1;

service ModuleMCPServer {
 / Register at gateway startup. Sends manifest of all tools.
 rpc Register(RegisterRequest) returns (RegisterResponse);/ Tool invocation forwarded from gateway. Streamable response.
 rpc InvokeTool(stream ToolCall) returns (stream ToolResult);/ For long-running tools the backend returns a task handle.
 rpc TaskStatus(TaskRef) returns (TaskState);/ Backend may initiate elicitation back through gateway.
 rpc Elicit(ElicitationRequest) returns (ElicitationResponse);/ Health + drain.
 rpc Health(Empty) returns (HealthResponse);
}

message RegisterRequest {
 string server_id = 1;
 string version = 2;
 repeated ToolDefinition tools = 3;
}

message ToolDefinition {
 string name = 1;/ "cyberos.brain.put_memory"
 string description = 2;
 string input_schema = 3;/ JSON Schema
 string output_schema = 4;
 string scope_required = 5;
 map<string, string> annotations = 6;
}

message ToolCall {
 string tool_name = 1;
 string args_json = 2;
 string idempotency_key = 3;
 string subject_jwt = 4;
 string persona_version = 5;
 string trace_id = 6;
}

Admin REST surface (operator-only)

MethodPathPurpose
GET/admin/serversList registered backends + their status.
GET/admin/toolsFull tool catalogue with annotations.
POST/admin/tools/{name}/disableSoft-disable a tool (server returns "method not allowed").
GET/admin/invocationsRecent invocations (filterable by tool, agent, subject).
POST/admin/invocations/{id}/replayReplay an invocation in dry-run mode (read-only tools only).
GET/admin/tasksList active tasks.
POST/admin/tasks/{id}/cancelForce-cancel a stuck task.
6

Key flows

Flow 1 — Well-known discovery + tool listing

sequenceDiagram autonumber participant A as Agent (Claude Desktop) participant G as MCP Gateway participant AS as AUTH service participant BR as cyberos.brain (backend) participant SK as cyberos.skill participant Cache as Catalogue cache A->>G: GET /.well-known/mcp G-->>A: {auth_url, prm_url, transports:["streamable-http"], capabilities:{…}} A->>G: GET /.well-known/oauth-protected-resource G-->>A: {auth_server, scopes, audience:"mcp.cyberos.com"} A->>AS: OAuth 2.1 PKCE auth code flow AS-->>A: {access_token aud=mcp.cyberos.com} A->>G: POST /mcp {jsonrpc:"2.0", method:"initialize"} G-->>A: {capabilities, server_info} A->>G: POST /mcp {method:"tools/list"} G->>Cache: get catalogue alt cache hit Cache-->>G: full tool list else cache miss G->>BR: ListTools G->>SK: ListTools BR-->>G: 12 tools SK-->>G: 8 tools G->>Cache: SET catalogue TTL=60s end G-->>A: {tools: [cyberos.brain.put_memory, cyberos.skill.invoke_skill, …]}

The agent sees one server; under the hood, 22 modules contribute their tools. Caching keeps catalogue assembly < 5 ms p95.

Flow 2 — Tool invocation with OAuth + RBAC

sequenceDiagram autonumber participant A as Agent participant G as MCP Gateway participant GA as gate.rs participant AS as AUTH RBAC.Check participant BR as cyberos.brain participant AUD as audit.rs participant B as 🧠 BRAIN A->>G: POST /mcp {method:"tools/call", name:"cyberos.brain.put_memory",
arguments:{path:"…", body:"…"}, idempotency_key:"…"} G->>GA: verify audience claim (mcp.cyberos.com) G->>GA: load annotations(destructive=false, scope_required=brain.put) GA->>AS: RBAC.Check(subject_jwt, action="brain.put", resource="memories/…") AS-->>GA: {allow:true, reason:"role.founder + scope.brain.put"} GA->>BR: InvokeTool(args_json, persona_version, trace_id) BR-->>GA: stream {chunks, done:{seq, chain, body_hash}} GA-->>A: {content:[{type:"text", text:"…"}], isError:false} GA->>AUD: write mcp.invocation AUD->>B: append row {tool, agent, subject, persona_version, outcome:"ok"}

Per-call latency: ~3 ms gateway overhead + backend processing time. Audit write is fire-and-forget; backlog > 60 s triggers an alert.

Flow 3 — Destructive tool with human-confirm gating

sequenceDiagram autonumber participant A as Agent participant G as MCP Gateway participant ANN as annotations.rs participant ELI as elicitation.rs participant U as User UI (CHAT or IDE) participant SK as cyberos.skill A->>G: tools/call {name:"cyberos.skill.invoke_skill",
arguments:{skill_id:"vietnam-vat-invoice"}} G->>ANN: load annotations ANN-->>G: destructive=true, requiresConfirm=true G->>ELI: needs user confirmation ELI->>U: "Skill 'vietnam-vat-invoice' will create an invoice in BRAIN. Proceed?" alt user approves U-->>ELI: {approved:true} ELI-->>G: proceed G->>SK: InvokeTool(...) SK-->>G: result G-->>A: result else user denies U-->>ELI: {approved:false} ELI-->>G: denied G-->>A: {error:"user_denied", isError:true} end

(FR pending): destructive tool calls without confirmation are rejected. The elicitation UI is rendered by the agent client (Claude Desktop, Cursor) — the gateway is content-agnostic.

Flow 4 — Long-running task via Tasks primitive

sequenceDiagram autonumber participant A as Agent participant G as MCP Gateway participant T as tasks.rs participant BG as cyberos.kb (backend) A->>G: tools/call {name:"cyberos.kb.reindex_corpus"} G->>BG: InvokeTool(...) BG-->>G: {task_id:"tsk_01HZJ…XK", expected_ms:120000} G->>T: register task tsk_01HZJ…XK G-->>A: {task_id, status:"running"} Note over A: agent receives task handle; returns control to user loop poll every 2 s A->>G: tasks/get {id:"tsk_…"} G->>BG: TaskStatus(task_id) BG-->>G: {status:"running", progress:0.34, message:"embedding 3,400 / 10k docs"} G-->>A: {status:"running", progress:0.34, message:"…"} end BG-->>G: {status:"completed", result:{indexed:10000, elapsed_s:118}} A->>G: tasks/get G-->>A: {status:"completed", result:{…}}

(FR pending): Tasks primitive for long-running tool invocations. The agent can release the call and resume the conversation; polling fetches updates.

Flow 5 — Mid-execution elicitation

sequenceDiagram autonumber participant A as Agent participant G as MCP Gateway participant SK as cyberos.skill (vietnam-bank-transfer) participant ELI as elicitation.rs participant U as User UI A->>G: tools/call cyberos.skill.invoke_skill {skill:"vietnam-bank-transfer", amount:25000000} G->>SK: InvokeTool(...) SK->>G: elicitation/request {prompt:"Confirm transfer of ₫25,000,000 to ACME — please type CONFIRM"} G->>ELI: proxy elicitation (with content-safety filter) ELI->>U: render prompt in client UI U->>ELI: types "CONFIRM" ELI-->>G: response {text:"CONFIRM"} G-->>SK: continue invocation SK->>SK: execute transfer SK-->>G: result {napas_tx_id:"…"} G-->>A: result

(FR pending): elicitation proxied with content-safety filter — prevents a compromised backend from injecting prompts that exfiltrate via the user.

7

Tool-call lifecycle

A single tool invocation traverses up to nine states. Most calls run synchronously and reach Completed in < 1 s; long-running ones go via the Tasks primitive.

stateDiagram-v2 [*] --> Received: agent → POST /mcp tools/call Received --> AudienceOK: aud claim matches gateway AudienceOK --> AnnotationLoaded: tool registry hit AnnotationLoaded --> RBACChecked: AUTH RBAC.Check AnnotationLoaded --> Rejected: tool disabled / unknown RBACChecked --> Confirming: destructive + requiresConfirm RBACChecked --> Forwarding: readOnly OR confirmed Confirming --> Forwarding: user approves Confirming --> Denied: user denies Forwarding --> Streaming: backend producing chunks Forwarding --> TaskCreated: long-running, task_id issued TaskCreated --> Polled: agent polls tasks/get Polled --> Polled: status=running Polled --> Completed: status=completed Polled --> Failed: status=failed Streaming --> Completed: done frame Streaming --> Failed: backend error Streaming --> Cancelled: agent / user cancels Completed --> Audited: mcp.invocation row written Failed --> Audited Cancelled --> Audited Rejected --> Audited Denied --> Audited Audited --> [*]
8

Functional Requirements

The CyberOS FR catalogue is being rebuilt one feature at a time via the open feature-request-author Agent Skill.

Previous FR enumerations were archived 2026-05-14 and are no longer reflected on this page. Specific FRs land here as they are re-authored.

9

Non-Functional Requirements

Performance + security NFRs that flow through MCP Gateway. Cross-referenced at nfr-catalog.html#mcp.

NFR IDConcernTargetMeasurement
N(FR pending)MCP read tool p95≤ 500 msk6 load test
N(FR pending)MCP write tool p95≤ 1 sk6 load test
N(FR pending)Gateway overhead per call≤ 5 ms p95internal bench
N(FR pending)tools/list discovery≤ 100 ms p95 (cache hit)internal bench
N(FR pending)Gateway availability (28-day)≥ 99.95%SLO monitor
N(FR pending)MCP spec conformance100% of conformance suiteCI gate
N(FR pending)Audit completeness100% (no dropped invocations)chaos test + BRAIN walk
N(FR pending)Destructive without confirm= 0 eventsCI regression + runtime check
N(FR pending)Tool name violations= 0 (rejected at register)registry validator
N(FR pending)Idempotency-key collision rate= 0 false positivesproperty-based test
N(FR pending)Task status update latency≤ 2 s after backend updatebench/tasks
N(FR pending)Per-tool rate-limit enforcement100% (no overflow)load test
N(FR pending)OAuth 2.1 conformanceOAuth 2.1 + RFC 9728 PRMConformance suite
10

Dependencies

graph LR subgraph upstream ["MCP Gateway depends on"] AUTH["🔐 AUTH
token + RBAC.Check"] BRAIN["🧠 BRAIN
mcp.invocation rows"] OBS["👁 OBS
traces + metrics"] PG["🗄 PostgreSQL
tool registry"] REDIS["⚡ Redis
catalogue + tasks cache"] end MCP["🔌 MCP Gateway"] subgraph backends ["Per-module servers"] BR["cyberos.brain"] SK["cyberos.skill"] AU["cyberos.auth"] AI["cyberos.ai"] OTH["+18 more"] end subgraph clients ["MCP clients"] CL["Claude Desktop"] CC["Claude Code"] CUR["Cursor / Cline / Codex"] INT["Internal agents"] end AUTH --> MCP BRAIN --> MCP OBS --> MCP PG --> MCP REDIS --> MCP MCP --> BR MCP --> SK MCP --> AU MCP --> AI MCP --> OTH CL --> MCP CC --> MCP CUR --> MCP INT --> MCP classDef shipped fill:#f5ede6,stroke:#45210e classDef planned fill:#fef6e0,stroke:#9c750a class BRAIN,SK,REDIS,PG shipped class MCP,AUTH,AI,AU,BR,OTH,OBS planned class CL,CC,CUR,INT shipped
11

Compliance scope

Regulation / standardArticle / clauseMCP Gateway feature
EU AI ActArt. 12 — LoggingOne mcp.invocation row per tool call.
EU AI ActArt. 14 — Human oversightDestructive tools require human-confirm via elicitation.
EU AI ActArt. 26 — Deployer obligationsPersona-version stamping ((FR pending)).
Vietnam PDPLArt. 14 — DSARPer-subject mcp.invocation export.
GDPRArt. 25 — Privacy by designAudience-bound tokens; confused-deputy mitigation.
GDPRArt. 32 — Security of processingOAuth 2.1 PKCE only; mTLS to backends.
OWASP Gen AI Top-10LLM02: Insecure output handlingElicitation content-safety filter.
OWASP Gen AI Top-10LLM07: Insecure plugin designTool annotations + RBAC gate; closed catalogue.
OWASP Gen AI Top-10LLM08: Excessive agencyAudience-bound token + persona scope; can't escalate.
RFC 9728OAuth 2.0 Protected Resource MetadataPRM at /.well-known/oauth-protected-resource.
RFC 7636PKCEPKCE-only — implicit grant disabled.
SOC 2 Type IICC6.7 — Restriction of system accessTool registry as closed catalogue; new tool registration requires CTO approval.
12

Risk entries

IDRiskLikelihoodImpactOwnerMitigation
R-MCP-001Spec drift — agent client expects newer features than gateway providesMediumMediumCTOQuarterly spec sync; CI gates on conformance suite; capability negotiation surfaces gaps.
R-MCP-002Tool-name squatting — module registers a tool name belonging to anotherLowHighCTOServer_id is part of registry key; cross-module names rejected at register ((FR pending)).
R-MCP-003Confused-deputy attack — token from one audience used against another moduleMediumHighCSOAudience claim mandatory + verified at backend; mTLS pins to right service.
R-MCP-004Destructive tool annotation bypass via newly-added toolMediumHighCSORegistration requires CTO + CSO approval; default annotation is destructive=true.
R-MCP-005Tasks primitive leak — task_id reused across tenantsLowHighCTOtask_id is UUIDv7 + tenant_id in lookup; cross-tenant query property-tested.
R-MCP-006Elicitation injection — backend prompts user into harmful actionMediumHighCSOContent-safety filter; allow-list of elicitation prompts per tool; CHAT log of all elicitations.
R-MCP-007Backend slow → caller times out → orphaned audit rowMediumLowCTOPer-tool timeout enforced; audit row written on cancellation; reconciliation job catches orphans.
R-MCP-008OAuth registration scaling — every agent client must registerLowLowCTODynamic Client Registration (DCR) per RFC 7591; tenant admin approves before activation.
R-MCP-009Tool catalogue cache staleness after backend deployMediumLowCTO60 s TTL + register-time invalidation; deploys trigger cache reset.
R-MCP-010Sampling-with-Tools amplification (LLM-driven loop)MediumMediumCSO(FR pending): per-session sampling rate limit; circuit-breaker on recursion depth.
R-MCP-011External agent token theft (Member's laptop compromised → Claude Code token grants full CyberOS access)MediumCriticalCSOShort-lived tokens (1 h default); refresh-token rotation; device-binding via DPoP (P2+); destructive-op confirmation gating even with valid token; emergency revoke endpoint pages CSO instantly.
R-MCP-012Prompt injection in tool description (agent reads description, follows attacker instruction)MediumHighCSOTool descriptions are protocol-trusted by gateway, untrusted by agents; CyberOS modules go through CSO review before publishing tool descriptions; agent-side system prompts treat tool descriptions as data, not instructions.
R-MCP-013Elicitation fatigue — too many destructive confirms → user starts rubber-stampingHighMediumCPOBundle destructive ops where safe (batch delete with one confirm); show explicit consequence in elicitation prompt; rate-limit elicitations per session; never auto-decay to "approve all".
R-MCP-014Federation lag — module deploys new tool, agent calls old name, gets cryptic errorMediumLowCTO60 s cache TTL + list_changed push to subscribed clients; deprecation aliases (old name → new name) supported for 1 minor release; per-tool version field in tool catalogue.
R-MCP-015Task storm — agent starts 1000s of long-running tasks, exhausts capacityLowHighCTOPer-tenant per-agent task limit (default 50 concurrent); rate limit on tasks/create; auto-cancel tasks older than 24 h; alarm on task backlog > 100.
R-MCP-016Resource leak via subscribed list_changed notifications (agent disconnects, gateway keeps emitting)MediumLowCTOSubscription tied to session lifetime; ping/pong heartbeat 30 s; auto-unsubscribe on missed heartbeats.
R-MCP-017Per-module heartbeat false-positive — gateway marks healthy module as downLowMediumCTO3 consecutive heartbeat misses required (not 1); module health endpoint independent of MCP server itself; manual override via cyberos-mcp servers reactivate.
R-MCP-018OAuth Dynamic Client Registration (DCR) abuse — attacker registers many clientsMediumMediumCSOTenant admin approval gate before activation; rate limit on DCR endpoint (10/hour per tenant); flag suspicious registrations (unusual redirect URIs).
R-MCP-019Older 2024-11-05 client connects, falls back to SSE + bearer token, less secureMediumMediumCSOOlder clients explicitly opted in per tenant (deny by default); audit row flags "older protocol session"; sunset older protocol by P3 · exit (push all tenants to 2025-11-25).
R-MCP-020SEP-986 naming collision (two modules define delete_thing)LowMediumCTOThe cyberos.<module> prefix is namespace; cross-module same-noun is allowed; registration validator rejects exact duplicates within the same prefix.
13

KPIs

KPIFormulaSourceTarget
Conformance pass ratepassed / totalMCP conformance suite100%
Read-tool p95 latencyhistogramOBS≤ 500 ms
Write-tool p95 latencyhistogramOBS≤ 1 s
Gateway overhead p95histogramOBS≤ 5 ms
Audit completenessrows_in_brain / invocationschaos test100%
Destructive-without-confirmcount / 28 dmcp.invocation= 0
Tool-name violationscountregistry validator= 0
Active taskscount of status=runningtasks DBtracked; alert on backlog > 100
Backend healthhealthy / registered/admin/servers≥ 95% always
Persona-stamp coverageaudit rows with persona stamp / totalBRAIN audit replay= 1.0 (hard floor)
Elicitation acceptance rateuser-confirmed elicitations / total elicitationsmcp.invocation rowstracked; sudden drop = UI confusion alarm
Tasks completion ratecompleted / createdtasks DB≥ 95% (excluding user-cancelled)
Cross-tenant token-replay attemptscount / 28 dOAuth + audit cross-checktracked; spike = active attack
Older-protocol session rate2024-11-05 sessions / totalsession init logsdeclining trend; = 0 by P3 · exit
List_changed push latency p95histogram, module deploy → subscriber notifiedOBS≤ 30 s
Destructive-op confirm fatiguemedian elicitations per Member per daymcp.invocation rows≤ 5; alarm on > 15 (rubber-stamping signal)
External-client tools coveragedistinct external clients that successfully invoked ≥ 1 tool / total registeredsession logs≥ 0.90 (clients should not register and never call)
SEP-986 compliancetools matching naming pattern / totalregistry validator= 1.0 (CI gate at registration)
14

RACI matrix

ActivityCEOCTOCSOModule ownersCDO
Gateway design + implementationARCII
Per-module backend implementationICCA/RI
Tool annotations reviewICA/RRI
Spec conformanceIA/RCII
OAuth + audience designICA/RII
Audit pipeline maintenanceIRCIA
Tool catalog curationACCRC
15

Planned CLI surface

Operator CLI cyberos-mcp + ad-hoc mcp-inspector for development.

1. List registered backends

$ cyberos-mcp servers list

SERVER_ID STATUS VERSION TOOLS LAST_SEEN
cyberos.brain active 2.0.0 12 2026-05-14T07:21Z
cyberos.skill active 1.4.0 8 2026-05-14T07:21Z
cyberos.auth active 0.9.0 7 2026-05-14T07:20Z
cyberos.ai active 0.8.0 5 2026-05-14T07:21Z
cyberos.crm draining 0.3.0 11 2026-05-14T07:15Z

2. Inspect a tool

$ cyberos-mcp tool inspect cyberos.brain.delete_memory

name: cyberos.brain.delete_memory
server: cyberos.brain
description: "Delete a memory file (tombstone by default; purge requires DSAR reason)"
scope_required: brain.delete
annotations:
 destructive: true
 readOnly: false
 idempotent: false
 requiresConfirm: true
 openWorld: false
input_schema: {path: string, mode: "tombstone"|"purge", reason: string?}

3. Replay an invocation (dry-run, read-only)

$ cyberos-mcp invocations replay --id inv_01HZJ…XK --dry-run

[replay] invocation inv_01HZJ…XK
 tool: cyberos.brain.search_memory
 agent: Claude Desktop (claude-desktop-v1.0.45)
 args: {query: "Singapore HoldCo"}
 original_outcome: ok (12 hits)
 replay_outcome: ok (12 hits) — identical
[replay] read-only tool only · audit row NOT written

4. Cancel a stuck task

$ cyberos-mcp tasks cancel --id tsk_01HZJ…XK --reason "client disconnected"

[cancel] tsk_01HZJ…XK · status: running → cancelled
[backend] cyberos.kb signalled to abort
[audit] mcp.invocation updated · outcome=cancelled

5. Conformance test

$ cyberos-mcp conformance run

[conformance] MCP 2025-11-25 spec suite · 142 tests
 initialize ✓ (12 / 12)
 tools/list ✓ (18 / 18)
 tools/call ✓ (24 / 24)
 resources/* ✓ (16 / 16)
 prompts/* ✓ (14 / 14)
 completion/complete ✓ (8 / 8)
 tasks/* ✓ (12 / 12)
 elicitation/* ✓ (10 / 10)
 sampling/* ✓ (6 / 6)
 oauth (pkce) ✓ (14 / 14)
 prm ✓ (8 / 8)
[result] 142 / 142 PASSED · 0 failed · 0 skipped

6. Register a new backend (CTO + CSO approval gate)

$ cyberos-mcp servers register \
 --id cyberos.crm \
 --endpoint grpc:/crm.internal:8081 \
 --version 0.3.0 \
 --manifest crm-tools.json \
 --approval-jira CYB-1234

[validate] manifest: 11 tools · SEP-986 ✓ · annotations ✓
[approve] CTO ✓ CSO ✓ (per CYB-1234)
[register] cyberos.crm registered
[catalog] cache invalidated
[audit] brain seq=14856
16

Phase status & estimates

Status
Planned
P0 · design phase · P0 · slice 2
Est. LoC (Rust)
~5,500
services/mcp-gateway
Planned tests
142 conformance + 60 unit
MCP spec suite
P0 tools (est.)
~80
BRAIN · Skill · AUTH · AI
P3 tools (est.)
~300+
22 modules × ~15 verbs
CLI commands
~18 planned
cyberos-mcp
CapabilityStatus
Streamable HTTP transport (RFC 9112)planned · P0
OAuth 2.1 + PKCE edge handshakeplanned · P0
Well-known discovery + PRMplanned · P0
Tool registry (SEP-986 enforced)planned · P0
tools/list federationplanned · P0
tools/call gating (annotations + RBAC)planned · P0
Tasks primitiveplanned · P0
Elicitation back-channelplanned · P0
Idempotency-Key replay safetyplanned · P0
Per-tool rate limit + circuit breakerplanned · P0
mcp.invocation audit rowplanned · P0
Conformance suite (142 tests)planned · P0
Sampling-with-Tools rate limitingplanned · P1
Dynamic Client Registration (RFC 7591)planned · P1
Multi-region active-activeplanned · P3+
17

References

  • Bigger picture (§0 above): 3 strategic roles + federation Mermaid + auto-vs-human matrix.
  • External-client federation (§2.5 above): SEP-986 naming + module registration sequence + 6-row client compatibility matrix.
  • Capability broker (§2.6 above): 6-row tool-annotation gating + audience-bound OAuth JWT + destructive-op confirmation flow with Elicitation.
  • Tool-discovery surface (§2.7 above): 6 discovery endpoints + Tasks primitive 8-field schema + 5 pre-canned prompt templates.
  • Cross-module page links: auth.html · cuo.html · brain.html · skill.html · ai.html · obs.html · proj.html · chat.html
  • Build-readiness audit: archive/2026-05-14/AUDIT_AND_PLAN.md (archived; see cyberos/CHANGELOG.md) — MCP Gateway placed at P0 · slice 3 in the P0 sequence (after AI Gateway + AUTH stub).
  • Research review: archive/2026-05-14/RESEARCH_REVIEW.md (archived; see cyberos/CHANGELOG.md) — MCP Gateway rated "Strong" (9/10); reviewer flagged the elicitation-fatigue risk (R-MCP-013) and the older-protocol sunset as the two operational concerns.
  • BRAIN auto-sync vision: BRAIN_AUTOSYNC_DESIGN.md §5 — MCP tool invocations are one of four canonical capture surfaces for the local BRAIN (every tool call → audit row); §6 — Lumi exposes cross-tenant MCP federation at P3+ for org-tenant agents.
  • FR authoring discipline: modules/skill/feature-request-audit/AUTHORING_DISCIPLINE.md — MCP Gateway FRs land via the feature-request-author Agent Skill.
  • MCP Specification 2025-11-25modelcontextprotocol.io/specification/2025-11-25.
  • SEP-986 — verbNoun.dotted tool naming convention.
  • RFC 6749 / draft-ietf-oauth-v2-1 — OAuth 2.1.
  • RFC 7591 — Dynamic Client Registration.
  • RFC 7636 — Proof Key for Code Exchange (PKCE).
  • RFC 9112 — HTTP/1.1 (chunked transfer).
  • RFC 9728 — OAuth 2.0 Protected Resource Metadata.
  • DPoP (RFC 9449) — device-binding tokens at P2+.
  • EU AI Act — Art. 12 logging, Art. 13 transparency, Art. 14 human oversight, Art. 26 deployer obligations.
  • Vietnam PDPL (Law 91/2025): Art. 14 (DSAR via mcp.invocation export), Art. 20 (security obligations).
  • OWASP Gen AI Top-10 (2025) — LLM02, LLM07, LLM08 mitigations.
  • Architecture context: infrastructure.html#mcp.