|
| 1 | +# OAB MCP Facade (`search_capabilities` / `execute_capability`) |
| 2 | + |
| 3 | +The OAB MCP Facade is a loopback Streamable HTTP MCP server that exposes |
| 4 | +exactly **two agent-facing tools** — `search_capabilities` and |
| 5 | +`execute_capability` — backed by every MCP server configured in `mcp.json`. |
| 6 | +Any MCP-capable coding CLI on the host (Kiro CLI, Claude Code, Codex, …) |
| 7 | +connects to `http://127.0.0.1:<port>/mcp` and gets progressive discovery over |
| 8 | +the whole provider catalog instead of a flat list of every provider tool. |
| 9 | + |
| 10 | +Design: [OAB MCP Adapter ADR](adr/oab-mcp-adapter.md) (§6). |
| 11 | + |
| 12 | +## Architecture |
| 13 | + |
| 14 | +```mermaid |
| 15 | +flowchart LR |
| 16 | + subgraph host["Host / Pod (trust boundary)"] |
| 17 | + cli["Coding CLI<br/>(Kiro CLI / Claude Code / Codex / …)"] |
| 18 | +
|
| 19 | + subgraph facade["OAB MCP Facade — loopback :8848/mcp"] |
| 20 | + tools["search_capabilities<br/>execute_capability"] |
| 21 | + end |
| 22 | +
|
| 23 | + subgraph runtime["Shared MCP runtime (openab-mcp)"] |
| 24 | + policy["tool_filter (least-privilege)<br/>JSON-Schema arg validation<br/>timeouts · circuit breaker<br/>secret redaction · audit log"] |
| 25 | + end |
| 26 | +
|
| 27 | + adapter["gmail-native adapter<br/>loopback :8850/mcp"] |
| 28 | + end |
| 29 | +
|
| 30 | + gmail["gmail.googleapis.com<br/>(GA REST)"] |
| 31 | + obk["octobroker<br/>(fleet policy / org credentials)"] |
| 32 | + hosted["hosted MCP servers<br/>(Notion, …, OAuth)"] |
| 33 | +
|
| 34 | + cli -- "MCP (Streamable HTTP)" --> tools |
| 35 | + tools --> policy |
| 36 | + policy -- "native tools/call" --> adapter |
| 37 | + policy -- "native tools/call" --> obk |
| 38 | + policy -- "native tools/call" --> hosted |
| 39 | + adapter -- "bearer (auth.json,<br/>offline refresh)" --> gmail |
| 40 | +``` |
| 41 | + |
| 42 | +The agent always sees exactly two tools; providers configured in `mcp.json` |
| 43 | +are discovered through `search_capabilities` and invoked through |
| 44 | +`execute_capability`. Because the runtime dispatches **native** `tools/call` |
| 45 | +requests downstream, per-tool policy at any downstream (for example |
| 46 | +octobroker's default-deny allowlists) sees real tool names — the meta-tool |
| 47 | +envelope never blinds it. |
| 48 | + |
| 49 | +## Two ways to run it |
| 50 | + |
| 51 | +**In-process in the OAB broker** — presence of `[mcp]` in `config.toml` |
| 52 | +starts the listener: |
| 53 | + |
| 54 | +```toml |
| 55 | +[mcp] |
| 56 | +listen = "127.0.0.1:8848" # loopback only; non-loopback refused at startup |
| 57 | +``` |
| 58 | + |
| 59 | +**Facade-only run mode** (no chat adapter anywhere — coding-CLI-only |
| 60 | +hosts, dev loops, CI runners): an adapter-less config with `[mcp]` present |
| 61 | +is a valid deployment; `openab run` serves just the facade listener: |
| 62 | + |
| 63 | +```sh |
| 64 | +cat > facade-only.toml <<'TOML' |
| 65 | +[mcp] |
| 66 | +listen = "127.0.0.1:8848" |
| 67 | +TOML |
| 68 | +openab run -c facade-only.toml |
| 69 | +``` |
| 70 | + |
| 71 | +Both read the same layered provider config: `~/.openab/agent/mcp.json` |
| 72 | +(global) and `./.openab/agent/mcp.json` (project). No `[mcp]` section / no |
| 73 | +configured servers → no listener / an empty capability catalog. Provider |
| 74 | +connections stay in `mcp.json` — `[mcp]` carries listener settings only |
| 75 | +(single source of truth, ADR Alternative E). |
| 76 | + |
| 77 | +## The two tools |
| 78 | + |
| 79 | +1. `search_capabilities` (optional `query`) — discover authorized provider |
| 80 | + tools: name, description, input schema, provider, availability. Filtered |
| 81 | + by each server's `tool_filter` **before** anything reaches the agent. |
| 82 | +2. `execute_capability` (`name` + `arguments`) — execute an exact capability |
| 83 | + returned by discovery. Arguments are validated against the capability's |
| 84 | + JSON Schema before dispatch; timeouts, circuit breaking, and secret |
| 85 | + redaction apply on the same path the native agent uses. |
| 86 | + |
| 87 | +An audit line is logged for every dispatch (tool name + args SHA-256 — never |
| 88 | +plaintext arguments): |
| 89 | + |
| 90 | +``` |
| 91 | +mcp.audit: mcp call_tool entry server="gmail" tool="search_threads" args_sha256=… |
| 92 | +mcp.audit: mcp call_tool exit server="gmail" tool="search_threads" … outcome="ok" |
| 93 | +``` |
| 94 | + |
| 95 | +## Client registration examples |
| 96 | + |
| 97 | +Kiro CLI (`~/.kiro/settings/mcp.json`, or the agent file — see gotcha): |
| 98 | + |
| 99 | +```json |
| 100 | +{ "mcpServers": { "oab": { "url": "http://127.0.0.1:8848/mcp" } } } |
| 101 | +``` |
| 102 | + |
| 103 | +> **Kiro CLI gotcha:** when kiro runs with `--agent <name>` (as OAB bot |
| 104 | +> deployments do), the MCP server list comes from |
| 105 | +> `~/.kiro/agents/<name>.json` (`mcpServers` + `allowedTools`), **not** the |
| 106 | +> global settings file. Register there and allowlist the server |
| 107 | +> (e.g. `"@oab"`). |
| 108 | +
|
| 109 | +Claude Code: |
| 110 | + |
| 111 | +```sh |
| 112 | +claude mcp add --transport http oab http://127.0.0.1:8848/mcp |
| 113 | +``` |
| 114 | + |
| 115 | +## Trust model |
| 116 | + |
| 117 | +Loopback-only, **no authentication layer** — the host/pod boundary is the |
| 118 | +trust boundary. Any process on the host can invoke every authorized |
| 119 | +capability while the facade runs. Do not enable it on hosts that colocate |
| 120 | +untrusted processes. Least-privilege is enforced per provider with |
| 121 | +`tool_filter` include/exclude lists in `mcp.json`; excluded tools are |
| 122 | +invisible to discovery and rejected at execution. |
| 123 | + |
| 124 | +## Positioning vs octobroker (OBK) |
| 125 | + |
| 126 | +The facade is **pod-level**: one agent's own capability access, personal |
| 127 | +OAuth credentials, host trust boundary. Fleet-level concerns — per-agent |
| 128 | +identity/keys, default-deny policy across many agents, centrally minted |
| 129 | +short-lived organization credentials, fail-closed audit — belong to |
| 130 | +[octobroker](https://github.com/openabdev/octobroker). The two compose: the |
| 131 | +facade can list an octobroker endpoint as one of its `mcp.json` downstreams, |
| 132 | +and because the facade dispatches native `tools/call` requests, octobroker's |
| 133 | +per-tool policy sees real tool names. See ADR §4.1. |
| 134 | + |
| 135 | +## Providers |
| 136 | + |
| 137 | +Any Streamable HTTP or stdio MCP server configured in `mcp.json` works, |
| 138 | +including OAuth-protected hosted servers (login via |
| 139 | +`openab-agent mcp login <server>`). For Gmail on consumer accounts, use the |
| 140 | +[native Gmail adapter](gmail-native.md). |
0 commit comments