diff --git a/plugins/dataapp-developer/skills/mcp-data-app/reference/deploy.md b/plugins/dataapp-developer/skills/mcp-data-app/reference/deploy.md index 2c524c3..e0086d8 100644 --- a/plugins/dataapp-developer/skills/mcp-data-app/reference/deploy.md +++ b/plugins/dataapp-developer/skills/mcp-data-app/reference/deploy.md @@ -72,6 +72,8 @@ Set the data app's built-in authentication to **None**. Keboola's app-level OIDC Deploy with `#MCP_PUBLIC_URL` empty → copy the app URL Keboola shows (`https://-.hub..keboola.com`, no trailing slash, no `/mcp`) → set `#MCP_PUBLIC_URL` → redeploy so the OAuth-shape discovery docs advertise the real origin. +`#MCP_PUBLIC_URL` is inherently instance-specific — every app has its own URL, so no two apps can share the value. **If you duplicate an existing MCP data-app config, config duplication copies all secrets verbatim, including `#MCP_PUBLIC_URL`.** The copy then advertises the *source* app's origin in its discovery docs, so it deploys and runs fine but a fresh client's OAuth handshake redirects to the old app and fails. Always re-run the two-pass dance on a duplicated app: reset `#MCP_PUBLIC_URL` to the copy's own URL and redeploy before connecting a client. + ## Verify Logs first (authoritative): look for `success: mcp-server entered RUNNING state` in the deploy logs (via `kbagent … data-app logs` or the Keboola Terminal Log tab). Then: diff --git a/plugins/dataapp-developer/skills/mcp-data-app/reference/troubleshooting.md b/plugins/dataapp-developer/skills/mcp-data-app/reference/troubleshooting.md index 1a99149..143fd4e 100644 --- a/plugins/dataapp-developer/skills/mcp-data-app/reference/troubleshooting.md +++ b/plugins/dataapp-developer/skills/mcp-data-app/reference/troubleshooting.md @@ -7,6 +7,7 @@ | `421 Misdirected Request` on `/mcp` | MCP SDK DNS-rebinding protection rejects the Host header | Ensure nginx sends `proxy_set_header Host "127.0.0.1:5000";` on every proxied location (see template nginx conf) | | Client sees the whole SSE response at once / hangs | nginx buffering the stream | `proxy_buffering off; proxy_cache off;` on `location /mcp` (already in template) | | Discovery JSON shows `127.0.0.1:5000` instead of the real host | `#MCP_PUBLIC_URL` not set | Set `#MCP_PUBLIC_URL` to the app origin and redeploy (two-pass dance) | +| Discovery JSON shows a *different* app's host; claude.ai gets a discovery response from the new app but redirects to the old app's `/authorize` and fails | `#MCP_PUBLIC_URL` copied verbatim from another app — config duplication carries secrets over, so a duplicated app still advertises the *source* app's origin. The app deploys and runs fine; only a fresh client's OAuth handshake breaks | Reset `#MCP_PUBLIC_URL` to *this* app's own URL and redeploy (re-run the two-pass dance on the copy), then re-add the connector | | All `/mcp` calls 401 even with the right key, connector never prompts for creds | App-level OIDC stripped `Authorization` | Set app-level auth to **None**; `#MCP_API_KEY` is the boundary | | `KeyError: 'MCP_API_KEY'` / `SystemExit: Missing required env vars` at boot | Secrets not set | Add `#MCP_API_KEY`, `#KBC_STORAGE_API_URL`, `#KBC_STORAGE_TOKEN` as data-app secrets | | claude.ai connector fails at the OAuth step | discovery endpoints unreachable or Host-rewrite missing | Confirm the five OAuth-shape locations are proxied with the Host rewrite; `curl` the two `.well-known/oauth-*` docs |