Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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://<slug>-<cfg>.hub.<region>.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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
Loading