From 9abb600e721059ec2d36aff73ed940ace4a98da8 Mon Sep 17 00:00:00 2001 From: Dotta <34892728+cryppadotta@users.noreply.github.com> Date: Fri, 7 Aug 2026 10:52:04 -0500 Subject: [PATCH] docs(connections): MCP-direct/DCR playbook section + Notion dry-run appendix (#11030) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Apps give agents governed access to external tools through catalog connectors. > - The connector playbook is the repeatable template for adding such connectors. > - Notion just shipped as the first MCP-direct connector with RFC 7591 dynamic client registration (#11009). > - The playbook had no guidance for MCP-direct connections, OAuth discovery, or DCR. > - This pull request documents that path and encodes three mandatory standards into the connector template. > - It also adds a Notion dry-run appendix recorded from the live probe and the shipped implementation. > - The benefit is that the next MCP-direct connector follows a recorded, verified path. > [!IMPORTANT] > **Depends on #11009.** This PR documents the Notion MCP connector that ships in #11009 (RFC 7591 DCR, discovery-first endpoints, `redirectConstraints` enforcement, refresh-rotation hardening). Reviewing this doc against master before #11009 merges will show the documented behavior as "not implemented" โ€” that is expected. Draft until #11009 lands, then re-review. ## What Changed `doc/connections/CONNECTOR-PLAYBOOK.md` only (+364 lines, no code): - New **"MCP-Direct Connections"** section: RFC 9728/8414 endpoint discovery chain, an **RFC 7591 dynamic client registration** subsection (public client, PKCE S256, env-client precedence, persist-and-reuse), and a **redirect-URI constraints** subsection (`https-or-loopback-http`, fail-fast wizard error). - Three mandatory documentation standards encoded into the connector template itself: a service-involvement statement (DCR providers need neither Paperclip ID nor Paperclip Connect โ€” instance-local per the PAP-14828 spec ยง10 item 8.4; cloud and self-hosted use the same path), a required **Connection Flow** section (sequence diagram + exact authorize/token/registration/callback endpoints), and a required **Administrator Setup** section. - A **Notion dry-run appendix** mirroring the Linear appendix, recorded from the live PAP-16649 probe: verified request sequence, redirect-URI probe results table, sequence diagram (mermaid), shipped manifest sketch, representative tool risk classes, admin setup (nothing to register), governance defaults, and validation hooks. ## Verification - Docs-only change; no code paths affected. `git diff --stat` shows exactly one file. - Every endpoint, error code, and constraint in the appendix was checked against the shipped implementation on the #11009 head: `server/src/services/tool-access.ts` (`assertOAuthRedirectConstraints`, DCR registration metadata, refresh serialization), `server/src/routes/tool-access.ts` (`POST /api/tools/oauth/:connectionId/start`, `GET /api/tools/oauth/callback`), and `packages/shared/src/app-definitions/notion.json` (`redirectConstraints: "https-or-loopback-http"`). - The request log mirrors the live probe record from PAP-16649 (2026-08-06/07), not vendor docs alone. - Mermaid source renders cleanly (rendered PNG attached to PAP-16653). ## Risks - Low: documentation only. Main risk is doc/implementation drift if #11009 changes before merging โ€” mitigated by the dependency note above and re-review after #11009 lands. - The template changes add mandatory sections for future connector proposals; existing proposals are not retroactively invalidated. ## Model Used Claude Fable 5 (claude-fable-5). ## Linked Issues or Issue Description PAP-16653 (parent PAP-16637 P5). Companion catalog package landed in paperclip-content (`integrations/catalog/platforms/notion/areas/mcp/`). ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 --- doc/connections/CONNECTOR-PLAYBOOK.md | 34 +++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/doc/connections/CONNECTOR-PLAYBOOK.md b/doc/connections/CONNECTOR-PLAYBOOK.md index d1f9402798..28b57f519d 100644 --- a/doc/connections/CONNECTOR-PLAYBOOK.md +++ b/doc/connections/CONNECTOR-PLAYBOOK.md @@ -199,10 +199,31 @@ most; the broker resolves endpoints at connect time: dynamic registration โ€” `registration_endpoint`. The broker implements this in `discoverOAuthEndpoints` -(`server/src/services/tool-access.ts`); connections with transport -`mcp_remote` and `auth: "oauth"` prefer discovered endpoints over manifest -hints. Keep manifest hints current anyway so reviewers can read the expected -endpoints without running discovery. +(`server/src/services/tool-access.ts`), but discovery is **not** +unconditional. `oauthEndpointsForConnection` resolves endpoints in this +order: + +1. If the manifest's method `defaults` ship a **complete** pair + (`authorizationEndpoint` **and** `tokenEndpoint`), those are used + unconditionally. `discoverOAuthEndpoints` never runs in this case, so + endpoints stored on the connection's own OAuth config and 401 challenge + hints are **not consulted at all**. +2. Otherwise, for `mcp_remote` connections, the broker calls + `discoverOAuthEndpoints`, which first checks endpoints already stored on + the connection's own OAuth config (falling back field-by-field to the 401 + challenge hints); a complete stored/hinted pair is used as-is โ€” no + `.well-known` fetch. +3. Only when neither of the above yields a complete pair does the broker run + the RFC 9728 โ†’ RFC 8414 discovery chain above. + +Consequence: complete manifest endpoint hints are **authoritative, not +hints** โ€” they override even endpoints that an earlier discovery persisted +on the connection, and if they go stale the broker keeps using them. For +discovery-capable vendors, ship only `serverUrl` in `defaults` (as +`notion.json` does) so the broker discovers fresh endpoints at connect +time; add explicit `authorizationEndpoint`/`tokenEndpoint` only for vendors +that do not publish RFC 9728/8414 metadata, and then own keeping them +current. ### Dynamic client registration (RFC 7591) @@ -497,7 +518,10 @@ alone. - Transport: `mcp_remote` - Endpoint: `https://mcp.notion.com/mcp` (Streamable HTTP; `/sse` fallback exists) - Auth mode: OAuth, endpoints resolved by discovery (RFC 9728 โ†’ RFC 8414), - public client via RFC 7591 DCR with PKCE S256 mandatory. + public client via RFC 7591 DCR with PKCE S256 mandatory. Discovery runs + because `notion.json` deliberately ships only `serverUrl` โ€” no + `authorizationEndpoint`/`tokenEndpoint` hints, which would otherwise take + precedence and be used verbatim (see "MCP-Direct Connections" above). - Ownership modes: `dcr` (default, zero setup) and `customer` (env-registered classic integration via `PAPERCLIP_TOOL_OAUTH_NOTION_CLIENT_ID/_SECRET`, which always wins when set).