Skip to content

Commit 981fde1

Browse files
move README to examples/ root (covers both client and server folders)
1 parent 1cb4abb commit 981fde1

1 file changed

Lines changed: 22 additions & 17 deletions

File tree

examples/server/src/mrtr-dual-path/README.md renamed to examples/README-mrtr-dual-path.md

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ the diff between files is the argument.
55

66
## What to look at
77

8-
| Direction | Where | How many options |
9-
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
10-
| **Old client → new server** | [`optionA`](./optionAShimMrtrCanonical.ts)[`optionE`](./optionEDegradeOnly.ts) in this folder | Five — server handler shape is genuinely contested |
11-
| **New client → old server** | [`clientDualPath.ts`](../../../client/src/mrtr-dual-path/clientDualPath.ts) (app, ~55 lines) + [`sdkLib.ts`](../../../client/src/mrtr-dual-path/sdkLib.ts) (SDK machinery) | One — handler signature is identical on both paths, SDK just routes |
8+
| Direction | Where | How many options |
9+
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
10+
| **Old client → new server** | [`optionA`](./server/src/mrtr-dual-path/optionAShimMrtrCanonical.ts)[`optionE`](./server/src/mrtr-dual-path/optionEDegradeOnly.ts) in `server/src/mrtr-dual-path/` | Five — server handler shape is genuinely contested |
11+
| **New client → old server** | [`clientDualPath.ts`](./client/src/mrtr-dual-path/clientDualPath.ts) (app, ~55 lines) + [`sdkLib.ts`](./client/src/mrtr-dual-path/sdkLib.ts) (SDK machinery) | One — handler signature is identical on both paths, SDK just routes |
1212

1313
The asymmetry is real: the server-side control flow changes between SSE-elicit (`await` inline) and MRTR (`return IncompleteResult`), so there are trade-offs to argue about. The client-side handler shape is the same either way (`(params) => Promise<ElicitResult>`), so there's
1414
nothing to choose.
@@ -17,20 +17,20 @@ nothing to choose.
1717

1818
| Server infra | 2025-11 client | 2026-06 client |
1919
| ------------ | ------------------------- | -------------- |
20-
| Can hold SSE | **this folder** | just use MRTR |
20+
| Can hold SSE | **options A–E** | just use MRTR |
2121
| MRTR-only | tool fails (unresolvable) | just use MRTR |
2222

2323
Bottom-left is discounted: no amount of SDK work fills it when the server infra can't hold SSE. These demos are about whether the top-left is worth filling, and if so, how.
2424

2525
## Options
2626

27-
| | Author writes | SDK does | Hidden re-entry | Old client gets |
28-
| -------------------------------------- | ------------------------------- | ------------------------------ | ------------------------------------------- | ------------------------------- |
29-
| [A](./optionAShimMrtrCanonical.ts) | MRTR-native only | Emulates retry loop over SSE | Yes, but safe (guard is explicit in source) | Full elicitation |
30-
| [B](./optionBShimAwaitCanonical.ts) | `await elicit()` only | Exception → `IncompleteResult` | Yes, **unsafe** (invisible in source) | Full elicitation |
31-
| [C](./optionCExplicitVersionBranch.ts) | One handler, `if (mrtr)` branch | Version accessor | No | Full elicitation |
32-
| [D](./optionDDualRegistration.ts) | Two handlers | Picks by version | No | Full elicitation |
33-
| [E](./optionEDegradeOnly.ts) | MRTR-native only | Nothing | No | Error ("requires newer client") |
27+
| | Author writes | SDK does | Hidden re-entry | Old client gets |
28+
| ---------------------------------------------------------------- | ------------------------------- | ------------------------------ | ------------------------------------------- | ------------------------------- |
29+
| [A](./server/src/mrtr-dual-path/optionAShimMrtrCanonical.ts) | MRTR-native only | Emulates retry loop over SSE | Yes, but safe (guard is explicit in source) | Full elicitation |
30+
| [B](./server/src/mrtr-dual-path/optionBShimAwaitCanonical.ts) | `await elicit()` only | Exception → `IncompleteResult` | Yes, **unsafe** (invisible in source) | Full elicitation |
31+
| [C](./server/src/mrtr-dual-path/optionCExplicitVersionBranch.ts) | One handler, `if (mrtr)` branch | Version accessor | No | Full elicitation |
32+
| [D](./server/src/mrtr-dual-path/optionDDualRegistration.ts) | Two handlers | Picks by version | No | Full elicitation |
33+
| [E](./server/src/mrtr-dual-path/optionEDegradeOnly.ts) | MRTR-native only | Nothing | No | Error ("requires newer client") |
3434

3535
"Hidden re-entry" = the handler function is invoked more than once for a single logical tool call, and the author can't tell from the source text. A is safe because MRTR-native code has the re-entry guard (`if (!prefs) return`) visible in the source even though the _loop_ is
3636
hidden. B is unsafe because `await elicit()` looks like a suspension point but is actually a re-entry point on MRTR sessions — see the `auditLog` landmine in that file.
@@ -41,9 +41,8 @@ None. All five options present identical wire behaviour to each client version.
4141
in every case. The server's internal choice doesn't leak. This is the cleanest argument against per-feature `-mrtr` capability flags: there's nothing for them to signal, because the client's behaviour is already fully determined by `protocolVersion` plus the existing
4242
`elicitation`/`sampling` capabilities.
4343

44-
For the reverse direction — new client SDK connecting to an old server — see `examples/client/src/mrtr-dual-path/`. Split into two files to make the boundary explicit: [`clientDualPath.ts`](../../../client/src/mrtr-dual-path/clientDualPath.ts) is ~55 lines of what the app
45-
developer writes (one `handleElicitation` function, one registration, one tool call); [`sdkLib.ts`](../../../client/src/mrtr-dual-path/sdkLib.ts) is the retry loop + `IncompleteResult` parsing the SDK would ship. The app file is small on purpose — the delta from today's client
46-
code is zero.
44+
For the reverse direction — new client SDK connecting to an old server — see `examples/client/src/mrtr-dual-path/`. Split into two files to make the boundary explicit: [`clientDualPath.ts`](./client/src/mrtr-dual-path/clientDualPath.ts) is ~55 lines of what the app developer
45+
writes (one `handleElicitation` function, one registration, one tool call); [`sdkLib.ts`](./client/src/mrtr-dual-path/sdkLib.ts) is the retry loop + `IncompleteResult` parsing the SDK would ship. The app file is small on purpose — the delta from today's client code is zero.
4746

4847
## Trade-offs
4948

@@ -61,14 +60,20 @@ the dual-path burden on the tool author rather than the SDK.
6160

6261
## Running
6362

64-
All demos use `DEMO_PROTOCOL_VERSION` to simulate the negotiated version, since the real SDK doesn't surface it to handlers yet:
63+
All demos use `DEMO_PROTOCOL_VERSION` to simulate the negotiated version, since the real SDK doesn't surface it to handlers yet. Server demos run from `examples/server`:
6564

6665
```sh
6766
DEMO_PROTOCOL_VERSION=2025-11 pnpm tsx src/mrtr-dual-path/optionAShimMrtrCanonical.ts
6867
DEMO_PROTOCOL_VERSION=2026-06 pnpm tsx src/mrtr-dual-path/optionAShimMrtrCanonical.ts
6968
```
7069

71-
`IncompleteResult` is smuggled through the current `registerTool` signature as a JSON text block (same hack as #1597). A real implementation emits `JSONRPCIncompleteResultResponse` at the protocol layer — see `shims.ts:wrap()`.
70+
The client demo spawns the server itself (run from `examples/client`):
71+
72+
```sh
73+
DEMO_PROTOCOL_VERSION=2026-06 pnpm tsx src/mrtr-dual-path/clientDualPath.ts
74+
```
75+
76+
`IncompleteResult` is smuggled through the current `registerTool` signature as a JSON text block (same hack as #1597). A real implementation emits `JSONRPCIncompleteResultResponse` at the protocol layer — see `server/src/mrtr-dual-path/shims.ts:wrap()`.
7277

7378
## Not in scope
7479

0 commit comments

Comments
 (0)