From 1f963c1b510778abf5a6ab906a5a828917445a1f Mon Sep 17 00:00:00 2001 From: chaodu-agent <274062505+chaodu-agent@users.noreply.github.com> Date: Fri, 24 Jul 2026 01:52:21 +0000 Subject: [PATCH 01/16] docs(adr): define OAB MCP adapter MVP --- docs/adr/oab-mcp-adapter.md | 502 ++++++++++++++++++++++++++++++++++++ 1 file changed, 502 insertions(+) create mode 100644 docs/adr/oab-mcp-adapter.md diff --git a/docs/adr/oab-mcp-adapter.md b/docs/adr/oab-mcp-adapter.md new file mode 100644 index 000000000..838380c23 --- /dev/null +++ b/docs/adr/oab-mcp-adapter.md @@ -0,0 +1,502 @@ +# ADR: OAB MCP Adapter MVP — Gmail and Notion + +- **Status:** Proposed +- **Date:** 2026-07-24 +- **Author:** chaodu-agent + +## 1. Context and Problem Statement + +OpenAB already has a native MCP client in `openab-agent`. It supports local stdio +servers and remote Streamable HTTP servers, OAuth, lazy connection, a single +LLM-facing `mcp` meta-tool, and configuration-driven activation. Those decisions +are recorded in [`openab-agent-mcp.md`](./openab-agent-mcp.md). + +What is missing is a small, explicit product and integration boundary for +first-party supported external services. Without that boundary, every service +becomes an ad-hoc `mcp.json` entry, authentication and tool-safety expectations +are unclear, and reviewers cannot distinguish an OAB adapter from a generic +third-party MCP server. + +This ADR defines **OAB MCP Adapter** as an outbound agent adapter. It connects an +OpenAB agent to configured external MCP servers and exposes their capabilities +through the existing native MCP client. The MVP supports: + +- **Notion** via Notion's hosted MCP server. +- **Gmail** via Google's hosted Gmail MCP server, currently a Developer Preview + and therefore explicitly opt-in and preview-labelled. + +This is not a proposal to add a second MCP client, an inbound OAB MCP server, or +native Gmail/Notion REST adapters. + +## 2. Goals and Non-Goals + +### Goals + +- Give OAB a named, documented **MCP adapter** comparable to other OAB + integrations, while keeping the transport implementation in `openab-agent`. +- Provide tested configuration profiles for Notion and Gmail over Streamable + HTTP. +- Preserve progressive disclosure: the LLM sees one `mcp` meta-tool and + discovers provider tools only when needed. +- Reuse the existing MCP OAuth, PKCE, credential storage, timeout, redaction, + circuit-breaker, and tool-filter mechanisms. +- Make least-privilege and write safety explicit: + - Notion read tools are the default MVP surface; page/database mutations are + explicit opt-in tools. + - Gmail search/read and draft creation are supported; direct send and delete + are not part of the MVP surface. +- Keep existing deployments unchanged when no MCP server is configured. + +### Non-goals + +- Implementing an OAB-hosted MCP server for external clients such as Codex or + Claude Code. +- Replacing OBK for GitHub, AWS, Discord, or other integrations already owned by + OBK. +- Implementing a native Gmail or Notion REST API adapter in OAB. +- Supporting legacy HTTP+SSE when the provider offers Streamable HTTP. +- Providing organization-wide credential management or a control plane. OAB's + configured MCP credentials remain agent-local and follow the existing + `openab-agent` persistence model. +- Automatically enabling Gmail's Developer Preview endpoint in existing or new + deployments without explicit configuration. + +## 3. At a Glance + +```text +┌──────────────────────────────────────────────────────────────────────────┐ +│ OpenAB │ +│ │ +│ Channel adapter (Discord / Slack / Gateway) │ +│ │ │ +│ ▼ │ +│ ACP host ── stdio JSON-RPC ──► openab-agent │ +│ │ │ +│ │ existing `mcp` meta-tool │ +│ ▼ │ +│ ┌─────────────────────┐ │ +│ │ OAB MCP Adapter │ │ +│ │ │ │ +│ │ config + OAuth │ │ +│ │ tool discovery │ │ +│ │ filtering + audit │ │ +│ └─────────┬──────────┘ │ +│ │ outbound MCP client │ +└───────────────────────────────────┼──────────────────────────────────────┘ + │ Streamable HTTP + OAuth + ┌──────────────────────┴────────────────────────┐ + ▼ ▼ +┌────────────────────────────┐ ┌────────────────────────────┐ +│ Notion hosted MCP │ │ Google Gmail hosted MCP │ +│ https://mcp.notion.com/mcp │ │ gmailmcp.googleapis.com/... │ +│ OAuth; provider permissions │ │ OAuth; Developer Preview │ +└────────────────────────────┘ └────────────────────────────┘ +``` + +The direction is intentional: the agent connects **out** to service MCP +servers. OAB does not expose an MCP endpoint in this MVP. + +## 4. Terminology and Positioning + +- **OAB MCP** is the user-facing feature name. +- **OAB MCP Adapter** is the architecture/component name. +- **MCP server instance** is one configured provider connection, such as + `notion` or `gmail`. +- **Provider tool** is a tool advertised by that remote MCP server. +- **`mcp` meta-tool** is the existing LLM-facing tool with actions such as + `list_servers`, `list_tools`, `describe_tool`, and `call`. + +MCP is an agent capability adapter, not a channel adapter and not an Ambient +activation mode. Ambient decides when an agent is prompted; MCP decides which +external capabilities the agent can use after it is prompted. + +## 5. Prior Art and Industry Research + +### 5.1 Existing OpenAB MCP client + +[`openab-agent-mcp.md`](./openab-agent-mcp.md) already establishes the relevant +foundation: + +- `openab-agent` is an MCP client, not an MCP server. +- `mcpServers` configuration is loaded from global and project + `.openab/agent/mcp.json` files. +- A configured server is the activation signal; an empty or missing config keeps + the MCP surface absent. +- Streamable HTTP and stdio are supported; the LLM receives one progressive + disclosure meta-tool rather than a flat tool list. +- OAuth uses PKCE and persisted credentials, with headless paste-back/device + flows where the provider supports them. + +This ADR adds service profiles and safety expectations; it does not re-specify +that client runtime. + +### 5.2 OpenWork + +OpenWork's Den provides useful prior art for the product boundary: + +- Its native Gmail capabilities use a Google OAuth account and Gmail REST API. +- Its external MCP path treats Notion and similar services as MCP clients, + discovers provider tools, and proxies calls with member-scoped credentials. +- Its agent-facing endpoint uses progressive discovery instead of exposing every + provider tool directly. + +OAB adopts the external MCP path for Notion. It does not copy OpenWork's Den +control plane or its native Gmail REST adapter; OAB remains a local/agent-side +adapter in this MVP. + +References: [OpenWork agent MCP](https://github.com/different-ai/openwork/blob/dev/ee/apps/den-api/src/mcp/agent.ts), +[OpenWork external capabilities](https://github.com/different-ai/openwork/blob/dev/ee/apps/den-api/src/mcp/external-capabilities.ts), +[OpenWork Google Workspace routes](https://github.com/different-ai/openwork/blob/dev/ee/apps/den-api/src/routes/org/google-workspace.ts). + +### 5.3 Notion hosted MCP + +Notion provides a first-party hosted MCP server at +`https://mcp.notion.com/mcp`, using Streamable HTTP and user OAuth. Its tools +are intentionally agent-oriented rather than a one-to-one dump of REST +endpoints. The documented surface includes search, fetch, page create/update, +comments, database queries, and async task status. + +Notion's official guidance also states that hosted MCP requires user-based OAuth +and does not support bearer-token authentication for headless service use. This +makes it a good MVP remote connector, but an operator must complete an +interactive login for each configured account. + +References: [Notion connection guide](https://developers.notion.com/guides/mcp/get-started-with-mcp), +[Notion supported tools](https://developers.notion.com/guides/mcp/mcp-supported-tools), +[Notion hosted MCP design](https://www.notion.com/blog/notions-hosted-mcp-server-an-inside-look). + +### 5.4 Gmail hosted MCP + +Google provides `https://gmailmcp.googleapis.com/mcp/v1` as a Gmail remote MCP +server. The official documentation currently labels it **Developer Preview**. +The documented setup enables Gmail API and Gmail MCP API, configures OAuth, and +requests `gmail.readonly` and `gmail.compose`. The documented tools include +thread/message search and retrieval, labels, and draft creation. + +Because the service is preview-only, Gmail support is an explicit opt-in profile +in this MVP. Direct sending and deletion are not exposed by the OAB profile. +A future native Gmail adapter remains possible if the hosted MCP contract is +not stable enough for production. + +Reference: [Google Gmail MCP setup](https://developers.google.com/workspace/gmail/api/guides/configure-mcp-server). + +### 5.5 OpenClaw and Hermes Agent + +The repository contribution guidelines require OpenClaw and Hermes Agent as +prior art for runtime integrations. + +- **OpenClaw** is primarily a multi-channel gateway. Its MCP work is useful for + configuration and channel-to-tool bridging, but it is not a direct model for + the native `openab-agent` client. OAB therefore keeps channel adapters and + the outbound MCP adapter as separate layers. +- **Hermes Agent** provides relevant MCP lifecycle patterns: per-server state, + OAuth handling, failure isolation, and circuit breaking. OAB already has + equivalent foundations in `openab-agent`; this MVP adds no second lifecycle + manager. + +References: [OpenClaw](https://github.com/openclaw/openclaw), +[Hermes Agent MCP implementation](https://github.com/NousResearch/hermes-agent). + +## 6. Proposed Solution + +### 6.1 Adapter boundary + +Add OAB MCP as a documented adapter profile on top of the existing +`McpRuntimeManager`: + +```text +McpRuntimeManager + └── McpAdapter instance per configured server + ├── notion → hosted MCP + OAuth + └── gmail → hosted MCP + OAuth (preview) +``` + +The adapter owns connection concerns only: + +- endpoint and transport selection; +- OAuth discovery, PKCE, login, refresh, and credential namespace; +- `tools/list` and tool-schema caching; +- configured include/exclude tool filters; +- timeout, cancellation, circuit breaker, and redacted errors; +- dispatch of exact provider tool names and arguments. + +Provider business logic remains at the provider MCP server. OAB must not +reimplement Notion or Gmail REST operations as part of this MVP. + +### 6.2 Configuration and activation + +Keep the existing `openab-agent` configuration contract rather than introducing +a duplicate top-level TOML section: + +- global: `~/.openab/agent/mcp.json`; +- project: `.openab/agent/mcp.json`; +- project entries override global entries with the same server name; +- no configured servers means no MCP meta-tool is injected; +- declaring a server is the explicit opt-in activation signal. + +Illustrative configuration: + +```json +{ + "mcpServers": { + "notion": { + "type": "http", + "url": "https://mcp.notion.com/mcp", + "oauth": { + "discovery": true, + "discovery_allowlist": ["*.notion.com"] + }, + "tool_filter": { + "include": [ + "notion-search", + "notion-fetch", + "notion-get-async-task" + ] + } + }, + "gmail": { + "type": "http", + "url": "https://gmailmcp.googleapis.com/mcp/v1", + "oauth": { + "discovery": true, + "discovery_allowlist": ["*.google.com", "*.googleapis.com"], + "scopes": [ + "https://www.googleapis.com/auth/gmail.readonly", + "https://www.googleapis.com/auth/gmail.compose" + ] + }, + "tool_filter": { + "include": [ + "search_threads", + "get_thread", + "get_message", + "create_draft" + ] + } + } + } +} +``` + +The exact OAuth client registration fields remain deployment/provider-specific. +They must not be committed with credentials. If a provider requires a +pre-registered client, operators use the existing `oauth.client_id`, +`oauth.client_secret`, and environment interpolation facilities. + +The profile examples are deliberately conservative. A deployment may add +provider tools after reviewing their schemas and side effects. + +### 6.3 Discovery and execution + +The existing meta-tool flow remains authoritative: + +```text +mcp(action="list_servers") + → notion (http, idle), gmail (http, needs login) + +mcp(action="list_tools", server="notion") + → provider tool names and descriptions + +mcp(action="describe_tool", server="notion", tool="notion-fetch") + → exact input schema + +mcp(action="call", server="notion", tool="notion-fetch", arguments={...}) + → provider CallToolResult +``` + +The LLM must use exact names and schemas returned by discovery. It must not +invent provider tools or arguments. An MCP `tools/list_changed` notification +invalidates the cache for that server. + +### 6.4 MVP capability profiles + +#### Notion + +- Stable hosted endpoint: `https://mcp.notion.com/mcp`. +- User OAuth; each configured account is authorized by a human. +- Default profile: search, fetch, and async-status read operations. +- Page/database/comment mutations require an explicit tool-filter change and + normal confirmation policy. +- File upload is out of scope because Notion's hosted MCP documentation does + not currently support it. + +#### Gmail + +- Hosted endpoint: `https://gmailmcp.googleapis.com/mcp/v1`. +- Developer Preview; disabled unless explicitly configured. +- OAuth scopes limited to `gmail.readonly` and `gmail.compose`. +- MVP profile: search/read threads and messages, plus create drafts. +- Direct send, permanent delete, settings changes, and unrestricted mailbox + mutation are out of scope. +- Draft results must be presented as drafts for user review; the adapter must + not claim that a message was sent. + +### 6.5 Credential and session model + +- HTTP MCP servers use the existing `openab-agent` OAuth manager and + namespaced credential store (`mcp:`). +- Refresh tokens remain on the agent's protected persistent filesystem and are + never sent through chat, inserted into prompts, or written to logs. +- The existing headless login flow is used for remote servers: device flow when + advertised, otherwise PKCE paste-back flow. +- A server is connected lazily on first discovery or call; one failing server + must not prevent the agent from starting or using another server. +- Existing per-server timeout, cancellation, idle eviction, and circuit breaker + behavior applies without an adapter-specific retry loop. + +### 6.6 Safety policy + +The adapter treats remote content as untrusted data: + +- Email bodies, Notion pages, comments, and search results must never be + interpreted as OAB system instructions. +- Read-only tools are preferred for the default profile. +- Mutation tools require explicit configuration and must preserve the provider's + own authorization checks. +- Gmail `create_draft` is the only write-like Gmail operation in the MVP; no + send capability is enabled. +- Tool arguments are validated against provider-declared schemas before call. +- Provider URLs and OAuth discovery are restricted to HTTPS and explicit + allowlists according to the existing MCP config validation. +- Stdio servers continue to use the existing environment scrubbing; the adapter + must not pass OAB channel tokens or unrelated secrets to child processes. +- Errors returned to the LLM and audit logs remain redacted. + +## 7. Why This Approach + +This approach uses the provider's maintained MCP contract while keeping OAB's +existing client/runtime small: + +- Notion already provides a production-oriented hosted MCP server and + agent-friendly tools; duplicating its REST API would create maintenance and + schema drift. +- Gmail's official server is available for an opt-in preview integration. The + profile makes its preview status and limited scopes visible instead of hiding + the risk behind a native adapter. +- Reusing the existing MCP client avoids a second OAuth store, transport stack, + meta-tool, or server lifecycle implementation. +- Tool filtering and progressive discovery prevent the model context from being + flooded with provider tools and create an explicit safety boundary. +- Existing deployments are unchanged: no `mcp.json` means no MCP runtime and no + new network calls. + +The trade-off is dependency on provider MCP availability, OAuth behavior, and +remote tool-schema stability. Those risks are acceptable for Notion and for an +explicitly preview-labelled Gmail profile; they are not acceptable grounds for +silently enabling either provider. + +## 8. Alternatives Considered + +### A. Add native Gmail and Notion REST adapters + +Rejected for this MVP. It duplicates provider API clients, OAuth scope mapping, +response normalization, and rate-limit behavior already implemented by the +providers. It remains a possible Gmail follow-up if Google's hosted MCP stays +preview-only or lacks required production controls. + +### B. Let each backing coding CLI configure Notion/Gmail directly + +Rejected as the OAB default. It produces different auth, tool filtering, +credential persistence, and diagnostics for each CLI. It can remain a manual +escape hatch for operators who intentionally configure a server outside OAB. + +### C. Add an inbound OAB MCP server + +Rejected as out of scope. This MVP is an outbound agent adapter. An inbound +server would let external coding clients call OAB workflows and requires a +separate authentication, tenancy, and authorization design. + +### D. Flatten all provider tools into the agent's top-level tool list + +Rejected. The existing `mcp` meta-tool and lazy discovery preserve the agent's +small prompt and isolate provider schema drift. This is already the accepted +OpenAB MCP client architecture. + +### E. Add a new top-level `[mcp]` TOML section + +Rejected for the MVP because `openab-agent` already owns and documents layered +`.openab/agent/mcp.json` configuration. A future broker-level configuration +facade may point to or generate that file, but it should not create a second +source of truth. + +## 9. Risks and Mitigations + +| Risk | Impact | Mitigation | +|---|---|---| +| Gmail hosted MCP is Developer Preview | Contract or availability changes | Explicit opt-in; preview label; limited tools/scopes; native adapter remains a follow-up | +| OAuth requires a human browser flow | Headless deployment cannot silently connect | Existing paste-back/device flows; actionable `mcp login` instructions; no false ready state | +| Provider tool/schema drift | Calls fail or model guesses stale arguments | Cache invalidation on `tools/list_changed`; exact-name/schema discovery; `mcp doctor` | +| Prompt injection in email/page content | Agent may perform unintended actions | Treat provider data as untrusted; least-privilege filters; no Gmail send/delete | +| Token leakage | Account compromise | PKCE, protected token store, env scrubbing, redacted logs, no credentials in prompts | +| Remote MCP outage/rate limit | Agent task failure or latency | Per-server timeout, circuit breaker, bounded retries, provider error surfaced accurately | +| Excessive provider tool context | Poor tool selection and token cost | Single meta-tool, lazy `list_tools`/`describe_tool`, include filters | +| Notion/Gmail account mismatch | Wrong mailbox/workspace action | Show server name and auth state; require explicit login per configured server; never infer identity from content | + +## 10. Rollout Plan + +1. **Documentation/profile slice:** land this ADR and checked-in configuration + examples; no behavior change for existing deployments. +2. **Notion MVP:** validate OAuth login, discovery, read tools, and one explicit + page mutation in a controlled test workspace. +3. **Gmail preview MVP:** validate Google OAuth, search/read, and draft creation + with a test mailbox; keep the profile opt-in and clearly preview-labelled. +4. **Operational hardening:** add provider-specific smoke checks and document + reconnect, rate-limit, and schema-drift remediation. +5. **Follow-up decision:** decide whether Gmail should remain hosted-MCP based on + preview stability or move to a native Gmail adapter. + +## 11. Validation + +### Documentation and configuration + +- Verify all relative ADR links resolve from `docs/adr/`. +- Parse the JSON examples and validate that profile fields match the existing + `openab-agent` MCP config schema. +- Confirm existing configuration with no `mcp.json` remains unchanged. + +### Automated checks + +- Unit-test config layering and server activation with zero, one, and two + servers. +- Unit-test include/exclude filters so Gmail send/delete-like tools cannot enter + the default profile. +- Unit-test OAuth URL/discovery allowlist validation and secret redaction. +- Mock Streamable HTTP `initialize`, `tools/list`, `tools/list_changed`, and + `tools/call` for both profiles. +- Test one provider failure does not prevent the other provider from connecting. + +### Manual integration checks + +- Notion: `mcp login notion`, list tools, search/fetch a test page, and verify a + mutation is blocked until explicitly enabled. +- Gmail: `mcp login gmail`, search a test mailbox, fetch a thread, create a draft, + and verify no send operation is exposed. +- Run `openab-agent mcp doctor` for each configured server. + +The implementation PR must run the repository validation commands required by +`AGENTS.md`: + +```bash +cargo fmt --check +cargo check +cargo clippy -- -D warnings +cargo test +``` + +For this docs-only ADR proposal, no code or Helm behavior changes are expected; +provider smoke tests are acceptance criteria for the follow-up implementation PR. + +## 12. Decision Summary + +Adopt **OAB MCP Adapter** as a first-class outbound agent adapter implemented on +top of the existing `openab-agent` MCP client. + +The MVP supports: + +- Notion hosted MCP with user OAuth and conservative read-first tooling. +- Gmail hosted MCP as an explicit, limited-scope Developer Preview integration + for search/read and draft creation. + +Configuration presence remains the opt-in signal. The MVP does not add an OAB +MCP server, a second MCP runtime, a native Gmail/Notion REST client, or a new +TOML source of truth. From 73d022ec6fa2f228b568d8bae3518e899605a3f5 Mon Sep 17 00:00:00 2001 From: chaodu-agent <274062505+chaodu-agent@users.noreply.github.com> Date: Fri, 24 Jul 2026 02:00:04 +0000 Subject: [PATCH 02/16] docs(adr): clarify OAB MCP facade boundary --- docs/adr/oab-mcp-adapter.md | 278 ++++++++++++++++++++++-------------- 1 file changed, 168 insertions(+), 110 deletions(-) diff --git a/docs/adr/oab-mcp-adapter.md b/docs/adr/oab-mcp-adapter.md index 838380c23..b2c9ba77c 100644 --- a/docs/adr/oab-mcp-adapter.md +++ b/docs/adr/oab-mcp-adapter.md @@ -7,9 +7,10 @@ ## 1. Context and Problem Statement OpenAB already has a native MCP client in `openab-agent`. It supports local stdio -servers and remote Streamable HTTP servers, OAuth, lazy connection, a single -LLM-facing `mcp` meta-tool, and configuration-driven activation. Those decisions -are recorded in [`openab-agent-mcp.md`](./openab-agent-mcp.md). +servers and remote Streamable HTTP servers, OAuth, lazy connection, a +progressive-disclosure `mcp` meta-tool for direct agent use, and +configuration-driven activation. Those decisions are recorded in +[`openab-agent-mcp.md`](./openab-agent-mcp.md). What is missing is a small, explicit product and integration boundary for first-party supported external services. Without that boundary, every service @@ -17,118 +18,133 @@ becomes an ad-hoc `mcp.json` entry, authentication and tool-safety expectations are unclear, and reviewers cannot distinguish an OAB adapter from a generic third-party MCP server. -This ADR defines **OAB MCP Adapter** as an outbound agent adapter. It connects an -OpenAB agent to configured external MCP servers and exposes their capabilities -through the existing native MCP client. The MVP supports: +This ADR defines **OAB MCP Adapter** as an outbound agent capability adapter behind an OAB-hosted MCP facade. The facade gives a coding agent one stable, OpenWork-style surface: + +- `search_capabilities` +- `execute_capability` + +OAB then discovers and invokes tools on configured external MCP servers. The MVP supports: - **Notion** via Notion's hosted MCP server. - **Gmail** via Google's hosted Gmail MCP server, currently a Developer Preview and therefore explicitly opt-in and preview-labelled. -This is not a proposal to add a second MCP client, an inbound OAB MCP server, or -native Gmail/Notion REST adapters. +This is not a proposal to add a second outbound MCP client. It adds the +agent-facing facade boundary while reusing the existing `openab-agent` MCP +runtime for downstream connections. It also does not add native Gmail/Notion +REST adapters. ## 2. Goals and Non-Goals ### Goals - Give OAB a named, documented **MCP adapter** comparable to other OAB - integrations, while keeping the transport implementation in `openab-agent`. + integrations, with a stable agent-facing MCP facade. +- Expose exactly two facade tools to the connected agent: + - `search_capabilities`: discover authorized capabilities from configured + external MCP servers. + - `execute_capability`: execute an exact capability returned by discovery. - Provide tested configuration profiles for Notion and Gmail over Streamable HTTP. -- Preserve progressive disclosure: the LLM sees one `mcp` meta-tool and - discovers provider tools only when needed. +- Preserve progressive disclosure: provider tools are not flattened into the + agent's top-level tool list. - Reuse the existing MCP OAuth, PKCE, credential storage, timeout, redaction, - circuit-breaker, and tool-filter mechanisms. + circuit-breaker, and tool-filter mechanisms for downstream connections. - Make least-privilege and write safety explicit: - Notion read tools are the default MVP surface; page/database mutations are explicit opt-in tools. - Gmail search/read and draft creation are supported; direct send and delete are not part of the MVP surface. -- Keep existing deployments unchanged when no MCP server is configured. +- Keep existing deployments unchanged when the MCP facade and no MCP adapters + are configured. ### Non-goals -- Implementing an OAB-hosted MCP server for external clients such as Codex or - Claude Code. +- Exposing every provider tool directly to the agent or copying provider-specific + MCP schemas into a second public tool surface. - Replacing OBK for GitHub, AWS, Discord, or other integrations already owned by OBK. - Implementing a native Gmail or Notion REST API adapter in OAB. - Supporting legacy HTTP+SSE when the provider offers Streamable HTTP. -- Providing organization-wide credential management or a control plane. OAB's - configured MCP credentials remain agent-local and follow the existing - `openab-agent` persistence model. +- Providing organization-wide credential management or a multi-tenant control + plane. This MVP assumes a configured OAB instance and its existing auth + boundary. - Automatically enabling Gmail's Developer Preview endpoint in existing or new deployments without explicit configuration. ## 3. At a Glance ```text -┌──────────────────────────────────────────────────────────────────────────┐ -│ OpenAB │ -│ │ -│ Channel adapter (Discord / Slack / Gateway) │ -│ │ │ -│ ▼ │ -│ ACP host ── stdio JSON-RPC ──► openab-agent │ -│ │ │ -│ │ existing `mcp` meta-tool │ -│ ▼ │ -│ ┌─────────────────────┐ │ -│ │ OAB MCP Adapter │ │ -│ │ │ │ -│ │ config + OAuth │ │ -│ │ tool discovery │ │ -│ │ filtering + audit │ │ -│ └─────────┬──────────┘ │ -│ │ outbound MCP client │ -└───────────────────────────────────┼──────────────────────────────────────┘ - │ Streamable HTTP + OAuth - ┌──────────────────────┴────────────────────────┐ - ▼ ▼ -┌────────────────────────────┐ ┌────────────────────────────┐ -│ Notion hosted MCP │ │ Google Gmail hosted MCP │ -│ https://mcp.notion.com/mcp │ │ gmailmcp.googleapis.com/... │ -│ OAuth; provider permissions │ │ OAuth; Developer Preview │ -└────────────────────────────┘ └────────────────────────────┘ +┌────────────────────────────────────────────────────────────────────────────┐ +│ Coding CLI / Agent │ +│ MCP client │ +└────────────────────────────────┬───────────────────────────────────────────┘ + │ Streamable HTTP MCP (local or remote) + ▼ +┌────────────────────────────────────────────────────────────────────────────┐ +│ OAB MCP Facade │ +│ search_capabilities(query) │ +│ execute_capability(name, arguments) │ +│ │ +│ auth + policy + capability registry │ +└────────────────────────────────┬───────────────────────────────────────────┘ + │ internal dispatch + ▼ +┌────────────────────────────────────────────────────────────────────────────┐ +│ OAB MCP Adapter │ +│ outbound MCP client · OAuth · tools/list · tools/call · filtering │ +└────────────────────────────────┬───────────────────────────────────────────┘ + │ Streamable HTTP MCP + provider OAuth + ┌───────────────┴────────────────┐ + ▼ ▼ +┌──────────────────────────────┐ ┌─────────────────────────────────────────┐ +│ Notion hosted MCP │ │ Google Gmail hosted MCP │ +│ https://mcp.notion.com/mcp │ │ https://gmailmcp.googleapis.com/mcp/v1 │ +│ user OAuth │ │ user OAuth · Developer Preview │ +└──────────────────────────────┘ └─────────────────────────────────────────┘ ``` -The direction is intentional: the agent connects **out** to service MCP -servers. OAB does not expose an MCP endpoint in this MVP. +The direction is intentional: the agent calls OAB, and OAB calls external +MCP servers. The facade never exposes provider credentials or asks the agent to +construct provider-specific tool calls directly. ## 4. Terminology and Positioning - **OAB MCP** is the user-facing feature name. -- **OAB MCP Adapter** is the architecture/component name. +- **OAB MCP Facade** is the inbound, agent-facing MCP server surface. +- **OAB MCP Adapter** is the outbound component that connects OAB to one or + more external MCP servers. - **MCP server instance** is one configured provider connection, such as `notion` or `gmail`. -- **Provider tool** is a tool advertised by that remote MCP server. -- **`mcp` meta-tool** is the existing LLM-facing tool with actions such as - `list_servers`, `list_tools`, `describe_tool`, and `call`. +- **Capability** is the OAB-facing, searchable representation of an authorized + provider tool. +- **`search_capabilities`** and **`execute_capability`** are the only facade + methods exposed to the connected agent in the MVP. MCP is an agent capability adapter, not a channel adapter and not an Ambient -activation mode. Ambient decides when an agent is prompted; MCP decides which -external capabilities the agent can use after it is prompted. +activation mode. Ambient decides when an agent is prompted; the OAB MCP facade +and adapter decide how that agent reaches authorized external capabilities. ## 5. Prior Art and Industry Research ### 5.1 Existing OpenAB MCP client -[`openab-agent-mcp.md`](./openab-agent-mcp.md) already establishes the relevant -foundation: +[`openab-agent-mcp.md`](./openab-agent-mcp.md) establishes the downstream +runtime foundation: -- `openab-agent` is an MCP client, not an MCP server. +- `openab-agent` is an MCP client, not the agent-facing OAB MCP server. - `mcpServers` configuration is loaded from global and project `.openab/agent/mcp.json` files. - A configured server is the activation signal; an empty or missing config keeps - the MCP surface absent. -- Streamable HTTP and stdio are supported; the LLM receives one progressive - disclosure meta-tool rather than a flat tool list. + the downstream MCP surface absent. +- Streamable HTTP and stdio are supported, with lazy connection and progressive + disclosure rather than a flat provider tool list. - OAuth uses PKCE and persisted credentials, with headless paste-back/device flows where the provider supports them. -This ADR adds service profiles and safety expectations; it does not re-specify -that client runtime. +The OAB MCP facade is the stable inbound boundary for a coding agent. It may use +this existing client/runtime internally for provider discovery and execution; +this ADR does not create a second transport or credential implementation. ### 5.2 OpenWork @@ -138,11 +154,12 @@ OpenWork's Den provides useful prior art for the product boundary: - Its external MCP path treats Notion and similar services as MCP clients, discovers provider tools, and proxies calls with member-scoped credentials. - Its agent-facing endpoint uses progressive discovery instead of exposing every - provider tool directly. + provider tool directly, matching the two-method OAB facade proposed here. -OAB adopts the external MCP path for Notion. It does not copy OpenWork's Den -control plane or its native Gmail REST adapter; OAB remains a local/agent-side -adapter in this MVP. +OAB adopts the external MCP path for Notion and the agent-facing progressive +facade pattern. It does not copy OpenWork's Den control plane or its native +Gmail REST adapter; OAB keeps authorization and provider connectivity within +its configured facade/adapter boundary. References: [OpenWork agent MCP](https://github.com/different-ai/openwork/blob/dev/ee/apps/den-api/src/mcp/agent.ts), [OpenWork external capabilities](https://github.com/different-ai/openwork/blob/dev/ee/apps/den-api/src/mcp/external-capabilities.ts), @@ -199,18 +216,31 @@ References: [OpenClaw](https://github.com/openclaw/openclaw), ## 6. Proposed Solution -### 6.1 Adapter boundary +### 6.1 Facade and adapter boundary -Add OAB MCP as a documented adapter profile on top of the existing -`McpRuntimeManager`: +The OAB MCP facade is the inbound MCP server exposed to the coding agent. It +owns the stable public contract and delegates provider work to the outbound +adapter runtime: ```text -McpRuntimeManager - └── McpAdapter instance per configured server - ├── notion → hosted MCP + OAuth - └── gmail → hosted MCP + OAuth (preview) +Agent / Coding CLI (MCP client) + └── OAB MCP Facade (MCP server) + ├── search_capabilities(query) + └── execute_capability(name, arguments) + └── OAB MCP Adapter / McpRuntimeManager (MCP client) + ├── notion → hosted MCP + OAuth + └── gmail → hosted MCP + OAuth (preview) ``` +The facade owns: + +- agent authentication and request authorization; +- capability search over the configured, policy-filtered catalog; +- stable capability names, schemas, availability, risk metadata, and provider + identity; +- validation that execution uses an exact capability returned by discovery; +- redacted results, errors, and audit records. + The adapter owns connection concerns only: - endpoint and transport selection; @@ -231,9 +261,14 @@ a duplicate top-level TOML section: - global: `~/.openab/agent/mcp.json`; - project: `.openab/agent/mcp.json`; - project entries override global entries with the same server name; -- no configured servers means no MCP meta-tool is injected; +- no configured adapter servers means the facade has no provider capabilities; - declaring a server is the explicit opt-in activation signal. +The existing file remains the source of truth for downstream provider +connections. The facade is the agent-facing source of truth for the two-method +contract; it does not inject provider tools into the agent's top-level tool +list. + Illustrative configuration: ```json @@ -286,27 +321,40 @@ pre-registered client, operators use the existing `oauth.client_id`, The profile examples are deliberately conservative. A deployment may add provider tools after reviewing their schemas and side effects. -### 6.3 Discovery and execution +### 6.3 Capability discovery and execution -The existing meta-tool flow remains authoritative: +The facade exposes only two stable methods. Provider-specific tools remain +behind the adapter and are represented as searchable capabilities: ```text -mcp(action="list_servers") - → notion (http, idle), gmail (http, needs login) - -mcp(action="list_tools", server="notion") - → provider tool names and descriptions - -mcp(action="describe_tool", server="notion", tool="notion-fetch") - → exact input schema +search_capabilities({"query":"find recent project notes"}) + → { + "capabilities": [{ + "name": "notion-search", + "description": "Search authorized Notion content", + "input_schema": {"...": "provider-declared JSON Schema"}, + "provider": "notion", + "risk": "read", + "availability": "ready" + }] + } -mcp(action="call", server="notion", tool="notion-fetch", arguments={...}) - → provider CallToolResult +execute_capability({ + "name": "notion-search", + "arguments": {"query":"project notes"} +}) + → provider CallToolResult (redacted and policy-checked) ``` -The LLM must use exact names and schemas returned by discovery. It must not -invent provider tools or arguments. An MCP `tools/list_changed` notification -invalidates the cache for that server. +`search_capabilities` returns only configured, authorized, policy-allowed +capabilities and their provider-declared schemas. `execute_capability` accepts +only an exact capability name and schema returned by discovery; it validates +arguments before dispatching the corresponding downstream `tools/call`. + +A downstream MCP `tools/list_changed` notification invalidates the relevant +capability cache. The facade must then refresh discovery before accepting a +call whose schema or availability may have changed. Provider names and raw +provider credentials are never required in the agent-facing contract. ### 6.4 MVP capability profiles @@ -335,12 +383,12 @@ invalidates the cache for that server. - HTTP MCP servers use the existing `openab-agent` OAuth manager and namespaced credential store (`mcp:`). -- Refresh tokens remain on the agent's protected persistent filesystem and are - never sent through chat, inserted into prompts, or written to logs. +- Refresh tokens remain on OAB's protected persistent filesystem and are never + sent through chat, inserted into prompts, or written to logs. - The existing headless login flow is used for remote servers: device flow when advertised, otherwise PKCE paste-back flow. -- A server is connected lazily on first discovery or call; one failing server - must not prevent the agent from starting or using another server. +- A server is connected lazily on first discovery or execution; one failing + server must not prevent the facade from starting or using another server. - Existing per-server timeout, cancellation, idle eviction, and circuit breaker behavior applies without an adapter-specific retry loop. @@ -360,7 +408,8 @@ The adapter treats remote content as untrusted data: allowlists according to the existing MCP config validation. - Stdio servers continue to use the existing environment scrubbing; the adapter must not pass OAB channel tokens or unrelated secrets to child processes. -- Errors returned to the LLM and audit logs remain redacted. +- Errors returned through the facade and written to audit logs remain redacted; + downstream provider details are not treated as agent instructions. ## 7. Why This Approach @@ -373,10 +422,11 @@ existing client/runtime small: - Gmail's official server is available for an opt-in preview integration. The profile makes its preview status and limited scopes visible instead of hiding the risk behind a native adapter. -- Reusing the existing MCP client avoids a second OAuth store, transport stack, - meta-tool, or server lifecycle implementation. -- Tool filtering and progressive discovery prevent the model context from being - flooded with provider tools and create an explicit safety boundary. +- Reusing the existing MCP client avoids a second outbound OAuth store, + transport stack, or server lifecycle implementation. +- The two-method facade, tool filtering, and progressive discovery prevent the + model context from being flooded with provider tools and create an explicit + safety boundary. - Existing deployments are unchanged: no `mcp.json` means no MCP runtime and no new network calls. @@ -400,17 +450,19 @@ Rejected as the OAB default. It produces different auth, tool filtering, credential persistence, and diagnostics for each CLI. It can remain a manual escape hatch for operators who intentionally configure a server outside OAB. -### C. Add an inbound OAB MCP server +### C. Add a second generic inbound MCP server -Rejected as out of scope. This MVP is an outbound agent adapter. An inbound -server would let external coding clients call OAB workflows and requires a -separate authentication, tenancy, and authorization design. +Rejected as unnecessary for this MVP. The OAB MCP facade is the intentionally +scoped inbound server for the coding agent. A separate generic server for +arbitrary OAB workflows would require another authentication, tenancy, and +authorization design and would blur the two-method capability boundary. ### D. Flatten all provider tools into the agent's top-level tool list -Rejected. The existing `mcp` meta-tool and lazy discovery preserve the agent's -small prompt and isolate provider schema drift. This is already the accepted -OpenAB MCP client architecture. +Rejected. The facade exposes only `search_capabilities` and +`execute_capability`; lazy discovery preserves the agent's small prompt and +isolates provider schema drift. This follows the accepted progressive-disclosure +pattern rather than flattening downstream tools. ### E. Add a new top-level `[mcp]` TOML section @@ -429,7 +481,7 @@ source of truth. | Prompt injection in email/page content | Agent may perform unintended actions | Treat provider data as untrusted; least-privilege filters; no Gmail send/delete | | Token leakage | Account compromise | PKCE, protected token store, env scrubbing, redacted logs, no credentials in prompts | | Remote MCP outage/rate limit | Agent task failure or latency | Per-server timeout, circuit breaker, bounded retries, provider error surfaced accurately | -| Excessive provider tool context | Poor tool selection and token cost | Single meta-tool, lazy `list_tools`/`describe_tool`, include filters | +| Excessive provider tool context | Poor tool selection and token cost | Two-method facade, lazy capability search, and include filters | | Notion/Gmail account mismatch | Wrong mailbox/workspace action | Show server name and auth state; require explicit login per configured server; never infer identity from content | ## 10. Rollout Plan @@ -488,8 +540,15 @@ provider smoke tests are acceptance criteria for the follow-up implementation PR ## 12. Decision Summary -Adopt **OAB MCP Adapter** as a first-class outbound agent adapter implemented on -top of the existing `openab-agent` MCP client. +Adopt **OAB MCP Adapter** behind an agent-facing **OAB MCP Facade**. The +facade exposes exactly two stable methods: + +- `search_capabilities` for authorized, policy-filtered provider discovery. +- `execute_capability` for schema-validated execution of an exact discovered + capability. + +The adapter uses the existing `openab-agent` MCP client/runtime to connect to +external providers. The MVP supports: @@ -497,6 +556,5 @@ The MVP supports: - Gmail hosted MCP as an explicit, limited-scope Developer Preview integration for search/read and draft creation. -Configuration presence remains the opt-in signal. The MVP does not add an OAB -MCP server, a second MCP runtime, a native Gmail/Notion REST client, or a new -TOML source of truth. +Configuration presence remains the opt-in signal. The MVP does not add a second +MCP runtime, a native Gmail/Notion REST client, or a new TOML source of truth. From 2ae3a03aeebc0006fada580cd2d586b602857649 Mon Sep 17 00:00:00 2001 From: chaodu-agent <274062505+chaodu-agent@users.noreply.github.com> Date: Fri, 24 Jul 2026 02:01:59 +0000 Subject: [PATCH 03/16] docs(adr): use ASCII architecture diagrams --- docs/adr/oab-mcp-adapter.md | 72 ++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/docs/adr/oab-mcp-adapter.md b/docs/adr/oab-mcp-adapter.md index b2c9ba77c..be81698c6 100644 --- a/docs/adr/oab-mcp-adapter.md +++ b/docs/adr/oab-mcp-adapter.md @@ -1,4 +1,4 @@ -# ADR: OAB MCP Adapter MVP — Gmail and Notion +# ADR: OAB MCP Adapter MVP - Gmail and Notion - **Status:** Proposed - **Date:** 2026-07-24 @@ -75,33 +75,33 @@ REST adapters. ## 3. At a Glance ```text -┌────────────────────────────────────────────────────────────────────────────┐ -│ Coding CLI / Agent │ -│ MCP client │ -└────────────────────────────────┬───────────────────────────────────────────┘ - │ Streamable HTTP MCP (local or remote) - ▼ -┌────────────────────────────────────────────────────────────────────────────┐ -│ OAB MCP Facade │ -│ search_capabilities(query) │ -│ execute_capability(name, arguments) │ -│ │ -│ auth + policy + capability registry │ -└────────────────────────────────┬───────────────────────────────────────────┘ - │ internal dispatch - ▼ -┌────────────────────────────────────────────────────────────────────────────┐ -│ OAB MCP Adapter │ -│ outbound MCP client · OAuth · tools/list · tools/call · filtering │ -└────────────────────────────────┬───────────────────────────────────────────┘ - │ Streamable HTTP MCP + provider OAuth - ┌───────────────┴────────────────┐ - ▼ ▼ -┌──────────────────────────────┐ ┌─────────────────────────────────────────┐ -│ Notion hosted MCP │ │ Google Gmail hosted MCP │ -│ https://mcp.notion.com/mcp │ │ https://gmailmcp.googleapis.com/mcp/v1 │ -│ user OAuth │ │ user OAuth · Developer Preview │ -└──────────────────────────────┘ └─────────────────────────────────────────┘ ++----------------------------------------------------------------------------+ +| Coding CLI / Agent | +| MCP client | ++--------------------------------+-------------------------------------------+ + | Streamable HTTP MCP (local or remote) + v ++----------------------------------------------------------------------------+ +| OAB MCP Facade | +| search_capabilities(query) | +| execute_capability(name, arguments) | +| | +| auth + policy + capability registry | ++--------------------------------+-------------------------------------------+ + | internal dispatch + v ++----------------------------------------------------------------------------+ +| OAB MCP Adapter | +| outbound MCP client - OAuth - tools/list - tools/call - filtering | ++--------------------------------+-------------------------------------------+ + | Streamable HTTP MCP + provider OAuth + +---------------+----------------+ + v v ++------------------------------+ +-----------------------------------------+ +| Notion hosted MCP | | Google Gmail hosted MCP | +| https://mcp.notion.com/mcp | | https://gmailmcp.googleapis.com/mcp/v1 | +| user OAuth | | user OAuth - Developer Preview | ++------------------------------+ +-----------------------------------------+ ``` The direction is intentional: the agent calls OAB, and OAB calls external @@ -224,12 +224,12 @@ adapter runtime: ```text Agent / Coding CLI (MCP client) - └── OAB MCP Facade (MCP server) - ├── search_capabilities(query) - └── execute_capability(name, arguments) - └── OAB MCP Adapter / McpRuntimeManager (MCP client) - ├── notion → hosted MCP + OAuth - └── gmail → hosted MCP + OAuth (preview) + +-- OAB MCP Facade (MCP server) + +-- search_capabilities(query) + +-- execute_capability(name, arguments) + +-- OAB MCP Adapter / McpRuntimeManager (MCP client) + +-- notion -> hosted MCP + OAuth + +-- gmail -> hosted MCP + OAuth (preview) ``` The facade owns: @@ -328,7 +328,7 @@ behind the adapter and are represented as searchable capabilities: ```text search_capabilities({"query":"find recent project notes"}) - → { + -> { "capabilities": [{ "name": "notion-search", "description": "Search authorized Notion content", @@ -343,7 +343,7 @@ execute_capability({ "name": "notion-search", "arguments": {"query":"project notes"} }) - → provider CallToolResult (redacted and policy-checked) + -> provider CallToolResult (redacted and policy-checked) ``` `search_capabilities` returns only configured, authorized, policy-allowed From 08dce6b12ba84092cc74aa3101996af44be5ac4b Mon Sep 17 00:00:00 2001 From: chaodu-agent <274062505+chaodu-agent@users.noreply.github.com> Date: Fri, 24 Jul 2026 02:04:40 +0000 Subject: [PATCH 04/16] docs(adr): show MCP and plugin capability paths --- docs/adr/oab-mcp-adapter.md | 118 ++++++++++++++++++++---------------- 1 file changed, 66 insertions(+), 52 deletions(-) diff --git a/docs/adr/oab-mcp-adapter.md b/docs/adr/oab-mcp-adapter.md index be81698c6..8855d2711 100644 --- a/docs/adr/oab-mcp-adapter.md +++ b/docs/adr/oab-mcp-adapter.md @@ -44,8 +44,9 @@ REST adapters. - `search_capabilities`: discover authorized capabilities from configured external MCP servers. - `execute_capability`: execute an exact capability returned by discovery. -- Provide tested configuration profiles for Notion and Gmail over Streamable - HTTP. +- Provide an extension point for services without a hosted MCP server: a + capability plugin/native adapter can use a provider API or SDK while exposing + the same facade contract. Plugin implementations are outside this MVP. - Preserve progressive disclosure: provider tools are not flattened into the agent's top-level tool list. - Reuse the existing MCP OAuth, PKCE, credential storage, timeout, redaction, @@ -64,7 +65,7 @@ REST adapters. MCP schemas into a second public tool surface. - Replacing OBK for GitHub, AWS, Discord, or other integrations already owned by OBK. -- Implementing a native Gmail or Notion REST API adapter in OAB. +- Implementing a native Gmail or Notion REST/API adapter as part of this MVP. - Supporting legacy HTTP+SSE when the provider offers Streamable HTTP. - Providing organization-wide credential management or a multi-tenant control plane. This MVP assumes a configured OAB instance and its existing auth @@ -74,46 +75,42 @@ REST adapters. ## 3. At a Glance -```text -+----------------------------------------------------------------------------+ -| Coding CLI / Agent | -| MCP client | -+--------------------------------+-------------------------------------------+ - | Streamable HTTP MCP (local or remote) - v -+----------------------------------------------------------------------------+ -| OAB MCP Facade | -| search_capabilities(query) | -| execute_capability(name, arguments) | -| | -| auth + policy + capability registry | -+--------------------------------+-------------------------------------------+ - | internal dispatch - v -+----------------------------------------------------------------------------+ -| OAB MCP Adapter | -| outbound MCP client - OAuth - tools/list - tools/call - filtering | -+--------------------------------+-------------------------------------------+ - | Streamable HTTP MCP + provider OAuth - +---------------+----------------+ - v v -+------------------------------+ +-----------------------------------------+ -| Notion hosted MCP | | Google Gmail hosted MCP | -| https://mcp.notion.com/mcp | | https://gmailmcp.googleapis.com/mcp/v1 | -| user OAuth | | user OAuth - Developer Preview | -+------------------------------+ +-----------------------------------------+ +```mermaid +flowchart TD + A["Coding CLI / Agent
MCP client"] -->|MCP| F["OAB MCP Facade
search_capabilities
execute_capability"] + F --> D["Capability Dispatcher
auth - policy - catalog - audit"] + D --> M["Hosted MCP Adapter
outbound MCP client
OAuth - tools/list - tools/call"] + D --> P["Capability Plugin / Native Adapter
provider API or SDK"] + M --> N["Notion hosted MCP"] + M --> G["Gmail hosted MCP
Developer Preview"] + P --> X["Service without hosted MCP
provider API or SDK"] + + style P stroke-dasharray: 5 5 + style X stroke-dasharray: 5 5 ``` -The direction is intentional: the agent calls OAB, and OAB calls external -MCP servers. The facade never exposes provider credentials or asks the agent to -construct provider-specific tool calls directly. +The facade exposes the same two-method contract regardless of the downstream +path. Notion and Gmail use the hosted MCP adapter in this MVP. The dashed +capability-plugin path is the extension point for services that do not provide +a hosted MCP server: a provider API/SDK adapter can publish the same searchable +capabilities and execute them under the same OAB authorization, policy, schema, +and audit controls. It is not a second agent-facing API. + +The direction is intentional: the agent calls OAB, and OAB dispatches either to +an external MCP server or to a provider plugin. The facade never exposes +provider credentials or asks the agent to construct provider-specific calls +directly. ## 4. Terminology and Positioning - **OAB MCP** is the user-facing feature name. - **OAB MCP Facade** is the inbound, agent-facing MCP server surface. - **OAB MCP Adapter** is the outbound component that connects OAB to one or - more external MCP servers. + more hosted external MCP servers. +- **Capability Plugin / Native Adapter** is an OAB-side provider integration + that uses a provider API or SDK when no hosted MCP server is available. It + is an implementation path behind the same facade, not a new agent-facing + contract. - **MCP server instance** is one configured provider connection, such as `notion` or `gmail`. - **Capability** is the OAB-facing, searchable representation of an authorized @@ -219,17 +216,20 @@ References: [OpenClaw](https://github.com/openclaw/openclaw), ### 6.1 Facade and adapter boundary The OAB MCP facade is the inbound MCP server exposed to the coding agent. It -owns the stable public contract and delegates provider work to the outbound -adapter runtime: +owns the stable public contract and delegates provider work to a shared +capability dispatcher: ```text Agent / Coding CLI (MCP client) +-- OAB MCP Facade (MCP server) +-- search_capabilities(query) +-- execute_capability(name, arguments) - +-- OAB MCP Adapter / McpRuntimeManager (MCP client) - +-- notion -> hosted MCP + OAuth - +-- gmail -> hosted MCP + OAuth (preview) + +-- Capability Dispatcher + +-- Hosted MCP Adapter (MCP client) + | +-- notion -> hosted MCP + OAuth + | +-- gmail -> hosted MCP + OAuth (preview) + +-- Capability Plugin / Native Adapter + +-- provider API or SDK ``` The facade owns: @@ -241,7 +241,7 @@ The facade owns: - validation that execution uses an exact capability returned by discovery; - redacted results, errors, and audit records. -The adapter owns connection concerns only: +The hosted MCP adapter owns connection concerns only: - endpoint and transport selection; - OAuth discovery, PKCE, login, refresh, and credential namespace; @@ -250,8 +250,16 @@ The adapter owns connection concerns only: - timeout, cancellation, circuit breaker, and redacted errors; - dispatch of exact provider tool names and arguments. -Provider business logic remains at the provider MCP server. OAB must not -reimplement Notion or Gmail REST operations as part of this MVP. +A capability plugin/native adapter implements the same catalog and execution +interface using a provider API or SDK. It is the fallback path for services +without a hosted MCP server and must use the same OAB authorization, schema, +policy, confirmation, redaction, and audit controls. Plugin implementations are +not part of the Notion/Gmail hosted-MCP MVP unless separately enabled and +reviewed. + +Hosted MCP provider business logic remains at the provider MCP server. A future +plugin may contain a thin provider API/SDK translation layer, but the facade +must not expose provider-specific APIs directly to the agent. ### 6.2 Configuration and activation @@ -413,8 +421,8 @@ The adapter treats remote content as untrusted data: ## 7. Why This Approach -This approach uses the provider's maintained MCP contract while keeping OAB's -existing client/runtime small: +This approach keeps one small, stable agent-facing contract while allowing OAB +to support both provider-owned MCP and providers that expose only an API or SDK: - Notion already provides a production-oriented hosted MCP server and agent-friendly tools; duplicating its REST API would create maintenance and @@ -422,13 +430,17 @@ existing client/runtime small: - Gmail's official server is available for an opt-in preview integration. The profile makes its preview status and limited scopes visible instead of hiding the risk behind a native adapter. +- A capability plugin/native adapter provides a controlled fallback for a + service without hosted MCP, without changing the agent's discovery or + execution methods. The plugin path carries extra provider-client maintenance + and is explicitly not part of this MVP. - Reusing the existing MCP client avoids a second outbound OAuth store, transport stack, or server lifecycle implementation. -- The two-method facade, tool filtering, and progressive discovery prevent the - model context from being flooded with provider tools and create an explicit - safety boundary. -- Existing deployments are unchanged: no `mcp.json` means no MCP runtime and no - new network calls. +- The two-method facade, shared dispatcher, tool filtering, and progressive + discovery prevent the model context from being flooded with provider tools + and create an explicit safety boundary. +- Existing deployments are unchanged: no `mcp.json` means no hosted MCP runtime + and no new network calls. The trade-off is dependency on provider MCP availability, OAuth behavior, and remote tool-schema stability. Those risks are acceptable for Notion and for an @@ -547,8 +559,10 @@ facade exposes exactly two stable methods: - `execute_capability` for schema-validated execution of an exact discovered capability. -The adapter uses the existing `openab-agent` MCP client/runtime to connect to -external providers. +The adapter uses the existing `openab-agent` MCP client/runtime for hosted MCP +connections. A future capability plugin/native adapter may use a provider API or +SDK for services without hosted MCP, but it must implement the same catalog, +policy, and execution boundary rather than adding agent-facing provider APIs. The MVP supports: From 7b65cd36b8fba7d6a773a5e637c526c36ea7e8fb Mon Sep 17 00:00:00 2001 From: chaodu-agent <274062505+chaodu-agent@users.noreply.github.com> Date: Fri, 24 Jul 2026 02:07:57 +0000 Subject: [PATCH 05/16] docs(adr): clarify OpenWork capability vision --- docs/adr/oab-mcp-adapter.md | 55 +++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/docs/adr/oab-mcp-adapter.md b/docs/adr/oab-mcp-adapter.md index 8855d2711..4a21505e5 100644 --- a/docs/adr/oab-mcp-adapter.md +++ b/docs/adr/oab-mcp-adapter.md @@ -44,6 +44,9 @@ REST adapters. - `search_capabilities`: discover authorized capabilities from configured external MCP servers. - `execute_capability`: execute an exact capability returned by discovery. +- Define the OAB Agent capability-access vision inspired by OpenWork: authorized + services such as Gmail, Calendar, Drive, Slack, Notion, and Linear should be + reachable through one OAB facade as their provider paths mature. - Provide an extension point for services without a hosted MCP server: a capability plugin/native adapter can use a provider API or SDK while exposing the same facade contract. Plugin implementations are outside this MVP. @@ -143,24 +146,46 @@ The OAB MCP facade is the stable inbound boundary for a coding agent. It may use this existing client/runtime internally for provider discovery and execution; this ADR does not create a second transport or credential implementation. -### 5.2 OpenWork - -OpenWork's Den provides useful prior art for the product boundary: - -- Its native Gmail capabilities use a Google OAuth account and Gmail REST API. -- Its external MCP path treats Notion and similar services as MCP clients, - discovers provider tools, and proxies calls with member-scoped credentials. -- Its agent-facing endpoint uses progressive discovery instead of exposing every - provider tool directly, matching the two-method OAB facade proposed here. - -OAB adopts the external MCP path for Notion and the agent-facing progressive -facade pattern. It does not copy OpenWork's Den control plane or its native -Gmail REST adapter; OAB keeps authorization and provider connectivity within -its configured facade/adapter boundary. +### 5.2 OpenWork inspiration and OAB Agent capability vision + +OpenWork is the primary product inspiration for the agent-facing boundary. Its +Connect and MCP model demonstrates that an agent can access authorized external +service capabilities through one progressive-discovery surface rather than +requiring every backing coding CLI to define its own provider integration. + +The OpenWork capability set provides useful direction for OAB's longer-term +vision: + +- Its user-facing Connect services include Gmail, Google Calendar, Google Drive, + Slack, Notion, and Linear. +- Its hosted MCP connections include services such as Notion, Linear, Stripe, + Sentry, Exa, Context7, and Slack when the required OAuth app is configured. +- It also supports custom compatible local or remote MCP servers. +- Its native Gmail capability path shows the complementary case where a + provider is accessed through a first-party API/SDK adapter instead of a + hosted MCP server. +- Its agent-facing endpoint uses progressive discovery and member-scoped + authorization instead of exposing every provider tool directly. + +OAB adopts the product principle, not a promise of immediate provider parity: +**the OAB Agent should be able to access authorized external capabilities such +as these through the OAB MCP Facade**, regardless of whether the implementation +behind the facade is a hosted MCP adapter or a capability plugin/native adapter. +The stable agent contract remains `search_capabilities` and +`execute_capability`. + +The MVP deliberately starts with Notion and Gmail hosted MCP profiles. Calendar, +Drive, Slack, Linear, Stripe, Sentry, Exa, Context7, and other services are +roadmap candidates that can be added through the same facade and provider path +after their auth, safety, availability, and operational requirements are +reviewed. OAB does not copy OpenWork's Den control plane or claim those services +are implemented by this ADR. References: [OpenWork agent MCP](https://github.com/different-ai/openwork/blob/dev/ee/apps/den-api/src/mcp/agent.ts), [OpenWork external capabilities](https://github.com/different-ai/openwork/blob/dev/ee/apps/den-api/src/mcp/external-capabilities.ts), -[OpenWork Google Workspace routes](https://github.com/different-ai/openwork/blob/dev/ee/apps/den-api/src/routes/org/google-workspace.ts). +[OpenWork Google Workspace routes](https://github.com/different-ai/openwork/blob/dev/ee/apps/den-api/src/routes/org/google-workspace.ts), +[OpenWork Connect services](https://openworklabs.com/docs/start-here/connect-your-stack/connect-services), +[OpenWork shared MCP connections](https://openworklabs.com/docs/cloud/share-with-your-team/shared-mcp-connections). ### 5.3 Notion hosted MCP From adcc2cd65f8a35435c80bd3d6a18604c67e3d246 Mon Sep 17 00:00:00 2001 From: chaodu-agent <274062505+chaodu-agent@users.noreply.github.com> Date: Fri, 24 Jul 2026 02:09:29 +0000 Subject: [PATCH 06/16] docs(adr): show OAB pod boundary --- docs/adr/oab-mcp-adapter.md | 43 ++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/docs/adr/oab-mcp-adapter.md b/docs/adr/oab-mcp-adapter.md index 4a21505e5..cd0ac0fe8 100644 --- a/docs/adr/oab-mcp-adapter.md +++ b/docs/adr/oab-mcp-adapter.md @@ -80,29 +80,42 @@ REST adapters. ```mermaid flowchart TD - A["Coding CLI / Agent
MCP client"] -->|MCP| F["OAB MCP Facade
search_capabilities
execute_capability"] - F --> D["Capability Dispatcher
auth - policy - catalog - audit"] - D --> M["Hosted MCP Adapter
outbound MCP client
OAuth - tools/list - tools/call"] - D --> P["Capability Plugin / Native Adapter
provider API or SDK"] - M --> N["Notion hosted MCP"] - M --> G["Gmail hosted MCP
Developer Preview"] - P --> X["Service without hosted MCP
provider API or SDK"] + A["Coding CLI / Agent
MCP client"] + + subgraph POD["OAB Pod"] + F["OAB MCP Facade
search_capabilities
execute_capability"] + D["Capability Dispatcher
auth - policy - catalog - audit"] + M["Hosted MCP Adapter
outbound MCP client
OAuth - tools/list - tools/call"] + P["Capability Plugin / Native Adapter
provider API or SDK"] + + F --> D + D --> M + D --> P + end + + N["Notion hosted MCP
external provider"] + G["Gmail hosted MCP
external provider - Developer Preview"] + X["External service without hosted MCP
provider API or SDK"] + + A -->|MCP| F + M --> N + M --> G + P --> X style P stroke-dasharray: 5 5 style X stroke-dasharray: 5 5 ``` +The `OAB Pod` boundary contains the OAB-owned facade, dispatcher, hosted MCP +adapter, and capability-plugin runtime. The Coding CLI/Agent remains outside +the Pod and connects only to the facade. Notion, Gmail, and provider APIs also +remain outside the Pod; the outbound adapter or plugin crosses that boundary +under OAB policy and audit controls. + The facade exposes the same two-method contract regardless of the downstream path. Notion and Gmail use the hosted MCP adapter in this MVP. The dashed capability-plugin path is the extension point for services that do not provide -a hosted MCP server: a provider API/SDK adapter can publish the same searchable -capabilities and execute them under the same OAB authorization, policy, schema, -and audit controls. It is not a second agent-facing API. - -The direction is intentional: the agent calls OAB, and OAB dispatches either to -an external MCP server or to a provider plugin. The facade never exposes -provider credentials or asks the agent to construct provider-specific calls -directly. +a hosted MCP server. It is not a second agent-facing API. ## 4. Terminology and Positioning From 745c0264ff746cb7a62ccdcb5b45acc50c2624ec Mon Sep 17 00:00:00 2001 From: chaodu-agent <274062505+chaodu-agent@users.noreply.github.com> Date: Fri, 24 Jul 2026 02:11:06 +0000 Subject: [PATCH 07/16] docs(adr): make pod boundary explicit --- docs/adr/oab-mcp-adapter.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/adr/oab-mcp-adapter.md b/docs/adr/oab-mcp-adapter.md index cd0ac0fe8..28d86b9be 100644 --- a/docs/adr/oab-mcp-adapter.md +++ b/docs/adr/oab-mcp-adapter.md @@ -82,7 +82,7 @@ REST adapters. flowchart TD A["Coding CLI / Agent
MCP client"] - subgraph POD["OAB Pod"] + subgraph OAB_POD["OAB Pod - OAB-owned runtime"] F["OAB MCP Facade
search_capabilities
execute_capability"] D["Capability Dispatcher
auth - policy - catalog - audit"] M["Hosted MCP Adapter
outbound MCP client
OAuth - tools/list - tools/call"] @@ -102,6 +102,7 @@ flowchart TD M --> G P --> X + style OAB_POD fill:none,stroke:#9ca3af,stroke-width:2px style P stroke-dasharray: 5 5 style X stroke-dasharray: 5 5 ``` From 7b63db65ea89fd7f6182813055ecb8db8c2d8295 Mon Sep 17 00:00:00 2001 From: chaodu-agent <274062505+chaodu-agent@users.noreply.github.com> Date: Fri, 24 Jul 2026 02:11:55 +0000 Subject: [PATCH 08/16] docs(adr): improve pod diagram compatibility --- docs/adr/oab-mcp-adapter.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/adr/oab-mcp-adapter.md b/docs/adr/oab-mcp-adapter.md index 28d86b9be..b0bed405b 100644 --- a/docs/adr/oab-mcp-adapter.md +++ b/docs/adr/oab-mcp-adapter.md @@ -82,7 +82,7 @@ REST adapters. flowchart TD A["Coding CLI / Agent
MCP client"] - subgraph OAB_POD["OAB Pod - OAB-owned runtime"] + subgraph OAB_POD [OAB Pod - OAB-owned runtime] F["OAB MCP Facade
search_capabilities
execute_capability"] D["Capability Dispatcher
auth - policy - catalog - audit"] M["Hosted MCP Adapter
outbound MCP client
OAuth - tools/list - tools/call"] @@ -102,7 +102,7 @@ flowchart TD M --> G P --> X - style OAB_POD fill:none,stroke:#9ca3af,stroke-width:2px + style OAB_POD fill:#111827,stroke:#f59e0b,stroke-width:3px style P stroke-dasharray: 5 5 style X stroke-dasharray: 5 5 ``` From 232c5c2358ad7e8df44671fb79958a6a5d40717d Mon Sep 17 00:00:00 2001 From: chaodu-agent <274062505+chaodu-agent@users.noreply.github.com> Date: Fri, 24 Jul 2026 02:15:58 +0000 Subject: [PATCH 09/16] docs(adr): separate coding cli pod --- docs/adr/oab-mcp-adapter.md | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/docs/adr/oab-mcp-adapter.md b/docs/adr/oab-mcp-adapter.md index b0bed405b..2a1c1fab5 100644 --- a/docs/adr/oab-mcp-adapter.md +++ b/docs/adr/oab-mcp-adapter.md @@ -80,7 +80,9 @@ REST adapters. ```mermaid flowchart TD - A["Coding CLI / Agent
MCP client"] + subgraph AGENT_POD [Coding CLI Pod - agent runtime] + A["Coding CLI / Agent
MCP client"] + end subgraph OAB_POD [OAB Pod - OAB-owned runtime] F["OAB MCP Facade
search_capabilities
execute_capability"] @@ -102,16 +104,18 @@ flowchart TD M --> G P --> X + style AGENT_POD fill:#1f2937,stroke:#60a5fa,stroke-width:3px style OAB_POD fill:#111827,stroke:#f59e0b,stroke-width:3px style P stroke-dasharray: 5 5 style X stroke-dasharray: 5 5 ``` -The `OAB Pod` boundary contains the OAB-owned facade, dispatcher, hosted MCP -adapter, and capability-plugin runtime. The Coding CLI/Agent remains outside -the Pod and connects only to the facade. Notion, Gmail, and provider APIs also -remain outside the Pod; the outbound adapter or plugin crosses that boundary -under OAB policy and audit controls. +The deployment has two runtime Pods. The **Coding CLI Pod** contains the +Coding CLI/Agent MCP client. The **OAB Pod** contains the OAB-owned facade, +dispatcher, hosted MCP adapter, and capability-plugin runtime. The Pods connect +only over MCP. Notion, Gmail, and provider APIs remain outside both Pods; the +outbound adapter or plugin crosses that boundary under OAB policy and audit +controls. The facade exposes the same two-method contract regardless of the downstream path. Notion and Gmail use the hosted MCP adapter in this MVP. The dashed @@ -259,7 +263,11 @@ owns the stable public contract and delegates provider work to a shared capability dispatcher: ```text -Agent / Coding CLI (MCP client) +Coding CLI Pod + +-- Agent / Coding CLI (MCP client) + +-- MCP connection + +OAB Pod +-- OAB MCP Facade (MCP server) +-- search_capabilities(query) +-- execute_capability(name, arguments) From 16a59a07e0a9a1a59c25aa905d5b01e72149bbbd Mon Sep 17 00:00:00 2001 From: chaodu-agent <274062505+chaodu-agent@users.noreply.github.com> Date: Fri, 24 Jul 2026 02:18:54 +0000 Subject: [PATCH 10/16] docs(adr): nest runtime inside oab pod --- docs/adr/oab-mcp-adapter.md | 65 ++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/docs/adr/oab-mcp-adapter.md b/docs/adr/oab-mcp-adapter.md index 2a1c1fab5..49eae5ef8 100644 --- a/docs/adr/oab-mcp-adapter.md +++ b/docs/adr/oab-mcp-adapter.md @@ -80,42 +80,43 @@ REST adapters. ```mermaid flowchart TD - subgraph AGENT_POD [Coding CLI Pod - agent runtime] + subgraph OAB_POD [OAB Pod - deployment boundary] A["Coding CLI / Agent
MCP client"] - end - subgraph OAB_POD [OAB Pod - OAB-owned runtime] - F["OAB MCP Facade
search_capabilities
execute_capability"] - D["Capability Dispatcher
auth - policy - catalog - audit"] - M["Hosted MCP Adapter
outbound MCP client
OAuth - tools/list - tools/call"] - P["Capability Plugin / Native Adapter
provider API or SDK"] + subgraph OAB_RUNTIME [OAB-owned runtime] + F["OAB MCP Facade
search_capabilities
execute_capability"] + D["Capability Dispatcher
auth - policy - catalog - audit"] + M["Hosted MCP Adapter
outbound MCP client
OAuth - tools/list - tools/call"] + P["Capability Plugin / Native Adapter
provider API or SDK"] + + F --> D + D --> M + D --> P + end - F --> D - D --> M - D --> P + A -->|MCP| F end N["Notion hosted MCP
external provider"] G["Gmail hosted MCP
external provider - Developer Preview"] X["External service without hosted MCP
provider API or SDK"] - A -->|MCP| F M --> N M --> G P --> X - style AGENT_POD fill:#1f2937,stroke:#60a5fa,stroke-width:3px - style OAB_POD fill:#111827,stroke:#f59e0b,stroke-width:3px + style OAB_POD fill:#0b1220,stroke:#60a5fa,stroke-width:3px + style OAB_RUNTIME fill:#111827,stroke:#f59e0b,stroke-width:3px style P stroke-dasharray: 5 5 style X stroke-dasharray: 5 5 ``` -The deployment has two runtime Pods. The **Coding CLI Pod** contains the -Coding CLI/Agent MCP client. The **OAB Pod** contains the OAB-owned facade, -dispatcher, hosted MCP adapter, and capability-plugin runtime. The Pods connect -only over MCP. Notion, Gmail, and provider APIs remain outside both Pods; the -outbound adapter or plugin crosses that boundary under OAB policy and audit -controls. +The **OAB Pod** is the outer deployment boundary. It contains both the Coding +CLI/Agent MCP client and the inner **OAB-owned runtime** boundary. The inner +runtime contains the OAB MCP Facade, dispatcher, hosted MCP adapter, and +capability-plugin runtime. Notion, Gmail, and provider APIs remain outside the +OAB Pod; only the outbound adapter or plugin crosses that boundary under OAB +policy and audit controls. The facade exposes the same two-method contract regardless of the downstream path. Notion and Gmail use the hosted MCP adapter in this MVP. The dashed @@ -263,20 +264,18 @@ owns the stable public contract and delegates provider work to a shared capability dispatcher: ```text -Coding CLI Pod - +-- Agent / Coding CLI (MCP client) - +-- MCP connection - -OAB Pod - +-- OAB MCP Facade (MCP server) - +-- search_capabilities(query) - +-- execute_capability(name, arguments) - +-- Capability Dispatcher - +-- Hosted MCP Adapter (MCP client) - | +-- notion -> hosted MCP + OAuth - | +-- gmail -> hosted MCP + OAuth (preview) - +-- Capability Plugin / Native Adapter - +-- provider API or SDK +OAB Pod (outer deployment boundary) + +-- Coding CLI / Agent (MCP client) + +-- OAB-owned runtime (inner boundary) + +-- OAB MCP Facade (MCP server) + +-- search_capabilities(query) + +-- execute_capability(name, arguments) + +-- Capability Dispatcher + +-- Hosted MCP Adapter (MCP client) + | +-- notion -> hosted MCP + OAuth + | +-- gmail -> hosted MCP + OAuth (preview) + +-- Capability Plugin / Native Adapter + +-- provider API or SDK ``` The facade owns: From 42566c118dedb10eff36cdf5826e4e14789ea12d Mon Sep 17 00:00:00 2001 From: chaodu-agent <274062505+chaodu-agent@users.noreply.github.com> Date: Fri, 24 Jul 2026 02:34:03 +0000 Subject: [PATCH 11/16] docs(adr): record OpenWorker connector lessons --- docs/adr/oab-mcp-adapter.md | 49 ++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/docs/adr/oab-mcp-adapter.md b/docs/adr/oab-mcp-adapter.md index 49eae5ef8..4986b0f41 100644 --- a/docs/adr/oab-mcp-adapter.md +++ b/docs/adr/oab-mcp-adapter.md @@ -206,7 +206,50 @@ References: [OpenWork agent MCP](https://github.com/different-ai/openwork/blob/d [OpenWork Connect services](https://openworklabs.com/docs/start-here/connect-your-stack/connect-services), [OpenWork shared MCP connections](https://openworklabs.com/docs/cloud/share-with-your-team/shared-mcp-connections). -### 5.3 Notion hosted MCP +### 5.3 OpenWorker native connector prior art + +[OpenWorker](https://github.com/andrewyng/openworker) provides complementary +prior art for the capability-plugin path. It is a local-first desktop app with +a local Python agent server, a connector registry, native provider tools, and +optional remote MCP support. Its architecture shows that an agent product can +support provider-maintained MCP and native API/SDK connectors without forcing +every integration through MCP. + +The Gmail implementation is a native REST connector rather than a hosted MCP +connection: + +- `gmail_search_messages` calls the Gmail REST messages endpoint with an OAuth + bearer token. +- `gmail_get_message` fetches a message resource directly from Gmail. +- `gmail_send_email` posts a base64url-encoded MIME message to Gmail and is + approval-gated. +- `gmail:account:` profiles support multiple mailboxes, managed token + refresh, a default-account pointer, and account-level privacy filters. +- A separate generic Email connector uses IMAP/SMTP and app passwords for + Gmail, iCloud, Fastmail, and custom providers; it is not the native Gmail + API path. + +OAB adopts the lessons, not OpenWorker's provider-specific agent surface: + +- keep connector descriptors/catalog metadata separate from auth/session state; +- enforce provider privacy filters before content reaches the agent; +- make write/send capabilities explicitly approval-gated; +- use a Capability Plugin / Native Adapter when a provider has no hosted MCP; +- allow generic MCP and native connectors to coexist under one policy boundary. + +OAB deliberately normalizes these paths behind `search_capabilities` and +`execute_capability` rather than exposing tools such as +`gmail_search_messages` directly. OpenWorker's generic MCP OAuth path is also +useful prior art, but the inspected Gmail implementation uses direct Gmail REST +calls, not Google's hosted Gmail MCP endpoint. + +References: [OpenWorker README](https://github.com/andrewyng/openworker), +[OpenWorker Gmail tools](https://github.com/andrewyng/openworker/blob/main/coworker/connectors/integration_tools.py), +[OpenWorker Gmail accounts](https://github.com/andrewyng/openworker/blob/main/coworker/connectors/gmail_accounts.py), +[OpenWorker generic email connector](https://github.com/andrewyng/openworker/blob/main/coworker/connectors/email_tools.py), +[OpenWorker MCP OAuth](https://github.com/andrewyng/openworker/blob/main/coworker/mcp/oauth.py). + +### 5.4 Notion hosted MCP Notion provides a first-party hosted MCP server at `https://mcp.notion.com/mcp`, using Streamable HTTP and user OAuth. Its tools @@ -223,7 +266,7 @@ References: [Notion connection guide](https://developers.notion.com/guides/mcp/g [Notion supported tools](https://developers.notion.com/guides/mcp/mcp-supported-tools), [Notion hosted MCP design](https://www.notion.com/blog/notions-hosted-mcp-server-an-inside-look). -### 5.4 Gmail hosted MCP +### 5.5 Gmail hosted MCP Google provides `https://gmailmcp.googleapis.com/mcp/v1` as a Gmail remote MCP server. The official documentation currently labels it **Developer Preview**. @@ -238,7 +281,7 @@ not stable enough for production. Reference: [Google Gmail MCP setup](https://developers.google.com/workspace/gmail/api/guides/configure-mcp-server). -### 5.5 OpenClaw and Hermes Agent +### 5.6 OpenClaw and Hermes Agent The repository contribution guidelines require OpenClaw and Hermes Agent as prior art for runtime integrations. From 042b468c39d0862793dc15ec3432a0f2f38daedb Mon Sep 17 00:00:00 2001 From: chaodu-agent Date: Fri, 24 Jul 2026 00:55:28 -0400 Subject: [PATCH 12/16] docs(adr): specify facade transport/registration and meta-tool relationship Address review round 1 (F2, F3): - New $6.2: facade delivered via ACP session/new mcpServers, Streamable HTTP on loopback with per-session token; in-process dispatch for the native agent; reconciled with acp-server-websocket-mcp-browser.md's MCP proxy/aggregator role - $6.4: facade and mcp meta-tool are two frontends over one capability dispatcher; no agent runtime sees both surfaces; meta-tool contract unchanged in the MVP --- docs/adr/oab-mcp-adapter.md | 70 +++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 7 deletions(-) diff --git a/docs/adr/oab-mcp-adapter.md b/docs/adr/oab-mcp-adapter.md index 4986b0f41..02299ca40 100644 --- a/docs/adr/oab-mcp-adapter.md +++ b/docs/adr/oab-mcp-adapter.md @@ -121,7 +121,10 @@ policy and audit controls. The facade exposes the same two-method contract regardless of the downstream path. Notion and Gmail use the hosted MCP adapter in this MVP. The dashed capability-plugin path is the extension point for services that do not provide -a hosted MCP server. It is not a second agent-facing API. +a hosted MCP server. It is not a second agent-facing API. The coding agent +reaches the facade through the ACP `session/new` `mcpServers` registration and +a loopback-only listener inside the pod (§6.2); the native `openab-agent` +dispatches in-process. ## 4. Terminology and Positioning @@ -350,7 +353,38 @@ Hosted MCP provider business logic remains at the provider MCP server. A future plugin may contain a thin provider API/SDK translation layer, but the facade must not expose provider-specific APIs directly to the agent. -### 6.2 Configuration and activation +### 6.2 Facade transport and registration + +The facade reaches the coding agent through the mechanism OAB already uses: +the ACP `session/new` request, whose `mcpServers` parameter OAB currently sends +as an empty list (`crates/openab-core/src/acp/connection.rs`). No coding CLI's +own MCP configuration file is edited, and no CLI-specific registration format +is required. + +- **External coding CLIs (Kiro, Claude Code, Codex, ...):** when the facade is + active, OAB serves it as a Streamable HTTP MCP server bound to a loopback + interface inside the OAB pod and advertises that endpoint, with a + per-session authorization token, in the `mcpServers` entry of `session/new`. + The listener must never bind a non-loopback interface in this MVP; the token + scopes each ACP session to its own facade session so one thread's + capabilities and audit trail cannot be reused by another. +- **Native `openab-agent`:** the dispatcher is invoked in-process. No loopback + hop or token exchange is required because the facade contract and policy + checks are implemented by the same dispatcher component (see §6.4). + +This is the same architectural role that +[`acp-server-websocket-mcp-browser.md`](./acp-server-websocket-mcp-browser.md) +assigns to OpenAB core: an MCP proxy/aggregator between the agent and upstream +capability sources, delivered to the agent via `mcpServers`. The OAB MCP Facade +is that inbound component for external service capabilities; browser tools and +external capabilities share the delivery mechanism, and Alternative C's +rejection of a "second generic inbound MCP server" means no additional +agent-facing MCP server beyond this one aggregation point. + +If a backing CLI does not honor ACP `mcpServers`, the facade is unavailable for +that CLI in the MVP rather than falling back to editing the CLI's config files. + +### 6.3 Configuration and activation Keep the existing `openab-agent` configuration contract rather than introducing a duplicate top-level TOML section: @@ -418,7 +452,7 @@ pre-registered client, operators use the existing `oauth.client_id`, The profile examples are deliberately conservative. A deployment may add provider tools after reviewing their schemas and side effects. -### 6.3 Capability discovery and execution +### 6.4 Capability discovery and execution The facade exposes only two stable methods. Provider-specific tools remain behind the adapter and are represented as searchable capabilities: @@ -453,7 +487,27 @@ capability cache. The facade must then refresh discovery before accepting a call whose schema or availability may have changed. Provider names and raw provider credentials are never required in the agent-facing contract. -### 6.4 MVP capability profiles +#### Relationship to the existing `mcp` meta-tool + +`openab-agent` already exposes an LLM-facing `mcp` meta-tool with six actions +(`help`, `list_servers`, `list_tools`, `describe_tool`, `call`, `status`) +implemented in `openab-agent/src/mcp/meta_tool.rs`. The facade does not add a +second discovery/execution surface on top of it: + +- The meta-tool and the facade are two frontends over the **same capability + dispatcher and MCP runtime**. Catalog contents, tool filters, policy checks, + schema validation, and audit behavior are identical regardless of frontend. +- No agent runtime sees both surfaces. The native `openab-agent` keeps the + in-process meta-tool; an external coding CLI receives only the facade via + ACP `mcpServers` (§6.2) and never sees the meta-tool, which is internal to + `openab-agent`. +- The meta-tool's action vocabulary is unchanged by this MVP. Converging its + action names with `search_capabilities`/`execute_capability` is a documented + follow-up, not an MVP requirement, because renaming the accepted meta-tool + contract would be a breaking change to + [`openab-agent-mcp.md`](./openab-agent-mcp.md). + +### 6.5 MVP capability profiles #### Notion @@ -476,7 +530,7 @@ provider credentials are never required in the agent-facing contract. - Draft results must be presented as drafts for user review; the adapter must not claim that a message was sent. -### 6.5 Credential and session model +### 6.6 Credential and session model - HTTP MCP servers use the existing `openab-agent` OAuth manager and namespaced credential store (`mcp:`). @@ -489,7 +543,7 @@ provider credentials are never required in the agent-facing contract. - Existing per-server timeout, cancellation, idle eviction, and circuit breaker behavior applies without an adapter-specific retry loop. -### 6.6 Safety policy +### 6.7 Safety policy The adapter treats remote content as untrusted data: @@ -554,7 +608,9 @@ escape hatch for operators who intentionally configure a server outside OAB. ### C. Add a second generic inbound MCP server Rejected as unnecessary for this MVP. The OAB MCP facade is the intentionally -scoped inbound server for the coding agent. A separate generic server for +scoped inbound server for the coding agent, filling the MCP proxy/aggregator +role that [`acp-server-websocket-mcp-browser.md`](./acp-server-websocket-mcp-browser.md) +already assigns to OpenAB core (§6.2). A separate generic server for arbitrary OAB workflows would require another authentication, tenancy, and authorization design and would blur the two-method capability boundary. From de35ac02b48cc517141c21f43f446d8a95cb532b Mon Sep 17 00:00:00 2001 From: chaodu-agent Date: Fri, 24 Jul 2026 01:18:58 -0400 Subject: [PATCH 13/16] docs(adr): facade transport is a stdio subprocess for the MVP The MCP runtime lives in the workspace-excluded openab-agent crate, so the broker cannot serve the facade in-process without duplicating the runtime (which this ADR forbids). The facade is therefore advertised as a stdio 'openab-agent mcp-facade' entry in ACP session/new mcpServers; per-session subprocess = session isolation by construction. Loopback HTTP with per-session tokens is recorded as the follow-up. --- docs/adr/oab-mcp-adapter.md | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/docs/adr/oab-mcp-adapter.md b/docs/adr/oab-mcp-adapter.md index 02299ca40..b8d8e4d22 100644 --- a/docs/adr/oab-mcp-adapter.md +++ b/docs/adr/oab-mcp-adapter.md @@ -122,9 +122,9 @@ The facade exposes the same two-method contract regardless of the downstream path. Notion and Gmail use the hosted MCP adapter in this MVP. The dashed capability-plugin path is the extension point for services that do not provide a hosted MCP server. It is not a second agent-facing API. The coding agent -reaches the facade through the ACP `session/new` `mcpServers` registration and -a loopback-only listener inside the pod (§6.2); the native `openab-agent` -dispatches in-process. +reaches the facade through the ACP `session/new` `mcpServers` registration — +a stdio `openab-agent mcp-facade` subprocess per session (§6.2); the native +`openab-agent` dispatches in-process. ## 4. Terminology and Positioning @@ -362,15 +362,22 @@ own MCP configuration file is edited, and no CLI-specific registration format is required. - **External coding CLIs (Kiro, Claude Code, Codex, ...):** when the facade is - active, OAB serves it as a Streamable HTTP MCP server bound to a loopback - interface inside the OAB pod and advertises that endpoint, with a - per-session authorization token, in the `mcpServers` entry of `session/new`. - The listener must never bind a non-loopback interface in this MVP; the token - scopes each ACP session to its own facade session so one thread's - capabilities and audit trail cannot be reused by another. -- **Native `openab-agent`:** the dispatcher is invoked in-process. No loopback - hop or token exchange is required because the facade contract and policy - checks are implemented by the same dispatcher component (see §6.4). + active, OAB advertises a **stdio** MCP server entry in the `mcpServers` + parameter of `session/new`: the command `openab-agent mcp-facade`. The CLI + spawns the facade as its own subprocess, giving each ACP session a private + facade instance — session isolation by construction, with no listener, no + port, and no session token to manage. This is dictated by a workspace + constraint: the MCP runtime (connections, OAuth, credential store, filters, + circuit breaker) lives in the `openab-agent` crate, which is excluded from + the broker workspace, so the broker cannot serve the facade in-process + without duplicating that runtime — exactly what this ADR forbids. A + loopback-only Streamable HTTP listener with per-session tokens remains the + documented follow-up if per-session subprocesses prove too heavy; it must + never bind a non-loopback interface. +- **Native `openab-agent`:** the dispatcher is invoked in-process via the + existing `mcp` meta-tool. No subprocess is required because the facade + contract and policy checks are implemented by the same dispatcher component + (see §6.4). This is the same architectural role that [`acp-server-websocket-mcp-browser.md`](./acp-server-websocket-mcp-browser.md) From 578c1fbdb951ebbec52076f11005c740342c48cd Mon Sep 17 00:00:00 2001 From: chaodu-agent Date: Fri, 24 Jul 2026 07:39:41 -0400 Subject: [PATCH 14/16] docs(adr): facade is broker-hosted loopback Streamable HTTP via shared openab-mcp crate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maintainer direction: any coding CLI on the host connects to http://127.0.0.1:/mcp; activation is the [mcp] section in the broker's config.toml. The MCP runtime is extracted to crates/openab-mcp (broker links it, openab-agent re-exports it) — one runtime, two hosts. [mcp] carries listener settings only; mcp.json remains the sole provider source of truth (Alternative E reworded accordingly). No-auth loopback posture documented; token scheme is a follow-up. --- docs/adr/oab-mcp-adapter.md | 70 ++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/docs/adr/oab-mcp-adapter.md b/docs/adr/oab-mcp-adapter.md index b8d8e4d22..2a7a031b4 100644 --- a/docs/adr/oab-mcp-adapter.md +++ b/docs/adr/oab-mcp-adapter.md @@ -121,10 +121,11 @@ policy and audit controls. The facade exposes the same two-method contract regardless of the downstream path. Notion and Gmail use the hosted MCP adapter in this MVP. The dashed capability-plugin path is the extension point for services that do not provide -a hosted MCP server. It is not a second agent-facing API. The coding agent -reaches the facade through the ACP `session/new` `mcpServers` registration — -a stdio `openab-agent mcp-facade` subprocess per session (§6.2); the native -`openab-agent` dispatches in-process. +a hosted MCP server. It is not a second agent-facing API. The broker serves +the facade in-process as a loopback-only Streamable HTTP endpoint +(`http://127.0.0.1:/mcp`), enabled by the `[mcp]` section in +`config.toml` (§6.2); any coding CLI on the host connects to that URL. The +native `openab-agent` dispatches in-process. ## 4. Terminology and Positioning @@ -355,29 +356,39 @@ must not expose provider-specific APIs directly to the agent. ### 6.2 Facade transport and registration -The facade reaches the coding agent through the mechanism OAB already uses: -the ACP `session/new` request, whose `mcpServers` parameter OAB currently sends -as an empty list (`crates/openab-core/src/acp/connection.rs`). No coding CLI's -own MCP configuration file is edited, and no CLI-specific registration format -is required. - -- **External coding CLIs (Kiro, Claude Code, Codex, ...):** when the facade is - active, OAB advertises a **stdio** MCP server entry in the `mcpServers` - parameter of `session/new`: the command `openab-agent mcp-facade`. The CLI - spawns the facade as its own subprocess, giving each ACP session a private - facade instance — session isolation by construction, with no listener, no - port, and no session token to manage. This is dictated by a workspace - constraint: the MCP runtime (connections, OAuth, credential store, filters, - circuit breaker) lives in the `openab-agent` crate, which is excluded from - the broker workspace, so the broker cannot serve the facade in-process - without duplicating that runtime — exactly what this ADR forbids. A - loopback-only Streamable HTTP listener with per-session tokens remains the - documented follow-up if per-session subprocesses prove too heavy; it must - never bind a non-loopback interface. +The facade is a **loopback-only Streamable HTTP** MCP server hosted +**in-process by the OAB broker**, activated by the presence of an `[mcp]` +section in the broker's `config.toml`: + +```toml +[mcp] +listen = "127.0.0.1:8848" # loopback only; this is the default +``` + +- **External coding CLIs (Kiro, Claude Code, Codex, ...):** connect to + `http://127.0.0.1:/mcp` like any remote MCP server. Because the + endpoint is plain Streamable HTTP, every MCP-capable CLI on the host can + use the facade with its normal remote-server configuration — no + CLI-specific registration format, no OAB-managed subprocess. +- **Runtime sharing:** the MCP runtime (connections, OAuth, credential store, + tool filters, circuit breaker, schema validation) is extracted into the + shared `crates/openab-mcp` crate. The broker links it directly to serve the + facade; `openab-agent` re-exports the same crate. One implementation, two + hosts — no duplicated runtime, which this ADR forbids. +- **Security posture:** the listener refuses to bind any non-loopback + address; the endpoint itself carries no authentication layer in the MVP, + so the host/pod boundary is the trust boundary. Every process on the host + that can reach loopback can call authorized capabilities — deployments + that colocate untrusted processes must not enable `[mcp]`. A token or + socket-permission scheme is a documented follow-up. - **Native `openab-agent`:** the dispatcher is invoked in-process via the - existing `mcp` meta-tool. No subprocess is required because the facade + existing `mcp` meta-tool. No HTTP hop is required because the facade contract and policy checks are implemented by the same dispatcher component (see §6.4). +- **ACP `session/new` `mcpServers` advertisement** (OAB injecting the facade + URL into the agent session it spawns) is a follow-up on top of this + transport, not a prerequisite: the loopback URL is already reachable by any + CLI the operator points at it. This is the same architectural role that [`acp-server-websocket-mcp-browser.md`](./acp-server-websocket-mcp-browser.md) @@ -628,12 +639,13 @@ Rejected. The facade exposes only `search_capabilities` and isolates provider schema drift. This follows the accepted progressive-disclosure pattern rather than flattening downstream tools. -### E. Add a new top-level `[mcp]` TOML section +### E. Duplicate provider configuration in a top-level `[mcp]` TOML section -Rejected for the MVP because `openab-agent` already owns and documents layered -`.openab/agent/mcp.json` configuration. A future broker-level configuration -facade may point to or generate that file, but it should not create a second -source of truth. +Rejected: `openab-agent` already owns and documents layered +`.openab/agent/mcp.json` configuration, and that file remains the only source +of provider connections. The broker's `[mcp]` section (§6.2) is deliberately +**not** a second provider registry — it carries only facade-listener settings +(`listen`), and its presence is the opt-in switch for serving the facade. ## 9. Risks and Mitigations From 522440a6fac5be76b1366f5e8a6798edcb05328d Mon Sep 17 00:00:00 2001 From: chaodu-agent Date: Fri, 24 Jul 2026 15:35:25 -0400 Subject: [PATCH 15/16] =?UTF-8?q?docs(adr):=20add=20=C2=A74.1=20two-tier?= =?UTF-8?q?=20positioning=20=E2=80=94=20pod-level=20facade=20vs=20fleet-le?= =?UTF-8?q?vel=20octobroker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/adr/oab-mcp-adapter.md | 52 +++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/docs/adr/oab-mcp-adapter.md b/docs/adr/oab-mcp-adapter.md index 2a7a031b4..2edbd11ee 100644 --- a/docs/adr/oab-mcp-adapter.md +++ b/docs/adr/oab-mcp-adapter.md @@ -148,6 +148,58 @@ MCP is an agent capability adapter, not a channel adapter and not an Ambient activation mode. Ambient decides when an agent is prompted; the OAB MCP facade and adapter decide how that agent reaches authorized external capabilities. +### 4.1 Positioning relative to octobroker (OBK): a two-tier adoption ladder + +OpenAB develops two MCP-facing products. They are not competitors and not +redundant; they answer different questions at different deployment scales, and +they compose: + +- **OAB MCP Facade (this ADR)** is **pod-level**, for a single OAB's own use. + It answers *"what can the connected coding CLI discover and use?"* — + presentation, capability search, catalog caching, and `tool_filter` + least-privilege hygiene. Its credentials are **personal OAuth grants** (the + user authorizing access to their own Gmail, their own Notion), held in the + pod's `auth.json`. For a single-OAB user this is the complete, standalone + product: no extra deployment, the pod boundary is the trust boundary. +- **octobroker (OBK)** is **fleet-level**, shared by many OABs with distinct + identities. It answers *"who is allowed to execute what?"* — per-agent + authentication (`X-Octobroker-Key`), default-deny tool and resource policy, + short-lived scoped credential minting for **organization-owned** resources, + and fail-closed audit. A single-OAB deployment does not need it; adopting it + buys governance at the cost of an extra service. + +| | OAB MCP Facade | octobroker (OBK) | +|---|---|---| +| Tier | Pod (one OAB, its own use) | Fleet (many OABs, distinct identities) | +| Question answered | What can the CLI discover and use? | Who may execute what? | +| Credentials | Personal OAuth (user's own resources) | Organization credentials (short-lived, scoped, minted centrally) | +| Trust boundary | Pod / host (loopback) | Network + per-agent key + fail-closed audit | +| When to skip | Never — it is the agent-facing entry point | Single OAB, no org-owned resources: pure added complexity | + +Credential ownership follows **resource ownership**, not product tier: personal +resources (the user's Gmail or Notion) are authorized via OAuth and their +tokens correctly live in the facade's `auth.json` — this is the end state, not +a transitional one. Organization resources (org GitHub repositories, a company +Notion workspace) belong behind OBK, so no organization credential ever resides +in an agent pod. + +The upgrade path between tiers is a configuration change, not an agent change: +a fleet deployment adds OBK as one more downstream entry in the facade's +`mcp.json`. The agent-facing surface remains exactly +`search_capabilities`/`execute_capability`; because the facade dispatches +native `tools/call` requests to downstreams, OBK's per-tool policy and audit +see real tool names and are never blinded by the meta-tool envelope. Two +disciplines preserve this ladder: + +1. No facade feature may assume OBK exists (the single-OAB tier must remain + complete on its own). +2. No OBK feature may assume the caller is the facade (directly connected MCP + clients are first-class in the fleet tier). + +Consequently, requests to add per-agent keys or fleet policy to the facade, or +personal-OAuth stores to OBK, are out of scope by construction for the +respective product. + ## 5. Prior Art and Industry Research ### 5.1 Existing OpenAB MCP client From 3c875b8be45c466a1c64fe534e31bbbaa7249458 Mon Sep 17 00:00:00 2001 From: chaodu-agent Date: Sat, 25 Jul 2026 00:59:24 -0400 Subject: [PATCH 16/16] =?UTF-8?q?docs(adr):=20=C2=A713=20post-decision=20s?= =?UTF-8?q?tatus=20addendum=20=E2=80=94=20shipped=20outcomes=20vs=20=C2=A7?= =?UTF-8?q?5/=C2=A710=20assumptions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/adr/oab-mcp-adapter.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/docs/adr/oab-mcp-adapter.md b/docs/adr/oab-mcp-adapter.md index 2edbd11ee..b8cbf73b9 100644 --- a/docs/adr/oab-mcp-adapter.md +++ b/docs/adr/oab-mcp-adapter.md @@ -788,3 +788,33 @@ The MVP supports: Configuration presence remains the opt-in signal. The MVP does not add a second MCP runtime, a native Gmail/Notion REST client, or a new TOML source of truth. + +## 13. Post-decision status (2026-07-25 addendum) + +The design above is recorded as decided; implementation and live validation +overtook parts of §5/§10 before this ADR merged. Decisions themselves are +unchanged — this section records outcomes so the document does not mislead: + +- **Facade MVP shipped** (#1448) as specified in §6.2 (broker-hosted loopback + Streamable HTTP + `openab-mcp` shared crate), including `tool_filter` + enforcement. **Facade-only run mode** followed (#1453): an adapter-less + config with `[mcp]` present is a valid `openab run` deployment. +- **Gmail (§5.5/§6.5) resolved ahead of Notion, and native-first**: live + validation showed the hosted server rejects every `tools/call` without + Workspace Developer Preview Program enrollment, and the program **rejects + consumer accounts** — for consumer mailboxes the hosted path is unavailable + regardless of waiting, and program terms bar pre-GA shipping in public + applications. The §6.1 Capability Plugin path shipped as the **native + Gmail adapter** (#1449, `docs/gmail-native.md`): the six-tool §6.5 profile + over Gmail's GA REST API with tool names/shapes mirroring the hosted + server, so the §10 step-5 cut-over back to hosted (re-evaluate at GA) + remains a config-only change. Rollout steps 3/5 are therefore resolved; + step 2 (Notion) is still pending. +- **Session-aware in-process capability sources** (#1454) extend §6: the + facade can host provider sources in-process, with per-agent-session + identity via broker-minted tokens (`Authorization` header → `SessionCtx`). + Session-bound capabilities (e.g. browser control, the ACP-MCP browser ADR) + are invisible and unreachable to anonymous clients. This supersedes the + assumption that all facade capabilities come from `mcp.json` servers. +- **Positioning** (§4.1) and CLI taxonomy (`docs/cli-conventions.md`) were + adopted as written.