This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git

commit 47428cf6438143d78b42b115fe3288c62a6240d9
Author: James Bognar <[email protected]>
AuthorDate: Tue Jul 28 15:38:11 2026 -0400

    test: capture MCP JSON-RPC characterization fixtures against pre-refactor 
behavior
    
    35 request/response fixture pairs covering every dispatched JSON-RPC method 
and
    every reachable error code, captured through the HTTP servlet path so 
addBeanTypes
    polymorphic discrimination is pinned too. These encode current behavior 
including
    the known-wrong -32601 collapse for tool/prompt/resource-not-found.
    
    Co-authored-by: Cursor <[email protected]>
---
 .../rest/server/mcp/Characterization_Test.java     | 185 +++++++++++++++++++++
 .../characterization/CAPS-initialize.request.json  |   1 +
 .../characterization/CAPS-initialize.response.json |   1 +
 .../EMPTY-empty-method.request.json                |   1 +
 .../EMPTY-empty-method.response.json               |   1 +
 .../characterization/EMPTY-initialize.request.json |   1 +
 .../EMPTY-initialize.response.json                 |   1 +
 .../EMPTY-missing-method.request.json              |   1 +
 .../EMPTY-missing-method.response.json             |   1 +
 .../EMPTY-notification-ping.request.json           |   1 +
 .../EMPTY-notification-ping.response.json          |   1 +
 .../EMPTY-notification-unknown.request.json        |   1 +
 .../EMPTY-notification-unknown.response.json       |   1 +
 .../characterization/EMPTY-ping.request.json       |   1 +
 .../characterization/EMPTY-ping.response.json      |   1 +
 .../EMPTY-prompts-get-missing-name.request.json    |   1 +
 .../EMPTY-prompts-get-missing-name.response.json   |   1 +
 .../EMPTY-prompts-get-unknown.request.json         |   1 +
 .../EMPTY-prompts-get-unknown.response.json        |   1 +
 .../EMPTY-prompts-list.request.json                |   1 +
 .../EMPTY-prompts-list.response.json               |   1 +
 .../EMPTY-resources-list.request.json              |   1 +
 .../EMPTY-resources-list.response.json             |   1 +
 .../EMPTY-resources-read-missing-uri.request.json  |   1 +
 .../EMPTY-resources-read-missing-uri.response.json |   1 +
 .../EMPTY-resources-read-unknown.request.json      |   1 +
 .../EMPTY-resources-read-unknown.response.json     |   1 +
 .../EMPTY-tools-call-missing-name.request.json     |   1 +
 .../EMPTY-tools-call-missing-name.response.json    |   1 +
 .../EMPTY-tools-call-unknown-tool.request.json     |   1 +
 .../EMPTY-tools-call-unknown-tool.response.json    |   1 +
 .../characterization/EMPTY-tools-list.request.json |   1 +
 .../EMPTY-tools-list.response.json                 |   1 +
 .../EMPTY-unknown-method.request.json              |   1 +
 .../EMPTY-unknown-method.response.json             |   1 +
 .../characterization/FULL-initialize.request.json  |   1 +
 .../characterization/FULL-initialize.response.json |   1 +
 .../characterization/FULL-prompts-get.request.json |   1 +
 .../FULL-prompts-get.response.json                 |   1 +
 .../FULL-prompts-list.request.json                 |   1 +
 .../FULL-prompts-list.response.json                |   1 +
 .../FULL-resources-list.request.json               |   1 +
 .../FULL-resources-list.response.json              |   1 +
 .../FULL-resources-read.request.json               |   1 +
 .../FULL-resources-read.response.json              |   1 +
 .../characterization/FULL-string-id.request.json   |   1 +
 .../characterization/FULL-string-id.response.json  |   1 +
 .../FULL-tools-call-arguments-not-map.request.json |   1 +
 ...FULL-tools-call-arguments-not-map.response.json |   1 +
 .../FULL-tools-call-error-flag.request.json        |   1 +
 .../FULL-tools-call-error-flag.response.json       |   1 +
 .../FULL-tools-call-mixed-content.request.json     |   1 +
 .../FULL-tools-call-mixed-content.response.json    |   1 +
 .../FULL-tools-call-no-arguments.request.json      |   1 +
 .../FULL-tools-call-no-arguments.response.json     |   1 +
 .../FULL-tools-call-params-not-map.request.json    |   1 +
 .../FULL-tools-call-params-not-map.response.json   |   1 +
 .../FULL-tools-call-text.request.json              |   1 +
 .../FULL-tools-call-text.response.json             |   1 +
 .../characterization/FULL-tools-list.request.json  |   1 +
 .../characterization/FULL-tools-list.response.json |   1 +
 .../PAGED-tools-list-first.request.json            |   1 +
 .../PAGED-tools-list-first.response.json           |   1 +
 .../PAGED-tools-list-second.request.json           |   1 +
 .../PAGED-tools-list-second.response.json          |   1 +
 .../THROW-mcp-exception.request.json               |   1 +
 .../THROW-mcp-exception.response.json              |   1 +
 .../characterization/THROW-no-message.request.json |   1 +
 .../THROW-no-message.response.json                 |   1 +
 .../THROW-runtime-exception.request.json           |   1 +
 .../THROW-runtime-exception.response.json          |   1 +
 71 files changed, 255 insertions(+)

diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/java/org/apache/juneau/rest/server/mcp/Characterization_Test.java
 
b/juneau-rest/juneau-rest-server-mcp/src/test/java/org/apache/juneau/rest/server/mcp/Characterization_Test.java
new file mode 100644
index 0000000000..0fc80b4788
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/java/org/apache/juneau/rest/server/mcp/Characterization_Test.java
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juneau.rest.server.mcp;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.nio.file.*;
+import java.util.*;
+import java.util.function.*;
+
+import org.apache.juneau.bean.mcp.*;
+import org.apache.juneau.commons.inject.*;
+import org.apache.juneau.marshall.collections.*;
+import org.apache.juneau.marshall.json.*;
+import org.apache.juneau.rest.mock.classic.*;
+import org.apache.juneau.rest.server.*;
+import org.junit.jupiter.params.*;
+import org.junit.jupiter.params.provider.*;
+
+/**
+ * Wire-compatibility characterization fixtures for the MCP JSON-RPC endpoint.
+ *
+ * <p>
+ * These fixtures encode <em>current</em> behavior, including behavior known 
to be wrong (all four
+ * "not found" kinds collapse to {@code -32601}). They are deliberately not 
named {@code golden/}.
+ * A fixture body must never be edited to accommodate a code change: if replay 
fails, the code
+ * change is wrong.
+ *
+ * <p>
+ * Regenerate the {@code *.response.json} files (only ever against known-good 
code) with:
+ * <p>
+ * {@code mvn test -Drat.skip=true -pl juneau-rest/juneau-rest-server-mcp 
-Dtest=Characterization_Test -Djuneau.mcp.characterization.write=true}
+ */
+@SuppressWarnings({
+       "resource" // MockRestClient is a Closeable test helper; lifetime is 
bounded by the test method.
+})
+class Characterization_Test {
+
+       private static final Path DIR = 
Paths.get("src/test/resources/characterization");
+       private static final boolean WRITE = 
Boolean.getBoolean("juneau.mcp.characterization.write");
+
+       // --- fixture servlets 
-------------------------------------------------------------------
+
+       @Rest(serializers = JsonSerializer.class, parsers = JsonParser.class, 
defaultAccept = "application/json")
+       public static class F_Empty extends McpRestServlet {
+               private static final long serialVersionUID = 1L;
+               @Override protected McpServerConfig createMcpConfig() { return 
new McpServerConfig(); }
+       }
+
+       @Rest(serializers = JsonSerializer.class, parsers = JsonParser.class, 
defaultAccept = "application/json")
+       public static class F_Full extends McpRestServlet {
+               private static final long serialVersionUID = 1L;
+               @Override protected McpServerConfig createMcpConfig() {
+                       return new McpServerConfig()
+                               .setServerInfo(new 
Implementation().setName("characterization").setVersion("1.0.0"))
+                               .setInstructions("Be concise.")
+                               .addTool(tool("echo", new 
JsonSchema().setType("object").setRequired("text"), a -> new CallToolResult()
+                                       .setContent(List.of(new 
TextContent().setText(String.valueOf(a.get("text")))))))
+                               .addTool(tool("mixed", null, a -> new 
CallToolResult().setContent(List.of(
+                                       new TextContent().setText("t"),
+                                       new 
ImageContent().setData("AAA=").setMimeType("image/png"),
+                                       new 
EmbeddedResourceContent().setResource(
+                                               new 
TextResourceContents().setUri("file:///e").setMimeType("text/plain").setText("emb"))))))
+                               .addTool(tool("failing", null, a -> new 
CallToolResult().setIsError(true)
+                                       .setContent(List.of(new 
TextContent().setText("nope")))))
+                               .addPrompt(prompt("greet", a -> new 
GetPromptResult().setDescription("d").setMessages(List.of(
+                                       new 
PromptMessage().setRole(Role.USER).setContent(new TextContent().setText("hi " + 
a.get("who")))))))
+                               .addResource(resource("file:///a", u -> new 
ReadResourceResult().setContents(List.of(
+                                       new 
TextResourceContents().setUri(u).setMimeType("text/plain").setText("body")))));
+               }
+       }
+
+       @Rest(serializers = JsonSerializer.class, parsers = JsonParser.class, 
defaultAccept = "application/json")
+       public static class F_Caps extends McpRestServlet {
+               private static final long serialVersionUID = 1L;
+               @Override protected McpServerConfig createMcpConfig() {
+                       return new McpServerConfig()
+                               .setCapabilities(new ServerCapabilities()
+                                       .setLogging(new 
LoggingCapability().setLevel("info"))
+                                       .setResources(new 
ResourceCapability().setSubscribe(true).setListChanged(true))
+                                       .setExperimental(JsonMap.of("flag", 
1)));
+               }
+       }
+
+       @Rest(serializers = JsonSerializer.class, parsers = JsonParser.class, 
defaultAccept = "application/json")
+       public static class F_Paged extends McpRestServlet {
+               private static final long serialVersionUID = 1L;
+               @Override protected McpServerConfig createMcpConfig() {
+                       return new McpServerConfig()
+                               .setCursor(McpCursor.fixedSize(1))
+                               .addTool(tool("t1", null, a -> new 
CallToolResult()))
+                               .addTool(tool("t2", null, a -> new 
CallToolResult()));
+               }
+       }
+
+       @Rest(serializers = JsonSerializer.class, parsers = JsonParser.class, 
defaultAccept = "application/json")
+       public static class F_Throw extends McpRestServlet {
+               private static final long serialVersionUID = 1L;
+               @Override protected McpServerConfig createMcpConfig() {
+                       return new McpServerConfig()
+                               .addTool(tool("mcpEx", null, a -> { throw new 
McpException(-32099, "nope", JsonMap.of("k", "v")); }))
+                               .addTool(tool("boom", null, a -> { throw new 
RuntimeException("boom"); }))
+                               .addTool(tool("silent", null, a -> { throw new 
IllegalStateException(); }));
+               }
+       }
+
+       // --- fixture handler factories 
---------------------------------------------------------
+
+       private static McpToolHandler tool(String name, JsonSchema schema, 
Function<Map<String,Object>,CallToolResult> fn) {
+               return new McpToolHandler() {
+                       @Override public Tool descriptor() { return new 
Tool().setName(name).setDescription("desc:" + name).setInputSchema(schema); }
+                       @Override public CallToolResult call(Map<String,Object> 
arguments, BeanStore ctx) { return fn.apply(arguments); }
+               };
+       }
+
+       private static McpPromptHandler prompt(String name, 
Function<Map<String,Object>,GetPromptResult> fn) {
+               return new McpPromptHandler() {
+                       @Override public Prompt descriptor() { return new 
Prompt().setName(name).setDescription("pd"); }
+                       @Override public GetPromptResult get(Map<String,Object> 
arguments, BeanStore ctx) { return fn.apply(arguments); }
+               };
+       }
+
+       private static McpResourceHandler resource(String uri, 
Function<String,ReadResourceResult> fn) {
+               return new McpResourceHandler() {
+                       @Override public Resource descriptor() { return new 
Resource().setUri(uri).setName("a").setMimeType("text/plain"); }
+                       @Override public ReadResourceResult read(String u, 
BeanStore ctx) { return fn.apply(u); }
+               };
+       }
+
+       private static Class<?> servletFor(String fixture) {
+               var prefix = fixture.substring(0, fixture.indexOf('-'));
+               return switch (prefix) {
+                       case "EMPTY" -> F_Empty.class;
+                       case "FULL" -> F_Full.class;
+                       case "CAPS" -> F_Caps.class;
+                       case "PAGED" -> F_Paged.class;
+                       case "THROW" -> F_Throw.class;
+                       default -> throw new IllegalArgumentException("Unknown 
fixture prefix: " + prefix);
+               };
+       }
+
+       // --- replay 
----------------------------------------------------------------------------
+
+       static List<String> fixtures() throws Exception {
+               try (var s = Files.list(DIR)) {
+                       return s.map(x -> x.getFileName().toString())
+                               .filter(x -> x.endsWith(".request.json"))
+                               .map(x -> x.substring(0, x.length() - 
".request.json".length()))
+                               .sorted()
+                               .toList();
+               }
+       }
+
+       @ParameterizedTest
+       @MethodSource("fixtures")
+       void a01_wireIsUnchanged(String fixture) throws Exception {
+               var requestBody = Files.readString(DIR.resolve(fixture + 
".request.json")).strip();
+               var client = MockRestClient.create(servletFor(fixture)).json()
+                       
.contentType("application/json").accept("application/json").ignoreErrors().build();
+               var res = client.post("/").contentString(requestBody).run();
+               assertEquals(200, res.getStatusCode(), () -> fixture + ": HTTP 
status changed");
+               var actual = res.getContent().asString();
+               var expected = DIR.resolve(fixture + ".response.json");
+               if (WRITE) {
+                       Files.writeString(expected, actual);
+                       return;
+               }
+               assertEquals(Files.readString(expected), actual,
+                       () -> fixture + ": WIRE FORMAT CHANGED. Do not update 
the fixture — fix the code.");
+       }
+}
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/CAPS-initialize.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/CAPS-initialize.request.json
new file mode 100644
index 0000000000..1ae1231b50
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/CAPS-initialize.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"initialize"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/CAPS-initialize.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/CAPS-initialize.response.json
new file mode 100644
index 0000000000..efb252d962
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/CAPS-initialize.response.json
@@ -0,0 +1 @@
+{"id":1,"jsonrpc":"2.0","result":{"capabilities":{"experimental":{"flag":1},"logging":{"level":"info"},"resources":{"listChanged":true,"subscribe":true}},"protocolVersion":"2025-06-18","serverInfo":{"name":"juneau-rest-server-mcp","version":"unknown"}}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-empty-method.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-empty-method.request.json
new file mode 100644
index 0000000000..e185dc3f05
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-empty-method.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":""}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-empty-method.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-empty-method.response.json
new file mode 100644
index 0000000000..17edff8059
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-empty-method.response.json
@@ -0,0 +1 @@
+{"error":{"code":-32600,"message":"Missing method"},"id":1,"jsonrpc":"2.0"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-initialize.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-initialize.request.json
new file mode 100644
index 0000000000..1ae1231b50
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-initialize.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"initialize"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-initialize.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-initialize.response.json
new file mode 100644
index 0000000000..cc2a22bc30
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-initialize.response.json
@@ -0,0 +1 @@
+{"id":1,"jsonrpc":"2.0","result":{"capabilities":{},"protocolVersion":"2025-06-18","serverInfo":{"name":"juneau-rest-server-mcp","version":"unknown"}}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-missing-method.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-missing-method.request.json
new file mode 100644
index 0000000000..2fc2fc2952
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-missing-method.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-missing-method.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-missing-method.response.json
new file mode 100644
index 0000000000..17edff8059
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-missing-method.response.json
@@ -0,0 +1 @@
+{"error":{"code":-32600,"message":"Missing method"},"id":1,"jsonrpc":"2.0"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-notification-ping.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-notification-ping.request.json
new file mode 100644
index 0000000000..dff54af339
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-notification-ping.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","method":"ping"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-notification-ping.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-notification-ping.response.json
new file mode 100644
index 0000000000..ec747fa47d
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-notification-ping.response.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-notification-unknown.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-notification-unknown.request.json
new file mode 100644
index 0000000000..ec7674a81b
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-notification-unknown.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","method":"no/such/method"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-notification-unknown.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-notification-unknown.response.json
new file mode 100644
index 0000000000..ec747fa47d
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-notification-unknown.response.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-ping.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-ping.request.json
new file mode 100644
index 0000000000..6f097ab5ab
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-ping.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"ping"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-ping.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-ping.response.json
new file mode 100644
index 0000000000..26d35bb1a7
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-ping.response.json
@@ -0,0 +1 @@
+{"id":1,"jsonrpc":"2.0","result":{}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-prompts-get-missing-name.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-prompts-get-missing-name.request.json
new file mode 100644
index 0000000000..f106d1e194
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-prompts-get-missing-name.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"prompts/get","params":{}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-prompts-get-missing-name.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-prompts-get-missing-name.response.json
new file mode 100644
index 0000000000..3c0d93e9a6
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-prompts-get-missing-name.response.json
@@ -0,0 +1 @@
+{"error":{"code":-32602,"message":"Missing prompt 
name"},"id":1,"jsonrpc":"2.0"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-prompts-get-unknown.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-prompts-get-unknown.request.json
new file mode 100644
index 0000000000..658d0255c7
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-prompts-get-unknown.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"prompts/get","params":{"name":"missing"}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-prompts-get-unknown.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-prompts-get-unknown.response.json
new file mode 100644
index 0000000000..a8afcb970a
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-prompts-get-unknown.response.json
@@ -0,0 +1 @@
+{"error":{"code":-32601,"message":"Prompt not found: 
missing"},"id":1,"jsonrpc":"2.0"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-prompts-list.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-prompts-list.request.json
new file mode 100644
index 0000000000..3bda935b3d
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-prompts-list.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"prompts/list"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-prompts-list.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-prompts-list.response.json
new file mode 100644
index 0000000000..6fa6df4f7a
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-prompts-list.response.json
@@ -0,0 +1 @@
+{"id":1,"jsonrpc":"2.0","result":{"prompts":[]}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-resources-list.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-resources-list.request.json
new file mode 100644
index 0000000000..b10e040403
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-resources-list.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"resources/list"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-resources-list.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-resources-list.response.json
new file mode 100644
index 0000000000..81a1dc1288
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-resources-list.response.json
@@ -0,0 +1 @@
+{"id":1,"jsonrpc":"2.0","result":{"resources":[]}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-resources-read-missing-uri.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-resources-read-missing-uri.request.json
new file mode 100644
index 0000000000..9c4e4b95ad
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-resources-read-missing-uri.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"resources/read","params":{}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-resources-read-missing-uri.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-resources-read-missing-uri.response.json
new file mode 100644
index 0000000000..dd5157816b
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-resources-read-missing-uri.response.json
@@ -0,0 +1 @@
+{"error":{"code":-32602,"message":"Missing resource 
uri"},"id":1,"jsonrpc":"2.0"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-resources-read-unknown.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-resources-read-unknown.request.json
new file mode 100644
index 0000000000..7b5d15ed71
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-resources-read-unknown.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"resources/read","params":{"uri":"ghost://"}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-resources-read-unknown.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-resources-read-unknown.response.json
new file mode 100644
index 0000000000..1919a85296
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-resources-read-unknown.response.json
@@ -0,0 +1 @@
+{"error":{"code":-32601,"message":"Resource not found: 
ghost://"},"id":1,"jsonrpc":"2.0"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-tools-call-missing-name.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-tools-call-missing-name.request.json
new file mode 100644
index 0000000000..4d687df20a
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-tools-call-missing-name.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"arguments":{}}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-tools-call-missing-name.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-tools-call-missing-name.response.json
new file mode 100644
index 0000000000..83d308b863
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-tools-call-missing-name.response.json
@@ -0,0 +1 @@
+{"error":{"code":-32602,"message":"Missing tool name"},"id":1,"jsonrpc":"2.0"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-tools-call-unknown-tool.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-tools-call-unknown-tool.request.json
new file mode 100644
index 0000000000..99f0348ac7
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-tools-call-unknown-tool.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"missing"}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-tools-call-unknown-tool.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-tools-call-unknown-tool.response.json
new file mode 100644
index 0000000000..38cf2d59dd
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-tools-call-unknown-tool.response.json
@@ -0,0 +1 @@
+{"error":{"code":-32601,"message":"Tool not found: 
missing"},"id":1,"jsonrpc":"2.0"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-tools-list.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-tools-list.request.json
new file mode 100644
index 0000000000..b0437c8329
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-tools-list.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"tools/list"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-tools-list.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-tools-list.response.json
new file mode 100644
index 0000000000..5d325b0641
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-tools-list.response.json
@@ -0,0 +1 @@
+{"id":1,"jsonrpc":"2.0","result":{"tools":[]}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-unknown-method.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-unknown-method.request.json
new file mode 100644
index 0000000000..d287ff29f2
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-unknown-method.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"no/such/method"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-unknown-method.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-unknown-method.response.json
new file mode 100644
index 0000000000..d58a01befb
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/EMPTY-unknown-method.response.json
@@ -0,0 +1 @@
+{"error":{"code":-32601,"message":"Method not found: 
no/such/method"},"id":1,"jsonrpc":"2.0"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-initialize.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-initialize.request.json
new file mode 100644
index 0000000000..1ae1231b50
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-initialize.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"initialize"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-initialize.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-initialize.response.json
new file mode 100644
index 0000000000..fe2c2ce918
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-initialize.response.json
@@ -0,0 +1 @@
+{"id":1,"jsonrpc":"2.0","result":{"capabilities":{"prompts":{},"resources":{},"tools":{}},"instructions":"Be
 
concise.","protocolVersion":"2025-06-18","serverInfo":{"name":"characterization","version":"1.0.0"}}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-prompts-get.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-prompts-get.request.json
new file mode 100644
index 0000000000..21b052e5b7
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-prompts-get.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"prompts/get","params":{"name":"greet","arguments":{"who":"world"}}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-prompts-get.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-prompts-get.response.json
new file mode 100644
index 0000000000..beecd65542
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-prompts-get.response.json
@@ -0,0 +1 @@
+{"id":1,"jsonrpc":"2.0","result":{"description":"d","messages":[{"content":{"type":"text","text":"hi
 world"},"role":"user"}]}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-prompts-list.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-prompts-list.request.json
new file mode 100644
index 0000000000..3bda935b3d
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-prompts-list.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"prompts/list"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-prompts-list.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-prompts-list.response.json
new file mode 100644
index 0000000000..327554a24e
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-prompts-list.response.json
@@ -0,0 +1 @@
+{"id":1,"jsonrpc":"2.0","result":{"prompts":[{"description":"pd","name":"greet"}]}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-resources-list.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-resources-list.request.json
new file mode 100644
index 0000000000..b10e040403
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-resources-list.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"resources/list"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-resources-list.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-resources-list.response.json
new file mode 100644
index 0000000000..78ed2d1b3d
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-resources-list.response.json
@@ -0,0 +1 @@
+{"id":1,"jsonrpc":"2.0","result":{"resources":[{"mimeType":"text/plain","name":"a","uri":"file:///a"}]}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-resources-read.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-resources-read.request.json
new file mode 100644
index 0000000000..066ff77362
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-resources-read.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"resources/read","params":{"uri":"file:///a"}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-resources-read.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-resources-read.response.json
new file mode 100644
index 0000000000..89c640eebc
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-resources-read.response.json
@@ -0,0 +1 @@
+{"id":1,"jsonrpc":"2.0","result":{"contents":[{"type":"resourceText","mimeType":"text/plain","text":"body","uri":"file:///a"}]}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-string-id.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-string-id.request.json
new file mode 100644
index 0000000000..16d419254e
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-string-id.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":"abc","method":"ping"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-string-id.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-string-id.response.json
new file mode 100644
index 0000000000..619d097d2a
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-string-id.response.json
@@ -0,0 +1 @@
+{"id":"abc","jsonrpc":"2.0","result":{}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-arguments-not-map.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-arguments-not-map.request.json
new file mode 100644
index 0000000000..661b64a5d1
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-arguments-not-map.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"echo","arguments":"nope"}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-arguments-not-map.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-arguments-not-map.response.json
new file mode 100644
index 0000000000..98ebe64d8c
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-arguments-not-map.response.json
@@ -0,0 +1 @@
+{"error":{"code":-32602,"message":"Param 'arguments' must be an 
object"},"id":1,"jsonrpc":"2.0"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-error-flag.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-error-flag.request.json
new file mode 100644
index 0000000000..229d06d3aa
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-error-flag.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"failing"}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-error-flag.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-error-flag.response.json
new file mode 100644
index 0000000000..4f52555769
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-error-flag.response.json
@@ -0,0 +1 @@
+{"id":1,"jsonrpc":"2.0","result":{"content":[{"type":"text","text":"nope"}],"isError":true}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-mixed-content.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-mixed-content.request.json
new file mode 100644
index 0000000000..c7bf79d383
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-mixed-content.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"mixed"}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-mixed-content.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-mixed-content.response.json
new file mode 100644
index 0000000000..52167e2af6
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-mixed-content.response.json
@@ -0,0 +1 @@
+{"id":1,"jsonrpc":"2.0","result":{"content":[{"type":"text","text":"t"},{"type":"image","data":"AAA=","mimeType":"image/png"},{"type":"resource","resource":{"type":"resourceText","mimeType":"text/plain","text":"emb","uri":"file:///e"}}]}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-no-arguments.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-no-arguments.request.json
new file mode 100644
index 0000000000..d741380c7a
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-no-arguments.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"echo"}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-no-arguments.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-no-arguments.response.json
new file mode 100644
index 0000000000..92dfd28fa3
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-no-arguments.response.json
@@ -0,0 +1 @@
+{"id":1,"jsonrpc":"2.0","result":{"content":[{"type":"text","text":"null"}]}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-params-not-map.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-params-not-map.request.json
new file mode 100644
index 0000000000..f519a066d4
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-params-not-map.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"tools/call","params":"not-a-map"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-params-not-map.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-params-not-map.response.json
new file mode 100644
index 0000000000..fad8612627
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-params-not-map.response.json
@@ -0,0 +1 @@
+{"error":{"code":-32602,"message":"Params must be an 
object"},"id":1,"jsonrpc":"2.0"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-text.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-text.request.json
new file mode 100644
index 0000000000..f280bce160
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-text.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"echo","arguments":{"text":"hello"}}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-text.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-text.response.json
new file mode 100644
index 0000000000..dd0cbc5594
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-call-text.response.json
@@ -0,0 +1 @@
+{"id":1,"jsonrpc":"2.0","result":{"content":[{"type":"text","text":"hello"}]}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-list.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-list.request.json
new file mode 100644
index 0000000000..b0437c8329
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-list.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"tools/list"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-list.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-list.response.json
new file mode 100644
index 0000000000..e1012c787a
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/FULL-tools-list.response.json
@@ -0,0 +1 @@
+{"id":1,"jsonrpc":"2.0","result":{"tools":[{"description":"desc:echo","inputSchema":{"required":["text"],"type":"object"},"name":"echo"},{"description":"desc:mixed","name":"mixed"},{"description":"desc:failing","name":"failing"}]}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/PAGED-tools-list-first.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/PAGED-tools-list-first.request.json
new file mode 100644
index 0000000000..b0437c8329
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/PAGED-tools-list-first.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"tools/list"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/PAGED-tools-list-first.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/PAGED-tools-list-first.response.json
new file mode 100644
index 0000000000..abae091149
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/PAGED-tools-list-first.response.json
@@ -0,0 +1 @@
+{"id":1,"jsonrpc":"2.0","result":{"nextCursor":"1","tools":[{"description":"desc:t1","name":"t1"}]}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/PAGED-tools-list-second.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/PAGED-tools-list-second.request.json
new file mode 100644
index 0000000000..d4aff4ea7c
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/PAGED-tools-list-second.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{"cursor":"1"}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/PAGED-tools-list-second.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/PAGED-tools-list-second.response.json
new file mode 100644
index 0000000000..709b1060ec
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/PAGED-tools-list-second.response.json
@@ -0,0 +1 @@
+{"id":2,"jsonrpc":"2.0","result":{"tools":[{"description":"desc:t2","name":"t2"}]}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/THROW-mcp-exception.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/THROW-mcp-exception.request.json
new file mode 100644
index 0000000000..b6c74777b3
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/THROW-mcp-exception.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"mcpEx"}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/THROW-mcp-exception.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/THROW-mcp-exception.response.json
new file mode 100644
index 0000000000..f1429b9d34
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/THROW-mcp-exception.response.json
@@ -0,0 +1 @@
+{"error":{"code":-32099,"data":{"k":"v"},"message":"nope"},"id":1,"jsonrpc":"2.0"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/THROW-no-message.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/THROW-no-message.request.json
new file mode 100644
index 0000000000..162a61b6d5
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/THROW-no-message.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"silent"}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/THROW-no-message.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/THROW-no-message.response.json
new file mode 100644
index 0000000000..156aa5610f
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/THROW-no-message.response.json
@@ -0,0 +1 @@
+{"error":{"code":-32603,"data":{"type":"java.lang.IllegalStateException"},"message":"IllegalStateException"},"id":1,"jsonrpc":"2.0"}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/THROW-runtime-exception.request.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/THROW-runtime-exception.request.json
new file mode 100644
index 0000000000..3adb84d06f
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/THROW-runtime-exception.request.json
@@ -0,0 +1 @@
+{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"boom"}}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/THROW-runtime-exception.response.json
 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/THROW-runtime-exception.response.json
new file mode 100644
index 0000000000..7fcc4e59b4
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server-mcp/src/test/resources/characterization/THROW-runtime-exception.response.json
@@ -0,0 +1 @@
+{"error":{"code":-32603,"data":{"type":"java.lang.RuntimeException"},"message":"boom"},"id":1,"jsonrpc":"2.0"}
\ No newline at end of file

Reply via email to