Commit Graph

172 Commits

Author SHA1 Message Date
Claude 0b3c2ebc8a fix: track main's optional serverInfo and empty-string server version
main now types Client.server_info as Implementation | None (serverInfo is
optional at 2026-07-28) and defaults server version to "" instead of None.

- ServerCard.from_server treats a derived empty version as unset, so a
  server without a version still fails card validation
- reconcile_server_card accepts server_info=None: an anonymous server makes
  no identity claim, so only the protocol version check applies
2026-08-02 18:46:21 +00:00
Claude 63fe92d5eb Merge remote-tracking branch 'origin/main' into feat/experimental-server-card 2026-08-02 18:37:45 +00:00
Claude e3536df3c9 refactor: address review feedback on the Server Card API surface
- Replace build_server_card() with the ServerCard.from_server() classmethod,
  matching the SDK's from_* alternate-constructor idiom; the _ServerIdentity
  protocol moves to mcp.shared.experimental.server_card alongside it.
- Make DiscoveryResult iterable over its listings (__iter__/__len__), so
  'for listing in result:' works without the .listings attribute hop.
- Remove the client-side server_card_url() helper: card URLs must come from
  an AI Catalog entry per the discovery spec, never be constructed by the
  client. fetch_server_card's docstring now says so.
- Explain the RFC 6598 shared address space constant in the SSRF guard and
  rename it _CGNAT_NETWORK -> _SHARED_ADDRESS_SPACE; ipaddress reports these
  addresses as neither private nor global, so the guard names them explicitly.

All symbols are experimental (no deprecation cycle), so the removals are clean.
2026-08-02 18:15:56 +00:00
Max 89c5e700f2 Gate log notifications on the per-request log-level opt-in at 2026-07-28 (#3198) 2026-07-28 02:20:33 +01:00
Max d3ffe87960 Split the registration request model from the registered-client record (#3181) 2026-07-27 23:11:01 +01:00
Jeremiah Lowin f599cdfcf9 Cache compiled output-schema validators on ClientSession (#3134)
Co-authored-by: Max Isbey <224885523+maxisbey@users.noreply.github.com>
2026-07-26 11:29:10 +01:00
Max 814072c94d Narrow message_handler's parameter to notifications and exceptions (#3168) 2026-07-26 00:24:48 +01:00
Max 47bfa85e83 Remove the unused timeout parameter from OAuthClientProvider (#3165) 2026-07-26 00:22:15 +01:00
Max 7163d8263f Remove the deprecated RFC7523OAuthClientProvider (#3169) 2026-07-25 22:50:57 +01:00
Max e90a66b554 Rename scopes= to scope= on the client-credentials OAuth providers (#3166) 2026-07-25 20:23:36 +01:00
Max 0cb920f126 Make CacheConfig() the Client cache default and None the off switch (#3164) 2026-07-25 17:50:53 +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
Claude 3d50b08b73 fix: harden Server Card discovery and close review gaps (experimental)
Discovery client:

- Bound each probe with DiscoveryPolicy.max_probe_entries (default 500),
  an aggregate budget over every card and nested-catalog entry one walk
  processes; exhaustion records a single "probe_budget" failure and drops
  the rest. Already-visited nested catalog URLs are never refetched, so
  cyclic or duplicated catalogs terminate. Without this the per-catalog
  entry cap and the depth cap compose multiplicatively (~entries**depth
  fetches from one hostile catalog).
- Catch OSError per entry too: an unresolvable host (socket.gaierror from
  the guard's own DNS resolution) or a tar-pit entry (TimeoutError from
  the per-fetch deadline) becomes a failure instead of killing the whole
  probe, as the DiscoveryResult contract promises. Both exceptions are
  now documented on the public fetchers.
- CardListing.listing_domain/hosting_domain return host[:port] built from
  the parsed hostname, never the raw netloc, and _admit_url rejects
  userinfo-carrying URLs outright, so https://github.com@evil.example/
  can neither be fetched nor rendered as a trusted brand in consent UI.
- _is_blocked_address unwraps IPv4-mapped IPv6 literals and applies the
  IPv4 rules, closing the ::ffff:100.64.0.1 CGNAT bypass (and the
  private-range leak on interpreters without the gh-113171 fix).
- discover_server_cards with http_client=None opens one credential-free
  client for the whole walk instead of one per fetched entry.
- Plain http is refused up front under the hardened policy (the loopback
  carve-out was unreachable: loopback fails the address guard anyway).
- DiscoveryErrorReason is re-exported from the public module, and one
  accept_header() helper replaces the duplicated Accept literals.

Models and server:

- Remote.required_variables now includes required headers that carry no
  value and no default, keyed by header name exactly as resolve_remote
  accepts them, so prompting from the property and then resolving works.
- mount_discovery documents that public_url is the app's public base URL.
- The discovery routes' CORSMiddleware allows only GET, so real browser
  preflights advertise the spec's method list.

Tests cover the budget walk (exact fetch sequence), visited-set dedup,
per-entry DNS-failure and timeout resilience, userinfo rejection and
display, mapped-IPv6 blocking, required-header prompting, Repository and
icons round-trips, and the preflight headers.
2026-07-21 07:26:29 +00:00
Claude 7d731decf8 feat: hardened Server Card discovery client (experimental)
Client-tier helpers: fetch_server_card / fetch_ai_catalog /
discover_server_cards run every fetch through a hardened core
(https-only with loopback-http exception, SSRF address guard with
post-DNS re-check, manual redirect walking with per-hop re-admission,
response size and catalog entry/depth caps, Accept and media type
discipline) governed by DiscoveryPolicy. Probes collect per-entry
failures instead of raising, and CardListing exposes the listing chain
for consent UI. Stateless request/parse pairs support host-owned ETag
revalidation, and reconcile_server_card compares card claims to runtime
values without ever enforcing them.
2026-07-21 06:22:10 +00: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
Max 9bdc03d54e Add the client-side subscriptions/listen driver (#3047) 2026-07-07 14:26:09 +01:00
Max 867bba6263 Share one event loop per test module to stop Windows socketpair churn (#3070) 2026-07-07 13:19:04 +01:00
Max 53117cb3a9 Make client-side cancellation work over the 2026 transports (#3046) 2026-07-02 19:21:04 +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 e50fb5be19 Serve the 2026-07-28 era over stdio and other stream-pair transports (#3038) 2026-07-01 00:11:56 +01:00
Max 4df609119f Add a client extension API (#3034) 2026-06-30 21:31:02 +01:00
Max b15b1d5f07 Add a client-side response cache honoring SEP-2549 caching hints (#3023) 2026-06-30 11:31:06 +01: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 cc596195bb Switch RFC7523OAuthClientProvider warning to MCPDeprecationWarning (#2996) 2026-06-26 15:27:57 +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
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
Marcelo Trylesinski 0ee7f1b293 Split protocol types into a standalone mcp-types package (#2973) 2026-06-25 19:18:38 +02:00
Max 03681ed55e Client call_tool: input_responses/request_state retry params; InputRequiredResult via allow_input_required (#2968) 2026-06-25 17:37:00 +02:00
Max f226d00d0a Client-side 2026-07-28 support: .discover()/.adopt() + Client(mode=); request-metadata green (#2950) 2026-06-25 16:09:23 +02:00
Max 44ce901ce3 OAuth client: keep refresh_token on non-rotating refresh; restore same-origin issuer binding (#2946) 2026-06-22 15:21:52 +01:00
Max 5e013d9c54 OAuth client: harden SEP-2352/SEP-2350 edge cases; fix conformance comment (#2936) 2026-06-22 14:45:20 +01:00
Max 2397319a68 Server-side 2026-07-28 stateless support: classifier, driver split, server/discover (#2928) 2026-06-21 19:34:17 +01:00
Marcelo Trylesinski 44724284b3 Bind client credentials to their authorization server (SEP-2352) (#2933) 2026-06-20 18:47:22 +01:00
Marcelo Trylesinski 3169922492 Move scope step-up test to top-level function (#2932) 2026-06-20 18:45:10 +01:00
Marcelo Trylesinski 1331131650 Union previously requested scopes on step-up re-authorization (SEP-2350) (#2931) 2026-06-20 18:45:04 +02:00
Marcelo Trylesinski 4573e4ac33 Deprecate roots, sampling, and logging methods per SEP-2577 (#2926) 2026-06-20 18:25:41 +02:00
Marcelo Trylesinski cf41441e44 Send application_type during Dynamic Client Registration (SEP-837) (#2930) 2026-06-20 18:19:12 +02:00
Marcelo Trylesinski 48cf4950dc Validate the iss authorization-response parameter (RFC 9207 / SEP-2468) (#2921) 2026-06-20 17:54:18 +02:00
Marcelo Trylesinski b7a5bffed0 Preserve empty URL paths on OAuth metadata models (#2925) 2026-06-20 15:32:03 +00:00
Max 5a3412ddc1 Ignore pre-2026 protocol_version pins at the StreamableHTTP transport (#2923) 2026-06-20 17:29:57 +02:00
Max 84bf9bde05 First end-to-end 2026-07-28 stateless tools/call (experimental entry + ClientSession pin) (#2917) 2026-06-20 14:55:59 +01:00
Max 65be5a7147 Protocol types for 2026-07-28: superset monolith, committed per-version packages, and wire-method maps (#2849) 2026-06-16 17:40:14 +01:00
Max 1012d60004 [v2] ClientSession runs on JSONRPCDispatcher; BaseSession removed (#2838) 2026-06-15 14:46:34 +01:00
Max 7267818e44 Fix unknown-method error code and add a protocol version registry (#2836) 2026-06-11 16:47:22 +01:00
Max 5d826490b6 [v2] Dispatcher/ServerRunner receive-path swap — replaces BaseSession (#2710) 2026-06-09 12:58:47 +01:00
Max b478bff56d Remove the unsupported WebSocket transport (#2785) 2026-06-08 12:05:27 +01:00
Max bdc48e98b1 Fix stdio client shutdown bugs and rebuild the stdio test suite (#2773) 2026-06-05 16:15:43 +01:00