Skip to content

Commit d6be368

Browse files
committed
feat: MRTR for resources/read + prompts/get; subscribe truthfulness; completion e2e; P2 hygiene
Release-prep sweep, part 1 (functional + hygiene): - MRTR (SEP-2322) now covers all three permitted methods. Shared handlers::input_required_to_result (capability gate -32003/400 + InputRequiredResult construction) adopted by tools/call and wired into resources/read and prompts/get. Resources surface retry inputResponses/requestState via session extensions; prompts receive them in render args under reserved io.modelcontextprotocol/* keys — McpPrompt::render has no session parameter and changing it is a breaking public trait change (stop condition respected; convention documented on the trait; wire prompt arguments are plain strings so reserved keys cannot collide). Tests: two-leg round trips for both methods + a resources/read capability-gate case, all real-HTTP. Revert-and-fail: without the handler conversion the sentinel escapes as -32603 (the pre-slice behavior). - resources.subscribe advertises true on the 2026 lane at BOTH capability construction sites (subscriptions/listen serves per-URI resources/updated); 2025 stays false (no resources/subscribe handler). Wire test on server/discover; first run caught the second, unfixed site. - completion/complete e2e: sessionless dispatch, CompleteResult wire shape, capability advertisement (last zero-e2e core method on the 2026 path). - Hygiene: 41 stale "0.3" dependency snippets across 15 non-frozen crate docs -> "0.4" (frozen snapshots + terminal shim correctly keep 0.3); legacy session/SSE prose in default-lane READMEs labeled 2025-11-25 opt-in; internal-phase tags and fix-history comment phrasing replaced with present-tense spec-anchored descriptions.
1 parent 4c4c142 commit d6be368

28 files changed

Lines changed: 615 additions & 111 deletions

File tree

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3535
- **SEP-2577 deprecation annotations** on Roots / Sampling / Logging types and traits (`#[deprecated(since = "0.4.0", note = "...")]` with migration-path guidance and 2027-07-28+ earliest-removal date). Annotation-only this revision; types remain fully functional during the 12-month migration window. `LoggingLevel` (the value type for the non-deprecated `RequestMetaObject.log_level` replacement) is intentionally NOT deprecated.
3636
- **ADR-028***Extensions strategy* (SEP-2133 / SEP-2663). Documents how the framework will host out-of-tree extensions including `turul-mcp-ext-tasks-2026-07-28` and `turul-mcp-ext-apps-2026-07-28`.
3737

38+
### Added (2026-06-10, release-prep sweep)
39+
40+
- **MRTR on `resources/read` and `prompts/get`** — completes the SEP-2322 triple (the only methods permitted to return `input_required`). The conversion + client-capability gate is now one shared helper (`handlers::input_required_to_result`, also adopted by `tools/call`). Resources surface the retry's `inputResponses`/`requestState` via the session extensions (same as tools); prompts receive them in the render args under reserved `io.modelcontextprotocol/*` keys, because `McpPrompt::render` has no session parameter and changing it would break the public trait (documented on the trait; reserved-namespace keys cannot collide with wire prompt arguments, which are plain strings). Tests: two-leg round trips for both methods + a `-32003`/400 capability-gate case on `resources/read` (all real-HTTP; the handlers previously leaked the sentinel to `-32603`).
41+
- **`resources.subscribe` capability truthfulness** — with `subscriptions/listen` serving per-URI `resources/updated`, both capability-construction sites now advertise `subscribe: true` on the 2026 lane (still `false` on 2025, which has no `resources/subscribe` handler). Wire test asserts the `server/discover` advertisement.
42+
- **`completion/complete` e2e coverage** — sessionless dispatch + `CompleteResult` wire shape (`completion.values`) + capability advertisement, closing the last zero-e2e core method on the 2026 path.
43+
44+
### Fixed (2026-06-10, release-prep sweep)
45+
46+
- **Stale crate-doc versions**: 41 dependency-snippet strings across 15 non-frozen crate READMEs/lib-docs said `"0.3"`; all now `"0.4"` (the frozen 2025 protocol snapshots and the terminal-0.3.x shim correctly keep `"0.3"`).
47+
- **Legacy prose labeled in default-lane docs**: `turul-http-mcp-server` README's session/SSE-resumability features and curl examples, and `turul-mcp-server` README's strict-lifecycle note, are now explicitly marked *2025-11-25 opt-in lane* (the 2026 default is POST-only, non-resumable, handshake-free).
48+
- **Comment hygiene in touched 2026 paths**: internal-phase tags, fix-history phrasing, and the `subscriptions.rs` module narrative replaced with present-tense, spec-anchored descriptions.
49+
3850
### Fixed (2026-06-10)
3951

4052
- **`turul-mcp-oauth` CIMD/DCR posture dispositioned (docs/tests-only by design).** Audited against the live draft authorization spec: Client ID Metadata Documents are a SHOULD for *authorization servers and MCP clients*; Dynamic Client Registration is deprecated upstream (MAY, AS back-compat; not removed — earliest removal 2027-07-28). This crate implements the resource-server role only — RFC 9728 Protected Resource Metadata and OAuth 2.1 §5.2/RFC 8707 token validation, both unchanged — so no CIMD or DCR surface belongs in it and none was invented. The role posture is now documented in the crate header, and a wire-shape test pins that the published RFC 9728 document carries no client-registration keys (`registration_endpoint`, `client_id*`, `redirect_uris`, …). Client-side CIMD belongs to a future full MCP OAuth client flow.

crates/turul-http-mcp-server/README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
7070
## Features
7171

7272
-**MCP 2026-07-28 Streamable HTTP (default)** - Stateless core (`server/discover`, per-request `_meta`, no `Mcp-Session-Id`) with SSE streaming; 2025-11-25 sessionful handshake is opt-in
73-
-**Session Management** - UUID v7 session IDs with automatic cleanup
74-
-**SSE Resumability** - Last-Event-ID support with event replay
73+
-**Session Management** *(2025-11-25 opt-in lane)* - UUID v7 session IDs with automatic cleanup
74+
-**SSE Resumability** *(2025-11-25 opt-in lane)* - `Last-Event-ID` event replay on GET SSE; the 2026 default is POST-only and not resumable
7575
-**CORS Support** - Browser client compatibility with configurable origins
7676
-**Protocol Version Detection** - Automatic feature flags based on client capabilities
7777
-**JSON-RPC Dispatch** - Efficient method routing and error handling
@@ -334,7 +334,10 @@ let progress_notification = ProgressNotification {
334334
broadcaster.send_progress_notification("session-123", progress_notification).await?;
335335
```
336336

337-
### Event Replay and Resumability
337+
### Event Replay and Resumability (2025-11-25 opt-in lane)
338+
339+
The 2026-07-28 default endpoint is POST-only and streams are not resumable;
340+
this machinery serves the sessionful 2025-11-25 opt-in lane.
338341

339342
```rust
340343
use turul_http_mcp_server::{extract_last_event_id, StreamManager};
@@ -434,12 +437,12 @@ curl -X POST http://localhost:3000/mcp \
434437
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' \
435438
-v # Note the Mcp-Session-Id header in response
436439

437-
# Test SSE streaming
440+
# Test GET SSE streaming — 2025-11-25 opt-in lane (the 2026 default answers GET with 405)
438441
curl -N -H "Accept: text/event-stream" \
439442
-H "Mcp-Session-Id: <session-id>" \
440443
http://localhost:3000/mcp
441444

442-
# Test event resumability
445+
# Test event resumability — 2025-11-25 opt-in lane
443446
curl -N -H "Accept: text/event-stream" \
444447
-H "Last-Event-ID: event-123" \
445448
-H "Mcp-Session-Id: <session-id>" \
@@ -505,7 +508,7 @@ let transport = HttpMcpServerBuilder::new()
505508

506509
```toml
507510
[dependencies]
508-
turul-http-mcp-server = { version = "0.3", features = ["sse"] }
511+
turul-http-mcp-server = { version = "0.4", features = ["sse"] }
509512
```
510513

511514
Available features:

crates/turul-http-mcp-server/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
//!
1313
//! ```toml
1414
//! [dependencies]
15-
//! turul-http-mcp-server = "0.3"
16-
//! turul-mcp-server = "0.3"
15+
//! turul-http-mcp-server = "0.4"
16+
//! turul-mcp-server = "0.4"
1717
//! ```
1818
//!
1919
//! ## Supported Transports

crates/turul-http-mcp-server/src/middleware/builtins/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@
1818
//! .build()?;
1919
//! ```
2020
21-
// Built-in middleware will be implemented in Phase 4
21+
// Placeholder module: no built-in middleware ships yet.
2222
// For now, this module serves as a placeholder

crates/turul-mcp-aws-lambda/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ Add this to your `Cargo.toml`:
2727

2828
```toml
2929
[dependencies]
30-
turul-mcp-aws-lambda = "0.3"
31-
turul-mcp-derive = "0.3"
30+
turul-mcp-aws-lambda = "0.4"
31+
turul-mcp-derive = "0.4"
3232
lambda_http = "0.17"
3333
tokio = { version = "1.0", features = ["macros"] }
3434
```
@@ -95,7 +95,7 @@ For real-time SSE streaming, enable the `streaming` feature and use `run_streami
9595

9696
```toml
9797
[dependencies]
98-
turul-mcp-aws-lambda = { version = "0.3", features = ["streaming"] }
98+
turul-mcp-aws-lambda = { version = "0.4", features = ["streaming"] }
9999
```
100100

101101
```rust
@@ -499,7 +499,7 @@ let server = LambdaMcpServerBuilder::new()
499499

500500
```toml
501501
[dependencies]
502-
turul-mcp-aws-lambda = { version = "0.3", features = ["cors", "sse", "dynamodb"] }
502+
turul-mcp-aws-lambda = { version = "0.4", features = ["cors", "sse", "dynamodb"] }
503503
```
504504

505505
- `default` - Includes `cors` and `sse`

crates/turul-mcp-builders/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ Add this to your `Cargo.toml`:
2424

2525
```toml
2626
[dependencies]
27-
turul-mcp-builders = "0.3"
28-
turul-mcp-server = "0.3"
27+
turul-mcp-builders = "0.4"
28+
turul-mcp-server = "0.4"
2929
serde_json = "1.0"
3030
```
3131

crates/turul-mcp-client/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Add this to your `Cargo.toml`:
2424

2525
```toml
2626
[dependencies]
27-
turul-mcp-client = "0.3"
27+
turul-mcp-client = "0.4"
2828
tokio = { version = "1.0", features = ["full"] }
2929
```
3030

@@ -479,7 +479,7 @@ fn compare_transports() -> Result<(), Box<dyn std::error::Error>> {
479479

480480
```toml
481481
[dependencies]
482-
turul-mcp-client = { version = "0.3", features = ["sse"] }
482+
turul-mcp-client = { version = "0.4", features = ["sse"] }
483483
```
484484

485485
Available features:

crates/turul-mcp-client/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
//!
2626
//! ```toml
2727
//! [dependencies]
28-
//! turul-mcp-client = "0.3"
28+
//! turul-mcp-client = "0.4"
2929
//! tokio = { version = "1.0", features = ["full"] }
3030
//! ```
3131
//!

crates/turul-mcp-derive/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
//!
2323
//! ```toml
2424
//! [dependencies]
25-
//! turul-mcp-derive = "0.3"
26-
//! turul-mcp-server = "0.3" # For server-side usage
25+
//! turul-mcp-derive = "0.4"
26+
//! turul-mcp-server = "0.4" # For server-side usage
2727
//! ```
2828
//!
2929
//! ## Quick Start

crates/turul-mcp-oauth/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ Add to your `Cargo.toml`:
2222

2323
```toml
2424
[dependencies]
25-
turul-mcp-server = "0.3"
26-
turul-mcp-oauth = "0.3"
25+
turul-mcp-server = "0.4"
26+
turul-mcp-oauth = "0.4"
2727
```
2828

2929
Use the convenience function for single-AS deployments:

0 commit comments

Comments
 (0)