diff --git a/runtime/binding-mcp-http/src/main/java/io/aklivity/zilla/runtime/binding/mcp/http/config/McpHttpToolConfig.java b/runtime/binding-mcp-http/src/main/java/io/aklivity/zilla/runtime/binding/mcp/http/config/McpHttpToolConfig.java index d958350022..8299912b40 100644 --- a/runtime/binding-mcp-http/src/main/java/io/aklivity/zilla/runtime/binding/mcp/http/config/McpHttpToolConfig.java +++ b/runtime/binding-mcp-http/src/main/java/io/aklivity/zilla/runtime/binding/mcp/http/config/McpHttpToolConfig.java @@ -19,21 +19,21 @@ public final class McpHttpToolConfig { public final String name; - public final String description; public final String summary; + public final String description; public final ModelConfig input; public final ModelConfig output; public McpHttpToolConfig( String name, - String description, String summary, + String description, ModelConfig input, ModelConfig output) { this.name = name; - this.description = description; this.summary = summary; + this.description = description; this.input = input; this.output = output; } diff --git a/runtime/binding-mcp-http/src/main/java/io/aklivity/zilla/runtime/binding/mcp/http/internal/config/McpHttpOptionsConfigAdapter.java b/runtime/binding-mcp-http/src/main/java/io/aklivity/zilla/runtime/binding/mcp/http/internal/config/McpHttpOptionsConfigAdapter.java index 579f435154..6a8b7187bf 100644 --- a/runtime/binding-mcp-http/src/main/java/io/aklivity/zilla/runtime/binding/mcp/http/internal/config/McpHttpOptionsConfigAdapter.java +++ b/runtime/binding-mcp-http/src/main/java/io/aklivity/zilla/runtime/binding/mcp/http/internal/config/McpHttpOptionsConfigAdapter.java @@ -107,14 +107,14 @@ public JsonObject adaptToJson( for (McpHttpToolConfig tool : tools) { JsonObjectBuilder toolObject = Json.createObjectBuilder(); - if (tool.description != null) - { - toolObject.add(DESCRIPTION_NAME, tool.description); - } if (tool.summary != null) { toolObject.add(SUMMARY_NAME, tool.summary); } + if (tool.description != null) + { + toolObject.add(DESCRIPTION_NAME, tool.description); + } JsonObjectBuilder schemas = Json.createObjectBuilder(); if (tool.input != null) { @@ -240,14 +240,14 @@ public OptionsConfig adaptFromJson( for (String name : toolsObject.keySet()) { JsonObject toolObject = toolsObject.getJsonObject(name); - String description = toolObject.containsKey(DESCRIPTION_NAME) - ? toolObject.getString(DESCRIPTION_NAME) - : null; - String summary = toolObject.containsKey(SUMMARY_NAME) ? toolObject.getString(SUMMARY_NAME) : null; + String description = toolObject.containsKey(DESCRIPTION_NAME) + ? toolObject.getString(DESCRIPTION_NAME) + : null; + ModelConfig input = null; ModelConfig output = null; if (toolObject.containsKey(SCHEMAS_NAME)) @@ -263,7 +263,7 @@ public OptionsConfig adaptFromJson( } } - tools.add(new McpHttpToolConfig(name, description, summary, input, output)); + tools.add(new McpHttpToolConfig(name, summary, description, input, output)); } } diff --git a/runtime/binding-mcp-openapi/src/main/java/io/aklivity/zilla/runtime/binding/mcp/openapi/internal/config/composite/McpOpenapiCompositeGenerator.java b/runtime/binding-mcp-openapi/src/main/java/io/aklivity/zilla/runtime/binding/mcp/openapi/internal/config/composite/McpOpenapiCompositeGenerator.java index 23b391d32a..3d7dd6a1dc 100644 --- a/runtime/binding-mcp-openapi/src/main/java/io/aklivity/zilla/runtime/binding/mcp/openapi/internal/config/composite/McpOpenapiCompositeGenerator.java +++ b/runtime/binding-mcp-openapi/src/main/java/io/aklivity/zilla/runtime/binding/mcp/openapi/internal/config/composite/McpOpenapiCompositeGenerator.java @@ -298,8 +298,10 @@ private McpHttpOptionsConfig mcpHttpOptions( { final String description = entry.toolConfig != null && entry.toolConfig.description != null ? entry.toolConfig.description - : entry.operation.id; - tools.add(new McpHttpToolConfig(entry.tool, description, null, input, output)); + : entry.operation.description != null + ? entry.operation.description + : entry.operation.id; + tools.add(new McpHttpToolConfig(entry.tool, entry.operation.summary, description, input, output)); } else { diff --git a/runtime/binding-mcp-openapi/src/test/java/io/aklivity/zilla/runtime/binding/mcp/openapi/internal/config/composite/McpOpenapiCompositeGeneratorTest.java b/runtime/binding-mcp-openapi/src/test/java/io/aklivity/zilla/runtime/binding/mcp/openapi/internal/config/composite/McpOpenapiCompositeGeneratorTest.java index 748f6e93fd..66b58218f8 100644 --- a/runtime/binding-mcp-openapi/src/test/java/io/aklivity/zilla/runtime/binding/mcp/openapi/internal/config/composite/McpOpenapiCompositeGeneratorTest.java +++ b/runtime/binding-mcp-openapi/src/test/java/io/aklivity/zilla/runtime/binding/mcp/openapi/internal/config/composite/McpOpenapiCompositeGeneratorTest.java @@ -138,6 +138,8 @@ public class McpOpenapiCompositeGeneratorTest " }," + " \"get\": {" + " \"operationId\": \"issues/list\"," + + " \"summary\": \"List repository issues\"," + + " \"description\": \"Retrieve a paginated list of open and closed issues for the specified repository.\"," + " \"security\": []," + " \"parameters\": [" + " { \"name\": \"owner\", \"in\": \"path\", \"required\": true, \"schema\": { \"type\": \"string\" } }," + @@ -318,6 +320,56 @@ public void shouldOverrideOutputSchema() assertThat(tool.output, sameInstance(override)); } + @Test + public void shouldUseOpenapiSummaryAsToolSummary() + { + BindingConfig binding = bindingWithRoutes(route(0, "list_issues", null, "issues/list")); + + McpOpenapiCompositeConfig composite = generator.generate(new McpOpenapiBindingConfig(context, binding)); + + McpHttpOptionsConfig mcpHttpOptions = (McpHttpOptionsConfig) mcpHttp(composite).options; + McpHttpToolConfig tool = mcpHttpOptions.tools.stream() + .filter(t -> "list_issues".equals(t.name)) + .findFirst() + .orElse(null); + assertThat(tool, notNullValue()); + assertThat(tool.summary, equalTo("List repository issues")); + } + + @Test + public void shouldDefaultToolDescriptionToOperationDescriptionWhenPresent() + { + BindingConfig binding = bindingWithRoutes(route(0, "list_issues", null, "issues/list")); + + McpOpenapiCompositeConfig composite = generator.generate(new McpOpenapiBindingConfig(context, binding)); + + McpHttpOptionsConfig mcpHttpOptions = (McpHttpOptionsConfig) mcpHttp(composite).options; + McpHttpToolConfig tool = mcpHttpOptions.tools.stream() + .filter(t -> "list_issues".equals(t.name)) + .findFirst() + .orElse(null); + assertThat(tool, notNullValue()); + assertThat(tool.description, + equalTo("Retrieve a paginated list of open and closed issues for the specified repository.")); + } + + @Test + public void shouldDefaultToolDescriptionToOperationIdWhenDescriptionAbsent() + { + BindingConfig binding = bindingWithRoutes(route(0, "get_repo", null, "repos/get")); + + McpOpenapiCompositeConfig composite = generator.generate(new McpOpenapiBindingConfig(context, binding)); + + McpHttpOptionsConfig mcpHttpOptions = (McpHttpOptionsConfig) mcpHttp(composite).options; + McpHttpToolConfig tool = mcpHttpOptions.tools.stream() + .filter(t -> "get_repo".equals(t.name)) + .findFirst() + .orElse(null); + assertThat(tool, notNullValue()); + assertThat(tool.description, equalTo("repos/get")); + assertThat(tool.summary, nullValue()); + } + @Test public void shouldInterpolateQueryParameters() { diff --git a/runtime/common-openapi/src/main/java/io/aklivity/zilla/runtime/common/openapi/model/OpenapiOperation.java b/runtime/common-openapi/src/main/java/io/aklivity/zilla/runtime/common/openapi/model/OpenapiOperation.java index a6c5d851bf..41924cfc5a 100644 --- a/runtime/common-openapi/src/main/java/io/aklivity/zilla/runtime/common/openapi/model/OpenapiOperation.java +++ b/runtime/common-openapi/src/main/java/io/aklivity/zilla/runtime/common/openapi/model/OpenapiOperation.java @@ -20,6 +20,8 @@ public class OpenapiOperation { public String operationId; + public String summary; + public String description; public List parameters; public OpenapiRequestBody requestBody; public Map responses; diff --git a/runtime/common-openapi/src/main/java/io/aklivity/zilla/runtime/common/openapi/view/OpenapiOperationView.java b/runtime/common-openapi/src/main/java/io/aklivity/zilla/runtime/common/openapi/view/OpenapiOperationView.java index dfda07ced8..35815f5bcb 100644 --- a/runtime/common-openapi/src/main/java/io/aklivity/zilla/runtime/common/openapi/view/OpenapiOperationView.java +++ b/runtime/common-openapi/src/main/java/io/aklivity/zilla/runtime/common/openapi/view/OpenapiOperationView.java @@ -36,6 +36,8 @@ public final class OpenapiOperationView public final String method; public final String path; public final String id; + public final String summary; + public final String description; public final List parameters; public final OpenapiRequestBodyView requestBody; @@ -61,6 +63,8 @@ public final class OpenapiOperationView this.path = path; this.id = model.operationId; + this.summary = model.summary; + this.description = model.description; this.parameters = model.parameters != null ? model.parameters.stream() diff --git a/specs/binding-mcp-openapi.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mcp/openapi/streams/mcp/create.pr.10k/client.rpt b/specs/binding-mcp-openapi.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mcp/openapi/streams/mcp/create.pr.10k/client.rpt index 345b12f807..dd413fe107 100644 --- a/specs/binding-mcp-openapi.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mcp/openapi/streams/mcp/create.pr.10k/client.rpt +++ b/specs/binding-mcp-openapi.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mcp/openapi/streams/mcp/create.pr.10k/client.rpt @@ -54,8 +54,7 @@ write '{"name":"create_pr","arguments":{"owner":"acme","repo":"widget","title":" write ${core:randomBase64(10000)} write '"}}' -read '{"content":[{"type":"text","text":' - '"{\\"number\\":42,\\"html_url\\":\\"https://github.com/acme/widget/pull/42\\",\\"state\\":\\"open\\",\\"title\\":\\"Add feature\\"}"}],' +read '{"content":[{"type":"text","text":"Create a pull request"}],' '"structuredContent":{"number":42,"html_url":"https://github.com/acme/widget/pull/42","state":"open","title":"Add feature"},' '"isError":false' '}' diff --git a/specs/binding-mcp-openapi.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mcp/openapi/streams/mcp/create.pr.10k/server.rpt b/specs/binding-mcp-openapi.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mcp/openapi/streams/mcp/create.pr.10k/server.rpt index cc61d45c5e..ad5f9fe394 100644 --- a/specs/binding-mcp-openapi.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mcp/openapi/streams/mcp/create.pr.10k/server.rpt +++ b/specs/binding-mcp-openapi.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mcp/openapi/streams/mcp/create.pr.10k/server.rpt @@ -56,8 +56,7 @@ read '"}}' write flush -write '{"content":[{"type":"text","text":' - '"{\\"number\\":42,\\"html_url\\":\\"https://github.com/acme/widget/pull/42\\",\\"state\\":\\"open\\",\\"title\\":\\"Add feature\\"}"}],' +write '{"content":[{"type":"text","text":"Create a pull request"}],' '"structuredContent":{"number":42,"html_url":"https://github.com/acme/widget/pull/42","state":"open","title":"Add feature"},' '"isError":false' '}' diff --git a/specs/binding-mcp-openapi.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mcp/openapi/streams/mcp/create.pr/client.rpt b/specs/binding-mcp-openapi.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mcp/openapi/streams/mcp/create.pr/client.rpt index e0f34731d6..91ebc92c96 100644 --- a/specs/binding-mcp-openapi.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mcp/openapi/streams/mcp/create.pr/client.rpt +++ b/specs/binding-mcp-openapi.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mcp/openapi/streams/mcp/create.pr/client.rpt @@ -52,10 +52,8 @@ connected write '{"name":"create_pr","arguments":{"owner":"acme","repo":"widget","title":"Add feature","head":"feature","base":"main"}}' -# no summary configured -> mcp_http sets content text to the compact projected JSON read '{' - '"content":[{"type":"text","text":' - '"{\\"number\\":42,\\"html_url\\":\\"https://github.com/acme/widget/pull/42\\",\\"state\\":\\"open\\",\\"title\\":\\"Add feature\\"}"}],' + '"content":[{"type":"text","text":"Create a pull request"}],' '"structuredContent":{"number":42,"html_url":"https://github.com/acme/widget/pull/42","state":"open","title":"Add feature"},' '"isError":false' '}' diff --git a/specs/binding-mcp-openapi.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mcp/openapi/streams/mcp/create.pr/server.rpt b/specs/binding-mcp-openapi.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mcp/openapi/streams/mcp/create.pr/server.rpt index e4645aa95d..e075cc117a 100644 --- a/specs/binding-mcp-openapi.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mcp/openapi/streams/mcp/create.pr/server.rpt +++ b/specs/binding-mcp-openapi.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mcp/openapi/streams/mcp/create.pr/server.rpt @@ -55,8 +55,7 @@ read '{"name":"create_pr","arguments":{"owner":"acme","repo":"widget","title":" write flush write '{' - '"content":[{"type":"text","text":' - '"{\\"number\\":42,\\"html_url\\":\\"https://github.com/acme/widget/pull/42\\",\\"state\\":\\"open\\",\\"title\\":\\"Add feature\\"}"}],' + '"content":[{"type":"text","text":"Create a pull request"}],' '"structuredContent":{"number":42,"html_url":"https://github.com/acme/widget/pull/42","state":"open","title":"Add feature"},' '"isError":false' '}'