diff --git a/doctrine/CHANGELOG.md b/doctrine/CHANGELOG.md index 8e74776..c68012f 100644 --- a/doctrine/CHANGELOG.md +++ b/doctrine/CHANGELOG.md @@ -6,6 +6,37 @@ evidence (Run Records / Retro Notes) behind it. Required by constitution invariant I8; written by `/tune-pipeline` when a human approves a proposal, or by hand for direct human edits. +## 2026-09-30 — move credential setup to the Identity section + +Files: `doctrine/speakeasy-setup.md`, `guides/*/{speakeasy,external,research}.md`, +`guides/*/meta.yaml`. + +Evidence: an audit of every guide against `speakeasy-api/gram` main +`68b3f78ffec0ab6072ece4b7cc2ee3868c6a7c06` found that #6364, #6905, #6906, +#6813 and #6974 replaced the remote-server **Authentication** section and +**Attach Remote Identity Provider** sheet with an **Identity** section. The +human asked for this correction as a pull request. + +- Choose **User Identity**, **Service Account**, or **No Identity** when + adding the server (catalog dialog and **Hosted remotely**), and in + **Settings > Identity** afterwards. +- Replace the provider form with the provider picker; route providers + without discoverable metadata through **Create a custom identity + provider**. +- Replace **Session Client** / **Client Type** with **Existing client**, + **Auto-Configure** (CIMD or DCR), and **Manual**; record when Manual must + be chosen over the Auto-Configure default. +- Scopes go under **Advanced > Scope**, space-separated; a blank value + requests every PRM scope. The auth method and audience controls are gone. +- API keys and tokens go in the **Service Account** credential, not + **Upstream Headers**. Servers left **Disabled** are enabled from + **Server Availability**. +- Refresh every guide and apply the audit's verified provider fixes. + +Verification is source-level plus live provider probes and repository +validation; this entry does not claim a production-browser walkthrough. +I8: human-approved correction. + ## 2026-09-17 — align in-app setup steps with current Control Plane UI Files: `doctrine/speakeasy-setup.md`, `guides/*/speakeasy.md`, diff --git a/doctrine/speakeasy-setup.md b/doctrine/speakeasy-setup.md index d910c23..29c22ef 100644 --- a/doctrine/speakeasy-setup.md +++ b/doctrine/speakeasy-setup.md @@ -13,10 +13,16 @@ Consumers may omit this file when Speakeasy setup is already in context UI facts below are drawn from the product source (`speakeasy-api/gram`, `client/dashboard`, branch `main`), commit -`8fa18729608e34de305e789b53f36eb2c6c853c9` (observed 2026-09-17). +`68b3f78ffec0ab6072ece4b7cc2ee3868c6a7c06` (observed 2026-09-30). Navigation and creation: `pages/mcp/MCP.tsx`, `pages/mcp/add/AddMcpServer.tsx`, -`pages/sources/remote-mcp/CreateRemoteMcp.tsx`, and `pages/catalog/`. -Authentication: `pages/mcp/x/tabs/settings/sections/authentication/`. +`pages/sources/remote-mcp/CreateRemoteMcp.tsx`, +`pages/catalog/AddServerDialog.tsx`, and +`pages/mcp/x/tabs/settings/sections/authentication/CreationIdentityChoice.tsx`. +Identity: `pages/mcp/x/tabs/settings/sections/authentication/RemoteMcpIdentitySection.tsx` +and `lib/remote-identity/` (`IdentityModeCards.tsx`, `ProviderRow.tsx`, +`CredentialFields.tsx`, `drafts/useIdentityDraft.ts`). Custom providers: +`pages/remote-identity-providers/`. Server availability: +`pages/mcp/x/tabs/settings/sections/DangerZoneSection.tsx`. Labels are code-level strings; a rendered-UI spot check is still worthwhile. Controls depend on configuration state and write permission. No role may invent a label this file does not carry. @@ -34,13 +40,29 @@ invent a label this file does not carry. - Optional `speakeasy_add_server`: `auto` (default), `catalog`, or `custom-remote`. - The Authentication Option the guide documents, which External-setup - step produced each credential field, and — for OAuth options — any - scopes the provider requires. For every OAuth option, record the - **Issuer URL**, discovery support, and documented authorization/token - endpoints when discovery is unavailable; DCR also needs a registration - endpoint. Do not assume the remote MCP URL is the OAuth issuer. Missing - provider-specific issuer/endpoint evidence is an open question, not a - value the Writer may invent. + step produced each credential field, and — for OAuth options — the + scopes the provider app is configured for. Map the option to an + identity mode: OAuth → **User Identity**; one shared API key or token + → **Service Account**; no upstream credential → **No Identity**. +- For every OAuth option, record: the probe outcome of the remote URL + (401 with a `resource_metadata` challenge, 401 without one, or 200 + unauthenticated); the issuer the protected-resource metadata (PRM) + names; whether that issuer advertises CIMD + (`client_id_metadata_document_supported`) or a `registration_endpoint`, + and whether anonymous registration actually succeeds; and, when + discovery is unavailable, the documented **Issuer URL**, authorization, + and token endpoints. Do not assume the remote MCP URL is the OAuth + issuer. Missing provider-specific issuer/endpoint evidence is an open + question, not a value the Writer may invent. +- The registration choice that works: **Auto-Configure** (and **CIMD** + or **DCR** when both are offered) or **Manual**. Record Manual whenever + automatic registration is advertised but fails, because the dashboard + defaults to **Auto-Configure** whenever it is advertised. +- For **Manual**, the exact scope string to enter under **Advanced > + Scope**, space-separated on one line. A blank **Scope** requests every + scope the PRM advertises, which is often broader than the provider app + allows; record the PRM scope list so the Writer can say whether blank + is safe. - `` — the provider's primary MCP documentation page, for the closing pointer. @@ -67,7 +89,7 @@ or absent). ## The skeleton (anchors are fixed; carry them verbatim) -Both bullets below are **source material**. Research emits only the +Both path bullets below are **source material**. Research emits only the matching imperative path (or both when unresolved). Writer renders what the Dossier chose — not the conditional "If … is in the catalog" framing when presence is known. @@ -81,105 +103,141 @@ In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select `speakeasy_add_server: catalog`; never when tenanted or `custom-remote`): choose **From the catalog**. On the **MCP Catalog** page, find using **Search MCP servers...**, open its catalog -entry, and click **Add**. In the **Add to Project** dialog, click -**Add to Project**. Wait for installation to complete, then click -**Configure MCP settings** to open the created server. +entry, and click **Add**. The **Add to Project** dialog shows **Server +name**, any **Upstream headers** the catalog entry declares, and an +**Identity** choice of **User Identity**, **Service Account**, or **No +Identity**. It preselects **User Identity** only when the catalog entry +supports OAuth client registration; otherwise it preselects **No +Identity**. Select the identity mode the Dossier records (see below), +then click **Add to Project**. When the dialog offers a **Guardrails** +step, finish it or click **Skip for now** (guardrails are out of guide +scope). After **Server added successfully**, click **Configure MCP +settings** to open the created server. When identity still needs setup, +there is no success banner: the server's result reads "Added, but +disabled until identity is set up." and **Finish setup** opens its +**Settings**. **Custom remote path** (tenanted, `speakeasy_add_server: custom-remote`, or Pulse **absent**): choose **Hosted remotely**. On **New remote MCP server**, paste `` into **MCP server URL**. Optionally enter -**Display name (optional)**. Click **Verify connectivity**, then, after -verification succeeds, click **Save**. This creates the hosted MCP server -and opens its **Overview** page. +**Display name (optional)**. Leave **User session issuer** at its +default. Click **Verify connectivity**. After verification succeeds, the +page shows the **Identity** choice. It preselects **User Identity** only +when the server answered with a 401 that names its PRM; otherwise it +preselects **No Identity**. Select the identity mode the Dossier records, +leave **Guardrails** off unless the reader wants one, then click +**Save**. This creates the server and opens its **Overview** page. **Dual conditional** (Pulse **ambiguous** / **skipped** only, `auto`, -and not tenanted / not forced) — keep both as bullets: +and not tenanted / not forced) — keep both as bullets, each with the +identity selection above: - If is in the catalog: choose **From the catalog**. Find using **Search MCP servers...**, open its catalog entry, - and click **Add**. In **Add to Project**, click **Add to Project**. - After installation, click **Configure MCP settings**. + and click **Add**. In **Add to Project**, select the identity mode, + then click **Add to Project**. After installation, click **Configure + MCP settings**. - If it is not: choose **Hosted remotely**. On **New remote MCP server**, paste `` into **MCP server URL**. Click **Verify - connectivity**, then **Save** after verification succeeds. This opens - the server's **Overview** page. + connectivity**, select the identity mode, then click **Save**. This + opens the server's **Overview** page. Do not describe catalog installation as automatically opening Overview. - +Identity at creation, by Authentication Option: + +- **User Identity** (OAuth): Speakeasy tries to configure the identity + provider and register a client automatically when it saves. When that + works, the server is ready and no credential step remains. When it + cannot (no discoverable metadata, or the provider needs a client + registered by hand), the server is kept **Disabled** and the result + says to finish setup in **Settings > Identity**. Guides whose Dossier + records **Manual** must say this is expected. +- **Service Account** (API key / token): the **Identity** choice shows a + credential format (**Bearer**, **Basic**, or **Manual**). Choose the + format the provider needs and paste the value from External setup into + **Token** (Bearer), **Username** and **Password** (Basic), or **Header + value** (Manual). Speakeasy sends it as the `Authorization` header. +- **No Identity**: nothing further. When the server answered with an + authentication challenge, the dashboard warns that requests may fail; + do not tell readers to ignore that warning. + + ### Connect your credentials {#connect-speakeasy-credentials} -Open the server's **Settings**. The Writer renders only the variant -matching the guide's Authentication Option, names the guide's actual -fields, and cross-links each value to the External-setup step that -produced it. Include provider-specific issuer and endpoint values from -the Dossier where needed, rather than making readers guess. - -For OAuth, under **Authentication**: - -- If authentication is not configured, choose **Use Discovered** when - available; otherwise choose **Configure Manually**. -- If authentication is already configured, find **Connected services**. - If no provider is attached, click **Add provider**. If the intended - provider is already attached, review its existing configuration instead - of attaching it again. Adding another provider is not available for - every server type. Changes require write permission. - -In **Attach Remote Identity Provider**, choose **Select existing** to -reuse the intended project provider, or **Add new** to configure one. -The selector appears when existing providers are available; otherwise -the new-provider form is shown directly. For a new provider, enter the -provider's **Issuer URL** when not already populated, retain the derived -**Slug**, and optionally set **Display name (optional)**. A discovered -issuer starts endpoint discovery automatically. Verify the populated -endpoints; if entering or changing the issuer manually, click **Discover** -under **Endpoints** when available. If discovery is unavailable, use the -documented authorization and token endpoints (and registration endpoint -for DCR). - -Under **Session Client**, reuse the intended existing client with -**Select existing**, or choose **Add new** when that selector is shown. -Reusing a client uses its stored credentials, scopes, and audience; do -not instruct readers to re-enter new-client fields in this branch. -Confirm its read-only configuration matches the guide. If it does not, -choose **Add new** rather than implying the attach sheet can edit a reused -client. For a pre-registered client, check the provider's registered -callback against `{{ gram.oauth.callback_url }}` before attachment; -**Redirect URI** is not displayed when selecting an existing client. Then click **Attach Identity Provider**. The -following credential variants apply to a **new** session client: - -- OAuth with a pre-registered client: set **Client Type** to **Manual**. - Paste the **Client ID** and **Client Secret (optional)** from External - setup, and any provider-required overrides. **Scope (override)** takes - comma-separated scopes. The label does not make a - secret optional when the provider requires it. Before clicking - **Attach Identity Provider**, confirm the displayed **Redirect URI** - matches the callback URL registered during External setup - (`{{ gram.oauth.callback_url }}`). Readers receive the rendered callback - URL, not the literal template key. Successful attachment closes the - sheet, so do not put this check after attachment. -- OAuth with Dynamic Client Registration (DCR): verify the registration - endpoint is populated, then set **Client Type** to **Dynamic Client - Registration (DCR)**. Keep **Token Endpoint Auth Method** at the - discovered default unless the Dossier records a required override. - Leave **Scope (override)** and **Audience (optional)** empty unless - the Dossier records values to enter. Click **Attach Identity Provider**. - The Control Plane registers the OAuth client at the provider's - registration endpoint — there is no **Client ID** or **Client Secret** - to paste, and readers do not register `{{ gram.oauth.callback_url }}` - on the provider for this path. When a client first needs provider - access, complete the provider's browser authorization prompts with the - intended account (exact prompt labels are provider-specific). - -For an API key / token, under **Upstream Headers**, click **Add header**, -enter the **Header name** (for example `Authorization`), leave **Value -source** as **Static value**, paste the value from External setup, check -**Secret**, and click **Save**. Catalog installs may collect these headers -earlier in **Add to Project** under **Upstream headers**; do not add them -a second time. - - +Open the server's **Settings** and find the **Identity** section. The +Writer renders only the variant matching the guide's Authentication +Option, names the guide's actual fields, and cross-links each value to +the External-setup step that produced it. When creation already +configured the identity (Auto-Configure succeeded, or a Service Account +credential was entered), say so and keep only the confirmation and +**Server Availability** steps. Changes require write permission and are +committed with the section's **Save** button. + +For OAuth, select **User Identity**. The provider picker (**Choose an +identity provider**) preselects the provider the server's PRM names; a +provider that does not exist yet is badged **Will be created** and is +created from the upstream's metadata on save. Confirm the preselected +provider matches the Dossier's issuer, or open the picker (**Search +identity providers…**) and choose it. When a provider already exists on +the same host but is the wrong issuer, say which one to pick. + +When discovery is unavailable (the Dossier records no PRM or wrong +metadata), the picker cannot create the provider. Render this route +instead: open the picker, click **Create a custom identity provider**, +which opens **Remote Identity Providers**; click **New Remote Identity +Provider**; enter the Dossier's **Issuer URL** and, under **Endpoints**, +**Authorization Endpoint** and **Token Endpoint** (click **Discover** +first when the issuer publishes metadata); keep the derived **Slug**; +click **Create**. Then use the provider's **Add Client** to create the +client (**Client Type** **Manual**, **Client ID**, **Client Secret +(optional)**, and **Scope (override)**, comma-separated), confirm the +displayed **Redirect URI** matches `{{ gram.oauth.callback_url }}`, and +click **Create**. Return to the server's **Settings > Identity**, select +that provider, choose **Existing client**, and pick the client under +**Client**. + +Under the provider, choose how the server gets a client. The dashboard +preselects **Existing client** when the provider already has one, +otherwise **Auto-Configure** when the provider advertises CIMD or DCR, +otherwise **Manual**. Render the Dossier's choice explicitly, and name +the switch when it differs from the default: + +- **Existing client**: pick it under **Client**. Reusing a client uses + its stored credentials and scopes; do not tell readers to re-enter + them. Choose it only when the Dossier says an existing client matches. +- **Auto-Configure**: Speakeasy registers a new client when you save. + When both are supported, **Advanced > Registration method** offers + **CIMD** (default) and **DCR**; name a method only when the Dossier + records that one fails. There is no **Client ID** or secret to paste, + and readers do not register `{{ gram.oauth.callback_url }}` on the + provider for this path. +- **Manual**: paste the **Client ID** and **Client secret** from External + setup. The secret field's "Optional" placeholder does not make a secret + optional when the provider requires it. Under **Advanced > Scope**, + enter the Dossier's scopes space-separated on one line, and tell + readers not to leave it blank when the PRM advertises more than the + provider app grants. The token endpoint auth method is chosen + automatically from the issuer's metadata; there is no control for it. + This surface does not display the redirect URI, so the External-setup + step that registers `{{ gram.oauth.callback_url }}` carries that check. + +Click **Save**. Replacing a client or switching mode asks for +confirmation (**Save changes**). When a person first uses the server, +the provider's browser authorization prompt appears; exact prompt labels +are provider-specific. + +For an API key / token on an existing server, select **Service Account**, +fill **Service Account credential** as described under creation above, +and click **Save**. Do not add the key under **Custom Headers**; that +area is for other upstream headers. + +When creation left the server **Disabled**, finish with **Settings > +Danger Zone > Server Availability**: turn on the switch (**Enable MCP +server**) so it shows **Enabled**. + + ## The closing pointer diff --git a/guides/asana/meta.yaml b/guides/asana/meta.yaml index 491d5b9..d0ae280 100644 --- a/guides/asana/meta.yaml +++ b/guides/asana/meta.yaml @@ -41,7 +41,7 @@ remotes: locator: https://developers.asana.com/docs/integrating-with-asanas-mcp-server name: Integrating with Asana's MCP Server classification: official - observed_at: "2026-08-06T23:24:28Z" + observed_at: "2026-09-30T21:30:00Z" - source: provider-documentation locator: https://developers.asana.com/docs/using-asanas-mcp-server name: Using Asana's MCP Server @@ -50,11 +50,11 @@ remotes: - source: endpoint-observation locator: https://mcp.asana.com/v2/mcp classification: official - observed_at: "2026-08-06T23:24:28Z" + observed_at: "2026-09-30T21:30:00Z" - source: endpoint-observation locator: https://mcp.asana.com/.well-known/oauth-protected-resource/v2 classification: official - observed_at: "2026-08-06T23:24:28Z" + observed_at: "2026-09-30T21:30:00Z" provenance: - source: pulsemcp locator: com.pulsemcp.mirror/asana-mcp @@ -66,7 +66,7 @@ provenance: locator: https://developers.asana.com/docs/integrating-with-asanas-mcp-server name: Integrating with Asana's MCP Server classification: official - observed_at: "2026-08-06T23:24:28Z" + observed_at: "2026-09-30T21:30:00Z" - source: provider-documentation locator: https://developers.asana.com/docs/using-asanas-mcp-server name: Using Asana's MCP Server @@ -115,17 +115,17 @@ provenance: - source: endpoint-observation locator: https://mcp.asana.com/v2/mcp classification: official - observed_at: "2026-08-06T23:24:28Z" + observed_at: "2026-09-30T21:30:00Z" - source: endpoint-observation locator: https://mcp.asana.com/.well-known/oauth-protected-resource/v2 classification: official - observed_at: "2026-08-06T23:24:28Z" + observed_at: "2026-09-30T21:30:00Z" - source: endpoint-observation locator: https://app.asana.com/.well-known/oauth-authorization-server classification: official - observed_at: "2026-08-06T23:24:28Z" + observed_at: "2026-09-30T21:30:00Z" - source: repository-doctrine locator: doctrine/speakeasy-setup.md name: Speakeasy setup canonical section classification: official - observed_at: "2026-08-06T23:24:28Z" + observed_at: "2026-09-30T21:30:00Z" diff --git a/guides/asana/research.md b/guides/asana/research.md index 5004be9..4ed2ff6 100644 --- a/guides/asana/research.md +++ b/guides/asana/research.md @@ -32,8 +32,8 @@ server is outside this guide. authorization-code and refresh-token grants, `client_secret_post` and `client_secret_basic`, and PKCE method `S256`; it has no dynamic registration endpoint. -- **Scope:** do not configure a scope. The integration guide says MCP - apps do not require specific scopes: use `default` or omit `scope`. +- **Scope:** only `default`. The integration guide says MCP apps do not + require specific scopes: use `default` or omit `scope`. Its Common issues section more narrowly says an explicit `scope` parameter can produce **Invalid scope(s) requested** and should be removed. The live resource metadata advertises `default`. @@ -80,7 +80,7 @@ Values the Speakeasy AI Control Plane needs: Paste `{{ gram.oauth.callback_url }}` into the app's **Redirect URL** setting on the **OAuth** page ({#configure-oauth-redirect}). Asana requires the redirect URL in the app settings to match the URL in the authorization -request exactly. No provider scope value is needed. +request exactly. The only scope value is `default`. Before users connect, set the app's **Distribution method**. For an internal deployment, **Specific workspaces** limits authorization to the @@ -176,51 +176,68 @@ The documented path is Asana main app > profile photo > **Settings** > ## Speakeasy setup -Canonical source: `doctrine/speakeasy-setup.md`, observed -`2026-08-06T23:24:28Z`. +Canonical source: `doctrine/speakeasy-setup.md` (gram main `68b3f78`), +observed `2026-09-30T21:30:00Z`. Per-guide values: -- Remote URL: `https://mcp.asana.com/v2/mcp` -- Transport: `streamable-http` (the add form's **Transport** field is - read-only) -- Authentication Option: OAuth with a manually pre-registered client; - Asana publishes discoverable OAuth metadata -- **Client ID** and **Client secret**: produced in - {#create-mcp-app} -- Redirect URI registered with Asana: `{{ gram.oauth.callback_url }}` in - {#configure-oauth-redirect} -- Provider scopes: none to enter; Asana says omit `scope` for MCP apps -- Further reading: - `https://developers.asana.com/docs/using-asanas-mcp-server` +- Remote URL: `https://mcp.asana.com/v2/mcp` (shared, not tenanted) +- Add-server path: catalog only (**From the catalog**), resolved by the + Speakeasy MCP Catalog record `com.pulsemcp.mirror/asana-mcp`. +- Authentication Option: `oauth-mcp-app`, mapped to **User Identity**. + **Client ID** and **Client secret** come from {#create-mcp-app}; the + redirect `{{ gram.oauth.callback_url }}` is registered at + {#configure-oauth-redirect}. +- Probe outcome (2026-09-30): an unauthenticated JSON-RPC `initialize` POST + returned 401 with `resource_metadata= + "https://mcp.asana.com/.well-known/oauth-protected-resource/v2"`. +- PRM issuer: `https://app.asana.com`. PRM `scopes_supported`: `default`. +- Issuer metadata: `https://app.asana.com/.well-known/oauth-authorization-server` + (issuer matches the PRM byte for byte) advertises no + `registration_endpoint` and no `client_id_metadata_document_supported`. + Neither CIMD nor DCR is available. +- Registration choice: **Manual**. The dashboard defaults to **Manual** here + because nothing automatic is advertised. Creation with **User Identity** + cannot register a client, so the server is kept **Disabled** and the + result points to **Settings > Identity**; the guide says this is expected + and ends with **Server Availability**. +- Scope string for **Advanced > Scope**: `default`. Asana's integration + guide says to use `default` or omit `scope`; its Common issues section + says other scope values produce "Invalid scope(s) requested". A blank + **Scope** would request the PRM list, which is also only `default`. +- Further reading: `https://developers.asana.com/docs/using-asanas-mcp-server` ### Add the server in Speakeasy {#add-server-in-speakeasy} -In the Speakeasy AI Control Plane sidebar, under **Connect**, select -**Sources**, then click **Add Source**. +In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select +**MCP**, then click **Add new** to open **Add MCP server**. Choose **From +the catalog**. On the **MCP Catalog** page, find **Asana** using **Search +MCP servers...**, open its catalog entry, and click **Add**. In **Add to +Project**, select **User Identity** under **Identity** (the dialog +preselects **No Identity** unless the entry supports client registration), +then click **Add to Project**. Finish or **Skip for now** any +**Guardrails** step. Because Asana needs a hand-registered client, the +result says to finish setup in **Settings > Identity** and the server stays +**Disabled**. -Choose **3rd-party server**. On the **MCP Catalog** page, find **Asana** -using **Search MCP servers...**, open it with **View**, and click **Add**. -In the **Add to Project** dialog, click **Add to Project**. This creates -the hosted MCP server and opens its **Overview** page. - -Screenshot note: capture the **Add Source** menu on **Sources**, or -Asana's catalog entry. +Screenshot note: Asana's catalog entry in **Add to Project** with **User +Identity** selected. ### Connect your credentials {#connect-speakeasy-credentials} -From the server's **Overview**, open **Settings**. Under -**Authentication**, use **Use Discovered** when the published Asana -metadata is offered; otherwise click **Configure Manually**. In -**Attach Remote Identity Provider**, set **Client Type** to **Manual**. -The sheet shows **Redirect URI** with a copy button. Its value must match the -`{{ gram.oauth.callback_url }}` value entered in Asana at -{#configure-oauth-redirect}. Paste the **Client ID** and **Client -Secret (optional)** copied at {#create-mcp-app}, then click **Attach -Identity Provider**. - -Screenshot note: capture **Attach Remote Identity Provider** with the -Redirect URI and credential fields visible and all credential values +In the server's **Settings**, open the **Identity** section and select +**User Identity**. In **Choose an identity provider**, confirm +`https://app.asana.com` (badged **Will be created** when new), or choose it +with **Search identity providers…**. Choose **Manual**, paste the **Client +ID** and **Client secret** from {#create-mcp-app} (Asana requires the +secret despite the "Optional" placeholder), enter `default` under +**Advanced > Scope**, and click **Save**. This surface shows no redirect +URI; {#configure-oauth-redirect} carries the callback check. Then open +**Danger Zone > Server Availability** and turn on **Enable MCP server** so +it shows **Enabled**. + +Screenshot note: **Settings > Identity** with **User Identity**, the +`app.asana.com` provider, and **Manual** selected; credential values redacted. Closing pointer: "This guide covers setup only. For anything beyond it — @@ -235,7 +252,7 @@ https://developers.asana.com/docs/using-asanas-mcp-server." workspaces**. - The integration page documents protected-resource metadata at `https://mcp.asana.com/v2/.well-known/oauth-protected-resource`, which - returned 404 this run. The live MCP challenge points to + returned 404 this run and again on 2026-09-30. The live MCP challenge points to `https://mcp.asana.com/.well-known/oauth-protected-resource/v2`, which returned valid metadata naming the exact MCP resource. This discrepancy does not change the browser setup path and should be rechecked during @@ -327,6 +344,11 @@ Sources drawn from: `com.pulsemcp.mirror/asana-mcp` (title **Asana**) — observed `2026-08-06T23:24:28Z`, `source: pulsemcp`. Backs catalog presence and the catalog-only add-server path. -- `doctrine/speakeasy-setup.md` — observed `2026-08-06T23:24:28Z`. Backs the - transcluded Speakeasy-side flow, fixed anchors, exact product labels, - callback-template behavior, and closing-pointer form. +- `doctrine/speakeasy-setup.md` — observed `2026-09-30T21:30:00Z` (gram + main `68b3f78`). Backs the transcluded Speakeasy-side flow, fixed + anchors, exact product labels, callback-template behavior, and + closing-pointer form. +- Live re-probe on `2026-09-30T21:30:00Z` of `https://mcp.asana.com/v2/mcp`, + its PRM, and `https://app.asana.com/.well-known/oauth-authorization-server` + confirmed the 401 challenge, issuer, `default` scope, and absence of + registration and CIMD support recorded above. diff --git a/guides/asana/speakeasy.md b/guides/asana/speakeasy.md index b0974b2..a384fc3 100644 --- a/guides/asana/speakeasy.md +++ b/guides/asana/speakeasy.md @@ -3,62 +3,38 @@ ### Add the server in Speakeasy {#add-server-in-speakeasy} 1. In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select **MCP**. -2. Select **Add new** to open the **Add MCP server** page. +2. Click **Add new** to open **Add MCP server**. 3. Choose **From the catalog**. 4. On the **MCP Catalog** page, find **Asana** using **Search MCP servers...**. -5. Open the **Asana** entry. -6. Select **Add**. -7. In **Add to Project**, select **Add to Project**. +5. Open the **Asana** entry and click **Add**. +6. In the **Add to Project** dialog, under **Identity**, select **User Identity**. The dialog may preselect **No Identity**. +7. Click **Add to Project**. If the dialog offers a **Guardrails** step, finish it or click **Skip for now**. -After installation, select **Configure MCP settings** on the completion screen to open the server, then open **Settings**. +Asana needs a client registered by hand, so the result says to finish setup in **Settings > Identity**, and the server stays **Disabled** for now. This is expected. Click **Finish setup** on the server's result to open its **Settings**. - + ### Connect your credentials {#connect-speakeasy-credentials} -Select **Configure MCP settings** on the completion screen, then open the server’s **Settings**. +In the server's **Settings**, find the **Identity** section. -Under **Authentication**, if unconfigured, select **Use Discovered** when available; otherwise select **Configure Manually**. If configured but no provider is attached, use **Connected services > Add provider**. If the intended provider is already attached, use its existing controls and skip the provider/client creation and attachment steps below; do not add a duplicate. +1. Select **User Identity**. +2. In **Choose an identity provider**, confirm the provider is `https://app.asana.com`. It may be badged **Will be created**. If no provider or a different one is selected, open the picker, search for `app.asana.com` in **Search identity providers…**, and choose it. +3. Under the provider, choose **Manual**. +4. Paste the **Client ID** from [Create the MCP app](external.md#create-mcp-app) into **Client ID**. +5. Paste the **Client secret** from [Create the MCP app](external.md#create-mcp-app) into **Client secret**. Asana requires it, even though the field shows "Optional". +6. Open **Advanced** and enter `default` in **Scope**. Do not add other scopes; Asana rejects them with "Invalid scope(s) requested". +7. Click **Save**. -#### Select the identity provider +This section does not show the redirect URI. Asana accepts the connection only if [Configure the OAuth redirect](external.md#configure-oauth-redirect) registered `{{ gram.oauth.callback_url }}`. -In **Attach Remote Identity Provider**, **Identity Provider** defaults to **Select existing** when project issuers are available. Select the matching provider and skip the new-provider fields below. Otherwise choose **Add new** (or use the new-provider form shown when none exist). +Then turn the server on: -For a new provider only, confirm **Issuer URL**, the auto-derived **Slug**, and **Endpoints**. Discovery runs automatically for a seeded issuer; after typing or changing the URL, select **Discover** only if offered. +1. In **Settings**, open **Danger Zone**. +2. Under **Server Availability**, turn on **Enable MCP server** so it shows **Enabled**. -For a new provider, enter **Issuer URL** `https://app.asana.com` and keep the auto-derived **Slug**. If discovery does not populate **Endpoints**, enter: +Each user sees Asana's authorization prompt the first time they use the server. -Authorization endpoint: - -```text -https://app.asana.com/-/oauth_authorize -``` - -Token endpoint: - -```text -https://app.asana.com/-/oauth_token -``` - - - -#### Select the session client - -Under **Session Client**, choose **Select existing** only for a client whose saved credentials, scopes, and audience match the requirements below; otherwise choose **Add new**. When reusing a matching client, skip directly to **Verify the callback and attach** below. Do not create credentials or register the client again. Otherwise choose **Add new** (or use the new-client form shown when no clients exist) and complete these new-client-only steps: - -Do not enter a scope during this setup. - -1. In **Attach Remote Identity Provider**, set **Client Type** to **Manual**. -1. Paste the **Client ID** saved in [Create the MCP app](external.md#create-mcp-app) into **Client ID**. -1. Paste the **Client secret** saved in [Create the MCP app](external.md#create-mcp-app) into **Client Secret (optional)**. - -#### Verify the callback and attach - -1. Confirm that the callback URL registered with the provider is `{{ gram.oauth.callback_url }}`. For a new manual client, also compare it with the sheet's displayed **Redirect URI**. The existing-client selection does not display that field; check the registered callback in the provider's app settings instead. -2. Click **Attach Identity Provider**. - -For the provider-side callback setting, see [Configure the OAuth redirect](external.md#configure-oauth-redirect). - - + This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Asana's MCP documentation](https://developers.asana.com/docs/using-asanas-mcp-server). diff --git a/guides/atlassian/external.md b/guides/atlassian/external.md index 2c86c43..5973c4a 100644 --- a/guides/atlassian/external.md +++ b/guides/atlassian/external.md @@ -17,14 +17,14 @@ You need no Atlassian-side configuration unless your organization restricts OAut 5. Check whether the allowed domains cover this hosted OAuth callback: ``` - https://app.getgram.ai/mcp/remote_login_callback + {{ gram.oauth.callback_url }} ``` 6. If it is not covered, select **Add domain**. 7. Enter this exact custom domain pattern: ``` - https://app.getgram.ai/mcp/remote_login_callback + {{ gram.oauth.callback_url }} ``` 8. Use the submission control shown in the console. diff --git a/guides/atlassian/meta.yaml b/guides/atlassian/meta.yaml index a364ee3..0730405 100644 --- a/guides/atlassian/meta.yaml +++ b/guides/atlassian/meta.yaml @@ -22,24 +22,24 @@ documentation: speakeasy: speakeasy.md remotes: - id: rovo - url: https://mcp.atlassian.com/v1/mcp/authv2 + url: https://mcp.atlassian.com/v2/mcp transport: streamable-http authentication: - oauth-dcr provenance: - source: provider-documentation - locator: https://support.atlassian.com/atlassian-rovo-mcp-server/docs/getting-started-with-the-atlassian-remote-mcp-server/ - name: Getting started with the Atlassian Rovo MCP Server + locator: https://support.atlassian.com/atlassian-ai-gateway/docs/get-started-with-the-atlassian-remote-mcp-server/ + name: Get started with the Atlassian MCP server classification: official - observed_at: "2026-08-07T21:49:51Z" + observed_at: "2026-09-30T00:00:00Z" - source: endpoint-observation - locator: https://mcp.atlassian.com/v1/mcp/authv2 + locator: https://mcp.atlassian.com/v2/mcp classification: official - observed_at: "2026-08-07T21:49:51Z" + observed_at: "2026-09-30T00:00:00Z" - source: endpoint-observation - locator: https://mcp.atlassian.com/.well-known/oauth-protected-resource/v1/mcp/authv2 + locator: https://mcp.atlassian.com/.well-known/oauth-protected-resource/v2/mcp classification: official - observed_at: "2026-08-07T21:49:51Z" + observed_at: "2026-09-30T00:00:00Z" provenance: - source: pulsemcp locator: query:atlassian @@ -54,82 +54,82 @@ provenance: status: hosted callback confirmed; hosted outbound IP ranges unknown observed_at: "2026-08-07T21:49:51Z" - source: provider-documentation - locator: https://support.atlassian.com/atlassian-rovo-mcp-server/docs/getting-started-with-the-atlassian-remote-mcp-server/ - name: Getting started with the Atlassian Rovo MCP Server + locator: https://support.atlassian.com/atlassian-ai-gateway/docs/get-started-with-the-atlassian-remote-mcp-server/ + name: Get started with the Atlassian MCP server classification: official - observed_at: "2026-08-07T21:49:51Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation - locator: https://support.atlassian.com/atlassian-rovo-mcp-server/docs/setting-up-clients/ - name: Setting up clients + locator: https://support.atlassian.com/atlassian-ai-gateway/docs/set-up-clients/ + name: Set up clients classification: official - observed_at: "2026-08-07T21:49:51Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation - locator: https://support.atlassian.com/atlassian-rovo-mcp-server/docs/authentication-and-authorization/ + locator: https://support.atlassian.com/atlassian-ai-gateway/docs/authentication-and-authorization/ name: Authentication and authorization classification: official - observed_at: "2026-08-07T21:49:51Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation - locator: https://support.atlassian.com/atlassian-rovo-mcp-server/docs/configuring-oauth-2-1/ - name: Configuring OAuth 2.1 + locator: https://support.atlassian.com/atlassian-ai-gateway/docs/configure-oauth-2-1/ + name: Configure OAuth 2.1 classification: official - observed_at: "2026-08-07T21:49:51Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation - locator: https://support.atlassian.com/atlassian-rovo-mcp-server/docs/configuring-authentication-via-api-token/ - name: Configuring authentication via API token + locator: https://support.atlassian.com/atlassian-ai-gateway/docs/configure-authentication-via-api-token/ + name: Configure authentication via API token classification: official - observed_at: "2026-08-07T21:49:51Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation - locator: https://support.atlassian.com/atlassian-rovo-mcp-server/docs/using-with-other-supported-mcp-clients/ - name: Using with other supported MCP clients + locator: https://support.atlassian.com/atlassian-ai-gateway/docs/use-atlassian-rovo-mcp-server/ + name: Use Atlassian Rovo MCP Server classification: official - observed_at: "2026-08-07T21:49:51Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation - locator: https://support.atlassian.com/security-and-access-policies/docs/control-atlassian-rovo-mcp-server-settings/ + locator: https://support.atlassian.com/security-and-access-policies/docs/control-atlassian-mcp-server-settings/ name: Control Atlassian Rovo MCP server settings classification: official - observed_at: "2026-08-07T21:49:51Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation locator: https://support.atlassian.com/security-and-access-policies/docs/specify-ip-addresses-for-product-access/ name: Specify IP addresses for product access classification: official - observed_at: "2026-08-07T21:49:51Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation - locator: https://support.atlassian.com/security-and-access-policies/docs/available-atlassian-rovo-mcp-server-domains/ + locator: https://support.atlassian.com/security-and-access-policies/docs/available-atlassian-mcp-server-domains/ name: Available Atlassian Rovo MCP server domains classification: official - observed_at: "2026-08-07T21:49:51Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation - locator: https://support.atlassian.com/atlassian-rovo-mcp-server/docs/troubleshooting-and-verifying-your-setup/ - name: Troubleshooting and verifying your setup + locator: https://support.atlassian.com/atlassian-ai-gateway/docs/troubleshoot-and-verify-your-setup/ + name: Troubleshoot and verify your setup classification: official - observed_at: "2026-08-07T21:49:51Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-marketing locator: https://www.atlassian.com/platform/remote-mcp-server name: Atlassian Rovo MCP server classification: official - observed_at: "2026-08-07T21:49:51Z" + observed_at: "2026-09-30T00:00:00Z" - source: endpoint-observation - locator: https://mcp.atlassian.com/v1/mcp/authv2 + locator: https://mcp.atlassian.com/v2/mcp classification: official - observed_at: "2026-08-07T21:49:51Z" + observed_at: "2026-09-30T00:00:00Z" - source: endpoint-observation - locator: https://mcp.atlassian.com/.well-known/oauth-protected-resource/v1/mcp/authv2 + locator: https://mcp.atlassian.com/.well-known/oauth-protected-resource/v2/mcp classification: official - observed_at: "2026-08-07T21:49:51Z" + observed_at: "2026-09-30T00:00:00Z" - source: endpoint-observation - locator: protected-resource-discovered authorization-server metadata - name: Atlassian authorization-server metadata with DCR registration endpoint + locator: https://auth.atlassian.com/.well-known/oauth-authorization-server/VCeDsk8ZHncYF1g234fKtc4lNipbBhu3 + name: Atlassian path-issuer authorization-server metadata (https://auth.atlassian.com/VCeDsk8ZHncYF1g234fKtc4lNipbBhu3) classification: official - status: authorization, token, and registration endpoints verified from metadata; empty DCR POST returned HTTP 400 - observed_at: "2026-08-07T21:49:51Z" + status: CIMD supported and registration endpoint advertised; anonymous DCR registration returned HTTP 201 + observed_at: "2026-09-30T00:00:00Z" - source: endpoint-observation locator: https://auth.atlassian.com/.well-known/oauth-authorization-server name: Atlassian base authorization-server metadata classification: official - status: stable base issuer plus authorization and token endpoints verified; no registration endpoint advertised here - observed_at: "2026-08-07T21:49:51Z" + status: base issuer advertises CIMD but no registration endpoint; not the issuer the PRM names + observed_at: "2026-09-30T00:00:00Z" - source: repository-doctrine locator: doctrine/speakeasy-setup.md name: Speakeasy setup canonical section classification: official - observed_at: "2026-08-07T21:49:51Z" + observed_at: "2026-09-30T00:00:00Z" diff --git a/guides/atlassian/research.md b/guides/atlassian/research.md index f59212a..fa15347 100644 --- a/guides/atlassian/research.md +++ b/guides/atlassian/research.md @@ -1,21 +1,39 @@ --- research_version: 1 slug: atlassian -researched_at: "2026-08-07T21:49:51Z" +researched_at: "2026-09-30T00:00:00Z" --- # Atlassian — Research Dossier Source ruling for this Guide: the Atlassian Support collection for the -Atlassian Rovo MCP Server is the primary setup source. Its current getting -started page specifies the `/v1/mcp/authv2` endpoint. The security and access -policies collection supplies organization-admin controls. Live endpoint and -OAuth metadata corroborate the endpoint and establish that Dynamic Client -Registration (DCR) is available. The marketing site is corroborative only. +Atlassian MCP server (now under `support.atlassian.com/atlassian-ai-gateway/`; +the old `atlassian-rovo-mcp-server` paths redirect there) is the primary setup +source. Its current getting started page specifies the v2 endpoint +`https://mcp.atlassian.com/v2/mcp`. The security and access policies +collection supplies organization-admin controls. Live endpoint and OAuth +metadata corroborate the endpoint and establish that the discovered issuer +supports Client ID Metadata Documents (CIMD) and Dynamic Client Registration +(DCR). The marketing site is corroborative only. Re-verified +`2026-09-30`. ## Server facts -- **Remote URL:** `https://mcp.atlassian.com/v1/mcp/authv2`. +- **Remote URL:** `https://mcp.atlassian.com/v2/mcp`. Atlassian's getting + started page lists it under "Other MCP-compatible clients" and in every + client example. The previous `https://mcp.atlassian.com/v1/mcp/authv2` + endpoint is v1; Atlassian says: "On March 1, 2027 any existing utilization + of v1 will automatically start to expose and utilize v2 tools. Any + incompatible clients will need to clear cached clientIds or .well-known + credentials to support continued authentication." Servers added from the + earlier version of this Guide on v1 may need their identity re-created + after that date. +- **Gateway override (not rendered):** the same page says "If you're + utilising an MCP gateway, you may want to expose all tools available in + Atlassian MCP, rather than utilising the discovery and execute methods", + using `https://mcp.atlassian.com/v2/mcp?tools=all`. Whether the Speakeasy + AI Control Plane should use this override is an open question; the Guide + renders the base URL. - **Transport:** `streamable-http`. Atlassian's current examples configure the URL with HTTP transport. The older SSE endpoint `https://mcp.atlassian.com/v1/sse` is unsupported after June 30, 2026. @@ -23,24 +41,29 @@ Registration (DCR) is available. The marketing site is corroborative only. Registration. OAuth is Atlassian's primary and recommended mechanism for an interactive user-driven connection. No Client ID or Client Secret is created in Atlassian Administration for this option. -- **OAuth discovery:** an unauthenticated request to the remote returns HTTP - 401 and names protected-resource metadata at - `https://mcp.atlassian.com/.well-known/oauth-protected-resource/v1/mcp/authv2`. - That document identifies the resource, supported scopes, bearer-header use, - and an Atlassian authorization-server metadata URL. Following that discovery - chain advertises authorization, token, and dynamic-registration endpoints, - authorization-code and refresh-token grants, PKCE `S256`, and token endpoint - authentication method `none` among its methods. Live checks verified - `https://auth.atlassian.com/authorize`, - `https://auth.atlassian.com/oauth/token`, and the advertised DCR endpoint; - an empty POST to the DCR endpoint returned HTTP 400 rather than 404. These - endpoints are metadata observations, not guessed URL constructions. The - Speakeasy AI Control Plane can therefore use protected-resource discovery - and DCR without a pasted issuer. The stable issuer/base auth URL is - `https://auth.atlassian.com`; do not present the opaque authorization-server - identifier as the base auth URL. Because the base issuer's own metadata does - not advertise registration, prefer **Use Discovered** rather than attempting - to reconstruct DCR from the base issuer alone. +- **OAuth discovery (probed 2026-09-30):** an unauthenticated JSON-RPC + `initialize` POST to `https://mcp.atlassian.com/v2/mcp` returns HTTP 401 + with `WWW-Authenticate: Bearer + resource_metadata="https://mcp.atlassian.com/.well-known/oauth-protected-resource/v2/mcp"`. + That PRM names resource `https://mcp.atlassian.com/v2/mcp` and one + authorization server, the path issuer + `https://auth.atlassian.com/VCeDsk8ZHncYF1g234fKtc4lNipbBhu3`. Its + `scopes_supported` lists 38 scopes (`read:me`, `read:account`, + `offline_access`, `email`, and `*:agent-interface` / `*:twg` scopes across + Jira, Confluence, Rovo, code, Goals, Projects, Bitbucket, Loom, Talent, + Jira Align, Teams, artifacts, capacity planning, Focus, and Assets). The + path issuer's metadata + (`https://auth.atlassian.com/.well-known/oauth-authorization-server/VCeDsk8ZHncYF1g234fKtc4lNipbBhu3`) + advertises `client_id_metadata_document_supported: true`, registration + endpoint + `https://auth.atlassian.com/VCeDsk8ZHncYF1g234fKtc4lNipbBhu3/dcr/register`, + authorization endpoint `https://auth.atlassian.com/authorize`, token + endpoint `https://auth.atlassian.com/oauth/token`, and token endpoint auth + methods `none`, `client_secret_post`, `client_secret_basic`, and + `private_key_jwt`. An anonymous DCR registration with the hosted callback + as redirect URI returned HTTP 201 with a `client_id`. The base issuer + `https://auth.atlassian.com` also advertises CIMD but no + `registration_endpoint`; it is not the issuer the PRM names. - **Access model:** after setup, each user signs in to Atlassian, authorizes the client for an Atlassian Cloud site, and enables the intended Atlassian apps. Calls remain constrained by that user's product access and permissions. @@ -66,21 +89,21 @@ Registration (DCR) is available. The marketing site is corroborative only. - **Speakeasy MCP Catalog:** unresolved for the current Rovo remote MCP Server. The operator's query `atlassian` produced one non-exact hit and no exact title/name match, so both add-server branches remain conditional; use - the Custom remote server path unless a catalog result clearly identifies the - current Rovo remote endpoint above. + the **Hosted remotely** path unless a catalog result clearly identifies the + current v2 remote endpoint above. ## Credential flow The selected Authentication Option does not require an Atlassian developer app or pre-created credentials. The Speakeasy AI Control Plane follows the remote's -protected-resource metadata and dynamically registers its session client. Use -**Use Discovered** so that chain supplies Atlassian's verified DCR endpoint; do -not construct or substitute a registration endpoint. The stable issuer/base -auth URL is `https://auth.atlassian.com`, but its base metadata alone does not -advertise DCR. DCR registers the hosted callback URL -`https://app.getgram.ai/mcp/remote_login_callback`; the reader does not create -an OAuth app or paste `{{ gram.oauth.callback_url }}` into an Atlassian app -registration. +protected-resource metadata to the path issuer +`https://auth.atlassian.com/VCeDsk8ZHncYF1g234fKtc4lNipbBhu3` and registers +its own client automatically (**Auto-Configure**, CIMD by default, DCR also +advertised). Do not construct or substitute a registration endpoint, and do +not use the base issuer `https://auth.atlassian.com` in its place. The +registered client uses the hosted callback `{{ gram.oauth.callback_url }}`; +the reader does not create an OAuth app or paste the callback into an +Atlassian app registration. At first use, the intended user completes Atlassian's browser authorization flow, grants access to the relevant Atlassian Cloud site, and enables the @@ -91,7 +114,7 @@ Before connecting, an organization admin must ensure that the hosted OAuth callback is allowed if it is not already covered by the organization's Atlassian-supported or custom domain rules. Atlassian's current published supported-domain list does not name the Speakeasy AI Control Plane. Add the -exact hosted callback `https://app.getgram.ai/mcp/remote_login_callback` as a +exact hosted callback `{{ gram.oauth.callback_url }}` as a custom domain pattern when required; it includes the protocol, valid host, and callback path Atlassian's documented pattern rules accept. @@ -112,7 +135,7 @@ server**. - Select **Rovo**, then **Rovo MCP server**. - Check whether the allowed domain rules already cover the hosted callback. If they do not, select **Add domain** and add this exact custom domain pattern: - `https://app.getgram.ai/mcp/remote_login_callback`. Atlassian requires a + `{{ gram.oauth.callback_url }}`. Atlassian requires a protocol and a valid host; this value also limits the rule to the callback path. The public provider docs do not name the input field or final save-button label; after entering the pattern, use the submission control @@ -144,81 +167,104 @@ Guide does not prescribe clicks. ## Speakeasy setup -Canonical source: `doctrine/speakeasy-setup.md`, observed -`2026-08-07T21:49:51Z`. +Canonical source: `doctrine/speakeasy-setup.md` (gram `main` +`68b3f78`), observed `2026-09-30`. Per-guide values: -- Remote URL: `https://mcp.atlassian.com/v1/mcp/authv2` -- Transport: `streamable-http` (the add form's **Transport** field is - read-only) -- Authentication Option: OAuth with DCR; protected-resource metadata makes - discovery available, and there are no provider credentials. Use **Use - Discovered**. The issuer/base auth URL is `https://auth.atlassian.com`, while - DCR availability and the registration endpoint come from the verified - protected-resource discovery chain, not from a constructed URL -- External governance step when required: {#allow-speakeasy-domain} -- Scope override: leave empty; discovery advertises the server's supported - scopes and Atlassian's authorization screen determines the granted apps and - scopes +- Remote URL: `https://mcp.atlassian.com/v2/mcp` (shared public URL, not + tenanted) +- `speakeasy_add_server`: `auto`; Pulse catalog presence ambiguous, so both + add-server bullets are kept, with the catalog bullet gated on a result + that clearly identifies the v2 URL +- Authentication Option: OAuth, no provider credentials. Identity mode: + **User Identity** +- Probe outcome: 401 with a `resource_metadata` challenge, so **Hosted + remotely** preselects **User Identity** after **Verify connectivity** +- PRM issuer: `https://auth.atlassian.com/VCeDsk8ZHncYF1g234fKtc4lNipbBhu3`. + A provider already in the project for the base issuer + `https://auth.atlassian.com` is the wrong provider; the Guide tells readers + to choose the one for the path issuer +- CIMD / DCR: the path issuer advertises both; anonymous DCR returned 201. + CIMD was not exercised end to end, so no registration method is named +- Registration choice: **Auto-Configure** (dashboard default); creation + normally configures the identity, so the credential section is a + confirmation plus the fallback +- Scope: none entered. **Auto-Configure** has no **Scope** control; the PRM + advertises 38 scopes and Atlassian's consent screen determines the granted + apps +- External credential fields: none. External governance step when required: + {#allow-speakeasy-domain} +- Server Availability: rendered as a conditional final step when creation + left the server **Disabled** - Further reading: - `https://support.atlassian.com/atlassian-rovo-mcp-server/docs/getting-started-with-the-atlassian-remote-mcp-server/` + `https://support.atlassian.com/atlassian-ai-gateway/docs/get-started-with-the-atlassian-remote-mcp-server/` ### Add the server in Speakeasy {#add-server-in-speakeasy} -In the Speakeasy AI Control Plane sidebar, under **Connect**, select -**Sources**, then click **Add Source**. +In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select +**MCP**, then click **Add new** to open **Add MCP server**. -- If an **Atlassian Rovo** result in the catalog clearly identifies the current - remote URL above: choose **3rd-party server**. On the **MCP Catalog** page, - find Atlassian using **Search MCP servers...**, open that result with - **View**, and click **Add**. In **Add to Project**, click **Add to Project**. -- If no clearly current Rovo result appears: choose **Custom remote server**. - On **Add a custom remote MCP server**, paste - `https://mcp.atlassian.com/v1/mcp/authv2` into **Remote MCP server URL** and - click **Add server**. +- If an **Atlassian Rovo** result in the catalog clearly identifies the + remote URL above: choose **From the catalog**. Find Atlassian using + **Search MCP servers...**, open its catalog entry, and click **Add**. In + **Add to Project**, select **User Identity**, then click **Add to + Project** (click **Skip for now** if a **Guardrails** step appears). After + **Server added successfully**, click **Configure MCP settings**. +- If it is not: choose **Hosted remotely**. On **New remote MCP server**, + paste `https://mcp.atlassian.com/v2/mcp` into **MCP server URL**. Click + **Verify connectivity**, keep the preselected **User Identity**, then + click **Save**. -Either branch creates the hosted MCP server and opens its **Overview** page. +On save, Speakeasy configures the identity provider and registers a client +automatically. When that cannot complete, the server is kept **Disabled** +and the result says to finish setup in **Settings > Identity**. -Screenshot note: capture the **Add Source** menu open on the **Sources** page, -or the exact current Atlassian Rovo catalog result if one is present. +Screenshot note: the **Add MCP server** choices, or the Atlassian catalog +entry with the **Identity** choice. ### Connect your credentials {#connect-speakeasy-credentials} -From the server's **Overview**, open **Settings**. Under **Authentication**, use -**Use Discovered**. In **Attach Remote Identity Provider**, confirm the -issuer/base auth URL is `https://auth.atlassian.com`. Keep the auto-derived -**Slug** and **Display name (optional)**. Under **Endpoints**, click **Discover** -so the authorization, token, and registration endpoints fill from Atlassian's -discovery chain. Under **Session Client**, keep **Client Type** set to **Dynamic -Client Registration (DCR)** and keep the discovered **Token Endpoint Auth -Method**. Leave **Scope -(override)** and **Audience (optional)** empty. Click **Attach Identity -Provider**. - -There is no **Client ID** or **Client Secret** to paste. When first prompted for -provider access, sign in with the intended Atlassian account, authorize the -intended Atlassian Cloud site, and enable the intended Atlassian apps. If the -flow is rejected by organization policy, complete {#allow-speakeasy-domain} -and retry. - -Screenshot note: capture **Attach Remote Identity Provider** after discovery -with DCR selected and no secret values visible. +Open the server's **Settings** and find the **Identity** section. When +creation already configured the identity, confirm **User Identity**, the +Atlassian provider, and **Auto-Configure**, and keep only the Server +Availability step. Otherwise: select **User Identity**; under **Choose an +identity provider**, confirm the preselected provider is the path issuer +`https://auth.atlassian.com/VCeDsk8ZHncYF1g234fKtc4lNipbBhu3` (a new one is +badged **Will be created**), or open the picker (**Search identity +providers…**) and choose it when a base `auth.atlassian.com` provider is +preselected; keep **Auto-Configure**; click **Save**. There is no **Client +ID** or secret to paste. If the server shows **Disabled**, open **Settings > +Danger Zone > Server Availability** and turn on **Enable MCP server** so it +shows **Enabled**. + +When first prompted for provider access, sign in with the intended Atlassian +account, authorize the intended Atlassian Cloud site, and enable the intended +Atlassian apps. If the flow is rejected by organization policy, complete +{#allow-speakeasy-domain} and retry. + +Screenshot note: **Settings > Identity** with **User Identity** selected, +the Atlassian provider, and **Auto-Configure**; values redacted. Closing pointer: "This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see Atlassian's MCP documentation at -https://support.atlassian.com/atlassian-rovo-mcp-server/docs/getting-started-with-the-atlassian-remote-mcp-server/." +https://support.atlassian.com/atlassian-ai-gateway/docs/get-started-with-the-atlassian-remote-mcp-server/." ## Open questions - Does the Speakeasy MCP Catalog contain an exact result for the current - Atlassian Rovo remote MCP Server? The supplied lookup was ambiguous, so both + Atlassian v2 remote MCP Server? The supplied lookup was ambiguous, so both add-server paths remain conditional. -- If **Use Discovered** is unavailable, can the current manual sheet retain the - protected-resource-discovered registration endpoint while showing - `https://auth.atlassian.com` as the issuer/base auth URL? The base issuer's - metadata does not itself advertise registration, so this Guide does not - claim a manual fallback that public sources cannot complete. +- Should the Speakeasy AI Control Plane use Atlassian's gateway override + `https://mcp.atlassian.com/v2/mcp?tools=all` (flat tool list) instead of + the base URL (discovery and execute tools)? Atlassian suggests it for MCP + gateways; this is a product decision. +- Does CIMD registration against the path issuer complete end to end? Only + DCR was exercised (anonymous registration returned 201). If CIMD fails, + the Guide should name **DCR** under **Advanced > Registration method**. +- When a base `https://auth.atlassian.com` provider already exists in the + project, does the picker still offer the path issuer as **Will be + created**? The rendered picker was not spot-checked. ## Provenance @@ -235,7 +281,7 @@ Source inventory from the sweep: identified the official remote MCP page; the page corroborates the product but does not add setup details. - **Live service metadata — `mcp.atlassian.com` and `auth.atlassian.com`:** used - to validate the endpoint, OAuth resource discovery, and DCR support. + to validate the endpoint, OAuth resource discovery, and CIMD/DCR support. - **Workflow operator observations:** used for Speakeasy-specific facts that Atlassian cannot publish: the hosted callback URL and the ambiguous current catalog lookup. @@ -244,71 +290,75 @@ Sources drawn from: - Workflow operator notes for assignment `atlassian` — observed `2026-08-07T21:49:51Z`. Back the hosted callback URL - `https://app.getgram.ai/mcp/remote_login_callback`, the unresolved current + (`{{ gram.oauth.callback_url }}`), the unresolved current catalog presence, and the absence of published exact hosted outbound IP ranges. -- `https://support.atlassian.com/atlassian-rovo-mcp-server/docs/getting-started-with-the-atlassian-remote-mcp-server/` - ("Getting started with the Atlassian Rovo MCP Server") — observed - `2026-08-07T21:49:51Z`. Backs current remote URL, broad MCP-client support, +- `https://support.atlassian.com/atlassian-ai-gateway/docs/get-started-with-the-atlassian-remote-mcp-server/` + ("Get started with the Atlassian MCP server") — observed + `2026-09-30`. Backs the v2 remote URL, the v1-to-v2 cutover on March 1, 2027, the MCP gateway `?tools=all` override, broad MCP-client support, OAuth 2.1 primary authentication, API-token availability, sign-in flow, and permissions warning. -- `https://support.atlassian.com/atlassian-rovo-mcp-server/docs/setting-up-clients/` - ("Setting up clients") — observed `2026-08-07T21:49:51Z`. Backs standing +- `https://support.atlassian.com/atlassian-ai-gateway/docs/set-up-clients/` + ("Set up clients") — observed `2026-09-30`. Backs standing Cloud-site, product-access, browser, and OAuth requirements; API-token admin gate; and the legacy SSE retirement date. -- `https://support.atlassian.com/atlassian-rovo-mcp-server/docs/authentication-and-authorization/` - ("Authentication and authorization") — observed `2026-08-07T21:49:51Z`. +- `https://support.atlassian.com/atlassian-ai-gateway/docs/authentication-and-authorization/` + ("Authentication and authorization") — observed `2026-09-30`. Backs OAuth recommendation, interactive consent, API-token alternatives, header methods, and organization-admin enablement. -- `https://support.atlassian.com/atlassian-rovo-mcp-server/docs/configuring-oauth-2-1/` - ("Configuring OAuth 2.1") — observed `2026-08-07T21:49:51Z`. Backs OAuth +- `https://support.atlassian.com/atlassian-ai-gateway/docs/configure-oauth-2-1/` + ("Configure OAuth 2.1") — observed `2026-09-30`. Backs OAuth bearer presentation, app/scope consent, site binding, permission enforcement, and first-connect OAuth recovery. -- `https://support.atlassian.com/atlassian-rovo-mcp-server/docs/configuring-authentication-via-api-token/` - ("Configuring authentication via API token") — observed - `2026-08-07T21:49:51Z`. Backs excluded Basic/Bearer alternatives, their +- `https://support.atlassian.com/atlassian-ai-gateway/docs/configure-authentication-via-api-token/` + ("Configure authentication via API token") — observed + `2026-09-30`. Backs excluded Basic/Bearer alternatives, their non-interactive purpose, admin gate, and reduced tool availability. -- `https://support.atlassian.com/atlassian-rovo-mcp-server/docs/using-with-other-supported-mcp-clients/` - ("Using with other supported MCP clients") — observed - `2026-08-07T21:49:51Z`. Backs custom-client requirements, OAuth login, site +- `https://support.atlassian.com/atlassian-ai-gateway/docs/use-atlassian-rovo-mcp-server/` + ("Use Atlassian Rovo MCP Server") — observed + `2026-09-30`. Backs custom-client requirements, OAuth login, site authorization, app enablement, and the possible app-management-policy gate. -- `https://support.atlassian.com/security-and-access-policies/docs/control-atlassian-rovo-mcp-server-settings/` +- `https://support.atlassian.com/security-and-access-policies/docs/control-atlassian-mcp-server-settings/` ("Control Atlassian Rovo MCP server settings") — observed - `2026-08-07T21:49:51Z`. Backs **Rovo** > **Rovo MCP server**, **Add domain**, + `2026-09-30`. Backs **Rovo** > **Rovo MCP server**, **Add domain**, **Allow Atlassian supported domains**, IP-allowlist behavior, `*.atlassian.net` egress, and the **API token** toggle. - `https://support.atlassian.com/security-and-access-policies/docs/specify-ip-addresses-for-product-access/` ("Specify IP addresses for product access") — observed - `2026-08-07T21:49:51Z`. Backs the Atlassian Administration URL, **Security** > + `2026-09-30`. Backs the Atlassian Administration URL, **Security** > **IP allowlists** route, **Create IP allowlist**, source-address/CIDR entry, and selection of the sites and apps to which an allowlist applies. -- `https://support.atlassian.com/security-and-access-policies/docs/available-atlassian-rovo-mcp-server-domains/` +- `https://support.atlassian.com/security-and-access-policies/docs/available-atlassian-mcp-server-domains/` ("Available Atlassian Rovo MCP server domains") — observed - `2026-08-07T21:49:51Z`. Backs the published default-domain list, domain-rule + `2026-09-30`. Backs the published default-domain list, domain-rule purpose, and protocol/host/pattern requirements; Speakeasy is not named. -- `https://support.atlassian.com/atlassian-rovo-mcp-server/docs/troubleshooting-and-verifying-your-setup/` - ("Troubleshooting and verifying your setup") — observed - `2026-08-07T21:49:51Z`. Backs first-connect symptoms and recovery for access, +- `https://support.atlassian.com/atlassian-ai-gateway/docs/troubleshoot-and-verify-your-setup/` + ("Troubleshoot and verify your setup") — observed + `2026-09-30`. Backs first-connect symptoms and recovery for access, scopes, redirects, browser pop-ups, and network filters. - `https://www.atlassian.com/platform/remote-mcp-server` — observed - `2026-08-07T21:49:51Z`. Corroborates that Atlassian operates the Rovo MCP + `2026-09-30`. Corroborates that Atlassian operates the Rovo MCP Server for external AI clients. -- `https://mcp.atlassian.com/v1/mcp/authv2` — direct unauthenticated endpoint - observation at `2026-08-07T21:49:51Z`. Returned HTTP 401 with a Bearer - challenge naming the protected-resource metadata URL. -- `https://mcp.atlassian.com/.well-known/oauth-protected-resource/v1/mcp/authv2` - — observed `2026-08-07T21:49:51Z`. Backs exact resource URL, authorization - issuer, scopes, bearer header method, and provider documentation URL. -- Atlassian authorization-server metadata discovered from the protected - resource — observed `2026-08-07T21:49:51Z`. Backs the exact authorization, - token, and dynamic-registration endpoints, grants, PKCE, and token endpoint - methods. The opaque discovery locator is intentionally not presented as the - user-entered issuer/base auth URL. +- `https://mcp.atlassian.com/v2/mcp` — direct unauthenticated JSON-RPC + `initialize` POST at `2026-09-30`. Returned HTTP 401 with a Bearer + challenge naming the protected-resource metadata URL. (The v1 + `https://mcp.atlassian.com/v1/mcp/authv2` still returns 401 with its own + PRM; not used.) +- `https://mcp.atlassian.com/.well-known/oauth-protected-resource/v2/mcp` + — observed `2026-09-30`. Backs exact resource URL, the path authorization + issuer, the 38 advertised scopes, bearer header method, and resource + documentation URL. +- `https://auth.atlassian.com/.well-known/oauth-authorization-server/VCeDsk8ZHncYF1g234fKtc4lNipbBhu3` + — observed `2026-09-30`. Backs the path issuer, CIMD support, the + registration endpoint, authorization and token endpoints, and token + endpoint auth methods. An anonymous DCR POST to the registration endpoint + returned 201 with a `client_id`. - `https://auth.atlassian.com/.well-known/oauth-authorization-server` — observed - `2026-08-07T21:49:51Z`. Backs the stable base issuer and exact authorization - and token endpoints. This base document does not advertise registration; - DCR support is established only by the protected-resource discovery chain. -- `doctrine/speakeasy-setup.md` — observed `2026-08-07T21:49:51Z`. Backs the - transcluded Speakeasy flow, fixed anchors, exact product labels, DCR behavior, - dual conditional under ambiguous catalog presence, and closing-pointer form. + `2026-09-30`. Backs the base issuer: CIMD advertised, no registration + endpoint. Not the issuer the PRM names. +- `doctrine/speakeasy-setup.md` (gram `main` `68b3f78`) — observed + `2026-09-30`. Backs the transcluded Speakeasy flow, fixed anchors, exact + product labels, the **Identity** section, **Auto-Configure**, Server + Availability, dual conditional under ambiguous catalog presence, and + closing-pointer form. diff --git a/guides/atlassian/speakeasy.md b/guides/atlassian/speakeasy.md index df01446..112e1e2 100644 --- a/guides/atlassian/speakeasy.md +++ b/guides/atlassian/speakeasy.md @@ -2,68 +2,53 @@ ### Add the server in Speakeasy {#add-server-in-speakeasy} -1. In the Speakeasy AI Control Plane sidebar, find **MCP Gateway** and select **MCP**. -2. Click **Add new** to open the **Add MCP server** page. +1. In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select **MCP**. +2. Click **Add new** to open **Add MCP server**. -If an **Atlassian Rovo** result in the catalog clearly identifies the current remote URL shown below: +If an **Atlassian Rovo** result in the catalog clearly identifies the remote URL shown below: 1. Choose **From the catalog**. 2. On the **MCP Catalog** page, enter `Atlassian` in **Search MCP servers...**. 3. Open that result. 4. Click **Add**. -5. In **Add to Project**, click **Add to Project**. +5. In **Add to Project**, under **Identity**, select **User Identity**. +6. Click **Add to Project**. If the dialog offers a **Guardrails** step, click **Skip for now**. +7. After **Server added successfully**, click **Configure MCP settings**. -If no clearly current **Atlassian Rovo** result appears in the catalog, use the custom remote path: +If no such result appears, use the custom remote path: 1. Choose **Hosted remotely**. 2. On **New remote MCP server**, paste this value into **MCP server URL**: ``` - https://mcp.atlassian.com/v1/mcp/authv2 + https://mcp.atlassian.com/v2/mcp ``` -3. Click **Verify connectivity**, then **Save**. +3. Click **Verify connectivity**. +4. Under **Identity**, keep **User Identity** selected. +5. Click **Save**. -After catalog installation, select **Configure MCP settings** on the completion screen to open the server, then open **Settings**. Saving a custom remote server opens **Overview**; open **Settings** from there. +On save, Speakeasy discovers Atlassian's identity provider and registers a client automatically. When that works, the server is ready. When it cannot, the server is kept **Disabled** and the result says to finish setup in **Settings > Identity**. - + ### Connect your credentials {#connect-speakeasy-credentials} -Open the server’s **Settings**. +Open the server's **Settings** and find the **Identity** section. If creation already configured the identity, **User Identity** is selected with the Atlassian provider and **Auto-Configure**; skip to step 6. -Under **Authentication**, if unconfigured, select **Use Discovered** when available; otherwise select **Configure Manually**. If configured but no provider is attached, use **Connected services > Add provider**. If the intended provider is already attached, use its existing controls and skip the provider/client creation and attachment steps below; do not add a duplicate. - -#### Select the identity provider - -In **Attach Remote Identity Provider**, **Identity Provider** defaults to **Select existing** when project issuers are available. Select the matching provider and skip the new-provider fields below. Otherwise choose **Add new** (or use the new-provider form shown when none exist). - -For a new provider only, confirm **Issuer URL**, the auto-derived **Slug**, and **Endpoints**. Discovery runs automatically for a seeded issuer; after typing or changing the URL, select **Discover** only if offered. - -1. In **Attach Remote Identity Provider**, confirm that the issuer/base auth URL is: +1. Select **User Identity**. +2. Under **Choose an identity provider**, confirm the preselected provider uses this issuer. A provider that does not exist yet shows **Will be created**. ``` - https://auth.atlassian.com + https://auth.atlassian.com/VCeDsk8ZHncYF1g234fKtc4lNipbBhu3 ``` -1. Keep the automatically derived **Slug**. -1. Keep the automatically derived **Display name (optional)**. -1. Under **Endpoints**, wait for automatic discovery of the seeded issuer. After typing or changing **Issuer URL**, click **Discover** only if offered, then confirm the authorization, token, and registration endpoints. - -#### Select the session client - -Under **Session Client**, choose **Select existing** only for a client whose saved credentials, scopes, and audience match the requirements below; otherwise choose **Add new**. When reusing a matching client, skip directly to **Attach the provider** below. Do not create credentials or register the client again. Otherwise choose **Add new** (or use the new-client form shown when no clients exist) and complete these new-client-only steps: - -1. Under **Session Client**, keep **Client Type** set to **Dynamic Client Registration (DCR)**. -1. Keep the discovered **Token Endpoint Auth Method**. -1. Leave **Scope (override)** and **Audience (optional)** empty. - -#### Attach the provider - -Click **Attach Identity Provider**. DCR handles client registration; you do not need to register a callback URL manually. -You do not need to paste a **Client ID** or **Client Secret**. +3. If the picker preselects a different provider on `auth.atlassian.com`, open the picker with **Search identity providers…** and choose the one for the issuer above. +4. Keep **Auto-Configure** selected. There is no **Client ID** or secret to paste. +5. Click **Save**. +6. If the server shows **Disabled**, open **Settings > Danger Zone > Server Availability** and turn on **Enable MCP server** so it shows **Enabled**. -When Atlassian prompts you for access: +When a person first uses the server, Atlassian prompts them in the browser: 1. Sign in with the intended Atlassian account. 2. Authorize the intended Atlassian Cloud site. @@ -71,6 +56,6 @@ When Atlassian prompts you for access: If organization policy rejects the flow, complete [Allow the Speakeasy OAuth domain](external.md#allow-speakeasy-domain), then retry the connection. - + -This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Atlassian's MCP documentation](https://support.atlassian.com/atlassian-rovo-mcp-server/docs/getting-started-with-the-atlassian-remote-mcp-server/). +This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Atlassian's MCP documentation](https://support.atlassian.com/atlassian-ai-gateway/docs/get-started-with-the-atlassian-remote-mcp-server/). diff --git a/guides/box/external.md b/guides/box/external.md index 74bd6a1..43b2b88 100644 --- a/guides/box/external.md +++ b/guides/box/external.md @@ -32,9 +32,12 @@ integration. 1. Select **Integrations**. 2. Apply the **MCP Category** filter, or type `Custom Box MCP Server` in the search bar at the top of the page. -3. Find the **Custom Box MCP Server** tile. +3. Find the **Custom Box MCP Server** tile. Some Box pages call this tile + **Box MCP server**; if `Custom Box MCP Server` finds nothing, search for + `Box MCP server` instead. -Do not select the **Box MCP Server** tab or a named partner tile. +Do not use the **Box MCP Server** tab, which controls tool access, or a named +partner tile. @@ -49,7 +52,7 @@ If the **Custom Box MCP Server** tile shows **Configuration**: Otherwise: -1. Hover over **Custom Box MCP Server**. +1. Hover over the **Custom Box MCP Server** (or **Box MCP server**) tile. 2. Click **Configure**. 3. Open **Additional Configuration**. 4. Click **+ Add Integration Credentials**. diff --git a/guides/box/meta.yaml b/guides/box/meta.yaml index cc544ca..c5dd138 100644 --- a/guides/box/meta.yaml +++ b/guides/box/meta.yaml @@ -51,17 +51,17 @@ remotes: locator: https://developer.box.com/guides/box-mcp/setup name: Set up the MCP server classification: official - observed_at: "2026-08-28T23:25:24Z" + observed_at: "2026-09-30T21:30:00Z" - source: endpoint-metadata locator: https://mcp.box.com/.well-known/oauth-protected-resource name: Box Model Context Protocol Server classification: official - observed_at: "2026-08-28T23:25:24Z" + observed_at: "2026-09-30T21:30:00Z" - source: provider-documentation - locator: https://www.speakeasy.com/docs/ai-control-plane/distribute/mcp-servers/remote-servers + locator: https://www.speakeasy.com/docs/ai-control-plane/mcp-gateway/remote-servers name: Remote MCP servers classification: official - observed_at: "2026-08-28T23:25:24Z" + observed_at: "2026-09-30T21:30:00Z" provenance: - source: pulsemcp locator: com.pulsemcp.mirror/box @@ -84,7 +84,7 @@ provenance: locator: https://docs.box.com/en/box-mcp/configuring-box-mcp-server/claude-code name: Claude Code classification: official - observed_at: "2026-08-28T23:25:24Z" + observed_at: "2026-09-30T21:30:00Z" - source: provider-documentation locator: https://docs.box.com/en/box-mcp/configuring-box-mcp-server/anthropic-messages-api name: Anthropic Messages API @@ -139,7 +139,7 @@ provenance: locator: https://developer.box.com/guides/box-mcp/setup name: Set up the MCP server classification: official - observed_at: "2026-08-28T23:25:24Z" + observed_at: "2026-09-30T21:30:00Z" - source: provider-documentation locator: https://support.box.com/hc/en-us/articles/43847256139923 name: Managing Box MCP Servers @@ -154,14 +154,24 @@ provenance: locator: https://mcp.box.com/.well-known/oauth-protected-resource name: Box Model Context Protocol Server classification: official - observed_at: "2026-08-28T23:25:24Z" + observed_at: "2026-09-30T21:30:00Z" - source: provider-documentation - locator: https://www.speakeasy.com/docs/ai-control-plane/distribute/mcp-servers/remote-servers + locator: https://www.speakeasy.com/docs/ai-control-plane/mcp-gateway/remote-servers name: Remote MCP servers classification: official - observed_at: "2026-08-28T23:25:24Z" + observed_at: "2026-09-30T21:30:00Z" + - source: endpoint-metadata + locator: https://api.box.com/.well-known/oauth-authorization-server + name: Box authorization server metadata + classification: official + observed_at: "2026-09-30T21:30:00Z" + - source: provider-documentation + locator: https://developer.box.com/reference/get-authorize/ + name: Authorize user + classification: official + observed_at: "2026-09-30T21:30:00Z" - source: repository-doctrine locator: doctrine/speakeasy-setup.md name: Canonical Speakeasy setup classification: official - observed_at: "2026-08-28T23:25:24Z" + observed_at: "2026-09-30T21:30:00Z" diff --git a/guides/box/research.md b/guides/box/research.md index a8be3a3..0f6a4bc 100644 --- a/guides/box/research.md +++ b/guides/box/research.md @@ -37,8 +37,12 @@ the labels. All public sources below were observed on - **OAuth endpoints:** authorization `https://account.box.com/api/oauth2/authorize`; token exchange `https://api.box.com/oauth2/token`. Box's protected-resource metadata names - `https://api.box.com/` as the authorization server and bearer headers as - supported. [Set up the MCP server; protected-resource metadata] + `https://api.box.com/` (with a trailing slash) as the authorization server + and bearer headers as supported. Box's RFC 8414 metadata at + `https://api.box.com/.well-known/oauth-authorization-server` names issuer + `https://api.box.com` (no trailing slash), the same two endpoints, and no + `registration_endpoint` or CIMD support (observed 2026-09-30). [Set up the + MCP server; protected-resource metadata; authorization-server metadata] - **OAuth scope strings:** `root_readwrite`, `ai.readwrite`, and `docgen.readwrite`. These are API-level strings; Box's product setup pages name the UI section **Access scopes** but do not publish checkbox-to-string @@ -51,11 +55,10 @@ the labels. All public sources below were observed on - **Permissions:** scopes cap possible actions, while each user can access only content that their Box permissions permit. [Set up the MCP server; About Box MCP Server] -- **Catalog path:** coordinator-supplied facts did not establish a - provider-specific Box mapping. Catalog presence is therefore unknown, not - absent. The shared remote is not tenanted and Metadata keeps - `speakeasy_add_server: auto`, so the canonical Speakeasy setup preserves both - safe add-server branches. [Canonical Speakeasy setup] +- **Catalog path:** `meta.yaml` sets `speakeasy_add_server: catalog` and + records the Speakeasy MCP Catalog record `com.pulsemcp.mirror/box` as + present, so the guide renders only the catalog path. [Canonical Speakeasy + setup] ## Credential flow @@ -70,9 +73,9 @@ Speakeasy AI Control Plane: | **Client Secret** | Generated in the same entry | `copy-client-credentials` | The admin enters `{{ gram.oauth.callback_url }}` directly in Box's -**Redirect URIs** field at `set-redirect-uri`. The canonical Speakeasy attach -sheet later shows the same **Redirect URI** for confirmation; the reader does -not need a Speakeasy-first detour. Box's Claude Code localhost redirect is +**Redirect URIs** field at `set-redirect-uri`. The Speakeasy **Add Client** form +later shows the same **Redirect URI** for confirmation; the reader does not +need a Speakeasy-first detour. Box's Claude Code localhost redirect is client-specific and must not be copied into this guide. [Claude Code; Anthropic Messages API; canonical Speakeasy setup] @@ -265,45 +268,75 @@ tool inventory. [Manage tool access; Available tools; MCP FAQ] ## Speakeasy setup -Canonical source: `doctrine/speakeasy-setup.md`, observed -`2026-08-28T23:25:24Z`. Per-guide values are remote -`https://mcp.box.com`, transport `streamable-http`, Authentication Option -`oauth-integration`, credential sources `copy-client-credentials`, and further -reading `https://docs.box.com/en/box-mcp/about-box-mcp-server`. +Canonical source: `doctrine/speakeasy-setup.md` (gram main `68b3f78`), +observed `2026-09-30T21:30:00Z`. + +Per-guide values: + +- Remote URL: `https://mcp.box.com` (shared, not tenanted) +- Add-server path: catalog only (**From the catalog**), from + `speakeasy_add_server: catalog`. +- Authentication Option: `oauth-integration`, mapped to **User Identity**. + **Client ID** and **Client Secret** come from `copy-client-credentials`; + `{{ gram.oauth.callback_url }}` is entered at `set-redirect-uri`. +- Probe outcome (2026-09-30): an unauthenticated JSON-RPC `initialize` POST + returned 401 with `resource_metadata= + "https://mcp.box.com/.well-known/oauth-protected-resource"`. +- PRM issuer: `https://api.box.com/`. PRM `scopes_supported`: none. +- Issuer metadata: `https://api.box.com/.well-known/oauth-authorization-server` + names issuer `https://api.box.com`, which does not match the PRM value + byte for byte. The Control Plane's issuer-metadata fetch + (`server/internal/remotesessions/issuerhandlers.go`, gram `68b3f78`) + refuses a document whose issuer differs from the requested one, + "including its path and trailing slash", so the picker cannot create the + provider from the PRM. Discovery is treated as unavailable, and the guide + renders the custom identity provider route with **Issuer URL** + `https://api.box.com` (no trailing slash), which matches the metadata. +- CIMD / DCR: neither advertised; Box's support article says DCR is not + supported. +- Registration choice: **Manual**, through the custom provider's **Add + Client** (**Client Type** **Manual**), then **Existing client** on the + server. Creation with **User Identity** cannot configure the provider, so + the server is kept **Disabled** and the result points to **Settings > + Identity**; the guide says this is expected and ends with **Server + Availability**. +- Scope: leave **Scope (override)** blank. Box's authorize reference says + an omitted `scope` "defaults to all the scopes configured for the + application", that is, the **Access scopes** chosen at + `check-access-scopes`; the PRM and issuer metadata advertise no scopes. +- Further reading: `https://docs.box.com/en/box-mcp/about-box-mcp-server` ### Add the server in Speakeasy {#add-server-in-speakeasy} -Catalog presence is unresolved and no override applies, so render both safe -branches. In the Speakeasy AI Control Plane sidebar, under **Connect**, select -**Sources**, then click **Add Source**. +In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select +**MCP**, then click **Add new** to open **Add MCP server**. Choose **From +the catalog**. On the **MCP Catalog** page, find **Box** with **Search MCP +servers...**, open its entry, and click **Add**. In **Add to Project**, +select **User Identity** under **Identity**, then click **Add to Project**. +Finish or **Skip for now** any **Guardrails** step. The result says to +finish setup in **Settings > Identity** and the server stays **Disabled**. -- If Box is in the catalog, choose **3rd-party server**. On the **MCP Catalog** - page, find Box (the search box reads **Search MCP servers...**), open its - entry with **View**, and click **Add**. In the **Add to Project** dialog, - click **Add to Project**. -- If Box is not in the catalog, choose **Custom remote server**. On the **Add a - custom remote MCP server** page, paste `https://mcp.box.com` into **Remote MCP - server URL** and click **Add server**. - -Either branch creates the hosted MCP server and opens its **Overview** page. -Catalog presence remains the soft research question recorded under **Research -limitations**. - - + ### Connect your credentials {#connect-speakeasy-credentials} -From the server's **Overview**, open **Settings**. Under **Authentication**, -click **Configure Manually** (or **Use Discovered** when offered by Box's -protected-resource metadata). In **Attach Remote Identity Provider**, set -**Client Type** to **Manual**. The sheet shows **Redirect URI** with a copy -button; confirm it matches the value substituted for -`{{ gram.oauth.callback_url }}` in Box at `set-redirect-uri`. Paste the -**Client ID** and **Client Secret (optional)** copied at -`copy-client-credentials`, then click **Attach Identity Provider**. +In the server's **Settings > Identity**, select **User Identity**, open +**Choose an identity provider**, and click **Create a custom identity +provider** to open **Remote Identity Providers**. Click **New Remote +Identity Provider**, enter **Issuer URL** `https://api.box.com`, click +**Discover**, confirm **Authorization Endpoint** and **Token Endpoint** +under **Endpoints**, keep the derived **Slug**, and click **Create**. On +that provider, click **Add Client**: **Client Type** **Manual**, **Client +ID** and **Client Secret (optional)** from `copy-client-credentials` (Box +requires the secret), **Scope (override)** blank, confirm **Redirect URI** +matches the value entered at `set-redirect-uri`, and click **Create**. +Return to the server's **Settings > Identity**, select that provider, +choose **Existing client**, pick the client under **Client**, and click +**Save**. Then open **Danger Zone > Server Availability** and turn on +**Enable MCP server** so it shows **Enabled**. - + This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Box's MCP documentation](https://docs.box.com/en/box-mcp/about-box-mcp-server). @@ -312,14 +345,13 @@ This guide covers setup only. For anything beyond it — billing, tool behavior, These public-source gaps are presentation-only or safely hedgeable; none is a material operator decision for first connection. -- **Soft research question — Pulse catalog presence:** Is Box present in the - Pulse catalog? Coordinator-supplied facts did not establish a - provider-specific Box mapping, so presence remains unresolved and setup - retains both canonical add-server branches. This safely hedgeable gap is a - Research limitation, not an Operator decision; under the strict scope gate it - stays out of structured `open_questions`. -- Box's current product pages use **Configuration** > **Add Integration - Credentials**; current Support pages use **Additional Configuration** > +- The Control Plane path above is derived from gram source and live + metadata, not a production walkthrough with a Box tenant. It has not been + confirmed that the custom `https://api.box.com` provider completes a Box + sign-in end to end. +- Box's current product pages use the **Custom Box MCP Server** tile and + **Configuration** > **Add Integration Credentials**; developer.box.com + searches for **Box MCP server**, and current Support pages use **Additional Configuration** > **+ Add Integration Credentials** and an initial name save. Public docs do not explain which enterprise receives which surface. - Product docs name **Access scopes** but do not publish exact checkbox labels @@ -352,7 +384,7 @@ None scopes, and license details, not to override product UI labels. - **Support KB:** `https://support.box.com`. Used for administrator eligibility, no-DCR, and the alternate credential surface. -- **Speakeasy docs:** `https://www.speakeasy.com/docs/ai-control-plane/distribute/mcp-servers/remote-servers`. +- **Speakeasy docs:** `https://www.speakeasy.com/docs/ai-control-plane/mcp-gateway/remote-servers`. Used to corroborate the supported remote transport and custom/catalog paths. - No community, partner, issue, or catalog record was used as factual authority. The coordinator-supplied Pulse note establishes only that the snapshot was @@ -415,12 +447,23 @@ All records below were observed `2026-08-28T23:25:24Z`. metadata fetched through Exa; backs resource `https://mcp.box.com/`, resource name **Box Model Context Protocol Server**, authorization server `https://api.box.com/`, bearer-header support, and official resource docs. -- `https://www.speakeasy.com/docs/ai-control-plane/distribute/mcp-servers/remote-servers` +- `https://www.speakeasy.com/docs/ai-control-plane/mcp-gateway/remote-servers` — official Speakeasy documentation; backs streamable HTTP support and the catalog and custom-URL registration paths. -- `doctrine/speakeasy-setup.md` — repository authority supplied for this run; - backs the transcluded Speakeasy labels, fixed anchors, dual-path behavior when - catalog presence is unresolved, manual OAuth flow, and closing pointer form. +- `doctrine/speakeasy-setup.md` — repository authority, observed + `2026-09-30T21:30:00Z` (gram main `68b3f78`); backs the transcluded + Speakeasy labels, fixed anchors, catalog path, custom identity provider + route, and closing pointer form. +- `https://api.box.com/.well-known/oauth-authorization-server` — observed + `2026-09-30T21:30:00Z`; backs issuer `https://api.box.com`, the + authorization and token endpoints, and the absence of registration and + CIMD support. +- `https://developer.box.com/reference/get-authorize/` — observed + `2026-09-30T21:30:00Z`; backs the default of an omitted `scope` to the + application's configured scopes. +- Live probe of `https://mcp.box.com` and its PRM on `2026-09-30T21:30:00Z` + — backs the 401 `resource_metadata` challenge, PRM issuer + `https://api.box.com/`, and no advertised scopes. - Credential-free Pulse snapshot note supplied by the coordinator — establishes snapshot readiness and an unknown Box mapping only. It is not treated as a provider record, and no private catalog content is reproduced. diff --git a/guides/box/speakeasy.md b/guides/box/speakeasy.md index 7aa16f8..e6e118e 100644 --- a/guides/box/speakeasy.md +++ b/guides/box/speakeasy.md @@ -3,49 +3,65 @@ ### Add the server in Speakeasy {#add-server-in-speakeasy} 1. In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select **MCP**. -2. Click **Add new** to open the **Add MCP server** page. +2. Click **Add new** to open **Add MCP server**. 3. Choose **From the catalog**. 4. On the **MCP Catalog** page, use **Search MCP servers...** to find **Box**. -5. Open the **Box** entry. -6. Click **Add**. -7. In the **Add to Project** dialog, click **Add to Project**. +5. Open the **Box** entry and click **Add**. +6. In the **Add to Project** dialog, under **Identity**, select **User Identity**. The dialog may preselect **No Identity**. +7. Click **Add to Project**. If the dialog offers a **Guardrails** step, finish it or click **Skip for now**. -After installation, select **Configure MCP settings** on the completion screen to open the server, then open **Settings**. +Box needs a client registered by hand, so the result says to finish setup in **Settings > Identity**, and the server stays **Disabled** for now. This is expected. Click **Finish setup** on the server's result to open its **Settings**. - + ### Connect your credentials {#connect-speakeasy-credentials} -Select **Configure MCP settings** on the completion screen, then open the server’s **Settings**. +Box's server names its sign-in provider as `https://api.box.com/`, with a trailing slash, while Box's provider metadata says `https://api.box.com`. The provider picker cannot create a provider from that mismatch, so create the Box provider by hand first. -Under **Authentication**, if unconfigured, select **Use Discovered** when available; otherwise select **Configure Manually**. If configured but no provider is attached, use **Connected services > Add provider**. If the intended provider is already attached, use its existing controls and skip the provider/client creation and attachment steps below; do not add a duplicate. +In the server's **Settings**, find the **Identity** section and select **User Identity**. Then create the provider: -#### Select the identity provider +1. Open **Choose an identity provider** and click **Create a custom identity provider**. This opens **Remote Identity Providers**. +2. Click **New Remote Identity Provider**. +3. In **Issuer URL**, enter `https://api.box.com`, with no trailing slash. +4. Click **Discover**. +5. Under **Endpoints**, confirm **Authorization Endpoint** and **Token Endpoint** show these values. If they are empty, enter them: -In **Attach Remote Identity Provider**, **Identity Provider** defaults to **Select existing** when project issuers are available. Select the matching provider and skip the new-provider fields below. Otherwise choose **Add new** (or use the new-provider form shown when none exist). + ```text + https://account.box.com/api/oauth2/authorize + ``` -For a new provider only, confirm **Issuer URL**, the auto-derived **Slug**, and **Endpoints**. Discovery runs automatically for a seeded issuer; after typing or changing the URL, select **Discover** only if offered. + ```text + https://api.box.com/oauth2/token + ``` -For **Identity Provider > Add new**, use **Issuer URL** `https://api.box.com/`, authorization endpoint `https://account.box.com/api/oauth2/authorize`, and token endpoint `https://api.box.com/oauth2/token`. Keep the auto-derived **Slug**. +6. Keep the derived **Slug** and click **Create**. -#### Select the session client +Add the Box client to that provider: -Under **Session Client**, choose **Select existing** only for a client whose saved credentials, scopes, and audience match the requirements below; otherwise choose **Add new**. When reusing a matching client, skip directly to **Verify the callback and attach** below. Do not create credentials or register the client again. Otherwise choose **Add new** (or use the new-client form shown when no clients exist) and complete these new-client-only steps: +1. On the new provider, click **Add Client**. +2. Set **Client Type** to **Manual**. +3. Paste the [Box Client ID](external.md#copy-client-credentials) into **Client ID**. +4. Paste the [Box Client Secret](external.md#copy-client-credentials) into **Client Secret (optional)**. Box requires it. +5. Leave **Scope (override)** empty. Box then grants the **Access scopes** selected in [Check the Access scopes](external.md#check-access-scopes). +6. Confirm the displayed **Redirect URI** matches the value you entered in [Set the Redirect URI](external.md#set-redirect-uri). +7. Click **Create**. -1. In **Attach Remote Identity Provider**, set **Client Type** to **Manual**. -1. Paste the [Box Client ID](external.md#copy-client-credentials) into - **Client ID**. -1. Paste the [Box Client Secret](external.md#copy-client-credentials) into - **Client Secret (optional)**. +Connect the server to that client: -#### Verify the callback and attach +1. Return to the server's **Settings > Identity** and select **User Identity**. +2. In **Choose an identity provider**, open the picker and choose the `api.box.com` provider you created. +3. Choose **Existing client**. +4. Under **Client**, pick the client you created. +5. Click **Save**. -1. Confirm that the callback URL registered with the provider is `{{ gram.oauth.callback_url }}`. For a new manual client, also compare it with the sheet's displayed **Redirect URI**. The existing-client selection does not display that field; check the registered callback in the provider's app settings instead. -2. Click **Attach Identity Provider**. +Then turn the server on: -For the provider-side callback setting, see [Redirect URIs](external.md#set-redirect-uri). +1. In **Settings**, open **Danger Zone**. +2. Under **Server Availability**, turn on **Enable MCP server** so it shows **Enabled**. + +Each user sees Box's authorization prompt the first time they use the server. - + This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Box's MCP documentation](https://docs.box.com/en/box-mcp/about-box-mcp-server). diff --git a/guides/github/external.md b/guides/github/external.md index 9a59819..e56c9b3 100644 --- a/guides/github/external.md +++ b/guides/github/external.md @@ -6,7 +6,7 @@ setup_version: 1 Before you begin, obtain: -- Administrative access to the GitHub Enterprise Cloud organization that will own the OAuth app. +- Administrative access to the GitHub organization that will own the OAuth app. - Standard GitHub.com hosting for the target organization. This Setup Guide does not cover GitHub Enterprise Cloud with data residency or GitHub Enterprise Server. - The organization-approved public URL for this connection from the application or cloud security owner. - If the target organization restricts OAuth apps, access to an organization owner who can grant access — see [Connect your credentials](speakeasy.md#connect-speakeasy-credentials). @@ -42,7 +42,7 @@ If the page shows **New OAuth App**, click it. If the page instead shows **Regis 5. Leave **Enable Device Flow** off. 6. Click **Register application**. This opens the app's settings page. -If the target organization restricts OAuth apps, complete the organization approval flow after attaching credentials in [Connect your credentials](speakeasy.md#connect-speakeasy-credentials). +If the target organization restricts OAuth apps, complete the organization approval flow after saving credentials in [Connect your credentials](speakeasy.md#connect-speakeasy-credentials). diff --git a/guides/github/meta.yaml b/guides/github/meta.yaml index 10c24e9..a0f3e16 100644 --- a/guides/github/meta.yaml +++ b/guides/github/meta.yaml @@ -54,15 +54,15 @@ remotes: locator: https://github.com/github/github-mcp-server/blob/main/docs/host-integration.md name: GitHub Remote MCP Integration Guide for MCP Host Authors classification: official - observed_at: "2026-08-06T23:22:50Z" + observed_at: "2026-09-30T21:30:00Z" - source: endpoint-observation locator: https://api.githubcopilot.com/mcp/ classification: official - observed_at: "2026-08-06T23:22:50Z" + observed_at: "2026-09-30T21:30:00Z" - source: endpoint-observation locator: https://api.githubcopilot.com/.well-known/oauth-protected-resource/mcp/ classification: official - observed_at: "2026-08-06T23:22:50Z" + observed_at: "2026-09-30T21:30:00Z" provenance: - source: pulsemcp name: io.github.github/github-mcp-server @@ -84,12 +84,12 @@ provenance: locator: https://github.com/github/github-mcp-server/blob/main/docs/host-integration.md name: GitHub Remote MCP Integration Guide for MCP Host Authors classification: official - observed_at: "2026-08-06T23:22:50Z" + observed_at: "2026-09-30T21:30:00Z" - source: provider-documentation locator: https://github.com/github/github-mcp-server/blob/main/docs/scope-filtering.md name: Scope Filtering classification: official - observed_at: "2026-08-06T23:22:50Z" + observed_at: "2026-09-30T21:30:00Z" - source: provider-documentation locator: https://github.com/github/github-mcp-server/blob/main/docs/policies-and-governance.md name: Policies & Governance for the GitHub MCP Server @@ -138,17 +138,17 @@ provenance: - source: endpoint-observation locator: https://api.githubcopilot.com/mcp/ classification: official - observed_at: "2026-08-06T23:22:50Z" + observed_at: "2026-09-30T21:30:00Z" - source: endpoint-observation locator: https://api.githubcopilot.com/.well-known/oauth-protected-resource/mcp/ classification: official - observed_at: "2026-08-06T23:22:50Z" + observed_at: "2026-09-30T21:30:00Z" - source: endpoint-observation - locator: https://github.com/login/oauth/.well-known/oauth-authorization-server + locator: https://github.com/.well-known/oauth-authorization-server/login/oauth classification: official - observed_at: "2026-08-06T23:22:50Z" + observed_at: "2026-09-30T21:30:00Z" - source: repository-doctrine locator: doctrine/speakeasy-setup.md name: Speakeasy setup canonical section classification: official - observed_at: "2026-08-06T23:22:50Z" + observed_at: "2026-09-30T21:30:00Z" diff --git a/guides/github/research.md b/guides/github/research.md index c8c140f..10defa6 100644 --- a/guides/github/research.md +++ b/guides/github/research.md @@ -37,16 +37,23 @@ walkthrough. `https://api.githubcopilot.com/.well-known/oauth-protected-resource/mcp/`. That document names `https://github.com/login/oauth` as the authorization server, lists supported scopes, and requires header bearer tokens. The - corresponding RFC authorization-server metadata URL returned 404 during - this run, so the server has protected-resource discovery but not a complete - discoverable authorization-server metadata chain. + RFC 8414 path-inserted metadata URL + `https://github.com/.well-known/oauth-authorization-server/login/oauth` + returned 200 on 2026-09-30 with issuer `https://github.com/login/oauth`, + authorization endpoint `https://github.com/login/oauth/authorize`, and + token endpoint `https://github.com/login/oauth/access_token`, with no + `registration_endpoint` and no CIMD support. (The earlier run probed the + suffix form `https://github.com/login/oauth/.well-known/oauth-authorization-server`, + which still returns 404.) Discovery is therefore complete. - **Scopes:** there is no single fixed scope set for setup. The remote server uses OAuth scope challenges and requests additional scopes when a selected - tool needs them. The protected-resource metadata advertises `repo`, - `read:org`, `read:user`, `user:email`, `read:packages`, `write:packages`, - `read:project`, `project`, `gist`, `notifications`, `workflow`, and - `codespace`. Do not pre-grant all of them merely because they are - advertised; users approve the scopes requested for their work. + tool needs them. On 2026-09-30 the protected-resource metadata advertised + `repo`, `read:org`, `read:user`, `user:email`, `read:packages`, + `write:packages`, `read:project`, `project`, `gist`, and `notifications` + (`workflow` and `codespace`, listed in the earlier run, are no longer + advertised). GitHub OAuth apps do not restrict which scopes they may + request, so every advertised scope is grantable; users approve the scopes + requested. GitHub's docs publish no minimal scope set for hosts. - **Authorization boundary:** GitHub's native permission model still applies. The server cannot access resources the signed-in user cannot normally access through GitHub's APIs. @@ -142,7 +149,7 @@ is **New OAuth App** (or **Register a new application** when no app exists) > **Register application**, showing the field labels and the callback template but no organization-sensitive homepage value. - Organization caveat: if the target organization restricts OAuth apps, - complete the organization approval flow after attaching credentials at + complete the organization approval flow after saving credentials at {#connect-speakeasy-credentials}. ### Generate the OAuth credentials {#generate-oauth-credentials} @@ -166,59 +173,73 @@ is **New OAuth App** (or **Register a new application** when no app exists) > ## Speakeasy setup -Canonical source: `doctrine/speakeasy-setup.md`, observed -`2026-08-06T23:22:50Z`. +Canonical source: `doctrine/speakeasy-setup.md` (gram main `68b3f78`), +observed `2026-09-30T21:30:00Z`. Per-guide values: -- Remote URL: `https://api.githubcopilot.com/mcp/` -- Transport: `streamable-http` (the add form's **Transport** field is - read-only) -- Authentication Option: OAuth with a manually pre-registered client -- OAuth discovery: GitHub publishes protected-resource metadata, but its - advertised authorization-server metadata URL did not resolve this run; - use **Use Discovered** only when the Speakeasy AI Control Plane offers it, - otherwise use **Configure Manually** -- **Client ID** and **Client secret**: produced at - {#generate-oauth-credentials} -- Redirect URI registered with GitHub: - `{{ gram.oauth.callback_url }}` at {#register-oauth-app} -- Provider scopes: no fixed upfront list; the server uses OAuth scope - challenges to request additional scopes as tools need them +- Remote URL: `https://api.githubcopilot.com/mcp/` (shared, not tenanted) +- Add-server path: catalog only (**From the catalog**), resolved by the + Speakeasy MCP Catalog record `io.github.github/github-mcp-server`, title + `GitHub`. Do not offer the Custom remote path. +- Authentication Option: `oauth-app`, mapped to **User Identity**. + **Client ID** and client secret come from {#generate-oauth-credentials}; + `{{ gram.oauth.callback_url }}` is registered as **Authorization callback + URL** at {#register-oauth-app}. +- Probe outcome (2026-09-30): 401 with `resource_metadata= + "https://api.githubcopilot.com/.well-known/oauth-protected-resource/mcp/"`. +- PRM issuer: `https://github.com/login/oauth`; issuer metadata matches it + byte for byte, so the provider picker can create the provider from + metadata ("Will be created"). +- CIMD / DCR: neither advertised; GitHub's host-integration guide also says + DCR is not supported. +- Registration choice: **Manual** (also the dashboard default here). + Creation with **User Identity** cannot register a client, so the server is + kept **Disabled** and the result points to **Settings > Identity**; the + guide says this is expected and ends with **Server Availability**. +- Scope string for **Advanced > Scope**: the organization's approved subset + of the advertised list, space-separated on one line. The guide shows the + full advertised string + `repo read:org read:user user:email read:packages write:packages read:project project gist notifications` + and tells readers to delete what their organization does not allow. A + blank **Scope** requests that full list, including `repo`, + `write:packages`, and `gist`. +- Fallback endpoints if discovery ever fails (custom identity provider + route): issuer `https://github.com/login/oauth`, authorization + `https://github.com/login/oauth/authorize`, token + `https://github.com/login/oauth/access_token`. Not rendered, because + discovery works. - Further reading: `https://github.com/github/github-mcp-server/blob/main/docs/remote-server.md` -Catalog selection is resolved by the Speakeasy MCP Catalog observation: -`name="io.github.github/github-mcp-server"`, title `GitHub`. Render only the -catalog path; do not offer the Custom remote path. - ### Add the server in Speakeasy {#add-server-in-speakeasy} -In the Speakeasy AI Control Plane sidebar, under **Connect**, select -**Sources**, then click **Add Source**. Choose **3rd-party server**. On the -**MCP Catalog** page, find GitHub using **Search MCP servers...**, open its -entry with **View**, and click **Add**. In the **Add to Project** dialog, -click **Add to Project**. - -This creates the hosted MCP server and opens its **Overview** page. +In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select +**MCP**, then click **Add new** to open **Add MCP server**. Choose **From +the catalog**. On the **MCP Catalog** page, find GitHub using **Search MCP +servers...**, open its entry, and click **Add**. In **Add to Project**, +select **User Identity** under **Identity**, then click **Add to Project**. +Finish or **Skip for now** any **Guardrails** step. The result says to +finish setup in **Settings > Identity** and the server stays **Disabled**. -Screenshot note: capture GitHub's catalog entry with **View** and **Add** -visible, excluding unrelated catalog results. +Screenshot note: GitHub's catalog entry in **Add to Project** with **User +Identity** selected. ### Connect your credentials {#connect-speakeasy-credentials} -From the server's **Overview**, open **Settings**. Under -**Authentication**, click **Use Discovered** when offered; otherwise click -**Configure Manually**. In **Attach Remote Identity Provider**, set -**Client Type** to **Manual**. Paste the **Client ID** and **Client Secret -(optional)** saved at {#generate-oauth-credentials}, then click -**Attach Identity Provider**. Confirm the sheet's **Redirect URI** matches -the `{{ gram.oauth.callback_url }}` value registered at -{#register-oauth-app}. +In the server's **Settings**, open the **Identity** section and select +**User Identity**. In **Choose an identity provider**, confirm +`https://github.com/login/oauth` (badged **Will be created** when new), or +choose it with **Search identity providers…**. Choose **Manual**, paste the +**Client ID** and client secret from {#generate-oauth-credentials} (GitHub +requires the secret despite the "Optional" placeholder), enter the scope +string above under **Advanced > Scope**, and click **Save**. This surface +shows no redirect URI; {#register-oauth-app} carries the callback check. +Then open **Danger Zone > Server Availability** and turn on **Enable MCP +server** so it shows **Enabled**. If the target organization restricts OAuth apps, have a user authorize the -connection after **Attach Identity Provider**, then complete the request and -owner-approval flow: +connection, then complete the request and owner-approval flow: - User request path: profile picture > **Settings** > **Applications** in the **Integrations** section of the sidebar > the **Authorized OAuth Apps** tab, @@ -232,9 +253,9 @@ owner-approval flow: Flagged recovery inference: if the user's first authorization attempt was blocked before approval, retry authorization after the owner grants access. -Screenshot note: capture **Attach Remote Identity Provider** with the -Redirect URI and credential fields visible and all credential values -redacted. +Screenshot note: **Settings > Identity** with **User Identity**, the +`github.com/login/oauth` provider, and **Manual** selected; credential +values redacted. Closing pointer: "This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see GitHub's MCP documentation at @@ -243,18 +264,14 @@ https://github.com/github/github-mcp-server/blob/main/docs/remote-server.md." ## Open questions - The exact Speakeasy control that launches GitHub user authorization after - **Attach Identity Provider** in {#connect-speakeasy-credentials}; name that - control in the restricted-organization branch once canonical doctrine or - Speakeasy docs confirm it. -- GitHub's protected-resource metadata was live and pointed to - `https://github.com/login/oauth`, but the corresponding standard - authorization-server metadata request returned 404. Confirm during - fidelity review whether the Speakeasy AI Control Plane offers - **Use Discovered** for this endpoint or requires **Configure Manually**. + **Save** in {#connect-speakeasy-credentials}; name that control in the + restricted-organization branch once canonical doctrine or Speakeasy docs + confirm it. - GitHub documents on-demand OAuth scope challenges for the remote server. Public Speakeasy doctrine does not state whether post-connection scope - challenges are surfaced to users; validate this behavior before claiming - that every scope-gated tool can be authorized on demand. + challenges are surfaced to users, so a scope removed from **Advanced > + Scope** may not be requestable later. Validate this behavior before + claiming that every scope-gated tool can be authorized on demand. ## Provenance @@ -349,16 +366,18 @@ Sources drawn from: at `2026-08-06T23:22:50Z`. Returned HTTP 401 with a Bearer challenge naming the protected-resource metadata URL. - `https://api.githubcopilot.com/.well-known/oauth-protected-resource/mcp/` - — observed `2026-08-06T23:22:50Z`. Backs the exact MCP resource, + — observed `2026-08-06T23:22:50Z`, re-observed `2026-09-30T21:30:00Z`. Backs the exact MCP resource, authorization-server locator, supported scopes, header bearer method, and resource name. -- `https://github.com/login/oauth/.well-known/oauth-authorization-server` — - observed `2026-08-06T23:22:50Z`. Returned HTTP 404; backs the discovery - caveat and open question. +- `https://github.com/.well-known/oauth-authorization-server/login/oauth` — + observed `2026-09-30T21:30:00Z`. Returned 200 with issuer + `https://github.com/login/oauth`, authorization and token endpoints, no + `registration_endpoint`, and no CIMD support. The suffix-form URL probed + on 2026-08-06 still returns 404. - Speakeasy MCP Catalog record `io.github.github/github-mcp-server` (title `GitHub`; source: `pulsemcp`) — observed `2026-08-06T23:22:50Z`. Backs catalog presence and the catalog-only add-server path. -- `doctrine/speakeasy-setup.md` — observed `2026-08-06T23:22:50Z`. Backs the - transcluded Speakeasy-side flow, fixed anchors, exact product labels, +- `doctrine/speakeasy-setup.md` — observed `2026-09-30T21:30:00Z` (gram main + `68b3f78`). Backs the transcluded Speakeasy-side flow, fixed anchors, exact product labels, callback-template behavior, and closing-pointer form. diff --git a/guides/github/speakeasy.md b/guides/github/speakeasy.md index 5f45e08..cfec2f4 100644 --- a/guides/github/speakeasy.md +++ b/guides/github/speakeasy.md @@ -3,45 +3,42 @@ ### Add the server in Speakeasy {#add-server-in-speakeasy} 1. In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select **MCP**. -2. Click **Add new** to open the **Add MCP server** page. +2. Click **Add new** to open **Add MCP server**. 3. Choose **From the catalog**. 4. On the **MCP Catalog** page, find GitHub using **Search MCP servers...**. -5. Open its entry. -6. Click **Add**. -7. In the **Add to Project** dialog, click **Add to Project**. +5. Open its entry and click **Add**. +6. In the **Add to Project** dialog, under **Identity**, select **User Identity**. The dialog may preselect **No Identity**. +7. Click **Add to Project**. If the dialog offers a **Guardrails** step, finish it or click **Skip for now**. -After installation, select **Configure MCP settings** on the completion screen to open the server, then open **Settings**. +GitHub needs a client registered by hand, so the result says to finish setup in **Settings > Identity**, and the server stays **Disabled** for now. This is expected. Click **Finish setup** on the server's result to open its **Settings**. - + ### Connect your credentials {#connect-speakeasy-credentials} -Select **Configure MCP settings** on the completion screen, then open the server’s **Settings**. +In the server's **Settings**, find the **Identity** section. -Under **Authentication**, if unconfigured, select **Use Discovered** when available; otherwise select **Configure Manually**. If configured but no provider is attached, use **Connected services > Add provider**. If the intended provider is already attached, use its existing controls and skip the provider/client creation and attachment steps below; do not add a duplicate. +1. Select **User Identity**. +2. In **Choose an identity provider**, confirm the provider is `https://github.com/login/oauth`. It may be badged **Will be created**. If no provider or a different one is selected, open the picker, search for `github.com` in **Search identity providers…**, and choose the `github.com/login/oauth` provider. +3. Under the provider, choose **Manual**. +4. Paste the **Client ID** from [Generate the OAuth credentials](external.md#generate-oauth-credentials) into **Client ID**. +5. Paste the client secret from [Generate the OAuth credentials](external.md#generate-oauth-credentials) into **Client secret**. GitHub requires it, even though the field shows "Optional". +6. Open **Advanced** and enter the scopes users may grant in **Scope**, on one line. Start from the full list GitHub's server advertises and delete any your organization does not allow: -#### Select the identity provider + ```text + repo read:org read:user user:email read:packages write:packages read:project project gist notifications + ``` -In **Attach Remote Identity Provider**, **Identity Provider** defaults to **Select existing** when project issuers are available. Select the matching provider and skip the new-provider fields below. Otherwise choose **Add new** (or use the new-provider form shown when none exist). + A blank **Scope** requests every scope in this list, including `repo`, `write:packages`, and `gist`. -For a new provider only, confirm **Issuer URL**, the auto-derived **Slug**, and **Endpoints**. Discovery runs automatically for a seeded issuer; after typing or changing the URL, select **Discover** only if offered. +7. Click **Save**. -For a new provider, use the authorization-server issuer `https://github.com/login/oauth` identified by GitHub’s protected-resource metadata. If discovery does not supply the endpoints, ask your administrator for the documented authorization and token endpoints before continuing; do not infer them from the MCP URL. +This section does not show the redirect URI. GitHub accepts the connection only if [Register the OAuth app](external.md#register-oauth-app) set **Authorization callback URL** to `{{ gram.oauth.callback_url }}`. -#### Select the session client +Then turn the server on: -Under **Session Client**, choose **Select existing** only for a client whose saved credentials, scopes, and audience match the requirements below; otherwise choose **Add new**. When reusing a matching client, skip directly to **Verify the callback and attach** below. Do not create credentials or register the client again. Otherwise choose **Add new** (or use the new-client form shown when no clients exist) and complete these new-client-only steps: - -1. In **Attach Remote Identity Provider**, set **Client Type** to **Manual**. -1. Paste the **Client ID** saved in [Generate the OAuth credentials](external.md#generate-oauth-credentials) into **Client ID**. -1. Paste the saved client secret into **Client Secret (optional)** — although the field is labeled optional, this OAuth connection requires it. - -#### Verify the callback and attach - -1. Confirm that the callback URL registered with the provider is `{{ gram.oauth.callback_url }}`. For a new manual client, also compare it with the sheet's displayed **Redirect URI**. The existing-client selection does not display that field; check the registered callback in the provider's app settings instead. -2. Click **Attach Identity Provider**. - -For the provider-side callback setting, see [Register the OAuth app](external.md#register-oauth-app). +1. In **Settings**, open **Danger Zone**. +2. Under **Server Availability**, turn on **Enable MCP server** so it shows **Enabled**. If the target organization restricts OAuth apps, have a user authorize the connection, then complete the following: @@ -65,6 +62,6 @@ Then have an organization owner approve the pending request: If the user's first authorization attempt was blocked before approval, have the user retry it after access is granted. - + This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [GitHub's MCP documentation](https://github.com/github/github-mcp-server/blob/main/docs/remote-server.md). diff --git a/guides/gmail/meta.yaml b/guides/gmail/meta.yaml index 1cb74e4..bcd6dcf 100644 --- a/guides/gmail/meta.yaml +++ b/guides/gmail/meta.yaml @@ -34,7 +34,7 @@ remotes: - source: google-developers locator: https://developers.google.com/workspace/gmail/api/guides/configure-mcp-server classification: official - observed_at: "2026-08-20T19:49:41Z" + observed_at: "2026-09-30T21:25:46Z" - source: google-developers locator: https://developers.google.com/workspace/gmail/api/reference/mcp classification: official @@ -46,7 +46,7 @@ provenance: - source: google-developers locator: https://developers.google.com/workspace/gmail/api/guides/configure-mcp-server classification: official - observed_at: "2026-08-20T19:49:41Z" + observed_at: "2026-09-30T21:25:46Z" - source: google-developers locator: https://developers.google.com/workspace/gmail/api/reference/mcp classification: official @@ -54,7 +54,7 @@ provenance: - source: google-developers locator: https://developers.google.com/workspace/preview classification: official - observed_at: "2026-08-20T19:49:41Z" + observed_at: "2026-09-30T21:25:46Z" - source: google-cloud-console locator: https://console.cloud.google.com/ classification: official @@ -71,7 +71,17 @@ provenance: locator: https://support.google.com/cloud/answer/15549257?hl=en classification: official observed_at: "2026-08-20T19:49:41Z" + - source: provider-metadata + locator: https://gmailmcp.googleapis.com/.well-known/oauth-protected-resource/mcp/v1 + name: Gmail MCP protected-resource metadata + classification: official + observed_at: "2026-09-30T21:25:46Z" + - source: provider-metadata + locator: https://accounts.google.com/.well-known/oauth-authorization-server + name: Google OAuth authorization-server metadata + classification: official + observed_at: "2026-09-30T21:25:46Z" - source: speakeasy-doctrine locator: doctrine/speakeasy-setup.md classification: official - observed_at: "2026-08-20T19:49:41Z" + observed_at: "2026-09-30T21:25:46Z" diff --git a/guides/gmail/research.md b/guides/gmail/research.md index b985476..e1e46aa 100644 --- a/guides/gmail/research.md +++ b/guides/gmail/research.md @@ -21,7 +21,7 @@ researched_at: 2026-08-20T19:49:41Z ## Credential flow -An administrator enables the Gmail and Gmail MCP APIs in the allowlisted Google Cloud project, configures the project's Google Auth consent settings, and creates an OAuth client with **Application type** set to **Web application**. In that client, the administrator adds `{{ gram.oauth.callback_url }}` under **Authorized redirect URIs** by clicking **+ Add URI**. The resulting **Client ID** and **Client Secret** are pasted into the Speakeasy AI Control Plane's manual OAuth sheet. +An administrator enables the Gmail and Gmail MCP APIs in the allowlisted Google Cloud project, configures the project's Google Auth consent settings, and creates an OAuth client with **Application type** set to **Web application**. In that client, the administrator adds `{{ gram.oauth.callback_url }}` under **Authorized redirect URIs** by clicking **+ Add URI**. The resulting **Client ID** and **Client Secret** are pasted into the **Manual** client fields of the server's **Identity** section in the Speakeasy AI Control Plane. Google's Gmail MCP page documents the same client-creation flow for other MCP hosts, each with that host's callback URI. The Speakeasy callback template is therefore the per-client value used in the documented **Authorized redirect URIs** field. Google Cloud's support documentation says the full client secret is visible and downloadable only at creation; store it securely before closing the dialog. @@ -79,30 +79,36 @@ Start at the [Google Cloud console](https://console.cloud.google.com/) with the ## Speakeasy setup +Transcluded from `doctrine/speakeasy-setup.md` (gram `main` `68b3f78`), observed 2026-09-30T21:25:46Z. Fixed anchors are carried verbatim. + Per-guide values: -- Remote URL: `https://gmailmcp.googleapis.com/mcp/v1` -- Transport: `streamable-http` (the **Transport** field is read-only) -- Add-server path: Custom remote server only because the operator set `speakeasy_add_server: custom-remote`; the catalog result is overridden because its mapping is unreliable or unsuitable for this guide. -- Authentication Option: manual OAuth 2.0 (`gmail-oauth`); Google explicitly does not support DCR. -- **Client ID**: produced by [Create the OAuth client](#create-oauth-client). -- **Client Secret (optional)**: produced by [Create the OAuth client](#create-oauth-client); it is required for this documented Gmail flow even though the Speakeasy sheet's generic label says optional. -- Registered callback: `{{ gram.oauth.callback_url }}` in the OAuth client's **Authorized redirect URIs** field. -- Required allowed scopes: `https://www.googleapis.com/auth/gmail.readonly` and `https://www.googleapis.com/auth/gmail.compose`, configured in [Configure the OAuth consent screen](#configure-oauth-consent). +- Remote URL: `https://gmailmcp.googleapis.com/mcp/v1`; `streamable-http`; shared, not tenanted. +- Add-server path: **Hosted remotely** only, because the operator set `speakeasy_add_server: custom-remote` (catalog mapping unreliable or unsuitable). +- Authentication Option: `gmail-oauth` (OAuth) → identity mode **User Identity**. +- Probe outcome (2026-09-30T21:25:46Z): an unauthenticated JSON-RPC `initialize` POST with `Accept: application/json, text/event-stream` returns **200** with no challenge. The create form therefore preselects **No Identity**; the reader must select **User Identity**. +- PRM: `https://gmailmcp.googleapis.com/.well-known/oauth-protected-resource/mcp/v1` names issuer `https://accounts.google.com/` and advertises 11 scopes: `https://mail.google.com/`, `gmail.compose`, `gmail.drafts`, `gmail.drafts.create`, `gmail.drafts.readonly`, `gmail.labels`, `gmail.metadata`, `gmail.modify`, `gmail.readonly`, `gmail.send`, `gmail.settings.basic` (all under `https://www.googleapis.com/auth/` except the first). +- Issuer metadata (`https://accounts.google.com/.well-known/oauth-authorization-server` and `/.well-known/openid-configuration`): no `registration_endpoint`, no `client_id_metadata_document_supported`; authorization endpoint `https://accounts.google.com/o/oauth2/v2/auth`, token endpoint `https://oauth2.googleapis.com/token`, `client_secret_post` and `client_secret_basic`. Google's MCP authentication docs also state DCR and CIMD are unsupported. +- Creation result: automatic configuration cannot register a client, so the server is kept **Disabled** and the result points to **Settings > Identity**. Expected. +- Provider picker: discovery is available (PRM is served), so the picker preselects the Google issuer, badged **Will be created** when no Google provider exists. No custom identity provider route is needed. +- Registration choice: **Manual** (the dashboard default when no client exists and neither CIMD nor DCR is advertised). +- **Client ID** and **Client secret**: produced by [Create the OAuth client](#create-oauth-client). The secret is required despite the "Optional" placeholder. +- **Advanced > Scope** (space-separated, one line): `https://www.googleapis.com/auth/gmail.readonly https://www.googleapis.com/auth/gmail.compose`. Blank is not safe: it requests all 11 PRM scopes, including the restricted `https://mail.google.com/`, which the consent configuration does not grant. +- Registered callback: `{{ gram.oauth.callback_url }}` under **Authorized redirect URIs**. The Identity section does not display a redirect URI, so External setup carries that check. +- Server Availability: required after the Identity save (**Settings > Danger Zone > Server Availability**, **Enable MCP server**, **Enabled**). - Further reading: `https://developers.google.com/workspace/gmail/api/guides/configure-mcp-server` -- Provenance for the fixed Speakeasy UI flow: `doctrine/speakeasy-setup.md`, observed 2026-08-20T19:49:41Z. ### Add the server in Speakeasy {#add-server-in-speakeasy} -In the Speakeasy AI Control Plane sidebar, under **Connect**, select **Sources**, then click **Add Source**. Choose **Custom remote server**. On the **Add a custom remote MCP server** page, paste `https://gmailmcp.googleapis.com/mcp/v1` into **Remote MCP server URL** and click **Add server**. This creates the hosted MCP server and opens its **Overview** page. +In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select **MCP**, then click **Add new** to open **Add MCP server**. Choose **Hosted remotely**. On **New remote MCP server**, paste `https://gmailmcp.googleapis.com/mcp/v1` into **MCP server URL**, leave **User session issuer** at its default, and click **Verify connectivity**. Under **Identity**, change the preselected **No Identity** to **User Identity**, leave **Guardrails** off, and click **Save**. The server is kept **Disabled** and the result says to finish setup in **Settings > Identity**; this is expected. - +Screenshot note: **New remote MCP server** after **Verify connectivity**, with **User Identity** selected. ### Connect your credentials {#connect-speakeasy-credentials} -From the server's **Overview**, open **Settings**. Under **Authentication**, click **Configure Manually**. In the **Attach Remote Identity Provider** sheet, set **Client Type** to **Manual**. The sheet shows the **Redirect URI** with a copy button—the callback URL registered during External setup. Paste the **Client ID** and **Client Secret (optional)** from [Create the OAuth client](#create-oauth-client), then click **Attach Identity Provider**. Confirm the sheet's **Redirect URI** matches the `{{ gram.oauth.callback_url }}` value registered under **Authorized redirect URIs**; the template value is entered directly during External setup, rather than copied from this sheet. The Gmail flow requires the client secret despite the sheet's generic optional label. +Open the server's **Settings** > **Identity**. Select **User Identity**. In **Choose an identity provider**, confirm the preselected Google issuer `https://accounts.google.com/` (or choose it via **Search identity providers…**). Choose **Manual** (switch from **Existing client** if preselected). Paste **Client ID** and **Client secret** from [Create the OAuth client](#create-oauth-client). Under **Advanced > Scope**, enter the scope string above on one line and do not leave it blank. Click **Save** (**Save changes** if asked to confirm). Then open **Settings > Danger Zone > Server Availability** and turn on **Enable MCP server** so it shows **Enabled**. -Screenshot note: capture the manual **Attach Remote Identity Provider** sheet with the **Redirect URI** visible and credentials redacted. +Screenshot note: **Settings > Identity** with **User Identity**, the Google provider, and **Manual** selected; values redacted. This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Gmail's MCP documentation](https://developers.google.com/workspace/gmail/api/guides/configure-mcp-server). @@ -120,12 +126,15 @@ None. The public documentation identifies the endpoint, manual OAuth model, requ ### Sources -- `https://developers.google.com/workspace/gmail/api/guides/configure-mcp-server` — observed 2026-08-20T19:49:41Z. Backs Developer Preview status; prerequisites; both required services; consent navigation, audience/test-user flow, exact scopes, and UI labels; web OAuth client creation; endpoint, HTTP transport description, OAuth authentication, client ID/secret flow, and primary further-reading URL. Page reported last updated 2026-08-19 UTC. +- `https://developers.google.com/workspace/gmail/api/guides/configure-mcp-server` — observed 2026-08-20T19:49:41Z; scopes, endpoint, and Developer Preview status re-verified 2026-09-30T21:25:46Z (page last updated 2026-09-18 UTC). Backs Developer Preview status; prerequisites; both required services; consent navigation, audience/test-user flow, exact scopes, and UI labels; web OAuth client creation; endpoint, HTTP transport description, OAuth authentication, client ID/secret flow, and primary further-reading URL. Page reported last updated 2026-08-19 UTC. - `https://developers.google.com/workspace/gmail/api/reference/mcp` — observed 2026-08-20T19:49:41Z. Backs the global Gmail MCP endpoint and its status as the Gmail API MCP server. - `https://developers.google.com/workspace/preview` — observed 2026-08-20T19:49:41Z. Backs Developer Preview enrollment requirements, the required Google Cloud project number, and the Google Workspace account / Google Cloud project verification and registration process. - `https://docs.cloud.google.com/mcp/authenticate-mcp` — observed 2026-08-20T19:49:41Z. Backs manual OAuth client ID and secret support and the explicit lack of Dynamic Client Registration and OAuth Client ID Metadata Documents. - `https://docs.cloud.google.com/service-usage/docs/enable-disable` — observed 2026-08-20T19:49:41Z. Backs **Service Usage Admin**, project selection, **APIs & Services** > **API Library**, **Search for APIs & Services**, API selection, and **Enable**. - `https://support.google.com/cloud/answer/15549257?hl=en` — observed 2026-08-20T19:49:41Z. Backs **Google Auth Platform** > **Clients**, **Create Client**, the warning that the full client secret is visible/downloadable only when created, and the client-detail controls for disabling, deleting, and replacing a missed secret. - `https://console.cloud.google.com/` — observed 2026-08-20T19:49:41Z. Official Google Cloud console entry URL. -- `doctrine/speakeasy-setup.md` — observed 2026-08-20T19:49:41Z. Backs fixed Speakeasy add-server and manual OAuth UI labels, transitions, anchors, and closing-pointer format. +- `doctrine/speakeasy-setup.md` (gram `main` `68b3f78`) — observed 2026-09-30T21:25:46Z. Backs fixed Speakeasy add-server, Identity section, **Manual** client, **Advanced > Scope**, and **Server Availability** labels, transitions, anchors, and closing-pointer format. +- `https://gmailmcp.googleapis.com/mcp/v1` — probed 2026-09-30T21:25:46Z; unauthenticated `initialize` returns 200. +- `https://gmailmcp.googleapis.com/.well-known/oauth-protected-resource/mcp/v1` — observed 2026-09-30T21:25:46Z. Backs the PRM issuer and the 11 advertised scopes. +- `https://accounts.google.com/.well-known/oauth-authorization-server` — observed 2026-09-30T21:25:46Z. Backs the endpoints and the absence of `registration_endpoint` and CIMD support. - Operator note: Speakeasy MCP Catalog query `gmail` returned `overridden-custom-remote`; observed 2026-08-20T19:49:41Z. Backs the `speakeasy_add_server: custom-remote` override and Custom remote-only path because catalog mapping is unreliable or unsuitable. diff --git a/guides/gmail/speakeasy.md b/guides/gmail/speakeasy.md index 8fa9e4c..dcca5c7 100644 --- a/guides/gmail/speakeasy.md +++ b/guides/gmail/speakeasy.md @@ -5,77 +5,43 @@ 1. In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select **MCP**. 2. Click **Add new** to open **Add MCP server**. 3. Choose **Hosted remotely**. -4. On the **New remote MCP server** page, paste this value into **MCP server URL**: - -```text -https://gmailmcp.googleapis.com/mcp/v1 -``` - -5. Click **Verify connectivity**, then **Save**. This creates the hosted MCP server and opens its **Overview** page. - - - -### Connect your credentials {#connect-speakeasy-credentials} - -Open the server's **Settings** (from **Overview** for a hosted remote server, or **Configure MCP settings** after a catalog addition). - -#### Choose an authentication provider - -- If **Authentication** is unconfigured, choose **Use Discovered** when available; otherwise choose **Configure Manually**. -- If authentication is configured but no provider is attached, use **Connected services** > **Add provider**. -- If the intended provider is already attached, use its existing controls. Do not attach a duplicate; check its client against the requirements below and skip **Verify and attach**. - -In **Attach Remote Identity Provider**, the provider selector defaults to **Select existing** when the project has issuers. Select the appropriate existing Google provider and skip new-provider setup. - -#### New provider only - -1. Choose **Add new** and enter **Issuer URL**: - - ```text - https://accounts.google.com/ - ``` - -2. Confirm the auto-derived **Slug** is unique in the project. -3. Discovery runs automatically for a seeded issuer URL. After typing or changing the URL, click **Discover** only if offered. -4. Review the endpoints, or enter these Google OAuth values if discovery does not populate them. - - Authorization endpoint: - - ```text - https://accounts.google.com/o/oauth2/v2/auth - ``` - - Token endpoint: +4. On **New remote MCP server**, paste this URL into **MCP server URL**: ```text - https://oauth2.googleapis.com/token + https://gmailmcp.googleapis.com/mcp/v1 ``` -#### Choose a session client - -- **Reuse:** Under **Session Client**, choose **Select existing** when available and select the appropriate Google OAuth client. Skip credential entry; continue to **Check client requirements**. -- **Create:** Choose **Add new** when available and set **Client Type** to **Manual**. For a new provider, complete the new-client form below. +5. Leave **User session issuer** at its default. +6. Click **Verify connectivity**. +7. Under **Identity**, select **User Identity**. The page preselects **No Identity** for this server, so change it. +8. If **Guardrails** appears, leave it off. +9. Click **Save**. -#### New session client only +Speakeasy keeps the new server **Disabled** and says to finish setup in **Settings > Identity**. This is expected for Gmail; the next section finishes it. -1. Paste the **Client ID** from [Create the OAuth client](external.md#create-oauth-client) into **Client ID**. -1. Paste the **Client Secret** from [Create the OAuth client](external.md#create-oauth-client) into **Client Secret (optional)**. The Gmail setup requires this value despite the generic optional label. + -#### Check client requirements +### Connect your credentials {#connect-speakeasy-credentials} -For both new and reused clients, verify the Google app's approved audience and publishing status. An **External** app in **Testing** must list each connecting account under **Test users**. Reusing a client does not require entering its credentials again. +Open the server's **Settings** and find the **Identity** section. -For a new client, enter these comma-separated scopes in **Scope (override)**. For a reused client, inspect its read-only **Scope** value; if it does not include both scopes, choose **Add new** instead. The scopes must also match the Google app's **Data Access** configuration: +1. Select **User Identity**. +2. In **Choose an identity provider**, confirm that the preselected provider is Google's issuer, `https://accounts.google.com/`. It is badged **Will be created** when the project has no Google provider yet. If another provider is selected, open the picker, search in **Search identity providers…**, and choose the Google provider. +3. Under the provider, choose **Manual**. If **Existing client** is preselected, switch to **Manual**. +4. Paste the **Client ID** from [Create the OAuth client](external.md#create-oauth-client) into **Client ID**. +5. Paste the **Client Secret** from [Create the OAuth client](external.md#create-oauth-client) into **Client secret**. Gmail requires the secret even though the field shows "Optional". +6. Open **Advanced**. In **Scope**, enter this value on one line. Do not leave **Scope** blank: a blank value requests every scope the Gmail server advertises, including `https://mail.google.com/`, which your Google app does not grant. -```text -https://www.googleapis.com/auth/gmail.readonly, https://www.googleapis.com/auth/gmail.compose -``` + ```text + https://www.googleapis.com/auth/gmail.readonly https://www.googleapis.com/auth/gmail.compose + ``` -#### Verify and attach +7. Click **Save**. If Speakeasy asks you to confirm, click **Save changes**. +8. Open **Settings > Danger Zone > Server Availability**. +9. Turn on **Enable MCP server** so the switch shows **Enabled**. -1. Confirm that the callback URL registered with the provider is `{{ gram.oauth.callback_url }}`. For a new manual client, also compare it with the sheet's displayed **Redirect URI**. The existing-client selection does not display that field; check the registered callback in the provider's app settings instead. -2. Click **Attach Identity Provider**. +When a person first uses the server, Google's browser authorization prompt appears. - + This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Gmail's MCP documentation](https://developers.google.com/workspace/gmail/api/guides/configure-mcp-server). diff --git a/guides/google-big-query/meta.yaml b/guides/google-big-query/meta.yaml index 1fcfb21..3ff555f 100644 --- a/guides/google-big-query/meta.yaml +++ b/guides/google-big-query/meta.yaml @@ -3,6 +3,7 @@ schema_version: 1 slug: google-big-query title: Google BigQuery summary: Query and manage BigQuery data through Google's hosted BigQuery MCP server. +speakeasy_add_server: catalog aliases: - com.pulsemcp.mirror/google-bigquery credential_setup: @@ -39,7 +40,7 @@ remotes: locator: https://docs.cloud.google.com/bigquery/docs/use-bigquery-mcp name: Use the BigQuery MCP server classification: official - observed_at: "2026-08-06T23:23:41Z" + observed_at: "2026-09-30T21:25:43Z" - source: provider-documentation locator: https://docs.cloud.google.com/bigquery/docs/reference/mcp name: BigQuery MCP reference @@ -54,18 +55,18 @@ remotes: locator: https://bigquery.googleapis.com/mcp name: BigQuery MCP endpoint classification: official - observed_at: "2026-08-06T23:23:41Z" + observed_at: "2026-09-30T21:25:43Z" - source: endpoint-observation locator: https://bigquery.googleapis.com/.well-known/oauth-protected-resource/mcp name: BigQuery MCP protected-resource metadata classification: official - observed_at: "2026-08-06T23:23:41Z" + observed_at: "2026-09-30T21:25:43Z" provenance: - source: provider-documentation locator: https://docs.cloud.google.com/bigquery/docs/use-bigquery-mcp name: Use the BigQuery MCP server classification: official - observed_at: "2026-08-06T23:23:41Z" + observed_at: "2026-09-30T21:25:43Z" - source: provider-documentation locator: https://docs.cloud.google.com/bigquery/docs/reference/mcp name: BigQuery MCP reference @@ -183,34 +184,34 @@ provenance: observed_at: "2026-08-06T23:23:41Z" - source: endpoint-observation locator: https://bigquery.googleapis.com/mcp - name: BigQuery MCP endpoint (tools/list 200 unauthenticated; tools/call 401) + name: BigQuery MCP endpoint (initialize and tools/list 200 unauthenticated; tools/call 401) classification: official - observed_at: "2026-08-06T23:23:41Z" + observed_at: "2026-09-30T21:25:43Z" - source: endpoint-observation locator: https://bigquery.googleapis.com/.well-known/oauth-protected-resource/mcp name: BigQuery MCP protected-resource metadata classification: official - observed_at: "2026-08-06T23:23:41Z" + observed_at: "2026-09-30T21:25:43Z" - source: endpoint-observation locator: https://accounts.google.com/.well-known/oauth-authorization-server name: Google authorization-server metadata classification: official - observed_at: "2026-08-06T23:23:41Z" + observed_at: "2026-09-30T21:25:43Z" - source: repository-doctrine locator: doctrine/speakeasy-setup.md name: Speakeasy setup canonical section classification: official - observed_at: "2026-08-06T23:23:41Z" + observed_at: "2026-09-30T21:25:43Z" - source: product-source - locator: speakeasy-api/gram@96f7f73:client/dashboard/src/pages/mcp/x/tabs/settings/sections/authentication/IssuerFormFields.tsx - name: Speakeasy identity-provider form fields + locator: speakeasy-api/gram@68b3f78:client/dashboard/src/pages/mcp/x/tabs/settings/sections/authentication/RemoteMcpIdentitySection.tsx + name: Speakeasy remote MCP Identity section classification: official - observed_at: "2026-08-06T23:23:41Z" + observed_at: "2026-09-30T21:25:43Z" - source: product-source - locator: speakeasy-api/gram@96f7f73:client/dashboard/src/pages/mcp/x/tabs/settings/sections/authentication/AttachRemoteIdentityProviderSheet.tsx - name: Speakeasy identity-provider attachment sheet + locator: speakeasy-api/gram@68b3f78:client/dashboard/src/pages/catalog/AddServerDialog.tsx + name: Speakeasy catalog Add to Project dialog classification: official - observed_at: "2026-08-06T23:23:41Z" + observed_at: "2026-09-30T21:25:43Z" - source: provider-documentation locator: https://docs.cloud.google.com/contact-center/ccai-platform/docs/oauth-email-google name: Configure an email channel for OAuth with Gmail diff --git a/guides/google-big-query/research.md b/guides/google-big-query/research.md index 0533686..15f52e6 100644 --- a/guides/google-big-query/research.md +++ b/guides/google-big-query/research.md @@ -115,12 +115,12 @@ Values needed by the Speakeasy AI Control Plane: | --- | --- | | Client ID | **OAuth 2.0 client created** dialog in {#copy-client-credentials} | | Client Secret | **Client secrets** section of the same dialog in {#copy-client-credentials}; copyable once | -| OAuth scope | `https://www.googleapis.com/auth/bigquery` | +| OAuth scope | `https://www.googleapis.com/auth/bigquery`, entered under **Advanced > Scope** | Paste `{{ gram.oauth.callback_url }}` directly into **Authorized redirect URIs** -while creating the OAuth client in {#create-oauth-client}. The template resolves -to the **Redirect URI** later shown by the Speakeasy AI Control Plane's -**Attach Remote Identity Provider** sheet. Google requires web applications to +while creating the OAuth client in {#create-oauth-client}. The Speakeasy +**Identity** section does not display the redirect URI, so this External step +carries the callback check. Google requires web applications to allowlist the application's redirect URI and does not accept custom URI schemes for this flow. @@ -338,65 +338,63 @@ the selected project. ## Speakeasy setup -Transcluded from `doctrine/speakeasy-setup.md`; its anchors -`{#add-server-in-speakeasy}` and `{#connect-speakeasy-credentials}` are fixed -and carried verbatim. Provenance: `doctrine/speakeasy-setup.md` (product source -`speakeasy-api/gram`, `client/dashboard`, branch `main`, commit `96f7f73`), -observed at `2026-08-06T23:23:41Z`. Operator-provided Speakeasy MCP Catalog -lookup result: absent for queries `google-big-query` and `google big query`; -therefore only the Custom remote server path is rendered. - -### Add the server in Speakeasy {#add-server-in-speakeasy} - -In the Speakeasy AI Control Plane sidebar, under **Connect**, select -**Sources**, then click **Add Source**. - -Choose **Custom remote server**. On the **Add a custom remote MCP server** -page, paste `https://bigquery.googleapis.com/mcp` into **Remote MCP server -URL** and click **Add server**. - -This creates the hosted MCP server and opens its **Overview** page. - - -Sequence condition: the reader follows this section after completing -{#copy-client-credentials}. +Transcluded from `doctrine/speakeasy-setup.md` (product source +`speakeasy-api/gram`, `client/dashboard`, `main` @ `68b3f78`), observed +`2026-09-30T21:25:43Z`. Anchors `{#add-server-in-speakeasy}` and +`{#connect-speakeasy-credentials}` are fixed and carried verbatim. Per-guide values: -- Remote URL: `https://bigquery.googleapis.com/mcp`. -- Transport: `streamable-http`; the add form's **Transport** field is read-only. -- Authentication Option: `oauth-client`, OAuth with a manually registered - client. +- Remote URL: `https://bigquery.googleapis.com/mcp` (not tenanted). +- Add-server path: **From the catalog** only; `meta.yaml` sets + `speakeasy_add_server: catalog`. Correction: the earlier lookup recorded + the catalog as absent because it searched `google-big-query` and + `google big query`. A Speakeasy MCP Catalog search for `BigQuery` on + `2026-09-30` returned the entry **BigQuery** (`com.pulsemcp.mirror/google-bigquery`, + the guide's existing alias), "Google-managed MCP server for BigQuery". + Search term: `BigQuery`. +- Authentication Option: `oauth-client` → **User Identity**. +- Probe outcome: `initialize` POST (with + `Accept: application/json, text/event-stream`) returned **200 + unauthenticated**, protocol `2025-06-18`. The catalog entry has no OAuth + client registration, so **Add to Project** preselects **No Identity**; the + reader selects **User Identity**. +- PRM: `https://bigquery.googleapis.com/.well-known/oauth-protected-resource/mcp` + names issuer `https://accounts.google.com/` and advertises only + `https://www.googleapis.com/auth/bigquery`. +- Issuer metadata: `https://accounts.google.com` publishes authorization + endpoint `https://accounts.google.com/o/oauth2/v2/auth` and token endpoint + `https://oauth2.googleapis.com/token`; no `registration_endpoint` and no + `client_id_metadata_document_supported`. Discovery works; no custom + provider route is needed. +- Registration choice: **Manual**. Creation with **User Identity** leaves the + server **Disabled** with a note to finish in **Settings > Identity**; this + is expected, and **Server Availability** must be turned on afterwards. +- Credential fields: **Client ID** and **Client secret** from + {#copy-client-credentials}; Google requires the secret despite the + "Optional" placeholder. +- Scope under **Advanced > Scope**: `https://www.googleapis.com/auth/bigquery`. + It matches the PRM list; the guide still enters it explicitly and says not + to leave the field blank. +- First connection: an account with the roles from + {#grant-bigquery-mcp-roles}; an External app in **Testing** also needs the + account under **Test users**. +- Screenshot notes: the **Add to Project** dialog with **User Identity** + selected; **Settings > Identity** with the Google provider and **Manual**, + credentials redacted. +- Further-reading URL: + `https://docs.cloud.google.com/bigquery/docs/use-bigquery-mcp`. -### Connect your credentials {#connect-speakeasy-credentials} - -From the server's **Overview**, open **Settings**. Under **Authentication**, -click **Configure Manually** (or **Use Discovered** when offered). In the -**Attach Remote Identity Provider** sheet, set **Client Type** to **Manual**. -The sheet shows the **Redirect URI** with a copy button — the callback URL -registered in {#create-oauth-client} with `{{ gram.oauth.callback_url }}`. - -Paste the **Client ID** and **Client Secret (optional)** from -{#copy-client-credentials}; Google's web client requires its generated secret -even though the Control Plane label says optional. In **Scope (override)**, -enter `https://www.googleapis.com/auth/bigquery`. The field accepts -comma-separated scopes; this guide requires this single value. Click **Attach -Identity Provider**. Confirm the sheet's **Redirect URI** matches the -`{{ gram.oauth.callback_url }}` value registered under **Authorized redirect -URIs** in {#create-oauth-client} — readers paste that template key directly -there; they do not visit this sheet mid–External-setup only to copy the URI. - -Screenshot note: **Attach Remote Identity Provider** showing **Client Type: -Manual**, **Redirect URI**, credential labels, and scope configuration, with -credential values redacted. +### Add the server in Speakeasy {#add-server-in-speakeasy} -Further-reading URL for the closing pointer: -`https://docs.cloud.google.com/bigquery/docs/use-bigquery-mcp`. +Catalog path with **User Identity** selected in **Add to Project**, per the +values above. Sequence condition: follows {#copy-client-credentials}. -Canonical closing sentence to render verbatim: +### Connect your credentials {#connect-speakeasy-credentials} -This guide covers setup only. For anything beyond it — billing, tool behavior, -limits — see [Google's BigQuery MCP documentation](https://docs.cloud.google.com/bigquery/docs/use-bigquery-mcp). +**Settings > Identity** > **User Identity** > Google provider > **Manual** +with the values above, **Save**, then **Settings > Danger Zone > Server +Availability** > **Enable MCP server**. ## Open questions @@ -531,14 +529,20 @@ at `2026-08-06T23:23:41Z`: registration endpoint. - `doctrine/speakeasy-setup.md` — every Speakeasy-side label and fixed anchor transcluded above; canonical product-source snapshot at - `speakeasy-api/gram`, `client/dashboard`, `main` @ `96f7f73`; observed at - `2026-08-06T23:23:41Z`. -- `speakeasy-api/gram`, commit `96f7f73`, - `client/dashboard/src/pages/mcp/x/tabs/settings/sections/authentication/IssuerFormFields.tsx` - — **Scope (override)** label, comma-separated interaction, and fallback - behavior. -- `speakeasy-api/gram`, commit `96f7f73`, - `client/dashboard/src/pages/mcp/x/tabs/settings/sections/authentication/AttachRemoteIdentityProviderSheet.tsx` - — **Attach Identity Provider** submit label. + `speakeasy-api/gram`, `client/dashboard`, `main` @ `68b3f78`; observed at + `2026-09-30T21:25:43Z`. +- `speakeasy-api/gram`, commit `68b3f78`, + `client/dashboard/src/pages/mcp/x/tabs/settings/sections/authentication/RemoteMcpIdentitySection.tsx` + and `client/dashboard/src/pages/catalog/AddServerDialog.tsx` — **Identity** + section, provider picker, **Manual** registration, **Advanced > Scope**, + and the **Add to Project** identity choice (via the doctrine). +- Re-observed `2026-09-30T21:25:43Z`: `https://bigquery.googleapis.com/mcp` + (`initialize` 200 unauthenticated, protocol `2025-06-18`), its + protected-resource metadata (issuer `https://accounts.google.com/`, scope + `https://www.googleapis.com/auth/bigquery`), Google's authorization-server + metadata (no registration endpoint, no CIMD), + `https://docs.cloud.google.com/bigquery/docs/use-bigquery-mcp` (URL, scope, + three IAM roles unchanged), and the Speakeasy MCP Catalog search for + `BigQuery` (entry **BigQuery**, `com.pulsemcp.mirror/google-bigquery`). - `https://docs.cloud.google.com/contact-center/ccai-platform/docs/oauth-email-google` — **Publish app** followed by **Confirm** in the confirmation dialog. diff --git a/guides/google-big-query/speakeasy.md b/guides/google-big-query/speakeasy.md index e9f9928..ddc3bd5 100644 --- a/guides/google-big-query/speakeasy.md +++ b/guides/google-big-query/speakeasy.md @@ -4,86 +4,43 @@ In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select **MCP**, then click **Add new** to open **Add MCP server**. -1. Choose **Hosted remotely**. -2. On the **New remote MCP server** page, paste this URL into **MCP server URL**: +1. Choose **From the catalog**. +2. On the **MCP Catalog** page, search for `BigQuery` in **Search MCP servers...**. +3. Open the **BigQuery** catalog entry. +4. Click **Add**. This opens the **Add to Project** dialog. +5. Under **Identity**, select **User Identity**. The dialog preselects **No Identity** for this entry, so change it. +6. Click **Add to Project**. +7. If the dialog offers a **Guardrails** step, finish it or click **Skip for now**. +8. When the dialog finishes, the result reads "Added, but disabled until identity is set up." Click **Finish setup** to open the server's **Settings**. - ``` - https://bigquery.googleapis.com/mcp - ``` - -3. Click **Verify connectivity**, then **Save**. - -This creates the hosted MCP server and opens its **Overview** page. +Speakeasy keeps the new server **Disabled** and says to finish setup in **Settings > Identity**. This is expected for BigQuery; continue with the next section. - + ### Connect your credentials {#connect-speakeasy-credentials} -Open the server's **Settings** (from **Overview** for a hosted remote server, or **Configure MCP settings** after a catalog addition). - -#### Choose an authentication provider - -- If **Authentication** is unconfigured, choose **Use Discovered** when available; otherwise choose **Configure Manually**. -- If authentication is configured but no provider is attached, use **Connected services** > **Add provider**. -- If the intended provider is already attached, use its existing controls. Do not attach a duplicate; check its client against the requirements below and skip **Verify and attach**. - -In **Attach Remote Identity Provider**, the provider selector defaults to **Select existing** when the project has issuers. Select the appropriate existing Google provider and skip new-provider setup. +Open the server's **Settings** and find the **Identity** section. -#### New provider only - -1. Choose **Add new** and enter **Issuer URL**: - - ```text - https://accounts.google.com/ - ``` - -2. Confirm the auto-derived **Slug** is unique in the project. -3. Discovery runs automatically for a seeded issuer URL. After typing or changing the URL, click **Discover** only if offered. -4. Review the endpoints, or enter these Google OAuth values if discovery does not populate them. - - Authorization endpoint: - - ```text - https://accounts.google.com/o/oauth2/v2/auth - ``` - - Token endpoint: - - ```text - https://oauth2.googleapis.com/token - ``` - -#### Choose a session client - -- **Reuse:** Under **Session Client**, choose **Select existing** when available and select the appropriate Google OAuth client. Skip credential entry; continue to **Check client requirements**. -- **Create:** Choose **Add new** when available and set **Client Type** to **Manual**. For a new provider, complete the new-client form below. - -#### New session client only - -Google's web client requires its generated secret even though the field is labeled **Client Secret (optional)**. - -1. Paste the **Client ID** from [Copy the client credentials](external.md#copy-client-credentials) into **Client ID**. -1. Paste the **Client secret** from [Copy the client credentials](external.md#copy-client-credentials) into **Client Secret (optional)**. - -#### Check client requirements - -For both new and reused clients, verify the Google app's approved audience and publishing status. An **External** app in **Testing** must list each connecting account under **Test users**. Reusing a client does not require entering its credentials again. - -Confirm the selected client includes the required scopes below. For a new client, configure **Scope (override)**; for a reused client, inspect the read-only **Scope** value. If it does not match, choose **Add new** to create a correctly scoped client; the attach sheet cannot edit a reused client. - -For a new client, enter this value: +1. Confirm **User Identity** is selected. +2. Under **Choose an identity provider**, confirm the preselected Google provider (`https://accounts.google.com`). A new provider shows **Will be created**. If a different provider is preselected, open the picker, search in **Search identity providers…**, and choose the Google provider. +3. Choose **Manual**. If **Existing client** is preselected, switch to **Manual** unless that client is the one created in [Create the OAuth client](external.md#create-oauth-client) with the BigQuery scope. +4. Paste the **Client ID** from [Copy the client credentials](external.md#copy-client-credentials) into **Client ID**. +5. Paste the **Client secret** from [Copy the client credentials](external.md#copy-client-credentials) into **Client secret**. Google requires this secret even though the field shows "Optional". +6. Under **Advanced > Scope**, enter this value. Do not leave **Scope** blank. ``` https://www.googleapis.com/auth/bigquery ``` -#### Verify and attach +7. Click **Save**. If asked to confirm, click **Save changes**. + +Turn the server on: -1. Confirm that the callback URL registered with the provider is `{{ gram.oauth.callback_url }}`. For a new manual client, also compare it with the sheet's displayed **Redirect URI**. The existing-client selection does not display that field; check the registered callback in the provider's app settings instead. -2. Click **Attach Identity Provider**. +1. Open **Settings > Danger Zone > Server Availability**. +2. Turn on the switch (**Enable MCP server**) so it shows **Enabled**. -For the provider-side callback setting, see [Create the OAuth client](external.md#create-oauth-client). +At first connection, complete Google's browser authorization with an account granted the roles in [Grant the BigQuery MCP roles](external.md#grant-bigquery-mcp-roles). An **External** app in **Testing** also requires that account under **Test users**. - + This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Google's BigQuery MCP documentation](https://docs.cloud.google.com/bigquery/docs/use-bigquery-mcp). diff --git a/guides/google-calendar/meta.yaml b/guides/google-calendar/meta.yaml index c35b2a4..7bdefe4 100644 --- a/guides/google-calendar/meta.yaml +++ b/guides/google-calendar/meta.yaml @@ -46,23 +46,23 @@ remotes: locator: https://developers.google.com/workspace/calendar/api/guides/configure-mcp-server name: Configure the Calendar MCP server classification: official - observed_at: "2026-08-29T15:13:24Z" + observed_at: "2026-09-30T21:25:46Z" - source: provider-metadata locator: https://calendarmcp.googleapis.com/.well-known/oauth-protected-resource/mcp/v1 name: Google Calendar MCP protected-resource metadata classification: official - observed_at: "2026-08-29T15:13:24Z" + observed_at: "2026-09-30T21:25:46Z" provenance: - source: provider-documentation locator: https://developers.google.com/workspace/calendar/api/guides/configure-mcp-server name: Configure the Calendar MCP server classification: official - observed_at: "2026-08-29T15:13:24Z" + observed_at: "2026-09-30T21:25:46Z" - source: provider-documentation locator: https://developers.google.com/workspace/preview name: Google Workspace Developer Preview Program classification: official - observed_at: "2026-08-29T15:13:24Z" + observed_at: "2026-09-30T21:25:46Z" - source: provider-documentation locator: https://docs.cloud.google.com/mcp/authenticate-mcp name: Authenticate to Google and Google Cloud MCP servers @@ -107,16 +107,16 @@ provenance: locator: https://calendarmcp.googleapis.com/.well-known/oauth-protected-resource/mcp/v1 name: Google Calendar MCP protected-resource metadata classification: official - observed_at: "2026-08-29T15:13:24Z" + observed_at: "2026-09-30T21:25:46Z" - source: provider-metadata locator: https://accounts.google.com/.well-known/oauth-authorization-server name: Google OAuth authorization-server metadata classification: official - observed_at: "2026-08-29T15:13:24Z" + observed_at: "2026-09-30T21:25:46Z" - source: repository-doctrine locator: doctrine/speakeasy-setup.md name: Speakeasy setup canonical file - observed_at: "2026-08-29T15:13:24Z" + observed_at: "2026-09-30T21:25:46Z" - source: pulsemcp locator: credential-free Pulse snapshot for Google Calendar name: Google Calendar catalog lookup diff --git a/guides/google-calendar/research.md b/guides/google-calendar/research.md index 7983a20..0912dd8 100644 --- a/guides/google-calendar/research.md +++ b/guides/google-calendar/research.md @@ -47,7 +47,7 @@ researched_at: 2026-08-29T15:13:24Z - The coordinator's credential-free Pulse snapshot was `ready` at `2026-08-29T15:13:24Z` and contained no Google Calendar catalog entry. With the non-tenanted remote and `speakeasy_add_server: auto`, the snapshot - resolves the current guide to the **Custom remote server** path. This is + resolves the current guide to the **Hosted remotely** (custom remote) path. This is snapshot evidence, not a permanent claim that the catalog cannot gain an entry and not a reason to force `speakeasy_add_server: custom-remote`. @@ -234,54 +234,77 @@ Cloud project's organization. ## Speakeasy setup -Transcluded from `doctrine/speakeasy-setup.md`, observed at -`2026-08-29T15:13:24Z`. Fixed anchors are carried verbatim. +Transcluded from `doctrine/speakeasy-setup.md` (gram `main` `68b3f78`), +observed at `2026-09-30T21:25:46Z`. Fixed anchors are carried verbatim. + +Per-guide values: + +- Remote URL `https://calendarmcp.googleapis.com/mcp/v1`; `streamable-http`; + shared, not tenanted; `speakeasy_add_server: auto`. +- Add-server path: **Hosted remotely** only. The coordinator's ready Pulse + snapshot at `2026-08-29T15:13:24Z` had no Google Calendar entry (absent). +- Authentication Option `oauth-client` (OAuth) → **User Identity**. +- Probe outcome (`2026-09-30T21:25:46Z`): an unauthenticated JSON-RPC + `initialize` POST with `Accept: application/json, text/event-stream` + returns **200** with no challenge, so the create form preselects **No + Identity**; the reader must select **User Identity**. +- PRM `https://calendarmcp.googleapis.com/.well-known/oauth-protected-resource/mcp/v1` + names issuer `https://accounts.google.com/` and advertises 12 scopes, + including full `https://www.googleapis.com/auth/calendar`, + `calendar.events`, `calendar.acls`, and `calendar.calendars`, well beyond + the three the setup procedure configures. +- Issuer metadata (`https://accounts.google.com/.well-known/oauth-authorization-server` + and `/.well-known/openid-configuration`): no `registration_endpoint`, no + `client_id_metadata_document_supported`. Authorization endpoint + `https://accounts.google.com/o/oauth2/v2/auth`, token endpoint + `https://oauth2.googleapis.com/token`. +- Creation result: automatic configuration cannot register a client, so the + server is kept **Disabled** and the result points to **Settings > + Identity**. Expected. +- Provider picker: PRM is served, so the picker preselects the Google issuer + (badged **Will be created** when absent). No custom identity provider route. +- Registration choice: **Manual**. +- **Client ID** and **Client secret** from {#copy-oauth-credentials}; the + secret is required despite the "Optional" placeholder. +- **Advanced > Scope**, space-separated on one line: + `https://www.googleapis.com/auth/calendar.calendarlist.readonly https://www.googleapis.com/auth/calendar.events.freebusy https://www.googleapis.com/auth/calendar.events.readonly`. + Blank is not safe: it requests all 12 PRM scopes. +- Registered callback `{{ gram.oauth.callback_url }}` in {#create-oauth-client}; + the Identity section does not display a redirect URI. +- Server Availability: required after the Identity save. +- Further reading: + `https://developers.google.com/workspace/calendar/api/guides/configure-mcp-server`. ### Add the server in Speakeasy {#add-server-in-speakeasy} -In the Speakeasy AI Control Plane sidebar, under **Connect**, select -**Sources**, then click **Add Source**. - -Choose **Custom remote server**. On the **Add a custom remote MCP server** -page, paste the following value into **Remote MCP server URL**, then click -**Add server**: +In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select +**MCP**, then click **Add new** to open **Add MCP server**. Choose **Hosted +remotely**. On **New remote MCP server**, paste the following value into +**MCP server URL**, leave **User session issuer** at its default, and click +**Verify connectivity**: ```text https://calendarmcp.googleapis.com/mcp/v1 ``` -This creates the hosted MCP server and opens its Overview page. - - +Under **Identity**, change the preselected **No Identity** to **User +Identity**, leave **Guardrails** off, and click **Save**. The server is kept +**Disabled** and the result says to finish setup in **Settings > Identity**; +this is expected. -Per-guide values: remote URL -`https://calendarmcp.googleapis.com/mcp/v1`; transport `streamable-http`; -Authentication Option `oauth-client`; `speakeasy_add_server: auto`. The -Custom remote path is resolved by the coordinator's ready Pulse snapshot with -no Google Calendar entry, not by a tenanted remote or forced override. + ### Connect your credentials {#connect-speakeasy-credentials} -From the server's **Overview**, open **Settings**. Under **Authentication**, -click **Configure Manually** (or **Use Discovered** when offered). Google -publishes protected-resource and authorization-server metadata, but does not -support dynamic client registration, so in **Attach Remote Identity Provider** -set **Client Type** to **Manual**. The sheet shows **Redirect URI** with a copy -button. - -Confirm **Redirect URI** matches the `{{ gram.oauth.callback_url }}` value -entered in {#create-oauth-client}. Paste **Client ID** and **Client Secret -(optional)** from {#copy-oauth-credentials}; despite the optional label in the -Control Plane, this manual Google web client uses the generated secret. - -**Scope (override)** must contain these three provider-documented scopes. -Speakeasy's public setup material does not document how the field separates -multiple values, so follow the current field guidance rather than assuming a -delimiter, then click **Attach Identity Provider**: - -- `https://www.googleapis.com/auth/calendar.calendarlist.readonly` -- `https://www.googleapis.com/auth/calendar.events.freebusy` -- `https://www.googleapis.com/auth/calendar.events.readonly` +Open the server's **Settings** > **Identity** and select **User Identity**. +In **Choose an identity provider**, confirm the preselected Google issuer +`https://accounts.google.com/` (or choose it via **Search identity +providers…**). Choose **Manual** (switch from **Existing client** if +preselected). Paste **Client ID** and **Client secret** from +{#copy-oauth-credentials}. Under **Advanced > Scope**, enter the scope string +above on one line; do not leave it blank. Click **Save** (**Save changes** if +asked to confirm). Open **Settings > Danger Zone > Server Availability** and +turn on **Enable MCP server** so it shows **Enabled**. At first connection, authorize with an intended Google account that has `mcp.tools.call` on the project, access to the required calendars, applicable @@ -290,7 +313,7 @@ normal predefined grant for `mcp.tools.call` is **MCP Tool User**. Google does n the exact Calendar authorization-prompt button labels, so the Writer must name the purpose and use the labels shown rather than inventing chrome. - + This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Google's MCP documentation](https://developers.google.com/workspace/calendar/api/guides/configure-mcp-server). @@ -310,15 +333,11 @@ This guide covers setup only. For anything beyond it — billing, tool behavior, three scopes in the product-specific setup procedure and do not promise write behavior. - Protected-resource metadata advertises a broader set of Calendar scopes than - the product-specific setup page. Use the product-specific three-scope set for - setup; do not guess that **Use Discovered** will narrow it. + the product-specific setup page. Use the product-specific three-scope set in + **Advanced > Scope**; a blank value requests the full PRM set. - Google does not publish the exact labels of the end-user Calendar OAuth authorization prompt. Use a resilient instruction to authorize the requested access with the intended account. -- Speakeasy's public setup material names **Scope (override)** but does not - document the accepted syntax for multiple scope values. Present the required - values separately and direct the reader to use the current multi-value - control rather than inventing a delimiter. - The Pulse result proves only that the ready credential-free snapshot at `2026-08-29T15:13:24Z` had no Google Calendar entry. It does not establish permanent catalog absence; `auto` preserves future catalog resolution. @@ -357,7 +376,10 @@ organizational knowledge. ### Sources -All public sources below were observed at `2026-08-29T15:13:24Z`. +All public sources below were observed at `2026-08-29T15:13:24Z`. The Calendar +setup page (scopes, endpoint; last updated 2026-09-18 UTC), the Developer +Preview page, the PRM, and the Google authorization-server metadata were +re-verified at `2026-09-30T21:25:46Z`. - `https://developers.google.com/workspace/calendar/api/guides/configure-mcp-server` — hosted endpoint; HTTP transport label; required services and scopes; exact @@ -399,8 +421,11 @@ All public sources below were observed at `2026-08-29T15:13:24Z`. authorization and token endpoint metadata and supported client-secret token authentication methods. - `https://support.google.com/llms.txt` — broad Google Help source inventory. -- `doctrine/speakeasy-setup.md` — observed 2026-08-29T15:13:24Z; fixed - Speakeasy anchors, Custom remote and manual-OAuth labels, transitions, and - closing-pointer contract. +- `doctrine/speakeasy-setup.md` (gram `main` `68b3f78`) — observed + 2026-09-30T21:25:46Z; fixed Speakeasy anchors, **Hosted remotely**, Identity + section, **Manual** client, **Advanced > Scope**, and **Server + Availability** labels, transitions, and closing-pointer contract. +- `https://calendarmcp.googleapis.com/mcp/v1` — probed 2026-09-30T21:25:46Z; + unauthenticated `initialize` returns 200. - Coordinator operator note — observed 2026-08-29T15:13:24Z; credential-free Pulse snapshot status `ready` with no Google Calendar catalog entry. diff --git a/guides/google-calendar/speakeasy.md b/guides/google-calendar/speakeasy.md index 57c92d4..f764c69 100644 --- a/guides/google-calendar/speakeasy.md +++ b/guides/google-calendar/speakeasy.md @@ -7,83 +7,43 @@ 3. Choose **Hosted remotely**. 4. On **New remote MCP server**, paste this URL into **MCP server URL**: - ``` + ```text https://calendarmcp.googleapis.com/mcp/v1 ``` -5. Click **Verify connectivity**, then **Save**. +5. Leave **User session issuer** at its default. +6. Click **Verify connectivity**. +7. Under **Identity**, select **User Identity**. The page preselects **No Identity** for this server, so change it. +8. If **Guardrails** appears, leave it off. +9. Click **Save**. -This creates the hosted MCP server and opens its Overview page. +Speakeasy keeps the new server **Disabled** and says to finish setup in **Settings > Identity**. This is expected for Google Calendar; the next section finishes it. - + ### Connect your credentials {#connect-speakeasy-credentials} -Open the server's **Settings** (from **Overview** for a hosted remote server, or **Configure MCP settings** after a catalog addition). - -#### Choose an authentication provider - -- If **Authentication** is unconfigured, choose **Use Discovered** when available; otherwise choose **Configure Manually**. -- If authentication is configured but no provider is attached, use **Connected services** > **Add provider**. -- If the intended provider is already attached, use its existing controls. Do not attach a duplicate; check its client against the requirements below and skip **Verify and attach**. +Open the server's **Settings** and find the **Identity** section. -In **Attach Remote Identity Provider**, the provider selector defaults to **Select existing** when the project has issuers. Select the appropriate existing Google provider and skip new-provider setup. - -#### New provider only - -1. Choose **Add new** and enter **Issuer URL**: +1. Select **User Identity**. +2. In **Choose an identity provider**, confirm that the preselected provider is Google's issuer, `https://accounts.google.com/`. It is badged **Will be created** when the project has no Google provider yet. If another provider is selected, open the picker, search in **Search identity providers…**, and choose the Google provider. +3. Under the provider, choose **Manual**. If **Existing client** is preselected, switch to **Manual**. +4. Paste the **Client ID** from [Copy the OAuth credentials](external.md#copy-oauth-credentials) into **Client ID**. +5. Paste the **Client Secret** from [Copy the OAuth credentials](external.md#copy-oauth-credentials) into **Client secret**. Google requires the secret even though the field shows "Optional". +6. Open **Advanced**. In **Scope**, enter this value on one line. Do not leave **Scope** blank: a blank value requests every scope the Calendar server advertises, including full `https://www.googleapis.com/auth/calendar`, which your Google app does not grant. ```text - https://accounts.google.com/ + https://www.googleapis.com/auth/calendar.calendarlist.readonly https://www.googleapis.com/auth/calendar.events.freebusy https://www.googleapis.com/auth/calendar.events.readonly ``` -2. Confirm the auto-derived **Slug** is unique in the project. -3. Discovery runs automatically for a seeded issuer URL. After typing or changing the URL, click **Discover** only if offered. -4. Review the endpoints, or enter these Google OAuth values if discovery does not populate them. - - Authorization endpoint: - - ```text - https://accounts.google.com/o/oauth2/v2/auth - ``` - - Token endpoint: - - ```text - https://oauth2.googleapis.com/token - ``` - -#### Choose a session client - -- **Reuse:** Under **Session Client**, choose **Select existing** when available and select the appropriate Google OAuth client. Skip credential entry; continue to **Check client requirements**. -- **Create:** Choose **Add new** when available and set **Client Type** to **Manual**. For a new provider, complete the new-client form below. - -#### New session client only - -1. Paste the **Client ID** from [Copy the OAuth credentials](external.md#copy-oauth-credentials). -1. Paste the **Client Secret** from [Copy the OAuth credentials](external.md#copy-oauth-credentials) into **Client Secret (optional)**. Google requires this value despite the optional Speakeasy label. - -#### Check client requirements - -For both new and reused clients, verify the Google app's approved audience and publishing status. An **External** app in **Testing** must list each connecting account under **Test users**. Reusing a client does not require entering its credentials again. - -Confirm the selected client includes the required scopes below. For a new client, configure **Scope (override)**; for a reused client, inspect the read-only **Scope** value. If it does not match, choose **Add new** to create a correctly scoped client; the attach sheet cannot edit a reused client. - -For a new client, enter all three scopes as a comma-separated value in **Scope (override)**: - -```text -https://www.googleapis.com/auth/calendar.calendarlist.readonly, https://www.googleapis.com/auth/calendar.events.freebusy, https://www.googleapis.com/auth/calendar.events.readonly -``` - -#### Verify and attach - -1. Confirm that the callback URL registered with the provider is `{{ gram.oauth.callback_url }}`. For a new manual client, also compare it with the sheet's displayed **Redirect URI**. The existing-client selection does not display that field; check the registered callback in the provider's app settings instead. -2. Click **Attach Identity Provider**. +7. Click **Save**. If Speakeasy asks you to confirm, click **Save changes**. +8. Open **Settings > Danger Zone > Server Availability**. +9. Turn on **Enable MCP server** so the switch shows **Enabled**. -For the provider-side callback setting, see [created the OAuth client](external.md#create-oauth-client). +The callback Speakeasy uses is the `{{ gram.oauth.callback_url }}` value you registered in [Create the OAuth client](external.md#create-oauth-client). At first connection, authorize the requested access with an intended Google account that is eligible under the Developer Preview terms, has `mcp.tools.call` on the project, access to the required calendars, applicable **Test user** status, and Workspace API-control approval when required. **MCP Tool User** is the normal predefined grant for `mcp.tools.call`, but another role containing the permission can suffice. Use the visible controls on Google's authorization screen. - + This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Google's MCP documentation](https://developers.google.com/workspace/calendar/api/guides/configure-mcp-server). diff --git a/guides/google-compute-engine/meta.yaml b/guides/google-compute-engine/meta.yaml index 6d33314..75e5db8 100644 --- a/guides/google-compute-engine/meta.yaml +++ b/guides/google-compute-engine/meta.yaml @@ -49,7 +49,7 @@ remotes: locator: https://docs.cloud.google.com/compute/docs/use-compute-engine-mcp name: Use the Compute Engine MCP server classification: official - observed_at: "2026-07-31T19:17:08Z" + observed_at: "2026-09-30T21:25:43Z" - source: provider-documentation locator: https://docs.cloud.google.com/compute/docs/reference/mcp name: Compute Engine MCP reference @@ -64,7 +64,7 @@ remotes: locator: https://compute.googleapis.com/.well-known/oauth-protected-resource/mcp name: Compute Engine MCP protected-resource metadata classification: official - observed_at: "2026-07-31T19:17:08Z" + observed_at: "2026-09-30T21:25:43Z" provenance: - source: pulsemcp locator: com.googleapis.compute/mcp @@ -76,7 +76,7 @@ provenance: locator: https://docs.cloud.google.com/compute/docs/use-compute-engine-mcp name: Use the Compute Engine MCP server classification: official - observed_at: "2026-07-31T19:17:08Z" + observed_at: "2026-09-30T21:25:43Z" - source: provider-documentation locator: https://docs.cloud.google.com/compute/docs/reference/mcp name: Compute Engine MCP reference @@ -149,16 +149,21 @@ provenance: observed_at: "2026-07-31T19:17:08Z" - source: endpoint-observation locator: https://compute.googleapis.com/mcp - name: Compute Engine MCP endpoint (tools/list 200 unauthenticated, tools/call 401) + name: Compute Engine MCP endpoint (initialize and tools/list 200 unauthenticated, tools/call 401) classification: official - observed_at: "2026-07-31T19:17:08Z" + observed_at: "2026-09-30T21:25:43Z" - source: endpoint-observation locator: https://compute.googleapis.com/.well-known/oauth-protected-resource/mcp name: Compute Engine MCP protected-resource metadata classification: official - observed_at: "2026-07-31T19:17:08Z" + observed_at: "2026-09-30T21:25:43Z" - source: endpoint-observation locator: https://accounts.google.com/.well-known/oauth-authorization-server name: Google authorization-server metadata classification: official - observed_at: "2026-07-31T19:17:08Z" + observed_at: "2026-09-30T21:25:43Z" + - source: repository-doctrine + locator: doctrine/speakeasy-setup.md + name: Speakeasy setup canonical section + classification: official + observed_at: "2026-09-30T21:25:43Z" diff --git a/guides/google-compute-engine/research.md b/guides/google-compute-engine/research.md index 1c13605..5817d6f 100644 --- a/guides/google-compute-engine/research.md +++ b/guides/google-compute-engine/research.md @@ -442,8 +442,9 @@ all steps below happen inside this one project. - "In the **Name** field, enter a name for your application." - "In the **Authorized redirect URIs** section, click **+ Add URI**, and then enter" the callback URL — paste - `{{ gram.oauth.callback_url }}` (copied from the Speakeasy - **Attach Remote Identity Provider** sheet, see Speakeasy setup). + `{{ gram.oauth.callback_url }}` directly. The Speakeasy + **Identity** section does not display the redirect URI, so this step + carries the callback check. - The page also documents an "**Authorized JavaScript origins**" section for "Applications that use client-side JavaScript to access Google's APIs" — not this flow; leave it empty (flagged @@ -481,52 +482,63 @@ all steps below happen inside this one project. ## Speakeasy setup -Transcluded from `doctrine/speakeasy-setup.md` (canonical Speakeasy-side -flow; anchors `{#add-server-in-speakeasy}` and -`{#connect-speakeasy-credentials}` are fixed there and carried -verbatim — never re-minted). Provenance for the transcluded facts: -`doctrine/speakeasy-setup.md` (product source `speakeasy-api/gram`, -`client/dashboard`, `main` @ `96f7f73` for add-server and manual OAuth -labels), observed this run (2026-07-31T19:17:08Z). Per-guide values the -skeleton renders with: - -- **Add-server path**: catalog only. The Speakeasy MCP Catalog lookup is - present, matched registry name `com.googleapis.compute/mcp`, title - **Google Compute Engine**. In **Sources**, click **Add Source**, choose - **3rd-party server**, search for `Google Compute Engine` on the **MCP - Catalog** page using **Search MCP servers...**, open the matched entry - with **View**, click **Add**, and then click **Add to Project** in the - **Add to Project** dialog. This creates the hosted MCP server and opens - its **Overview** page. Do not render the Custom remote server path. -- **Remote URL**: `https://compute.googleapis.com/mcp` (catalog-backed - server fact; the Control Plane proxies remote servers over - streamable-http, matching this server's transport). -- **Authentication Option**: `oauth-client` (OAuth with a - pre-registered client; `client_registration: manual`). The provider - publishes discoverable OAuth metadata (protected-resource and - authorization-server metadata, observed this run — so **Use - Discovered** may be offered), but Dynamic Client Registration is - unsupported, so a manually created client is required either way; - the manual path (**Configure Manually**, **Client Type** → - **Manual**) is the documented fit. -- The **Redirect URI** shown later in the **Attach Remote Identity - Provider** sheet is the same callback represented by - `{{ gram.oauth.callback_url }}`. In {#create-oauth-client}, the reader - pastes that template key directly into **Authorized redirect URIs**; - do not send the reader into Speakeasy mid-way through External setup. -- Credential fields and their producing steps: - - **Client ID** ← {#copy-client-credentials}. - - **Client Secret (optional)** ← {#copy-client-credentials} — for - Google web-application clients the secret is required at token - exchange (the authorization server supports `client_secret_post` / - `client_secret_basic`; observed AS metadata), so the guide treats - the field as required despite its "(optional)" label. - - Scopes the provider requires: - `https://www.googleapis.com/auth/compute` (see the scope conflict - in Server facts and open questions). -- **Further-reading URL** for the closing pointer: - `https://docs.cloud.google.com/compute/docs/use-compute-engine-mcp` - (the provider's primary MCP documentation page). +Transcluded from `doctrine/speakeasy-setup.md` (product source +`speakeasy-api/gram`, `client/dashboard`, `main` @ `68b3f78`), observed +`2026-09-30T21:25:43Z`. Anchors `{#add-server-in-speakeasy}` and +`{#connect-speakeasy-credentials}` are fixed there and carried verbatim. + +Per-guide values: + +- Remote URL: `https://compute.googleapis.com/mcp` (not tenanted). +- Add-server path: **From the catalog** only (`speakeasy_add_server: + catalog`). Speakeasy MCP Catalog search for `Compute Engine` on + `2026-09-30` returned **Google Compute Engine** + (`com.googleapis.compute/mcp`). Search term: `Google Compute Engine`. +- Authentication Option: `oauth-client` → **User Identity**. +- Probe outcome: `initialize` POST (with + `Accept: application/json, text/event-stream`) returned **200 + unauthenticated**, protocol `2025-06-18`. The catalog entry has no OAuth + client registration, so **Add to Project** preselects **No Identity**; the + reader selects **User Identity**. +- PRM: `https://compute.googleapis.com/.well-known/oauth-protected-resource/mcp` + names issuer `https://accounts.google.com/` and advertises only + `https://www.googleapis.com/auth/compute`. +- Issuer metadata: `https://accounts.google.com` publishes authorization + endpoint `https://accounts.google.com/o/oauth2/v2/auth` and token endpoint + `https://oauth2.googleapis.com/token`; no `registration_endpoint` and no + `client_id_metadata_document_supported`. Discovery works; no custom + provider route is needed. +- Registration choice: **Manual**. Creation with **User Identity** leaves the + server **Disabled** with a note to finish in **Settings > Identity**; this + is expected, and **Server Availability** must be turned on afterwards. +- Credential fields: **Client ID** and **Client secret** from + {#copy-client-credentials}; Google requires the secret despite the + "Optional" placeholder (the issuer advertises only `client_secret_post` + and `client_secret_basic`). +- Scope under **Advanced > Scope**: `https://www.googleapis.com/auth/compute` + (endpoint-advertised; see the open question on the documented + `.read-only`/`.read-write` strings, still present on the provider page on + `2026-09-30`). Do not leave it blank: the audit of this guide observed a + blank scope yielding a token without `compute`. +- First connection: an account with the roles from {#grant-iam-roles}; an + External app in **Testing** also needs the account under **Test users** + ({#consent-screen}). +- Screenshot notes: the **Add to Project** dialog with **User Identity** + selected; **Settings > Identity** with the Google provider and **Manual**, + credentials redacted. +- Further-reading URL: + `https://docs.cloud.google.com/compute/docs/use-compute-engine-mcp`. + +### Add the server in Speakeasy {#add-server-in-speakeasy} + +Catalog path with **User Identity** selected in **Add to Project**, per the +values above. + +### Connect your credentials {#connect-speakeasy-credentials} + +**Settings > Identity** > **User Identity** > Google provider > **Manual** +with the values above, **Save**, then **Settings > Danger Zone > Server +Availability** > **Enable MCP server**. ## Open questions @@ -764,5 +776,13 @@ provenance uses this run's workflow timestamp, `2026-07-31T19:17:08Z`: drawn from them. - `doctrine/speakeasy-setup.md` (repo-canonical Speakeasy-side flow; product source `speakeasy-api/gram` `client/dashboard` `main` @ - `96f7f73`) — backs every Speakeasy-side label transcluded above; - observed this run. + `68b3f78`) — backs every Speakeasy-side label transcluded above; + observed `2026-09-30T21:25:43Z`. +- Re-observed `2026-09-30T21:25:43Z`: `https://compute.googleapis.com/mcp` + (`initialize` 200 unauthenticated, protocol `2025-06-18`), its + protected-resource metadata (issuer `https://accounts.google.com/`, scope + `https://www.googleapis.com/auth/compute`), Google's authorization-server + metadata (no registration endpoint, no CIMD), the Compute Engine MCP page + (server URL and the `.read-only`/`.read-write` scope table unchanged), and + the Speakeasy MCP Catalog search for `Compute Engine` (entry + **Google Compute Engine**, `com.googleapis.compute/mcp`). diff --git a/guides/google-compute-engine/speakeasy.md b/guides/google-compute-engine/speakeasy.md index e99d22b..f4c2b33 100644 --- a/guides/google-compute-engine/speakeasy.md +++ b/guides/google-compute-engine/speakeasy.md @@ -4,86 +4,43 @@ In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select **MCP**, then click **Add new** to open **Add MCP server**. -Choose **From the catalog**. On the **MCP Catalog** page, search for `Google Compute Engine` in **Search MCP servers...**, open the matched entry, and click **Add**. In the **Add to Project** dialog, click **Add to Project**. +1. Choose **From the catalog**. +2. On the **MCP Catalog** page, search for `Google Compute Engine` in **Search MCP servers...**. +3. Open the **Google Compute Engine** catalog entry. +4. Click **Add**. This opens the **Add to Project** dialog. +5. Under **Identity**, select **User Identity**. The dialog preselects **No Identity** for this entry, so change it. +6. Click **Add to Project**. +7. If the dialog offers a **Guardrails** step, finish it or click **Skip for now**. +8. When the dialog finishes, the result reads "Added, but disabled until identity is set up." Click **Finish setup** to open the server's **Settings**. -After the server is added, click **Configure MCP settings** on the completion screen to open the server, then open **Settings**. +Speakeasy keeps the new server **Disabled** and says to finish setup in **Settings > Identity**. This is expected for Compute Engine; continue with the next section. - + ### Connect your credentials {#connect-speakeasy-credentials} -Open the server's **Settings** (from **Overview** for a hosted remote server, or **Configure MCP settings** after a catalog addition). +Open the server's **Settings** and find the **Identity** section. -#### Choose an authentication provider +1. Confirm **User Identity** is selected. +2. Under **Choose an identity provider**, confirm the preselected Google provider (`https://accounts.google.com`). A new provider shows **Will be created**. If a different provider is preselected, open the picker, search in **Search identity providers…**, and choose the Google provider. +3. Choose **Manual**. If **Existing client** is preselected, switch to **Manual** unless that client is the one created in [Create the OAuth client](external.md#create-oauth-client) with the Compute Engine scope. +4. Paste the **Client ID** from [Copy the client credentials](external.md#copy-client-credentials) into **Client ID**. +5. Paste the **Client secret** from [Copy the client credentials](external.md#copy-client-credentials) into **Client secret**. Google requires this secret even though the field shows "Optional". +6. Under **Advanced > Scope**, enter this value. Do not leave **Scope** blank; without it, the token can lack Compute Engine access. -- If **Authentication** is unconfigured, choose **Use Discovered** when available; otherwise choose **Configure Manually**. -- If authentication is configured but no provider is attached, use **Connected services** > **Add provider**. -- If the intended provider is already attached, use its existing controls. Do not attach a duplicate; check its client against the requirements below and skip **Verify and attach**. - -In **Attach Remote Identity Provider**, the provider selector defaults to **Select existing** when the project has issuers. Select the appropriate existing Google provider and skip new-provider setup. - -#### New provider only - -1. Choose **Add new** and enter **Issuer URL**: - - ```text - https://accounts.google.com/ ``` - -2. Confirm the auto-derived **Slug** is unique in the project. -3. Discovery runs automatically for a seeded issuer URL. After typing or changing the URL, click **Discover** only if offered. -4. Review the endpoints, or enter these Google OAuth values if discovery does not populate them. - - Authorization endpoint: - - ```text - https://accounts.google.com/o/oauth2/v2/auth - ``` - - Token endpoint: - - ```text - https://oauth2.googleapis.com/token + https://www.googleapis.com/auth/compute ``` -#### Choose a session client - -- **Reuse:** Under **Session Client**, choose **Select existing** when available and select the appropriate Google OAuth client. Skip credential entry; continue to **Check client requirements**. -- **Create:** Choose **Add new** when available and set **Client Type** to **Manual**. For a new provider, complete the new-client form below. - -#### New session client only - -1. Paste the client ID from - [Copy the client credentials](external.md#copy-client-credentials) into - **Client ID**. -1. Paste the client secret into **Client Secret (optional)** — despite - the label, Google requires the secret, so treat the field as - required. - -#### Check client requirements - -For both new and reused clients, verify the Google app's approved audience and publishing status. An **External** app in **Testing** must list each connecting account under **Test users**. Reusing a client does not require entering its credentials again. - -Verify the new or reused Google client has these required scopes, matching the Google app's **Data Access** configuration: - -```text -https://www.googleapis.com/auth/compute -``` - -#### Verify and attach +7. Click **Save**. If asked to confirm, click **Save changes**. -1. Confirm that the callback URL registered with the provider is `{{ gram.oauth.callback_url }}`. For a new manual client, also compare it with the sheet's displayed **Redirect URI**. The existing-client selection does not display that field; check the registered callback in the provider's app settings instead. -2. Click **Attach Identity Provider**. +Turn the server on: -For the provider-side callback setting, see [Create the OAuth client](external.md#create-oauth-client). +1. Open **Settings > Danger Zone > Server Availability**. +2. Turn on the switch (**Enable MCP server**) so it shows **Enabled**. - +Each user who then connects signs in with their own Google account. They need the roles from [Grant IAM roles](external.md#grant-iam-roles) and, while an **External** app's publishing status is **Testing**, a listing under **Test users** in [Configure the consent screen](external.md#consent-screen). -Each user who then connects signs in with their own Google account. -For their sign-in to succeed, they need the roles from -[Grant IAM roles](external.md#grant-iam-roles), and — while an External app's -publishing status is **Testing** — a listing under **Test users** in -[Configure the consent screen](external.md#consent-screen). + -This guide covers setup only. For anything beyond it — billing, tool -behavior, limits — see [Google's Compute Engine MCP documentation](https://docs.cloud.google.com/compute/docs/use-compute-engine-mcp). +This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Google's Compute Engine MCP documentation](https://docs.cloud.google.com/compute/docs/use-compute-engine-mcp). diff --git a/guides/google-docs/external.md b/guides/google-docs/external.md index 35901aa..d3088f5 100644 --- a/guides/google-docs/external.md +++ b/guides/google-docs/external.md @@ -4,12 +4,26 @@ setup_version: 1 # Set up Google Docs -Sign in to [console.cloud.google.com](https://console.cloud.google.com) with an account that can select a Google Cloud project, enable APIs, configure the **Google Auth platform**, and create OAuth credentials. Google does not document a Google Docs MCP-specific paid plan or license requirement. Enabling APIs requires `serviceusage.services.enable`; **Service Usage Admin** provides this permission. Each account that will connect needs **MCP Tool User** (`roles/mcp.toolUser`) on the project and access to the Google Docs it will use. Obtain the approved support and contact addresses before you begin. If your organization restricts high-risk Drive and Docs scopes or unconfigured apps, you also need a Google Workspace administrator with the **Service Settings administrator** privilege. +Sign in to [console.cloud.google.com](https://console.cloud.google.com) with an account that can select a Google Cloud project, enable APIs, configure the **Google Auth platform**, and create OAuth credentials. Google does not document a Google Docs MCP-specific paid plan or license requirement, but the Docs MCP server is available only through the Google Workspace Developer Preview Program, so the project must be registered in it. Enabling APIs requires `serviceusage.services.enable`; **Service Usage Admin** provides this permission. Granting **MCP Tool User** (`roles/mcp.toolUser`) requires IAM administration access on the project. Each account that will connect needs that role and access to the Google Docs it will use. Obtain the approved support and contact addresses before you begin. If your organization restricts high-risk Drive and Docs scopes or unconfigured apps, you also need a Google Workspace administrator with the **Service Settings administrator** privilege. + +### Join the Google Workspace Developer Preview Program {#join-developer-preview} + +1. Open [developers.google.com/workspace/preview](https://developers.google.com/workspace/preview). +2. Review the **Developer Preview Program Terms** with the application or security owner. +3. Click **Apply to join the Developer Preview Program**. +4. In the application form, enter the requested Google Workspace account and Google Cloud project information. +5. Agree to the terms only with organizational approval. +6. Submit the form with the visible or equivalent submission control. +7. Wait for Google's project-registration confirmation at the submitted email address. Google says this should complete within a couple of days. + +Use the registered project for every Google Cloud step that follows. + + ### Enable the Docs MCP APIs {#enable-docs-mcp-apis} 1. In the toolbar, open the resource selector. -2. Select the Google Cloud project that will own the credentials. +2. Select the Google Cloud project registered in the Developer Preview Program. 3. Open **APIs & Services** > **Library**. 4. Open **Google Docs API**. 5. Click **Enable**. @@ -19,9 +33,23 @@ Sign in to [console.cloud.google.com](https://console.cloud.google.com) with an If **Enable** is unavailable, ask the project administrator for `serviceusage.services.enable`. + + +### Grant the MCP Tool User role {#grant-mcp-tool-user} + +1. Open [console.cloud.google.com/iam-admin/iam](https://console.cloud.google.com/iam-admin/iam). +2. Select the same project. +3. Click **Grant access**. +4. In **New principals**, enter the Google Account email of a user who will connect from the Speakeasy AI Control Plane. +5. Click **Select a role**. +6. Search for `MCP Tool User`. +7. Select **MCP Tool User**. +8. Click **Save**. +9. Repeat these steps for every connecting user. + Open **Google Auth platform** > **Branding**. - + ### Configure the OAuth consent screen {#configure-oauth-consent} diff --git a/guides/google-docs/meta.yaml b/guides/google-docs/meta.yaml index d1a765b..8244c55 100644 --- a/guides/google-docs/meta.yaml +++ b/guides/google-docs/meta.yaml @@ -22,6 +22,8 @@ credential_setup: - external.md#create-oauth-client - external.md#copy-client-credentials requirements: + - id: developer-preview + description: Google has registered the Google Cloud project in the Google Workspace Developer Preview Program, which the Docs MCP server requires - id: google-cloud-project description: A Google Cloud project that will own the Google Docs API, Google Docs MCP API, and OAuth client - id: google-cloud-administrator @@ -45,23 +47,33 @@ remotes: locator: https://developers.google.com/workspace/docs/api/guides/configure-mcp-server name: Configure the Docs MCP server classification: official - observed_at: "2026-08-29T15:13:21Z" + observed_at: "2026-09-30T21:25:45Z" - source: endpoint-observation locator: https://docsmcp.googleapis.com/.well-known/oauth-protected-resource/mcp/v1 name: Google Docs MCP protected-resource metadata classification: official - observed_at: "2026-08-29T15:13:21Z" + observed_at: "2026-09-30T21:25:45Z" provenance: + - source: provider-documentation + locator: https://developers.google.com/workspace/preview + name: Google Workspace Developer Preview Program + classification: official + observed_at: "2026-09-30T21:25:45Z" + - source: provider-documentation + locator: https://docs.cloud.google.com/iam/docs/grant-role-console + name: Grant an IAM role by using the Google Cloud console + classification: official + observed_at: "2026-09-30T21:25:45Z" - source: provider-documentation locator: https://developers.google.com/workspace/docs/api/guides/configure-mcp-server name: Configure the Docs MCP server classification: official - observed_at: "2026-08-29T15:13:21Z" + observed_at: "2026-09-30T21:25:45Z" - source: provider-documentation locator: https://developers.google.com/workspace/guides/configure-mcp-servers name: Configure the Google Workspace MCP servers classification: official - observed_at: "2026-08-29T15:13:21Z" + observed_at: "2026-09-30T21:25:45Z" - source: provider-documentation locator: https://developers.google.com/workspace/guides/configure-oauth-consent name: Configure the OAuth consent screen and choose scopes @@ -91,7 +103,7 @@ provenance: locator: https://docs.cloud.google.com/mcp/set-up-authentication-mcp-servers name: Set up authentication to Google and Google Cloud MCP servers classification: official - observed_at: "2026-08-29T15:13:21Z" + observed_at: "2026-09-30T21:25:45Z" - source: provider-documentation locator: https://docs.cloud.google.com/service-usage/docs/enable-disable name: Enable and disable services @@ -111,17 +123,17 @@ provenance: locator: https://docsmcp.googleapis.com/.well-known/oauth-protected-resource/mcp/v1 name: Google Docs MCP protected-resource metadata classification: official - observed_at: "2026-08-29T15:13:21Z" + observed_at: "2026-09-30T21:25:45Z" - source: endpoint-observation locator: https://accounts.google.com/.well-known/oauth-authorization-server name: Google authorization-server metadata classification: official - observed_at: "2026-08-29T15:13:21Z" + observed_at: "2026-09-30T21:25:45Z" - source: repository-doctrine locator: doctrine/speakeasy-setup.md name: Speakeasy setup canonical section classification: official - observed_at: "2026-08-29T15:13:21Z" + observed_at: "2026-09-30T21:25:45Z" - source: pulsemcp locator: credential-free Pulse snapshot name: Google Docs catalog lookup diff --git a/guides/google-docs/research.md b/guides/google-docs/research.md index 37ad973..f220240 100644 --- a/guides/google-docs/research.md +++ b/guides/google-docs/research.md @@ -68,8 +68,8 @@ redirect URIs**: | Client ID | **OAuth 2.0 client created** in {#copy-client-credentials} | | Client Secret | **Client secrets** in {#copy-client-credentials}; copy when shown and store securely | -The same callback appears later as **Redirect URI** in the Control Plane's -**Attach Remote Identity Provider** sheet. Each connecting user completes +The Control Plane's **Identity** section does not display the redirect URI, +so this registration is the only callback check. Each connecting user completes Google's browser authorization using the account whose Docs permissions should apply. @@ -79,6 +79,28 @@ Sign in to the Google Cloud console, select the project that will own the OAuth client, enable both APIs, configure **Google Auth platform**, create the client, copy its credentials, and conditionally allow it in the Google Admin console. +### Join the Google Workspace Developer Preview Program {#join-developer-preview} + +- Re-verified at `2026-09-30T21:25:45Z`: Google's Docs MCP setup page lists "Membership in + the Google Workspace Developer Preview Program" as the first prerequisite, + and the program page lists the **Docs MCP server** among its preview + features. +- Open `https://developers.google.com/workspace/preview` and review the + **Developer Preview Program Terms** with the application or security owner. +- Click **Apply to join the Developer Preview Program**. The form requests + "Google Workspace account and Google Cloud project information"; Google does + not publish its exact field labels, so the submit control is rendered as + "visible or equivalent". Agree to the terms only with organizational + approval. +- Wait for the project-registration confirmation. Google says "The whole + process should be done within a couple of days." +- Result and transition: the registered project is used for every Google + Cloud step that follows. +- Values entered: organization-specific Workspace account and Cloud project + information. Values copied: none. +- Screenshot note: the program page with **Docs MCP server** listed under + **Latest features**; do not capture application-form data. + ### Enable the Docs MCP APIs {#enable-docs-mcp-apis} - Open [console.cloud.google.com](https://console.cloud.google.com). On the @@ -88,10 +110,25 @@ copy its credentials, and conditionally allow it in the Google Admin console. - Return to **Library**. Open **Google Docs MCP API**, then click **Enable**. - If **Enable** is unavailable, obtain `serviceusage.services.enable` from the project administrator before continuing. -- Continue to **Google Auth platform** > **Branding**. +- Continue to **IAM** to grant **MCP Tool User**. - Values entered: none. Values copied: none. - Screenshot note: **Google Docs MCP API** showing its enabled state. +### Grant the MCP Tool User role {#grant-mcp-tool-user} + +- Added `2026-09-30T21:25:45Z` per the setup-docs audit: the prerequisites + already required **MCP Tool User** but no step granted it. Google Cloud's MCP + authentication page says: "ask your administrator to grant you the MCP Tool + User (roles/mcp.toolUser) IAM role", which contains `mcp.tools.call`. +- Open `https://console.cloud.google.com/iam-admin/iam` and select the same + project. Click **Grant access**. +- In **New principals**, enter a connecting user's Google Account email. +- Click **Select a role**, search for `MCP Tool User`, select **MCP Tool + User**, and click **Save**. Repeat for each connecting user. +- Result and transition: continue to **Google Auth platform** > **Branding**. +- Values entered: user emails and **MCP Tool User**. Values copied: none. +- Screenshot note: **Grant access** with the principal and **MCP Tool User**. + ### Configure the OAuth consent screen {#configure-oauth-consent} - Before starting, obtain approved support and contact email addresses. Google @@ -178,62 +215,77 @@ Docs scopes or block unconfigured apps. ## Speakeasy setup -Transcluded from `doctrine/speakeasy-setup.md`, observed at -`2026-08-29T15:13:21Z`. Its fixed anchors are carried verbatim. - -The credential-free Pulse snapshot observed at `2026-08-29T15:13:21Z` had no -confident exact Google Docs MCP catalog match. Preserve -`speakeasy_add_server: custom-remote` and render only the Custom remote path. - -### Add the server in Speakeasy {#add-server-in-speakeasy} - -In the Speakeasy AI Control Plane sidebar, under **Connect**, select -**Sources**, then click **Add Source**. +Transcluded from `doctrine/speakeasy-setup.md` (gram `main` `68b3f78`), +re-rendered at `2026-09-30T21:25:45Z`. The fixed anchors are carried verbatim. This replaces +the retired **Authentication** / **Attach Remote Identity Provider** flow. -Choose **Custom remote server**. On the **Add a custom remote MCP server** -page, paste this value into **Remote MCP server URL**: - -``` -https://docsmcp.googleapis.com/mcp/v1 -``` +Per-guide values: -Click **Add server**. This creates the hosted MCP server and opens its -**Overview** page. +- Remote URL: `https://docsmcp.googleapis.com/mcp/v1` (shared public endpoint, not tenanted). +- Add-server path: Custom remote only (**Hosted remotely**). `speakeasy_add_server: custom-remote` is preserved (Pulse + snapshot had no confident exact catalog match). +- Authentication Option: `oauth-client` (OAuth) → **User Identity**. Client + ID and Client secret come from {#copy-client-credentials}. +- Probe outcome (`2026-09-30T21:25:45Z`): an unauthenticated JSON-RPC `initialize` POST with + `Accept: application/json, text/event-stream` returned HTTP 200 with a + result (protocol `2025-06-18`), not a 401. The create form therefore + preselects **No Identity**; the reader must select **User Identity**. +- PRM: `https://docsmcp.googleapis.com/.well-known/oauth-protected-resource/mcp/v1` + names issuer `https://accounts.google.com/`. The dashboard's discovery + probes this path-suffixed location (the origin-root location returns an + error), so the provider picker preselects the Google provider or badges it + **Will be created**. +- Registration: `https://accounts.google.com/.well-known/oauth-authorization-server` + advertises no `registration_endpoint` and no + `client_id_metadata_document_supported`; Google states its remote MCP + servers support neither DCR nor CIMD. The dashboard defaults to **Manual** + (or **Existing client** when one exists). Registration choice: **Manual**. + Automatic configuration at creation cannot register a client, so the server + is saved **Disabled** and must be enabled under **Settings > Danger Zone > + Server Availability** after the Identity section is saved. +- Token endpoint auth: the issuer advertises `client_secret_post` and + `client_secret_basic`; the dashboard picks the method automatically. +- PRM `scopes_supported`: `https://www.googleapis.com/auth/drive.readonly`, `https://www.googleapis.com/auth/documents.readonly`, `https://www.googleapis.com/auth/drive`, `https://www.googleapis.com/auth/documents`. This is + broader than the consent-screen configuration (full `drive`), so **Scope** + must not be left blank. +- Scope string for **Advanced > Scope** (space-separated, one line): + `https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/documents.readonly https://www.googleapis.com/auth/documents` +- Further-reading URL: the provider's MCP setup page listed in Provenance. - +### Add the server in Speakeasy {#add-server-in-speakeasy} -Per-guide values: +Under **MCP Gateway**, select **MCP**, click **Add new**, and choose **Hosted +remotely**. On **New remote MCP server**, paste `https://docsmcp.googleapis.com/mcp/v1` into **MCP server +URL**, leave **User session issuer** at its default, and click **Verify +connectivity**. Under **Identity**, select **User Identity** (the page +preselects **No Identity** for this 200-unauthenticated server). Leave +**Guardrails** off if it appears, then click **Save**. The result keeps the +server **Disabled** and says to finish setup in **Settings > Identity**; this +is expected for Manual registration. -- Remote URL: `https://docsmcp.googleapis.com/mcp/v1` -- Transport: `streamable-http`; **Transport** is read-only. -- Authentication Option: `oauth-client`, manual OAuth. -- Required provider scopes: the four scope URLs listed under Server facts. +Screenshot note: **New remote MCP server** with the URL verified and **User +Identity** selected. ### Connect your credentials {#connect-speakeasy-credentials} -From the server's **Overview**, open **Settings**. Under **Authentication**, -click **Configure Manually**, or click **Use Discovered** when offered because -the provider publishes protected-resource and authorization-server metadata. +Open **Settings** > **Identity**. Confirm **User Identity**. In **Choose an +identity provider**, confirm the Google provider (`https://accounts.google.com/`) +or pick it via **Search identity providers…**. Choose **Manual**. Paste +**Client ID** and **Client secret** from {#copy-client-credentials}; Google requires the +secret despite the "Optional" placeholder. Under **Advanced > Scope**, enter the +scope string above and do not leave it blank. Click **Save**. Then open +**Settings > Danger Zone > Server Availability** and turn on **Enable MCP +server** so it shows **Enabled**. -In the **Attach Remote Identity Provider** sheet, set **Client Type** to -**Manual**. Paste **Client ID** and **Client Secret (optional)** from -{#copy-client-credentials}, then click **Attach Identity Provider**. Google -requires the generated client secret for this MCP client path. Confirm that the -sheet's **Redirect URI** matches the callback registered in -{#create-oauth-client}. +This surface does not display the redirect URI; {#create-oauth-client} +registers `{{ gram.oauth.callback_url }}` directly. -When a client first needs access, complete Google's browser authorization with -the intended account. If the app is External and in **Testing**, that account -must be listed under **Test users**. +On first use, Google's browser authorization prompt appears. The account must +hold **MCP Tool User** ({#grant-mcp-tool-user}) and, for an External app in +**Testing**, be listed under **Test users**. - - -Further-reading URL: -`https://developers.google.com/workspace/docs/api/guides/configure-mcp-server`. - -This guide covers setup only. For anything beyond it — billing, tool behavior, -limits — see Google's Docs MCP documentation at -https://developers.google.com/workspace/docs/api/guides/configure-mcp-server. +Screenshot note: **Settings > Identity** with **User Identity**, the Google +provider, and **Manual** selected; values redacted. ## Research limitations @@ -302,3 +354,15 @@ All sources below were observed at `2026-08-29T15:13:21Z`: - `doctrine/speakeasy-setup.md` — Control Plane labels and fixed anchors. - Credential-free Pulse snapshot — no confident exact Google Docs MCP catalog match; safe Custom remote override retained. + +Re-observed at `2026-09-30T21:25:45Z` (identity-section refresh): the product MCP setup page, +`https://developers.google.com/workspace/guides/configure-mcp-servers`, +`https://docs.cloud.google.com/mcp/set-up-authentication-mcp-servers`, the MCP +endpoint `initialize` probe, the path-suffixed PRM, Google's +authorization-server metadata, and `doctrine/speakeasy-setup.md` (gram +`68b3f78`). Newly drawn from: + +- `https://developers.google.com/workspace/preview` — Developer Preview + Program terms, apply action, form contents, timeline, and listed MCP servers. +- `https://docs.cloud.google.com/iam/docs/grant-role-console` — IAM + **Grant access**, **New principals**, role selection, and **Save**. diff --git a/guides/google-docs/speakeasy.md b/guides/google-docs/speakeasy.md index 2d9ecd0..a5dcccb 100644 --- a/guides/google-docs/speakeasy.md +++ b/guides/google-docs/speakeasy.md @@ -11,79 +11,37 @@ https://docsmcp.googleapis.com/mcp/v1 ``` -5. Click **Verify connectivity**, then **Save**. +5. Leave **User session issuer** at its default. +6. Click **Verify connectivity**. +7. Under **Identity**, select **User Identity**. The page preselects **No Identity** for this server, so change it. +8. If **Guardrails** appears, leave it off. +9. Click **Save**. -This creates the hosted MCP server and opens its **Overview** page. The **Transport** field is read-only. +Speakeasy saves the server as **Disabled** and says to finish setup in **Settings > Identity**. This is expected; the next section completes it. - + ### Connect your credentials {#connect-speakeasy-credentials} -Open the server's **Settings** (from **Overview** for a hosted remote server, or **Configure MCP settings** after a catalog addition). +1. Open the server's **Settings** and find the **Identity** section. +2. Confirm that **User Identity** is selected. +3. In **Choose an identity provider**, confirm that the preselected provider is Google (`https://accounts.google.com/`). If another provider is shown, open the picker, search in **Search identity providers…**, and choose the Google provider. A provider badged **Will be created** is created when you save. +4. Choose **Manual**. +5. In **Client ID**, paste the **Client ID** from [Copy the client credentials](external.md#copy-client-credentials). +6. In **Client secret**, paste the **Client secret** from the same section. Google requires it even though the field says "Optional". +7. Open **Advanced**. In **Scope**, enter this value on one line: -#### Choose an authentication provider - -- If **Authentication** is unconfigured, choose **Use Discovered** when available; otherwise choose **Configure Manually**. -- If authentication is configured but no provider is attached, use **Connected services** > **Add provider**. -- If the intended provider is already attached, use its existing controls. Do not attach a duplicate; check its client against the requirements below and skip **Verify and attach**. - -In **Attach Remote Identity Provider**, the provider selector defaults to **Select existing** when the project has issuers. Select the appropriate existing Google provider and skip new-provider setup. - -#### New provider only - -1. Choose **Add new** and enter **Issuer URL**: - - ```text - https://accounts.google.com/ - ``` - -2. Confirm the auto-derived **Slug** is unique in the project. -3. Discovery runs automatically for a seeded issuer URL. After typing or changing the URL, click **Discover** only if offered. -4. Review the endpoints, or enter these Google OAuth values if discovery does not populate them. - - Authorization endpoint: - - ```text - https://accounts.google.com/o/oauth2/v2/auth ``` - - Token endpoint: - - ```text - https://oauth2.googleapis.com/token + https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/documents.readonly https://www.googleapis.com/auth/documents ``` -#### Choose a session client - -- **Reuse:** Under **Session Client**, choose **Select existing** when available and select the appropriate Google OAuth client. Skip credential entry; continue to **Check client requirements**. -- **Create:** Choose **Add new** when available and set **Client Type** to **Manual**. For a new provider, complete the new-client form below. - -#### New session client only - -1. In **Client ID**, paste the value you [copied from Google](external.md#copy-client-credentials). -1. In **Client Secret (optional)**, paste the secret you [copied from Google](external.md#copy-client-credentials). Google requires this value. - -#### Check client requirements - -For both new and reused clients, verify the Google app's approved audience and publishing status. An **External** app in **Testing** must list each connecting account under **Test users**. Reusing a client does not require entering its credentials again. - -Confirm the selected client includes the required scopes below. For a new client, configure **Scope (override)**; for a reused client, inspect the read-only **Scope** value. If it does not match, choose **Add new** to create a correctly scoped client; the attach sheet cannot edit a reused client. - -For a new client, enter this value: - - ``` - https://www.googleapis.com/auth/drive.readonly, https://www.googleapis.com/auth/drive.file, https://www.googleapis.com/auth/documents.readonly, https://www.googleapis.com/auth/documents - ``` - -#### Verify and attach - -1. Confirm that the callback URL registered with the provider is `{{ gram.oauth.callback_url }}`. For a new manual client, also compare it with the sheet's displayed **Redirect URI**. The existing-client selection does not display that field; check the registered callback in the provider's app settings instead. -2. Click **Attach Identity Provider**. + Do not leave **Scope** blank. A blank value requests every scope the server advertises, including full Drive access, which the consent screen does not grant. -For the provider-side callback setting, see [created the OAuth client](external.md#create-oauth-client). +8. Click **Save**. +9. Open **Settings > Danger Zone > Server Availability** and turn on **Enable MCP server** so it shows **Enabled**. -Complete Google's browser authorization with the intended account. If the app is **External** and in **Testing**, that account must be listed under **Test users**. +When a person first uses the server, Google's browser authorization prompt appears. They must sign in with an account granted [MCP Tool User](external.md#grant-mcp-tool-user). If the app's audience is **External** and in **Testing**, the account must also be listed under **Test users**. - + This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Google's Docs MCP documentation](https://developers.google.com/workspace/docs/api/guides/configure-mcp-server). diff --git a/guides/google-drive/external.md b/guides/google-drive/external.md index 51412bd..96cdc89 100644 --- a/guides/google-drive/external.md +++ b/guides/google-drive/external.md @@ -4,9 +4,23 @@ setup_version: 1 # Set up Google Drive -Use a Google Cloud project where you can enable services, configure the Google Auth platform, create credentials, and grant project roles. You need **Service Usage Admin** or **Owner** to enable the APIs and appropriate IAM administration access to grant **MCP Tool User**. Every connecting user needs a Google Account with access to the intended Drive files. +The Drive MCP server is available only through the Google Workspace Developer Preview Program, so the Google Cloud project must be registered in it. Use a Google Cloud project where you can enable services, configure the Google Auth platform, create credentials, and grant project roles. You need **Service Usage Admin** or **Owner** to enable the APIs and appropriate IAM administration access to grant **MCP Tool User**. Every connecting user needs a Google Account with access to the intended Drive files. -Sign in at [console.cloud.google.com](https://console.cloud.google.com) and select the project that will own the APIs and credentials. If your organization restricts high-risk Drive scopes, arrange access to a **Service Settings administrator** and obtain an approved app-access setting from the application or cloud security owner. +Sign in at [console.cloud.google.com](https://console.cloud.google.com) and select the project registered in the Developer Preview Program. It owns the APIs and credentials. If your organization restricts high-risk Drive scopes, arrange access to a **Service Settings administrator** and obtain an approved app-access setting from the application or cloud security owner. + +### Join the Google Workspace Developer Preview Program {#join-developer-preview} + +1. Open [developers.google.com/workspace/preview](https://developers.google.com/workspace/preview). +2. Review the **Developer Preview Program Terms** with the application or security owner. +3. Click **Apply to join the Developer Preview Program**. +4. In the application form, enter the requested Google Workspace account and Google Cloud project information. +5. Agree to the terms only with organizational approval. +6. Submit the form with the visible or equivalent submission control. +7. Wait for Google's project-registration confirmation at the submitted email address. Google says this should complete within a couple of days. + +Use the registered project for every Google Cloud step that follows. + + ### Enable the Google Drive API {#enable-drive-api} @@ -109,7 +123,7 @@ Do not add **Authorized JavaScript origins**. Before the next action, prepare an 1. In **OAuth 2.0 client created**, copy the **Client ID** to your approved secret store. 2. Under **Client secrets**, copy the **Client secret** to the same location. -3. Keep both values ready for [Speakeasy setup](speakeasy.md#connect-speakeasy-credentials). +3. Keep both values ready for [Speakeasy setup](speakeasy.md#add-server-in-speakeasy). If you lose the client secret before connecting, delete it and create a new one. diff --git a/guides/google-drive/meta.yaml b/guides/google-drive/meta.yaml index 7a163ce..dafc029 100644 --- a/guides/google-drive/meta.yaml +++ b/guides/google-drive/meta.yaml @@ -21,6 +21,8 @@ credential_setup: - external.md#create-oauth-client - external.md#copy-client-credentials requirements: + - id: developer-preview + description: Google has registered the Google Cloud project in the Google Workspace Developer Preview Program, which the Drive MCP server requires - id: google-cloud-project description: A Google Cloud project whose administrator can enable the Google Drive API and Google Drive MCP API, configure the Google Auth platform, create OAuth credentials, and grant connecting users the MCP Tool User role - id: workspace-policy-access @@ -39,7 +41,7 @@ remotes: locator: https://developers.google.com/workspace/drive/api/guides/configure-mcp-server name: Configure the Drive MCP server classification: official - observed_at: "2026-07-29T20:37:22Z" + observed_at: "2026-09-30T21:25:45Z" - source: provider-documentation locator: https://developers.google.com/workspace/drive/api/reference/mcp name: Google Drive MCP reference @@ -54,18 +56,23 @@ remotes: locator: https://drivemcp.googleapis.com/mcp/v1 name: Google Drive MCP endpoint classification: official - observed_at: "2026-07-29T20:37:22Z" + observed_at: "2026-09-30T21:25:45Z" - source: endpoint-observation locator: https://drivemcp.googleapis.com/.well-known/oauth-protected-resource/mcp/v1 name: Google Drive MCP protected-resource metadata classification: official - observed_at: "2026-07-29T20:37:22Z" + observed_at: "2026-09-30T21:25:45Z" provenance: + - source: provider-documentation + locator: https://developers.google.com/workspace/preview + name: Google Workspace Developer Preview Program + classification: official + observed_at: "2026-09-30T21:25:45Z" - source: provider-documentation locator: https://developers.google.com/workspace/drive/api/guides/configure-mcp-server name: Configure the Drive MCP server classification: official - observed_at: "2026-07-29T20:37:22Z" + observed_at: "2026-09-30T21:25:45Z" - source: provider-documentation locator: https://developers.google.com/workspace/drive/api/reference/mcp name: Google Drive MCP reference @@ -105,7 +112,7 @@ provenance: locator: https://docs.cloud.google.com/mcp/set-up-authentication-mcp-servers name: Set up authentication to Google and Google Cloud MCP servers classification: official - observed_at: "2026-07-29T20:37:22Z" + observed_at: "2026-09-30T21:25:45Z" - source: provider-documentation locator: https://docs.cloud.google.com/mcp/manage-mcp-servers name: Manage MCP servers @@ -140,19 +147,19 @@ provenance: locator: https://drivemcp.googleapis.com/mcp/v1 name: Google Drive MCP endpoint classification: official - observed_at: "2026-07-29T20:37:22Z" + observed_at: "2026-09-30T21:25:45Z" - source: endpoint-observation locator: https://drivemcp.googleapis.com/.well-known/oauth-protected-resource/mcp/v1 name: Google Drive MCP protected-resource metadata classification: official - observed_at: "2026-07-29T20:37:22Z" + observed_at: "2026-09-30T21:25:45Z" - source: endpoint-observation locator: https://accounts.google.com/.well-known/oauth-authorization-server name: Google authorization-server metadata classification: official - observed_at: "2026-07-29T20:37:22Z" + observed_at: "2026-09-30T21:25:45Z" - source: repository-doctrine locator: doctrine/speakeasy-setup.md name: Speakeasy setup canonical section classification: official - observed_at: "2026-07-29T20:37:22Z" + observed_at: "2026-09-30T21:25:45Z" diff --git a/guides/google-drive/research.md b/guides/google-drive/research.md index 2ed9182..53e2e05 100644 --- a/guides/google-drive/research.md +++ b/guides/google-drive/research.md @@ -12,6 +12,9 @@ researched_at: 2026-07-29T20:37:22Z - Transport: `streamable-http`. Google labels it **HTTP**; its MCP reference shows JSON-RPC over HTTPS with `application/json, text/event-stream`. - Launch stage: **Developer Preview** in Google's supported-products table. + Re-verified `2026-09-30T21:25:45Z`: the Drive setup page lists "Membership in + the Google Workspace Developer Preview Program" as a prerequisite + ({#join-developer-preview}). - Enable both **Google Drive API** (`drive.googleapis.com`) and **Google Drive MCP API** (`drivemcp.googleapis.com`) in the same Google Cloud project. - Authentication: OAuth 2.0 with a manually registered Web application @@ -59,8 +62,9 @@ Google generates: | OAuth scopes | The two Drive scopes listed in Server facts | Paste `{{ gram.oauth.callback_url }}` directly into **Authorized redirect -URIs** in {#create-oauth-client}. The Speakeasy AI Control Plane later shows -the same value as **Redirect URI** for confirmation. +URIs** in {#create-oauth-client}. The Control Plane's **Identity** section +does not display the redirect URI, so this registration is the only callback +check. Each user who connects must have **MCP Tool User**, access to the intended Drive files, permission under Workspace app-access policy, and—when the @@ -71,6 +75,28 @@ audience is External and Testing—membership in **Test users**. Sign in at `https://console.cloud.google.com` and select the project that will own the APIs and OAuth client. +### Join the Google Workspace Developer Preview Program {#join-developer-preview} + +- Re-verified at `2026-09-30T21:25:45Z`: Google's Drive MCP setup page lists "Membership in + the Google Workspace Developer Preview Program" as the first prerequisite, + and the program page lists the **Drive MCP server** among its preview + features. +- Open `https://developers.google.com/workspace/preview` and review the + **Developer Preview Program Terms** with the application or security owner. +- Click **Apply to join the Developer Preview Program**. The form requests + "Google Workspace account and Google Cloud project information"; Google does + not publish its exact field labels, so the submit control is rendered as + "visible or equivalent". Agree to the terms only with organizational + approval. +- Wait for the project-registration confirmation. Google says "The whole + process should be done within a couple of days." +- Result and transition: the registered project is used for every Google + Cloud step that follows. +- Values entered: organization-specific Workspace account and Cloud project + information. Values copied: none. +- Screenshot note: the program page with **Drive MCP server** listed under + **Latest features**; do not capture application-form data. + ### Enable the Google Drive API {#enable-drive-api} - Open Google's documented console flow: @@ -178,42 +204,77 @@ own the APIs and OAuth client. ## Speakeasy setup -Transcluded from `doctrine/speakeasy-setup.md`, observed at -`2026-07-29T20:37:22Z`. The fixed anchors are carried verbatim. +Transcluded from `doctrine/speakeasy-setup.md` (gram `main` `68b3f78`), +re-rendered at `2026-09-30T21:25:45Z`. The fixed anchors are carried verbatim. This replaces +the retired **Authentication** / **Attach Remote Identity Provider** flow. + +Per-guide values: + +- Remote URL: `https://drivemcp.googleapis.com/mcp/v1` (shared public endpoint, not tenanted). +- Add-server path: Custom remote only (**Hosted remotely**). Operator notes record catalog queries `google-drive` and `google drive` as + absent. +- Authentication Option: `oauth-client` (OAuth) → **User Identity**. Client + ID and Client secret come from {#copy-client-credentials}. +- Probe outcome (`2026-09-30T21:25:45Z`): an unauthenticated JSON-RPC `initialize` POST with + `Accept: application/json, text/event-stream` returned HTTP 200 with a + result (protocol `2025-06-18`), not a 401. The create form therefore + preselects **No Identity**; the reader must select **User Identity**. +- PRM: `https://drivemcp.googleapis.com/.well-known/oauth-protected-resource/mcp/v1` + names issuer `https://accounts.google.com/`. The dashboard's discovery + probes this path-suffixed location (the origin-root location returns an + error), so the provider picker preselects the Google provider or badges it + **Will be created**. +- Registration: `https://accounts.google.com/.well-known/oauth-authorization-server` + advertises no `registration_endpoint` and no + `client_id_metadata_document_supported`; Google states its remote MCP + servers support neither DCR nor CIMD. The dashboard defaults to **Manual** + (or **Existing client** when one exists). Registration choice: **Manual**. + Automatic configuration at creation cannot register a client, so the server + is saved **Disabled** and must be enabled under **Settings > Danger Zone > + Server Availability** after the Identity section is saved. +- Token endpoint auth: the issuer advertises `client_secret_post` and + `client_secret_basic`; the dashboard picks the method automatically. +- PRM `scopes_supported`: `https://www.googleapis.com/auth/drive`, `https://www.googleapis.com/auth/drive.readonly`, `https://www.googleapis.com/auth/drive.file`. This is + broader than the consent-screen configuration (full `drive`), so **Scope** + must not be left blank. +- Scope string for **Advanced > Scope** (space-separated, one line): + `https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/drive.file` +- Further-reading URL: the provider's MCP setup page listed in Provenance. ### Add the server in Speakeasy {#add-server-in-speakeasy} -In the Speakeasy AI Control Plane sidebar, under **Connect**, select -**Sources**, then click **Add Source**. - -Choose **Custom remote server**. On **Add a custom remote MCP server**, paste -`https://drivemcp.googleapis.com/mcp/v1` into **Remote MCP server URL** and -click **Add server**. - -This creates the hosted MCP server and opens its **Overview** page. +Under **MCP Gateway**, select **MCP**, click **Add new**, and choose **Hosted +remotely**. On **New remote MCP server**, paste `https://drivemcp.googleapis.com/mcp/v1` into **MCP server +URL**, leave **User session issuer** at its default, and click **Verify +connectivity**. Under **Identity**, select **User Identity** (the page +preselects **No Identity** for this 200-unauthenticated server). Leave +**Guardrails** off if it appears, then click **Save**. The result keeps the +server **Disabled** and says to finish setup in **Settings > Identity**; this +is expected for Manual registration. - - -Only this path is rendered because operator notes record both catalog queries, -`google-drive` and `google drive`, as absent. There is no catalog open -question. +Screenshot note: **New remote MCP server** with the URL verified and **User +Identity** selected. ### Connect your credentials {#connect-speakeasy-credentials} -From **Overview**, open **Settings**. Under **Authentication**, click -**Configure Manually** or **Use Discovered** when offered. In **Attach Remote -Identity Provider**, set **Client Type** to **Manual**. +Open **Settings** > **Identity**. Confirm **User Identity**. In **Choose an +identity provider**, confirm the Google provider (`https://accounts.google.com/`) +or pick it via **Search identity providers…**. Choose **Manual**. Paste +**Client ID** and **Client secret** from {#copy-client-credentials}; Google requires the +secret despite the "Optional" placeholder. Under **Advanced > Scope**, enter the +scope string above and do not leave it blank. Click **Save**. Then open +**Settings > Danger Zone > Server Availability** and turn on **Enable MCP +server** so it shows **Enabled**. -Confirm **Redirect URI** matches the value registered in -{#create-oauth-client}. Paste **Client ID** and **Client Secret (optional)** -from {#copy-client-credentials}; Google's Web application flow requires the -generated secret despite the optional Speakeasy label. Configure both required -Drive scopes, then click **Attach Identity Provider**. +This surface does not display the redirect URI; {#create-oauth-client} +registers `{{ gram.oauth.callback_url }}` directly. -Screenshot note: the identity-provider sheet with credentials redacted. +On first use, Google's browser authorization prompt appears. The account must +hold **MCP Tool User** ({#grant-mcp-tool-user}) and, for an External app in +**Testing**, be listed under **Test users**. -Further reading: -`https://developers.google.com/workspace/drive/api/guides/configure-mcp-server`. +Screenshot note: **Settings > Identity** with **User Identity**, the Google +provider, and **Manual** selected; values redacted. ## Open questions @@ -274,3 +335,13 @@ All entries were observed at `2026-07-29T20:37:22Z`: - `https://accounts.google.com/.well-known/oauth-authorization-server` — OAuth endpoints and no registration endpoint. - `doctrine/speakeasy-setup.md` — canonical Speakeasy labels and anchors. + +Re-observed at `2026-09-30T21:25:45Z` (identity-section refresh): the product MCP setup page, +`https://developers.google.com/workspace/guides/configure-mcp-servers`, +`https://docs.cloud.google.com/mcp/set-up-authentication-mcp-servers`, the MCP +endpoint `initialize` probe, the path-suffixed PRM, Google's +authorization-server metadata, and `doctrine/speakeasy-setup.md` (gram +`68b3f78`). Newly drawn from: + +- `https://developers.google.com/workspace/preview` — Developer Preview + Program terms, apply action, form contents, timeline, and listed MCP servers. diff --git a/guides/google-drive/speakeasy.md b/guides/google-drive/speakeasy.md index 1a3318f..76ca8e3 100644 --- a/guides/google-drive/speakeasy.md +++ b/guides/google-drive/speakeasy.md @@ -11,78 +11,37 @@ https://drivemcp.googleapis.com/mcp/v1 ``` -5. Click **Verify connectivity**, then **Save**. +5. Leave **User session issuer** at its default. +6. Click **Verify connectivity**. +7. Under **Identity**, select **User Identity**. The page preselects **No Identity** for this server, so change it. +8. If **Guardrails** appears, leave it off. +9. Click **Save**. -This creates the hosted MCP server and opens its **Overview** page. +Speakeasy saves the server as **Disabled** and says to finish setup in **Settings > Identity**. This is expected; the next section completes it. - + ### Connect your credentials {#connect-speakeasy-credentials} -Open the server's **Settings** (from **Overview** for a hosted remote server, or **Configure MCP settings** after a catalog addition). - -#### Choose an authentication provider - -- If **Authentication** is unconfigured, choose **Use Discovered** when available; otherwise choose **Configure Manually**. -- If authentication is configured but no provider is attached, use **Connected services** > **Add provider**. -- If the intended provider is already attached, use its existing controls. Do not attach a duplicate; check its client against the requirements below and skip **Verify and attach**. - -In **Attach Remote Identity Provider**, the provider selector defaults to **Select existing** when the project has issuers. Select the appropriate existing Google provider and skip new-provider setup. - -#### New provider only - -1. Choose **Add new** and enter **Issuer URL**: - - ```text - https://accounts.google.com/ - ``` - -2. Confirm the auto-derived **Slug** is unique in the project. -3. Discovery runs automatically for a seeded issuer URL. After typing or changing the URL, click **Discover** only if offered. -4. Review the endpoints, or enter these Google OAuth values if discovery does not populate them. - - Authorization endpoint: - - ```text - https://accounts.google.com/o/oauth2/v2/auth - ``` - - Token endpoint: - - ```text - https://oauth2.googleapis.com/token - ``` - -#### Choose a session client - -- **Reuse:** Under **Session Client**, choose **Select existing** when available and select the appropriate Google OAuth client. Skip credential entry; continue to **Check client requirements**. -- **Create:** Choose **Add new** when available and set **Client Type** to **Manual**. For a new provider, complete the new-client form below. - -#### New session client only - -1. Paste the **Client ID** from [Copy the client credentials](external.md#copy-client-credentials). -1. Paste the **Client Secret (optional)** from the same section. Google's Web application flow requires the generated secret despite the optional field label. - -#### Check client requirements - -For both new and reused clients, verify the Google app's approved audience and publishing status. An **External** app in **Testing** must list each connecting account under **Test users**. Reusing a client does not require entering its credentials again. - -Confirm the selected client includes the required scopes below. For a new client, configure **Scope (override)**; for a reused client, inspect the read-only **Scope** value. If it does not match, choose **Add new** to create a correctly scoped client; the attach sheet cannot edit a reused client. - -Configure these two scopes as required: +1. Open the server's **Settings** and find the **Identity** section. +2. Confirm that **User Identity** is selected. +3. In **Choose an identity provider**, confirm that the preselected provider is Google (`https://accounts.google.com/`). If another provider is shown, open the picker, search in **Search identity providers…**, and choose the Google provider. A provider badged **Will be created** is created when you save. +4. Choose **Manual**. +5. In **Client ID**, paste the **Client ID** from [Copy the client credentials](external.md#copy-client-credentials). +6. In **Client secret**, paste the **Client secret** from the same section. Google requires it even though the field says "Optional". +7. Open **Advanced**. In **Scope**, enter this value on one line: ``` - https://www.googleapis.com/auth/drive.readonly - https://www.googleapis.com/auth/drive.file + https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/drive.file ``` -#### Verify and attach + Do not leave **Scope** blank. A blank value requests every scope the server advertises, including full Drive access, which the consent screen does not grant. -1. Confirm that the callback URL registered with the provider is `{{ gram.oauth.callback_url }}`. For a new manual client, also compare it with the sheet's displayed **Redirect URI**. The existing-client selection does not display that field; check the registered callback in the provider's app settings instead. -2. Click **Attach Identity Provider**. +8. Click **Save**. +9. Open **Settings > Danger Zone > Server Availability** and turn on **Enable MCP server** so it shows **Enabled**. -For the provider-side callback setting, see [Create the OAuth client](external.md#create-oauth-client). +When a person first uses the server, Google's browser authorization prompt appears. They must sign in with an account granted [MCP Tool User](external.md#grant-mcp-tool-user). If the app's audience is **External** and in **Testing**, the account must also be listed under **Test users**. - + -For more information, see [Google's Drive MCP documentation](https://developers.google.com/workspace/drive/api/guides/configure-mcp-server). +This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Google's Drive MCP documentation](https://developers.google.com/workspace/drive/api/guides/configure-mcp-server). diff --git a/guides/google-people/external.md b/guides/google-people/external.md index 7eeda39..ed3b73b 100644 --- a/guides/google-people/external.md +++ b/guides/google-people/external.md @@ -4,12 +4,24 @@ setup_version: 1 # Set up Google People -You need a Google Cloud project and access to the [Google Cloud console](https://console.cloud.google.com). To enable the People API, you need `serviceusage.services.enable`, normally through **Service Usage Admin** or **Owner**. To grant project roles, you need **Project IAM Admin**. Each connecting user must already have access to the intended Google profile, contacts, and directory data. Google documents that application developers are responsible for screening prompts and responses for malicious content or prompt injection; Model Armor is one documented option. +The People API MCP server is in the Google Workspace Developer Preview Program. You need a Google Workspace account that can be added to Google Groups and a Google Cloud project that your organization can register in the program. To enable the People API, you need `serviceusage.services.enable`, normally through **Service Usage Admin** or **Owner**. To grant project roles, you need **Project IAM Admin**. Each connecting user must already have access to the intended Google profile, contacts, and directory data. Google documents that application developers are responsible for screening prompts and responses for malicious content or prompt injection; Model Armor is one documented option. + +### Join the Google Workspace Developer Preview Program {#join-developer-preview} + +1. Open [developers.google.com/workspace/preview](https://developers.google.com/workspace/preview). +2. Review the **Developer Preview Program Terms** with the application or security owner. +3. Click **Apply to join the Developer Preview Program**. +4. In the current application form, enter the requested Google Workspace account and Google Cloud project information. +5. Agree to the terms only with organizational approval. +6. Submit the form with the visible or equivalent submission control. Google verifies the Workspace account, adds it to the program group, and then registers the Cloud project. +7. Wait for the final project-registration confirmation at the submitted email address. Google says this should complete within a couple of days. + + ### Enable the People API {#enable-people-api} 1. Sign in to the [Google Cloud console](https://console.cloud.google.com). -2. In the console toolbar, use the resource selector to select the project that will own this configuration. +2. In the console toolbar, use the resource selector to select the project registered in the Developer Preview Program. 3. Open **APIs & Services** > **API Library**. 4. In **Search for APIs & Services**, search for `People API`. 5. Open **People API**. diff --git a/guides/google-people/meta.yaml b/guides/google-people/meta.yaml index 43a1bd3..73b45ba 100644 --- a/guides/google-people/meta.yaml +++ b/guides/google-people/meta.yaml @@ -21,6 +21,8 @@ credential_setup: - external.md#create-oauth-client - external.md#copy-oauth-credentials requirements: + - id: developer-preview + description: Google has confirmed the intended Google Workspace account and registered the Google Cloud project in the Google Workspace Developer Preview Program - id: google-cloud-project description: A Google Cloud project where an administrator can enable the People API, grant project IAM roles, configure Google Auth platform, and create OAuth credentials - id: connecting-user-access @@ -40,18 +42,23 @@ remotes: locator: https://developers.google.com/people/v1/configure-mcp-server name: Configure the People API MCP server classification: official - observed_at: "2026-08-29T15:13:24Z" + observed_at: "2026-09-30T21:25:46Z" - source: endpoint-observation locator: https://people.googleapis.com/.well-known/oauth-protected-resource/mcp/v1 name: Google People API MCP protected-resource metadata classification: official - observed_at: "2026-08-29T15:13:24Z" + observed_at: "2026-09-30T21:25:46Z" provenance: - source: provider-documentation locator: https://developers.google.com/people/v1/configure-mcp-server name: Configure the People API MCP server classification: official - observed_at: "2026-08-29T15:13:24Z" + observed_at: "2026-09-30T21:25:46Z" + - source: provider-documentation + locator: https://developers.google.com/workspace/preview + name: Google Workspace Developer Preview Program + classification: official + observed_at: "2026-09-30T21:25:46Z" - source: provider-documentation locator: https://developers.google.com/people/api/mcp name: People API MCP reference @@ -116,14 +123,14 @@ provenance: locator: https://people.googleapis.com/.well-known/oauth-protected-resource/mcp/v1 name: Google People API MCP protected-resource metadata classification: official - observed_at: "2026-08-29T15:13:24Z" + observed_at: "2026-09-30T21:25:46Z" - source: endpoint-observation locator: https://accounts.google.com/.well-known/oauth-authorization-server name: Google authorization-server metadata classification: official - observed_at: "2026-08-29T15:13:24Z" + observed_at: "2026-09-30T21:25:46Z" - source: repository-doctrine locator: doctrine/speakeasy-setup.md name: Speakeasy setup canonical section classification: official - observed_at: "2026-08-29T15:13:24Z" + observed_at: "2026-09-30T21:25:46Z" diff --git a/guides/google-people/research.md b/guides/google-people/research.md index c16745c..ac4c9ef 100644 --- a/guides/google-people/research.md +++ b/guides/google-people/research.md @@ -12,7 +12,13 @@ researched_at: 2026-08-29T15:13:24Z - Transport: `streamable-http`. Google's setup page labels the transport **HTTP**, and its MCP reference shows JSON-RPC requests sent to the HTTPS endpoint with both JSON and event-stream response types. -- Launch stage: **Developer Preview** in Google's supported-products list. +- Launch stage: **Developer Preview**. The People setup page (last updated + 2026-09-18 UTC, re-verified 2026-09-30T21:25:46Z) lists **Membership in the + Google Workspace Developer Preview Program** as the first prerequisite, and + the program page lists **People MCP server** under **MCP SERVERS**. The + program requires an application, a Google Workspace account that can be + added to Google Groups, account verification, and Google Cloud project + registration before use. - Enable **People API** (`people.googleapis.com`) in a Google Cloud project. The product page calls this the API and MCP service; it documents no second MCP-specific service. @@ -36,8 +42,12 @@ researched_at: 2026-08-29T15:13:24Z - The URL is a shared global endpoint, not a region-, instance-, or organization-specific endpoint, so the remote is not tenanted. - Speakeasy MCP Catalog presence is unknown: the coordinator's safe Pulse - inspection found no confident Google People match. With no tenanted remote - and no `speakeasy_add_server` override, preserve both add-server paths. + inspection found no confident Google People match. A reviewed-catalogue + search for `google people` on 2026-09-30 returned no candidates, but the + same tool was rate-limited before a control query could confirm it was + searching the full catalog, so presence stays unresolved. With no tenanted + remote and no `speakeasy_add_server` override, preserve both add-server + paths. ## Credential flow @@ -65,9 +75,30 @@ expire seven days after consent. ## Console walkthrough +### Join the Google Workspace Developer Preview Program {#join-developer-preview} + +- Open `https://developers.google.com/workspace/preview` and review the + **Developer Preview Program Terms** with the organization's application or + security owner. +- Confirm that the submitted Google Workspace account can be added to Google + Groups, as the program requires. +- Click **Apply to join the Developer Preview Program**. In the current + application form, provide the requested Google Workspace account and Google + Cloud project information, agree to the terms only with organizational + approval, and submit. Google does not publish the form's field labels. +- Google verifies the Workspace account, adds it to the program group, and + registers the Cloud project. Wait for the final confirmation at the + submitted email address; Google says this should take a couple of days. +- Values entered: organization-specific account and project information. + Values copied: none. +- Screenshot note: the program page with **People MCP server** listed under + **MCP SERVERS**; do not capture application-form data. +- Source: `https://developers.google.com/workspace/preview` and the People + setup page's prerequisites, observed 2026-09-30T21:25:46Z. + Sign in at `https://console.cloud.google.com`. In the toolbar resource -selector, select the project that will own this configuration. Keep it -selected throughout the Google steps. +selector, select the project registered in the Developer Preview Program. +Keep it selected throughout the Google steps. ### Enable the People API {#enable-people-api} @@ -166,59 +197,89 @@ selected throughout the Google steps. ## Speakeasy setup -Transcluded from `doctrine/speakeasy-setup.md`, observed at -`2026-08-29T15:13:24Z`. These anchors are fixed and carried verbatim. +Transcluded from `doctrine/speakeasy-setup.md` (gram `main` `68b3f78`), +observed at `2026-09-30T21:25:46Z`. These anchors are fixed and carried +verbatim. + +Per-guide values: + +- Remote URL `https://people.googleapis.com/mcp/v1`; `streamable-http`; + shared, not tenanted; `speakeasy_add_server: auto`. +- Add-server path: catalog presence unresolved, so both bullets (dual + conditional) remain. +- Authentication Option `oauth-client` (OAuth) → **User Identity**. +- Probe outcome (`2026-09-30T21:25:46Z`): an unauthenticated JSON-RPC + `initialize` POST with `Accept: application/json, text/event-stream` + returns **200** with no challenge, so the create form preselects **No + Identity**. A catalog entry would also preselect **No Identity** because + Google offers no client registration. The reader must select **User + Identity** on either path. +- PRM `https://people.googleapis.com/.well-known/oauth-protected-resource/mcp/v1` + names issuer `https://accounts.google.com/` and advertises exactly the three + required scopes. +- Issuer metadata (`https://accounts.google.com/.well-known/oauth-authorization-server` + and `/.well-known/openid-configuration`): no `registration_endpoint`, no + `client_id_metadata_document_supported`. Authorization endpoint + `https://accounts.google.com/o/oauth2/v2/auth`, token endpoint + `https://oauth2.googleapis.com/token`. +- Creation result: automatic configuration cannot register a client, so the + server is kept **Disabled** and the result points to **Settings > + Identity**. Expected. +- Provider picker: PRM is served, so the picker preselects the Google issuer + (badged **Will be created** when absent). No custom identity provider route. +- Registration choice: **Manual**. +- **Client ID** and **Client secret** from {#copy-oauth-credentials}; the + secret is required despite the "Optional" placeholder. +- **Advanced > Scope**, space-separated on one line: + `https://www.googleapis.com/auth/directory.readonly https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/contacts.readonly`. + Because the PRM advertises only these three, a blank value would request the + same set; the guide still enters them explicitly. +- Registered callback `{{ gram.oauth.callback_url }}` in {#create-oauth-client}; + the Identity section does not display a redirect URI. +- Server Availability: required after the Identity save. +- Further reading: `https://developers.google.com/people/v1/configure-mcp-server`. ### Add the server in Speakeasy {#add-server-in-speakeasy} -In the Speakeasy AI Control Plane sidebar, under **Connect**, select -**Sources**, then click **Add Source**. - -- If **Google People** is in the catalog, choose **3rd-party server**. On the - **MCP Catalog** page, search for Google People in **Search MCP servers...**, - open the matching entry with **View**, click **Add**, and then click **Add to - Project** in **Add to Project**. -- If no matching catalog entry is available, choose **Custom remote server**. - On **Add a custom remote MCP server**, paste - `https://people.googleapis.com/mcp/v1` into **Remote MCP server URL** and - click **Add server**. +In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select +**MCP**, then click **Add new** to open **Add MCP server**. -Either path creates the hosted MCP server and opens its **Overview** page. +- If **Google People** is in the catalog, choose **From the catalog**. On the + **MCP Catalog** page, find Google People using **Search MCP servers...**, + open its entry, and click **Add**. In **Add to Project**, select **User + Identity**, click **Add to Project** (click **Skip for now** if a + **Guardrails** step appears), then after **Server added successfully** click + **Configure MCP settings**. +- If it is not, choose **Hosted remotely**. On **New remote MCP server**, + paste `https://people.googleapis.com/mcp/v1` into **MCP server URL**, leave + **User session issuer** at its default, click **Verify connectivity**, + change the preselected **No Identity** to **User Identity**, leave + **Guardrails** off, and click **Save**. - +Either way the server is kept **Disabled** and the result says to finish +setup in **Settings > Identity**; this is expected. -Per-guide values: remote URL `https://people.googleapis.com/mcp/v1`; -`streamable-http` transport with read-only **Transport**; manually registered -`oauth-client`; shared non-tenanted endpoint; catalog presence unresolved, so -both add-server paths remain available. + ### Connect your credentials {#connect-speakeasy-credentials} -From **Overview**, open **Settings**. Under **Authentication**, click -**Configure Manually** or **Use Discovered** when offered. The endpoint -publishes protected-resource metadata. In **Attach Remote Identity Provider**, -set **Client Type** to **Manual**. - -Confirm **Redirect URI** matches `{{ gram.oauth.callback_url }}` entered in -{#create-oauth-client}. Paste **Client ID** and **Client Secret (optional)** -from {#copy-oauth-credentials}. Google's Web application flow requires the -generated secret despite the optional Speakeasy label. - -In **Scope (override)**, enter all three scope identifiers from Server facts -using the field's visible or equivalent multi-scope format, then click **Attach -Identity Provider**. At first connection, authorize with an account granted -**MCP Tool User** in {#grant-mcp-tool-user}. +Open the server's **Settings** > **Identity** and select **User Identity**. +In **Choose an identity provider**, confirm the preselected Google issuer +`https://accounts.google.com/` (or choose it via **Search identity +providers…**). Choose **Manual** (switch from **Existing client** if +preselected). Paste **Client ID** and **Client secret** from +{#copy-oauth-credentials}. Under **Advanced > Scope**, enter the scope string +above on one line. Click **Save** (**Save changes** if asked to confirm). +Open **Settings > Danger Zone > Server Availability** and turn on **Enable +MCP server** so it shows **Enabled**. At first connection, authorize with an +account granted **MCP Tool User** in {#grant-mcp-tool-user}. Provider-specific prompt labels are not documented. -Screenshot note: **Attach Remote Identity Provider** showing Manual client -type, redirect URI, credential labels, and scopes, with secrets redacted. - -Further-reading URL: -`https://developers.google.com/people/v1/configure-mcp-server`. +Screenshot note: **Settings > Identity** with **User Identity**, the Google +provider, and **Manual** selected; values redacted. This guide covers setup only. For anything beyond it — billing, tool behavior, -limits — see Google's People API MCP documentation at -https://developers.google.com/people/v1/configure-mcp-server. +limits — see [Google's People API MCP documentation](https://developers.google.com/people/v1/configure-mcp-server). ## Research limitations @@ -241,9 +302,6 @@ https://developers.google.com/people/v1/configure-mcp-server. provider-independent minimum or acceptance test. This dossier therefore does not claim that an independently verifiable screening prerequisite has been completed. -- The dossier sources identify the three required scope identifiers but do not - prescribe a delimiter for Speakeasy's **Scope (override)** field. The guide - therefore directs the reader to the visible or equivalent multi-scope format. - Google's MCP authentication documentation identifies the OAuth client as the object to delete when its one-time secret was missed, but does not name the exact delete control. The guide uses a bounded visible-control hedge. @@ -270,7 +328,9 @@ Documentation-property sweep: used because the People setup page prescribes no app-access control step. - `doctrine/speakeasy-setup.md` supplies Speakeasy labels and fixed anchors. -All sources were observed at `2026-08-29T15:13:24Z`: +All sources were observed at `2026-08-29T15:13:24Z` unless noted. The People +setup page, PRM, and Google authorization-server metadata were re-verified at +`2026-09-30T21:25:46Z`: - `https://developers.google.com/people/v1/configure-mcp-server` — endpoint, transport label, enablement, OAuth, consent values, scopes, client creation, @@ -300,6 +360,14 @@ All sources were observed at `2026-08-29T15:13:24Z`: — authorization server, bearer method, resource URL, and scopes. - `https://accounts.google.com/.well-known/oauth-authorization-server` — OAuth endpoints and no registration endpoint. -- `doctrine/speakeasy-setup.md` — unresolved-catalog dual add-server paths and - the Manual OAuth flow. +- `doctrine/speakeasy-setup.md` (gram `main` `68b3f78`, observed + 2026-09-30T21:25:46Z) — unresolved-catalog dual add-server paths, Identity + section, **Manual** client, **Advanced > Scope**, and **Server + Availability**. +- `https://developers.google.com/workspace/preview` — observed + 2026-09-30T21:25:46Z; Developer Preview application, terms, Google Groups + requirement, verification and project-registration sequence, and **People + MCP server** listing. +- `https://people.googleapis.com/mcp/v1` — probed 2026-09-30T21:25:46Z; + unauthenticated `initialize` returns 200. - `doctrine/personas/it-admin.md` — browser-only achievability requirements. diff --git a/guides/google-people/speakeasy.md b/guides/google-people/speakeasy.md index d4df93e..eac631c 100644 --- a/guides/google-people/speakeasy.md +++ b/guides/google-people/speakeasy.md @@ -10,90 +10,50 @@ 2. On the **MCP Catalog** page, find Google People in **Search MCP servers...**. 3. Open the matching entry. 4. Click **Add**. - 5. In **Add to Project**, click **Add to Project**. + 5. In **Add to Project**, under **Identity**, select **User Identity**. + 6. Click **Add to Project**. If a **Guardrails** step appears, click **Skip for now**. + 7. When the dialog finishes, the result reads "Added, but disabled until identity is set up." Click **Finish setup** to open the server's **Settings**. - If no matching catalog entry is available: 1. Choose **Hosted remotely**. 2. On **New remote MCP server**, paste this URL into **MCP server URL**: - ``` + ```text https://people.googleapis.com/mcp/v1 ``` - 3. Click **Verify connectivity**, then **Save**. + 3. Leave **User session issuer** at its default. + 4. Click **Verify connectivity**. + 5. Under **Identity**, select **User Identity**. The page preselects **No Identity** for this server, so change it. + 6. If **Guardrails** appears, leave it off. + 7. Click **Save**. -For the catalog path, click **Configure MCP settings** on the completion screen to open the server, then open **Settings**. The **Hosted remotely** path opens **Overview** after **Save**; open **Settings** there. +Either way, Speakeasy keeps the new server **Disabled** and says to finish setup in **Settings > Identity**. This is expected for Google People; the next section finishes it. - + ### Connect your credentials {#connect-speakeasy-credentials} -Open the server's **Settings** (from **Overview** for a hosted remote server, or **Configure MCP settings** after a catalog addition). - -#### Choose an authentication provider - -- If **Authentication** is unconfigured, choose **Use Discovered** when available; otherwise choose **Configure Manually**. -- If authentication is configured but no provider is attached, use **Connected services** > **Add provider**. -- If the intended provider is already attached, use its existing controls. Do not attach a duplicate; check its client against the requirements below and skip **Verify and attach**. - -In **Attach Remote Identity Provider**, the provider selector defaults to **Select existing** when the project has issuers. Select the appropriate existing Google provider and skip new-provider setup. - -#### New provider only - -1. Choose **Add new** and enter **Issuer URL**: - - ```text - https://accounts.google.com/ - ``` - -2. Confirm the auto-derived **Slug** is unique in the project. -3. Discovery runs automatically for a seeded issuer URL. After typing or changing the URL, click **Discover** only if offered. -4. Review the endpoints, or enter these Google OAuth values if discovery does not populate them. - - Authorization endpoint: - - ```text - https://accounts.google.com/o/oauth2/v2/auth - ``` +Open the server's **Settings** and find the **Identity** section. - Token endpoint: +1. Select **User Identity**. +2. In **Choose an identity provider**, confirm that the preselected provider is Google's issuer, `https://accounts.google.com/`. It is badged **Will be created** when the project has no Google provider yet. If another provider is selected, open the picker, search in **Search identity providers…**, and choose the Google provider. +3. Under the provider, choose **Manual**. If **Existing client** is preselected, switch to **Manual**. +4. Paste the **Client ID** from the [OAuth credentials](external.md#copy-oauth-credentials) into **Client ID**. +5. Paste the **Client Secret** from the [OAuth credentials](external.md#copy-oauth-credentials) into **Client secret**. Google requires the secret even though the field shows "Optional". +6. Open **Advanced**. In **Scope**, enter this value on one line: ```text - https://oauth2.googleapis.com/token + https://www.googleapis.com/auth/directory.readonly https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/contacts.readonly ``` -#### Choose a session client - -- **Reuse:** Under **Session Client**, choose **Select existing** when available and select the appropriate Google OAuth client. Skip credential entry; continue to **Check client requirements**. -- **Create:** Choose **Add new** when available and set **Client Type** to **Manual**. For a new provider, complete the new-client form below. - -#### New session client only - -1. Paste the **Client ID** from the [OAuth credentials](external.md#copy-oauth-credentials). -1. Paste the **Client Secret (optional)** from the [OAuth credentials](external.md#copy-oauth-credentials). Google requires this secret even though the field is labeled optional. - -#### Check client requirements - -For both new and reused clients, verify the Google app's approved audience and publishing status. An **External** app in **Testing** must list each connecting account under **Test users**. Reusing a client does not require entering its credentials again. - -Confirm the selected client includes the required scopes below. For a new client, configure **Scope (override)**; for a reused client, inspect the read-only **Scope** value. If it does not match, choose **Add new** to create a correctly scoped client; the attach sheet cannot edit a reused client. - -For a new client, enter these three identifiers using the field's visible or equivalent multi-scope format: - - ``` - https://www.googleapis.com/auth/directory.readonly - https://www.googleapis.com/auth/userinfo.profile - https://www.googleapis.com/auth/contacts.readonly - ``` - -#### Verify and attach - -1. Confirm that the callback URL registered with the provider is `{{ gram.oauth.callback_url }}`. For a new manual client, also compare it with the sheet's displayed **Redirect URI**. The existing-client selection does not display that field; check the registered callback in the provider's app settings instead. -2. Click **Attach Identity Provider**. +7. Click **Save**. If Speakeasy asks you to confirm, click **Save changes**. +8. Open **Settings > Danger Zone > Server Availability**. +9. Turn on **Enable MCP server** so the switch shows **Enabled**. -For the provider-side callback setting, see [created the OAuth client](external.md#create-oauth-client). +The callback Speakeasy uses is the `{{ gram.oauth.callback_url }}` value you registered in [Create the OAuth client](external.md#create-oauth-client). At first connection, follow Google's visible or equivalent browser authorization controls with an account that has [MCP Tool User access](external.md#grant-mcp-tool-user). - + This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Google's People API MCP documentation](https://developers.google.com/people/v1/configure-mcp-server). diff --git a/guides/google-sheets/external.md b/guides/google-sheets/external.md index 94569c2..d9cc4c5 100644 --- a/guides/google-sheets/external.md +++ b/guides/google-sheets/external.md @@ -4,9 +4,23 @@ setup_version: 1 # Set up Google Sheets -Use a Google Cloud project where you can enable services, grant project IAM roles, configure the **Google Auth platform**, and create OAuth credentials. You normally need **Service Usage Admin** or **Owner** to enable the APIs and **Project IAM Admin** to grant access. Each person who will connect needs access to the intended spreadsheets. Before setup, have the application or security owner configure prompt and response screening for malicious content or prompt injection. +The Sheets MCP server is available only through the Google Workspace Developer Preview Program, so the Google Cloud project must be registered in it. Use a Google Cloud project where you can enable services, grant project IAM roles, configure the **Google Auth platform**, and create OAuth credentials. You normally need **Service Usage Admin** or **Owner** to enable the APIs and **Project IAM Admin** to grant access. Each person who will connect needs access to the intended spreadsheets. Before setup, have the application or security owner configure prompt and response screening for malicious content or prompt injection. -Sign in to the [Google Cloud console](https://console.cloud.google.com). In the console toolbar, use the resource selector to choose the project that will own this configuration. Keep the same project selected throughout setup. +Sign in to the [Google Cloud console](https://console.cloud.google.com). In the console toolbar, use the resource selector to choose the project registered in the Developer Preview Program. Keep the same project selected throughout setup. + +### Join the Google Workspace Developer Preview Program {#join-developer-preview} + +1. Open [developers.google.com/workspace/preview](https://developers.google.com/workspace/preview). +2. Review the **Developer Preview Program Terms** with the application or security owner. +3. Click **Apply to join the Developer Preview Program**. +4. In the application form, enter the requested Google Workspace account and Google Cloud project information. +5. Agree to the terms only with organizational approval. +6. Submit the form with the visible or equivalent submission control. +7. Wait for Google's project-registration confirmation at the submitted email address. Google says this should complete within a couple of days. + +Use the registered project for every Google Cloud step that follows. + + ### Enable the Google Sheets APIs {#enable-google-sheets-apis} @@ -106,6 +120,6 @@ This opens **OAuth 2.0 client created**. If you miss the one-time **Client secret**, delete it and create a new one before continuing. -Keep both values available, then [connect your credentials in the Speakeasy AI Control Plane](speakeasy.md#connect-speakeasy-credentials). +Keep both values available, then [add the server in the Speakeasy AI Control Plane](speakeasy.md#add-server-in-speakeasy). diff --git a/guides/google-sheets/meta.yaml b/guides/google-sheets/meta.yaml index 07c5992..eb10f96 100644 --- a/guides/google-sheets/meta.yaml +++ b/guides/google-sheets/meta.yaml @@ -21,6 +21,8 @@ credential_setup: - external.md#create-oauth-client - external.md#copy-oauth-credentials requirements: + - id: developer-preview + description: Google has registered the Google Cloud project in the Google Workspace Developer Preview Program, which the Sheets MCP server requires - id: google-cloud-project description: A Google Cloud project where an administrator can enable the Google Sheets API and Google Sheets MCP API, grant project IAM roles, configure Google Auth platform, and create OAuth credentials - id: connecting-user-access @@ -41,28 +43,33 @@ remotes: locator: https://developers.google.com/workspace/sheets/api/guides/configure-mcp-server name: Configure the Sheets MCP server classification: official - observed_at: "2026-07-29T20:37:05Z" + observed_at: "2026-09-30T21:25:45Z" - source: endpoint-observation locator: https://sheetsmcp.googleapis.com/mcp/v1 name: Google Sheets MCP endpoint classification: official - observed_at: "2026-07-29T20:37:05Z" + observed_at: "2026-09-30T21:25:45Z" - source: endpoint-observation locator: https://sheetsmcp.googleapis.com/.well-known/oauth-protected-resource/mcp/v1 name: Google Sheets MCP protected-resource metadata classification: official - observed_at: "2026-07-29T20:37:05Z" + observed_at: "2026-09-30T21:25:45Z" provenance: + - source: provider-documentation + locator: https://developers.google.com/workspace/preview + name: Google Workspace Developer Preview Program + classification: official + observed_at: "2026-09-30T21:25:45Z" - source: provider-documentation locator: https://developers.google.com/workspace/sheets/api/guides/configure-mcp-server name: Configure the Sheets MCP server classification: official - observed_at: "2026-07-29T20:37:05Z" + observed_at: "2026-09-30T21:25:45Z" - source: provider-documentation locator: https://developers.google.com/workspace/guides/configure-mcp-servers name: Configure the Google Workspace MCP servers classification: official - observed_at: "2026-07-29T20:37:05Z" + observed_at: "2026-09-30T21:25:45Z" - source: provider-documentation locator: https://developers.google.com/workspace/guides/configure-oauth-consent name: Configure the OAuth consent screen and choose scopes @@ -82,7 +89,7 @@ provenance: locator: https://docs.cloud.google.com/mcp/set-up-authentication-mcp-servers name: Set up authentication to Google and Google Cloud MCP servers classification: official - observed_at: "2026-07-29T20:37:05Z" + observed_at: "2026-09-30T21:25:45Z" - source: provider-documentation locator: https://cloud.google.com/service-usage/docs/enable-disable name: Enable and disable services @@ -118,20 +125,20 @@ provenance: name: Google Sheets MCP endpoint classification: official status: MCP initialize returned HTTP 200 - version: "2025-03-26" - observed_at: "2026-07-29T20:37:05Z" + version: "2025-06-18" + observed_at: "2026-09-30T21:25:45Z" - source: endpoint-observation locator: https://sheetsmcp.googleapis.com/.well-known/oauth-protected-resource/mcp/v1 name: Google Sheets MCP protected-resource metadata classification: official - observed_at: "2026-07-29T20:37:05Z" + observed_at: "2026-09-30T21:25:45Z" - source: endpoint-observation locator: https://accounts.google.com/.well-known/oauth-authorization-server name: Google authorization-server metadata classification: official - observed_at: "2026-07-29T20:37:05Z" + observed_at: "2026-09-30T21:25:45Z" - source: repository-doctrine locator: doctrine/speakeasy-setup.md name: Speakeasy setup canonical section classification: official - observed_at: "2026-07-29T20:37:05Z" + observed_at: "2026-09-30T21:25:45Z" diff --git a/guides/google-sheets/research.md b/guides/google-sheets/research.md index 0959102..c41fea9 100644 --- a/guides/google-sheets/research.md +++ b/guides/google-sheets/research.md @@ -12,9 +12,11 @@ researched_at: 2026-07-29T20:37:05Z - Transport: `streamable-http`. Google labels it **HTTP**. A direct MCP `initialize` request over HTTPS POST returned HTTP 200 and an MCP JSON response during this run. -- Launch stage: Developer Preview, announced in Google's July 13, 2026 - Workspace developer release notes. The setup page documents no separate - preview-enrollment step. +- Launch stage: Developer Preview. Re-verified `2026-09-30T21:25:45Z`: the + Sheets setup page lists "Membership in the Google Workspace Developer + Preview Program" as a prerequisite, so enrollment is a setup step + ({#join-developer-preview}). This supersedes the earlier note that no + preview-enrollment step was documented. - Enable both **Google Sheets API** (`sheets.googleapis.com`) and **Google Sheets MCP API** (`sheetsmcp.googleapis.com`) in one Google Cloud project. Enabling APIs requires `serviceusage.services.enable`, normally @@ -70,6 +72,28 @@ Sign in at `https://console.cloud.google.com`. In the console toolbar, use the resource selector to select the project that will own this configuration. Keep that project selected throughout the Google steps. +### Join the Google Workspace Developer Preview Program {#join-developer-preview} + +- Re-verified at `2026-09-30T21:25:45Z`: Google's Sheets MCP setup page lists "Membership in + the Google Workspace Developer Preview Program" as the first prerequisite, + and the program page lists the **Sheets MCP server** among its preview + features. +- Open `https://developers.google.com/workspace/preview` and review the + **Developer Preview Program Terms** with the application or security owner. +- Click **Apply to join the Developer Preview Program**. The form requests + "Google Workspace account and Google Cloud project information"; Google does + not publish its exact field labels, so the submit control is rendered as + "visible or equivalent". Agree to the terms only with organizational + approval. +- Wait for the project-registration confirmation. Google says "The whole + process should be done within a couple of days." +- Result and transition: the registered project is used for every Google + Cloud step that follows. +- Values entered: organization-specific Workspace account and Cloud project + information. Values copied: none. +- Screenshot note: the program page with **Sheets MCP server** listed under + **Latest features**; do not capture application-form data. + ### Enable the Google Sheets APIs {#enable-google-sheets-apis} - Open **APIs & Services** > **API Library**. @@ -165,61 +189,76 @@ that project selected throughout the Google steps. ## Speakeasy setup -Transcluded from `doctrine/speakeasy-setup.md`, observed at -`2026-07-29T20:37:05Z`. The two anchors below are fixed and carried verbatim. - -### Add the server in Speakeasy {#add-server-in-speakeasy} - -In the Speakeasy AI Control Plane sidebar, under **Connect**, select -**Sources**, then click **Add Source**. - -Choose **Custom remote server**. On **Add a custom remote MCP server**, paste -`https://sheetsmcp.googleapis.com/mcp/v1` into **Remote MCP server URL** and -click **Add server**. - -This creates the hosted MCP server and opens its **Overview** page. - - +Transcluded from `doctrine/speakeasy-setup.md` (gram `main` `68b3f78`), +re-rendered at `2026-09-30T21:25:45Z`. The fixed anchors are carried verbatim. This replaces +the retired **Authentication** / **Attach Remote Identity Provider** flow. Per-guide values: -- Remote URL: `https://sheetsmcp.googleapis.com/mcp/v1`. -- Transport: `streamable-http`; **Transport** is read-only. -- Authentication Option: `oauth-client`, manually registered OAuth. -- Catalog decision: absent; Custom remote server only. +- Remote URL: `https://sheetsmcp.googleapis.com/mcp/v1` (shared public endpoint, not tenanted). +- Add-server path: Custom remote only (**Hosted remotely**). Catalog lookup absent for `google-sheets` and `google sheets`. +- Authentication Option: `oauth-client` (OAuth) → **User Identity**. Client + ID and Client secret come from {#copy-oauth-credentials}. +- Probe outcome (`2026-09-30T21:25:45Z`): an unauthenticated JSON-RPC `initialize` POST with + `Accept: application/json, text/event-stream` returned HTTP 200 with a + result (protocol `2025-06-18`), not a 401. The create form therefore + preselects **No Identity**; the reader must select **User Identity**. +- PRM: `https://sheetsmcp.googleapis.com/.well-known/oauth-protected-resource/mcp/v1` + names issuer `https://accounts.google.com/`. The dashboard's discovery + probes this path-suffixed location (the origin-root location returns an + error), so the provider picker preselects the Google provider or badges it + **Will be created**. +- Registration: `https://accounts.google.com/.well-known/oauth-authorization-server` + advertises no `registration_endpoint` and no + `client_id_metadata_document_supported`; Google states its remote MCP + servers support neither DCR nor CIMD. The dashboard defaults to **Manual** + (or **Existing client** when one exists). Registration choice: **Manual**. + Automatic configuration at creation cannot register a client, so the server + is saved **Disabled** and must be enabled under **Settings > Danger Zone > + Server Availability** after the Identity section is saved. +- Token endpoint auth: the issuer advertises `client_secret_post` and + `client_secret_basic`; the dashboard picks the method automatically. +- PRM `scopes_supported`: `https://www.googleapis.com/auth/drive.readonly`, `https://www.googleapis.com/auth/spreadsheets.readonly`, `https://www.googleapis.com/auth/drive`, `https://www.googleapis.com/auth/spreadsheets`. This is + broader than the consent-screen configuration (full `drive`), so **Scope** + must not be left blank. +- Scope string for **Advanced > Scope** (space-separated, one line): + `https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/spreadsheets.readonly https://www.googleapis.com/auth/spreadsheets` +- Further-reading URL: the provider's MCP setup page listed in Provenance. -### Connect your credentials {#connect-speakeasy-credentials} +### Add the server in Speakeasy {#add-server-in-speakeasy} -From **Overview**, open **Settings**. Under **Authentication**, click -**Configure Manually** or **Use Discovered** when offered. In -**Attach Remote Identity Provider**, set **Client Type** to **Manual**. +Under **MCP Gateway**, select **MCP**, click **Add new**, and choose **Hosted +remotely**. On **New remote MCP server**, paste `https://sheetsmcp.googleapis.com/mcp/v1` into **MCP server +URL**, leave **User session issuer** at its default, and click **Verify +connectivity**. Under **Identity**, select **User Identity** (the page +preselects **No Identity** for this 200-unauthenticated server). Leave +**Guardrails** off if it appears, then click **Save**. The result keeps the +server **Disabled** and says to finish setup in **Settings > Identity**; this +is expected for Manual registration. -Confirm that the sheet's **Redirect URI** matches -`{{ gram.oauth.callback_url }}` entered in {#create-oauth-client}. Paste the -**Client ID** and **Client Secret (optional)** from -{#copy-oauth-credentials}. Google's web client requires the generated secret -even though the Speakeasy label says optional. +Screenshot note: **New remote MCP server** with the URL verified and **User +Identity** selected. -In **Scope (override)**, enter these comma-separated values: -`https://www.googleapis.com/auth/drive.readonly`, -`https://www.googleapis.com/auth/drive.file`, -`https://www.googleapis.com/auth/spreadsheets.readonly`, -`https://www.googleapis.com/auth/spreadsheets`. Click -**Attach Identity Provider**. +### Connect your credentials {#connect-speakeasy-credentials} -At first connection, complete Google's browser authorization with an account -granted **MCP Tool User** in {#grant-mcp-tool-user} and access to the intended -spreadsheets. Provider-specific prompt labels are not documented. +Open **Settings** > **Identity**. Confirm **User Identity**. In **Choose an +identity provider**, confirm the Google provider (`https://accounts.google.com/`) +or pick it via **Search identity providers…**. Choose **Manual**. Paste +**Client ID** and **Client secret** from {#copy-oauth-credentials}; Google requires the +secret despite the "Optional" placeholder. Under **Advanced > Scope**, enter the +scope string above and do not leave it blank. Click **Save**. Then open +**Settings > Danger Zone > Server Availability** and turn on **Enable MCP +server** so it shows **Enabled**. -Screenshot note: **Attach Remote Identity Provider** showing Manual client -type, redirect URI, credential labels, and scopes, with secrets redacted. +This surface does not display the redirect URI; {#create-oauth-client} +registers `{{ gram.oauth.callback_url }}` directly. -Further-reading URL: -`https://developers.google.com/workspace/sheets/api/guides/configure-mcp-server`. +On first use, Google's browser authorization prompt appears. The account must +hold **MCP Tool User** ({#grant-mcp-tool-user}) and, for an External app in +**Testing**, be listed under **Test users**. -This guide covers setup only. For anything beyond it — billing, tool behavior, -limits — see Google's Sheets MCP documentation at -https://developers.google.com/workspace/sheets/api/guides/configure-mcp-server. +Screenshot note: **Settings > Identity** with **User Identity**, the Google +provider, and **Manual** selected; values redacted. ## Open questions @@ -228,8 +267,8 @@ https://developers.google.com/workspace/sheets/api/guides/configure-mcp-server. protected-resource metadata advertises `drive.readonly`, `drive`, `spreadsheets.readonly`, and `spreadsheets`. This Dossier follows the product-specific setup page for the manual override. Public documentation - does not confirm whether **Use Discovered** alone provides equivalent Drive - access. + does not confirm whether the PRM scope set alone provides equivalent Drive + access, so **Advanced > Scope** is set explicitly. ## Provenance @@ -282,3 +321,13 @@ All sources were observed at `2026-07-29T20:37:05Z`: authorization/token endpoints and no registration endpoint. - `doctrine/speakeasy-setup.md` — Custom remote and Manual OAuth flow. - `doctrine/personas/it-admin.md` — browser-only achievability requirements. + +Re-observed at `2026-09-30T21:25:45Z` (identity-section refresh): the product MCP setup page, +`https://developers.google.com/workspace/guides/configure-mcp-servers`, +`https://docs.cloud.google.com/mcp/set-up-authentication-mcp-servers`, the MCP +endpoint `initialize` probe, the path-suffixed PRM, Google's +authorization-server metadata, and `doctrine/speakeasy-setup.md` (gram +`68b3f78`). Newly drawn from: + +- `https://developers.google.com/workspace/preview` — Developer Preview + Program terms, apply action, form contents, timeline, and listed MCP servers. diff --git a/guides/google-sheets/speakeasy.md b/guides/google-sheets/speakeasy.md index 29883e7..8ca9838 100644 --- a/guides/google-sheets/speakeasy.md +++ b/guides/google-sheets/speakeasy.md @@ -11,79 +11,37 @@ https://sheetsmcp.googleapis.com/mcp/v1 ``` -5. Click **Verify connectivity**, then **Save**. +5. Leave **User session issuer** at its default. +6. Click **Verify connectivity**. +7. Under **Identity**, select **User Identity**. The page preselects **No Identity** for this server, so change it. +8. If **Guardrails** appears, leave it off. +9. Click **Save**. -This creates the hosted MCP server and opens its **Overview** page. +Speakeasy saves the server as **Disabled** and says to finish setup in **Settings > Identity**. This is expected; the next section completes it. - + ### Connect your credentials {#connect-speakeasy-credentials} -Open the server's **Settings** (from **Overview** for a hosted remote server, or **Configure MCP settings** after a catalog addition). +1. Open the server's **Settings** and find the **Identity** section. +2. Confirm that **User Identity** is selected. +3. In **Choose an identity provider**, confirm that the preselected provider is Google (`https://accounts.google.com/`). If another provider is shown, open the picker, search in **Search identity providers…**, and choose the Google provider. A provider badged **Will be created** is created when you save. +4. Choose **Manual**. +5. In **Client ID**, paste the **Client ID** from [Copy the OAuth credentials](external.md#copy-oauth-credentials). +6. In **Client secret**, paste the **Client secret** from the same section. Google requires it even though the field says "Optional". +7. Open **Advanced**. In **Scope**, enter this value on one line: -#### Choose an authentication provider - -- If **Authentication** is unconfigured, choose **Use Discovered** when available; otherwise choose **Configure Manually**. -- If authentication is configured but no provider is attached, use **Connected services** > **Add provider**. -- If the intended provider is already attached, use its existing controls. Do not attach a duplicate; check its client against the requirements below and skip **Verify and attach**. - -In **Attach Remote Identity Provider**, the provider selector defaults to **Select existing** when the project has issuers. Select the appropriate existing Google provider and skip new-provider setup. - -#### New provider only - -1. Choose **Add new** and enter **Issuer URL**: - - ```text - https://accounts.google.com/ - ``` - -2. Confirm the auto-derived **Slug** is unique in the project. -3. Discovery runs automatically for a seeded issuer URL. After typing or changing the URL, click **Discover** only if offered. -4. Review the endpoints, or enter these Google OAuth values if discovery does not populate them. - - Authorization endpoint: - - ```text - https://accounts.google.com/o/oauth2/v2/auth ``` - - Token endpoint: - - ```text - https://oauth2.googleapis.com/token + https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/spreadsheets.readonly https://www.googleapis.com/auth/spreadsheets ``` -#### Choose a session client - -- **Reuse:** Under **Session Client**, choose **Select existing** when available and select the appropriate Google OAuth client. Skip credential entry; continue to **Check client requirements**. -- **Create:** Choose **Add new** when available and set **Client Type** to **Manual**. For a new provider, complete the new-client form below. - -#### New session client only - -1. In **Client ID**, paste the **Client ID** from [Copy the OAuth credentials](external.md#copy-oauth-credentials). -1. In **Client Secret (optional)**, paste the **Client secret** from the same step. Google requires this generated secret. - -#### Check client requirements - -For both new and reused clients, verify the Google app's approved audience and publishing status. An **External** app in **Testing** must list each connecting account under **Test users**. Reusing a client does not require entering its credentials again. - -Confirm the selected client includes the required scopes below. For a new client, configure **Scope (override)**; for a reused client, inspect the read-only **Scope** value. If it does not match, choose **Add new** to create a correctly scoped client; the attach sheet cannot edit a reused client. - -For a new client, enter this value: - - ``` - https://www.googleapis.com/auth/drive.readonly,https://www.googleapis.com/auth/drive.file,https://www.googleapis.com/auth/spreadsheets.readonly,https://www.googleapis.com/auth/spreadsheets - ``` - -#### Verify and attach - -1. Confirm that the callback URL registered with the provider is `{{ gram.oauth.callback_url }}`. For a new manual client, also compare it with the sheet's displayed **Redirect URI**. The existing-client selection does not display that field; check the registered callback in the provider's app settings instead. -2. Click **Attach Identity Provider**. + Do not leave **Scope** blank. A blank value requests every scope the server advertises, including full Drive access, which the consent screen does not grant. -For the provider-side callback setting, see [Create the OAuth client](external.md#create-oauth-client). +8. Click **Save**. +9. Open **Settings > Danger Zone > Server Availability** and turn on **Enable MCP server** so it shows **Enabled**. -At first connection, complete Google's browser authorization with an account granted [MCP Tool User](external.md#grant-mcp-tool-user) and access to the intended spreadsheets. +When a person first uses the server, Google's browser authorization prompt appears. They must sign in with an account granted [MCP Tool User](external.md#grant-mcp-tool-user). If the app's audience is **External** and in **Testing**, the account must also be listed under **Test users**. - + This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Google's Sheets MCP documentation](https://developers.google.com/workspace/sheets/api/guides/configure-mcp-server). diff --git a/guides/google-slides/external.md b/guides/google-slides/external.md index 9866979..5cf7d17 100644 --- a/guides/google-slides/external.md +++ b/guides/google-slides/external.md @@ -4,11 +4,27 @@ setup_version: 1 # Set up Google Slides -The Google Slides MCP Server is in Developer Preview. Google does not document a Google Slides MCP-specific paid plan or license requirement. +The Google Slides MCP Server is in Developer Preview. Google requires membership in the Google Workspace Developer Preview Program, with the Google Cloud project registered in the program. Google does not document a Google Slides MCP-specific paid plan or license requirement. Use a Google Cloud project where you can enable services, grant project roles, configure **Google Auth platform**, and create OAuth credentials. Each connecting user needs access to the intended presentations. An application or security owner must also configure prompt and response screening for malicious content or prompt injection. -Sign in to the [Google Cloud console](https://console.cloud.google.com). In the console toolbar, select the project that will own this configuration, and keep it selected throughout the Google Cloud steps. +### Join the Google Workspace Developer Preview Program {#join-developer-preview} + +Skip this step if Google has already registered the project in the program. + +1. Open [developers.google.com/workspace/preview](https://developers.google.com/workspace/preview). +2. Review the **Developer Preview Program Terms** with the application or security owner. +3. Click **Apply to join the Developer Preview Program**. +4. In the current application form, enter the requested Google Workspace account and Google Cloud project information. The submitted email must accept being added to Google Groups. +5. Agree to the terms only with organizational approval. +6. Submit the form with the visible or equivalent submission control. +7. Wait for the final project-registration confirmation at the submitted email address. Google says this should complete within a couple of days. +8. After confirmation, sign in to the [Google Cloud console](https://console.cloud.google.com). +9. In the console toolbar, select the registered project. + +Keep that project selected throughout the Google Cloud steps. + + ### Enable the Google Slides APIs {#enable-google-slides-apis} diff --git a/guides/google-slides/meta.yaml b/guides/google-slides/meta.yaml index 80c6e9b..6d95589 100644 --- a/guides/google-slides/meta.yaml +++ b/guides/google-slides/meta.yaml @@ -22,6 +22,8 @@ credential_setup: - external.md#create-oauth-client - external.md#copy-oauth-credentials requirements: + - id: developer-preview + description: Google has registered the Google Cloud project in the Google Workspace Developer Preview Program, and the applicant's email accepts being added to the program's Google Group - id: google-cloud-project description: A Google Cloud project where an administrator can enable the Google Slides API and Google Slides MCP API, grant project IAM roles, configure Google Auth platform, and create OAuth credentials - id: connecting-user-access @@ -44,25 +46,30 @@ remotes: locator: https://developers.google.com/workspace/slides/api/guides/configure-mcp-server name: Configure the Slides MCP server classification: official - observed_at: "2026-07-29T21:55:52Z" + observed_at: "2026-09-30T21:25:42Z" - source: endpoint-observation locator: https://slidesmcp.googleapis.com/mcp/v1 name: Google Slides MCP endpoint classification: official status: MCP initialize returned HTTP 200 - version: "2025-03-26" - observed_at: "2026-07-29T21:55:52Z" + version: "2025-06-18" + observed_at: "2026-09-30T21:25:42Z" - source: endpoint-observation locator: https://slidesmcp.googleapis.com/.well-known/oauth-protected-resource/mcp/v1 name: Google Slides MCP protected-resource metadata classification: official - observed_at: "2026-07-29T21:55:52Z" + observed_at: "2026-09-30T21:25:42Z" provenance: - source: provider-documentation locator: https://developers.google.com/workspace/slides/api/guides/configure-mcp-server name: Configure the Slides MCP server classification: official - observed_at: "2026-07-29T21:55:52Z" + observed_at: "2026-09-30T21:25:42Z" + - source: provider-documentation + locator: https://developers.google.com/workspace/preview + name: Google Workspace Developer Preview Program + classification: official + observed_at: "2026-09-30T21:25:42Z" - source: provider-documentation locator: https://developers.google.com/workspace/guides/configure-mcp-servers name: Configure the Google Workspace MCP servers @@ -123,20 +130,20 @@ provenance: name: Google Slides MCP endpoint classification: official status: MCP initialize returned HTTP 200 - version: "2025-03-26" - observed_at: "2026-07-29T21:55:52Z" + version: "2025-06-18" + observed_at: "2026-09-30T21:25:42Z" - source: endpoint-observation locator: https://slidesmcp.googleapis.com/.well-known/oauth-protected-resource/mcp/v1 name: Google Slides MCP protected-resource metadata classification: official - observed_at: "2026-07-29T21:55:52Z" + observed_at: "2026-09-30T21:25:42Z" - source: endpoint-observation locator: https://accounts.google.com/.well-known/oauth-authorization-server name: Google authorization-server metadata classification: official - observed_at: "2026-07-29T21:55:52Z" + observed_at: "2026-09-30T21:25:42Z" - source: repository-doctrine locator: doctrine/speakeasy-setup.md name: Speakeasy setup canonical section classification: official - observed_at: "2026-07-29T21:55:52Z" + observed_at: "2026-09-30T21:25:42Z" diff --git a/guides/google-slides/research.md b/guides/google-slides/research.md index 7255358..8c037ee 100644 --- a/guides/google-slides/research.md +++ b/guides/google-slides/research.md @@ -10,11 +10,17 @@ researched_at: 2026-07-29T21:55:52Z - Remote URL: `https://slidesmcp.googleapis.com/mcp/v1`. - Transport: `streamable-http`. Google labels it **HTTP**. A direct MCP - `initialize` request over HTTPS POST returned HTTP 200 and protocol version - `2025-03-26` during this run. + `initialize` request over HTTPS POST (with + `Accept: application/json, text/event-stream`) returned HTTP 200 + unauthenticated and protocol version `2025-06-18` on + `2026-09-30T21:25:42Z`. - Launch stage: Developer Preview, announced in Google's July 13, 2026 - Workspace developer release notes. No separate preview enrollment is - documented. + Workspace developer release notes. Re-verified `2026-09-30`: the Slides + setup page's banner reads "Developer Preview: Available as part of the + Google Workspace Developer Preview Program" and its first prerequisite is + "Membership in the Google Workspace Developer Preview Program". The + earlier note that no enrollment was documented is superseded; see + {#join-developer-preview}. - Enable **Google Slides API** (`slides.googleapis.com`) and **Google Slides MCP API** (`slidesmcp.googleapis.com`) in one Google Cloud project. @@ -46,8 +52,10 @@ researched_at: 2026-07-29T21:55:52Z organizational solution can satisfy this requirement. - No Google Slides MCP-specific paid plan or license gate is documented. - The Speakeasy MCP Catalog lookup was **absent** for `google-slides` and - `google slides`. Render only the **Custom remote server** path; the shared - URL is not tenanted. + `google slides` (re-checked `2026-09-30` with `Google Slides` and + `slides`; no Google Slides entry). `meta.yaml` sets + `speakeasy_add_server: custom-remote`. Render only the **Hosted remotely** + path; the shared URL is not tenanted. ## Credential flow @@ -63,17 +71,42 @@ Create a **Web application** OAuth client. Enter | --- | --- | | Client ID | **OAuth 2.0 client created** in {#copy-oauth-credentials} | | Client Secret | **Client secrets** in {#copy-oauth-credentials}; copyable once | -| Scope override | The four scopes configured in {#configure-oauth-consent}, comma-separated | +| Scope | The four scopes configured in {#configure-oauth-consent}, space-separated on one line under **Advanced > Scope** | -The callback template is the same **Redirect URI** later displayed in -Speakeasy's **Attach Remote Identity Provider** sheet. Each connecting user -then authorizes with the Google Account whose Slides permissions should apply. +The Speakeasy **Identity** section does not display the redirect URI, so +{#create-oauth-client} carries the callback check by entering +`{{ gram.oauth.callback_url }}` directly. Each connecting user then authorizes +with the Google Account whose Slides permissions should apply. ## Console walkthrough -Sign in at `https://console.cloud.google.com`. Use the console toolbar's -resource selector to select the project that will own this configuration, and -keep it selected throughout the Google Cloud steps. +### Join the Google Workspace Developer Preview Program {#join-developer-preview} + +Source: `https://developers.google.com/workspace/preview` and the Slides setup +page's Prerequisites, observed `2026-09-30T21:25:42Z`. Same flow as the +Google Calendar guide's {#join-developer-preview}. + +- Skip when Google has already registered the project in the program. +- Open Google's **Google Workspace Developer Preview Program** page and review + the **Developer Preview Program Terms** with the organization's application + or security owner. +- Click **Apply to join the Developer Preview Program**. In the current + application form, provide the requested Google Workspace account and Google + Cloud project information, agree to the terms only with organizational + approval, and submit the form. Google does not publish the form's exact + field labels on the program page. +- The submitted email must accept being added to Google Groups; Google adds + the verified account to the program's Google Group, then registers the Cloud + project. +- Wait for the final confirmation at the registered email address. Google + says the process should be done within a couple of days. +- Then sign in at `https://console.cloud.google.com` and use the console + toolbar's resource selector to select the registered project; keep it + selected throughout the Google Cloud steps. +- Values entered: organization-specific Workspace account and Cloud project + information. Values copied: none. +- Screenshot note: the program page with **Apply to join the Developer + Preview Program**. ### Enable the Google Slides APIs {#enable-google-slides-apis} @@ -186,64 +219,64 @@ Slides scopes or block unconfigured apps. ## Speakeasy setup -Transcluded from `doctrine/speakeasy-setup.md`, observed at -`2026-07-29T21:55:52Z`. Fixed anchors are carried verbatim. - -The Speakeasy MCP Catalog lookup was **absent** for `google-slides` and -`google slides`. Render only the Custom remote server path. - -### Add the server in Speakeasy {#add-server-in-speakeasy} - -In the Speakeasy AI Control Plane sidebar, under **Connect**, select -**Sources**, then click **Add Source**. - -Choose **Custom remote server**. On the -**Add a custom remote MCP server** page, paste -`https://slidesmcp.googleapis.com/mcp/v1` into -**Remote MCP server URL** and click **Add server**. - -This creates the hosted MCP server and opens its **Overview** page. - - +Transcluded from `doctrine/speakeasy-setup.md` (product source +`speakeasy-api/gram`, `client/dashboard`, `main` @ `68b3f78`), observed +`2026-09-30T21:25:42Z`. Fixed anchors are carried verbatim. Per-guide values: -- Remote URL: `https://slidesmcp.googleapis.com/mcp/v1`. -- Transport: `streamable-http`; **Transport** is read-only. -- Authentication Option: `oauth-client`, manually registered OAuth. -- Catalog decision: absent; Custom remote server only. - -### Connect your credentials {#connect-speakeasy-credentials} - -From the server's **Overview**, open **Settings**. Under **Authentication**, -click **Configure Manually**, or **Use Discovered** when offered. In the -**Attach Remote Identity Provider** sheet, set **Client Type** to **Manual**. - -Confirm the sheet's **Redirect URI** matches `{{ gram.oauth.callback_url }}` -entered in {#create-oauth-client}. Paste the **Client ID** and -**Client Secret (optional)** from {#copy-oauth-credentials}. Google requires -the generated secret even though the Speakeasy label says optional. - -In **Scope (override)**, enter these comma-separated values: -`https://www.googleapis.com/auth/drive.readonly`, -`https://www.googleapis.com/auth/drive.file`, -`https://www.googleapis.com/auth/presentations.readonly`, -`https://www.googleapis.com/auth/presentations`. Click -**Attach Identity Provider**. +- Remote URL: `https://slidesmcp.googleapis.com/mcp/v1` (not tenanted). +- Add-server path: `speakeasy_add_server: custom-remote`; catalog lookup + absent. Render only **Hosted remotely**. +- Authentication Option: `oauth-client` → **User Identity**. +- Probe outcome: `initialize` POST returned **200 unauthenticated**, so the + create form preselects **No Identity**; the reader must select + **User Identity**. +- PRM: `https://slidesmcp.googleapis.com/.well-known/oauth-protected-resource/mcp/v1` + names issuer `https://accounts.google.com/` and advertises + `drive.readonly`, `presentations.readonly`, `drive`, `drive.file`, + `presentations`. +- Issuer metadata (`https://accounts.google.com/.well-known/oauth-authorization-server`): + issuer `https://accounts.google.com`, authorization endpoint + `https://accounts.google.com/o/oauth2/v2/auth`, token endpoint + `https://oauth2.googleapis.com/token`, no `registration_endpoint`, no + `client_id_metadata_document_supported`. Discovery works, so the provider + picker can preselect or create the Google provider; no custom provider + route is needed. +- Registration choice: **Manual** (neither CIMD nor DCR advertised; the + dashboard default is also Manual unless the provider already has a + client). Creation with **User Identity** leaves the server **Disabled** + with a note to finish in **Settings > Identity**; this is expected, and + **Server Availability** must be turned on afterwards. +- Credential fields: **Client ID** and **Client secret** from + {#copy-oauth-credentials}; Google requires the secret despite the + "Optional" placeholder. +- Scope under **Advanced > Scope**, space-separated on one line: + `https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/presentations.readonly https://www.googleapis.com/auth/presentations`. + Blank is not safe: the PRM also advertises full + `https://www.googleapis.com/auth/drive`, which the consent screen does not + configure. +- Redirect URI: not displayed on the Identity section; {#create-oauth-client} + registers `{{ gram.oauth.callback_url }}`. +- First connection: an account with **MCP Tool User** ({#grant-mcp-tool-user}) + and access to the presentations; an External app in **Testing** also needs + the account under **Test users**. +- Screenshot notes: **New remote MCP server** after **Verify connectivity** + with **User Identity** selected; **Settings > Identity** with the Google + provider and **Manual**, credentials redacted. +- Further-reading URL: + `https://developers.google.com/workspace/slides/api/guides/configure-mcp-server`. -Complete Google's browser authorization with an account granted -**MCP Tool User** in {#grant-mcp-tool-user} and access to the intended -presentations. An External app in **Testing** also requires that account under -**Test users**. +### Add the server in Speakeasy {#add-server-in-speakeasy} -Screenshot note: the manual identity-provider sheet with credentials redacted. +Hosted remotely path with **User Identity** selected at creation, per the +values above. -Further-reading URL: -`https://developers.google.com/workspace/slides/api/guides/configure-mcp-server`. +### Connect your credentials {#connect-speakeasy-credentials} -This guide covers setup only. For anything beyond it — billing, tool behavior, -limits — see Google's Slides MCP documentation at -https://developers.google.com/workspace/slides/api/guides/configure-mcp-server. +**Settings > Identity** > **User Identity** > Google provider > **Manual** +with the values above, **Save**, then **Settings > Danger Zone > Server +Availability** > **Enable MCP server**. ## Open questions @@ -296,11 +329,24 @@ All sources were observed at `2026-07-29T21:55:52Z`: - `https://support.google.com/cloud/answer/15549135` — Data Access controls. - `https://support.google.com/a/answer/7281227?hl=en` — Workspace app controls, high-risk scopes, and allowlisting labels. + +- `doctrine/personas/it-admin.md` — browser-only achievability requirements. + +Re-observed at `2026-09-30T21:25:42Z`: + +- `https://developers.google.com/workspace/slides/api/guides/configure-mcp-server` + — Developer Preview Program membership prerequisite; endpoint, scopes, and + Web application client unchanged. +- `https://developers.google.com/workspace/preview` — program terms, + application button, Google Groups requirement, and couple-of-days timing. - `https://slidesmcp.googleapis.com/mcp/v1` — MCP `initialize` returned HTTP - 200 with protocol version `2025-03-26`. + 200 unauthenticated with protocol version `2025-06-18`. - `https://slidesmcp.googleapis.com/.well-known/oauth-protected-resource/mcp/v1` - — authorization server, resource URL, and advertised scopes. + — authorization server `https://accounts.google.com/`, resource URL, and + five advertised scopes including full `drive`. - `https://accounts.google.com/.well-known/oauth-authorization-server` — - authorization/token endpoints and no registration endpoint. -- `doctrine/speakeasy-setup.md` — Custom remote and Manual OAuth flow. -- `doctrine/personas/it-admin.md` — browser-only achievability requirements. + authorization/token endpoints; no registration endpoint and no CIMD. +- Speakeasy MCP Catalog search (`Google Slides`, `slides`) — no Google Slides + entry. +- `doctrine/speakeasy-setup.md` (gram `68b3f78`) — Hosted remotely, Identity + section, Manual registration, and Server Availability. diff --git a/guides/google-slides/speakeasy.md b/guides/google-slides/speakeasy.md index 48cdcf0..b5e5795 100644 --- a/guides/google-slides/speakeasy.md +++ b/guides/google-slides/speakeasy.md @@ -11,79 +11,41 @@ https://slidesmcp.googleapis.com/mcp/v1 ``` -5. Click **Verify connectivity**, then **Save**. +5. Leave **User session issuer** at its default. +6. Click **Verify connectivity**. +7. After verification succeeds, select **User Identity** under **Identity**. The page preselects **No Identity** for this server, so change it. +8. Click **Save**. -This creates the hosted MCP server and opens its **Overview** page. **Transport** is read-only. +Speakeasy keeps the new server **Disabled** and says to finish setup in **Settings > Identity**. This is expected for Google Slides; continue with the next section. - + ### Connect your credentials {#connect-speakeasy-credentials} -Open the server's **Settings** (from **Overview** for a hosted remote server, or **Configure MCP settings** after a catalog addition). +Open the server's **Settings** and find the **Identity** section. -#### Choose an authentication provider +1. Confirm **User Identity** is selected. +2. Under **Choose an identity provider**, confirm the preselected Google provider (`https://accounts.google.com`). A new provider shows **Will be created**. If a different provider is preselected, open the picker, search in **Search identity providers…**, and choose the Google provider. +3. Choose **Manual**. If **Existing client** is preselected, switch to **Manual** unless that client is the one created in [Create the OAuth client](external.md#create-oauth-client) with the four scopes below. +4. Paste the **Client ID** from [Copy the OAuth credentials](external.md#copy-oauth-credentials) into **Client ID**. +5. Paste the **Client secret** from [Copy the OAuth credentials](external.md#copy-oauth-credentials) into **Client secret**. Google requires this secret even though the field shows "Optional". +6. Under **Advanced > Scope**, enter this value on one line: -- If **Authentication** is unconfigured, choose **Use Discovered** when available; otherwise choose **Configure Manually**. -- If authentication is configured but no provider is attached, use **Connected services** > **Add provider**. -- If the intended provider is already attached, use its existing controls. Do not attach a duplicate; check its client against the requirements below and skip **Verify and attach**. - -In **Attach Remote Identity Provider**, the provider selector defaults to **Select existing** when the project has issuers. Select the appropriate existing Google provider and skip new-provider setup. - -#### New provider only - -1. Choose **Add new** and enter **Issuer URL**: - - ```text - https://accounts.google.com/ - ``` - -2. Confirm the auto-derived **Slug** is unique in the project. -3. Discovery runs automatically for a seeded issuer URL. After typing or changing the URL, click **Discover** only if offered. -4. Review the endpoints, or enter these Google OAuth values if discovery does not populate them. - - Authorization endpoint: - - ```text - https://accounts.google.com/o/oauth2/v2/auth ``` - - Token endpoint: - - ```text - https://oauth2.googleapis.com/token + https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/presentations.readonly https://www.googleapis.com/auth/presentations ``` -#### Choose a session client - -- **Reuse:** Under **Session Client**, choose **Select existing** when available and select the appropriate Google OAuth client. Skip credential entry; continue to **Check client requirements**. -- **Create:** Choose **Add new** when available and set **Client Type** to **Manual**. For a new provider, complete the new-client form below. - -#### New session client only - -1. Paste the **Client ID** from [Copy the OAuth credentials](external.md#copy-oauth-credentials). -1. Paste the **Client Secret** from [Copy the OAuth credentials](external.md#copy-oauth-credentials) into **Client Secret (optional)**. Google's web client requires this generated secret. - -#### Check client requirements - -For both new and reused clients, verify the Google app's approved audience and publishing status. An **External** app in **Testing** must list each connecting account under **Test users**. Reusing a client does not require entering its credentials again. - -Confirm the selected client includes the required scopes below. For a new client, configure **Scope (override)**; for a reused client, inspect the read-only **Scope** value. If it does not match, choose **Add new** to create a correctly scoped client; the attach sheet cannot edit a reused client. - -For a new client, enter this value: - - ``` - https://www.googleapis.com/auth/drive.readonly,https://www.googleapis.com/auth/drive.file,https://www.googleapis.com/auth/presentations.readonly,https://www.googleapis.com/auth/presentations - ``` + Do not leave **Scope** blank. A blank value also requests full Google Drive access (`https://www.googleapis.com/auth/drive`), which the consent screen does not grant. -#### Verify and attach +7. Click **Save**. If asked to confirm, click **Save changes**. -1. Confirm that the callback URL registered with the provider is `{{ gram.oauth.callback_url }}`. For a new manual client, also compare it with the sheet's displayed **Redirect URI**. The existing-client selection does not display that field; check the registered callback in the provider's app settings instead. -2. Click **Attach Identity Provider**. +Turn the server on: -For the provider-side callback setting, see [Create the OAuth client](external.md#create-oauth-client). +1. Open **Settings > Danger Zone > Server Availability**. +2. Turn on the switch (**Enable MCP server**) so it shows **Enabled**. At first connection, complete Google's browser authorization with an account granted **MCP Tool User** in [Grant MCP Tool User access](external.md#grant-mcp-tool-user) and access to the intended presentations. An **External** app in **Testing** also requires that account under **Test users**. - + -For anything beyond setup — billing, tool behavior, or limits — see [Google's Slides MCP documentation](https://developers.google.com/workspace/slides/api/guides/configure-mcp-server). +This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Google's Slides MCP documentation](https://developers.google.com/workspace/slides/api/guides/configure-mcp-server). diff --git a/guides/hubspot/external.md b/guides/hubspot/external.md index 2b63c9b..281943c 100644 --- a/guides/hubspot/external.md +++ b/guides/hubspot/external.md @@ -8,23 +8,23 @@ You need a HubSpot account and a user who can open the **Development** workspace from the main navigation bar. The remote MCP server is available to all HubSpot accounts. Sign in at [app.hubspot.com](https://app.hubspot.com). -### Open MCP Auth Apps in the Development workspace {#open-mcp-auth-apps} +### Open MCP Connectors in the Development workspace {#open-mcp-auth-apps} 1. Sign in at [app.hubspot.com](https://app.hubspot.com). 2. In the main navigation bar, select **Development**. -3. In the left sidebar menu, select **MCP Auth Apps**. +3. In the left sidebar menu, select **MCP Connectors**. If **Development** is unavailable, use the direct -[MCP Auth Apps page](https://app.hubspot.com/l/mcp-auth-apps/). If you still +[MCP Connectors page](https://app.hubspot.com/l/mcp-auth-apps/). If you still cannot open it, ask your HubSpot administrator to confirm your access to this developer feature. - + -### Create the MCP auth app {#create-mcp-auth-app} +### Create the MCP connector {#create-mcp-auth-app} -1. In the upper right, click **Create MCP auth app**. -2. In **App name**, enter a recognizable name, such as +1. In the upper right, click **Create MCP connector**. +2. In **Name**, enter a recognizable name, such as `Speakeasy AI Control Plane`. 3. Optionally, enter a **Description**. 4. In **Redirect URL**, paste this value: @@ -40,11 +40,11 @@ If you configure multiple redirect URLs, keep `{{ gram.oauth.callback_url }}` first because HubSpot uses the first URL as the default. - + ### Copy the client credentials {#copy-client-credentials} -HubSpot opens the app's details page. +HubSpot opens the connector's details page. 1. Copy the **Client ID**. 2. Copy the **Client secret**. diff --git a/guides/hubspot/meta.yaml b/guides/hubspot/meta.yaml index 5264490..c1eb9da 100644 --- a/guides/hubspot/meta.yaml +++ b/guides/hubspot/meta.yaml @@ -2,7 +2,7 @@ schema_version: 1 slug: hubspot title: HubSpot -summary: Connect HubSpot's hosted MCP server using an MCP auth app and OAuth. +summary: Connect HubSpot's hosted MCP server using an MCP connector and OAuth. aliases: - com.pulsemcp.mirror/hubspot speakeasy_add_server: catalog @@ -23,7 +23,7 @@ credential_setup: - external.md#copy-client-credentials requirements: - id: hubspot-account - description: HubSpot account whose user can open the Development workspace from the main navigation bar to create and manage MCP auth apps + description: HubSpot account whose user can open the Development workspace from the main navigation bar to create and manage MCP connectors documentation: external: external.md speakeasy: speakeasy.md @@ -38,11 +38,11 @@ remotes: locator: https://developers.hubspot.com/docs/apps/developer-platform/build-apps/integrate-with-the-remote-hubspot-mcp-server name: Integrate AI tools with the HubSpot MCP server classification: official - observed_at: "2026-07-28T18:22:41Z" + observed_at: "2026-09-30T00:00:00Z" - source: endpoint-observation locator: https://mcp.hubspot.com/.well-known/oauth-protected-resource classification: official - observed_at: "2026-07-28T18:22:41Z" + observed_at: "2026-09-30T00:00:00Z" provenance: - source: pulsemcp name: com.pulsemcp.mirror/hubspot @@ -54,7 +54,7 @@ provenance: locator: https://developers.hubspot.com/docs/apps/developer-platform/build-apps/integrate-with-the-remote-hubspot-mcp-server name: Integrate AI tools with the HubSpot MCP server classification: official - observed_at: "2026-07-28T18:22:41Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation locator: https://developers.hubspot.com/docs/llms.txt name: HubSpot developer documentation index @@ -93,13 +93,13 @@ provenance: - source: endpoint-observation locator: https://mcp.hubspot.com/.well-known/oauth-protected-resource classification: official - observed_at: "2026-07-28T18:22:41Z" + observed_at: "2026-09-30T00:00:00Z" - source: endpoint-observation locator: https://mcp.hubspot.com/.well-known/oauth-authorization-server classification: official - observed_at: "2026-07-28T18:22:41Z" + observed_at: "2026-09-30T00:00:00Z" - source: repository-doctrine locator: doctrine/speakeasy-setup.md name: Speakeasy setup canonical section classification: official - observed_at: "2026-07-28T18:22:41Z" + observed_at: "2026-09-30T00:00:00Z" diff --git a/guides/hubspot/research.md b/guides/hubspot/research.md index 5f23141..ecd001b 100644 --- a/guides/hubspot/research.md +++ b/guides/hubspot/research.md @@ -21,7 +21,9 @@ behavior and the Sensitive Data Properties restriction, both flagged where used. The developer changelog is used for product status and for capability changes newer than the setup page. The primary setup page, its newly published documentation index, the permissions guide, and the live -OAuth metadata were reverified at `2026-07-28T18:22:41Z`. The operator also +OAuth metadata were reverified at `2026-07-28T18:22:41Z`; the setup page +and live OAuth metadata were re-read on `2026-09-30`, when HubSpot's UI +names had changed from MCP auth app to MCP connector. The operator also confirmed that the Speakeasy MCP Catalog contains `com.pulsemcp.mirror/hubspot`, titled **HubSpot**, so this Guide uses only the catalog add-server path. @@ -145,8 +147,8 @@ catalog add-server path. ## Credential flow Who acts: a user in the HubSpot account who can open the **Development** -workspace from the main navigation bar — that is where **MCP Auth Apps** -lives. The current setup page also links directly to +workspace from the main navigation bar — that is where **MCP +Connectors** (formerly **MCP Auth Apps**) lives. The current setup page also links directly to `https://app.hubspot.com/l/mcp-auth-apps/`. No HubSpot source names the exact permission that gates this UI. The KB's user-permissions guide documents a **Developer tools access** @@ -164,7 +166,8 @@ be a Super Admin to access private apps") is scoped to *private apps*, a different app type — not evidence about MCP auth apps (see open questions). -What gets created: one **MCP auth app** in the account's Development +What gets created: one **MCP connector** (formerly **MCP auth app**) in +the account's Development workspace. HubSpot generates a **Client ID** and **Client secret** for it; both stay viewable on the app's details page (no one-time display). @@ -176,7 +179,7 @@ Values the Speakeasy AI Control Plane needs, and where they come from: | Client secret | Generated by HubSpot; shown on the same details page ({#copy-client-credentials}) | Where `{{ gram.oauth.callback_url }}` gets pasted: into the **Redirect -URL** field of the **Create MCP auth app** dialog +URL** field of the **Create MCP connector** dialog ({#create-mcp-auth-app}). The setup page describes the field as "the URL to use for OAuth authentication" and notes app details "you can update later as needed" via **Edit info** on the details page. If multiple @@ -197,16 +200,20 @@ must connect before other users can (see {#admin-connects-first}). Primary source: the setup page's "Create an MCP auth app" section (developers.hubspot.com; fetched live this run). The flow is short: main -navigation > Development > MCP Auth Apps > Create MCP auth app dialog > +navigation > Development > MCP Connectors > Create MCP connector dialog > Create > auto-redirect to the app's details page. Every transition below is documented except where flagged. -### Open MCP Auth Apps in the Development workspace {#open-mcp-auth-apps} +### Open MCP Connectors in the Development workspace {#open-mcp-auth-apps} + +HubSpot renamed **MCP Auth Apps** to **MCP Connectors** (setup page +re-read `2026-09-30`). The anchor keeps its original ID so existing links +stay valid. - Entry: sign in at `app.hubspot.com`. Setup page, verbatim: "In the main navigation bar of your HubSpot account, navigate to **Development**." Then: "In the left sidebar menu, navigate to **MCP - Auth Apps**." + Connectors**." - If navigation is unavailable, the setup page's direct account link is `https://app.hubspot.com/l/mcp-auth-apps/`; opening it still requires a signed-in account with access to this developer feature. @@ -216,16 +223,16 @@ is documented except where flagged. (flagged inference — see credential flow and open questions). - Values entered: HubSpot sign-in only. Values copied: none. - Screenshot note: the HubSpot main navigation bar with **Development** - visible, and the resulting Development workspace with **MCP Auth - Apps** highlighted in the left sidebar menu. + visible, and the resulting Development workspace with **MCP + Connectors** highlighted in the left sidebar menu. -### Create the MCP auth app {#create-mcp-auth-app} +### Create the MCP connector {#create-mcp-auth-app} -- Setup page, verbatim: "In the upper right, click **Create MCP auth - app**." -- "In the dialog box, enter your app details, which you can update later - as needed" — fields, with the page's own descriptions: - - **App name**: "the name of your app" — a recognizable name such as +- Setup page, verbatim: "In the upper right, click **Create MCP + connector**." +- "In the dialog box, enter your connector details, which you can update + later as needed" — fields, with the page's own descriptions: + - **Name**: "the name of your connector" — a recognizable name such as `Speakeasy AI Control Plane`. - **Description**: "an optional description of your app." - **Redirect URL**: "the URL to use for OAuth authentication" — paste @@ -240,12 +247,12 @@ is documented except where flagged. field; how additional URLs are added is not documented (see open questions). Keep the Speakeasy AI Control Plane callback as the first (or only) entry. -- Values entered: **App name**, `{{ gram.oauth.callback_url }}` into +- Values entered: **Name**, `{{ gram.oauth.callback_url }}` into **Redirect URL**, optional **Description**/**Icon**. Values copied: none yet. -- Screenshot note: the **MCP Auth Apps** page with the **Create MCP auth - app** button in the upper right and the creation dialog open, showing - the **App name**, **Description**, **Redirect URL**, and **Icon** +- Screenshot note: the **MCP Connectors** page with the **Create MCP + connector** button in the upper right and the creation dialog open, + showing the **Name**, **Description**, **Redirect URL**, and **Icon** fields. - Recovery: nothing bites — "you can update later as needed"; app details are editable afterward via **Edit info** on the details page @@ -253,10 +260,10 @@ is documented except where flagged. ### Copy the client credentials {#copy-client-credentials} -- Setup page, verbatim: "You'll then be redirected to the app's details - page, where you can view its client credentials, redirect URLs, and - more. To edit your app details, you can click **Edit info** in the - upper right." +- Setup page, verbatim: "You'll then be redirected to the connector's + details page, where you can view its client credentials, redirect URLs, + and more. To edit your connector details, you can click **Edit info** in + the upper right." - Copy the **Client ID** and **Client secret** into the matching Speakeasy AI Control Plane fields; treat the Client secret like a password. @@ -270,59 +277,76 @@ is documented except where flagged. ## Speakeasy setup -Canonical source: `doctrine/speakeasy-setup.md`, observed -`2026-07-28T18:22:41Z`. +Canonical source: `doctrine/speakeasy-setup.md` (gram `main` `68b3f78`), +observed `2026-09-30`. Per-guide values: -- Remote URL: `https://mcp.hubspot.com` -- Transport: `streamable-http` (the add form's **Transport** field is - read-only) +- Remote URL: `https://mcp.hubspot.com` (shared, not tenanted) +- `speakeasy_add_server`: `catalog`; catalog presence resolved by the + operator's Pulse lookup: `com.pulsemcp.mirror/hubspot`, title **HubSpot** - Authentication Option: OAuth with a manually registered client; HubSpot - requires PKCE -- Client ID and Client Secret: generated in - {#copy-client-credentials} + requires PKCE. Identity mode: **User Identity** +- Probe outcome (`2026-09-30`): JSON-RPC `initialize` POST returns 401 with + `WWW-Authenticate: Bearer + resource_metadata="https://mcp.hubspot.com/.well-known/oauth-protected-resource"` +- PRM issuer: `https://mcp.hubspot.com`; PRM `scopes_supported: []` +- CIMD / DCR: neither. Authorization-server metadata has no + `client_id_metadata_document_supported` and no `registration_endpoint`; + token endpoint auth method `client_secret_post` only, so the client secret + is required +- Catalog **Identity** default: the entry does not support client + registration (Pulse records DCR unsupported), so **Add to Project** + preselects **No Identity**; readers select **User Identity**. Creation + cannot register a client, so the server is kept **Disabled** and the + result points to **Settings > Identity**; the Guide says this is expected +- Registration choice: **Manual** (the dashboard default when no client + exists and neither CIMD nor DCR is advertised) +- Client ID and Client secret: generated in {#copy-client-credentials} +- Scope: leave **Advanced > Scope** blank. HubSpot determines scopes + automatically and the PRM advertises none, so blank requests nothing + broader than the connector grants - Redirect callback: `{{ gram.oauth.callback_url }}`, registered in HubSpot's - **Redirect URL** field in {#create-mcp-auth-app} -- Scopes to type: none; HubSpot determines scopes automatically -- OAuth discovery: HubSpot publishes protected-resource metadata pointing to - issuer `https://mcp.hubspot.com`, plus authorization-server metadata, but - does not publish a dynamic client-registration endpoint + **Redirect URL** field in {#create-mcp-auth-app}. The **Identity** section + does not display the redirect URI, so the Guide points back to that step +- Server Availability: required, because creation left the server + **Disabled** - Further reading: `https://developers.hubspot.com/docs/apps/developer-platform/build-apps/integrate-with-the-remote-hubspot-mcp-server` ### Add the server in Speakeasy {#add-server-in-speakeasy} -In the Speakeasy AI Control Plane sidebar, under **Connect**, select -**Sources**, then click **Add Source**. - -Choose **3rd-party server**. On the **MCP Catalog** page, find **HubSpot** -(the search box reads **Search MCP servers...**), open its entry with -**View**, and click **Add**. In the **Add to Project** dialog, click -**Add to Project**. This creates the hosted MCP server and opens its -**Overview** page. +In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select +**MCP**, then click **Add new** to open **Add MCP server**. Choose **From the +catalog**. On the **MCP Catalog** page, find **HubSpot** using **Search MCP +servers...**, open its catalog entry, and click **Add**. In **Add to +Project**, switch **Identity** from **No Identity** to **User Identity**, +then click **Add to Project** (click **Skip for now** if a **Guardrails** +step appears). After **Server added successfully**, click **Configure MCP +settings**. The server is kept **Disabled** until identity setup finishes; +this is expected. -Screenshot note: capture the **Add Source** menu or the **HubSpot** catalog -entry. Catalog presence was resolved by the operator's Pulse lookup: -`com.pulsemcp.mirror/hubspot`, title **HubSpot**. +Screenshot note: the **HubSpot** catalog entry with the **Identity** choice +set to **User Identity**. ### Connect your credentials {#connect-speakeasy-credentials} -From the server's **Overview**, open **Settings**. Under **Authentication**, -click **Configure Manually**, or **Use Discovered** if HubSpot's published -metadata makes that control available. In **Attach Remote Identity Provider**: +Open the server's **Settings** and find the **Identity** section: -1. Set **Client Type** to **Manual**. -2. Confirm the sheet's **Redirect URI** matches the - `{{ gram.oauth.callback_url }}` value registered in HubSpot's - **Redirect URL** field in {#create-mcp-auth-app}. -3. Paste the **Client ID** and **Client Secret (optional)** copied in - {#copy-client-credentials}. -4. Leave any scope override empty; HubSpot determines scopes automatically. -5. Click **Attach Identity Provider**. +1. Select **User Identity**. +2. Under **Choose an identity provider**, confirm the preselected provider + is `https://mcp.hubspot.com` (badged **Will be created** when new). +3. Select **Manual**. +4. Paste the **Client ID** and **Client secret** copied in + {#copy-client-credentials}. The secret is required despite the + "Optional" placeholder. +5. Leave **Advanced > Scope** blank. +6. Click **Save**. +7. Open **Settings > Danger Zone > Server Availability** and turn on + **Enable MCP server** so it shows **Enabled**. -Screenshot note: capture **Attach Remote Identity Provider** with -**Client Type** set to **Manual** and all credential values redacted. +Screenshot note: **Settings > Identity** with **User Identity** selected, +the HubSpot provider, and **Manual**; all credential values redacted. When HubSpot authorization opens, use the intended account, grant the permissions offered, and authorize the connection. HubSpot documents the @@ -409,7 +433,8 @@ admin has connected — are undocumented (see open questions). The guide's only Super Admin requirement in this area is scoped to private apps, a different app type; whether Super Admin is required for MCP auth apps is unknown. -- **MCP Auth Apps beta status.** The MCP Auth Apps UI was announced as +- **MCP Connectors (formerly MCP Auth Apps) beta status.** The MCP Auth + Apps UI was announced as public beta (changelog 2026-01-20) and still labeled "Public Beta" in the Spring 2026 Spotlight (2026-04-14), but the current setup page shows no beta badge or label anywhere (checked explicitly this run), @@ -459,14 +484,17 @@ One entry per source drawn from: - `https://developers.hubspot.com/docs/apps/developer-platform/build-apps/integrate-with-the-remote-hubspot-mcp-server` ("Integrate AI tools with the HubSpot MCP server") — reobserved at - `2026-07-28T18:22:41Z`. The former alternate path + `2026-07-28T18:22:41Z` and re-read `2026-09-30` for the MCP Connectors + labels (**MCP Connectors**, **Create MCP connector**, **Name**), the + unchanged direct link `https://app.hubspot.com/l/mcp-auth-apps/`, and + unchanged endpoint, PKCE, and automatic-scope statements. The former alternate path `.../build-apps/integrate-with-hubspot-mcp-server` now 308-redirects here (redirect observed this run; the prior run saw it serve the page verbatim). Backs: endpoint `https://mcp.hubspot.com`, PKCE requirement and troubleshooting detail, the full MCP-auth-app creation flow (navigation "main navigation bar ... **Development**", "left - sidebar menu ... **MCP Auth Apps**", "**Create MCP auth app**", dialog - fields **App name** / **Description** / **Redirect URL** / **Icon**, + sidebar menu ... **MCP Connectors**", "**Create MCP connector**", dialog + fields **Name** / **Description** / **Redirect URL** / **Icon**, "**Create**"), multiple-redirect default behavior, details-page redirect and **Edit info**, general client connection values (Client ID / Client secret / Redirect URL) and the three-step end-user OAuth @@ -536,13 +564,14 @@ One entry per source drawn from: `https://mcp.hubspot.com/.well-known/oauth-protected-resource` + `https://mcp.hubspot.com/.well-known/oauth-authorization-server` — direct endpoint observation reverified at - `2026-07-28T18:22:41Z`. Backs: + `2026-09-30` (unchanged; no CIMD advertised). Backs: 401/Bearer behavior with `resource_metadata` pointer, protected- resource metadata (resource `https://mcp.hubspot.com`, authorization server `https://mcp.hubspot.com`, `scopes_supported: []`, `resource_documentation: https://developers.hubspot.com/mcp`), and authorization-server metadata (endpoints, grant types, S256, `client_secret_post`, no `registration_endpoint`). -- `doctrine/speakeasy-setup.md` — observed - `2026-07-28T18:22:41Z`. Backs the catalog add-server and manual OAuth - attachment labels, fixed Speakeasy anchors, and closing pointer. +- `doctrine/speakeasy-setup.md` (gram `main` `68b3f78`) — observed + `2026-09-30`. Backs the catalog add-server path, the **Identity** section + with **Manual** registration and **Advanced > Scope**, Server + Availability, fixed Speakeasy anchors, and closing pointer. diff --git a/guides/hubspot/speakeasy.md b/guides/hubspot/speakeasy.md index c6521de..b275a76 100644 --- a/guides/hubspot/speakeasy.md +++ b/guides/hubspot/speakeasy.md @@ -9,43 +9,32 @@ **HubSpot**. 5. Open the **HubSpot** entry. 6. Click **Add**. -7. In the **Add to Project** dialog, click **Add to Project**. +7. In the **Add to Project** dialog, under **Identity**, select **User Identity**. The dialog preselects **No Identity** for HubSpot. +8. Click **Add to Project**. If the dialog offers a **Guardrails** step, click **Skip for now**. +9. When the dialog finishes, the result reads "Added, but disabled until identity is set up." Click **Finish setup** to open the server's **Settings**. -After installation, select **Configure MCP settings** on the completion screen to open the server, then open **Settings**. +HubSpot needs a client registered by hand, so the server is kept **Disabled** and the result says to finish setup in **Settings > Identity**. This is expected. - + ### Connect your credentials {#connect-speakeasy-credentials} -Select **Configure MCP settings** on the completion screen, then open the server’s **Settings**. +Open the server's **Settings** and find the **Identity** section. -Under **Authentication**, if unconfigured, select **Use Discovered** when available; otherwise select **Configure Manually**. If configured but no provider is attached, use **Connected services > Add provider**. If the intended provider is already attached, use its existing controls and skip the provider/client creation and attachment steps below; do not add a duplicate. - -#### Select the identity provider - -In **Attach Remote Identity Provider**, **Identity Provider** defaults to **Select existing** when project issuers are available. Select the matching provider and skip the new-provider fields below. Otherwise choose **Add new** (or use the new-provider form shown when none exist). - -For a new provider only, confirm **Issuer URL**, the auto-derived **Slug**, and **Endpoints**. Discovery runs automatically for a seeded issuer; after typing or changing the URL, select **Discover** only if offered. - -For **Identity Provider > Add new**, use **Issuer URL** `https://mcp.hubspot.com`, authorization endpoint `https://mcp.hubspot.com/oauth/authorize/user`, and token endpoint `https://mcp.hubspot.com/oauth/v3/token`. Keep the auto-derived **Slug**. - -#### Select the session client - -Under **Session Client**, choose **Select existing** only for a client whose saved credentials, scopes, and audience match the requirements below; otherwise choose **Add new**. When reusing a matching client, skip directly to **Verify the callback and attach** below. Do not create credentials or register the client again. Otherwise choose **Add new** (or use the new-client form shown when no clients exist) and complete these new-client-only steps: - -1. In **Attach Remote Identity Provider**, set **Client Type** to **Manual**. -1. Paste the **Client ID** copied in +1. Select **User Identity**. +2. Under **Choose an identity provider**, confirm the preselected provider is `https://mcp.hubspot.com`. A provider that does not exist yet shows **Will be created**. +3. Select **Manual**. It is the default for HubSpot unless the provider already has a client. +4. In **Client ID**, paste the **Client ID** copied in [Copy the client credentials](external.md#copy-client-credentials). -1. Paste the **Client Secret (optional)** copied in - [Copy the client credentials](external.md#copy-client-credentials). -1. Leave any scope override empty. - -#### Verify the callback and attach +5. In **Client secret**, paste the **Client secret** copied in + [Copy the client credentials](external.md#copy-client-credentials). HubSpot requires it, even though the field shows "Optional". +6. Leave **Advanced > Scope** blank. HubSpot determines scopes automatically and advertises none, so a blank field requests nothing extra. +7. Click **Save**. +8. Open **Settings > Danger Zone > Server Availability** and turn on **Enable MCP server** so it shows **Enabled**. -1. Confirm that the callback URL registered with the provider is `{{ gram.oauth.callback_url }}`. For a new manual client, also compare it with the sheet's displayed **Redirect URI**. The existing-client selection does not display that field; check the registered callback in the provider's app settings instead. -2. Click **Attach Identity Provider**. +This screen does not show the redirect URI. If authorization later fails with a redirect error, check that the connector's **Redirect URL** in HubSpot is `{{ gram.oauth.callback_url }}`, as set in [Create the MCP connector](external.md#create-mcp-auth-app). - + For the HubSpot account's first connection, use an account admin. HubSpot does not document which admin role qualifies. diff --git a/guides/intercom/meta.yaml b/guides/intercom/meta.yaml index 901c5ea..cb30c00 100644 --- a/guides/intercom/meta.yaml +++ b/guides/intercom/meta.yaml @@ -40,7 +40,7 @@ remotes: locator: https://developers.intercom.com/docs/guides/mcp name: Model Context Protocol (MCP) classification: official - observed_at: "2026-07-29T15:06:51Z" + observed_at: "2026-09-30T00:00:00Z" - source: operator-validation locator: draft-guide operator notes for intercom status: manual OAuth validated @@ -56,7 +56,7 @@ remotes: locator: https://developers.intercom.com/docs/guides/mcp name: Model Context Protocol (MCP) classification: official - observed_at: "2026-07-29T15:06:51Z" + observed_at: "2026-09-30T00:00:00Z" - source: operator-validation locator: draft-guide operator notes for intercom status: manual OAuth validated @@ -66,7 +66,7 @@ provenance: locator: https://developers.intercom.com/docs/guides/mcp name: Model Context Protocol (MCP) classification: official - observed_at: "2026-07-29T15:06:51Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation locator: https://developers.intercom.com/docs/build-an-integration/getting-started name: Set up a Workspace @@ -76,7 +76,7 @@ provenance: locator: https://developers.intercom.com/docs/build-an-integration/learn-more/authentication/setting-up-oauth name: Setting up OAuth classification: official - observed_at: "2026-07-29T15:06:51Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation locator: https://developers.intercom.com/docs/build-an-integration/learn-more/authentication/oauth-scopes name: OAuth Scopes @@ -105,7 +105,11 @@ provenance: - source: endpoint-observation locator: https://mcp.intercom.com/.well-known/oauth-authorization-server classification: official - observed_at: "2026-07-29T15:06:51Z" + observed_at: "2026-09-30T00:00:00Z" + - source: endpoint-observation + locator: https://mcp.eu.intercom.com/.well-known/oauth-authorization-server + classification: official + observed_at: "2026-09-30T00:00:00Z" - source: operator-validation locator: draft-guide operator notes for intercom status: manual OAuth recommended; DCR requires callback allowlisting @@ -114,4 +118,4 @@ provenance: locator: doctrine/speakeasy-setup.md name: Speakeasy setup canonical section classification: official - observed_at: "2026-07-29T15:06:51Z" + observed_at: "2026-09-30T00:00:00Z" diff --git a/guides/intercom/research.md b/guides/intercom/research.md index 8b2296f..dbb471b 100644 --- a/guides/intercom/research.md +++ b/guides/intercom/research.md @@ -33,11 +33,13 @@ is rendered. - **Authentication Option documented by this Guide:** OAuth with a pre-registered Intercom Developer Hub app. The Speakeasy AI Control Plane receives the app's **Client ID** and **Client secret** and uses: - - Issuer URL: `https://mcp.intercom.com` - - Authorization endpoint: `https://app.intercom.com/oauth` + - Issuer URL: US `https://mcp.intercom.com`; EU `https://mcp.eu.intercom.com` + - Authorization endpoint: US `https://app.intercom.com/oauth`; EU + `https://app.eu.intercom.com/oauth` - Token endpoint: `https://api.intercom.io/auth/eagle/token` - The issuer and endpoint combination was validated by the operator for the - manual attachment flow. Intercom's OAuth guide independently documents the + The US issuer and endpoint combination was validated by the operator for the + manual flow; the EU values come from Intercom's documentation and the EU + issuer metadata (2026-09-30) and are not operator-validated. Intercom's OAuth guide independently documents the US authorization endpoint and Eagle token endpoint. - **Why manual registration is recommended:** Intercom's live MCP authorization-server metadata advertises a DCR endpoint, but the operator @@ -90,8 +92,8 @@ Information** page. | Client ID | Intercom Developer Hub app, **Basic Information** ({#copy-client-credentials}) | | Client Secret (optional) | Intercom Developer Hub app, **Basic Information** ({#copy-client-credentials}) | | Redirect URI registered with Intercom | `{{ gram.oauth.callback_url }}` in the app's **Redirect URLs** ({#configure-oauth}) | -| Issuer URL | Operator-validated constant `https://mcp.intercom.com` | -| Authorization endpoint | Intercom-documented `https://app.intercom.com/oauth` | +| Issuer URL | US `https://mcp.intercom.com` (operator-validated); EU `https://mcp.eu.intercom.com` | +| Authorization endpoint | Intercom-documented US `https://app.intercom.com/oauth`; EU `https://app.eu.intercom.com/oauth` | | Token endpoint | Intercom-documented `https://api.intercom.io/auth/eagle/token` | Intercom's OAuth guide calls the generated values `client_id` and @@ -170,65 +172,93 @@ which MCP Server URL the reader adds later. ## Speakeasy setup -Canonical source: `doctrine/speakeasy-setup.md`, observed -`2026-07-29T15:06:51Z`. +Canonical source: `doctrine/speakeasy-setup.md` (gram `main` commit +`68b3f78`), read 2026-09-30. Per-guide values: -- Remote URL: the US or EU URL selected in - {#identify-workspace-region} -- Transport: `streamable-http` +- Remote URL: the US or EU URL selected in {#identify-workspace-region}. - Add-server path: Custom remote only because both URLs are region-specific - (`tenanted: true`); ignore catalog presence -- Authentication Option: OAuth with a pre-registered client -- Client ID and Client Secret: produced in - {#copy-client-credentials} -- Redirect URI: registered in {#configure-oauth} -- Issuer URL: `https://mcp.intercom.com` -- Authorization endpoint: `https://app.intercom.com/oauth` -- Token endpoint: `https://api.intercom.io/auth/eagle/token` -- Scopes: chosen in Intercom; no Speakeasy scope override -- Further reading: - `https://developers.intercom.com/docs/guides/mcp` + (`tenanted: true`); ignore catalog presence. Render **Hosted remotely**. +- Authentication Option: OAuth with a pre-registered client → **User + Identity**. **Client ID** and **Client secret** come from + {#copy-client-credentials}; the callback is registered in {#configure-oauth}. +- Probe outcome (2026-09-30, both regions): `initialize` POST with + `Accept: application/json, text/event-stream` returns 401 with + `WWW-Authenticate: Bearer realm="OAuth", error="invalid_token"` and **no** + `resource_metadata`. `/.well-known/oauth-protected-resource` (and the + `/mcp`-suffixed form) returns 404. The create form therefore preselects + **No Identity**; the reader must select **User Identity**. With no PRM, + creation cannot configure identity, so the server is kept **Disabled** and + the result points to **Settings > Identity**. +- PRM issuer: none (no PRM). The picker cannot discover or create a provider, + so render the custom identity provider route. +- Issuer metadata (`/.well-known/oauth-authorization-server`, 2026-09-30): + US issuer `https://mcp.intercom.com`, EU issuer `https://mcp.eu.intercom.com`; + each advertises its own `/authorize`, `/token`, and `/register` + (`registration_endpoint`, so DCR is advertised), no + `client_id_metadata_document_supported` (no CIMD), auth methods + `client_secret_basic`, `client_secret_post`, `none`. Operator validation + found DCR fails unless Intercom allowlists the callback, so automatic + registration is not used. +- Custom provider values (New Remote Identity Provider): + - **Issuer URL**: US `https://mcp.intercom.com`; EU + `https://mcp.eu.intercom.com` (from each region's issuer metadata). + - **Authorization Endpoint**: US `https://app.intercom.com/oauth`; EU + `https://app.eu.intercom.com/oauth` (Intercom's Setting up OAuth page, + re-read 2026-09-30). + - **Token Endpoint**: `https://api.intercom.io/auth/eagle/token` for every + region (Intercom's Setting up OAuth page shows one token endpoint). + - Do not click **Discover**: it fills the MCP issuer's `/authorize` and + `/token`, which the operator found do not work with the manual app. + - The US values were operator-validated; the EU values are documented but + not operator-validated. +- Registration choice: a **Manual** client created under the custom provider's + **Add Client** (**Client Type** **Manual**, **Client ID**, **Client Secret + (optional)** (required by Intercom), **Scope (override)** empty, confirm + **Redirect URI**), then **Existing client** on the server's **Settings > + Identity**. Auto-Configure (DCR) is advertised but fails. +- Scope string: none. Permissions are chosen on the Intercom app, and there is + no PRM scope list for a blank value to expand to, so **Scope (override)** + stays empty. +- Server Availability: finish with **Settings > Danger Zone > Server + Availability** → **Enable MCP server**. +- Further reading: `https://developers.intercom.com/docs/guides/mcp`. ### Add the server in Speakeasy {#add-server-in-speakeasy} -In the Speakeasy AI Control Plane sidebar, under **Connect**, select -**Sources**, then click **Add Source**. +In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select +**MCP**, then click **Add new** to open **Add MCP server**. Choose **Hosted +remotely**. On **New remote MCP server**, paste the regional remote URL +selected in {#identify-workspace-region} into **MCP server URL**, leave **User +session issuer** at its default, and click **Verify connectivity**. Under +**Identity**, change the preselected **No Identity** to **User Identity**, +leave **Guardrails** off, and click **Save**. The server is kept **Disabled**; +setup continues in **Settings > Identity**. -Choose **Custom remote server**. On **Add a custom remote MCP server**, paste -the regional remote URL selected in {#identify-workspace-region} into -**Remote MCP server URL**, then click **Add server**. This creates the hosted -MCP server and opens its **Overview** page. - -Screenshot note: capture the **Add Source** menu or the **Add a custom remote -MCP server** page with the matching Intercom remote URL. +Screenshot note: capture **New remote MCP server** after verification with the +Intercom remote URL and **User Identity** selected. ### Connect your credentials {#connect-speakeasy-credentials} -From the server's **Overview**, open **Settings**. Under **Authentication**, -click **Configure Manually**. In **Attach Remote Identity Provider**: - -1. Set **Client Type** to **Manual**. -2. Enter `https://mcp.intercom.com` as **Issuer URL**. -3. Under **Endpoints**, set the authorization endpoint to - `https://app.intercom.com/oauth` and the token endpoint to - `https://api.intercom.io/auth/eagle/token`. Do not use the MCP issuer's - discovered `/authorize` and `/token` endpoints for this manual app. -4. Paste the **Client ID** and **Client Secret (optional)** from - {#copy-client-credentials}. -5. Leave **Scope (override)** and **Audience (optional)** empty because - permissions were selected in Intercom. -6. Confirm that the sheet's **Redirect URI** is - `https://app.getgram.ai/mcp/remote_login_callback`, matching the value - registered through `{{ gram.oauth.callback_url }}` in {#configure-oauth}. -7. Click **Attach Identity Provider**. - -Screenshot note: capture **Attach Remote Identity Provider** with **Client -Type** set to **Manual** and the issuer, authorization, and token endpoint -fields visible. Fully redact the Client ID and Client Secret. - -When a client first needs Intercom access, complete Intercom's browser +In **Settings > Identity**, select **User Identity**, open **Choose an identity +provider**, and click **Create a custom identity provider** (opens **Remote +Identity Providers**). Click **New Remote Identity Provider**, enter the +region's **Issuer URL**, **Authorization Endpoint**, and **Token Endpoint** +above, keep the derived **Slug**, and click **Create**. On the provider, click +**Add Client**: **Client Type** **Manual**, **Client ID**, **Client Secret +(optional)**, leave **Scope (override)** empty, confirm **Redirect URI** +matches `{{ gram.oauth.callback_url }}` registered in {#configure-oauth}, and +click **Create**. Back in the server's **Settings > Identity**, select that +provider, choose **Existing client**, pick the client under **Client**, and +click **Save** (confirm with **Save changes** when asked). Then turn on +**Enable MCP server** under **Settings > Danger Zone > Server Availability**. + +Screenshot note: capture **New Remote Identity Provider** with the Intercom +issuer and endpoints, and **Settings > Identity** with the provider and +**Existing client** selected. Fully redact the Client ID and Client Secret. + +When a person first needs Intercom access, they complete Intercom's browser authorization prompts with the intended workspace account. Intercom says the screen presents the requested permissions but does not publish the current button labels. @@ -250,6 +280,11 @@ https://developers.intercom.com/docs/guides/mcp." - **OAuth page save control:** Intercom's public OAuth guide names and shows **Use OAuth**, **Redirect URLs**, **Add redirect URL**, and the permission checkboxes, but does not name the control that persists changes. +- **EU token endpoint:** Intercom documents one token endpoint, + `https://api.intercom.io/auth/eagle/token`, for all regions. A regional host + `https://api.eu.intercom.io/auth/eagle/token` also answers (404 "Client not + found" to a dummy client on 2026-09-30). The EU path has not been + operator-validated; confirm which token host an EU app accepts. - **DCR allowlisting process:** operator validation established that DCR needs callback allowlisting, but Intercom publishes no request path, eligibility rule, or turnaround time. Manual OAuth remains the recommended path. @@ -277,7 +312,7 @@ Sources drawn from: (MCP)") — observed `2026-07-29T15:06:51Z`. Backs US/EU URLs and availability, Australian exclusion, Streamable HTTP, OAuth and Bearer alternatives, the browser authorization behavior, and the public MCP page's broader - **Read and write articles** recommendation. + **Read and write articles** recommendation. Re-read `2026-09-30`. - `https://developers.intercom.com/docs/build-an-integration/getting-started` and its `.md` representation — observed `2026-07-29T15:06:51Z`. Back the Developer Hub URL and **Your Apps**, **New App**, **Create app**, app-name, @@ -300,13 +335,17 @@ Sources drawn from: workspace-host mapping and wrong-region sign-in recovery. - `https://app.intercom.com/admins/sign_in` — observed `2026-07-29T15:06:51Z`. Backs the current region-selector labels. -- `https://mcp.intercom.com/.well-known/oauth-authorization-server` — - observed `2026-07-29T15:06:51Z`. Confirms that the MCP issuer advertises DCR - and separate `/authorize` and `/token` endpoints. +- `https://mcp.intercom.com/.well-known/oauth-authorization-server` and + `https://mcp.eu.intercom.com/.well-known/oauth-authorization-server` — + observed `2026-09-30`. Confirm that each regional MCP issuer advertises DCR + and separate `/authorize` and `/token` endpoints, and no CIMD. +- `https://mcp.intercom.com/mcp` and `https://mcp.eu.intercom.com/mcp` probes + and their `/.well-known/oauth-protected-resource` — observed `2026-09-30`. + 401 without `resource_metadata`; PRM 404. - Operator validation recorded for this run — observed `2026-07-29T15:06:51Z`. Backs DCR callback-allowlist failure, the recommended manual OAuth path, callback URL, validated issuer/authorization/token values, and the least-privilege permission set. -- `doctrine/speakeasy-setup.md` — observed `2026-07-29T15:06:51Z`. Backs the +- `doctrine/speakeasy-setup.md` — observed `2026-09-30`. Backs the canonical Speakeasy skeleton, fixed anchors, exact common labels, and tenanted Custom-remote path selection. diff --git a/guides/intercom/speakeasy.md b/guides/intercom/speakeasy.md index ce91917..0c0ace5 100644 --- a/guides/intercom/speakeasy.md +++ b/guides/intercom/speakeasy.md @@ -3,54 +3,67 @@ ### Add the server in Speakeasy {#add-server-in-speakeasy} 1. In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select **MCP**. -2. Click **Add new** to open the **Add MCP server** page. +2. Click **Add new** to open **Add MCP server**. 3. Choose **Hosted remotely**. 4. On **New remote MCP server**, paste the remote URL from [Identify the workspace region](external.md#identify-workspace-region) into **MCP server URL**. -5. Click **Verify connectivity**, then **Save**. +5. Leave **User session issuer** at its default. +6. Click **Verify connectivity**. +7. Under **Identity**, select **User Identity**. The page preselects **No Identity** for this server, so change it. +8. If **Guardrails** appears, leave it off. +9. Click **Save**. -This creates the hosted MCP server and opens its **Overview** page. +Speakeasy keeps the new server **Disabled** and says to finish setup in **Settings > Identity**. This is expected for Intercom; the next section finishes it. - + ### Connect your credentials {#connect-speakeasy-credentials} -From the server's **Overview**, open **Settings**. +Intercom's server does not publish metadata the provider picker can use, so create the Intercom provider and its client first. Use the values for the region you recorded in [Identify the workspace region](external.md#identify-workspace-region). -Under **Authentication**, if unconfigured, select **Use Discovered** when available; otherwise select **Configure Manually**. If configured but no provider is attached, use **Connected services > Add provider**. If the intended provider is already attached, use its existing controls and skip the provider/client creation and attachment steps below; do not add a duplicate. +1. Open the server's **Settings** and find the **Identity** section. +2. Select **User Identity**. +3. Open **Choose an identity provider** and click **Create a custom identity provider**. This opens **Remote Identity Providers**. +4. Click **New Remote Identity Provider**. +5. In **Issuer URL**, enter `https://mcp.intercom.com` for a US workspace or `https://mcp.eu.intercom.com` for an EU workspace. -#### Select the identity provider +6. Under **Endpoints**, in **Authorization Endpoint**, enter the value for your region. -In **Attach Remote Identity Provider**, **Identity Provider** defaults to **Select existing** when project issuers are available. Select the matching provider and skip the new-provider fields below. Otherwise choose **Add new** (or use the new-provider form shown when none exist). - -For a new provider only, confirm **Issuer URL**, the auto-derived **Slug**, and **Endpoints**. Discovery runs automatically for a seeded issuer; after typing or changing the URL, select **Discover** only if offered. - -1. Enter `https://mcp.intercom.com` as **Issuer URL**. -1. Under **Endpoints**, set the authorization endpoint to `https://app.intercom.com/oauth`. -1. Set the token endpoint to this URL: + US workspace: + ```text + https://app.intercom.com/oauth ``` - https://api.intercom.io/auth/eagle/token - ``` - -#### Select the session client -Under **Session Client**, choose **Select existing** only for a client whose saved credentials, scopes, and audience match the requirements below; otherwise choose **Add new**. When reusing a matching client, skip directly to **Verify the callback and attach** below. Do not create credentials or register the client again. Otherwise choose **Add new** (or use the new-client form shown when no clients exist) and complete these new-client-only steps: + EU workspace: -1. In **Attach Remote Identity Provider**, set **Client Type** to **Manual**. -1. Paste the **Client ID** from [Copy the client credentials](external.md#copy-client-credentials). -1. Paste the **Client Secret (optional)** from [Copy the client credentials](external.md#copy-client-credentials). -1. Leave **Scope (override)** empty. -1. Leave **Audience (optional)** empty. - -#### Verify the callback and attach + ```text + https://app.eu.intercom.com/oauth + ``` -1. Confirm that the callback URL registered with the provider is `{{ gram.oauth.callback_url }}`. For a new manual client, also compare it with the sheet's displayed **Redirect URI**. The existing-client selection does not display that field; check the registered callback in the provider's app settings instead. -2. Click **Attach Identity Provider**. + Do not click **Discover**: it fills in Intercom's MCP `/authorize` and `/token` endpoints, which do not work with the app you created. -For the provider-side callback setting, see [Configure OAuth](external.md#configure-oauth). +7. In **Token Endpoint**, enter this value for either region: - + ```text + https://api.intercom.io/auth/eagle/token + ``` -When a client initiates Intercom access, complete the on-screen browser prompts with the intended workspace account. +8. Keep the derived **Slug** and click **Create**. +9. On the new provider, click **Add Client**. +10. Set **Client Type** to **Manual**. +11. Paste the **Client ID** from [Copy the client credentials](external.md#copy-client-credentials) into **Client ID**. +12. Paste the **Client secret** from [Copy the client credentials](external.md#copy-client-credentials) into **Client Secret (optional)**. Intercom requires the secret. +13. Leave **Scope (override)** empty. The permissions you selected in [Configure OAuth](external.md#configure-oauth) apply. +14. Confirm that the displayed **Redirect URI** matches the callback you registered in [Configure OAuth](external.md#configure-oauth), then click **Create**. +15. Return to the server's **Settings > Identity** and select **User Identity**. +16. In **Choose an identity provider**, select the Intercom provider you created. +17. Choose **Existing client** and pick the new client under **Client**. +18. Click **Save**. If Speakeasy asks you to confirm, click **Save changes**. +19. Open **Settings > Danger Zone > Server Availability**. +20. Turn on **Enable MCP server** so the switch shows **Enabled**. + +When a person first uses the server, Intercom's browser authorization prompt appears. Complete it with an account in the intended workspace. + + This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Intercom's MCP documentation](https://developers.intercom.com/docs/guides/mcp). diff --git a/guides/netsuite/external.md b/guides/netsuite/external.md index 357414a..818edce 100644 --- a/guides/netsuite/external.md +++ b/guides/netsuite/external.md @@ -58,7 +58,7 @@ Sign in to the NetSuite application as an Administrator or delegated administrat ``` For a sandbox or Release Preview account, replace underscores with hyphens and uppercase letters with lowercase letters. For example, `123456_SB1` becomes `123456-sb1`. -4. Keep the completed endpoint for **Remote MCP server URL** in the Speakeasy AI Control Plane. +4. Keep the completed endpoint for **MCP server URL** in the Speakeasy AI Control Plane. diff --git a/guides/netsuite/meta.yaml b/guides/netsuite/meta.yaml index d4bf84e..a26549e 100644 --- a/guides/netsuite/meta.yaml +++ b/guides/netsuite/meta.yaml @@ -39,7 +39,7 @@ remotes: locator: https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_0714082142.html name: Connect to the NetSuite AI Connector Service classification: official - observed_at: "2026-08-07T22:23:30Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation locator: https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/article_0902023450.html name: Installing the MCP Standard Tools SuiteApp @@ -50,7 +50,7 @@ provenance: locator: https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/article_4160616848.html name: NetSuite AI Connector Service FAQ classification: official - observed_at: "2026-08-07T22:23:30Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation locator: https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/article_3200541651.html name: Get Started with the NetSuite AI Connector Service @@ -75,7 +75,7 @@ provenance: locator: https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_0714082142.html name: Connect to the NetSuite AI Connector Service classification: official - observed_at: "2026-08-07T22:23:30Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation locator: https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_157771733782.html name: Create Integration Records for Applications to Use OAuth 2.0 @@ -91,11 +91,26 @@ provenance: name: URLs for Account-Specific Domains classification: official observed_at: "2026-08-07T22:23:30Z" + - source: provider-documentation + locator: https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_158081944642.html + name: Step One GET Request to the Authorization Endpoint + classification: official + observed_at: "2026-09-30T00:00:00Z" + - source: provider-documentation + locator: https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_158081952044.html + name: Step Two POST Request to the Token Endpoint + classification: official + observed_at: "2026-09-30T00:00:00Z" + - source: provider-documentation + locator: https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_160855299656.html + name: Configure NetSuite as OIDC Provider + classification: official + observed_at: "2026-09-30T00:00:00Z" - source: speakeasy-doctrine locator: doctrine/speakeasy-setup.md name: Speakeasy setup canonical file classification: official - observed_at: "2026-08-07T22:23:30Z" + observed_at: "2026-09-30T00:00:00Z" - source: operator-validation locator: draft-guide operator notes for netsuite status: Bundle ID 522506; public-client PKCE path; scoped non-admin role; Attach Remote Identity Provider shows Redirect URI with a copy button before credential entry; Speakeasy MCP Catalog result overridden-tenanted for query netsuite; tenanted remote requires Custom remote path diff --git a/guides/netsuite/research.md b/guides/netsuite/research.md index fad2a2e..697f456 100644 --- a/guides/netsuite/research.md +++ b/guides/netsuite/research.md @@ -23,7 +23,7 @@ researched_at: 2026-08-07T22:23:30Z ## Credential flow -An administrator enables the required SuiteCloud features, installs MCP Standard Tools, prepares a least-privilege non-Administrator role, finds the account ID, and manually creates an OAuth 2.0 integration record. The integration record is a public client: NetSuite issues a **Client ID**, while the Speakeasy AI Control Plane does not need the displayed client secret. Enter `{{ gram.oauth.callback_url }}` directly in NetSuite's **Redirect URI** field. Later, the Speakeasy **Attach Remote Identity Provider** sheet displays the resolved **Redirect URI** with a copy button before the credential-entry fields. Confirm that it matches the callback registered in NetSuite before entering the client ID. +An administrator enables the required SuiteCloud features, installs MCP Standard Tools, prepares a least-privilege non-Administrator role, finds the account ID, and manually creates an OAuth 2.0 integration record. The integration record is a public client: NetSuite issues a **Client ID**, while the Speakeasy AI Control Plane does not need the displayed client secret. Enter `{{ gram.oauth.callback_url }}` directly in NetSuite's **Redirect URI** field. Later, the Speakeasy **Add Client** form on the custom identity provider displays the resolved **Redirect URI**; confirm that it matches the callback registered in NetSuite. The MCP endpoint embeds the account ID. Oracle's MCP connection page says an Administrator can provide this account-specific URL. Oracle's account-domain page places account-specific URLs at **Setup > Company > Company Information > Company URLs**, but does not identify an MCP-specific row there. For this documented endpoint, copy the account ID shown in NetSuite and substitute it exactly as the MCP page directs; note that sandbox and Release Preview account IDs are normalized in hostnames (underscores become hyphens and letters become lowercase). @@ -71,7 +71,7 @@ Start from the NetSuite application while signed in as an Administrator or an ap `https://.suitetalk.api.netsuite.com/services/mcp/v1/suiteapp/com.netsuite.mcpstandardtools` - Replace `` with the account's domain-form ID. For sandbox and Release Preview IDs, convert underscores to hyphens and uppercase letters to lowercase (for example, the documented account ID form `123456_SB1` becomes host component `123456-sb1`). Do not omit the `/suiteapp/com.netsuite.mcpstandardtools` suffix. -- Keep the completed URL for **Remote MCP server URL** in the Speakeasy AI Control Plane. +- Keep the completed URL for **MCP server URL** in the Speakeasy AI Control Plane. - Screenshot note: capture **Company Information > Company URLs** with the account-specific SuiteTalk domain visible; redact unrelated URLs and account data. The final MCP path is assembled from Oracle's documented fixed suffix rather than copied from a named MCP row. ### Create the OAuth integration {#create-oauth-integration} @@ -96,26 +96,99 @@ Start from the NetSuite application while signed in as an Administrator or an ap ## Speakeasy setup -The Speakeasy MCP Catalog result for query `netsuite` was **overridden-tenanted**. Independently, the account-specific remote has `tenanted: true`, which requires rendering only the Custom remote server path. +Canonical source: `doctrine/speakeasy-setup.md` (gram `main` commit +`68b3f78`), read 2026-09-30. The Speakeasy MCP Catalog result for query +`netsuite` was **overridden-tenanted**. Independently, the account-specific +remote has `tenanted: true`, which requires rendering only the **Hosted +remotely** path. + +Per-guide values: + +- Remote URL: + `https://.suitetalk.api.netsuite.com/services/mcp/v1/suiteapp/com.netsuite.mcpstandardtools`, + formed in {#record-account-mcp-url}. +- Authentication Option: `oauth-public-client` → **User Identity**. OAuth 2.0 + Authorization Code Grant with PKCE, manual public client, **Client ID** only + (from {#create-oauth-integration}); no client secret. +- Probe outcome: not observed. Account-specific hosts resolve only for real + accounts (sample IDs did not resolve in DNS on 2026-09-30), and no account + was available. Oracle's MCP pages do not document protected-resource + metadata. Whether the create form preselects **User Identity** is unknown, + so the guide tells the reader to select it. +- PRM issuer: unknown (see probe). Treat discovery as unavailable and render + the custom identity provider route. +- CIMD/DCR: unknown for the MCP resource. NetSuite integration records carry a + **Dynamic Client Registration** checkbox and Oracle says an integration + record is created automatically on first connection from Claude, which + suggests DCR exists; this guide keeps DCR cleared and uses the manual + public client. +- Custom provider values (New Remote Identity Provider), `` in + domain form: + - **Issuer URL**: `https://.suitetalk.api.netsuite.com`. Oracle + documents the account's OIDC metadata at + `https://.suitetalk.api.netsuite.com/.well-known/openid-configuration` + (NetSuite as OIDC Provider), which places the issuer on this host. The + exact issuer string was not observed. + - **Authorization Endpoint**: + `https://.app.netsuite.com/app/login/oauth2/authorize.nl` + (Oracle, Step One GET Request to the Authorization Endpoint). + - **Token Endpoint**: + `https://.suitetalk.api.netsuite.com/services/rest/auth/oauth2/v1/token` + (Oracle, Step Two POST Request to the Token Endpoint; public clients send + `client_id` in the body with PKCE and no secret). + - **Discover** is not used: the OIDC metadata exists only when the NetSuite + as OIDC Provider feature is enabled. +- Registration choice: a **Manual** client created under the custom + provider's **Add Client** (**Client Type** **Manual**, **Client ID**, + **Client Secret (optional)** left empty, **Scope (override)** `mcp`, + confirm **Redirect URI**), then **Existing client** on the server's + **Settings > Identity**. +- Scope string: `mcp`. Oracle lists `mcp` as the scope value for the NetSuite + AI Connector Service and says it can only be used on its own (scopes are + otherwise space-separated). There is no PRM scope list to fall back on, so + the scope must be entered. +- Server Availability: when creation left the server **Disabled**, finish + with **Settings > Danger Zone > Server Availability** → **Enable MCP + server**. +- Further reading: + `https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/article_4160616848.html` ### Add the server in Speakeasy {#add-server-in-speakeasy} -In the Speakeasy AI Control Plane sidebar, under **Connect**, select **Sources**, then click **Add Source**. Choose **Custom remote server**. On **Add a custom remote MCP server**, paste the account-specific URL produced in [Record the account-specific MCP URL](#record-account-mcp-url) into **Remote MCP server URL**, then click **Add server**. This creates the hosted MCP server and opens its **Overview** page. +In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select +**MCP**, then click **Add new** to open **Add MCP server**. Choose **Hosted +remotely**. On **New remote MCP server**, paste the account-specific URL from +{#record-account-mcp-url} into **MCP server URL**, leave **User session +issuer** at its default, click **Verify connectivity**, select **User +Identity**, leave **Guardrails** off, and click **Save**. -- Per-guide remote: `https://.suitetalk.api.netsuite.com/services/mcp/v1/suiteapp/com.netsuite.mcpstandardtools` -- Transport: `streamable-http`; the form's **Transport** is read-only. -- Screenshot note: capture the **Add Source** menu open on the **Sources** page, or the provider's catalog entry. +- Screenshot note: capture **New remote MCP server** after verification with + the NetSuite endpoint (account ID redacted) and **User Identity** selected. ### Connect your credentials {#connect-speakeasy-credentials} -From the server's **Overview**, open **Settings**. Under **Authentication**, click **Configure Manually**. In **Attach Remote Identity Provider**, set **Client Type** to **Manual**. Before entering credentials, use the displayed **Redirect URI** and its copy button to confirm that the value matches the `{{ gram.oauth.callback_url }}` value registered in [Create the OAuth integration](#create-oauth-integration). Paste the **Client ID** produced by that step. Leave **Client Secret (optional)** empty because the NetSuite integration is a public client, then click **Attach Identity Provider**. - -The selected Authentication Option is `oauth-public-client`: OAuth 2.0 Authorization Code Grant with PKCE, manual client registration, Client ID only. The provider documentation reviewed does not state whether protected-resource metadata enables **Use Discovered**, so use **Configure Manually**. - -When a client first requests access, complete NetSuite's browser sign-in with the intended scoped non-Administrator role, review the allow/deny prompt, and allow access only after reviewing the organization's data-sharing controls. - -- Screenshot note: capture **Attach Remote Identity Provider** before credential entry, with **Client Type: Manual**, the **Redirect URI** and its copy button, **Client ID**, and the empty optional secret visible; redact the URI and any entered ID. -- Further reading: https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/article_4160616848.html +In **Settings > Identity**, select **User Identity**, open **Choose an +identity provider**, and click **Create a custom identity provider** (opens +**Remote Identity Providers**). Click **New Remote Identity Provider**, enter +the **Issuer URL**, **Authorization Endpoint**, and **Token Endpoint** above, +keep the derived **Slug**, and click **Create**. On the provider, click **Add +Client**: **Client Type** **Manual**, the **Client ID** from +{#create-oauth-integration}, leave **Client Secret (optional)** empty, enter +`mcp` in **Scope (override)**, confirm **Redirect URI** matches +`{{ gram.oauth.callback_url }}`, and click **Create**. Back in the server's +**Settings > Identity**, select that provider, choose **Existing client**, +pick the client under **Client**, and click **Save** (confirm with **Save +changes** when asked). Then turn on **Enable MCP server** under **Settings > +Danger Zone > Server Availability**. + +When a person first requests access, they complete NetSuite's browser sign-in +with the intended scoped non-Administrator role, review the allow/deny +prompt, and allow access only after reviewing the organization's +data-sharing controls. + +- Screenshot note: capture **New Remote Identity Provider** with the NetSuite + issuer and endpoints (account ID redacted), and **Settings > Identity** with + the provider and **Existing client** selected. The Writer should close with: This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [NetSuite's MCP documentation](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/article_4160616848.html). @@ -124,7 +197,7 @@ The Writer should close with: This guide covers setup only. For anything beyond - Oracle's current public Marketplace installation page names **MCP Standard Tools** but does not expose Bundle ID **522506** in its text. The ID comes from operator validation; confirm it against the authenticated SuiteApp Marketplace listing during screenshot capture. - Oracle documents the account-ID endpoint template and the **Company URLs** page, but does not name a dedicated MCP URL field or give an exact text label for the account ID on that page. The Guide therefore uses the documented account ID and hostname normalization rather than claiming a copyable MCP row. - Oracle does not publish, on the reviewed MCP setup and SuiteApp installation pages, the exact MCP Standard Tools folder path in the File Cabinet or the role-form control used to grant folder access. If File Cabinet restrictions are in use, obtain those account-specific details from the NetSuite owner. -- Oracle does not publish, on the reviewed MCP setup pages, whether this MCP endpoint exposes protected-resource metadata usable by Speakeasy discovery. The Speakeasy path therefore uses manual configuration. +- Oracle does not publish, on the reviewed MCP setup pages, whether this MCP endpoint exposes protected-resource metadata usable by Speakeasy discovery, and no account was available to probe it. The Speakeasy path therefore uses a custom identity provider. An operator with a NetSuite account should probe the remote (401 with or without `resource_metadata`), record the PRM issuer and whether it advertises DCR or CIMD, and confirm the **Issuer URL** value. If the PRM advertises working DCR, creation may auto-register its own client, and the guide should be re-rendered for that path. ## Provenance @@ -136,14 +209,17 @@ The Writer should close with: This guide covers setup only. For anything beyond ### Sources used -- https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/article_4160616848.html — observed 2026-08-07T22:23:30Z; official NetSuite AI Connector FAQ. Backs protocol version, streamable HTTP, OAuth authorization-code PKCE, endpoint forms and `/all` warning, required features and role permissions, non-Administrator restriction, no-cost statement, integration-record properties, and troubleshooting facts. +- https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/article_4160616848.html — observed 2026-08-07T22:23:30Z, re-read 2026-09-30; official NetSuite AI Connector FAQ. Backs protocol version, streamable HTTP, OAuth authorization-code PKCE, endpoint forms and `/all` warning, required features and role permissions, non-Administrator restriction, no-cost statement, integration-record properties, and troubleshooting facts. - https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/article_3200541651.html — observed 2026-08-07T22:23:30Z; official getting-started hub. Backs service identity, MCP Standard Tools availability, and compliance warning. - https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_0714080625.html — observed 2026-08-07T22:23:30Z; official required features and permissions page. Backs exact feature path and labels, role path/subtab, exact permission labels, Administrator prohibition, and REST Web Services requirements. - https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/article_143403258.html — observed 2026-08-07T22:23:30Z; official MCP Standard Tools overview. Backs role-based data/action boundaries, create/update implications, and separate least-privilege role recommendation. - https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/article_0902023450.html — observed 2026-08-07T22:23:30Z; official SuiteApp installation page. Backs exact Marketplace navigation, controls, managed-update behavior, endpoint suffix, and File Cabinet access caveat. -- https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_0714082142.html — observed 2026-08-07T22:23:30Z; official connection and namespacing page. Backs account-specific server URL, Standard Tools application ID, `/all` distinction, integration-record requirements, first-connection consent behavior, and role selection. +- https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_0714082142.html — observed 2026-08-07T22:23:30Z, re-read 2026-09-30 (adds that an integration record is created automatically on first connection from Claude); official connection and namespacing page. Backs account-specific server URL, Standard Tools application ID, `/all` distinction, integration-record requirements, first-connection consent behavior, and role selection. - https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_157771733782.html — observed 2026-08-07T22:23:30Z; official OAuth integration-record task. Backs navigation, field labels, public-client behavior, redirect rules, NetSuite AI Connector Service scope exclusivity, consent-policy choices, create permission, save action, one-time credential display, and the **Edit** > **Reset Credentials** > **OK** recovery path. - https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_N895277.html — observed 2026-08-07T22:23:30Z; official employee-access task. Backs the employee record's **Access > Roles** path and assigning a role with **Role**, **Add**, and **Save**. - https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_1498251763.html — observed 2026-08-07T22:23:30Z; official account-specific domains page. Backs **Company Information > Company URLs**, account-specific URL behavior, and sandbox/Release Preview hostname normalization. -- `doctrine/speakeasy-setup.md` — observed 2026-08-07T22:23:30Z; canonical Speakeasy AI Control Plane add-server and manual OAuth labels, transitions, fixed anchors, and closing pointer. -- Draft-guide operator notes for `netsuite` — observed 2026-08-07T22:23:30Z; backs Bundle ID 522506, public-client PKCE path, scoped non-admin role decision, the verified **Attach Remote Identity Provider** layout (**Redirect URI** with a copy button before credential entry), matching Speakeasy callback requirement, and Speakeasy MCP Catalog result `overridden-tenanted` for query `netsuite`. +- https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_158081944642.html — observed 2026-09-30; official authorization-endpoint step. Backs the authorization endpoint, the `mcp` scope value and its must-be-alone rule, space-separated scopes, and required S256 PKCE. +- https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_158081952044.html — observed 2026-09-30; official token-endpoint step. Backs the token endpoint and public-client authentication without a secret. +- https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_160855299656.html — observed 2026-09-30; official NetSuite as OIDC Provider page. Backs the account-specific metadata URL host used for **Issuer URL**, and that the metadata requires that feature. +- `doctrine/speakeasy-setup.md` — observed 2026-09-30; canonical Speakeasy AI Control Plane add-server, Identity section, custom identity provider labels, transitions, fixed anchors, and closing pointer. +- Draft-guide operator notes for `netsuite` — observed 2026-08-07T22:23:30Z; backs Bundle ID 522506, public-client PKCE path, scoped non-admin role decision, the then-verified **Attach Remote Identity Provider** layout (a retired surface; no longer rendered), matching Speakeasy callback requirement, and Speakeasy MCP Catalog result `overridden-tenanted` for query `netsuite`. diff --git a/guides/netsuite/speakeasy.md b/guides/netsuite/speakeasy.md index a94825d..e063804 100644 --- a/guides/netsuite/speakeasy.md +++ b/guides/netsuite/speakeasy.md @@ -3,43 +3,61 @@ ### Add the server in Speakeasy {#add-server-in-speakeasy} 1. In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select **MCP**. -2. Click **Add new** to open the **Add MCP server** page. +2. Click **Add new** to open **Add MCP server**. 3. Choose **Hosted remotely**. -4. On **New remote MCP server**, paste the account-specific endpoint you formed in [Record the account-specific MCP URL](external.md#record-account-mcp-url) into **MCP server URL**. **Transport** is read-only. -5. Click **Verify connectivity**, then **Save**. This creates the hosted MCP server and opens its **Overview** page. +4. On **New remote MCP server**, paste the account-specific endpoint you formed in [Record the account-specific MCP URL](external.md#record-account-mcp-url) into **MCP server URL**. +5. Leave **User session issuer** at its default. +6. Click **Verify connectivity**. +7. Under **Identity**, select **User Identity** if it is not already selected. +8. If **Guardrails** appears, leave it off. +9. Click **Save**. - +If Speakeasy keeps the new server **Disabled** and says to finish setup in **Settings > Identity**, that is expected; the next section finishes it. -### Connect your credentials {#connect-speakeasy-credentials} - -From the server's **Overview**, open **Settings**. + -Under **Authentication**, if unconfigured, select **Use Discovered** when available; otherwise select **Configure Manually**. If configured but no provider is attached, use **Connected services > Add provider**. If the intended provider is already attached, use its existing controls and skip the provider/client creation and attachment steps below; do not add a duplicate. - -#### Select the identity provider +### Connect your credentials {#connect-speakeasy-credentials} -In **Attach Remote Identity Provider**, **Identity Provider** defaults to **Select existing** when project issuers are available. Select the matching provider and skip the new-provider fields below. Otherwise choose **Add new** (or use the new-provider form shown when none exist). +Create a NetSuite provider for your account, add the integration's client to it, then select it on the server. In each value below, replace `` with the same domain-form account ID you used in [Record the account-specific MCP URL](external.md#record-account-mcp-url). -For a new provider only, confirm **Issuer URL**, the auto-derived **Slug**, and **Endpoints**. Discovery runs automatically for a seeded issuer; after typing or changing the URL, select **Discover** only if offered. +1. Open the server's **Settings** and find the **Identity** section. +2. Select **User Identity**. +3. Open **Choose an identity provider** and click **Create a custom identity provider**. This opens **Remote Identity Providers**. +4. Click **New Remote Identity Provider**. +5. In **Issuer URL**, enter: -If no matching provider or complete discovered configuration is available, ask your administrator for the documented **Issuer URL** and authorization and token **Endpoints** before continuing. Do not infer them from the MCP server URL. + ```text + https://.suitetalk.api.netsuite.com + ``` -#### Select the session client +6. Under **Endpoints**, in **Authorization Endpoint**, enter: -Under **Session Client**, choose **Select existing** only for a client whose saved credentials, scopes, and audience match the requirements below; otherwise choose **Add new**. When reusing a matching client, skip directly to **Verify the callback and attach** below. Do not create credentials or register the client again. Otherwise choose **Add new** (or use the new-client form shown when no clients exist) and complete these new-client-only steps: + ```text + https://.app.netsuite.com/app/login/oauth2/authorize.nl + ``` -1. In **Attach Remote Identity Provider**, set **Client Type** to **Manual**. -1. Use the displayed **Redirect URI** and its copy button to confirm that the value matches the callback registered in [Create the OAuth integration](external.md#create-oauth-integration). -1. Paste the **Client ID** copied in that step. -1. Leave **Client Secret (optional)** empty. +7. In **Token Endpoint**, enter: -#### Verify the callback and attach + ```text + https://.suitetalk.api.netsuite.com/services/rest/auth/oauth2/v1/token + ``` -1. Confirm that the callback URL registered with the provider is `{{ gram.oauth.callback_url }}`. For a new manual client, also compare it with the sheet's displayed **Redirect URI**. The existing-client selection does not display that field; check the registered callback in the provider's app settings instead. -2. Click **Attach Identity Provider**. +8. Keep the derived **Slug** and click **Create**. +9. On the new provider, click **Add Client**. +10. Set **Client Type** to **Manual**. +11. Paste the **Client ID** from [Create the OAuth integration](external.md#create-oauth-integration) into **Client ID**. +12. Leave **Client Secret (optional)** empty. The integration is a public client. +13. In **Scope (override)**, enter `mcp`. NetSuite accepts `mcp` only on its own, so add no other scope. +14. Confirm that the displayed **Redirect URI** matches the callback you registered in [Create the OAuth integration](external.md#create-oauth-integration), then click **Create**. +15. Return to the server's **Settings > Identity** and select **User Identity**. +16. In **Choose an identity provider**, select the NetSuite provider you created. +17. Choose **Existing client** and pick the new client under **Client**. +18. Click **Save**. If Speakeasy asks you to confirm, click **Save changes**. +19. Open **Settings > Danger Zone > Server Availability**. +20. Turn on **Enable MCP server** so the switch shows **Enabled**. -When a client first requests access, sign in to NetSuite with the scoped non-Administrator role assigned in [Configure a scoped non-admin role](external.md#configure-scoped-role). Review the allow/deny prompt, then allow access only after reviewing your organization's data-sharing controls. +When a person first uses the server, NetSuite's browser sign-in appears. Sign in with the scoped non-Administrator role assigned in [Configure a scoped non-admin role](external.md#configure-scoped-role), review the allow/deny prompt, and allow access only after reviewing your organization's data-sharing controls. - + This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [NetSuite's MCP documentation](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/article_4160616848.html). diff --git a/guides/salesforce/external.md b/guides/salesforce/external.md index 031efb6..7521d6c 100644 --- a/guides/salesforce/external.md +++ b/guides/salesforce/external.md @@ -4,7 +4,7 @@ setup_version: 1 # Connect Salesforce to the Speakeasy AI Control Plane -Use Salesforce System Administrator credentials for an API-enabled production org where Hosted MCP Servers are available. Salesforce documents availability for Enterprise Edition and above. You need authority to install the Speakeasy application or create an **External Client App**, and enable Hosted MCP Servers. +Use Salesforce System Administrator credentials for an API-enabled production or sandbox org where Hosted MCP Servers are available. Salesforce documents availability for Enterprise Edition and above. You need authority to install the Speakeasy application or create an **External Client App**, and enable Hosted MCP Servers. Sign in to the Salesforce org you want to connect. Install or create the app in that same org. This guide does not cover scratch orgs. For a lower-edition org, confirm Hosted MCP availability in [Salesforce Setup](#open-salesforce-setup) before starting either path. @@ -41,7 +41,7 @@ After installation, **contact Speakeasy support to finish OAuth setup**. Install -## Create your own Salesforce app +## Create your own Salesforce app {#create-your-own-salesforce-app} Before creating the app, choose a server in the [endpoint reference](#endpoint-reference) and confirm its prerequisites. Then create an **External Client App** in the org you want to connect and enable that server. @@ -85,7 +85,7 @@ This path uses the app's **Consumer Key** without a client secret. Salesforce do Select **Create**. -The app can take up to 30 minutes to become operational. If attachment fails immediately, allow that window before retrying. +The app can take up to 30 minutes to become operational. If sign-in fails immediately, allow that window before retrying. @@ -116,64 +116,120 @@ Choose the least-privileged server that meets your team's needs using the endpoi If you created your own app, continue to [Speakeasy setup](speakeasy.md#add-server-in-speakeasy) with your selected URL and **Consumer Key**. If you installed Speakeasy's app, continue with Speakeasy support. -## Endpoint reference +## Endpoint reference {#endpoint-reference} -The following endpoints are for production orgs. Copy the URL for your selected server. +Copy the production or sandbox URL for your selected server. It must match the org where you created the app and enabled the server. **SObject Reads (sobject-reads)** Discovery, query, search, and relationship traversal; no record changes. +Production: + ``` https://api.salesforce.com/platform/mcp/v1/platform/sobject-reads ``` +Sandbox: + +``` +https://api.salesforce.com/platform/mcp/v1/sandbox/platform/sobject-reads +``` + **SObject Mutations (sobject-mutations)** Read, create, and update records; no deletes. +Production: + ``` https://api.salesforce.com/platform/mcp/v1/platform/sobject-mutations ``` +Sandbox: + +``` +https://api.salesforce.com/platform/mcp/v1/sandbox/platform/sobject-mutations +``` + **SObject Deletes (sobject-deletes)** Identify and delete records; no creates or updates. +Production: + ``` https://api.salesforce.com/platform/mcp/v1/platform/sobject-deletes ``` +Sandbox: + +``` +https://api.salesforce.com/platform/mcp/v1/sandbox/platform/sobject-deletes +``` + **SObject All (sobject-all)** Create, read, update, delete, query, and search records. +Production: + ``` https://api.salesforce.com/platform/mcp/v1/platform/sobject-all ``` +Sandbox: + +``` +https://api.salesforce.com/platform/mcp/v1/sandbox/platform/sobject-all +``` + **Data 360 (data360)** Query data and change customer-data configuration. Requires a Data 360 license, API v66.0+, and **Manage Data 360** for configuration or **View Data 360** for read-only operations. +Production: + ``` https://api.salesforce.com/platform/mcp/v1/data/data360 ``` +Sandbox: + +``` +https://api.salesforce.com/platform/mcp/v1/data/sandbox/data360 +``` + **Headless 360 (Beta) (platform/headless-360)** Broad Setup and platform operations, not read-only record access. Available starting July 2026 under Beta Services Terms. Requires API v67.0+, an External Client App with `mcp_api`, and an OAuth client. +Production: + ``` https://api.salesforce.com/platform/mcp/v1/platform/headless-360 ``` +Sandbox: + +``` +https://api.salesforce.com/platform/mcp/v1/sandbox/platform/headless-360 +``` + **Tableau Next (analytics/tableau-next)** Semantic-model and analytics access. Confirm the org has the required Tableau Next capabilities. +Production: + ``` https://api.salesforce.com/platform/mcp/v1/analytics/tableau-next ``` +Sandbox: + +``` +https://api.salesforce.com/platform/mcp/v1/sandbox/analytics/tableau-next +``` + Calls remain subject to the signed-in user's field-level security, object permissions, and sharing rules. If the connection fails with valid credentials, confirm that the selected server is enabled, the URL matches the selected server, and the org has API access. diff --git a/guides/salesforce/meta.yaml b/guides/salesforce/meta.yaml index 83a78ae..b1d4243 100644 --- a/guides/salesforce/meta.yaml +++ b/guides/salesforce/meta.yaml @@ -212,17 +212,17 @@ provenance: locator: https://api.salesforce.com/.well-known/oauth-protected-resource/platform/mcp/v1/platform/sobject-reads name: Salesforce SObject Reads protected-resource metadata classification: official - observed_at: "2026-08-06T23:23:14Z" + observed_at: "2026-09-30T21:25:35Z" - source: endpoint-observation locator: https://api.salesforce.com/platform/mcp/v1/platform/sobject-reads name: Salesforce SObject Reads production endpoint classification: official - observed_at: "2026-08-06T23:23:14Z" + observed_at: "2026-09-30T21:25:35Z" - source: repository-doctrine locator: doctrine/speakeasy-setup.md name: Speakeasy setup canonical section classification: official - observed_at: "2026-08-06T23:23:14Z" + observed_at: "2026-09-30T21:25:35Z" - source: provider-documentation locator: https://developer.salesforce.com/docs/platform/hosted-mcp-servers/guide/setup-overview.html name: Set Up Your Org @@ -277,3 +277,18 @@ provenance: locator: https://login.salesforce.com/packaging/installPackage.apexp?p0=04tdM000000cNGXQA2 name: Speakeasy Salesforce application installation and mandatory support OAuth handoff observed_at: "2026-09-17T16:15:46Z" + - source: endpoint-observation + locator: https://api.salesforce.com/.well-known/oauth-protected-resource/platform/mcp/v1/sandbox/platform/sobject-reads + name: Salesforce sandbox protected-resource metadata (issuer test.salesforce.com) + classification: official + observed_at: "2026-09-30T21:25:35Z" + - source: endpoint-observation + locator: https://login.salesforce.com/.well-known/openid-configuration + name: Salesforce production OpenID configuration (registration endpoint, no CIMD) + classification: official + observed_at: "2026-09-30T21:25:35Z" + - source: endpoint-observation + locator: https://login.salesforce.com/services/oauth2/register + name: Salesforce anonymous dynamic client registration (401 invalid_client) + classification: official + observed_at: "2026-09-30T21:25:35Z" diff --git a/guides/salesforce/research.md b/guides/salesforce/research.md index b1c36ab..07a8b0a 100644 --- a/guides/salesforce/research.md +++ b/guides/salesforce/research.md @@ -110,6 +110,16 @@ equivalent permission is needed to create an ECA (`setup-overview.html`); server activation requires an administrator (`activate-mcp-servers.html`). These are not grants of data access to every connecting user. +### Endpoint reference {#endpoint-reference} + +- Section heading in `external.md` (an H2 there) listing every server with + its literal production and sandbox URL from **Server facts** and the table + above. Render both URLs per server; the reader copies the one matching the + org where the app was created and the server enabled. Sandbox URLs + re-confirmed live 2026-09-30: each answers `401` and its PRM names + `https://test.salesforce.com` (except the Data 360 sandbox URL; see + Speakeasy setup). + ## Credential flow Who acts: a Salesforce System Administrator (or equivalent permissions for @@ -119,7 +129,7 @@ App documentation states that a Salesforce administrator creates the app. For method 2, what gets created: one local **External Client App** with OAuth enabled. The candidate Speakeasy configuration uses the generated **Consumer Key** as -**Client ID** and leaves **Client Secret (optional)** empty. Salesforce +**Client ID** and leaves **Client secret** empty. Salesforce documents that Consumer Key-only PKCE configuration for Postman and Cursor, and says other clients supporting OAuth 2.0 Authorization Code with PKCE should work. Salesforce does not name the Speakeasy AI Control Plane as a @@ -136,7 +146,7 @@ documents that other clients must use the callback URL supplied by the client; the canonical Speakeasy setup defines this template as the Speakeasy AI Control Plane callback URL. -After the app is attached, each connecting user completes Salesforce sign-in. +After the server's identity is saved, each connecting user completes Salesforce sign-in. Salesforce warns that its multitenant sign-in can choose the wrong org: before authorization, the user should log out of other Salesforce orgs, sign in to the target org in the default browser, and keep that browser open. This is a @@ -197,6 +207,12 @@ package contents, installation UI, org compatibility, or OAuth behavior. - Screenshot note: the Salesforce page with the setup gear menu open and **Setup** visible. +### Create your own Salesforce app {#create-your-own-salesforce-app} + +- Section heading for method 2 in `external.md` (an H2 there). It groups + {#start-external-client-app} through {#enable-sobject-server} and opens + with the server-choice prerequisite and the Consumer Key-only note. + ### Start an External Client App {#start-external-client-app} - Method 2 only; do not repeat this flow after installing the Speakeasy app. @@ -250,7 +266,7 @@ package contents, installation UI, org compatibility, or OAuth behavior. - Click **Create**. - The app can take up to 30 minutes to become available and operational. If - attaching it immediately fails even though the settings are correct, wait + signing in immediately fails even though the settings are correct, wait for that window before changing the configuration. - Values entered or copied: none. - Screenshot exception: **Create** is a standard action with no distinct @@ -303,79 +319,119 @@ activation page, refresh date. ## Speakeasy setup -The manual credential-entry skeleton below applies to **method 2 only**. -For method 1, the administrator must contact Speakeasy support to finish OAuth; -no public self-service credential-entry procedure is established for this -package. Metadata models its OAuth registration as manual (not DCR), with no -invented credential fields. Do not derive a package Client ID or secret from -the self-created-app instructions. +The skeleton below applies to **method 2 only**. For method 1, the +administrator must contact Speakeasy support to finish OAuth; no public +self-service credential-entry procedure is established for this package. +Metadata models its OAuth registration as manual, with no invented +credential fields. Do not derive a package Client ID or secret from the +self-created-app instructions. - -Per-guide values rendered into the canonical -`doctrine/speakeasy-setup.md` skeleton: +Per-guide values rendered into the canonical `doctrine/speakeasy-setup.md` +skeleton (doctrine pinned to gram `main` `68b3f78`, observed 2026-09-30): - Provider: Salesforce. - Remote URL: the production or sandbox URL selected in - {#enable-sobject-server}; all fourteen cataloged choices are in Metadata. -- Transport: `streamable-http`; the **Transport** field is read-only. -- Add-server path: use **Custom remote server** only. The operator forced - `speakeasy_add_server: custom-remote` because the catalog mapping is - unreliable or unsuitable for this Guide's selection among distinct - production and sandbox URLs. Pasting the selected URL preserves the - server and org-type choice made in {#enable-sobject-server}. Do not render a - catalog path or a catalog-presence open question. -- Authentication Option: OAuth with a manually registered client. -- OAuth scopes: `mcp_api` and `refresh_token`. -- Discovery: Salesforce publishes RFC 9728 protected-resource metadata for the - SObject endpoint, including its authorization server and required scopes. - Salesforce still requires a manually created External Client App, so use - **Configure Manually** for this Guide; whether the Speakeasy sheet also - offers **Use Discovered** is not required for this path. + {#enable-sobject-server} from {#endpoint-reference}; all fourteen + cataloged choices are in Metadata. +- Add-server path: **Custom remote path** only (**Hosted remotely**). The + operator forced `speakeasy_add_server: custom-remote` because a catalog + entry cannot carry this Guide's selection among distinct production and + sandbox URLs. Do not render a catalog path or a catalog-presence open + question. +- Authentication Option: OAuth with a manually registered External Client + App → **User Identity**. +- Probe outcome (2026-09-30, JSON-RPC `initialize` POST with + `Accept: application/json, text/event-stream`, all fourteen URLs): `401` + with body `{"errors":[{"message":"JWT Token is required"}]}` and **no + `WWW-Authenticate` header**, so no `resource_metadata` challenge. The + create form therefore preselects **No Identity**; the reader must select + **User Identity**. +- PRM: published at the path-style well-known URL + (`https://api.salesforce.com/.well-known/oauth-protected-resource/platform/mcp/v1/`), + which the dashboard's server-side discovery probes first. Production URLs + name issuer `https://login.salesforce.com`; `/v1/sandbox/...` URLs name + `https://test.salesforce.com`. Every PRM advertises exactly `mcp_api` and + `refresh_token`. Exception: the documented Data 360 sandbox URL + (`/v1/data/sandbox/data360`) has no path-style PRM (404); discovery falls + back to the origin document, which names `https://login.salesforce.com` + with scopes `api sfap_api refresh_token einstein_gpt_api`. That is the + wrong issuer and wrong scopes for a sandbox, so the Writer tells sandbox + readers to pick `https://test.salesforce.com` and, when no such provider + exists, renders the custom identity provider route (issuer + `https://test.salesforce.com`, **Discover** fills the endpoints + `https://test.salesforce.com/services/oauth2/authorize` and + `https://test.salesforce.com/services/oauth2/token`). +- Issuer metadata: `https://login.salesforce.com/.well-known/openid-configuration` + and the `test.salesforce.com` equivalent return 200 (the + `oauth-authorization-server` path is 404). Both advertise + `registration_endpoint` (`/services/oauth2/register`); neither advertises + `client_id_metadata_document_supported` (no CIMD). Anonymous DCR against + `https://login.salesforce.com/services/oauth2/register` returns `401 + invalid_client` ("invalid client credentials"). +- Registration choice: **Manual**. The dashboard defaults to + **Auto-Configure** because DCR is advertised, so the Writer names the + switch. Creation with **User Identity** tries automatic registration, + fails, and keeps the server **Disabled** (expected); the guide ends with + **Server Availability**. **Existing client** is correct only when an + earlier server in the project already holds a client for this same + External Client App. - **Client ID** origin: Salesforce **Consumer Key** from - {#copy-consumer-key}. -- Client Secret: the standards-based candidate configuration leaves - **Client Secret (optional)** empty because Salesforce documents Consumer - Key-only PKCE for public MCP clients. This exact configuration remains - unverified in the Speakeasy AI Control Plane. + {#copy-consumer-key}. **Client secret**: leave empty; Salesforce documents + Consumer Key-only PKCE for public MCP clients. With no secret the + dashboard picks token endpoint auth method `none` automatically. This + exact configuration remains unverified end to end in the Speakeasy AI + Control Plane. +- Scope string for **Advanced > Scope**: `mcp_api refresh_token`. Blank is + equivalent on every URL except the Data 360 sandbox URL (origin-PRM + fallback advertises other scopes), so the Writer says not to leave it + blank. In the custom-provider route, **Scope (override)** is + comma-separated: `mcp_api,refresh_token`. - Redirect URI registered in Salesforce: `{{ gram.oauth.callback_url }}` in - **Callback URL** at {#configure-oauth-settings}. + **Callback URL** at {#configure-oauth-settings}. The remote Identity + section does not display it; the custom-provider **Add Client** form does. - Further-reading URL: `https://developer.salesforce.com/docs/platform/hosted-mcp-servers/guide/hosted-mcp-servers-overview.html`. ### Add the server in Speakeasy {#add-server-in-speakeasy} -In the Speakeasy AI Control Plane sidebar, under **Connect**, select -**Sources**, then click **Add Source**. - -Choose **Custom remote server**. On the **Add a custom remote MCP server** -page, paste the selected MCP URL into **Remote MCP server URL** and click -**Add server**. - -This creates the hosted MCP server and opens its **Overview** page. +In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select +**MCP**, then click **Add new** to open **Add MCP server**. Choose **Hosted +remotely**. On **New remote MCP server**, paste the selected URL into **MCP +server URL**, leave **User session issuer** at its default, and click +**Verify connectivity**. Under **Identity**, change the preselected **No +Identity** to **User Identity**, then click **Save**. Automatic +registration fails for Salesforce, so the server is kept **Disabled** and +the result says to finish setup in **Settings > Identity**; this is +expected. -Screenshot note: capture the **Add Source** menu open on the **Sources** page -with **Custom remote server** visible. +Screenshot note: **New remote MCP server** after **Verify connectivity**, +with **User Identity** selected. ### Connect your credentials {#connect-speakeasy-credentials} -From the server's **Overview**, open **Settings**. Under **Authentication**, -click **Configure Manually**. In the **Attach Remote Identity Provider** sheet, -set **Client Type** to **Manual**. The sheet shows the **Redirect URI** with a -copy button — the callback URL registered in Salesforce as -`{{ gram.oauth.callback_url }}`. For the unverified candidate configuration, -paste the **Consumer Key** from {#copy-consumer-key} into **Client ID**, leave -**Client Secret (optional)** empty, and click **Attach Identity Provider**. -Confirm the sheet's **Redirect URI** matches the -`{{ gram.oauth.callback_url }}` value registered under Salesforce's **Callback -URL** field at {#configure-oauth-settings}. Salesforce documents this Consumer -Key-only PKCE pattern for compatible public clients but does not document the -Speakeasy AI Control Plane, so the mapping is unverified. If attaching still -fails after Salesforce's documented 30-minute app propagation window, stop and +Open the server's **Settings** and find **Identity**. Confirm **User +Identity**. Under **Choose an identity provider**, confirm the preselected +provider matches the URL's issuer (`https://login.salesforce.com` for +production, `https://test.salesforce.com` for sandbox); **Will be created** +is expected for a first server. Choose **Manual** (switching from the +**Auto-Configure** default), paste the **Consumer Key** from +{#copy-consumer-key} into **Client ID**, leave **Client secret** empty, +enter `mcp_api refresh_token` under **Advanced > Scope**, and click +**Save** (**Save changes** if asked). For a sandbox URL with no +`test.salesforce.com` provider, use **Create a custom identity provider** > +**New Remote Identity Provider** with **Issuer URL** +`https://test.salesforce.com` and **Discover**, then **Add Client** +(**Client Type** **Manual**, **Client ID**, empty **Client Secret +(optional)**, **Scope (override)** `mcp_api,refresh_token`, confirm +**Redirect URI**), and select it on the server as **Existing client**. +Finish with **Settings > Danger Zone > Server Availability**: turn on +**Enable MCP server** so it shows **Enabled**. If sign-in still fails after +Salesforce's documented 30-minute app propagation window, stop and escalate instead of changing the candidate configuration. -Screenshot note: capture the **Attach Remote Identity Provider** sheet with -**Client Type**, **Redirect URI**, and the credential labels visible; redact -the Client ID. +Screenshot note: **Settings > Identity** with **User Identity**, the +Salesforce provider, **Manual**, and **Advanced > Scope** filled; redact the +Client ID. This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Salesforce's MCP documentation](https://developer.salesforce.com/docs/platform/hosted-mcp-servers/guide/hosted-mcp-servers-overview.html). @@ -417,7 +473,7 @@ limits — see [Salesforce's MCP documentation](https://developer.salesforce.com Authorization Code with PKCE, but does not name the Speakeasy AI Control Plane as a tested client. Compatibility is inferred from the canonical Speakeasy OAuth flow. The Consumer Key-to-**Client ID** mapping with **Client - Secret (optional)** empty is unverified; if attaching still fails after + secret** empty is unverified; if sign-in still fails after Salesforce's documented 30-minute app propagation window, stop and escalate instead of changing the candidate configuration. - Salesforce's April 2026 GA announcement promises Hosted MCP Servers for @@ -427,11 +483,15 @@ limits — see [Salesforce's MCP documentation](https://developer.salesforce.com Treat lower-edition availability as conditional and confirm the feature is available in the target org before setup; do not infer a Setup label beyond the documented **MCP Servers** navigation path. -- The canonical Speakeasy setup ends when the administrator clicks **Attach - Identity Provider** and does not document which Speakeasy control starts the - Salesforce user-authorization prompt. Do not invent that transition in the - Setup Guide; the canonical doctrine needs an explicit authorization step - before a later guide can document the Salesforce sign-in sequence. +- The canonical Speakeasy setup says the provider's browser authorization + prompt appears when a person first uses the server; exact Salesforce prompt + labels are not documented here. Do not invent them. +- Salesforce documents the Data 360 sandbox URL as + `https://api.salesforce.com/platform/mcp/v1/data/sandbox/data360`, but on + 2026-09-30 that path has no path-style PRM (404) while + `.../v1/sandbox/data/data360` does (issuer `https://test.salesforce.com`). + The guide keeps the documented URL and a custom-provider fallback; whether + the documented URL accepts sandbox tokens is untested without an org. ## Provenance @@ -526,9 +586,19 @@ observations are historical, not tests rerun in September. observations returned HTTP 401 in the August research, backing the URLs' existence and OAuth protection. The protected-resource metadata request for production SObject Reads returned HTTP 200 and advertised `mcp_api` and `refresh_token`. -- `doctrine/speakeasy-setup.md` — observed `2026-08-06T23:23:14Z`; backs the - fixed Speakeasy-side anchors, labels, OAuth attach flow, callback template - semantics, forced Custom remote path behavior, and closing pointer. +- `doctrine/speakeasy-setup.md` (gram `main` `68b3f78`) — observed + `2026-09-30T21:25:35Z`; backs the fixed Speakeasy-side anchors, Identity + section labels, Manual registration flow, Server Availability step, + callback template semantics, forced Custom remote path behavior, and + closing pointer. +- Endpoint observations `2026-09-30`: JSON-RPC `initialize` POST to all + fourteen remotes (401, no `WWW-Authenticate`); path-style PRM for each + remote; `https://api.salesforce.com/.well-known/oauth-protected-resource` + (origin PRM); `https://login.salesforce.com/.well-known/openid-configuration` + and `https://test.salesforce.com/.well-known/openid-configuration` + (registration endpoint, no CIMD); anonymous POST to + `https://login.salesforce.com/services/oauth2/register` (401 + `invalid_client`). - Operator note `Speakeasy MCP Catalog: overridden-custom-remote` with query `salesforce` — observed `2026-08-06T23:23:14Z`; backs the decision not to render or investigate a catalog path because the Guide-level diff --git a/guides/salesforce/speakeasy.md b/guides/salesforce/speakeasy.md index 7bfc63a..fdd1d86 100644 --- a/guides/salesforce/speakeasy.md +++ b/guides/salesforce/speakeasy.md @@ -5,49 +5,58 @@ Follow these steps after [creating your own Salesforce app](external.md#create-y ### Add the server in Speakeasy {#add-server-in-speakeasy} 1. In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select **MCP**. -2. Select **Add new** to open the **Add MCP server** page. +2. Click **Add new** to open **Add MCP server**. 3. Choose **Hosted remotely**. -4. On the **New remote MCP server** page, paste the URL recorded in [Enable the selected MCP server](external.md#enable-sobject-server) into **MCP server URL**. -5. Select **Verify connectivity**, then **Save**. +4. On **New remote MCP server**, paste the URL recorded in [Enable the selected MCP server](external.md#enable-sobject-server) into **MCP server URL**. +5. Leave **User session issuer** at its default. +6. Click **Verify connectivity**. +7. Under **Identity**, select **User Identity**. The page preselects **No Identity** for Salesforce URLs, so change it. +8. Click **Save**. -This creates the hosted MCP server and opens its **Overview** page. +Speakeasy cannot register a Salesforce client automatically. It keeps the server **Disabled** and says to finish setup in **Settings > Identity**. This is expected. - + ### Connect your credentials {#connect-speakeasy-credentials} -From the server's **Overview**, open **Settings**. +Open the server's **Settings** and find the **Identity** section. -Under **Authentication**, if unconfigured, select **Use Discovered** when available; otherwise select **Configure Manually**. If configured but no provider is attached, use **Connected services > Add provider**. If the intended provider is already attached, use its existing controls and skip the provider/client creation and attachment steps below; do not add a duplicate. +1. Confirm that **User Identity** is selected. +2. Under **Choose an identity provider**, confirm the preselected provider is `https://login.salesforce.com` for a production URL or `https://test.salesforce.com` for a sandbox URL. A provider badged **Will be created** is expected. If a sandbox URL shows `https://login.salesforce.com`, open the picker (**Search identity providers…**) and choose `https://test.salesforce.com`. +3. Under the provider, choose **Manual**. The dashboard preselects **Auto-Configure**, which fails for Salesforce. If an earlier Salesforce server already uses this app, **Existing client** is preselected instead: pick that client under **Client** and skip to step 7. +4. Paste the [**Consumer Key**](external.md#copy-consumer-key) into **Client ID**. +5. Leave **Client secret** empty. +6. Open **Advanced** and enter this value in **Scope**. Do not leave it blank. -#### Select the identity provider + ``` + mcp_api refresh_token + ``` -In **Attach Remote Identity Provider**, **Identity Provider** defaults to **Select existing** when project issuers are available. Select the matching provider and skip the new-provider fields below. Otherwise choose **Add new** (or use the new-provider form shown when none exist). +7. Click **Save**. If asked to confirm, click **Save changes**. -For a new provider only, confirm **Issuer URL**, the auto-derived **Slug**, and **Endpoints**. Discovery runs automatically for a seeded issuer; after typing or changing the URL, select **Discover** only if offered. +If a sandbox URL offers no `https://test.salesforce.com` provider, create one, then return to step 7: -If no matching provider or complete discovered configuration is available, ask your administrator for the documented **Issuer URL** and authorization and token **Endpoints** before continuing. Do not infer them from the MCP server URL. +1. Open the picker and click **Create a custom identity provider**. This opens **Remote Identity Providers**. +2. Click **New Remote Identity Provider**. +3. Enter `https://test.salesforce.com` in **Issuer URL**. +4. Click **Discover** and keep the derived **Slug**. +5. Click **Create**. +6. On the new provider, click **Add Client**. +7. Set **Client Type** to **Manual**. +8. Paste the **Consumer Key** into **Client ID** and leave **Client Secret (optional)** empty. +9. Enter `mcp_api,refresh_token` in **Scope (override)**. +10. Confirm the displayed **Redirect URI** matches the **Callback URL** you [entered in Salesforce](external.md#configure-oauth-settings). +11. Click **Create**. +12. Return to the server's **Settings > Identity** and select that provider. +13. Choose **Existing client** and pick the new client under **Client**. -#### Select the session client +Turn the server on: -Under **Session Client**, choose **Select existing** only for a client whose saved credentials, scopes, and audience match the requirements below; otherwise choose **Add new**. When reusing a matching client, skip directly to **Verify the callback and attach** below. Do not create credentials or register the client again. Otherwise choose **Add new** (or use the new-client form shown when no clients exist) and complete these new-client-only steps: +1. In **Settings > Danger Zone > Server Availability**, turn on **Enable MCP server**. +2. Confirm it shows **Enabled**. -1. In the **Attach Remote Identity Provider** sheet, set **Client Type** to **Manual**. +When a person first uses the server, Salesforce asks them to sign in and allow access. If sign-in fails right after you created the app, wait out Salesforce's 30-minute activation window before retrying. Do not change the OAuth settings. -The sheet shows the **Redirect URI** with a copy button. It is the callback URL registered in Salesforce as `{{ gram.oauth.callback_url }}`. - -1. Paste the [**Consumer Key**](external.md#copy-consumer-key) into **Client ID**. -1. Leave **Client Secret (optional)** empty. - -#### Verify the callback and attach - -1. Confirm that the callback URL registered with the provider is `{{ gram.oauth.callback_url }}`. For a new manual client, also compare it with the sheet's displayed **Redirect URI**. The existing-client selection does not display that field; check the registered callback in the provider's app settings instead. -2. Click **Attach Identity Provider**. - -For the provider-side callback setting, see [**Callback URL**](external.md#configure-oauth-settings). - -If attachment still fails after the app's 30-minute activation window, stop and escalate; do not change the OAuth settings. - - + This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Salesforce's MCP documentation](https://developer.salesforce.com/docs/platform/hosted-mcp-servers/guide/hosted-mcp-servers-overview.html). diff --git a/guides/slack/meta.yaml b/guides/slack/meta.yaml index ef6973a..51a5fc4 100644 --- a/guides/slack/meta.yaml +++ b/guides/slack/meta.yaml @@ -38,22 +38,26 @@ remotes: - source: provider-documentation locator: https://docs.slack.dev/ai/slack-mcp-server/ classification: official - observed_at: "2026-09-17T00:05:11Z" + observed_at: "2026-09-30T00:00:00Z" provenance: - source: provider-documentation locator: https://docs.slack.dev/ai/slack-mcp-server/ name: Slack MCP server overview classification: official - observed_at: "2026-09-17T00:05:11Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation locator: https://docs.slack.dev/ai/slack-mcp-server/developing/ name: Developing a sample app with the Slack MCP Server classification: official - observed_at: "2026-09-17T00:05:11Z" + observed_at: "2026-09-30T00:00:00Z" - source: endpoint-observation locator: https://mcp.slack.com/.well-known/oauth-authorization-server classification: official - observed_at: "2026-09-17T00:05:11Z" + observed_at: "2026-09-30T00:00:00Z" + - source: endpoint-observation + locator: https://mcp.slack.com/.well-known/oauth-protected-resource + classification: official + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation locator: https://docs.slack.dev/reference/app-manifest/ classification: official diff --git a/guides/slack/research.md b/guides/slack/research.md index ff91cd6..6f54ccc 100644 --- a/guides/slack/research.md +++ b/guides/slack/research.md @@ -39,13 +39,17 @@ operator explicitly requested this copy-paste configuration alternative. OAuth installation, consent, and secure credential storage. Observed 2026-09-16. - **Authorization metadata:** https://mcp.slack.com/.well-known/oauth-authorization-server — fetched public - JSON on 2026-09-16. Issuer `https://mcp.slack.com`; authorization endpoint + JSON on 2026-09-16, re-fetched 2026-09-30 (unchanged). Issuer `https://mcp.slack.com`; authorization endpoint `https://slack.com/oauth/v2_user/authorize`; token endpoint `https://slack.com/api/oauth.v2.user.access`; token authentication `client_secret_post`; S256 PKCE; authorization-code and refresh-token grants. No registration endpoint. Scope list includes the four channel-list scopes. -- **Client setup:** `doctrine/speakeasy-setup.md`, read 2026-09-16 — canonical - Control Plane UI, callback template, custom-remote route, and manual client. +- **Client setup:** `doctrine/speakeasy-setup.md`, read 2026-09-30 — canonical + Control Plane UI, callback template, custom-remote route, and Identity + section. +- **Protected-resource metadata:** + https://mcp.slack.com/.well-known/oauth-protected-resource — fetched + 2026-09-30. Issuer `https://mcp.slack.com`; 30 advertised scopes. - **Client capabilities:** `doctrine/ai-control-plane-oauth.md`, read 2026-09-16, verified upstream revision `4e1fef388aa0f5b498f5d35400780ff2b99815e4` on 2026-09-15 — source-inspected support, not a Slack acceptance test. @@ -81,10 +85,9 @@ operator explicitly requested this copy-paste configuration alternative. The maintained capability reference establishes manual registration, S256 PKCE, `client_secret_post`, configurable scopes, discovery, and refresh-token grant -support. Token authentication defaults to Basic when a secret is present and no -recognized method is stored, so explicitly select Post; merely supplying the -secret is not enough. A nonempty issuer scope override wins over client scopes; -ensure it matches the selected Slack user scopes. Slack metadata does not +support. On the current dashboard the token endpoint auth method is chosen +automatically from the issuer metadata, which advertises only +`client_secret_post`, so no reader action is needed. Slack metadata does not advertise OpenID scopes, so do not add `openid` or `offline_access` speculatively. Relevant pinned sources retained from the reference: @@ -148,32 +151,69 @@ Screenshot: Credential labels with values redacted. ## Control Plane transclusion and anchor contract -Use `speakeasy_add_server: custom-remote` to target the official endpoint -unambiguously. Catalog presence was not checked, and no catalog absence is -claimed. No Pulse alias is invented. - -- `{#add-server-in-speakeasy}`: **Connect** → **Sources** → **Add Source** → - **Custom remote server** → **Add a custom remote MCP server**. Enter the remote - in **Remote MCP server URL**, click **Add server**, arrive at **Overview**. - Screenshot: custom-remote form with the Slack URL. -- `{#connect-speakeasy-credentials}`: **Overview** → **Settings** → - **Authentication** → **Configure Manually** or **Use Discovered**. - **Issuer URL** `https://mcp.slack.com`, **Endpoints** → **Discover** if needed; - **Attach Remote Identity Provider**, **Client Type** **Manual**, **Client ID**, - **Client Secret (optional)** (required by Slack), explicit `client_secret_post`, - selected scopes, **Attach Identity Provider**. Match the displayed **Redirect - URI** with the callback registered upstream. Screenshot: Manual, user-token - endpoints, Post authentication, all credentials redacted. +Canonical source: `doctrine/speakeasy-setup.md` (gram `main` commit +`68b3f78`), read 2026-09-30. + +Per-guide values: + +- Remote URL: `https://mcp.slack.com/mcp`, shared, not tenanted. +- Add-server path: `speakeasy_add_server: custom-remote` targets the official + endpoint unambiguously. Catalog presence was not checked, and no catalog + absence is claimed. Render **Hosted remotely** only. +- Authentication Option: `internal-app-oauth` → **User Identity**. **Client + ID** and **Client Secret** come from `copy-client-credentials`; scopes come + from `set-user-permissions`. +- Probe outcome (2026-09-30): `initialize` POST with + `Accept: application/json, text/event-stream` returns 401 with + `WWW-Authenticate: Bearer resource_metadata="https://mcp.slack.com/.well-known/oauth-protected-resource"`. + The create form therefore preselects **User Identity**. +- PRM issuer: `authorization_servers` is `https://mcp.slack.com`. The PRM + advertises 30 scopes (canvases, chat, files, history, search, users, and + more), far beyond the four the manifest grants. +- Issuer metadata (`/.well-known/oauth-authorization-server`, 2026-09-30): + authorization `https://slack.com/oauth/v2_user/authorize`, token + `https://slack.com/api/oauth.v2.user.access`, + `token_endpoint_auth_methods_supported: ["client_secret_post"]`, S256 PKCE. + No `registration_endpoint` and no `client_id_metadata_document_supported` + (no DCR, no CIMD); Slack's overview also says DCR is unsupported. +- Registration choice: **Manual**. Auto-registration at creation cannot + succeed, so the server is kept **Disabled** and the reader finishes in + **Settings > Identity**; the dashboard defaults to **Manual** because the + issuer advertises neither CIMD nor DCR. The token endpoint auth method is + chosen automatically from the issuer metadata (`client_secret_post`); there + is no control for it. +- Scope string for **Advanced > Scope**: `channels:read groups:read im:read mpim:read`. + Blank is not safe: it requests all 30 PRM scopes, and Slack consent fails + for scopes the app does not grant. +- Client secret: required by Slack, despite the field's "Optional" placeholder. +- Server Availability: finish with **Settings > Danger Zone > Server + Availability** → **Enable MCP server**. +- Further reading: `https://docs.slack.dev/ai/slack-mcp-server/`. + +Anchors: + +- `{#add-server-in-speakeasy}`: **MCP Gateway** → **MCP** → **Add new** → + **Hosted remotely** → **New remote MCP server**; paste the remote into **MCP + server URL**, leave **User session issuer** at its default, **Verify + connectivity**, keep **User Identity**, **Save**. Screenshot: the form with + Slack's endpoint and **User Identity** selected. +- `{#connect-speakeasy-credentials}`: **Settings** → **Identity** → **User + Identity**; confirm the provider `https://mcp.slack.com` in **Choose an + identity provider** (badged **Will be created** when new); **Manual**; + **Client ID**, **Client secret**; **Advanced** → **Scope** with the string + above; **Save** (confirm with **Save changes** when asked); then **Server + Availability**. The Identity section shows no Redirect URI, so + `register-callback` carries the callback check. Screenshot: Identity with + User Identity, the Slack provider, and Manual; values redacted. - Preserve the canonical final pointer to Slack's MCP documentation. Setup ends after credentials; publishing and downstream-client distribution are out of scope. Explain user consent without inventing a dashboard test button. ## Research limitations and operator decisions -- No screenshots or authenticated console inspection. Exact user-scope, - reveal-secret, token-authentication-method, and scope-control labels may vary; - use action-oriented wording without inventing a label. If the deployment - hides the latter controls, its administrator must configure the required values. +- No screenshots or authenticated console inspection. Exact user-scope and + reveal-secret labels in Slack may vary; use action-oriented wording without + inventing a label. - No end-to-end Slack test, independent evidence of the current app's eligibility, or successful consent. Keep that limitation visible in the setup guide. - The organization supplies an internal app, its administrator approval, any diff --git a/guides/slack/speakeasy.md b/guides/slack/speakeasy.md index f614fe0..0131281 100644 --- a/guides/slack/speakeasy.md +++ b/guides/slack/speakeasy.md @@ -3,69 +3,48 @@ ### Add the server in Speakeasy {#add-server-in-speakeasy} 1. In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select **MCP**. -2. Click **Add new** to open the **Add MCP server** page. +2. Click **Add new** to open **Add MCP server**. 3. Choose **Hosted remotely**. -4. On **New remote MCP server**, paste this value into **MCP server URL**: +4. On **New remote MCP server**, paste this URL into **MCP server URL**: - ``` + ```text https://mcp.slack.com/mcp ``` 5. Optionally enter a **Display name (optional)**. -6. Click **Verify connectivity**, then, after verification succeeds, click **Save**. +6. Leave **User session issuer** at its default. +7. Click **Verify connectivity**. +8. Under **Identity**, confirm that **User Identity** is selected. +9. If **Guardrails** appears, leave it off. +10. Click **Save**. -This creates the hosted MCP server and opens its **Overview** page. +Speakeasy keeps the new server **Disabled** and says to finish setup in **Settings > Identity**. This is expected for Slack; the next section finishes it. - + ### Connect your credentials {#connect-speakeasy-credentials} -From **Overview**, open **Settings**. - -Under **Authentication**, if unconfigured, select **Use Discovered** when available; otherwise select **Configure Manually**. If configured but no provider is attached, use **Connected services > Add provider**. If the intended provider is already attached, use its existing controls and skip the provider/client creation and attachment steps below; do not add a duplicate. - -#### Select the identity provider +Open the server's **Settings** and find the **Identity** section. -In **Attach Remote Identity Provider**, **Identity Provider** defaults to **Select existing** when project issuers are available. Select the matching provider and skip the new-provider fields below. Otherwise choose **Add new** (or use the new-provider form shown when none exist). - -For a new provider only: - -1. Enter `https://mcp.slack.com` as the **Issuer URL** if it is not already populated, and keep the auto-derived **Slug**. -1. Under **Endpoints**, wait for automatic discovery. After typing or changing the **Issuer URL**, click **Discover** only if offered. -1. Confirm the discovered endpoints are Slack's user-token endpoints, not the bot-token OAuth endpoints. If discovery does not populate them, enter: - - Authorization endpoint: +1. Select **User Identity**. +2. In **Choose an identity provider**, confirm that the preselected provider is Slack's issuer, `https://mcp.slack.com`. It is badged **Will be created** when the project has no Slack provider yet. If another provider is selected, open the picker, search in **Search identity providers…**, and choose the Slack provider. +3. Under the provider, choose **Manual**. If **Existing client** is preselected, switch to **Manual**. +4. Paste the [Slack Client ID](external.md#copy-client-credentials) into **Client ID**. +5. Paste the [Slack Client Secret](external.md#copy-client-credentials) into **Client secret**. Slack requires the secret even though the field shows "Optional". +6. Open **Advanced**. In **Scope**, enter the scopes from [Set user permissions](external.md#set-user-permissions) on one line. Do not leave **Scope** blank: a blank value requests every scope the Slack server advertises, which your app does not grant, and Slack consent fails. ```text - https://slack.com/oauth/v2_user/authorize + channels:read groups:read im:read mpim:read ``` - Token endpoint: - - ```text - https://slack.com/api/oauth.v2.user.access - ``` - -#### Select the session client - -Under **Session Client**, choose **Select existing** only for a client whose saved credentials, scopes, and audience match the requirements below; otherwise choose **Add new**. When reusing a matching client, skip directly to **Verify the callback and attach** below. Do not create credentials or register the client again. Otherwise choose **Add new** (or use the new-client form shown when no clients exist) and complete these new-client-only steps: - -1. Set **Client Type** to **Manual**. Slack does not support Dynamic Client Registration. -1. Paste the [Slack Client ID](external.md#copy-client-credentials) into **Client ID**. -1. Paste the [Slack Client Secret](external.md#copy-client-credentials) into **Client Secret (optional)**. Slack requires this secret. -1. Set **Token Endpoint Auth Method** to `client_secret_post`. Do not use `client_secret_basic`. -1. In **Scope (override)**, enter the scopes that match your [Slack user permissions](external.md#set-user-permissions), comma-separated: `channels:read`, `groups:read`, `im:read`, and `mpim:read` for listing channels. If an issuer-level scope override is configured, make it match this selection. - -#### Verify the callback and attach - -1. Confirm that the callback URL registered under Slack's [Redirect URLs](external.md#register-callback) is `{{ gram.oauth.callback_url }}`. For a new manual client, also compare it with the sheet's displayed **Redirect URI**. The existing-client selection does not display that field; check the registered callback in the provider's app settings instead. -2. Click **Attach Identity Provider**. + If your app owner added more user-token scopes, add them to this line, separated by spaces. -Each user must complete Slack consent when connecting; attaching the client credentials does not grant access to everyone's Slack data. +7. Click **Save**. If Speakeasy asks you to confirm, click **Save changes**. +8. Open **Settings > Danger Zone > Server Availability**. +9. Turn on **Enable MCP server** so the switch shows **Enabled**. -If your deployment does not expose the authentication-method or scope controls, ask the Control Plane administrator to configure these values before connecting. This configuration is based on Slack's documentation and the Control Plane's OAuth implementation; it has not been tested end to end with a Slack workspace. +When a person first uses the server, Slack's browser authorization prompt appears. Each person authorizes with their own Slack account; saving the client does not grant access to anyone's Slack data. - - + This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Slack's MCP documentation](https://docs.slack.dev/ai/slack-mcp-server/). diff --git a/guides/snowflake/meta.yaml b/guides/snowflake/meta.yaml index f6053f4..25e214e 100644 --- a/guides/snowflake/meta.yaml +++ b/guides/snowflake/meta.yaml @@ -53,7 +53,7 @@ provenance: locator: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-mcp name: Snowflake-managed MCP server classification: official - observed_at: "2026-08-11T18:36:01Z" + observed_at: "2026-09-30T21:30:00Z" - source: provider-documentation locator: https://docs.snowflake.com/en/sql-reference/sql/create-mcp-server name: CREATE MCP SERVER @@ -73,7 +73,7 @@ provenance: locator: https://docs.snowflake.com/en/user-guide/oauth-custom name: Configure Snowflake OAuth for custom clients classification: official - observed_at: "2026-08-11T18:36:01Z" + observed_at: "2026-09-30T21:30:00Z" - source: provider-documentation locator: https://docs.snowflake.com/en/user-guide/oauth-snowflake-overview name: Snowflake OAuth overview @@ -143,4 +143,4 @@ provenance: locator: doctrine/speakeasy-setup.md name: Speakeasy setup canonical section classification: official - observed_at: "2026-08-11T18:36:01Z" + observed_at: "2026-09-30T21:30:00Z" diff --git a/guides/snowflake/research.md b/guides/snowflake/research.md index f57e114..e88c76a 100644 --- a/guides/snowflake/research.md +++ b/guides/snowflake/research.md @@ -17,9 +17,13 @@ researched_at: 2026-08-11T18:36:01Z Snowflake constructs this account-specific endpoint from the account host and MCP server object names. It is a tenanted MCP Server URL: copy the account-specific URL produced by External setup into the Speakeasy AI - Control Plane's Custom remote server form. + Control Plane's **Hosted remotely** form. - **Transport:** remote HTTP (`streamable-http`). Snowflake documents MCP - JSON-RPC over HTTP `POST` and supports only non-streaming responses. + JSON-RPC over HTTP `POST`. Since 2026-08-20, `tools/call` responses are a + Server-Sent Events stream ending with `data: [DONE]`, and clients must send + `Accept: application/json, text/event-stream` (re-verified on + `cortex-agents-mcp`, 2026-09-30). The Speakeasy AI Control Plane proxies + remote servers over streamable-http, so no guide step changes. - **Authentication:** OAuth 2.0 using a manually registered, confidential custom Snowflake OAuth security integration. Snowflake recommends OAuth over hardcoded Programmatic Access Tokens and does not support Dynamic Client @@ -339,52 +343,89 @@ Registration, so the manually registered client ID and secret are required. ## Speakeasy setup -Per-guide values for `doctrine/speakeasy-setup.md`: +Per-guide values rendered into the canonical `doctrine/speakeasy-setup.md` +skeleton (doctrine pinned to gram `main` `68b3f78`, observed 2026-09-30): - Provider: Snowflake. -- Remote URL fact: the account-specific Snowflake URL template in Server - facts and `meta.yaml`; External setup forms it at - {#create-cortex-agent-mcp-server}. -- Transport: `streamable-http`. -- Add-server path: Custom remote server only because the Snowflake MCP Server - URL is account-specific (`remotes[].tenanted: true`). The path is resolved; - do not render an alternate add-server path or presence question. -- Authentication Option: manually registered confidential OAuth client. -- OAuth metadata: Snowflake requires the security integration's client ID and - secret and does not support Dynamic Client Registration. Use - **Configure Manually**. -- **Client ID** and **Client Secret**: values copied at - {#copy-oauth-credentials}. -- Redirect URI: `{{ gram.oauth.callback_url }}` registered at - {#create-oauth-integration}. +- Remote URL: the account-specific URL template in Server facts and + `meta.yaml`; External setup forms it at {#create-cortex-agent-mcp-server}. +- Add-server path: **Custom remote path** only (**Hosted remotely**) because + the URL is account-specific (`remotes[].tenanted: true`). Do not render a + catalog path or a presence question. +- Authentication Option: manually registered confidential Snowflake OAuth + security integration → **User Identity**. +- Probe outcome: not probed live. No account is available, and unknown + account hosts return `404` HTML for the MCP path and every well-known path + (observed 2026-09-30 against placeholder hosts). Snowflake documents that a + connecting client receives `401` with a `WWW-Authenticate` header pointing + to Protected Resource Metadata, so the create form likely preselects + **User Identity**; the Writer says to select it if it is not already. +- PRM: documented, not observed. By default (no External OAuth binding and no + `OAUTH_SCOPES_SUPPORTED`), MCP servers use Snowflake OAuth and advertise + `session:role:all` as the only supported scope. The PRM's + `authorization_servers` value and whether the account publishes RFC 8414 / + OpenID metadata are not documented. +- CIMD/DCR: Snowflake states the managed MCP server does not support dynamic + client registration. CIMD is not documented. Automatic registration at + creation therefore fails and the server is kept **Disabled** (expected). +- Registration choice: **Manual** with the integration's client ID and + secret. Lead with the picker's discovered provider; when no Snowflake + provider is offered (discovery unavailable), render the custom identity + provider route with **Issuer URL** `https://`, + **Authorization Endpoint** `https:///oauth/authorize`, and + **Token Endpoint** `https:///oauth/token-request` + (`oauth-custom`, re-verified 2026-09-30). The issuer value is the account + URL by inference, not documentation. +- Scope string for **Advanced > Scope**: `session:role:all`. Snowflake + documents that clients requesting it get a session in the user's + `DEFAULT_ROLE`, which this guide sets to ``. Blank would + request every PRM scope, which grows if an administrator sets + `OAUTH_SCOPES_SUPPORTED`, so the Writer says not to leave it blank. In the + custom-provider route, **Scope (override)** takes the same single value. +- **Client ID** and **Client secret**: `oauth_client_id` and + `oauth_client_secret` from {#copy-oauth-credentials}. The integration is + `CONFIDENTIAL`, so the secret is required despite the "Optional" + placeholder. +- Redirect URI: `{{ gram.oauth.callback_url }}` registered as + `OAUTH_REDIRECT_URI` at {#create-oauth-integration}. The remote Identity + section does not display it; the custom-provider **Add Client** form does. - Further reading: `https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-mcp`. ### Add the server in Speakeasy {#add-server-in-speakeasy} -In the Speakeasy AI Control Plane sidebar, under **Connect**, select -**Sources**, then click **Add Source**. +In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select +**MCP**, then click **Add new** to open **Add MCP server**. Choose **Hosted +remotely**. On **New remote MCP server**, paste the account-specific URL +retained at {#create-cortex-agent-mcp-server} into **MCP server URL**, leave +**User session issuer** at its default, and click **Verify connectivity**. +Under **Identity**, select **User Identity** if it is not preselected, then +click **Save**. Automatic registration fails, so the server is kept +**Disabled** and the result says to finish setup in **Settings > Identity**; +this is expected. -Choose **Custom remote server**. On the **Add a custom remote MCP server** -page, paste the account-specific URL retained at -{#create-cortex-agent-mcp-server} into **Remote MCP server URL**, then click -**Add server**. This creates the hosted MCP server and opens its **Overview** -page. - -Screenshot note: the Add Source menu open on the Sources page, or the -provider's catalog entry. +Screenshot note: **New remote MCP server** after **Verify connectivity**, +with **User Identity** selected. ### Connect your credentials {#connect-speakeasy-credentials} -From the server's **Overview**, open **Settings**. Under **Authentication**, -click **Configure Manually**. In the **Attach Remote Identity Provider** -sheet, set **Client Type** to **Manual**. The sheet displays the -**Redirect URI** with a copy button. Confirm that URI matches the callback -registered in Snowflake. Paste the -values from {#copy-oauth-credentials} into **Client ID** and -**Client Secret (optional)**, then click **Attach Identity Provider**. - -Screenshot note: the attachment sheet with labels visible and values redacted. +Open the server's **Settings** and find **Identity**. Confirm **User +Identity**. Under **Choose an identity provider**, confirm the preselected +provider is on the Snowflake account hostname (**Will be created** is +expected). Choose **Manual**, paste the values from {#copy-oauth-credentials} +into **Client ID** and **Client secret**, enter `session:role:all` under +**Advanced > Scope**, and click **Save** (**Save changes** if asked). When no +Snowflake provider is offered, use **Create a custom identity provider** > +**New Remote Identity Provider** with the issuer and endpoints above, then +**Add Client** (**Client Type** **Manual**, **Client ID**, **Client Secret +(optional)**, **Scope (override)** `session:role:all`, confirm **Redirect +URI**), and select it on the server as **Existing client**. Finish with +**Settings > Danger Zone > Server Availability**: turn on **Enable MCP +server** so it shows **Enabled**. + +Screenshot note: **Settings > Identity** with **User Identity**, the +Snowflake provider, **Manual**, and **Advanced > Scope** filled; values +redacted. When a client first requests Snowflake access, Snowflake's OAuth flow opens in a browser. The user signs in with their own Snowflake credentials and consents @@ -392,8 +433,7 @@ to the non-privileged default role. The resulting session uses that user's `DEFAULT_ROLE`. This guide covers setup only. For anything beyond it — billing, tool behavior, -limits — see Snowflake's MCP documentation at -`https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-mcp`. +limits — see [Snowflake's MCP documentation](https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-mcp). ## Open questions @@ -401,6 +441,12 @@ limits — see Snowflake's MCP documentation at controls but does not publish a stable label or navigation path for the role selector. The walkthrough therefore refers conceptually to the workspace role context control rather than inventing a UI label. +- No Snowflake account was available to probe the MCP URL. Unconfirmed: the + PRM's `authorization_servers` value, whether the account publishes + authorization-server metadata the dashboard can discover (which decides + whether the picker offers a Snowflake provider or the custom route is + needed), and that the issuer is `https://`. Verify against a + live account before removing the custom-provider fallback. ## Provenance @@ -460,5 +506,10 @@ pages and indexes remained reachable, and the setup facts above were unchanged. hostname formatting. - `https://quickstarts.snowflake.com/guide/getting-started-with-snowflake-mcp-server/index.html` — official managed MCP creation and endpoint example; PAT path not used. -- `doctrine/speakeasy-setup.md` — canonical Speakeasy labels and fixed - anchors. +- `doctrine/speakeasy-setup.md` (gram `main` `68b3f78`, observed + 2026-09-30) — canonical Speakeasy labels, Identity section, Manual and + custom-provider routes, Server Availability, and fixed anchors. +- Re-observed 2026-09-30: `cortex-agents-mcp` (SSE `tools/call` since + 2026-08-20, `Accept` header, no DCR, default PRM scope `session:role:all`, + `WWW-Authenticate` 401 behavior) and `oauth-custom` (authorize and + token-request endpoints, scope values). diff --git a/guides/snowflake/speakeasy.md b/guides/snowflake/speakeasy.md index 16d19aa..8663fba 100644 --- a/guides/snowflake/speakeasy.md +++ b/guides/snowflake/speakeasy.md @@ -3,46 +3,64 @@ ### Add the server in Speakeasy {#add-server-in-speakeasy} 1. In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select **MCP**. -2. Click **Add new** to open the **Add MCP server** page. +2. Click **Add new** to open **Add MCP server**. 3. Choose **Hosted remotely**. -4. On the **New remote MCP server** page, paste the account-specific URL retained in [Create the Cortex Agent MCP server](external.md#create-cortex-agent-mcp-server) into **MCP server URL**. -5. Click **Verify connectivity**, then **Save**. +4. On **New remote MCP server**, paste the account-specific URL retained in [Create the Cortex Agent MCP server](external.md#create-cortex-agent-mcp-server) into **MCP server URL**. +5. Leave **User session issuer** at its default. +6. Click **Verify connectivity**. +7. Under **Identity**, select **User Identity** if it is not already selected. +8. Click **Save**. -This creates the hosted MCP server and opens its **Overview** page. +Snowflake does not support automatic client registration, so Speakeasy keeps the server **Disabled** and says to finish setup in **Settings > Identity**. This is expected. - + ### Connect your credentials {#connect-speakeasy-credentials} -From the server's **Overview**, open **Settings**. +Open the server's **Settings** and find the **Identity** section. -Under **Authentication**, if unconfigured, select **Use Discovered** when available; otherwise select **Configure Manually**. If configured but no provider is attached, use **Connected services > Add provider**. If the intended provider is already attached, use its existing controls and skip the provider/client creation and attachment steps below; do not add a duplicate. +1. Confirm that **User Identity** is selected. +2. Under **Choose an identity provider**, confirm the preselected provider is on your Snowflake account hostname (``). A provider badged **Will be created** is expected. If no Snowflake provider is offered, follow the custom provider steps below instead. +3. Under the provider, choose **Manual**. +4. Paste the [**Client ID**](external.md#copy-oauth-credentials) into **Client ID**. +5. Paste the [**Client Secret**](external.md#copy-oauth-credentials) into **Client secret**. The secret is required even though the field says "Optional". +6. Open **Advanced** and enter `session:role:all` in **Scope**. Do not leave it blank. +7. Click **Save**. If asked to confirm, click **Save changes**. -#### Select the identity provider +If no Snowflake provider is offered, create one: -In **Attach Remote Identity Provider**, **Identity Provider** defaults to **Select existing** when project issuers are available. Select the matching provider and skip the new-provider fields below. Otherwise choose **Add new** (or use the new-provider form shown when none exist). +1. Open the picker and click **Create a custom identity provider**. This opens **Remote Identity Providers**. +2. Click **New Remote Identity Provider**. +3. Enter `https://` in **Issuer URL**, using the public account hostname from [Create the Cortex Agent MCP server](external.md#create-cortex-agent-mcp-server). +4. Under **Endpoints**, enter this value in **Authorization Endpoint**: -For a new provider only, confirm **Issuer URL**, the auto-derived **Slug**, and **Endpoints**. Discovery runs automatically for a seeded issuer; after typing or changing the URL, select **Discover** only if offered. + ``` + https:///oauth/authorize + ``` -If no matching provider or complete discovered configuration is available, ask your administrator for the documented **Issuer URL** and authorization and token **Endpoints** before continuing. Do not infer them from the MCP server URL. +5. Enter this value in **Token Endpoint**: -#### Select the session client + ``` + https:///oauth/token-request + ``` -Under **Session Client**, choose **Select existing** only for a client whose saved credentials, scopes, and audience match the requirements below; otherwise choose **Add new**. When reusing a matching client, skip directly to **Verify the callback and attach** below. Do not create credentials or register the client again. Otherwise choose **Add new** (or use the new-client form shown when no clients exist) and complete these new-client-only steps: +6. Keep the derived **Slug** and click **Create**. +7. On the new provider, click **Add Client**. +8. Set **Client Type** to **Manual**. +9. Paste the **Client ID** into **Client ID** and the **Client Secret** into **Client Secret (optional)**. +10. Enter `session:role:all` in **Scope (override)**. +11. Confirm the displayed **Redirect URI** matches the `OAUTH_REDIRECT_URI` you set in [Create the OAuth integration](external.md#create-oauth-integration). +12. Click **Create**. +13. Return to the server's **Settings > Identity** and select that provider. +14. Choose **Existing client**, pick the new client under **Client**, and click **Save**. -1. In the **Attach Remote Identity Provider** sheet, set **Client Type** to **Manual**. -1. Paste the [**Client ID**](external.md#copy-oauth-credentials) into **Client ID**. -1. Paste the [**Client Secret**](external.md#copy-oauth-credentials) into **Client Secret (optional)**. +Turn the server on: -#### Verify the callback and attach +1. In **Settings > Danger Zone > Server Availability**, turn on **Enable MCP server**. +2. Confirm it shows **Enabled**. -1. Confirm that the callback URL registered with the provider is `{{ gram.oauth.callback_url }}`. For a new manual client, also compare it with the sheet's displayed **Redirect URI**. The existing-client selection does not display that field; check the registered callback in the provider's app settings instead. -2. Click **Attach Identity Provider**. +When a person first uses the server, Snowflake's OAuth flow opens in a browser. Each user signs in with their own Snowflake credentials and consents to the non-privileged default role. The resulting session uses that user's `DEFAULT_ROLE`. -For the provider-side callback setting, see [Create the OAuth integration](external.md#create-oauth-integration). - - - -When a client first requests Snowflake access, Snowflake's OAuth flow opens in a browser. Each user signs in with their own Snowflake credentials and consents to the non-privileged default role. The resulting session uses that user's `DEFAULT_ROLE`. + This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Snowflake's MCP documentation](https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-mcp). diff --git a/guides/x-docs/meta.yaml b/guides/x-docs/meta.yaml index 673aa39..7c7b7d1 100644 --- a/guides/x-docs/meta.yaml +++ b/guides/x-docs/meta.yaml @@ -27,7 +27,7 @@ remotes: classification: official version: 1.0.0 status: reachable-without-authentication - observed_at: "2026-07-29T20:05:42Z" + observed_at: "2026-09-30T00:00:00Z" provenance: - source: provider-runtime locator: https://docs.x.com/mcp @@ -35,26 +35,26 @@ provenance: classification: official version: 1.0.0 status: reachable-without-authentication - observed_at: "2026-07-29T20:05:42Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation - locator: https://x-preview.mintlify.app/tools/mcp + locator: https://docs.x.com/tools/mcp name: MCP servers for the X API and X developer docs classification: official - observed_at: "2026-07-29T20:05:42Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation - locator: https://x-preview.mintlify.app/llms.txt + locator: https://docs.x.com/llms.txt name: X Developer Platform documentation index classification: official - observed_at: "2026-07-29T20:05:42Z" + observed_at: "2026-09-30T00:00:00Z" - source: pulsemcp locator: com.pulsemcp.mirror/x-docs name: X Docs classification: mirror scope: tenant status: present - observed_at: "2026-07-29T20:05:42Z" + observed_at: "2026-09-30T00:00:00Z" - source: speakeasy-product-documentation locator: doctrine/speakeasy-setup.md name: Speakeasy setup canonical section classification: official - observed_at: "2026-07-29T20:05:42Z" + observed_at: "2026-09-30T00:00:00Z" diff --git a/guides/x-docs/research.md b/guides/x-docs/research.md index 978bf7d..f72de9d 100644 --- a/guides/x-docs/research.md +++ b/guides/x-docs/research.md @@ -47,34 +47,47 @@ documented fixed URL before proceeding to the Speakeasy AI Control Plane. ## Speakeasy setup Per-guide values rendered into the canonical -`doctrine/speakeasy-setup.md` skeleton: +`doctrine/speakeasy-setup.md` skeleton (gram `main` `68b3f78`): - Provider and catalog title: X Docs. -- Remote URL: `https://docs.x.com/mcp`. -- Transport: `streamable-http`; the **Transport** field is read-only. -- Add-server path: catalog only. The Speakeasy MCP Catalog lookup was present - and matched `name="com.pulsemcp.mirror/x-docs"` with title `X Docs`. -- Authentication Option: open. No External-setup step produces a credential, - and no upstream header or identity provider is configured. +- Remote URL: `https://docs.x.com/mcp` (shared public endpoint; not tenanted). +- Add-server path: `speakeasy_add_server: catalog`. The Speakeasy MCP Catalog + search on 2026-09-30 returned `com.pulsemcp.mirror/x-docs`, title `X Docs`. + Render only the catalog path. +- Authentication Option: open → identity mode **No Identity**. No + External-setup step produces a credential, and no **Upstream headers** are + added. +- Probe outcome (2026-09-30): `POST https://docs.x.com/mcp` `initialize` + without credentials → 200 `text/event-stream`, protocol `2025-06-18`, + server `X` `1.0.0`. `https://docs.x.com/.well-known/oauth-protected-resource/mcp` + returns 404, so there is no PRM, issuer, or registration to record. +- Registration choice and scope string: not applicable. +- Identity default at creation: the catalog dialog preselects **No + Identity** because the entry does not support OAuth client registration. + The Guide tells readers to keep it. No authentication-challenge warning + applies because the server answers 200 unauthenticated. +- Server Availability: not rendered; **No Identity** creation does not leave + the server **Disabled**. - Further-reading URL: `https://docs.x.com/tools/mcp`. ### Add the server in Speakeasy {#add-server-in-speakeasy} -In the Speakeasy AI Control Plane sidebar, under **Connect**, select -**Sources**, then click **Add Source**. Choose **3rd-party server**. On the -**MCP Catalog** page, enter `X Docs` in **Search MCP servers...**, open the -**X Docs** entry with **View**, and click **Add**. In the **Add to Project** -dialog, click **Add to Project**. +In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select +**MCP**, then click **Add new** to open **Add MCP server**. Choose **From the +catalog**. On the **MCP Catalog** page, enter `X Docs` in **Search MCP +servers...**, open the **X Docs** entry, and click **Add**. In the **Add to +Project** dialog, keep **Identity** set to **No Identity**, add no +**Upstream headers**, and click **Add to Project**. When the dialog offers a +**Guardrails** step, finish it or click **Skip for now**. After **Server +added successfully**, click **Configure MCP settings** to open the server. -This creates the hosted MCP server and opens its **Overview** page. - -Screenshot note: capture the **X Docs** catalog entry or the **Add to -Project** dialog; no credential values need redaction. +Screenshot note: the X Docs **Add to Project** dialog with **No Identity** +selected; no credential values need redaction. ### Connect your credentials {#connect-speakeasy-credentials} No credential connection is required because the X Docs MCP Server is public. -Do not add an upstream header or attach an identity provider. +The server's **Settings > Identity** section stays on **No Identity**. Screenshot exception: there is no credential form to complete for this open Authentication Option. @@ -93,38 +106,45 @@ None. - **Developer documentation:** `docs.x.com`, including the MCP overview at `https://docs.x.com/tools/mcp`, the MCP Server at `https://docs.x.com/mcp`, and the machine-readable index at - `https://docs.x.com/llms.txt`. The canonical documentation pages returned - HTTP 403 to the page fetch during this run; the same official MCP overview - and index were available from X's Mintlify preview property at - `https://x-preview.mintlify.app/`. + `https://docs.x.com/llms.txt`. On 2026-07-29 the canonical pages returned + HTTP 403 and the Mintlify preview property `https://x-preview.mintlify.app/` + was used instead; on 2026-09-30 the canonical pages returned HTTP 200 and + are now the cited locators. - **Developer product/admin documentation:** `developer.x.com` was swept. It returned HTTP 403 to the page fetch and is not needed for this public server, because X's MCP documentation requires no developer app or credential. - **Support KB:** `help.x.com` was swept. It returned HTTP 403 to the page fetch; no MCP-specific setup fact was drawn from it. -- **Speakeasy MCP Catalog:** the supplied tenant lookup reported a present - match for `com.pulsemcp.mirror/x-docs`, title `X Docs`. +- **Speakeasy MCP Catalog:** the catalog search on 2026-09-30 returned + `com.pulsemcp.mirror/x-docs`, title `X Docs`. - **Speakeasy product doctrine:** `doctrine/speakeasy-setup.md`, used for the fixed Speakeasy-side flow and anchors. ### Fact sources -- `https://docs.x.com/mcp` — observed `2026-07-29T20:05:42Z`. Official MCP +- `https://docs.x.com/mcp` — observed `2026-09-30T00:00:00Z` (re-probed; + first observed `2026-07-29T20:05:42Z`). Official MCP Server URL supplied by the operator and directly probed without credentials. Backs the remote URL, successful unauthenticated Streamable HTTP initialization, protocol version, server identity, and capabilities. -- `https://x-preview.mintlify.app/tools/mcp` (canonical page: - `https://docs.x.com/tools/mcp`) — observed `2026-07-29T20:05:42Z`. + The absent protected-resource metadata (404 at + `https://docs.x.com/.well-known/oauth-protected-resource/mcp`) was + observed the same day. +- `https://docs.x.com/tools/mcp` — observed `2026-09-30T00:00:00Z` + (first read from `https://x-preview.mintlify.app/tools/mcp` on + `2026-07-29T20:05:42Z`). Official X documentation. Backs the distinction between the Docs MCP and X API MCP servers, the Docs MCP purpose and URL, and its URL-only client configuration. -- `https://x-preview.mintlify.app/llms.txt` (canonical index: - `https://docs.x.com/llms.txt`) — observed `2026-07-29T20:05:42Z`. +- `https://docs.x.com/llms.txt` — observed `2026-09-30T00:00:00Z` (first + read from `https://x-preview.mintlify.app/llms.txt` on + `2026-07-29T20:05:42Z`). Official X documentation index. Backs the documentation-property sweep and primary MCP documentation locator. - Pulse registry key `com.pulsemcp.mirror/x-docs`, title `X Docs` — observed - `2026-07-29T20:05:42Z`; `source: pulsemcp`, mirror record. Backs catalog + `2026-09-30T00:00:00Z`; `source: pulsemcp`, mirror record. Backs catalog presence and the catalog-only add-server path. -- `doctrine/speakeasy-setup.md` — observed `2026-07-29T20:05:42Z`. Backs the - fixed `add-server-in-speakeasy` and `connect-speakeasy-credentials` anchors, - exact Speakeasy labels, catalog flow, and closing-pointer form. +- `doctrine/speakeasy-setup.md` (gram `main` `68b3f78`) — observed + `2026-09-30T00:00:00Z`. Backs the fixed `add-server-in-speakeasy` and + `connect-speakeasy-credentials` anchors, exact Speakeasy labels, catalog + flow with the **No Identity** choice, and closing-pointer form. diff --git a/guides/x-docs/speakeasy.md b/guides/x-docs/speakeasy.md index f5e86f3..88ea8eb 100644 --- a/guides/x-docs/speakeasy.md +++ b/guides/x-docs/speakeasy.md @@ -3,20 +3,20 @@ ### Add the server in Speakeasy {#add-server-in-speakeasy} 1. In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select **MCP**. -2. Click **Add new** to open the **Add MCP server** page. +2. Click **Add new** to open **Add MCP server**. 3. Choose **From the catalog**. 4. On the **MCP Catalog** page, enter `X Docs` in **Search MCP servers...**. -5. Open the **X Docs** entry. -6. Click **Add**. -7. In the **Add to Project** dialog, click **Add to Project**. +5. Open the **X Docs** entry and click **Add**. This opens the **Add to Project** dialog. +6. Under **Identity**, keep **No Identity** selected, and add no **Upstream headers**. +7. Click **Add to Project**. +8. If the dialog shows a **Guardrails** step, finish it or click **Skip for now**. +9. After **Server added successfully**, click **Configure MCP settings** to open the server. -After installation, select **Configure MCP settings** on the completion screen to open the server, then open **Settings**. - - + ### Connect your credentials {#connect-speakeasy-credentials} -No credential connection is required because the X Docs MCP Server is public. Do not add an upstream header or attach an identity provider. +X Docs is public, so there is no credential to connect. In the server's **Settings**, the **Identity** section stays on **No Identity**. diff --git a/guides/x/meta.yaml b/guides/x/meta.yaml index 0eb8186..43d3114 100644 --- a/guides/x/meta.yaml +++ b/guides/x/meta.yaml @@ -35,18 +35,18 @@ remotes: locator: https://docs.x.com/tools/mcp.md name: MCP servers for the X API and X developer docs classification: official - observed_at: "2026-08-06T23:21:18Z" + observed_at: "2026-09-30T00:00:00Z" provenance: - source: provider-documentation locator: https://docs.x.com/tools/mcp.md name: MCP servers for the X API and X developer docs classification: official - observed_at: "2026-08-06T23:21:18Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation locator: https://docs.x.com/llms.txt name: X Developer Platform documentation index classification: official - observed_at: "2026-08-06T23:21:18Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation locator: https://docs.x.com/x-api/getting-started/getting-access.md name: Getting Access @@ -91,9 +91,9 @@ provenance: locator: doctrine/speakeasy-setup.md name: Speakeasy setup canonical section classification: official - observed_at: "2026-08-06T23:21:18Z" + observed_at: "2026-09-30T00:00:00Z" - source: pulsemcp locator: com.pulsemcp.mirror/xdevplatform-xmcp name: X classification: mirror - observed_at: "2026-08-06T23:21:18Z" + observed_at: "2026-09-30T00:00:00Z" diff --git a/guides/x/research.md b/guides/x/research.md index 29a5f46..a860938 100644 --- a/guides/x/research.md +++ b/guides/x/research.md @@ -22,13 +22,19 @@ researched_at: 2026-08-06T23:21:18Z `@xdevplatform/xurl` stdio bridge. The bridge uses an X developer app's `CLIENT_ID` and `CLIENT_SECRET`, performs Authorization Code with PKCE, injects and refreshes Bearer tokens, and relays to the hosted URL. The - default registered callback is `http://localhost:8080/callback`. X states - that the MCP Server does not advertise native MCP OAuth discovery and that - there is no dynamic client registration. The Speakeasy AI Control Plane - canonical flow hosts a remote Streamable HTTP source; it cannot run this - local stdio bridge. Therefore this Guide does not offer the full OAuth - route as a connectable Authentication Option and does not ask for Client ID - or Client Secret. + default registered callback is `http://localhost:8080/callback`. X's MCP + page still states that the server does not advertise native MCP OAuth + discovery and that there is no dynamic client registration. A live probe + on 2026-09-30 shows the first half is stale: `https://api.x.com/mcp` + answers 401 with a `resource_metadata` challenge, and the protected-resource + metadata names issuer `https://api.x.com` (authorize + `https://x.com/i/oauth2/authorize`, token + `https://api.x.com/2/oauth2/token`). That issuer advertises neither a + `registration_endpoint` nor CIMD, so no client can be registered + automatically. X documents only the local `xurl` bridge for user-context + OAuth, and does not document a hosted-client callback. This Guide + therefore documents the app-only Bearer Token and does not ask for Client + ID or Client Secret. - **Authorization behavior:** an app-only token provides public-data reads only and cannot act as a user. X describes the hosted server as spanning search, users, bookmarks, trends, news, and Articles, but user-context @@ -61,7 +67,7 @@ Value the Speakeasy AI Control Plane needs: | Value | Origin | Speakeasy destination | | --- | --- | --- | -| Bearer Token | Generated for the new X app and shown with its credentials ({#copy-bearer-token}) | Static secret value for the `Authorization` upstream header, prefixed with `Bearer ` | +| Bearer Token | Generated for the new X app and shown with its credentials ({#copy-bearer-token}) | **Service Account** credential, format **Bearer**, field **Token** (raw token; the Bearer format adds the `Bearer ` prefix to the `Authorization` header) | There is no provider callback field in this app-only flow, so `{{ gram.oauth.callback_url }}` is not used. The OAuth callback @@ -109,9 +115,9 @@ route and must not be substituted into this Guide. organization's password manager or secure vault. X identifies this as the app-only credential for reading public data. This is a copy-now step; do not leave the view before saving the token. -- Destination: later enter this token in the Speakeasy AI Control Plane as the - secret static value `Bearer ` for an upstream header named - `Authorization`. +- Destination: later paste this token into **Token** under the **Service + Account** identity with the **Bearer** format in the Speakeasy AI Control + Plane. - Recovery: if the generated credential view was closed before the token was saved, reopen the app from the Developer Console dashboard, open **Keys and tokens**, and select **Regenerate** for the **Bearer Token**. Regeneration @@ -123,48 +129,67 @@ route and must not be substituted into this Guide. ## Speakeasy setup Per-guide values rendered into the canonical -`doctrine/speakeasy-setup.md` skeleton: +`doctrine/speakeasy-setup.md` skeleton (gram `main` `68b3f78`): - Provider: X. -- Remote URL: `https://api.x.com/mcp`. -- Transport: `streamable-http`; the **Transport** field is read-only. -- Catalog status: present. The Speakeasy MCP Catalog lookup matched - registry name `com.pulsemcp.mirror/xdevplatform-xmcp`, title `X`, for the - query `x`. Render only the catalog path; enter `X` in the catalog search +- Remote URL: `https://api.x.com/mcp` (shared public endpoint; not tenanted). +- Add-server path: `speakeasy_add_server: catalog`. The Speakeasy MCP Catalog + search for `X` on 2026-09-30 returned `com.pulsemcp.mirror/xdevplatform-xmcp`, + title `X`. Render only the catalog path; enter `X` in the catalog search box. -- Authentication Option: app-only Bearer Token (`api_key` in Metadata). -- Credential origin: **Bearer Token** from {#copy-bearer-token}. -- Upstream header: name `Authorization`; **Value source** **Static value**; - value `Bearer `; mark **Secret**. -- Further-reading URL: - `https://docs.x.com/tools/mcp`. +- Authentication Option: app-only Bearer Token (`api_key` in Metadata) → + identity mode **Service Account**, credential format **Bearer**. +- Credential origin: **Bearer Token** from {#copy-bearer-token}, pasted raw + into **Token**. The **Bearer** format supplies the `Bearer ` prefix, so the + reader must not type it (typing it produces `Bearer Bearer `). +- Probe outcome (2026-09-30): `POST https://api.x.com/mcp` `initialize` + without credentials → 401 with + `WWW-Authenticate: Bearer resource_metadata="https://api.x.com/.well-known/oauth-protected-resource"`. +- PRM issuer: `https://api.x.com`. PRM `scopes_supported`: `tweet.read + users.read follows.read space.read mute.read like.read list.read list.write + block.read block.write bookmark.read bookmark.write dm.read dm.write + developer.billing.write developer.write offline.access`. +- Issuer metadata (`https://api.x.com/.well-known/oauth-authorization-server`): + authorize `https://x.com/i/oauth2/authorize`, token + `https://api.x.com/2/oauth2/token`, token auth methods `none` and + `client_secret_basic`. No `registration_endpoint`, no + `client_id_metadata_document_supported`. Not used by this Guide. +- Registration choice: not applicable (Service Account, no OAuth client). +- Scope string: not applicable. +- Identity default at creation: the catalog dialog preselects **User + Identity** only when the entry supports OAuth client registration; X does + not, so the dialog starts on **No Identity**. The Guide tells readers to + select **Service Account** explicitly. +- Server Availability: not rendered. A Service Account credential entered at + creation does not leave the server **Disabled**. +- Further-reading URL: `https://docs.x.com/tools/mcp`. ### Add the server in Speakeasy {#add-server-in-speakeasy} -In the Speakeasy AI Control Plane sidebar, under **Connect**, select -**Sources**, then click **Add Source**. +In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select +**MCP**, then click **Add new** to open **Add MCP server**. Choose **From the +catalog**. On the **MCP Catalog** page, enter `X` in **Search MCP +servers...**, open the X catalog entry, and click **Add**. In the **Add to +Project** dialog, under **Identity**, select **Service Account**, select +**Bearer**, and paste the Bearer Token from {#copy-bearer-token} into +**Token** without a `Bearer ` prefix. Speakeasy sends it as the +`Authorization` header. Click **Add to Project**. When the dialog offers a +**Guardrails** step, finish it or click **Skip for now**. After **Server +added successfully**, click **Configure MCP settings** to open the server. -Choose **3rd-party server**. On the **MCP Catalog** page, enter `X` in -**Search MCP servers...**, open the X result with **View**, and click **Add**. -In the **Add to Project** dialog, click **Add to Project**. - -This creates the hosted MCP Server and opens its **Overview** page. - -Screenshot note: capture the X catalog entry with **View** and **Add** -visible. Do not include credentials. +Screenshot note: the X **Add to Project** dialog with **Service Account** and +**Bearer** selected; redact the token. ### Connect your credentials {#connect-speakeasy-credentials} -From the server's **Overview**, open **Settings**. Under **Upstream Headers**, -click **Add header**. Enter `Authorization` as **Header name**, leave -**Value source** as **Static value**, paste -`Bearer ` as the value, check **Secret**, -then click **Save**. If a catalog install collects headers in the -**Add to Project** dialog instead, use its **Upstream headers** section with -the same name, value, and secret setting. +Creation already configured the identity. To confirm it, or for an X server +created without the credential: open the server's **Settings**, find the +**Identity** section, select **Service Account**, fill **Service Account +credential** with format **Bearer** and the raw Bearer Token in **Token**, +and click **Save**. Do not add the token under **Custom Headers**. -Screenshot note: capture the **Upstream Headers** editor with -`Authorization`, **Static value**, and **Secret** visible; redact the value. +Screenshot note: **Settings > Identity** with **Service Account** and +**Bearer** selected; redact the token. This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see X's MCP documentation at @@ -197,17 +222,20 @@ limits — see X's MCP documentation at not a substitute for the primary MCP page. - **Speakeasy product doctrine:** `doctrine/speakeasy-setup.md`, read locally and used only for the fixed Speakeasy-side flow and anchors. +- **Live endpoint probes:** the remote URL and its OAuth metadata, probed + without credentials on 2026-09-30. ### Fact sources - `https://docs.x.com/tools/mcp.md` — observed - `2026-08-06T23:21:18Z`. Primary MCP source. Backs the X MCP URL, hosted + `2026-09-30T00:00:00Z` (re-verified; first observed + `2026-08-06T23:21:18Z`). Primary MCP source. Backs the X MCP URL, hosted Streamable HTTP transport, protocol/server information, direct app-only Bearer route, read-only limitation, `Authorization` header shape, local - `xurl mcp` OAuth route, no dynamic registration or native MCP OAuth - discovery, callback value, and the server's search, users, bookmarks, trends, + `xurl mcp` OAuth route, the documented (now stale) statement of no native + MCP OAuth discovery, no dynamic registration, callback value, and the server's search, users, bookmarks, trends, news, and Articles capability areas. Also supplies the further-reading URL. -- `https://docs.x.com/llms.txt` — observed `2026-08-06T23:21:18Z`. Backs the +- `https://docs.x.com/llms.txt` — observed `2026-09-30T00:00:00Z`. Backs the documentation-property sweep and discovery of the MCP, authentication, Developer Console, app, access, and pricing pages. - `https://docs.x.com/x-api/getting-started/getting-access.md` — observed @@ -244,10 +272,16 @@ limits — see X's MCP documentation at stdio-to-Streamable-HTTP bridge architecture, `CLIENT_ID` / `CLIENT_SECRET`, token caching and refresh, browser/headless behavior, and default `http://localhost:8080/callback`. -- `doctrine/speakeasy-setup.md` — observed `2026-08-06T23:21:18Z`. Backs the - fixed {#add-server-in-speakeasy} and {#connect-speakeasy-credentials} - anchors, exact Speakeasy labels, resolved catalog path, upstream-header +- `https://api.x.com/mcp`, `https://api.x.com/.well-known/oauth-protected-resource`, + and `https://api.x.com/.well-known/oauth-authorization-server` — live + probes observed `2026-09-30T00:00:00Z`. Back the 401 `resource_metadata` + challenge, the PRM issuer and scope list, the authorize and token + endpoints, and the absence of DCR and CIMD. +- `doctrine/speakeasy-setup.md` (gram `main` `68b3f78`) — observed + `2026-09-30T00:00:00Z`. Backs the fixed {#add-server-in-speakeasy} and + {#connect-speakeasy-credentials} anchors, exact Speakeasy labels, resolved + catalog path, the **Service Account** / **Bearer** / **Token** credential flow, and closing pointer form. - Speakeasy MCP Catalog record `com.pulsemcp.mirror/xdevplatform-xmcp` - (title `X`) — observed `2026-08-06T23:21:18Z`, `source: pulsemcp`. Backs + (title `X`) — observed `2026-09-30T00:00:00Z`, `source: pulsemcp`. Backs catalog presence and the catalog-only add-server path. diff --git a/guides/x/speakeasy.md b/guides/x/speakeasy.md index e460d2e..eaa9f36 100644 --- a/guides/x/speakeasy.md +++ b/guides/x/speakeasy.md @@ -2,26 +2,32 @@ ### Add the server in Speakeasy {#add-server-in-speakeasy} -In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select **MCP**, then click **Add new** to open the **Add MCP server** page. - -Choose **From the catalog**. On the **MCP Catalog** page, enter `X` in **Search MCP servers...**, open the X result, and click **Add**. If the **Add to Project** dialog requests headers during installation, enter `Bearer ` followed by your saved [**Bearer Token**](external.md#copy-bearer-token) in the provided `Authorization` value field under **Upstream headers**. The dialog supplies the header name and secret handling; it does not show the Settings editor's controls. If no header field is offered, follow [Connect your credentials](#connect-speakeasy-credentials) after installation. In the **Add to Project** dialog, click **Add to Project**. - -After installation, select **Configure MCP settings** on the completion screen to open the server, then open **Settings**. - - +1. In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select **MCP**. +2. Click **Add new** to open **Add MCP server**. +3. Choose **From the catalog**. +4. On the **MCP Catalog** page, enter `X` in **Search MCP servers...**. +5. Open the X catalog entry and click **Add**. This opens the **Add to Project** dialog. +6. Under **Identity**, select **Service Account**. +7. Select **Bearer**. +8. In **Token**, paste the [**Bearer Token**](external.md#copy-bearer-token) you saved. Paste the token only, without `Bearer ` in front of it. Speakeasy adds the prefix and sends the value as the `Authorization` header. +9. Click **Add to Project**. +10. If the dialog shows a **Guardrails** step, finish it or click **Skip for now**. +11. After **Server added successfully**, click **Configure MCP settings** to open the server. + + ### Connect your credentials {#connect-speakeasy-credentials} -If you configured headers in the **Add to Project** dialog, skip this section. Otherwise, select **Configure MCP settings** on the completion screen: +The Bearer Token you entered in the **Add to Project** dialog is already the server's credential. To confirm it, or to add it to an X server created without it: + +1. Open the server's **Settings** and find the **Identity** section. +2. Select **Service Account**. +3. Under **Service Account credential**, select **Bearer**. +4. In **Token**, paste the [**Bearer Token**](external.md#copy-bearer-token), without `Bearer ` in front of it. +5. Click **Save**. -1. Open **Settings**. -2. Under **Upstream Headers**, select **Add header**. -3. Enter `Authorization` in **Header name**. -4. Leave **Value source** set to **Static value**. -5. In the value field, enter `Bearer ` followed by the [**Bearer Token**](external.md#copy-bearer-token) you saved. -6. Select **Secret**. -7. Select **Save**. +Do not add the token under **Custom Headers**. - + This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [X's MCP documentation](https://docs.x.com/tools/mcp). diff --git a/guides/zapier/meta.yaml b/guides/zapier/meta.yaml index b3601d6..00d8e63 100644 --- a/guides/zapier/meta.yaml +++ b/guides/zapier/meta.yaml @@ -34,7 +34,7 @@ provenance: observed_at: "2026-08-11T18:36:07Z" - source: provider-documentation locator: https://docs.zapier.com/mcp/get-started/connect - observed_at: "2026-08-11T18:36:07Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation locator: https://docs.zapier.com/mcp/get-started/authentication observed_at: "2026-08-11T18:36:07Z" @@ -46,22 +46,22 @@ provenance: observed_at: "2026-08-11T18:36:07Z" - source: provider-documentation locator: https://docs.zapier.com/mcp/features/usage - observed_at: "2026-08-11T18:36:07Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation locator: https://docs.zapier.com/mcp/manage/security - observed_at: "2026-08-11T18:36:07Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation locator: https://help.zapier.com/hc/en-us/articles/36265392843917-Use-Zapier-MCP-with-your-client observed_at: "2026-08-11T18:36:07Z" - source: provider-documentation locator: https://mcp.zapier.com/api/v1/connect - observed_at: "2026-08-11T18:36:07Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation locator: https://mcp.zapier.com/.well-known/oauth-protected-resource/api/v1/connect - observed_at: "2026-08-11T18:36:07Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation locator: https://mcp.zapier.com/.well-known/oauth-authorization-server - observed_at: "2026-08-11T18:36:07Z" + observed_at: "2026-09-30T00:00:00Z" - source: provider-documentation locator: https://zapier.com/llms.txt observed_at: "2026-08-11T18:36:07Z" @@ -70,4 +70,4 @@ provenance: observed_at: "2026-08-11T18:36:07Z" - source: doctrine locator: doctrine/speakeasy-setup.md - observed_at: "2026-08-11T18:36:07Z" + observed_at: "2026-09-30T00:00:00Z" diff --git a/guides/zapier/research.md b/guides/zapier/research.md index 2042d63..18ccfd5 100644 --- a/guides/zapier/research.md +++ b/guides/zapier/research.md @@ -60,7 +60,9 @@ The Speakeasy AI Control Plane can discover OAuth from the remote: `https://mcp.zapier.com/api/v1/oauth/register` as its DCR endpoint and advertises the `openid`, `profile`, and `email` scopes. 4. The Speakeasy AI Control Plane registers and retains the resulting OAuth - client details. The reader does not paste `{{ gram.oauth.callback_url }}` + client details (**Auto-Configure**; the issuer advertises DCR only, no + CIMD). An anonymous DCR registration probe on `2026-09-30` returned HTTP + 201 with a `client_id`. The reader does not paste `{{ gram.oauth.callback_url }}` into Zapier and does not handle the generated client ID or secret. 5. When provider access is first requested, the intended user signs in to Zapier and completes Zapier's browser authorization prompts. Their own @@ -76,7 +78,7 @@ Authentication Option selected for this catalog Guide. There is no provider-side console walkthrough before adding the catalog server. The selected DCR path creates no credential in `mcp.zapier.com`; provider sign-in and authorization happen on demand after the Speakeasy-side identity -provider is attached. Consequently, there are no provider-step anchors or +provider is configured. Consequently, there are no provider-step anchors or provider screenshots to mint. Screenshot exception: there is no provider console state in the pre-connection path. @@ -87,55 +89,68 @@ MCP connection itself. ## Speakeasy setup +Canonical source: `doctrine/speakeasy-setup.md` (gram `main` `68b3f78`), +observed `2026-09-30`. + Per-guide values: -- Remote URL: `https://mcp.zapier.com/api/v1/connect` -- Transport: `streamable-http` -- Authentication Option: OAuth with DCR (`oauth-dcr`) +- Remote URL: `https://mcp.zapier.com/api/v1/connect` (shared, not tenanted) +- `speakeasy_add_server`: `catalog`; catalog lookup present, matched + registry `com.pulsemcp.mirror/zapier`, title **Zapier** +- Authentication Option: OAuth with DCR (`oauth-dcr`). Identity mode: + **User Identity** - External credential fields: none -- OAuth discovery: available through protected-resource and authorization - server metadata; no Issuer URL needs to be pasted manually -- Scopes: discovered as `openid`, `profile`, and `email`; no scope override - should be entered -- Catalog lookup: present; matched registry - `com.pulsemcp.mirror/zapier`, title **Zapier** -- Further reading: - `https://docs.zapier.com/mcp/get-started/connect` +- Probe outcome (`2026-09-30`): JSON-RPC `initialize` POST returns 401 with + `WWW-Authenticate: Bearer + resource_metadata="https://mcp.zapier.com/.well-known/oauth-protected-resource/api/v1/connect"` +- PRM issuer: `https://mcp.zapier.com`; PRM `scopes_supported`: `openid`, + `profile`, `email` +- CIMD / DCR: no `client_id_metadata_document_supported`; registration + endpoint `https://mcp.zapier.com/api/v1/oauth/register`; anonymous DCR + returned 201 +- Registration choice: **Auto-Configure** (DCR, the only method offered). + The catalog entry supports client registration, so **Add to Project** + preselects **User Identity** and creation normally configures the + identity; the credential section is a confirmation plus the fallback +- Scope: none entered; **Auto-Configure** has no **Scope** control +- Server Availability: rendered as a conditional final step when creation + left the server **Disabled** +- Further reading: `https://docs.zapier.com/mcp/get-started/connect` ### Add the server in Speakeasy {#add-server-in-speakeasy} -In the Speakeasy AI Control Plane sidebar, under **Connect**, select -**Sources**, then click **Add Source**. Choose **3rd-party server**. On the -**MCP Catalog** page, find Zapier using **Search MCP servers...**, open its -entry with **View**, and click **Add**. In the **Add to Project** dialog, click -**Add to Project**. This creates the hosted MCP server and opens its -**Overview** page. +In the Speakeasy AI Control Plane sidebar, under **MCP Gateway**, select +**MCP**, then click **Add new** to open **Add MCP server**. Choose **From the +catalog**. On the **MCP Catalog** page, find Zapier using **Search MCP +servers...**, open its catalog entry, and click **Add**. In **Add to +Project**, keep **User Identity**, then click **Add to Project** (click +**Skip for now** if a **Guardrails** step appears). After **Server added +successfully**, click **Configure MCP settings**. + +Speakeasy registers a client with Zapier automatically. There is no +**Client ID** or secret to paste. If that cannot complete, the server is +kept **Disabled** and the result says to finish setup in **Settings > +Identity**. -Screenshot note: capture the **Add Source** menu open on the **Sources** page, -or the Zapier catalog entry. +Screenshot note: the Zapier catalog entry with the **Identity** choice. ### Connect your credentials {#connect-speakeasy-credentials} -From the server's **Overview**, open **Settings**. Under **Authentication**, -use **Use Discovered** when offered; otherwise click **Configure Manually**. -In the **Attach Remote Identity Provider** sheet, Zapier's protected-resource -metadata allows discovery without a pasted issuer. Keep the auto-derived -**Slug** and **Display name (optional)**. Under **Endpoints**, click -**Discover** so the authorization, token, and registration endpoints fill -from Zapier's authorization-server metadata. Under **Session Client**, keep -**Client Type** set to **Dynamic Client Registration (DCR)** and keep **Token -Endpoint Auth Method** at its discovered default. Leave **Scope (override)** -and **Audience (optional)** empty. Click **Attach Identity Provider**. - -The Speakeasy AI Control Plane registers the OAuth client with Zapier. There is -no **Client ID** or **Client Secret** for the reader to paste and no provider -callback field to configure. When provider access is first needed, complete -Zapier's on-screen browser sign-in and authorization prompts with the account -whose app connections should be available. - -Screenshot note: capture the **Attach Remote Identity Provider** sheet after -discovery, showing **Dynamic Client Registration (DCR)** and the discovered -endpoints, with any account-specific values redacted. +Open the server's **Settings** and find the **Identity** section. Creation +normally already shows **User Identity**, the `https://mcp.zapier.com` +provider, and **Auto-Configure**; keep only the Server Availability step. +Otherwise: select **User Identity**, confirm the preselected provider is +`https://mcp.zapier.com` (a new one is badged **Will be created**), keep +**Auto-Configure**, and click **Save**. If the server shows **Disabled**, +open **Settings > Danger Zone > Server Availability** and turn on **Enable +MCP server** so it shows **Enabled**. + +When provider access is first needed, complete Zapier's on-screen browser +sign-in and authorization prompts with the account whose app connections +should be available. + +Screenshot note: **Settings > Identity** with **User Identity** selected, +the Zapier provider, and **Auto-Configure**; values redacted. The closing pointer is: This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see Zapier's MCP documentation at @@ -144,13 +159,17 @@ https://docs.zapier.com/mcp/get-started/connect. ## Open questions - Zapier's public documentation does not publish the exact labels or content - of the browser sign-in and authorization prompts presented after DCR. The + of the browser sign-in and authorization prompts presented after + registration. The Setup Guide should direct the reader to complete Zapier's on-screen prompts without inventing labels. - Zapier has not reconciled its direct-connect page with its server-creation quickstart and support pages. The direct DCR route is selected from live - discovery metadata, but it was not completed end to end because doing so - requires registering a client and authorizing a Zapier account. + discovery metadata. Anonymous registration succeeds (201 on + `2026-09-30`), but the browser authorization was not completed end to end + because that requires authorizing a Zapier account. As of `2026-09-30` + the connect page states "Zapier creates and configures the server during + that sign-in", which supports the direct path. ## Provenance @@ -169,7 +188,8 @@ https://docs.zapier.com/mcp/get-started/connect. positioning. - Support knowledge base: `https://help.zapier.com/hc/en-us`. Used to compare the older server/token setup path and confirm plan availability. -- Speakeasy setup doctrine: `doctrine/speakeasy-setup.md`. Used for the fixed +- Speakeasy setup doctrine: `doctrine/speakeasy-setup.md` (gram `main` + `68b3f78`). Used for the fixed Speakeasy-side flow, labels, and anchors. ### Source records @@ -178,8 +198,8 @@ https://docs.zapier.com/mcp/get-started/connect. `2026-08-11T18:36:07Z`; documentation-property sweep and current MCP page inventory. - `https://docs.zapier.com/mcp/get-started/connect` — observed - `2026-08-11T18:36:07Z`; shared remote URL, Streamable HTTP, no SSE, - direct OAuth connection, and no-server-setup statement. + `2026-09-30`; shared remote URL, Streamable HTTP, no SSE, + direct OAuth connection, and server created during sign-in. - `https://docs.zapier.com/mcp/get-started/authentication` — observed `2026-08-11T18:36:07Z`; documented authentication alternatives and the older connection-token path. @@ -190,10 +210,10 @@ https://docs.zapier.com/mcp/get-started/connect. `2026-08-11T18:36:07Z`; dynamic discovery, OAuth auto-provisioning, ownership limitation for app connections, and manual-mode distinction. - `https://docs.zapier.com/mcp/features/usage` — observed - `2026-08-11T18:36:07Z`; task billing, non-billable setup/authentication, + `2026-09-30`; task billing, non-billable setup/authentication, and task-limit behavior. - `https://docs.zapier.com/mcp/manage/security` — observed - `2026-08-11T18:36:07Z`; default account enablement, workspace controls, + `2026-09-30`; default account enablement, workspace controls, user permissions, and account-level restrictions. - `https://zapier.com/llms.txt` — observed `2026-08-11T18:36:07Z`; product-property sweep and pointer to the developer documentation index. @@ -203,16 +223,18 @@ https://docs.zapier.com/mcp/get-started/connect. — observed `2026-08-11T18:36:07Z`; support-site requirements, all-plan availability, and the older unlisted-client token flow. - `https://mcp.zapier.com/api/v1/connect` — observed - `2026-08-11T18:36:07Z`; live `401` response and RFC 9728 + `2026-09-30`; live `401` response and RFC 9728 `WWW-Authenticate` challenge. - `https://mcp.zapier.com/.well-known/oauth-protected-resource/api/v1/connect` - — observed `2026-08-11T18:36:07Z`; resource identifier, authorization + — observed `2026-09-30`; resource identifier, authorization server, and supported scopes. - `https://mcp.zapier.com/.well-known/oauth-authorization-server` — observed - `2026-08-11T18:36:07Z`; issuer, OAuth endpoints, DCR endpoint, grants, - token authentication methods, PKCE methods, and scopes. + `2026-09-30`; issuer, OAuth endpoints, DCR endpoint (anonymous + registration returned 201), no CIMD, grants, token authentication methods, + PKCE methods, and scopes. - Pulse MCP Catalog record `com.pulsemcp.mirror/zapier`, title `Zapier` — observed `2026-08-11T18:36:07Z`; catalog presence and catalog add-server path. Source: `pulsemcp`. -- `doctrine/speakeasy-setup.md` — observed `2026-08-11T18:36:07Z`; fixed - Speakeasy-side flow, labels, screenshot notes, and anchors. +- `doctrine/speakeasy-setup.md` (gram `main` `68b3f78`) — observed + `2026-09-30`; fixed Speakeasy-side flow, **Identity** labels, + **Auto-Configure**, Server Availability, screenshot notes, and anchors. diff --git a/guides/zapier/speakeasy.md b/guides/zapier/speakeasy.md index 822ea0e..b26f467 100644 --- a/guides/zapier/speakeasy.md +++ b/guides/zapier/speakeasy.md @@ -8,71 +8,26 @@ 4. On the **MCP Catalog** page, enter `Zapier` in **Search MCP servers...**. 5. Open the **Zapier** entry. 6. Select **Add**. -7. In the **Add to Project** dialog, select **Add to Project**. +7. In the **Add to Project** dialog, under **Identity**, keep **User Identity** selected. +8. Select **Add to Project**. If the dialog offers a **Guardrails** step, select **Skip for now**. +9. After **Server added successfully**, select **Configure MCP settings**. -After installation, select **Configure MCP settings** on the completion screen to open the server, then open **Settings**. +When it adds the server, Speakeasy discovers Zapier's identity provider and registers a client automatically. There is no **Client ID** or secret to paste. If that cannot complete, the server is kept **Disabled** and the result says to finish setup in **Settings > Identity**. - + ### Connect your credentials {#connect-speakeasy-credentials} -Select **Configure MCP settings** on the completion screen, then open the server’s **Settings**. +Open the server's **Settings** and find the **Identity** section. It normally shows **User Identity** with the `https://mcp.zapier.com` provider and **Auto-Configure** already set; skip to step 5. -Under **Authentication**, if unconfigured, select **Use Discovered** when available; otherwise select **Configure Manually**. If configured but no provider is attached, use **Connected services > Add provider**. If the intended provider is already attached, use its existing controls and skip the provider/client creation and attachment steps below; do not add a duplicate. +1. Select **User Identity**. +2. Under **Choose an identity provider**, confirm the preselected provider is `https://mcp.zapier.com`. A provider that does not exist yet shows **Will be created**. +3. Keep **Auto-Configure** selected. +4. Select **Save**. +5. If the server shows **Disabled**, open **Settings > Danger Zone > Server Availability** and turn on **Enable MCP server** so it shows **Enabled**. -#### Select the identity provider +When a person first uses the server, they sign in to Zapier with the account whose app connections should be available and complete Zapier's on-screen authorization prompts. -In **Attach Remote Identity Provider**, **Identity Provider** defaults to **Select existing** when project issuers are available. Select the matching provider and skip the new-provider fields below. Otherwise choose **Add new** (or use the new-provider form shown when none exist). - -For a new provider only, confirm **Issuer URL**, the auto-derived **Slug**, and **Endpoints**. Discovery runs automatically for a seeded issuer; after typing or changing the URL, select **Discover** only if offered. - -For a new provider, enter **Issuer URL** `https://mcp.zapier.com` and keep the auto-derived **Slug**. If discovery does not populate **Endpoints**, enter: - -Authorization endpoint: - -```text -https://mcp.zapier.com/oauth/authorize -``` - -Token endpoint: - -```text -https://mcp.zapier.com/api/v1/oauth/token -``` - -Registration endpoint: - -```text -https://mcp.zapier.com/api/v1/oauth/register -``` - - - -1. Keep the auto-derived **Slug**. -1. Keep the auto-derived **Display name (optional)**. -1. Under **Endpoints**, wait for automatic discovery of the seeded issuer. After typing or changing **Issuer URL**, select **Discover** only if offered, then confirm the authorization, token, and registration endpoints. - -#### Select the session client - -Under **Session Client**, choose **Select existing** only for a client whose saved credentials, scopes, and audience match the requirements below; otherwise choose **Add new**. When reusing a matching client, skip directly to **Attach the provider** below. Do not create credentials or register the client again. Otherwise choose **Add new** (or use the new-client form shown when no clients exist) and complete these new-client-only steps: - -1. Under **Session Client**, keep **Client Type** set to **Dynamic Client - Registration (DCR)**. -1. Keep **Token Endpoint Auth Method** at its discovered default. -1. Leave **Scope (override)** empty. -1. Leave **Audience (optional)** empty. - -#### Attach the provider - -Click **Attach Identity Provider**. DCR handles client registration; you do not need to register a callback URL manually. - -For a new DCR client, the Speakeasy AI Control Plane registers the OAuth client with Zapier. You do -not need to paste a **Client ID** or **Client Secret**. - -1. When provider access is first requested, sign in to Zapier with the account - whose app connections should be available. -2. Complete Zapier's on-screen authorization prompts. - - + This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Zapier's MCP documentation](https://docs.zapier.com/mcp/get-started/connect).