From 4f5e8154ce0c420bceb3f6210811668818dc3a0a Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 3 Aug 2026 17:13:32 +0000 Subject: [PATCH 1/3] fix(mcp-kafka): rename produce/consume tool docs to produce_message/consume_messages binding-mcp-kafka's TOOL_PRODUCE/TOOL_CONSUME constants were renamed to produce_message/consume_messages on develop after these docs were written. Verified against origin/develop's McpKafkaProxyFactory.java: all other mcp-kafka tool names already match the implementation. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_014ikToCpeJTceYRhdyZNGRw --- .../config/bindings/mcp-kafka/.partials/client.yaml | 4 ++-- .../config/bindings/mcp-kafka/.partials/options.md | 2 +- .../config/bindings/mcp-kafka/.partials/routes.md | 8 ++++---- .../config/bindings/mcp-kafka/.partials/tools.md | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/reference/config/bindings/mcp-kafka/.partials/client.yaml b/src/reference/config/bindings/mcp-kafka/.partials/client.yaml index eaa61899..489adbb2 100644 --- a/src/reference/config/bindings/mcp-kafka/.partials/client.yaml +++ b/src/reference/config/bindings/mcp-kafka/.partials/client.yaml @@ -14,13 +14,13 @@ mcp_kafka_client: my_guard: - kafka:admin - when: - - tool: produce + - tool: produce_message topics: [ orders ] guarded: my_guard: - kafka:write - when: - - tool: consume + - tool: consume_messages topics: [ orders ] - when: - tool: describe_configs diff --git a/src/reference/config/bindings/mcp-kafka/.partials/options.md b/src/reference/config/bindings/mcp-kafka/.partials/options.md index 2f11d1e8..7a10687f 100644 --- a/src/reference/config/bindings/mcp-kafka/.partials/options.md +++ b/src/reference/config/bindings/mcp-kafka/.partials/options.md @@ -69,6 +69,6 @@ SASL token. Required when `mechanism` is `oauthbearer`; not allowed with any oth > `array` of `object` -Per-topic key and value validation, applied to `produce` calls and to records read back by `consume`. +Per-topic key and value validation, applied to `produce_message` calls and to records read back by `consume_messages`. diff --git a/src/reference/config/bindings/mcp-kafka/.partials/routes.md b/src/reference/config/bindings/mcp-kafka/.partials/routes.md index 934cc738..0d7aae8d 100644 --- a/src/reference/config/bindings/mcp-kafka/.partials/routes.md +++ b/src/reference/config/bindings/mcp-kafka/.partials/routes.md @@ -2,18 +2,18 @@ > `array` of `object` -Conditional `mcp-kafka` specific routes, matching by tool name and, for `produce` and `consume`, by topic. At least one route is required. Routes are evaluated in order; the first matching route wins. +Conditional `mcp-kafka` specific routes, matching by tool name and, for `produce_message` and `consume_messages`, by topic. At least one route is required. Routes are evaluated in order; the first matching route wins. ```yaml routes: - when: - - tool: produce + - tool: produce_message topics: [ orders ] guarded: my_guard: - kafka:write - when: - - tool: consume + - tool: consume_messages topics: [ orders ] ``` @@ -40,7 +40,7 @@ Tool name matched by `tools/call`. Omit to match every tool not already claimed > `array` of `string` -Topic name allow-list (exact names or `*` glob patterns) restricting this route to matching topics. Only enforced for [`produce`](../client.md#produce) and [`consume`](../client.md#consume), the only two tools that name a single topic as a routing key — every other tool either takes no topic or names one as a `tools/call` argument rather than a route match, so this list has no effect on them. +Topic name allow-list (exact names or `*` glob patterns) restricting this route to matching topics. Only enforced for [`produce_message`](../client.md#produce_message) and [`consume_messages`](../client.md#consume_messages), the only two tools that name a single topic as a routing key — every other tool either takes no topic or names one as a `tools/call` argument rather than a route match, so this list has no effect on them. #### routes[].guarded diff --git a/src/reference/config/bindings/mcp-kafka/.partials/tools.md b/src/reference/config/bindings/mcp-kafka/.partials/tools.md index 830691a8..77d65647 100644 --- a/src/reference/config/bindings/mcp-kafka/.partials/tools.md +++ b/src/reference/config/bindings/mcp-kafka/.partials/tools.md @@ -1,6 +1,6 @@ The `mcp-kafka` client exposes a fixed set of intrinsic tools — there is no `options.tools` to author, and no upstream server or spec to derive them from. Each tool's `inputSchema` validates `tools/call` `arguments` before Zilla dispatches the matching Kafka request; a tool with no declared `outputSchema` still returns a result, either as `structuredContent` or as `content` text only. -### produce +### produce_message > Not read-only, not idempotent @@ -15,7 +15,7 @@ Appends one record to a topic. No `outputSchema` is declared; the result is a `content` text summary only. -### consume +### consume_messages > Read-only, idempotent From 88c7e84d391154c44ed8f925094608ed37945994 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 3 Aug 2026 17:23:38 +0000 Subject: [PATCH 2/3] fix(mcp): correct remaining drift between mcp-* tools docs and implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Systematic audit of every mcp-* binding's tools documentation against zilla's current develop implementation, beyond the produce/consume rename already fixed: - mcp-openapi: fix the cross-link to mcp-kafka-connect/mcp-schema-registry in the x-zilla-mcp callout — @include'd partials resolve relative links from the partial file's own path (mcp-openapi/.partials/), so reaching a sibling binding directory needs two levels up, not one. This was breaking the linkChecker CI job. - mcp-openapi: resources.description has no fallback to the operation's native description/operation id (unlike tools.description) — the doc claimed one that McpOpenapiCompositeGenerator doesn't implement. - mcp-openapi: remove when[].capability from routes.md — no such field exists on McpOpenapiConditionConfig, and the JSON schema patch would reject it outright. - mcp-http: document tools.title and tools.annotations (with its 4 hint fields) — both exist and are fully wired in McpHttpToolConfig / McpHttpOptionsConfigAdapter but were never documented. - mcp-kafka-connect / mcp-schema-registry: correct required/optional status for every request-body-derived tool argument. Neither bundled OpenAPI spec declares a JSON-Schema `required` array on any request body, and McpOpenapiCompositeGenerator only required-flags a body property when one exists, so these arguments are actually optional in the generated tool despite being documented as required. - mcp (base): eager.policy's none/all semantics were exactly swapped — none (default) disables partitioning entirely so every tool stays eager, and all marks every tool cold, per McpProxyCache.eager()/ eagerConfigured() and confirmed against the binding's own K3PO specs. Verified every finding directly against origin/develop source in the zilla repo before fixing (OpenAPI spec JSON, config classes, composite generator, K3PO scripts) rather than trusting audit-agent output blind. Re-ran pnpm lint and a full pnpm link-checker build locally: 0 errors. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_014ikToCpeJTceYRhdyZNGRw --- .../bindings/mcp-http/.partials/options.md | 43 +++++++++++++++++++ .../mcp-kafka-connect/.partials/tools.md | 18 ++++---- .../bindings/mcp-openapi/.partials/options.md | 4 +- .../bindings/mcp-openapi/.partials/routes.md | 17 +------- .../mcp-schema-registry/.partials/tools.md | 6 +-- .../bindings/mcp/.partials/options-proxy.md | 2 +- 6 files changed, 59 insertions(+), 31 deletions(-) diff --git a/src/reference/config/bindings/mcp-http/.partials/options.md b/src/reference/config/bindings/mcp-http/.partials/options.md index 112df75f..99177c47 100644 --- a/src/reference/config/bindings/mcp-http/.partials/options.md +++ b/src/reference/config/bindings/mcp-http/.partials/options.md @@ -69,6 +69,12 @@ HTTP request headers added to the upstream request, with values resolved from th MCP tools terminated by this binding and expanded into `http` requests. The named key is the tool name surfaced to MCP clients by `tools/list` and matched by `tools/call`. +#### tools.title + +> `string` + +Tool title surfaced to MCP clients by `tools/list`. Unlike [`tools.description`](#tools-description), there is no fallback — a tool with no authored `title` has none. + #### tools.description > `string` @@ -123,6 +129,43 @@ Specific version of the registered schema. Converter validating and projecting the upstream `http` response, surfaced as the tool-call `structuredContent`. Uses the same shape as [`schemas.input`](#schemas-input). +#### tools.annotations + +> `object` + +Behavior hints surfaced to MCP clients by `tools/list`. Unlike [`mcp-openapi`](../mcp-openapi/README.md)'s `tools.annotations`, there is no HTTP-method-derived default — a hint left unset here is simply absent. Each hint resolves independently — overriding one does not require overriding the others. + +```yaml +annotations: + readOnlyHint: false + destructiveHint: false + idempotentHint: false +``` + +#### annotations.readOnlyHint + +> `boolean` + +Whether the tool only reads data without modifying any state. + +#### annotations.destructiveHint + +> `boolean` + +Whether the tool may perform a destructive update. + +#### annotations.idempotentHint + +> `boolean` + +Whether calling the tool repeatedly with the same arguments has no additional effect beyond the first call. + +#### annotations.openWorldHint + +> `boolean` + +Whether the tool interacts with an open-ended set of external entities, rather than a fixed, closed set. + #### options.resources > `object` as map of named `object` diff --git a/src/reference/config/bindings/mcp-kafka-connect/.partials/tools.md b/src/reference/config/bindings/mcp-kafka-connect/.partials/tools.md index 0f139cb7..c431a652 100644 --- a/src/reference/config/bindings/mcp-kafka-connect/.partials/tools.md +++ b/src/reference/config/bindings/mcp-kafka-connect/.partials/tools.md @@ -18,8 +18,8 @@ Creates a new connector. | Argument | Type | Required | Description | | --- | --- | --- | --- | -| `name` | `string` | Yes | Connector name. | -| `config` | `object` as map of named `string` | Yes | Connector configuration properties. | +| `name` | `string` | No | Connector name. | +| `config` | `object` as map of named `string` | No | Connector configuration properties. | No fixed `outputSchema` is declared; the result's `structuredContent` mirrors the raw upstream JSON response, with no fixed property list. The summary interpolates `${result.name}`. @@ -68,8 +68,8 @@ Creates or updates a connector by setting its full configuration. | Argument | Type | Required | Description | | --- | --- | --- | --- | | `connector` | `string` | Yes | Connector to configure. | -| `connector.class` | `string` | Yes | Connector class to instantiate. | -| `tasks.max` | `string` | Yes | Maximum number of tasks to run. | +| `connector.class` | `string` | No | Connector class to instantiate. | +| `tasks.max` | `string` | No | Maximum number of tasks to run. | No fixed `outputSchema` is declared; the result's `structuredContent` mirrors the raw upstream JSON response, with no fixed property list. The summary interpolates `${result.name}`. @@ -82,8 +82,8 @@ Validates a connector configuration against a plugin's configuration definition, | Argument | Type | Required | Description | | --- | --- | --- | --- | | `pluginName` | `string` | Yes | Connector plugin to validate against. | -| `connector.class` | `string` | Yes | Connector class to validate. | -| `tasks.max` | `string` | Yes | Maximum number of tasks to validate. | +| `connector.class` | `string` | No | Connector class to validate. | +| `tasks.max` | `string` | No | Maximum number of tasks to validate. | No fixed `outputSchema` is declared; the result's `structuredContent` mirrors the raw upstream JSON response, with no fixed property list. The summary interpolates `${result.error_count}`, such as `Validated connector config with 0 errors`. @@ -193,9 +193,9 @@ Overwrites a connector's source or sink offsets. The connector must be stopped f | Argument | Type | Required | Description | | --- | --- | --- | --- | | `connector` | `string` | Yes | Connector whose offsets to alter. | -| `offsets` | `array` of `object` | Yes | Offsets to write. | -| `offsets[].partition` | `object` | Yes | Source partition or sink topic-partition identifying the offset. | -| `offsets[].offset` | `object` | Yes | New offset value for the identified partition. | +| `offsets` | `array` of `object` | No | Offsets to write. | +| `offsets[].partition` | `object` | No | Source partition or sink topic-partition identifying the offset. | +| `offsets[].offset` | `object` | No | New offset value for the identified partition. | No fixed `outputSchema` is declared; the result's `structuredContent` mirrors the raw upstream JSON response, with no fixed property list. The summary interpolates `${result.message}`. diff --git a/src/reference/config/bindings/mcp-openapi/.partials/options.md b/src/reference/config/bindings/mcp-openapi/.partials/options.md index f24c1cb8..47ab8fda 100644 --- a/src/reference/config/bindings/mcp-openapi/.partials/options.md +++ b/src/reference/config/bindings/mcp-openapi/.partials/options.md @@ -121,7 +121,7 @@ paths: idempotentHint: false ``` -[`tools.title`](#tools-title), [`tools.description`](#tools-description), and each [`tools.annotations`](#tools-annotations) hint fall back to this extension before falling back further still. This is how [`mcp-kafka-connect`](../mcp-kafka-connect/client.md) and [`mcp-schema-registry`](../mcp-schema-registry/client.md) supply real tool titles, descriptions, and annotations for their bundled specs via an `overlay`, without editing the vendored OpenAPI document itself. +[`tools.title`](#tools-title), [`tools.description`](#tools-description), and each [`tools.annotations`](#tools-annotations) hint fall back to this extension before falling back further still. This is how [`mcp-kafka-connect`](../../mcp-kafka-connect/client.md) and [`mcp-schema-registry`](../../mcp-schema-registry/client.md) supply real tool titles, descriptions, and annotations for their bundled specs via an `overlay`, without editing the vendored OpenAPI document itself. ::: #### specs.security @@ -246,7 +246,7 @@ Overrides for MCP resources generated from routed OpenAPI operations. The named > `string` -Resource description surfaced to MCP clients by `resources/list`, overriding the OpenAPI operation's own `description`, which is itself the fallback before the operation id. +Resource description surfaced to MCP clients by `resources/list`. Unlike [`tools.description`](#tools-description), there is no fallback to the OpenAPI operation's own `description` or its operation id — a resource with no authored override here has no description. #### resources.mimeType diff --git a/src/reference/config/bindings/mcp-openapi/.partials/routes.md b/src/reference/config/bindings/mcp-openapi/.partials/routes.md index 7c27e665..15e5df73 100644 --- a/src/reference/config/bindings/mcp-openapi/.partials/routes.md +++ b/src/reference/config/bindings/mcp-openapi/.partials/routes.md @@ -7,7 +7,7 @@ Conditional `mcp-openapi` specific routes, compiling matched OpenAPI operations A route either names a single operation explicitly, or bulk-selects many operations at once: - **Explicit** — [`with.operation`](#with-operation) names one exact `operationId`. May pair with [`when[].tool`](#when-tool) or [`when[].resource`](#when-resource) to name and shape the generated MCP primitive. -- **Bulk** — [`with.spec`](#with-spec) alone selects every operation in the spec, [`with.tag`](#with-tag) selects every operation carrying the named OpenAPI tag, or [`with.operation`](#with-operation) containing a `*` selects every operation whose id matches the glob pattern. Bulk-selected operations always become tools, never resources, and cannot be named with `when[].tool` or `when[].resource` — each is named automatically. [`when[].capability`](#when-capability) can still restrict a bulk route to only `tool` or only `resource`. +- **Bulk** — [`with.spec`](#with-spec) alone selects every operation in the spec, [`with.tag`](#with-tag) selects every operation carrying the named OpenAPI tag, or [`with.operation`](#with-operation) containing a `*` selects every operation whose id matches the glob pattern. Bulk-selected operations always become tools, never resources, and cannot be named with `when[].tool` or `when[].resource` — each is named automatically. ```yaml routes: @@ -71,21 +71,6 @@ Resource identifier matched by `resources/read`, naming the explicit OpenAPI ope An operation whose OpenAPI path contains a `{param}` capture is surfaced as a resource template through `resources/templates/list`. Otherwise it is a concrete resource surfaced through `resources/list`, with any query parameters appended to its URI as an RFC 6570 `{?name1,name2}` suffix rather than disqualifying it from being concrete. ::: -#### when[].capability - -> `array` of `enum` [ `tool`, `resource` ] - -Restricts a bulk route to only the listed primitive kinds. An explicit route naming [`when[].tool`](#when-tool) or [`when[].resource`](#when-resource) is filtered accordingly whether or not `capability` is also listed. - -```yaml -routes: - - when: - - capability: [ tool ] - with: - spec: github - tag: issues -``` - #### routes[].with\* > `object` diff --git a/src/reference/config/bindings/mcp-schema-registry/.partials/tools.md b/src/reference/config/bindings/mcp-schema-registry/.partials/tools.md index 2073a549..753a2713 100644 --- a/src/reference/config/bindings/mcp-schema-registry/.partials/tools.md +++ b/src/reference/config/bindings/mcp-schema-registry/.partials/tools.md @@ -31,7 +31,7 @@ Registers a new schema version under a subject. | Argument | Type | Required | Description | | --- | --- | --- | --- | | `subject` | `string` | Yes | Subject to register the schema under. | -| `schema` | `string` | Yes | Schema document to register. | +| `schema` | `string` | No | Schema document to register. | | `schemaType` | `string` | No | Schema format, such as `AVRO`, `JSON`, or `PROTOBUF`. Defaults to `AVRO` when omitted. | The summary interpolates `${result.id}`, such as `Registered schema with id 1`. @@ -82,7 +82,7 @@ Checks whether a schema is compatible with a specific already-registered version | --- | --- | --- | --- | | `subject` | `string` | Yes | Subject to check compatibility against. | | `version` | `string` | Yes | Schema version number, or `latest`, to check compatibility against. | -| `schema` | `string` | Yes | Schema document to check. | +| `schema` | `string` | No | Schema document to check. | | `schemaType` | `string` | No | Schema format, such as `AVRO`, `JSON`, or `PROTOBUF`. Defaults to `AVRO` when omitted. | The summary interpolates `${result.is_compatible}`, such as `Compatibility check result: true`. @@ -108,6 +108,6 @@ Sets the compatibility level for a subject. | Argument | Type | Required | Description | | --- | --- | --- | --- | | `subject` | `string` | Yes | Subject to set the compatibility level of. | -| `compatibility` | `string` | Yes | Compatibility level, such as `BACKWARD`, `FORWARD`, `FULL`, or `NONE`. | +| `compatibility` | `string` | No | Compatibility level, such as `BACKWARD`, `FORWARD`, `FULL`, or `NONE`. | The summary interpolates `${result.compatibility}`, such as `Compatibility level set to FULL`. diff --git a/src/reference/config/bindings/mcp/.partials/options-proxy.md b/src/reference/config/bindings/mcp/.partials/options-proxy.md index a2be816c..499e7a61 100644 --- a/src/reference/config/bindings/mcp/.partials/options-proxy.md +++ b/src/reference/config/bindings/mcp/.partials/options-proxy.md @@ -137,7 +137,7 @@ tools: > `enum` [ `none`, `all`, `explicit` ] | Default: `none` -Which cached tools are eager. `none` marks every tool cold, `all` marks every tool eager, and `explicit` marks only tools matching [`match`](#eager-match) eager. +Which cached tools are eager. `none` marks every tool eager (no partitioning is applied), `all` marks every tool cold, and `explicit` marks only tools matching [`match`](#eager-match) eager, leaving every other tool cold. #### eager.match From d778132ada10156f4ce3004e4d7377e986b8feb9 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 3 Aug 2026 17:27:46 +0000 Subject: [PATCH 3/3] fix(mcp-http): correct sibling-binding link depth introduced in prior commit Same @include relative-link resolution rule as the mcp-openapi fix earlier in this branch: a link from within mcp-http/.partials/options.md needs two levels up to reach a sibling binding directory, not one. Verified with a full local pnpm link-checker build: 0 errors. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_014ikToCpeJTceYRhdyZNGRw --- src/reference/config/bindings/mcp-http/.partials/options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reference/config/bindings/mcp-http/.partials/options.md b/src/reference/config/bindings/mcp-http/.partials/options.md index 99177c47..3232f133 100644 --- a/src/reference/config/bindings/mcp-http/.partials/options.md +++ b/src/reference/config/bindings/mcp-http/.partials/options.md @@ -133,7 +133,7 @@ Converter validating and projecting the upstream `http` response, surfaced as th > `object` -Behavior hints surfaced to MCP clients by `tools/list`. Unlike [`mcp-openapi`](../mcp-openapi/README.md)'s `tools.annotations`, there is no HTTP-method-derived default — a hint left unset here is simply absent. Each hint resolves independently — overriding one does not require overriding the others. +Behavior hints surfaced to MCP clients by `tools/list`. Unlike [`mcp-openapi`](../../mcp-openapi/README.md)'s `tools.annotations`, there is no HTTP-method-derived default — a hint left unset here is simply absent. Each hint resolves independently — overriding one does not require overriding the others. ```yaml annotations: