You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 09020ac
Browse filesBrowse the repository at this point in the historyBrowse files
Modern stateless server for MCP 2026-07-28 (#1170)
A new server in io.modelcontextprotocol.modern, next to the existing
one and independent of the legacy McpSchema. Passes all 37 required
2026-07-28 conformance scenarios.
- Pick a paradigm, not a server: one McpServer, sync or async
repositories, no Reactor in sync code. The immediateExecution flag
is gone; the transport decides where blocking code runs, and
thread-locals from servlet filters just work.
- Primitives are yours: tools, resources, prompts and completions come
from repositories you implement. Dynamic, per-tenant, filtered and
paginated catalogs, no SDK registry in the way.
- Stream when it pays: a handler returns a single result
(application/json) or a streaming body (SSE). No more JSON-only
stateless vs. SSE-always sessions.
- McpFeature as the one extension point: methods, handler, capabilities.
- MRTR with requestState HMAC-sealed to principal, expiry, method and
tool or resource.
- server/discover, caching hints, subscriptions/listen fed by
McpChangeFeed.
- Tool arguments checked against inputSchema, structuredContent against
outputSchema; prompt arguments and completions validated too.
- McpException goes out as given; other exception messages stay in
the log.
- HTTP: POST only, keep-alives, disconnect detection, configurable
error statuses, cross-origin refused by default.
- Stdio: concurrent requests, cancellation, one writer, line size limit.
- Logging dropped, as the revision deprecates it.
Also: modern conformance server and CI job, conformance runs moved to
0.2.0-alpha.12, CONTRIBUTING record rules refined.
Not yet: SEP-2243 custom headers, tasks, a modern client.
Addresses, for users of the modern server
- Sessions gone: #274, #499, #577, #738, #952, #1063
- No server-to-client requests: #1061
- Errors: #249, #737, #955, #1081, #1086
- HTTP: #293, #400, #539, #844, #880, #957, #1155
- Stdio: #303, #936
- Repositories: #578, #626, #941, #967
- Context and schema: #492, #766
- 2026-07-28 server side: #1001, #1004, #1009, #1010, #1011
Additionally, reinstall server-everything when its cached copy was pruned:
If the install directory exists but lacks the server, e.g. after the OS
cleaned up the temporary directory, delete it and install again instead
of failing on every run.
Signed-off-by: Dariusz Jędrzejczyk <dariusz.jedrzejczyk@broadcom.com>
Copy file name to clipboardExpand all lines: CONTRIBUTING.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -114,13 +114,13 @@ Records in `McpSchema` are serialized directly to the MCP JSON wire format. The
114
114
115
115
When the MCP specification marks a field as required, callers must not be able to construct a structurally invalid record, but the wire parser must still tolerate peers that fail to send it. Follow these rules in addition to the relevant Case A rules (annotation, naming, append-only).
116
116
117
-
1.**Reject `null` in the compact constructor.**Use`Assert.notNull` for required objects or `Assert.hasText` for required `String` identifiers (`name`, `uri`, `uriTemplate`, `version`). This throws `IllegalArgumentException` at construction time instead of producing a record that fails later in serialization or protocol handling. Overrides Case A Rule 7 for this field.
117
+
1.**Reject `null` in the compact constructor**with`Assert.notNull`. This throws `IllegalArgumentException` at construction time instead of producing a record that fails later in serialization or protocol handling. Overrides Case A Rule 7 for this field. The compact constructor is the one path that both Java callers and `fromJson` (Rule 2) go through, so it may only enforce what a wire default can satisfy. Stricter Java-side checks, such as non-empty identifiers (`Assert.hasText` on `name`, `uri`, `uriTemplate`, `version`), belong in the required-first builder factory (Rule 3).
118
118
2.**Add a `@JsonCreator` static `fromJson` factory** alongside the canonical constructor. When a required field is absent from the wire, substitute a documented safe default (`""` for strings, `[]` for collections, `{}` for maps, `0` / `0.0` for numerics, `INFO` for `LoggingLevel`, etc.) and log at `WARN` naming the field and the value used. The SDK must not halt the conversation because of a missing field. Place `@JsonCreator` on this `fromJson` factory, never on the canonical constructor (Case A Rule 6 still applies to the canonical constructor itself).
119
-
- Exception: `JSONRPCResponse.JSONRPCError` fails fast on missing `code` / `message` because a malformed JSON-RPC error envelope is unrecoverable.
119
+
- Exception: do not substitute a default when the missing value would make the message unprocessable anyway. This covers `JSONRPCResponse.JSONRPCError` (`code` / `message`), since a malformed JSON-RPC error envelope is unrecoverable, and the identifiers a request is dispatched on (e.g. `name` of `tools/call` and `prompts/get`, `uri` of `resources/read`, `ref` of `completion/complete`). A missing dispatch identifier must fail fast with an `INVALID_PARAMS` error, not an internal error.
120
120
3.**Provide a required-first builder factory**`builder(req1, req2, …)` and remove the corresponding setters from the `Builder`. A no-arg `builder()` factory must not exist on a record that has required fields. If one already exists for source compatibility, mark it `@Deprecated`.
121
121
4.**Add tests per required field**:
122
122
- Constructing the record with `null` for the field throws `IllegalArgumentException`.
123
-
- Deserializing JSON *without* the field succeeds and yields the documented default.
123
+
- Deserializing JSON *without* the field succeeds and yields the documented default, or, for a Rule 2 exception, fails.
124
124
- Deserializing JSON with an extra *unknown* field still succeeds (Case A Rule 8 also applies).
0 commit comments