Rewrite Notion MCP guide for Kubernetes remote proxy support#1004
Merged
Conversation
The K8s tab claimed the operator doesn't support remote MCP servers with OAuth, which hasn't been true for a long time. Replace the static-integration-key workaround with a verified MCPRemoteProxy + embedded authorization server setup. Notion's remote MCP server only supports Dynamic Client Registration for third-party OAuth clients, so the guide walks through minting persistent credentials via DCR instead of a dashboard app. Callouts cover two gotchas found while verifying this end to end: the issuer field must stay path-free, and the upstream redirectUri default computed from resourceUrl breaks once resourceUrl has a path.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
There was a problem hiding this comment.
Pull request overview
Updates the Notion remote MCP server guide to correct Kubernetes guidance and document a working remote-proxy + embedded authorization server flow, including Dynamic Client Registration (DCR) for Notion’s OAuth client credentials.
Changes:
- Replaces the prior “static integration key” Kubernetes workaround with an
MCPRemoteProxy+MCPExternalAuthConfig(embedded auth server) setup. - Adds a DCR-based “mint persistent client credentials” step and expands Kubernetes-specific operational/troubleshooting guidance around sessions and OAuth flow debugging.
- Updates recommended practices/troubleshooting to reflect the embedded-auth-server session model and points external exposure guidance at
connect-clients.mdx.
Rephrase four spaced-hyphen sentence separators per the style guide.
Clarify why this guide sets redirectUri explicitly instead of relying
on the documented {resourceUrl}/oauth/callback default: that default
only works for a bare-host resourceUrl, and breaks once resourceUrl
has a path (as it does here), since the callback route is only ever
served at the host root. Cross-references the relevant auth-k8s.mdx
section instead of leaving the divergence unexplained.
danbarr
added a commit
that referenced
this pull request
Jul 6, 2026
Split the 1,492-line guides-k8s/auth-k8s.mdx into a scenario-first entry point plus two focused pages: embedded-auth-server-k8s.mdx and authorization-k8s.mdx. Remove the front-loaded five-approach picker and the vestigial legacy ConfigMap section, pointing instead to the existing migrate-to-v1beta1.mdx guidance for that upgrade path. Add the issuer-must-be-path-free and redirectUri callouts learned from PR #1004 to the new embedded auth server page and to concepts/embedded-auth-server.mdx. Trim the duplicate backend-pattern decision table out of embedded-auth-server.mdx, and note that vMCP's incoming/outgoing terminology maps to MCPServer's frontend/backend in auth-framework.mdx. Tighten the header-forwarding wording in remote-mcp-proxy.mdx to list the full disallowed-header set and clarify User-Agent isn't blocked. Correct the OIDC prerequisites partial and the CLI auth examples: only the issuer is required, JWKS is auto-discovered, and client ID only matters for introspection-based providers. Update sidebars.ts and cross-references across the files that linked to anchors which moved. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
7 tasks
danbarr
added a commit
that referenced
this pull request
Jul 7, 2026
) * Restructure K8s auth guide, dedup concept docs Split the 1,492-line guides-k8s/auth-k8s.mdx into a scenario-first entry point plus two focused pages: embedded-auth-server-k8s.mdx and authorization-k8s.mdx. Remove the front-loaded five-approach picker and the vestigial legacy ConfigMap section, pointing instead to the existing migrate-to-v1beta1.mdx guidance for that upgrade path. Add the issuer-must-be-path-free and redirectUri callouts learned from PR #1004 to the new embedded auth server page and to concepts/embedded-auth-server.mdx. Trim the duplicate backend-pattern decision table out of embedded-auth-server.mdx, and note that vMCP's incoming/outgoing terminology maps to MCPServer's frontend/backend in auth-framework.mdx. Tighten the header-forwarding wording in remote-mcp-proxy.mdx to list the full disallowed-header set and clarify User-Agent isn't blocked. Correct the OIDC prerequisites partial and the CLI auth examples: only the issuer is required, JWKS is auto-discovered, and client ID only matters for introspection-based providers. Update sidebars.ts and cross-references across the files that linked to anchors which moved. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Trim boilerplate, nest auth pages under a category Remove the "authentication is emerging" admonition from the K8s and CLI auth guides; the spec has had a stable dated release for a while, and client-support caveats belong closer to where they matter, not a blanket disclaimer up top. Trim the Prerequisites sections on the three K8s auth pages down to what's actually specific to each page, dropping the boilerplate cluster/kubectl/operator bullets already established earlier in the section. Reorder the K8s sidebar so token-exchange-k8s sits with the other auth-adjacent pages instead of after Redis/rate-limiting, and nest all four under a new "Authentication and authorization" category (auth-k8s.mdx as the landing page), matching the existing "Permissions and security" and "Deploy the Registry Server" category patterns elsewhere in the sidebar. Add short sidebar_label overrides to the two new pages so their labels match their neighbors. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Fix client ID/secret framing in OIDC prerequisites Client ID isn't operator-invented like audience is; when it's needed, the provider issues it on app registration. Reframe around whether it's required, not where it comes from, and pair it with client secret since both travel together for introspection-based providers. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Trim token exchange prereqs, note Entra OBO is Enterprise Drop the same cluster/kubectl/operator boilerplate from the Prerequisites section as the other auth pages. Add an enterprise callout: Entra ID doesn't implement RFC 8693 token exchange, only its own RFC 7523-based on-behalf-of flow, which Stacklok Enterprise supports via a dedicated obo auth type. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Extract IdP token exchange setup into a shared partial The "Configure your identity provider" steps (register a client, define audience/scopes, create an access policy) were duplicated between the CLI and K8s token exchange guides, with K8s punting to the CLI page for the actual steps. Since it's pure IdP-side configuration with nothing CLI-specific in it, extract it to _configure-token-exchange-idp.mdx and embed it directly in both, matching the existing pattern for shared auth content. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Add diagrams showing CRD relationships Signed-off-by: Dan Barr <6922515+danbarr@users.noreply.github.com> * Cross-link backend federation options from each other auth-k8s.mdx never mentioned AWS STS, so a reader starting at the entry point had no way to discover it short of clicking into a child page. Add it alongside token exchange in Next steps. token-exchange-k8s.mdx didn't point to the "combine with embedded auth server" pattern that already existed on the embedded-auth-server page, so that combination was undiscoverable from the token exchange side. Add the missing link back. The combine section itself only showed AWS STS in its worked example even though the same authServerRef + externalAuthConfigRef pattern works identically for plain RFC 8693 token exchange. Generalize the wording and YAML, and link both paths. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Cut vestigial section, fix mismatched heading framing "Benefits of MCPOIDCConfig" was written as a comparison against inline oidcConfig, which no longer exists as an option since v0.21.0. Its still-accurate bullets (validation, status tracking, lifecycle) were retrospective justification for a resource the reader already created, not something that helps them do anything next. Cut it. "Run an embedded OAuth server for spec-compliant clients" mismatched the section's own body text, which correctly frames the reason as no federation relationship with the IdP, not client compliance. Drop the qualifier and match the plain action-phrase style of its sibling headings. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Move CIMD/DCR config into the how-to, promote CIMD ordering The concept doc's CIMD and baseline-scopes sections carried the actual YAML config, field defaults, and document validation rules, while the how-to guide only had a one-row table summary that bounced readers out to concepts for the mechanics. Move the real configuration (YAML blocks, cache defaults, validation rules) into embedded-auth-server-k8s.mdx as two proper subsections, and trim the concept doc back to the why (registration friction, the two-layer trust architecture) with forward links into the how-to. Also promote CIMD above DCR/baseline-scopes in both files' section ordering, matching the MCP spec's stated preference (CIMD preferred, DCR is the backward-compatibility fallback) and the ordering already used everywhere else in the concept doc that lists both side by side. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Surface backend auth decision on the main K8s auth page auth-k8s.mdx only discussed frontend (client-to-proxy) auth; backend auth (MCP server/proxy-to-backend) wasn't mentioned until a single Next steps bullet at the bottom. Add a "Choose a backend authentication pattern" section mirroring the decision table in concepts/backend-auth.mdx, giving both axes equal up-front billing. Static credentials route to the actual common path (spec.secrets env vars, Vault) plus the narrower MCPRemoteProxy header-forwarding case, rather than only the proxy-level option. The MCPExternalAuthConfig headerInjection/bearerToken gap for MCPServer is tracked in #1013. Also add a CRD reference cross-link to embedded-auth-server-k8s.mdx, closing out the last open item from #866. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Fix issues found by independent editorial review Fix a broken sentence in the "First consent only" Google callout. Trim the concept doc's new "issuer must be a bare host" section down to a pointer into the how-to guide, which already carries the same explanation almost verbatim - the one place this diff grew new duplication instead of removing it. Import the shared auth-troubleshooting partial into authorization-k8s.mdx so the 403 guidance auth-k8s.mdx points readers to is actually there. Note the entities_json/entitiesJson casing difference between the ConfigMap and inline authzConfig contexts, and reword an ambiguous "always required" claim about oidcConfigRef. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Address Copilot review findings Fix placeholder inconsistency in guides-cli/auth.mdx: embedded full URLs and lowercase names inside angle brackets, unlike the <YOUR_X> convention used everywhere else. Scope the OIDC prerequisites partial: the issuer-lookup guidance only applies to external IdPs, not Kubernetes service account auth, where there's nothing to look up. Set redirectUri explicitly in embedded-auth-server-k8s.mdx's two main upstream-provider examples. Both omitted it while resourceUrl (set in Step 5) includes a path, which is exactly the broken combination the page's own later warning describes - the primary walkthrough wasn't actually copy-paste-safe. Fix the real source of the MCPAuthzConfig walkthrough link: scripts/lib/crd-intros.mjs, not just the generated .mdx, which would have reverted on the next CRD doc regeneration. Use conventional header casing (TE, HTTP2-Settings, X-Real-IP) in the disallowed-header list; HTTP header names are case-insensitive so this doesn't change behavior, just readability. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Signed-off-by: Dan Barr <6922515+danbarr@users.noreply.github.com> Co-authored-by: Dan Barr <6922515+danbarr@users.noreply.github.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
jhrozek
reviewed
Jul 8, 2026
jhrozek
previously approved these changes
Jul 8, 2026
Replace the manual client registration curl step and static client secret with the embedded auth server's dcrConfig field, which registers a client with Notion automatically at startup. Verified end to end against a real cluster: the proxy performed live DCR registration against Notion and a real client connected through it. Also flag that DCR credentials share the session store, so a pod restart without Redis-backed storage re-registers a new client with Notion instead of just re-authenticating.
Drop the "only supports DCR... unlike classic API integrations" framing and shorten the issuer path-free note, which repeated the same reasoning twice.
jhrozek
approved these changes
Jul 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The Kubernetes tab claimed the ToolHive operator doesn't support remote MCP servers with OAuth, which hasn't been true for a long time. Replaced the static-integration-key workaround with a verified
MCPRemoteProxy+ embedded authorization server setup.Notion's remote MCP server only supports Dynamic Client Registration for third-party OAuth clients, so the guide walks through minting persistent credentials via DCR instead of a dashboard app. Two callouts cover gotchas found while verifying this end to end against a real cluster and a real Notion account: the
issuerfield must stay path-free, and the upstreamredirectUridefault computed fromresourceUrlbreaks onceresourceUrlhas a path.Also updated the Overview, Recommended Practices, and Troubleshooting sections to reflect the embedded-auth-server session model instead of a bare pass-through, and pointed the "expose the proxy externally" reference at the more complete
connect-clients.mdxguide instead of a thinner duplicate section.Type of change
Related issues/PRs
N/A
Screenshots
N/A - no visual or sidebar changes.
Submitter checklist
Content and formatting
Reviewer checklist
Content