3 Commits

Author SHA1 Message Date
Stéphane Tailland de31e0cd39 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:33 +02:00
Stéphane Tailland 67a080ac3b refactor(mcp): generate the tool definitions from the spec
Produced by k8s-platform/tools/generate-mcp-tools.py: deck file openapi2mcp
does the conversion, and the wrapper re-injects the five things Kong's
generator cannot emit — per-tool ACLs, the MCP behavioural annotations, the
response schemas the plugin uses for structuredOutput, the real upstream host,
and JSON-only request bodies. Each is a documented gap; see
k8s-platform/MCP-TOOL-GENERATION.md.

tools-policy.yaml carries the ACLs and doubles as the allow-list: an operation
becomes a tool only if the policy names it. Kong would otherwise expose every
operation in the spec, DELETE included, and can express no authorization at all
from a bearer-token spec — silently, exit 0, no warning.

Same tools as before, same ACLs. What changed: query parameters are now
declared and callable, each tool carries its response schema so calls return
structured content instead of raw JSON, and request bodies are no longer
tripled across three identical content types.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-29 08:48:40 +02:00
Stéphane Tailland 028a0be2a6 Add payments-mcp (Layer 3 MCP surface), single-route pattern from the start
list-payments/get-payment (all 5 roles) and create-payment (admin
only — matches PaymentPermission's actual write-access logic, not
guessed). One KongRoute for GET/POST/DELETE, one ai-mcp-proxy
binding — avoids the duplicate-tool-name bug found and fixed on
customers-mcp (STATUS.md section 18), built correctly here instead
of repeating the two-route mistake.

Keycloak (local): mcp-payments-audience client scope + mcp-payments
resource client, attached to librechat as an optional scope, no
dedicated protocol mappers on the client itself.
2026-08-23 16:27:56 +02:00