Commit Graph

104 Commits

Author SHA1 Message Date
Max Isbey 116a95fc37 Re-point fd at the wire when a divert dup2 fails
A Windows dup2 (UCRT before Windows 11) closes its target before
duplicating, so an OSError from the divert can leave the standard
descriptor closed rather than still carrying the wire. Run the same
dup2(private_fd, fd) restore the exit path uses before serving in
place: an idempotent no-op when fd is already on the wire, and a
re-materialization from the private duplicate when the target was
closed. Adds a regression variant that closes the target as UCRT does.

Also scopes the real-host logging note to the default stderr handler.
2026-07-24 16:19:49 +00:00
Max Isbey 885c6aa9a4 Scope the stray-output docs to flushed writes
The diversion catches output that is actually flushed to stdout while
serving. A print() in a block-buffered process usually stays unflushed
in sys.stdout's user-space buffer, and the interpreter's exit flush
drains it onto the restored protocol stream, so the docs now say so
instead of implying every stray print is diverted. The logging advice
is unchanged: its handler flushes each record.

No-Verification-Needed: docs-only wording change
2026-07-24 16:19:49 +00:00
Max Isbey ad9c115f29 Correct the watchdog poll mask note and use the public get_osfhandle
The null device reports POLLIN (plus POLLOUT under the default event
mask), never POLLERR; the migration note taught the wrong mask. The
Windows handle rebind now uses msvcrt.get_osfhandle, the documented
public API, instead of pywin32's underscore-private equivalent, which
also drops the win32file import. The migration entry also gains the
one API-visible change: a second concurrent stdio_server() raises
RuntimeError.
2026-07-24 16:19:48 +00:00
Max Isbey 0f9695fe2c Never close a buffer the transport does not own
The transport's text layers now detach instead of closing on garbage
collection. In the in-place paths the wrapped buffer is the sys
stream's own, and closing it destroyed sys.stdout for the rest of the
process (the issue #1933 class, which the claimed path had already
fixed incidentally via the private descriptor).

Also strengthens the fd 0 watchdog migration note (the null device
reports permanently readable, so any-event watchers misfire at startup
rather than merely never firing) and restores the note about child
output volume flowing into the client's stderr channel.
2026-07-24 16:19:48 +00:00
Max Isbey 87dda9759d Scope the fd 0 watchdog migration example to POSIX
os.getppid() never changes on Windows, and the polled-fd pattern being
migrated is POSIX-only to begin with.

No-Verification-Needed: docs-only change
2026-07-24 16:19:48 +00:00
Max Isbey 3e321f6de0 Add migration note for code that watches fd 0 directly
No-Verification-Needed: docs-only change
2026-07-24 16:19:48 +00:00
Max Isbey 987b69128d Replace dashes with plain punctuation in prose added by this branch
No-Verification-Needed: docstring and docs prose only
2026-07-24 16:19:48 +00:00
Max Isbey 2e609e18a3 Refuse abnormal processes instead of repairing them in stdio isolation
The stdin/stdout claim now engages only in a normal process: the sys
stream backed by its real descriptor and fds 0-2 all open, which makes
it impossible for the private wire duplicates to land in the standard
range. Anything else - replaced streams, an incomplete descriptor
table, a failed dup - is served in place exactly as v1 was, and a
second concurrent stdio_server() raises RuntimeError instead of
contending for the streams.

This replaces the previous hardening (the dup-above-standard-range
loop, stderr-merge detection, and nested transports serving into the
diversion) with guards, and removes the migration entry: no working
code changes behavior, so there is nothing to migrate. Comments and
docstrings trimmed throughout the diff.
2026-07-24 16:19:48 +00:00
Max Isbey 2b0f3ace9f Isolate the stdio server's stdout from handler code and subprocesses
While serving on the process's real stdout, stdio_server now moves the
protocol pipe to a private descriptor and points fd 1 - and, on
Windows, the standard output handle - at stderr, restoring it when the
transport exits. A stray print() in handler code or a child process
writing to its inherited stdout lands in the client's log instead of
corrupting the JSON-RPC stream. The null device stands in when stderr
is unusable or, on POSIX, is detected as merged into stdout (2>&1).

The stdin claim generalizes into the shared _claim_fd mechanism: one
lock-guarded sentinel table covers both descriptors, private wire
duplicates are forced above the standard descriptor range so a process
started with a standard descriptor closed cannot hand the wire out as
its "stderr", and a failed claim degrades to serving the sys stream's
buffer in place exactly as v1 did.

Docs now describe the guarded behavior with its remaining gaps (output
flushed before serving begins, injected streams, merged stderr on
Windows), and the transport:stdio:stream-purity divergence narrows
accordingly.
2026-07-24 16:19:48 +00:00
Max Isbey fbe9841788 Isolate the stdio server's stdin from handler subprocesses
While serving on the process's real stdin, stdio_server() now reads the
protocol from a private duplicate of fd 0 and points fd 0 (and, on
Windows, the standard input handle) at the null device, restoring both
on exit. Children spawned by handler code then inherit the null device
instead of the protocol pipe.

A child that inherited the pipe could consume protocol bytes on any
platform, and on Windows a Python child hangs inside interpreter
startup behind the transport's pending read (CPython gh-78961) until
the next request arrives, so any tool that ran a subprocess without
stdin=DEVNULL appeared to hang until timeout.

Isolation engages only when sys.stdin is backed by the real fd 0, at
most once per process, and degrades to reading stdin in place when the
descriptor table cannot be rearranged.

Fixes #671.
2026-07-24 16:19:48 +00:00
Max 00a70148bc Serve the 2026-07-28 protocol over stdio: decide the era from the opening request (#3152)
CI / checks (push) Failing after 1s
Deploy Docs / deploy-docs (push) Has been cancelled
Conformance Tests / server-conformance (push) Has been cancelled
Conformance Tests / client-conformance (push) Has been cancelled
GitHub Actions Security Analysis / zizmor (push) Has been cancelled
CI / all-green (push) Has been cancelled
2026-07-24 13:46:37 +01:00
Max 837ef904f8 Align with spec #3002: optional clientInfo, serverInfo in result _meta (#3143)
Deploy Docs / deploy-docs (push) Has been cancelled
CI / checks (push) Failing after 24m23s
CI / all-green (push) Has been cancelled
Conformance Tests / server-conformance (push) Has been cancelled
Conformance Tests / client-conformance (push) Has been cancelled
GitHub Actions Security Analysis / zizmor (push) Has been cancelled
2026-07-23 12:00:36 +01:00
Max 3a6f2996cd docs: load media examples from disk instead of inline base64 (#3108) 2026-07-16 20:41:05 +01:00
Andre.Kalberer e464f72c12 docs: document Windows stdio subprocess stdin handling (#3079) 2026-07-16 11:25:47 +01:00
Marcelo Trylesinski 03aaebd3aa Add Streamable HTTP request body limits (#3095) 2026-07-16 08:33:32 +02:00
Marcelo Trylesinski 2713b53b12 Replace httpx and httpx-sse with httpx2 (#2972)
CI / checks (push) Failing after 1s
CI / all-green (push) Has been cancelled
Co-authored-by: Max Isbey <224885523+maxisbey@users.noreply.github.com>
2026-07-14 17:05:08 +01:00
Marcelo Trylesinski 4fc8882c02 docs: replace MkDocs with Zensical (#3073)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Max Isbey <224885523+maxisbey@users.noreply.github.com>
2026-07-10 12:48:46 +01:00
Max 9bdc03d54e Add the client-side subscriptions/listen driver (#3047) 2026-07-07 14:26:09 +01:00
Max d287c9868f Extend resolver DI to sampling and roots requests (#3049) 2026-07-06 18:25:57 +01:00
Max bf4402725d docs: restructure the migration guide around topical groups with a navigation layer (#3058) 2026-07-02 18:54:21 +01:00
Max 2359b40285 docs: modernize the site theme (#3057) 2026-07-02 16:17:33 +01:00
Max e4d95e0d44 docs: add a "What's new in v2" page (#3054) 2026-07-02 15:01:30 +01:00
Max 220d362112 docs: restructure into topical sections and add the four most-asked-for pages (#3044) 2026-07-01 21:06:04 +01:00
Max 080f2a869d Harden the dual-era stream loop's era-lock and rejection semantics (#3040) 2026-07-01 17:07:12 +01:00
Max 0da9092037 Point pre-release install pins at 2.0.0b1 (#3039)
CI / checks (push) Failing after 0s
CI / all-green (push) Has been cancelled
2026-07-01 00:14:52 +01:00
Max 410cc0db31 Add v2 feedback issue template (#3037) 2026-07-01 00:03:11 +01:00
Max ca10dade2c Serve subscriptions/listen with a pluggable event bus (SEP-2575) (#3035) 2026-06-30 23:01:04 +01:00
Max 48ef569f7e Validate Mcp-Param-* headers server-side on the 2026-07-28 HTTP path (SEP-2243) (#3033) 2026-06-30 21:39:32 +01:00
Max 4df609119f Add a client extension API (#3034) 2026-06-30 21:31:02 +01:00
Max 7322ca56f4 Require integrity protection for MRTR requestState (#3032) 2026-06-30 21:30:32 +01:00
Max b15b1d5f07 Add a client-side response cache honoring SEP-2549 caching hints (#3023) 2026-06-30 11:31:06 +01:00
Max 67d7593df1 docs: publish llms.txt and markdown renditions of the docs (#3024) 2026-06-30 11:30:55 +01:00
Max 8d0f928e40 Pass InputRequiredResult through the MCPServer prompt and resource pipelines (#3020) 2026-06-29 16:50:58 +01:00
Max 8f2c97b769 Consult request_state only for the question a resolver is asking (#3019) 2026-06-29 16:44:05 +01:00
Max 533c6a8226 Add cache_hints constructor map for SEP-2549 caching hints (#3015) 2026-06-29 14:11:15 +00:00
Marcelo Trylesinski c85836a081 Drive resolver elicitation over the 2026-07-28 input_required flow (#2986)
Co-authored-by: Max Isbey <224885523+maxisbey@users.noreply.github.com>
2026-06-29 14:39:43 +01:00
Max 24fdd909ac docs: convert bold cross-references into links, link SEP and RFC mentions (#3017) 2026-06-29 11:07:26 +00:00
Marcelo Trylesinski f664db8952 Add resolver dependency injection for MCPServer tools (#2969)
Co-authored-by: Max Isbey <224885523+maxisbey@users.noreply.github.com>
2026-06-29 11:51:46 +01:00
Marcelo Trylesinski 4b519782f1 Add a pluggable server extension API with MCP Apps (#3003)
Co-authored-by: Max Isbey <224885523+maxisbey@users.noreply.github.com>
2026-06-29 10:58:05 +01:00
Max 3b78f86886 Add docs, tested examples, and a story for SEP-990 identity assertion (#3004) 2026-06-26 21:01:46 +02:00
Max 24717cc8eb feat: RFC 6570 URI templates with operator-aware security (#2356) 2026-06-26 20:29:17 +02:00
Marcelo Trylesinski c0ecb70e24 Support RFC 8693 token exchange for enterprise IdP flows (SEP-990) (#2988)
Co-authored-by: Max Isbey <224885523+maxisbey@users.noreply.github.com>
2026-06-26 17:57:10 +02:00
Marcelo Trylesinski ecdf09d44f Deprecate Server.__init__ handlers for removed capabilities (#3002) 2026-06-26 17:51:13 +02:00
Max 08b62308d4 Client auto-resolves InputRequiredResult via existing callbacks (SEP-2322) (#2998) 2026-06-26 17:35:23 +02:00
Marcelo Trylesinski b31d95a429 Make OpenTelemetry tracing the single default middleware (#2995) 2026-06-26 15:47:37 +02:00
Marcelo Trylesinski 5b2713d40c Mirror x-mcp-header tool arguments into Mcp-Param-* request headers (SEP-2243) (#2990) 2026-06-26 14:36:56 +02:00
Max 3a8da8c0c3 Fix docs/release follow-ups from the mcp-types package split (#2977) 2026-06-26 13:16:09 +02:00
Max 411a6d3980 Rebuild the docs around tested examples; shrink README.v2.md to a pitch (#2978) 2026-06-26 12:49:19 +02:00
Marcelo Trylesinski f41a5193f3 Preserve empty issuer/resource paths on AuthSettings (#2987) 2026-06-26 11:41:41 +02:00
Max 587340279e Conformance burn-down: server-side InputRequiredResult, Mcp-Method/Name validation, x-mcp-header filter (14 scenarios → green) (#2974)
CI / checks (push) Failing after 0s
CI / all-green (push) Has been cancelled
2026-06-26 09:51:59 +02:00