Request both the MCP and the broker audience

A token audienced only for mcp-catalog is refused by the gateway with a
bare 401. The reason is not visible to the caller: Kong's own
openid-connect plugin exchanges the token again before reaching the
backend, and Keycloak refuses that second exchange unless the token also
names kong-token-exchange-broker. The gateway log says "invalid status
code received from the token endpoint (403)"; the client sees only 401.

LibreChat already requests both audiences for the same reason. Proven end
to end with a pm-user token: aud=[mcp-catalog, kong-token-exchange-broker]
returns 200 from catalog-mcp, and the same request with aud=[mcp-catalog]
alone returns 401.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Stéphane Tailland
2026-08-28 09:14:33 +02:00
parent ba8892b0ad
commit 4fd6e21a40
+8 -2
View File
@@ -23,10 +23,16 @@ class Settings(BaseSettings):
# One entry per MCP server this agent may reach. The audience is requested # One entry per MCP server this agent may reach. The audience is requested
# as a SCOPE, not through the `audience` parameter — Keycloak answers # as a SCOPE, not through the `audience` parameter — Keycloak answers
# "Requested audience not available" to the latter. See identity.py. # "Requested audience not available" to the latter. See identity.py.
#
# Two audiences 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 Kong's onward exchange
# is refused and the caller sees a bare 401, with the real cause only in the
# gateway log ("invalid status code received from the token endpoint (403)").
mcp_catalog_url: str = "https://catalog-dev.sttlab.local/catalog-mcp" mcp_catalog_url: str = "https://catalog-dev.sttlab.local/catalog-mcp"
mcp_catalog_scope: str = "mcp-catalog-audience" mcp_catalog_scope: str = "mcp-catalog-audience kong-token-exchange-broker-audience"
mcp_sales_url: str = "https://sales-dev.sttlab.local/sales-mcp" mcp_sales_url: str = "https://sales-dev.sttlab.local/sales-mcp"
mcp_sales_scope: str = "mcp-sales-audience" mcp_sales_scope: str = "mcp-sales-audience kong-token-exchange-broker-audience"
# --- inference ---------------------------------------------------------- # --- inference ----------------------------------------------------------
# Always the Kong AI gateway, never a provider directly: it carries the rate # Always the Kong AI gateway, never a provider directly: it carries the rate