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

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


The following commit(s) were added to refs/heads/docs by this push:
     new 2558c9fa83 feat: add MCP 2026-07-28 revision server (new bean + 
adapter modules)
2558c9fa83 is described below

commit 2558c9fa83ab7bdf71ac4d3eb756d5418e8cf643
Author: James Bognar <[email protected]>
AuthorDate: Thu Jul 30 14:20:36 2026 -0400

    feat: add MCP 2026-07-28 revision server (new bean + adapter modules)
    
    Adds juneau-bean-mcp-2026-07-28 and juneau-rest-server-mcp-2026-07-28
    implementing the stateless 2026-07-28 MCP revision on the neutral core:
    server/discover capability discovery, opaque _meta on the JSON-RPC
    envelopes, SEP-2243 Mcp-Method/Mcp-Name header routing, and JsonSchema-typed
    tool input/output schemas.  De-versions the 2025-06-18 adapter binding class
    names (package-only differentiation) to match.
---
 artifact-packages.json                 |  1 -
 artifact-paths.json                    |  6 +++-
 pages/release-notes/10.0.0.md          | 16 +++++-----
 pages/topics/11.JuneauRestServerMcp.md | 54 +++++++++++++++++-----------------
 4 files changed, 40 insertions(+), 37 deletions(-)

diff --git a/artifact-packages.json b/artifact-packages.json
index 84cd8d0702..571b61309b 100644
--- a/artifact-packages.json
+++ b/artifact-packages.json
@@ -6,7 +6,6 @@
   "juneau-bean-jsonapi": "org/apache/juneau/bean/jsonapi",
   "juneau-bean-jsonpatch": "org/apache/juneau/bean/jsonpatch",
   "juneau-bean-jsonschema": "org/apache/juneau/bean/jsonschema",
-  "juneau-bean-mcp": "org/apache/juneau/bean/mcp",
   "juneau-bean-openapi-v3": "org/apache/juneau/bean/openapi3",
   "juneau-bean-rfc7807": "org/apache/juneau/bean/rfc7807",
   "juneau-bean-swagger-v2": "org/apache/juneau/bean/swagger",
diff --git a/artifact-paths.json b/artifact-paths.json
index 28a4f07251..a5be25db64 100644
--- a/artifact-paths.json
+++ b/artifact-paths.json
@@ -7,8 +7,10 @@
   "juneau-bean-html5": "juneau-bean/juneau-bean-html5",
   "juneau-bean-jsonapi": "juneau-bean/juneau-bean-jsonapi",
   "juneau-bean-jsonpatch": "juneau-bean/juneau-bean-jsonpatch",
+  "juneau-bean-jsonrpc": "juneau-bean/juneau-bean-jsonrpc",
   "juneau-bean-jsonschema": "juneau-bean/juneau-bean-jsonschema",
-  "juneau-bean-mcp": "juneau-bean/juneau-bean-mcp",
+  "juneau-bean-mcp-2025-06-18": "juneau-bean/juneau-bean-mcp-2025-06-18",
+  "juneau-bean-mcp-2026-07-28": "juneau-bean/juneau-bean-mcp-2026-07-28",
   "juneau-bean-openapi-v3": "juneau-bean/juneau-bean-openapi-v3",
   "juneau-bean-rfc7807": "juneau-bean/juneau-bean-rfc7807",
   "juneau-bean-swagger-v2": "juneau-bean/juneau-bean-swagger-v2",
@@ -53,6 +55,8 @@
   "juneau-rest-server-auth-saml": "juneau-rest/juneau-rest-server-auth-saml",
   "juneau-rest-server-management-logging": 
"juneau-rest/juneau-rest-server-management-logging",
   "juneau-rest-server-mcp": "juneau-rest/juneau-rest-server-mcp",
+  "juneau-rest-server-mcp-2025-06-18": 
"juneau-rest/juneau-rest-server-mcp-2025-06-18",
+  "juneau-rest-server-mcp-2026-07-28": 
"juneau-rest/juneau-rest-server-mcp-2026-07-28",
   "juneau-rest-server-metrics-micrometer": 
"juneau-rest/juneau-rest-server-metrics-micrometer",
   "juneau-rest-server-rdf": "juneau-rest/juneau-rest-server-rdf",
   "juneau-rest-server-reactive": "juneau-rest/juneau-rest-server-reactive",
diff --git a/pages/release-notes/10.0.0.md b/pages/release-notes/10.0.0.md
index 6dbfdae6d3..c58929b894 100644
--- a/pages/release-notes/10.0.0.md
+++ b/pages/release-notes/10.0.0.md
@@ -742,7 +742,7 @@ JsonRpcResponse err = JsonRpcResponse.errorResponse(1, 
-32601, "Method not found
 - **`McpCursor`**, **`McpPage<T>`** — pagination strategy seam, unchanged: 
`McpCursor.SINGLE_PAGE` (default, returns everything in one page) and 
`McpCursor.fixedSize(n)` (opaque integer-offset paging).
 - **`McpParamUtils`** — shared `params`-coercion plumbing 
(`asMap`/`strParam`/`mapParam`) used by revision `dispatch()` implementations.
 
-**Removed:** `McpDispatcher` and the static `Mcp` façade are gone with no 
drop-in replacement class — their method-table logic now lives in each 
revision's own `McpRevision.dispatch()` implementation (see 
`Mcp20250618Revision` below), and their internal plumbing helpers were 
redistributed onto `JsonRpcResponse`, `McpCursor`, and the new `McpParamUtils`.
+**Removed:** `McpDispatcher` and the static `Mcp` façade are gone with no 
drop-in replacement class — their method-table logic now lives in each 
revision's own `McpRevision.dispatch()` implementation (see 
`org.apache.juneau.rest.server.mcp.v20250618.McpRevision` below), and their 
internal plumbing helpers were redistributed onto `JsonRpcResponse`, 
`McpCursor`, and the new `McpParamUtils`.
 
 See [juneau-rest-server-mcp](/docs/topics/JuneauRestServerMcp) for the full 
topic.
 
@@ -795,9 +795,9 @@ A new adapter module, `juneau-rest-server-mcp-2025-06-18` 
(package `org.apache.j
 
 ### New Classes
 
-- **`Mcp20250618Revision`** — the `McpRevision` implementation for protocol 
revision `2025-06-18`. Replaces the old `McpDispatcher`/`Mcp` façade: owns the 
JSON-RPC method table (`initialize`, `ping`, `tools/list|call`, 
`prompts/list|get`, `resources/list|read`) and the error-code table. The 
error-code table intentionally preserves a known-wrong mapping carried over 
unmodified from the pre-re-layering dispatcher — unknown-method, 
tool-not-found, prompt-not-found, and resource-not-found al [...]
-- **`McpRestServlet20250618`** — concrete abstract servlet for this revision; 
subclass it (instead of the core `McpRestServlet`) and implement 
`createMcpConfig()`. Exposes a `protected ServerCapabilities capabilities()` 
hook (returns `null` by default) for explicitly overriding the `initialize` 
capabilities advertisement instead of relying on auto-derivation from the 
registered tool/prompt/resource lists.
-- **`McpEndpoint20250618`** — mixin interface for this revision, at parity 
with `McpRestServlet20250618`: implement `getMcpConfig()`, and optionally 
override its `default ServerCapabilities capabilities()` hook.
+- **`org.apache.juneau.rest.server.mcp.v20250618.McpRevision`** — the 
`McpRevision` implementation for protocol revision `2025-06-18`. Replaces the 
old `McpDispatcher`/`Mcp` façade: owns the JSON-RPC method table (`initialize`, 
`ping`, `tools/list|call`, `prompts/list|get`, `resources/list|read`) and the 
error-code table. The error-code table intentionally preserves a known-wrong 
mapping carried over unmodified from the pre-re-layering dispatcher — 
unknown-method, tool-not-found, prompt- [...]
+- **`org.apache.juneau.rest.server.mcp.v20250618.McpRestServlet`** — concrete 
abstract servlet for this revision; subclass it (instead of the core 
`McpRestServlet`) and implement `createMcpConfig()`. Exposes a `protected 
ServerCapabilities capabilities()` hook (returns `null` by default) for 
explicitly overriding the `initialize` capabilities advertisement instead of 
relying on auto-derivation from the registered tool/prompt/resource lists.
+- **`org.apache.juneau.rest.server.mcp.v20250618.McpEndpoint`** — mixin 
interface for this revision, at parity with 
`org.apache.juneau.rest.server.mcp.v20250618.McpRestServlet`: implement 
`getMcpConfig()`, and optionally override its `default ServerCapabilities 
capabilities()` hook.
 - **`McpTypedToolHandler<A,R>`**, **`McpTypedPromptHandler<A>`**, 
**`McpTypedHandlers`** — the typed sugar layer, moved here (package-renamed 
only) since it's revision-specific by construction: it binds arguments into 
this revision's wire-bean argument types and adapts the result to the neutral 
`McpToolHandler`/`McpPromptHandler` raw interfaces the core registry holds.
 
 **New behavior:** on a given `McpServerConfig`'s first dispatch, this revision 
validates that every registered tool's `McpSchema` uses only the 6 JSON Schema 
keywords its wire `JsonSchema` bean can represent (`type`, `properties`, 
`required`, `additionalProperties`, `items`, `$defs`) — throwing 
`IllegalArgumentException` naming the offending tool and keyword if not, rather 
than silently dropping an unsupported keyword on the wire.
@@ -806,7 +806,7 @@ A new adapter module, `juneau-rest-server-mcp-2025-06-18` 
(package `org.apache.j
 
 ```java
 @Rest(path="/mcp")
-public class MyMcpServlet extends McpRestServlet20250618 {
+public class MyMcpServlet extends McpRestServlet {
     @Override
     protected McpServerConfig createMcpConfig() {
         return new 
McpServerConfig().setName("my-server").setVersion("1.0.0").addTool(new 
MyEchoTool());
@@ -818,7 +818,7 @@ public class MyMcpServlet extends McpRestServlet20250618 {
 
 ```java
 @Rest(path="/api")
-public class MyResource extends BasicRestServlet implements 
McpEndpoint20250618 {
+public class MyResource extends BasicRestServlet implements McpEndpoint {
     @Override
     public McpServerConfig getMcpConfig() {
         return new McpServerConfig().addTool(new MyEchoTool());
@@ -854,7 +854,7 @@ config.setCursor(McpCursor.fixedSize(50));
 
 ```java
 @Rest(path="/mcp")
-public class MyMcpServlet extends McpRestServlet20250618 {
+public class MyMcpServlet extends McpRestServlet {
     @Override
     protected McpServerConfig createMcpConfig() {
         return new McpServerConfig().addTool(new MyEchoTool());
@@ -867,7 +867,7 @@ public class MyMcpServlet extends McpRestServlet20250618 {
 }
 ```
 
-Returning `null` (the default) leaves capabilities auto-derived from the 
registered tool/prompt/resource lists. Returning a non-`null` value bypasses 
auto-derivation entirely — the way to advertise `resources.subscribe`, 
`logging`, `listChanged`, or `experimental`, none of which are derivable from a 
handler registry. `McpEndpoint20250618` exposes the equivalent hook as a 
`default` interface method for the mixin path.
+Returning `null` (the default) leaves capabilities auto-derived from the 
registered tool/prompt/resource lists. Returning a non-`null` value bypasses 
auto-derivation entirely — the way to advertise `resources.subscribe`, 
`logging`, `listChanged`, or `experimental`, none of which are derivable from a 
handler registry. `McpEndpoint` exposes the equivalent hook as a `default` 
interface method for the mixin path.
 
 ### Notifications
 
diff --git a/pages/topics/11.JuneauRestServerMcp.md 
b/pages/topics/11.JuneauRestServerMcp.md
index 7d10893a8a..eb605e216c 100644
--- a/pages/topics/11.JuneauRestServerMcp.md
+++ b/pages/topics/11.JuneauRestServerMcp.md
@@ -12,8 +12,8 @@ slug: JuneauRestServerMcp
 MCP is a JSON-RPC 2.0 protocol that lets AI assistants discover and invoke 
external **tools**, **prompts**, and **resources**. Together, the two modules 
provide:
 
 - A **revision SPI** (`McpRevision`) that a protocol revision implements — the 
neutral core dispatches through it without knowing what's on the other side.
-- A drop-in **servlet** (`McpRestServlet`, concretely 
`McpRestServlet20250618`) for the common case of "expose an MCP endpoint at 
`POST /mcp`".
-- An **interface mixin** (`McpEndpoint`, concretely `McpEndpoint20250618`) for 
embedding an MCP endpoint inside an existing `@Rest` resource.
+- A drop-in **servlet** (`McpRestServlet`, concretely 
`org.apache.juneau.rest.server.mcp.v20250618.McpRestServlet`) for the common 
case of "expose an MCP endpoint at `POST /mcp`".
+- An **interface mixin** (`McpEndpoint`, concretely 
`org.apache.juneau.rest.server.mcp.v20250618.McpEndpoint`) for embedding an MCP 
endpoint inside an existing `@Rest` resource.
 - Functional **handler interfaces** for tools/prompts/resources, typed against 
a revision-neutral model, plus a typed sugar layer (in the adapter) that does 
argument binding and result wrapping for you.
 - A pluggable **pagination** seam for `*/list` methods.
 
@@ -24,19 +24,19 @@ The implementation is stateless — every request is 
dispatched against the `Mcp
 ### Architecture
 
 ```
-+----------------------------+        +-------------------------+        
+-----------------+
-|   McpRestServlet20250618   |        |   Mcp20250618Revision   |        |   
Tool/Prompt/  |
-|   -or- McpEndpoint20250618 |  --->  |   (this revision's      |  --->  |   
Resource      |
-|   (POST handler, adapter)  |        |    JSON-RPC method      |        |   
Handlers      |
-+----------------------------+        |    table + error codes) |        |   
(neutral)     |
-              |                       +-------------------------+        
+-----------------+
-              v                                    |
-   juneau-rest-server-mcp                          v
-   (core: McpServerConfig,               juneau-bean-mcp-2025-06-18
-   McpRevision SPI, neutral model)       (wire beans, via Mcp20250618Wire)
++------------------------------------------------+        
+------------------------------------------------+        +-----------------+
+|   org.apache.juneau.rest.server.mcp.v20250618   |        |   
org.apache.juneau.rest.server.mcp.v20250618  |        |   Tool/Prompt/  |
+|   .McpRestServlet -or- .McpEndpoint             |  --->  |   .McpRevision 
(this revision's JSON-RPC       |  --->  |   Resource      |
+|   (POST handler, adapter)                       |        |    method table + 
error codes)                 |        |   Handlers      |
++------------------------------------------------+        
+------------------------------------------------+        +-----------------+
+              |                                                          |
+              v                                                          v
+   juneau-rest-server-mcp                                       
juneau-bean-mcp-2025-06-18
+   (core: McpServerConfig,                                      (wire beans, 
via
+   McpRevision SPI, neutral model)                              
org.apache.juneau.rest.server.mcp.v20250618.McpWire)
 ```
 
-`Mcp20250618Revision` implements `McpRevision` and owns this revision's 
JSON-RPC method table and error-code table — it replaces the earlier, 
now-deleted `McpDispatcher`/`Mcp` façade. The adapter servlet/mixin only 
translates from `RestRequest` to an `McpExchange` + `BeanStore`, then calls 
`revision().dispatch(...)`.
+`org.apache.juneau.rest.server.mcp.v20250618.McpRevision` implements 
`McpRevision` and owns this revision's JSON-RPC method table and error-code 
table — it replaces the earlier, now-deleted `McpDispatcher`/`Mcp` façade. The 
adapter servlet/mixin only translates from `RestRequest` to an `McpExchange` + 
`BeanStore`, then calls `revision().dispatch(...)`.
 
 ## Getting Started
 
@@ -56,7 +56,7 @@ This module transitively pulls in `juneau-rest-server-mcp` 
(the core) and `junea
 
 ### Drop-in servlet
 
-Subclass `McpRestServlet20250618` (not the abstract core `McpRestServlet` 
directly) and supply your config in `createMcpConfig()`. The base class wires 
up `@Rest`, `@SerializerConfig(addBeanTypes="true")`, and a `POST /` handler:
+Subclass `org.apache.juneau.rest.server.mcp.v20250618.McpRestServlet` (not the 
abstract core `McpRestServlet` directly) and supply your config in 
`createMcpConfig()`. The base class wires up `@Rest`, 
`@SerializerConfig(addBeanTypes="true")`, and a `POST /` handler:
 
 ```java
 import org.apache.juneau.rest.server.*;
@@ -64,7 +64,7 @@ import org.apache.juneau.rest.server.mcp.*;
 import org.apache.juneau.rest.server.mcp.v20250618.*;
 
 @Rest(path="/mcp")
-public class MyMcpServlet extends McpRestServlet20250618 {
+public class MyMcpServlet extends 
org.apache.juneau.rest.server.mcp.v20250618.McpRestServlet {
 
     @Override
     protected McpServerConfig createMcpConfig() {
@@ -80,11 +80,11 @@ Mount the servlet through your microservice / Spring Boot 
config like any other
 
 ### Interface mixin
 
-If you already have a `@Rest` resource and want to expose MCP at `POST /mcp` 
next to your other endpoints, implement `McpEndpoint20250618`:
+If you already have a `@Rest` resource and want to expose MCP at `POST /mcp` 
next to your other endpoints, implement `McpEndpoint`:
 
 ```java
 @Rest(path="/api")
-public class MyResource extends BasicRestServlet implements 
McpEndpoint20250618 {
+public class MyResource extends BasicRestServlet implements McpEndpoint {
 
     @Override
     public McpServerConfig getMcpConfig() {
@@ -93,7 +93,7 @@ public class MyResource extends BasicRestServlet implements 
McpEndpoint20250618
 }
 ```
 
-The default `handleMcpRequest(...)` method on `McpEndpoint` (annotated 
`@RestPost("/mcp")`) takes care of dispatch, via `McpEndpoint20250618`'s 
`revision()` override.
+The default `handleMcpRequest(...)` method on `McpEndpoint` (annotated 
`@RestPost("/mcp")`) takes care of dispatch, via 
`org.apache.juneau.rest.server.mcp.v20250618.McpEndpoint`'s `revision()` 
override.
 
 ## Writing Handlers
 
@@ -203,10 +203,10 @@ Throw `McpException` (from `juneau-bean-jsonrpc`) from 
any handler to surface a
 import org.apache.juneau.bean.jsonrpc.*;
 import org.apache.juneau.rest.server.mcp.v20250618.*;
 
-throw new McpException(Mcp20250618Revision.CODE_INVALID_PARAMS, "Missing 
required argument 'city'");
+throw new McpException(McpRevision.CODE_INVALID_PARAMS, "Missing required 
argument 'city'");
 ```
 
-`McpException` carries the JSON-RPC `code`, `message`, and optional `data` 
fields. `Mcp20250618Revision` converts other unchecked exceptions into `-32603 
Internal error` automatically.
+`McpException` carries the JSON-RPC `code`, `message`, and optional `data` 
fields. `McpRevision` converts other unchecked exceptions into `-32603 Internal 
error` automatically.
 
 ## Pagination
 
@@ -241,15 +241,15 @@ config.setCursor(myCursor);
 
 ## Notifications
 
-JSON-RPC requests with `id == null` are *notifications*. 
`Mcp20250618Revision.dispatch()` invokes the handler, **silently swallows any 
exception**, and returns `null`. The REST servlet/mixin renders this as an 
empty response body, so transports can map this to `204 No Content`.
+JSON-RPC requests with `id == null` are *notifications*. 
`McpRevision.dispatch()` invokes the handler, **silently swallows any 
exception**, and returns `null`. The REST servlet/mixin renders this as an 
empty response body, so transports can map this to `204 No Content`.
 
 ## Capabilities
 
-Capabilities are revision-owned, not part of the neutral `McpServerConfig` — 
`ServerCapabilities` is a `2025-06-18` wire type, and capability shape is 
expected to diverge across future MCP revisions. `McpRestServlet20250618` and 
`McpEndpoint20250618` each expose a `capabilities()` hook:
+Capabilities are revision-owned, not part of the neutral `McpServerConfig` — 
`ServerCapabilities` is a `2025-06-18` wire type, and capability shape is 
expected to diverge across future MCP revisions. `McpRestServlet` and 
`McpEndpoint` each expose a `capabilities()` hook:
 
 ```java
 @Rest(path="/mcp")
-public class MyMcpServlet extends McpRestServlet20250618 {
+public class MyMcpServlet extends McpRestServlet {
     @Override
     protected McpServerConfig createMcpConfig() {
         return new McpServerConfig().addTool(new EchoTool());
@@ -262,11 +262,11 @@ public class MyMcpServlet extends McpRestServlet20250618 {
 }
 ```
 
-Returning `null` (the default) leaves capabilities auto-derived from the 
registered tool/prompt/resource lists — `Mcp20250618Revision` synthesizes a 
bare `ServerCapabilities` advertising `tools`/`prompts`/`resources` only when 
at least one matching handler is registered, exactly as the earlier 
`McpDispatcher` did. Returning a non-`null` value bypasses auto-derivation 
entirely — the way to advertise `resources.subscribe`, `logging`, 
`listChanged`, or `experimental`, none of which are deri [...]
+Returning `null` (the default) leaves capabilities auto-derived from the 
registered tool/prompt/resource lists — `McpRevision` synthesizes a bare 
`ServerCapabilities` advertising `tools`/`prompts`/`resources` only when at 
least one matching handler is registered, exactly as the earlier 
`McpDispatcher` did. Returning a non-`null` value bypasses auto-derivation 
entirely — the way to advertise `resources.subscribe`, `logging`, 
`listChanged`, or `experimental`, none of which are derivable fr [...]
 
 ## Server Info Defaults
 
-`McpServerConfig` has plain `name`/`version` `String` fields 
(`setName(...)`/`setVersion(...)`) rather than a dedicated identity bean. If 
neither is set, `Mcp20250618Revision` reports:
+`McpServerConfig` has plain `name`/`version` `String` fields 
(`setName(...)`/`setVersion(...)`) rather than a dedicated identity bean. If 
neither is set, `McpRevision` reports:
 
 - `name` = `"juneau-rest-server-mcp"`
 - `version` = `"unknown"`
@@ -275,13 +275,13 @@ Always set your own name/version so MCP clients can 
identify and version your se
 
 ## Tool schema validation
 
-**New behavior added by the re-layering.** On a given `McpServerConfig`'s 
first dispatch, `Mcp20250618Revision` validates that every registered tool's 
`McpSchema` uses only the six JSON Schema keywords its wire `JsonSchema` bean 
can represent (`type`, `properties`, `required`, `additionalProperties`, 
`items`, `$defs`). A schema using an unsupported keyword (`oneOf`, `$ref`, 
etc.) throws `IllegalArgumentException`, naming both the offending tool and the 
keyword, rather than silently dropp [...]
+**New behavior added by the re-layering.** On a given `McpServerConfig`'s 
first dispatch, `McpRevision` validates that every registered tool's 
`McpSchema` uses only the six JSON Schema keywords its wire `JsonSchema` bean 
can represent (`type`, `properties`, `required`, `additionalProperties`, 
`items`, `$defs`). A schema using an unsupported keyword (`oneOf`, `$ref`, 
etc.) throws `IllegalArgumentException`, naming both the offending tool and the 
keyword, rather than silently dropping it o [...]
 
 The check is memoized per `McpServerConfig` instance (an identity-keyed weak 
set), so it runs once — on that config's first routed request — not on every 
request. A server with an inexpressible schema still comes up healthy; only the 
first request against that config fails.
 
 ## Polymorphic Wire Format
 
-MCP returns polymorphic content (`Content`, `ResourceContents`) discriminated 
by a `type` property. The core `McpRestServlet` enables `addBeanTypes` on its 
serializer via `@SerializerConfig(addBeanTypes="true")` so the discriminator is 
emitted on the wire — this carries over unchanged onto 
`McpRestServlet20250618`. If you build your own `RestServlet` (bypassing both), 
apply the same configuration.
+MCP returns polymorphic content (`Content`, `ResourceContents`) discriminated 
by a `type` property. The core `McpRestServlet` enables `addBeanTypes` on its 
serializer via `@SerializerConfig(addBeanTypes="true")` so the discriminator is 
emitted on the wire — this carries over unchanged onto 
`org.apache.juneau.rest.server.mcp.v20250618.McpRestServlet`. If you build your 
own `RestServlet` (bypassing both), apply the same configuration.
 
 See [juneau-bean-mcp-2025-06-18](/docs/topics/JuneauBeanMcp) for the full 
wire-bean catalog.
 

Reply via email to