From e7474b54eceda735f92bc8147e6c31a141c3af28 Mon Sep 17 00:00:00 2001 From: ndom91 Date: Fri, 3 Jul 2026 12:15:21 +0200 Subject: [PATCH 1/4] Add Plain to integrations registry Plain (plain.com) exposes an official remote MCP server (OAuth) and a Bearer-authenticated GraphQL API for support workflows. Both endpoints were probed live (MCP 401 + www-authenticate; GraphQL 401, docs-confirmed canonical endpoint). Co-Authored-By: Claude Opus 4.8 (1M context) --- sources/discovered.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/sources/discovered.json b/sources/discovered.json index 1da3c113..4f7ce082 100644 --- a/sources/discovered.json +++ b/sources/discovered.json @@ -30360,6 +30360,26 @@ } ] }, + { + "domain": "plain.com", + "summary": "Plain (plain.com) exposes an official remote MCP server authenticated over OAuth against your Plain user, plus a Bearer-authenticated GraphQL API for customer support workflows — threads, customers, tenants, and help-center content; no public REST or CLI surface was confirmed.", + "surfaces": [ + { + "slug": "plain-mcp-server", + "name": "Plain MCP server", + "type": "mcp", + "authStatus": "required", + "url": "https://mcp.plain.com/mcp" + }, + { + "slug": "plain-graphql-api", + "name": "Plain GraphQL API", + "type": "graphql", + "authStatus": "required", + "url": "https://core-api.uk.plain.com/graphql/v1" + } + ] + }, { "domain": "planetscale.com", "summary": "PlanetScale exposes one HTTP API, one hosted MCP server, and the `pscale` CLI; API/CLI use service tokens, while MCP uses OAuth-based auth.", From f57c6a5d4cb251f2d17e844bef15865d431bf6d3 Mon Sep 17 00:00:00 2001 From: ndom91 Date: Fri, 3 Jul 2026 13:14:21 +0200 Subject: [PATCH 2/4] Add Plain full discovery doc with credentials + auth bindings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit results-full/plain.com.json — the rich source (→ load-kv → KV) that renders Plain's domain-page CREDENTIALS block: OAuth for the MCP server (detected via live 401 + WWW-Authenticate probe) and a Machine-User API key (Bearer) for the GraphQL API, per Plain's auth docs. Mirrors the planetscale.com.json shape. Note: `bun run validate:batch` cannot run in this checkout — the `effect` dependency (imported by src/lib/discovery-schema.ts) is not installed, so the validator errors before evaluating any record. Pre-existing dependency drift, unrelated to this change; the file was verified by hand against each validator rule and against the peer planetscale record. Co-Authored-By: Claude Opus 4.8 (1M context) --- scripts/batch/results-full/plain.com.json | 110 ++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 scripts/batch/results-full/plain.com.json diff --git a/scripts/batch/results-full/plain.com.json b/scripts/batch/results-full/plain.com.json new file mode 100644 index 00000000..77844d82 --- /dev/null +++ b/scripts/batch/results-full/plain.com.json @@ -0,0 +1,110 @@ +{ + "result": { + "version": 3, + "domain": "plain.com", + "detect": { + "domain": "plain.com", + "found": [], + "mcp": [ + "https://mcp.plain.com/mcp" + ], + "llmsTxt": false, + "errors": [] + }, + "usedLlm": false, + "discoveredAt": "2026-07-03T00:00:00.000Z", + "summary": "Plain (plain.com) is a customer support platform. It exposes an official remote MCP server authenticated over OAuth against your existing Plain user, plus a Bearer-authenticated GraphQL API for support workflows — threads, customers, tenants, labels, and help-center content. No public REST or CLI surface was confirmed.", + "credentials": { + "plain_oauth": { + "type": "oauth2", + "label": "Plain OAuth", + "setup": "The MCP server uses OAuth against your existing Plain login — there is nothing to mint. Add `https://mcp.plain.com/mcp` in an OAuth-capable client and approve the Plain consent screen; the connection inherits your user's permissions and replies appear as though they come from your user. Claude Code lacks OAuth token refresh, so wrap the remote server with [`mcp-remote`](https://help.plain.com/article/mcp-server): `npx -y mcp-remote https://mcp.plain.com/mcp`.", + "acquisition": "manual" + }, + "plain_api_key": { + "type": "api_key", + "label": "Plain API key", + "generateUrl": "https://app.plain.com/settings/machine-users", + "setup": "API keys belong to a Machine User. Go to [Settings → Machine Users](https://app.plain.com/settings/machine-users) in Plain and click **Add Machine User**, then **Add API Key** and select the permissions the key needs (e.g. `customer:read`, `thread:create`) — insufficient scopes surface an error naming the missing permission. Copy the `plainApiKey_…` value; it is shown only once. Send it as `Authorization: Bearer plainApiKey_…`. See [API authentication](https://www.plain.com/docs/api-reference/graphql/authentication).", + "acquisition": "manual" + } + }, + "surfaces": [ + { + "slug": "plain-mcp-server", + "name": "Plain MCP server", + "type": "mcp", + "docs": "https://help.plain.com/article/mcp-server", + "basis": { + "via": "detected", + "signal": "POST initialize returned 401 with WWW-Authenticate: Bearer resource_metadata=\"https://mcp.plain.com/.well-known/oauth-protected-resource\"", + "verifiedAt": "2026-07-03" + }, + "auth": { + "status": "required", + "entries": [ + { + "use": [ + { + "id": "plain_oauth", + "mechanics": { + "source": "well-known" + } + } + ], + "basis": { + "via": "detected", + "signal": "WWW-Authenticate header advertises OAuth protected-resource metadata at https://mcp.plain.com/.well-known/oauth-protected-resource", + "verifiedAt": "2026-07-03" + } + } + ] + }, + "url": "https://mcp.plain.com/mcp", + "transports": [ + "streamable-http" + ] + }, + { + "slug": "plain-graphql-api", + "name": "Plain GraphQL API", + "type": "graphql", + "docs": "https://www.plain.com/docs/api-reference/graphql/introduction", + "basis": { + "via": "discovered", + "evidence": [ + "https://www.plain.com/docs/api-reference/graphql/introduction", + "https://www.plain.com/docs/api-reference/graphql/authentication" + ] + }, + "auth": { + "status": "required", + "entries": [ + { + "use": [ + { + "id": "plain_api_key", + "mechanics": { + "source": "http", + "in": "header", + "headerName": "Authorization", + "scheme": "Bearer" + } + } + ], + "basis": { + "via": "discovered", + "evidence": [ + "https://www.plain.com/docs/api-reference/graphql/authentication" + ] + } + } + ] + }, + "spec": "https://core-api.uk.plain.com/graphql/v1/schema.graphql", + "url": "https://core-api.uk.plain.com/graphql/v1" + } + ] + }, + "discoveredAt": "2026-07-03T00:00:00.000Z" +} From 196f8806f3299af2617953e15067c5c512956ac8 Mon Sep 17 00:00:00 2001 From: ndom91 Date: Fri, 3 Jul 2026 13:18:10 +0200 Subject: [PATCH 3/4] Cleanup plain.com json copy --- scripts/batch/results-full/plain.com.json | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/scripts/batch/results-full/plain.com.json b/scripts/batch/results-full/plain.com.json index 77844d82..ad936b9d 100644 --- a/scripts/batch/results-full/plain.com.json +++ b/scripts/batch/results-full/plain.com.json @@ -5,15 +5,13 @@ "detect": { "domain": "plain.com", "found": [], - "mcp": [ - "https://mcp.plain.com/mcp" - ], + "mcp": ["https://mcp.plain.com/mcp"], "llmsTxt": false, "errors": [] }, "usedLlm": false, "discoveredAt": "2026-07-03T00:00:00.000Z", - "summary": "Plain (plain.com) is a customer support platform. It exposes an official remote MCP server authenticated over OAuth against your existing Plain user, plus a Bearer-authenticated GraphQL API for support workflows — threads, customers, tenants, labels, and help-center content. No public REST or CLI surface was confirmed.", + "summary": "Plain (plain.com) is a customer support platform. It exposes an official remote MCP server authenticated over OAuth against your existing Plain user, plus an API key authenticated GraphQL API - threads, customers, tenants, labels, and help-center content.", "credentials": { "plain_oauth": { "type": "oauth2", @@ -61,9 +59,7 @@ ] }, "url": "https://mcp.plain.com/mcp", - "transports": [ - "streamable-http" - ] + "transports": ["streamable-http"] }, { "slug": "plain-graphql-api", From f4b8de8a7418ed736ad1396a355248349c224f75 Mon Sep 17 00:00:00 2001 From: ndom91 Date: Fri, 3 Jul 2026 13:24:40 +0200 Subject: [PATCH 4/4] Add required model field to Plain StoredDiscovery envelope StoredDiscovery (src/lib/discovery-schema.ts) requires a non-optional `model` string alongside `result`/`discoveredAt`; readers decode via that Schema, so the row would fail to load into KV without it. Use the schema-sanctioned "cache-backfill" value for this hand-authored (non-LLM) record. Co-Authored-By: Claude Opus 4.8 (1M context) --- scripts/batch/results-full/plain.com.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/batch/results-full/plain.com.json b/scripts/batch/results-full/plain.com.json index ad936b9d..6c4a3a20 100644 --- a/scripts/batch/results-full/plain.com.json +++ b/scripts/batch/results-full/plain.com.json @@ -102,5 +102,6 @@ } ] }, - "discoveredAt": "2026-07-03T00:00:00.000Z" + "discoveredAt": "2026-07-03T00:00:00.000Z", + "model": "cache-backfill" }