zuplo 6.70.53 → 6.70.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/docs/mcp-gateway/auth/configuring-auth0.mdx +216 -0
  2. package/docs/mcp-gateway/auth/configuring-clerk.mdx +153 -0
  3. package/docs/mcp-gateway/auth/configuring-cognito.mdx +128 -0
  4. package/docs/mcp-gateway/auth/configuring-entra.mdx +134 -0
  5. package/docs/mcp-gateway/auth/configuring-generic-oidc.mdx +242 -0
  6. package/docs/mcp-gateway/auth/configuring-google.mdx +117 -0
  7. package/docs/mcp-gateway/auth/configuring-keycloak.mdx +125 -0
  8. package/docs/mcp-gateway/auth/configuring-logto.mdx +116 -0
  9. package/docs/mcp-gateway/auth/configuring-okta.mdx +199 -0
  10. package/docs/mcp-gateway/auth/configuring-onelogin.mdx +122 -0
  11. package/docs/mcp-gateway/auth/configuring-ping.mdx +157 -0
  12. package/docs/mcp-gateway/auth/configuring-workos.mdx +117 -0
  13. package/docs/mcp-gateway/auth/manual-oauth-testing.mdx +528 -0
  14. package/docs/mcp-gateway/auth/overview.mdx +314 -0
  15. package/docs/mcp-gateway/auth/upstream-oauth.mdx +221 -0
  16. package/docs/mcp-gateway/capability-filtering.mdx +162 -0
  17. package/docs/mcp-gateway/code-config/compatibility-dates.mdx +33 -0
  18. package/docs/mcp-gateway/code-config/local-development.mdx +198 -0
  19. package/docs/mcp-gateway/code-config/mcp-proxy-handler.mdx +186 -0
  20. package/docs/mcp-gateway/code-config/multi-upstream.mdx +293 -0
  21. package/docs/mcp-gateway/code-config/overview.mdx +210 -0
  22. package/docs/mcp-gateway/connect-clients/chatgpt.mdx +127 -0
  23. package/docs/mcp-gateway/connect-clients/claude-code.mdx +184 -0
  24. package/docs/mcp-gateway/connect-clients/claude-desktop.mdx +160 -0
  25. package/docs/mcp-gateway/connect-clients/cursor.mdx +100 -0
  26. package/docs/mcp-gateway/connect-clients/other-clients.mdx +207 -0
  27. package/docs/mcp-gateway/connect-clients/overview.mdx +137 -0
  28. package/docs/mcp-gateway/connect-clients/vs-code.mdx +128 -0
  29. package/docs/mcp-gateway/how-it-works.mdx +266 -0
  30. package/docs/mcp-gateway/how-to/connect-upstream-oauth.mdx +268 -0
  31. package/docs/mcp-gateway/how-to/curate-tools.mdx +278 -0
  32. package/docs/mcp-gateway/introduction.mdx +151 -0
  33. package/docs/mcp-gateway/observability/analytics.mdx +191 -0
  34. package/docs/mcp-gateway/observability/logging.mdx +191 -0
  35. package/docs/mcp-gateway/quickstart.mdx +266 -0
  36. package/docs/mcp-gateway/reference.mdx +148 -0
  37. package/docs/mcp-gateway/test-clients.mdx +130 -0
  38. package/docs/mcp-gateway/troubleshooting.mdx +228 -0
  39. package/docs/mcp-server/introduction.mdx +10 -0
  40. package/docs/mcp-server/openai-apps-sdk.mdx +12 -0
  41. package/docs/policies/_index.md +14 -0
  42. package/docs/policies/akamai-ai-firewall/schema.json +1 -0
  43. package/docs/policies/akamai-firewall-for-ai-inbound/schema.json +1 -0
  44. package/docs/policies/akamai-firewall-for-ai-outbound/schema.json +1 -0
  45. package/docs/policies/amberflo-metering-inbound/schema.json +1 -0
  46. package/docs/policies/api-key-inbound/schema.json +1 -0
  47. package/docs/policies/audit-log-inbound/schema.json +1 -0
  48. package/docs/policies/auth0-jwt-auth-inbound/schema.json +1 -0
  49. package/docs/policies/authzen-inbound/schema.json +1 -0
  50. package/docs/policies/axiomatics-authz-inbound/schema.json +1 -0
  51. package/docs/policies/basic-auth-inbound/schema.json +1 -0
  52. package/docs/policies/bot-detection-inbound/schema.json +1 -0
  53. package/docs/policies/brownout-inbound/schema.json +1 -0
  54. package/docs/policies/caching-inbound/schema.json +1 -0
  55. package/docs/policies/change-method-inbound/schema.json +1 -0
  56. package/docs/policies/clear-headers-inbound/schema.json +1 -0
  57. package/docs/policies/clear-headers-outbound/schema.json +1 -0
  58. package/docs/policies/clerk-jwt-auth-inbound/schema.json +1 -0
  59. package/docs/policies/cognito-jwt-auth-inbound/schema.json +1 -0
  60. package/docs/policies/comet-opik-tracing-inbound/schema.json +1 -0
  61. package/docs/policies/complex-rate-limit-inbound/schema.json +1 -0
  62. package/docs/policies/composite-inbound/schema.json +1 -0
  63. package/docs/policies/composite-outbound/schema.json +1 -0
  64. package/docs/policies/curity-phantom-token-inbound/schema.json +1 -0
  65. package/docs/policies/firebase-jwt-inbound/schema.json +1 -0
  66. package/docs/policies/formdata-to-json-inbound/schema.json +1 -0
  67. package/docs/policies/galileo-tracing-inbound/schema.json +1 -0
  68. package/docs/policies/geo-filter-inbound/schema.json +1 -0
  69. package/docs/policies/graphql-complexity-limit-inbound/schema.json +1 -0
  70. package/docs/policies/graphql-disable-introspection-inbound/schema.json +1 -0
  71. package/docs/policies/graphql-introspection-filter-outbound/schema.json +1 -0
  72. package/docs/policies/http-deprecation-outbound/schema.json +1 -0
  73. package/docs/policies/jwt-scopes-inbound/schema.json +1 -0
  74. package/docs/policies/ldap-auth-inbound/schema.json +1 -0
  75. package/docs/policies/mcp-auth0-oauth-inbound/doc.md +54 -0
  76. package/docs/policies/mcp-auth0-oauth-inbound/intro.md +7 -0
  77. package/docs/policies/mcp-auth0-oauth-inbound/schema.json +135 -0
  78. package/docs/policies/mcp-capability-filter-inbound/doc.md +58 -0
  79. package/docs/policies/mcp-capability-filter-inbound/intro.md +9 -0
  80. package/docs/policies/mcp-capability-filter-inbound/schema.json +212 -0
  81. package/docs/policies/mcp-clerk-oauth-inbound/doc.md +34 -0
  82. package/docs/policies/mcp-clerk-oauth-inbound/intro.md +1 -0
  83. package/docs/policies/mcp-clerk-oauth-inbound/schema.json +134 -0
  84. package/docs/policies/mcp-cognito-oauth-inbound/doc.md +52 -0
  85. package/docs/policies/mcp-cognito-oauth-inbound/intro.md +7 -0
  86. package/docs/policies/mcp-cognito-oauth-inbound/schema.json +152 -0
  87. package/docs/policies/mcp-entra-oauth-inbound/doc.md +51 -0
  88. package/docs/policies/mcp-entra-oauth-inbound/intro.md +6 -0
  89. package/docs/policies/mcp-entra-oauth-inbound/schema.json +131 -0
  90. package/docs/policies/mcp-google-oauth-inbound/doc.md +52 -0
  91. package/docs/policies/mcp-google-oauth-inbound/intro.md +6 -0
  92. package/docs/policies/mcp-google-oauth-inbound/schema.json +125 -0
  93. package/docs/policies/mcp-keycloak-oauth-inbound/doc.md +43 -0
  94. package/docs/policies/mcp-keycloak-oauth-inbound/intro.md +2 -0
  95. package/docs/policies/mcp-keycloak-oauth-inbound/schema.json +140 -0
  96. package/docs/policies/mcp-logto-oauth-inbound/doc.md +52 -0
  97. package/docs/policies/mcp-logto-oauth-inbound/intro.md +6 -0
  98. package/docs/policies/mcp-logto-oauth-inbound/schema.json +131 -0
  99. package/docs/policies/mcp-oauth-inbound/doc.md +70 -0
  100. package/docs/policies/mcp-oauth-inbound/intro.md +11 -0
  101. package/docs/policies/mcp-oauth-inbound/schema.json +177 -0
  102. package/docs/policies/mcp-okta-oauth-inbound/doc.md +61 -0
  103. package/docs/policies/mcp-okta-oauth-inbound/intro.md +7 -0
  104. package/docs/policies/mcp-okta-oauth-inbound/schema.json +137 -0
  105. package/docs/policies/mcp-onelogin-oauth-inbound/doc.md +50 -0
  106. package/docs/policies/mcp-onelogin-oauth-inbound/intro.md +6 -0
  107. package/docs/policies/mcp-onelogin-oauth-inbound/schema.json +131 -0
  108. package/docs/policies/mcp-ping-oauth-inbound/doc.md +80 -0
  109. package/docs/policies/mcp-ping-oauth-inbound/intro.md +7 -0
  110. package/docs/policies/mcp-ping-oauth-inbound/schema.json +151 -0
  111. package/docs/policies/mcp-token-exchange-inbound/doc.md +135 -0
  112. package/docs/policies/mcp-token-exchange-inbound/intro.md +6 -0
  113. package/docs/policies/mcp-token-exchange-inbound/schema.json +134 -0
  114. package/docs/policies/mcp-workos-oauth-inbound/doc.md +50 -0
  115. package/docs/policies/mcp-workos-oauth-inbound/intro.md +6 -0
  116. package/docs/policies/mcp-workos-oauth-inbound/schema.json +125 -0
  117. package/docs/policies/mock-api-inbound/schema.json +1 -0
  118. package/docs/policies/moesif-inbound/schema.json +1 -0
  119. package/docs/policies/monetization-inbound/schema.json +1 -0
  120. package/docs/policies/mtls-auth-inbound/schema.json +1 -0
  121. package/docs/policies/okta-fga-authz-inbound/schema.json +1 -0
  122. package/docs/policies/okta-jwt-auth-inbound/schema.json +1 -0
  123. package/docs/policies/open-id-jwt-auth-inbound/schema.json +1 -0
  124. package/docs/policies/openfga-authz-inbound/schema.json +1 -0
  125. package/docs/policies/openmeter-inbound/schema.json +1 -0
  126. package/docs/policies/prompt-injection-outbound/schema.json +1 -0
  127. package/docs/policies/propel-auth-jwt-inbound/schema.json +1 -0
  128. package/docs/policies/query-param-to-header-inbound/schema.json +1 -0
  129. package/docs/policies/quota-inbound/schema.json +1 -0
  130. package/docs/policies/rate-limit-inbound/schema.json +1 -0
  131. package/docs/policies/readme-metrics-inbound/schema.json +1 -0
  132. package/docs/policies/remove-headers-inbound/schema.json +1 -0
  133. package/docs/policies/remove-headers-outbound/schema.json +1 -0
  134. package/docs/policies/remove-query-params-inbound/schema.json +1 -0
  135. package/docs/policies/replace-string-outbound/schema.json +1 -0
  136. package/docs/policies/request-size-limit-inbound/schema.json +1 -0
  137. package/docs/policies/request-validation-inbound/schema.json +1 -0
  138. package/docs/policies/require-origin-inbound/schema.json +1 -0
  139. package/docs/policies/secret-masking-outbound/schema.json +1 -0
  140. package/docs/policies/semantic-cache-inbound/schema.json +1 -0
  141. package/docs/policies/set-body-inbound/schema.json +1 -0
  142. package/docs/policies/set-headers-inbound/schema.json +1 -0
  143. package/docs/policies/set-headers-outbound/schema.json +1 -0
  144. package/docs/policies/set-query-params-inbound/schema.json +1 -0
  145. package/docs/policies/set-status-outbound/schema.json +1 -0
  146. package/docs/policies/set-upstream-api-key-inbound/schema.json +1 -0
  147. package/docs/policies/sleep-inbound/schema.json +1 -0
  148. package/docs/policies/stripe-webhook-verification-inbound/schema.json +1 -0
  149. package/docs/policies/supabase-jwt-auth-inbound/schema.json +1 -0
  150. package/docs/policies/upstream-azure-ad-service-auth-inbound/schema.json +1 -0
  151. package/docs/policies/upstream-firebase-admin-auth-inbound/schema.json +1 -0
  152. package/docs/policies/upstream-firebase-user-auth-inbound/schema.json +1 -0
  153. package/docs/policies/upstream-gcp-federated-auth-inbound/schema.json +1 -0
  154. package/docs/policies/upstream-gcp-jwt-inbound/schema.json +1 -0
  155. package/docs/policies/upstream-gcp-service-auth-inbound/schema.json +1 -0
  156. package/docs/policies/upstream-zuplo-jwt-auth-inbound/schema.json +1 -0
  157. package/docs/policies/validate-json-schema-inbound/schema.json +1 -0
  158. package/docs/policies/web-bot-auth-inbound/schema.json +1 -0
  159. package/docs/policies/xml-to-json-outbound/schema.json +1 -0
  160. package/package.json +4 -4
@@ -0,0 +1,137 @@
1
+ ---
2
+ title: "Connect MCP clients"
3
+ sidebar_label: "Overview"
4
+ description:
5
+ Learn how MCP clients connect to a Zuplo MCP Gateway, where to find the
6
+ connection URL, what the OAuth flow looks like on first use, and which clients
7
+ support which spec features.
8
+ ---
9
+
10
+ The Zuplo MCP Gateway exposes each MCP route at a stable HTTPS URL that any
11
+ modern MCP client can connect to. Clients speak the Streamable HTTP transport,
12
+ complete an OAuth flow on first use, and then call tools, read resources, and
13
+ run prompts through the gateway just as they would against any other remote MCP
14
+ server.
15
+
16
+ This page covers the connection model and links to a step-by-step guide for each
17
+ of the major clients.
18
+
19
+ ## The MCP route URL
20
+
21
+ Each MCP route in `config/routes.oas.json` is reachable at:
22
+
23
+ ```text
24
+ https://{deploymentUrl}/{routePath}
25
+ ```
26
+
27
+ The `{deploymentUrl}` is your project's deployment URL — for example
28
+ `acme-mcp-main-abc123.d2.zuplo.dev` for a default Zuplo deployment, or a custom
29
+ domain you configure for the project. The `{routePath}` is the path you set on
30
+ the route in `routes.oas.json`. A typical convention is `/mcp/<provider>-v<n>`,
31
+ so a Linear route looks like
32
+ `https://acme-mcp-main-abc123.d2.zuplo.dev/mcp/linear-v1`.
33
+
34
+ For local development with `zuplo dev`, the URL is
35
+ `http://127.0.0.1:9000/{routePath}` — for example
36
+ `http://127.0.0.1:9000/mcp/linear-v1`. See
37
+ [Local development](../code-config/local-development.mdx).
38
+
39
+ ## Transport
40
+
41
+ The gateway uses the **Streamable HTTP** transport defined in the MCP
42
+ specification. Clients POST JSON-RPC requests to the MCP route URL. The gateway
43
+ does not currently accept GET requests for server-sent event streams — it
44
+ returns `405 Method Not Allowed` — so configure your client to use Streamable
45
+ HTTP, not the older two-endpoint HTTP+SSE transport.
46
+
47
+ For more on transports, see the
48
+ [MCP transports specification](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports).
49
+
50
+ ## What happens on first connect
51
+
52
+ The first time a user connects, the gateway runs two distinct OAuth handshakes
53
+ before any tool call reaches an upstream MCP server.
54
+
55
+ 1. **Discovery.** The client POSTs an MCP request to the route URL without an
56
+ `Authorization` header. The gateway responds with `401 Unauthorized` and a
57
+ `WWW-Authenticate` header that points at the gateway's
58
+ [Protected Resource Metadata document (RFC 9728)](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization).
59
+ 2. **Gateway login.** The client opens the gateway's authorization endpoint in a
60
+ browser. The gateway redirects the user to your identity provider — Auth0,
61
+ Okta, Entra, Google, Cognito, or any of the other
62
+ [supported IdPs](../auth/overview.mdx#identity-providers) — to sign in. After
63
+ login, the gateway issues an access token bound to the route URL and returns
64
+ it to the client through the standard OAuth 2.1 Authorization Code with PKCE
65
+ flow.
66
+ 3. **Upstream consent.** If the route's upstream MCP server requires per-user
67
+ OAuth (Linear, Notion, Stripe, GitHub, and so on), the gateway shows a
68
+ consent page with a **Connect** button for the upstream. Clicking **Connect**
69
+ opens the upstream provider's OAuth flow in the same browser. Once the
70
+ upstream is connected, the user clicks **Authorize** and the gateway returns
71
+ the access token to the client.
72
+
73
+ After the first connect, subsequent requests reuse the issued access token and
74
+ the stored upstream credentials. Tokens refresh automatically. If the gateway
75
+ needs the user to re-consent to an upstream — for example, when an upstream
76
+ provider revokes the gateway's credentials — the client receives a JSON-RPC
77
+ error with a URL to open in the browser to complete re-consent.
78
+
79
+ For the full authentication model, see
80
+ [Authentication overview](../auth/overview.mdx).
81
+
82
+ ## Client compatibility
83
+
84
+ The table below summarizes which MCP spec features each major client supports
85
+ today. All clients listed here support remote Streamable HTTP and work with the
86
+ Zuplo MCP Gateway.
87
+
88
+ | Client | Tools | Prompts | Resources | Roots | Sampling | Elicitation | DCR | CIMD | Apps |
89
+ | -------------------------------------------------------------------- | :---: | :-----: | :-------: | :---: | :------: | :---------: | :-: | :--: | :--: |
90
+ | [Claude Desktop](./claude-desktop.mdx) | yes | yes | yes | yes | – | – | yes | – | yes |
91
+ | [Claude.ai (web)](./claude-desktop.mdx) | yes | yes | yes | – | – | – | yes | yes | yes |
92
+ | [Claude Code](./claude-code.mdx) | yes | yes | yes | yes | – | yes | yes | – | – |
93
+ | [ChatGPT](./chatgpt.mdx) | yes | – | – | – | – | – | yes | yes | yes |
94
+ | [Cursor](./cursor.mdx) | yes | yes | – | yes | – | yes | yes | – | yes |
95
+ | [VS Code (GitHub Copilot)](./vs-code.mdx) | yes | yes | yes | yes | yes | yes | yes | yes | yes |
96
+ | [Windsurf (Cascade)](./other-clients.mdx#windsurf) | yes | – | – | – | – | – | yes | – | – |
97
+ | [Goose](./other-clients.mdx#goose) | yes | yes | yes | yes | yes | yes | yes | – | yes |
98
+ | [Gemini CLI](./other-clients.mdx#gemini-cli) | yes | yes | – | – | – | – | yes | – | – |
99
+ | [GitHub Copilot CLI](./other-clients.mdx#github-copilot-cli) | yes | – | – | – | yes | yes | yes | – | – |
100
+ | [Postman](./other-clients.mdx#postman) | yes | yes | yes | – | yes | yes | – | – | yes |
101
+ | [MCPJam](./other-clients.mdx#mcpjam) | yes | yes | yes | – | – | yes | yes | yes | yes |
102
+ | [Continue](./other-clients.mdx#continue) | yes | yes | yes | – | – | – | – | – | yes |
103
+ | [LibreChat](./other-clients.mdx#librechat) | yes | – | – | – | – | – | yes | – | – |
104
+ | [JetBrains AI Assistant](./other-clients.mdx#jetbrains-ai-assistant) | yes | – | – | – | – | – | – | – | – |
105
+
106
+ Capability data is sourced from the
107
+ [official MCP clients page](https://modelcontextprotocol.io/clients). Clients
108
+ ship new features frequently; check the client's own documentation for the
109
+ latest support status.
110
+
111
+ :::note
112
+
113
+ The gateway exposes whatever capabilities the upstream MCP servers expose. If an
114
+ upstream server only ships tools, a client that supports resources won't see
115
+ anything in `resources/list` for that server. The compatibility matrix above
116
+ tracks **what each client can consume**, not what the gateway forwards.
117
+
118
+ :::
119
+
120
+ ## Per-client guides
121
+
122
+ - [Claude Desktop](./claude-desktop.mdx) — add via `claude_desktop_config.json`.
123
+ - [Claude Code](./claude-code.mdx) — add via the `claude mcp add` CLI command.
124
+ - [ChatGPT](./chatgpt.mdx) — add via Settings → Connectors (Developer Mode
125
+ required).
126
+ - [Cursor](./cursor.mdx) — add via `.cursor/mcp.json` or the one-click install
127
+ link.
128
+ - [VS Code](./vs-code.mdx) — add via `.vscode/mcp.json` or the `code --add-mcp`
129
+ CLI command.
130
+ - [Other clients](./other-clients.mdx) — Windsurf, Goose, Gemini CLI, GitHub
131
+ Copilot CLI, Postman, MCPJam, Continue, LibreChat, JetBrains AI Assistant.
132
+
133
+ ## Related
134
+
135
+ - [How the MCP Gateway works](../how-it-works.mdx)
136
+ - [Authentication overview](../auth/overview.mdx)
137
+ - [Configuring the MCP Gateway with code](../code-config/overview.mdx)
@@ -0,0 +1,128 @@
1
+ ---
2
+ title: "Connect VS Code (GitHub Copilot)"
3
+ sidebar_label: "VS Code"
4
+ description:
5
+ Connect VS Code with GitHub Copilot to a Zuplo MCP Gateway through
6
+ `.vscode/mcp.json`, the `code --add-mcp` CLI, or the Extensions view, and use
7
+ gateway tools in Copilot Chat's Agent mode.
8
+ ---
9
+
10
+ VS Code with GitHub Copilot connects to remote MCP servers and exposes their
11
+ tools to Copilot Chat's **Agent mode**. Add the Zuplo MCP Gateway through a
12
+ `.vscode/mcp.json` file in your workspace, the `code` CLI, or the Extensions
13
+ view.
14
+
15
+ ## Prerequisites
16
+
17
+ - A Zuplo project with the MCP Gateway plugin configured and at least one MCP
18
+ route. See the [quickstart](../quickstart.mdx) if you haven't set one up yet.
19
+ - VS Code installed.
20
+ - The GitHub Copilot extension installed and signed in.
21
+
22
+ ## Get the route URL
23
+
24
+ Each MCP route in `config/routes.oas.json` is reachable at
25
+ `https://{deploymentUrl}/{routePath}` once deployed — for example
26
+ `https://{deploymentUrl}/mcp/linear-v1`.
27
+
28
+ ## Add the gateway
29
+
30
+ There are three supported ways to register the gateway.
31
+
32
+ ### Option 1: `.vscode/mcp.json` in your workspace
33
+
34
+ Create or open `.vscode/mcp.json` at the root of your workspace, then add an
35
+ HTTP server entry pointing at the route URL:
36
+
37
+ ```json title=".vscode/mcp.json"
38
+ {
39
+ "servers": {
40
+ "zuplo": {
41
+ "type": "http",
42
+ "url": "https://{deploymentUrl}/{routePath}"
43
+ }
44
+ }
45
+ }
46
+ ```
47
+
48
+ Commit the file to source control to share the configuration with your team.
49
+
50
+ ### Option 2: `code --add-mcp` CLI
51
+
52
+ Use the VS Code CLI to add a server to your user profile or to a workspace:
53
+
54
+ ```bash
55
+ code --add-mcp '{"name":"zuplo","type":"http","url":"https://{deploymentUrl}/{routePath}"}'
56
+ ```
57
+
58
+ VS Code prompts you to confirm the server registration and to choose between
59
+ user-profile and workspace scope.
60
+
61
+ ### Option 3: Extensions view
62
+
63
+ 1. Open the **Extensions** view in VS Code.
64
+ 2. Type `@mcp` in the search field. VS Code shows the curated MCP server gallery
65
+ alongside any servers you've already registered.
66
+ 3. To add a custom server (the Zuplo gateway), use the **MCP: Add Server**
67
+ command from the Command Palette and paste your route URL when prompted, or
68
+ open **MCP: Open User Configuration** to edit `mcp.json` directly.
69
+
70
+ ## Authenticate
71
+
72
+ The first time VS Code talks to the gateway, the gateway returns
73
+ `401 Unauthorized` and VS Code opens the OAuth flow in your default browser.
74
+
75
+ <Stepper>
76
+
77
+ 1. Sign in to the gateway with your identity provider.
78
+ 2. On the gateway's consent page, click **Connect** next to the upstream MCP
79
+ server and complete its OAuth flow.
80
+ 3. Click **Authorize** to finish. VS Code receives the access token and marks
81
+ the server as connected.
82
+
83
+ </Stepper>
84
+
85
+ Tokens refresh automatically. To revoke access, remove the server from
86
+ `mcp.json` (or from MCP settings) and re-add it to start over.
87
+
88
+ ## Use tools in Copilot Chat
89
+
90
+ Once the server is connected, open Copilot Chat and switch to **Agent** mode
91
+ (the mode picker is at the top of the chat panel). Tools from the gateway appear
92
+ in the tool picker — click the tools icon to see them and to enable or disable
93
+ individual tools per chat. Reference resources from the gateway by typing `#` in
94
+ your prompt.
95
+
96
+ ## What VS Code supports
97
+
98
+ VS Code's MCP client is one of the most feature-complete on the market. With the
99
+ Zuplo MCP Gateway it supports:
100
+
101
+ - **Tools** — invoke gateway-exposed tools from Agent mode.
102
+ - **Prompts** — surface prompts as slash commands.
103
+ - **Resources** — reference resources with `#` in prompts.
104
+ - **Roots** — declare workspace folders as roots.
105
+ - **Sampling** — handle server-initiated sampling requests, including the
106
+ `tools` and `toolChoice` parameters added in MCP `2025-11-25`.
107
+ - **Elicitation** — handle both form-mode and URL-mode elicitation requests,
108
+ including upstream re-authorization prompts.
109
+ - **MCP Apps** — render interactive HTML widgets inline in the chat.
110
+ - **DCR** and **CIMD** — both client registration paths are supported.
111
+
112
+ ## Troubleshooting
113
+
114
+ - **Server stays in "Pending" state.** Confirm the URL in `mcp.json` is
115
+ reachable. VS Code shows server logs in the **Output** panel under **MCP** —
116
+ check there for the exact failure reason.
117
+ - **Tools do not appear in Copilot Chat.** Confirm Copilot Chat is in **Agent**
118
+ mode. Tool calling is gated to that mode.
119
+ - **OAuth flow does not start.** Some corporate proxies block the local
120
+ callback. Try connecting from outside the proxy or use the VS Code setting to
121
+ override the callback port.
122
+
123
+ ## Related
124
+
125
+ - [Connect MCP clients overview](./overview.mdx)
126
+ - VS Code's docs:
127
+ [Add and manage MCP servers in VS Code](https://code.visualstudio.com/docs/copilot/chat/mcp-servers)
128
+ - [Authentication overview](../auth/overview.mdx)
@@ -0,0 +1,266 @@
1
+ ---
2
+ title: "How the MCP Gateway works"
3
+ sidebar_label: "How it works"
4
+ description:
5
+ Architecture overview — request lifecycle, the two OAuth surfaces, the
6
+ Streamable HTTP transport, and the configuration model.
7
+ ---
8
+
9
+ The MCP Gateway is a set of policies and a route handler that run inside any
10
+ Zuplo project. A single deployment hosts any number of public MCP routes, each
11
+ pointing at a different upstream MCP server. The gateway runs its own OAuth 2.1
12
+ authorization server for inbound clients and acts as an OAuth client to each
13
+ upstream provider.
14
+
15
+ ## Request lifecycle
16
+
17
+ The diagram below shows a first-time call from an MCP client to a route that
18
+ wires a single OAuth-protected upstream. Once tokens are issued and the upstream
19
+ connection exists, the gateway skips the OAuth dance and goes straight from the
20
+ bearer-token check to the upstream proxy.
21
+
22
+ <Diagram height="h-72">
23
+ <DiagramNode id="client">MCP Client</DiagramNode>
24
+ <DiagramGroup id="gateway" label="Zuplo MCP Gateway">
25
+ <DiagramNode id="oauth" variant="zuplo">
26
+ OAuth endpoints
27
+ </DiagramNode>
28
+ <DiagramNode id="route" variant="zuplo">
29
+ MCP route
30
+ </DiagramNode>
31
+ </DiagramGroup>
32
+ <DiagramNode id="idp">Identity Provider</DiagramNode>
33
+ <DiagramNode id="upstream">Upstream MCP Server</DiagramNode>
34
+ <DiagramEdge from="client" to="oauth" label="Discover + auth" />
35
+ <DiagramEdge from="oauth" to="idp" label="Browser login" />
36
+ <DiagramEdge from="client" to="route" label="Bearer token" />
37
+ <DiagramEdge from="route" to="upstream" label="Proxied request" />
38
+ </Diagram>
39
+
40
+ The flow in detail, for the first call from a new client to an OAuth-protected
41
+ upstream:
42
+
43
+ 1. The client POSTs to the MCP route with no token.
44
+ 2. The gateway returns `401` with
45
+ `WWW-Authenticate: Bearer resource_metadata=...`.
46
+ 3. The client fetches the Protected Resource Metadata document and discovers the
47
+ gateway's authorization server.
48
+ 4. The client fetches the AS metadata, registers via DCR (or uses a CIMD client
49
+ ID), and starts the authorization flow with PKCE and a `resource` parameter.
50
+ 5. The gateway redirects the user's browser to the configured identity provider
51
+ for login.
52
+ 6. After login, the gateway renders a consent page that lists every upstream the
53
+ route requires.
54
+ 7. The user completes upstream OAuth for each required upstream — the gateway
55
+ stores per-user tokens encrypted at rest.
56
+ 8. The user approves consent. The gateway redirects the client back with an
57
+ authorization code.
58
+ 9. The client exchanges the code at `/oauth/token` and receives an access token
59
+ scoped to `mcp:tools`.
60
+ 10. The client POSTs to the MCP route with the bearer token. The gateway
61
+ validates the token, attaches the user's upstream credential, and proxies to
62
+ the upstream MCP server.
63
+
64
+ Once tokens are issued and the upstream connection exists, only step 10 runs on
65
+ subsequent calls.
66
+
67
+ Three details that come up during debugging:
68
+
69
+ - The `resource` parameter (RFC 8707) is required on `/oauth/authorize` and
70
+ `/oauth/token`. The gateway rejects tokens whose audience doesn't match the
71
+ route they're being used against.
72
+ - The consent screen lists the upstream the route depends on with a **Connect**
73
+ button. The user can't approve the grant until the upstream is connected.
74
+ - The upstream OAuth flow runs once per (user, upstream) pair. Subsequent
75
+ requests reuse the stored credential. If an upstream returns a 401 mid-call,
76
+ the gateway refreshes and retries once before propagating the error.
77
+
78
+ ## Two OAuth surfaces
79
+
80
+ The gateway plays two OAuth roles simultaneously. The inbound role — as an OAuth
81
+ server for MCP clients — and the outbound role — as an OAuth client to each
82
+ upstream — use different policies and different credential stores.
83
+
84
+ ### Downstream — gateway as OAuth 2.1 server
85
+
86
+ The gateway implements the MCP authorization spec from the perspective of a
87
+ Resource Server and an Authorization Server. MCP clients talk OAuth to the
88
+ gateway, not to the upstream providers. Standards observed:
89
+
90
+ - **RFC 8414** Authorization Server Metadata and **OpenID Connect Discovery
91
+ 1.0** for AS discovery.
92
+ - **RFC 9728** Protected Resource Metadata for advertising the AS.
93
+ - **RFC 7591** Dynamic Client Registration and **OAuth Client ID Metadata
94
+ Documents** (CIMD) for client registration. CIMD is the recommended path; DCR
95
+ is supported for clients that don't speak it.
96
+ - **RFC 7636** PKCE with S256 required.
97
+ - **RFC 8707** Resource Indicators — the `resource` parameter is required on
98
+ every authorization and token request.
99
+ - **RFC 6750** Bearer tokens — the gateway issues opaque tokens carried in
100
+ `Authorization: Bearer` headers.
101
+
102
+ The gateway delegates user authentication to a configured OIDC identity provider
103
+ (Auth0 through `McpAuth0OAuthInboundPolicy` or generic OIDC through
104
+ `McpOAuthInboundPolicy`). The provider's tokens never leave the gateway — the
105
+ gateway issues its own opaque access tokens, scoped to `mcp:tools`, and binds
106
+ each to one specific MCP route. The route binding is a deliberate blast-radius
107
+ constraint: a token issued for `/mcp/linear-v1` can't be replayed against
108
+ `/mcp/stripe-v1`, so a stolen token from one upstream stays confined to that
109
+ upstream.
110
+
111
+ Token passthrough is explicitly forbidden by the spec, and the gateway enforces
112
+ it: inbound auth headers don't leak to the upstream.
113
+
114
+ ### Upstream — gateway as OAuth client
115
+
116
+ For each upstream MCP server that requires OAuth, the gateway acts as a standard
117
+ OAuth client.
118
+
119
+ - **Per-user OAuth (`authMode: "user-oauth"`)** — every end user goes through a
120
+ one-time consent. The gateway stores their access and refresh tokens encrypted
121
+ at rest, keyed by user. Token refresh is automatic.
122
+ - **Shared OAuth (`authMode: "shared-oauth"`)** — one upstream connection shared
123
+ across every user of the gateway. The connection is established by an
124
+ administrator through a special connect flow.
125
+
126
+ Client registration with the upstream supports two modes:
127
+
128
+ - `clientRegistration: { mode: "auto" }` (the default) — the gateway publishes a
129
+ per-upstream OAuth Client ID Metadata Document at
130
+ `/.well-known/oauth-client/<connection>` and tells the upstream that URL is
131
+ the `client_id`. If the upstream doesn't support CIMD, the gateway falls back
132
+ to RFC 7591 Dynamic Client Registration.
133
+ - `clientRegistration: { mode: "manual" }` — supply a pre-registered `clientId`
134
+ and `clientSecret` (and optional auth method).
135
+
136
+ When the gateway needs an upstream connection it doesn't have yet, the gateway
137
+ returns a JSON-RPC error with a URL to open in a browser. Modern MCP clients pop
138
+ the browser automatically; older ones surface the URL for the user to open
139
+ manually.
140
+
141
+ ## Transport — Streamable HTTP, POST only
142
+
143
+ Every MCP route uses the
144
+ [Streamable HTTP transport](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports)
145
+ defined in the MCP spec. The gateway accepts POST requests only:
146
+
147
+ - `POST` on the route path carries the JSON-RPC payload.
148
+ - `GET` on the same path returns `405 Method Not Allowed` with `Allow: POST`.
149
+ The gateway doesn't open SSE streams for server-initiated messages.
150
+
151
+ Route paths are whatever you set in `routes.oas.json` — `/mcp/<provider>-v<n>`
152
+ is the recommended convention (and what the dogfood gateway uses), but any path
153
+ the OpenAPI router accepts works.
154
+
155
+ The gateway is **stateless**. It does not maintain MCP sessions, doesn't track
156
+ subscriptions, and doesn't emit server-initiated notifications. Statelessness is
157
+ what lets the gateway run on Zuplo's edge runtime and scale horizontally without
158
+ session affinity — any node can serve any request. Stateful MCP features
159
+ (long-running subscriptions, server-initiated sampling) aren't supported through
160
+ the gateway today.
161
+
162
+ ## Configuration model
163
+
164
+ The MCP Gateway is configured the same way as the rest of a Zuplo project: an
165
+ OpenAPI route file, a policy library, and a runtime plugin registration. Every
166
+ project that uses the gateway has the same shape:
167
+
168
+ | Piece | Lives in | Purpose |
169
+ | ---------------------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
170
+ | `compatibilityDate >= 2026-03-01` | `zuplo.jsonc` | Unlocks MCP Gateway features. Required. |
171
+ | `McpGatewayPlugin` | `modules/zuplo.runtime.ts` | Registers the OAuth metadata, authorization endpoints, consent page, and upstream connect callbacks. |
172
+ | One MCP OAuth policy | `config/policies.json` | Authenticates inbound MCP requests against your identity provider. One per project — pick the [wrapper for your IdP](./auth/overview.mdx#identity-providers) (Auth0, Cognito, Clerk, Entra, Google, Keycloak, Logto, Okta, OneLogin, Ping, WorkOS) or `mcp-oauth-inbound` for any other OIDC provider. |
173
+ | One `mcp-token-exchange-inbound` policy per upstream | `config/policies.json` | Resolves the user's upstream credential and attaches it as the upstream `Authorization` header. Omit for non-OAuth upstreams. |
174
+ | Optional `mcp-capability-filter-inbound` policy | `config/policies.json` | Curates the tools, prompts, resources, and resource templates the route exposes. |
175
+ | One route per upstream | `config/routes.oas.json` | Uses `McpProxyHandler` with the upstream URL as `rewritePattern`. Attaches the OAuth policy + token exchange policy. |
176
+
177
+ A minimal route looks like this:
178
+
179
+ ```jsonc title="config/routes.oas.json"
180
+ "/mcp/linear-v1": {
181
+ "get,post": {
182
+ "operationId": "linear-mcp-server",
183
+ "x-zuplo-route": {
184
+ "corsPolicy": "none",
185
+ "handler": {
186
+ "module": "$import(@zuplo/runtime/mcp-gateway)",
187
+ "export": "McpProxyHandler",
188
+ "options": { "rewritePattern": "https://mcp.linear.app/mcp" }
189
+ },
190
+ "policies": {
191
+ "inbound": ["auth0-managed-oauth", "mcp-token-exchange-linear"]
192
+ }
193
+ }
194
+ }
195
+ }
196
+ ```
197
+
198
+ The plugin registration:
199
+
200
+ ```ts title="modules/zuplo.runtime.ts"
201
+ import { RuntimeExtensions } from "@zuplo/runtime";
202
+ import { McpGatewayPlugin } from "@zuplo/runtime/mcp-gateway";
203
+
204
+ export function runtimeInit(runtime: RuntimeExtensions) {
205
+ runtime.addPlugin(new McpGatewayPlugin());
206
+ }
207
+ ```
208
+
209
+ The `operationId` on each MCP route is more than a label — it identifies the MCP
210
+ route and is the `virtualServerName` in analytics. Changing it strands all
211
+ stored tokens and per-user upstream connections.
212
+
213
+ :::caution
214
+
215
+ MCP Gateway features require `compatibilityDate >= 2026-03-01` in `zuplo.jsonc`.
216
+ See [Compatibility dates](./code-config/compatibility-dates.mdx).
217
+
218
+ :::
219
+
220
+ ### Inbound policy chain
221
+
222
+ For each request to an MCP route, the policies run in this order:
223
+
224
+ 1. **MCP OAuth policy** — one of the
225
+ [IdP-specific wrappers](./auth/overview.mdx#identity-providers)
226
+ (`mcp-auth0-oauth-inbound`, `mcp-okta-oauth-inbound`,
227
+ `mcp-entra-oauth-inbound`, and so on) or the generic `mcp-oauth-inbound`.
228
+ Validates the gateway-issued bearer token, asserts audience binding and
229
+ scope.
230
+ 2. **MCP token-exchange policy** (`mcp-token-exchange-inbound`) — resolves the
231
+ right upstream credential for the authenticated user. If the user hasn't
232
+ connected this upstream yet, the policy returns a connect-required error.
233
+ 3. **Capability filter policy** (`mcp-capability-filter-inbound`, optional) —
234
+ filters the upstream's `tools/list`, `prompts/list`, `resources/list`, and
235
+ `resources/templates/list` responses, and blocks calls to hidden capabilities
236
+ with `MethodNotFound`.
237
+
238
+ The handler — `McpProxyHandler` — runs after the policies, forwards the request
239
+ to the upstream URL, and emits capability analytics events.
240
+
241
+ ## What the gateway does not do
242
+
243
+ A few capabilities are intentionally out of scope, at least today:
244
+
245
+ - **No stateful sessions.** The gateway doesn't open SSE streams, doesn't track
246
+ `MCP-Session-Id`, and doesn't proxy server-initiated requests.
247
+ - **No `tools/list` caching.** Every request goes upstream. If an upstream is
248
+ slow to list capabilities, callers feel it.
249
+ - **No prompt-injection or PII scanning at the policy level.** These belong in a
250
+ separate inbound policy and can be composed alongside the MCP policies through
251
+ Zuplo's standard policy model.
252
+ - **No rate limiting on OAuth endpoints out of the box.** Add Zuplo's built-in
253
+ `rate-limit-inbound` policy to those routes if needed.
254
+
255
+ ## Related
256
+
257
+ - [Set up an MCP Gateway](./code-config/overview.mdx) — the how-to that puts
258
+ this conceptual model into practice.
259
+ - [Quickstart](./quickstart.mdx) — add the MCP Gateway plugin to a Zuplo project
260
+ and front your first upstream.
261
+ - [Authentication overview](./auth/overview.mdx) — the two OAuth layers expanded
262
+ with the full standards table.
263
+ - [Reference](./reference.mdx) — the full URL catalog, default TTLs,
264
+ compatibility date, and OAuth metadata extensions.
265
+ - [Troubleshooting](./troubleshooting.mdx) — the gotchas that catch most people
266
+ the first time.