Stéphane Tailland 644c013edf fix(mcp): translate OpenAPI 3.0 nullable into JSON Schema
The response schemas added yesterday made every paginated list tool fail. The
plugin's fields are documented as OpenAPI format and validated with a JSON
Schema validator, and `nullable: true` is not a JSON Schema keyword — so it is
ignored, `type: string` is enforced, and `previous: null` on the first page is
rejected as *null is not of type "string"*.

The failure lands after the backend has already done the work, surfaces to the
caller as a bare tool retry exhaustion, and appears nowhere in the gateway's own
logs. Found only because an orchestrating agent asked a question that paged.

The generator now rewrites `nullable: true` into `type: [T, "null"]` wherever it
inlines a schema, request bodies included. A 3.1 spec needs none of this.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-29 12:19:29 +02:00
2026-08-20 13:24:10 +02:00
2026-08-20 17:27:09 +02:00

catalog-api

Kong routing/policy layer for the catalog slice of classic-models-api (see /Users/stephanetailland/git/classic-models-api), split out per the DDD decomposition in ../kong-konnect-deployment-strategy.md. The backend itself stays a single monolith — only Kong does the domain split.

Two exposure surfaces of the same API, both proxying to the real classic-models-api backend:

  • REST (kong/rest/) — 14 routes covering products/productlines.
  • MCP (kong/mcp/) — the same catalog exposed as MCP tools (list-products, get-product, create-product so far; extending to the rest is mechanical), via ai-mcp-proxy.

Auth

openid-connect on both surfaces, with a distinct audience each (catalog-api for REST, mcp-catalog for MCP) and a real RFC 8693 token exchange chain: MCP → catalog-api → classic-models-api (REST's own exchange target), narrowing the token before it ever reaches the backend — the backend never sees a token minted for a different audience. consumer_claims/consumer_by map the JWT sub to a Kong Consumer for per-consumer rate limiting; consumer_groups_claim maps realm roles to Kong Consumer Groups for MCP's per-tool ACLs.

Other policies

Per-consumer + API-level rate limiting, response caching (GET/HEAD), audit log (http-log, endpoint still a placeholder — no real log collector in this lab).

Structure

  • dev/gitrepository.yaml + dev/flux-kustomization.yaml — this repo, self-referential; deploys ./kong into the catalog domain's dev environment (dependsOn the domain's Gateway infra in dataplane-catalog).
  • dev/externalsecret.yaml — git deploy key (ESO/Vault).
  • dev/token-exchange-broker-externalsecret.yaml — the shared client secret Kong uses to authenticate its own token-exchange calls to Keycloak.
  • kong/rest/, kong/mcp/ — see above.
  • openapi.yaml — extracted from the live backend, filtered to this domain's paths/schemas.
S
Description
No description provided
Readme 116 KiB