docs: correct the audience table and refresh the blockers
- Two audience scopes per MCP server, not one: Kong's own openid-connect
plugin re-exchanges the token, so it must also name
kong-token-exchange-broker. Measured on catalog.
- Drop the resolved Konnect-not-persisting blocker; the cause was a dead
Konnect org, not Konnect refusing writes.
- Drop the resolved kong-token-exchange-broker secret mismatch; its
client_credentials returns 200.
- Record the real blocker: PydanticAI's MCP client cannot open a session
against ai-mcp-proxy.
- Document the realm's override-on-start import and ${KC_SECRET_*}
placeholders, and the a2a-sdk 1.x serving requirements.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -95,13 +95,21 @@ access token five minutes.
|
||||
|
||||
MCP servers, one per domain, served by Kong:
|
||||
|
||||
| Domain | URL | Audience scope |
|
||||
| Domain | URL | Audience scopes to request |
|
||||
|---|---|---|
|
||||
| catalog | `https://catalog-dev.sttlab.local/catalog-mcp` | `mcp-catalog-audience` |
|
||||
| customers | `https://customers-dev.sttlab.local/customers-mcp` | `mcp-customers-audience` |
|
||||
| payments | `https://payments-dev.sttlab.local/payments-mcp` | `mcp-payments-audience` |
|
||||
| sales | `https://sales-dev.sttlab.local/sales-mcp` | `mcp-sales-audience` |
|
||||
| workforce | `https://workforce-dev.sttlab.local/workforce-mcp` | `mcp-workforce-audience` |
|
||||
| catalog | `https://catalog-dev.sttlab.local/catalog-mcp` | `mcp-catalog-audience kong-token-exchange-broker-audience` |
|
||||
| customers | `https://customers-dev.sttlab.local/customers-mcp` | `mcp-customers-audience kong-token-exchange-broker-audience` |
|
||||
| payments | `https://payments-dev.sttlab.local/payments-mcp` | `mcp-payments-audience kong-token-exchange-broker-audience` |
|
||||
| sales | `https://sales-dev.sttlab.local/sales-mcp` | `mcp-sales-audience kong-token-exchange-broker-audience` |
|
||||
| workforce | `https://workforce-dev.sttlab.local/workforce-mcp` | `mcp-workforce-audience kong-token-exchange-broker-audience` |
|
||||
|
||||
**Two scopes per server, not one.** The gateway's own `openid-connect` plugin
|
||||
exchanges the token again before reaching the backend, so the token must also
|
||||
name `kong-token-exchange-broker`. Without it the call fails with a bare `401`
|
||||
and the real cause appears only in the gateway log — *invalid status code
|
||||
received from the token endpoint (403)*. Measured on catalog: with both scopes
|
||||
the MCP server answers `200`, with `mcp-catalog-audience` alone it answers
|
||||
`401`. LibreChat has always requested both.
|
||||
|
||||
LLM inference goes through the Kong AI gateway, never direct to a provider:
|
||||
|
||||
@@ -153,12 +161,32 @@ The realm actually deployed is `infra-keycloak/k8s/keycloak/configmap-realm.yaml
|
||||
— note that `kong-v2/classic-models-realm.yaml` is an older partial copy and is
|
||||
**not** authoritative.
|
||||
|
||||
## Known blockers
|
||||
**The realm file is re-imported with `--override true` on every pod start.** An
|
||||
`import-realm` initContainer replays it before Keycloak serves traffic, so the
|
||||
file wins over the database and nothing created through the admin console
|
||||
survives a restart. Add clients here, never in the console.
|
||||
|
||||
**Konnect is not persisting configuration.** The operator loops on the same
|
||||
objects without converging and the dataplanes stay behind the control plane, so
|
||||
no new Kong config reaches the gateways — including any new agent audience.
|
||||
Resolve this before expecting an end-to-end run.
|
||||
**Client secrets and user passwords in that file are `${KC_SECRET_*}` /
|
||||
`${KC_USER_*}` placeholders**, substituted from the `keycloak-realm-secrets`
|
||||
Secret (Vault + ExternalSecret). Never commit a literal secret back into it.
|
||||
|
||||
## Serving A2A
|
||||
|
||||
The `a2a-sdk` 1.x server rejects a request that does not carry the protocol
|
||||
version header:
|
||||
|
||||
```
|
||||
A2A-Version: 1.0
|
||||
```
|
||||
|
||||
`DefaultRequestHandler` speaks the older 0.3 shape; use
|
||||
`DefaultRequestHandlerV2`, and mount both `create_agent_card_routes(...)` and
|
||||
`create_jsonrpc_routes(handler, "/", enable_v0_3_compat=True)`. An executor must
|
||||
enqueue the `Task` before any status update, or the client blocks waiting for a
|
||||
task it never saw. `AgentInterface` names the field `protocol_binding`, not
|
||||
`transport`.
|
||||
|
||||
## Known blockers
|
||||
|
||||
**No `employeeNumber` in tokens.** Sales territory scoping (a rep sees their
|
||||
territory, a manager sees all) resolves through
|
||||
@@ -166,8 +194,14 @@ territory, a manager sees all) resolves through
|
||||
identity, so the API cannot filter server-side. The realm's users
|
||||
(`admin-user`, `pm-user`, …) are role placeholders, not real employees.
|
||||
|
||||
**The `kong-token-exchange-broker` secret does not match the realm** — its
|
||||
`client_credentials` returns `unauthorized_client`.
|
||||
**PydanticAI's MCP client cannot open a session against Kong's
|
||||
`ai-mcp-proxy`.** It fails with `Failed to initialize server session` and
|
||||
swallows the cause. Everything else was eliminated: identity, TLS, DNS and the
|
||||
token are all fine, and the three handshake steps — `initialize` (200 with a
|
||||
session id), the SSE `GET` (200), `notifications/initialized` (202) — all
|
||||
succeed with curl using the very token the agent minted. This blocks the
|
||||
Catalogue agent end to end, and with it the Kong AI gateway path, which has
|
||||
therefore never been exercised.
|
||||
|
||||
## Conventions
|
||||
|
||||
|
||||
Reference in New Issue
Block a user