Commit Graph

1048 Commits

Author SHA1 Message Date
Max Isbey 2716d09e7a Pin the decorator's refusal messages and describe two wire-base tests
The two `@deferred_model` refusals asserted only the exception type;
they now snapshot the message so a wording change is a deliberate diff
rather than a silent one. The first two wire-base tests gain the
provenance docstrings the rest of the file carries.
2026-07-29 22:38:08 +00:00
Max Isbey cb7c68cf84 Resolve attribute chains through the four leaf sub-packages too
Every package init in the SDK resolves its submodules on attribute
access except four docstring-only leaves - mcp.os.posix, mcp.os.win32,
mcp.server.auth.handlers and mcp.server.auth.middleware - so a chain like
`import mcp; mcp.server.auth.handlers.token` stopped resolving even though
`mcp.client.stdio` and friends do. Give them the same lazy fallback, so
"attribute chains still resolve" is true without a footnote (explicit
imports remain the supported form), and pin one chain through each in the
ratchet.
2026-07-29 22:37:04 +00:00
Max Isbey 008c74e199 Document the prewarm recipe and the rebuild lock's terms
The startup page now leads its prewarming section with warm(version), the
form a host actually wants: it names the version the transport negotiates
and takes the first connection from ~200 ms of one-time builds to within a
millisecond of steady state; the no-argument and all_versions forms are
described as the narrower and wider variants. The magnitude table is
labelled as single-machine measurements.

Two consequences of holding one process-wide lock across a model's first
build are spelled out where they can be found - the lock's docstring and an
FAQ entry: user code inside pydantic schema/subclass hooks runs under the
lock (so ordinary lock-ordering rules apply), a thread mid-build during
fork() leaves the child's lock held, warm() at startup sidesteps both, and
the SDK's lock goes once a pydantic release with a thread-safe
model_rebuild is the dependency floor. The FAQ also notes that
get_type_hints() imports what the hints name (evaluating mcp.Client's hints
imports mcp.server), and the migration guide's list of incidental changes
is no longer titled "two" now that it holds four.
2026-07-29 22:35:26 +00:00
Max Isbey 6da7ba4f09 Spell warm()'s every-version flag as all_versions and return a frozen dataclass
`warm(everything=True)` warmed every protocol version's routing surface -
not "everything the SDK could ever build": the mcp package's own model
roots (mcpserver settings, tool/prompt argument models) belong to the mcp
layer that mcp-types cannot see, and they build during server construction
and tool registration anyway, which is startup work rather than
first-request work. Naming the flag `all_versions` says what it does; the
recommended host recipe is unchanged (`warm(version)` for the version the
transport negotiates).

WarmReport becomes a frozen dataclass instead of a NamedTuple, so a later
field addition does not disturb code that reads the existing fields, and
`mcp.warm` stays the very same function as `mcp_types.methods.warm` (pinned
by a test).
2026-07-29 22:34:45 +00:00
Max Isbey b592f09f4b Generate a deferred model's JSON schema under the rebuild lock too
Completing a deferred model under the process-wide rebuild lock and then
letting pydantic generate its JSON schema outside it left one interleaving:
schema generation for a model reads the core schema of every model it
references, and for the mutually recursive wire JSON models (JSONObject /
JSONArray / JSONValue) a sibling could still be mid-build on another
thread, surfacing as a rare KeyError inside pydantic's schema generation
on some pydantic versions when many threads generated their first schema
of that family at once. No SDK-internal path did this (registration is
single-threaded), but user code may.

The generation now runs under the same lock as the build. Schema
generation is a cold path, so it just serializes with the deferred first
builds; steady state is unchanged. The concurrency ratchet also covers a
concurrent first schema over the recursive JSON family and the 2026 wire
package.
2026-07-29 22:17:24 +00:00
Max Isbey fc4f4e6d1d Cover the decorator's refusal paths and the runtime-only lazy-init branches
The two TypeError guards in deferred_model and plain warm() were
untested, and coverage.py counts the never-taken false arc of the
`if not TYPE_CHECKING:` guards around the lazy module attributes; that
arc belongs to the type checker, so declare it partial by design next
to the existing exclusion rules.
2026-07-29 22:09:54 +00:00
Max Isbey e02caca54b Fail generation if a non-class statement sits between generated classes
The define-before-use reorder reassembles a generated wire package from
its class blocks plus the text before the first class and after the
last, so a module-level statement emitted between two classes would
silently disappear. codegen emits none today; assert it stays that way.
2026-07-29 22:09:54 +00:00
Max Isbey 986d3b9fad Import the internal deferred_model decorator under a private name
Twenty public modules imported the decorator as `deferred_model`, so it
showed up as e.g. mcp.server.elicitation.deferred_model and
mcp_types.jsonrpc.deferred_model even though it is machinery of the
type-layer package, not part of any module's surface. Import it as
_deferred_model so the public namespaces list only what they mean to
export.
2026-07-29 22:09:35 +00:00
Max Isbey 53a46e6c1c Construct DEFAULT_CLIENT_INFO without building the Implementation model
The default Implementation instance was validated at import, which
force-built the deferred Implementation model on every client import
(~0.7 ms). The two literals are trusted, so model_construct produces an
equal instance (same dict, same fields set) without touching the
validator; the model now builds on the first real message instead.
2026-07-29 22:09:18 +00:00
Max Isbey 7fae57664b Document the deferred-work bills and correct the import-cost bullets
docs/advanced/import-cost.md now states the size of every deferred bill (the
per-version wire package, the first HTTP app, the first span, cryptography,
the OAuth provider models, and the ~130 ms a fresh process pays once on its
first connection), and grows an FAQ: an installed pydantic plugin such as
logfire still loads at `import mcp.types` (PYDANTIC_DISABLE_PLUGINS is the
lever), __pydantic_complete__ reads False until first use, function-local
model subclasses keep the generic signature until first use, what to hand a
static bundler, and the get_type_hints waiver for the app builders.

AGENTS.md's import-cost bullets are corrected to match the code: only
mcp/__init__ resolves exports lazily while the other package inits resolve
submodules; cryptography and the OAuth provider models load with their
first user rather than at import; the wire packages also load for the first
rendered elicitation schema. The migration guide notes the removed
McpHttpClientFactory re-export from mcp.client.streamable_http.
2026-07-29 22:08:59 +00:00
Max Isbey 33471c77fd Add mcp.warm(): opt-in prewarming for the deferred validators
The wire schemas load on the first message per protocol version and the
pydantic validators build on first use, which keeps imports fast but puts a
one-time bill on a process's first messages. A long-running host that
would rather pay that at startup than on its first request had only a DIY
recipe of model_rebuild() loops.

mcp_types.methods.warm(version=None, *, everything=False) is the supported
version: with no argument it builds the version-independent set (the
exported mcp_types models, the JSON-RPC envelopes and the routing union
adapters, ~50 ms); with a version it also imports that version's wire
package and builds the routing surface a connection at that version uses
(so its first messages then build nothing); everything=True covers every
known version. Model classes are always completed before the adapters
that reference them, so no schema is generated twice, and repeat calls
are no-ops. It returns a small WarmReport for logging and is re-exported
as mcp.warm. Nothing in the SDK calls it. The import-cost docs recipe now
uses it.
2026-07-29 22:08:37 +00:00
Max Isbey 8c9f2a2ed8 Serialize the deferred first build of the SDK's pydantic models
Released pydantic (through 2.13) does not lock model_rebuild(), so the
first use of a defer_build model from several threads at once - sync tools
running on worker threads, or one client session per thread at process
start - could raise (AttributeError: __pydantic_core_schema__ and friends)
or install a stale validator instead of just building twice. A narrow
version of the same hazard already existed for the handful of models
that were incomplete at import; deferring every model made it reachable
from every entry point.

One process-wide RLock now serializes that one-time build. The
@deferred_model decorator becomes the single mechanism for a deferred
model root: it installs the lazy __signature__, the subclass hook, a
locked model_rebuild (public pydantic API; the extra wrapper frame is
accounted for via _parent_namespace_depth + 1) and a model_json_schema
that completes the class under the same lock before pydantic reads it
(pydantic re-reads the mock schema around a concurrent build).
MCPModel, WireModel and WireRootModel are decorated rather than
hand-writing the hook, and the remaining private deferred roots get the
decorator too, so no deferred model in the SDK builds outside the lock.
The decorator refuses a class that lacks defer_build or that defines its
own __pydantic_init_subclass__ (which it would otherwise replace).
Steady state is untouched: an already-built model never takes the lock.

A subprocess ratchet test races 8 threads over the monolith models, a
wire package, the JSON-RPC envelopes, the SDK's own models, the
module-level adapters and first schema/signature access, and asserts
zero exceptions (it fails without the lock).
2026-07-29 22:07:43 +00:00
Max Isbey d515c85a1f Cover the deferred-signature edge cases: instance access and defer_build turned off 2026-07-29 22:07:43 +00:00
Max Isbey 1facb5762d Document the import-cost contract and the deferred-work model
- AGENTS.md: state the import-cost exception to the imports-at-top rule,
  listing which stacks stay off which import paths and pointing at the
  ratchet test that enforces it.
- New docs page "Imports & startup time" (Advanced): what loads when, the
  one-time first-use costs, and a tested prewarm recipe for hosts that want
  the deferred work paid at startup.
- Migration guide: the lazy import graph, the incidental namespace bindings
  that moved to their defining modules, and defer_build inheritance for user
  subclasses of SDK models.
- What's new: one paragraph on imports paying only for what they use.
2026-07-29 22:07:29 +00:00
Max Isbey 45bb6c9a3b Defer building the SDK's own eager pydantic models and adapters
Every SDK-defined model that used to be built at import - the auth and
OAuth handler models, mcpserver's Resource/ResourceTemplate/Prompt/Tool/
Settings/Context/FuncMetadata, the client's parameter models, transport
security, apps and elicitation results - now sets defer_build=True, and
the remaining module-level TypeAdapters (message_validator,
token_request_adapter) build on first use as well. Each model or validator
is built once, at its first construction or validation, instead of adding
its cost to the import of the module that defines it.

Models that derive from BaseModel directly opt into the lazy __signature__
with @deferred_model, so inspect.signature() on a never-used model keeps
reporting its fields (and mcpserver Settings, whose signature could not
resolve at all before, now does).
2026-07-29 22:06:34 +00:00
Max Isbey 08f438584b Defer building the monolith protocol models and routing adapters
Set defer_build=True on MCPModel, the JSON-RPC envelope models and every
module-level TypeAdapter (the six union adapters in mcp_types, the message
adapter, and the four in mcp.client.session), so importing mcp_types no longer
pays for ~150 models' core schemas, validators and serializers: each is built
once, on first use. The explicit model_rebuild() calls go away (they force an
eager build), and the request-parameter models that carry InputResponses plus
the ContentBlock members are defined before their users so their field
metadata is complete without a first-use rebuild.

Under defer_build pydantic derives a model's __signature__ only when it
builds; a class-level lazy __signature__ (mcp_types._deferred, public pydantic
API only) completes the one-time build via model_rebuild() on first
inspect.signature() access, so introspection matches an eagerly-built model.
MCPModel and the generated wire bases install it for all their subclasses;
models deriving from BaseModel directly opt in with @deferred_model.
2026-07-29 22:05:05 +00:00
Max Isbey b8bc17d787 Defer building the generated wire models and emit them in dependency order
The generated _v2025_11_25 and _v2026_07_28 packages spent ~100-115 ms
each at import building pydantic core schemas, validators and serializers
for ~175 models per version, of which a connection touches only a handful.

Both generated bases now carry defer_build=True: WireModel, and a new
generic WireRootModel[T] the RootModel aliases derive from (deferring only
the object models made things slower, as the eager union roll-ups then
regenerated every deferred model's schema inline). The generator drops
codegen's trailing model_rebuild() epilogue and emits classes in dependency
order - failing if any class names a class defined later - so every
non-recursive generated class still exposes complete field metadata at
import. Building each model's validator now happens once, on first use.
2026-07-29 22:04:51 +00:00
Max Isbey 695b1ab262 Keep the wire packages statically discoverable to bundlers
The per-version wire packages are now imported by module name at runtime,
so PyInstaller-style dependency scanners could no longer see them. A
compiled-in but never-executed TYPE_CHECKING import of both packages next
to the registry keeps them discoverable (and typed) without importing them
at module load.
2026-07-29 22:04:14 +00:00
Max Isbey 9ef39b6cf2 Load the OAuth provider stack and cryptography with their first user, not the server
Two dependencies still rode along with every `import mcp.server*` for
features most servers never use: the OAuth provider models (via
mcp.shared.auth and urllib.parse, ~10 ms) were imported by the
access-token leaf only for a return annotation and by request_state for
principal decomposition, and cryptography (~10 ms, 20-odd modules) was
imported at request_state's module top for the built-in codec.

The access-token module now spells its return type through the lazy
mcp.server.auth namespace and imports no OAuth model; request_state
resolves the provider's principal_components and the AEAD/KDF primitives
through cached loaders on first use (a codec is built by MCPServer(), so
that is where cryptography now loads - once, at construction, never per
request). The import-cost ratchet adds cryptography to the banned set of
every transport-agnostic server entry point and pins where its deferred
load lands.
2026-07-29 22:03:26 +00:00
Max Isbey cdc78fc9d5 Keep the public server signatures resolvable by typing.get_type_hints
Moving the HTTP transport and auth imports under TYPE_CHECKING made
typing.get_type_hints() raise NameError on public methods it used to
resolve on: MCPServer.streamable_http_app / sse_app / run_sse_async /
run_streamable_http_async / session_manager and Server.streamable_http_app
/ session_manager (EventStore, TransportSecuritySettings,
StreamableHTTPSessionManager, AuthSettings, OAuthAuthorizationServerProvider,
TokenVerifier were typing-only names in real annotations).

Two of those types get web-framework-free homes so the server modules can
import them for real without loading starlette: the resumability contract
(EventStore, EventMessage, EventCallback, EventId, StreamId) moves to
mcp.server.event_store, and mcp.server.transport_security keeps only the
pydantic TransportSecuritySettings while its starlette middleware moves
beside the transports. Both old import paths keep working with the same
objects. The session manager and the OAuth annotations are spelled through
the lazy mcp.server namespace instead (the trick already used for
Client.server), so they evaluate on demand and MCPServer stops importing
the OAuth provider stack at module load. The starlette-owned annotations
of the app builders (Starlette, Route, Request/Response) stay typing-only;
get_type_hints on those methods needs starlette's names supplied by the
caller.
2026-07-29 22:02:59 +00:00
Max Isbey 1f3fbc7ca3 Use one lazy-attribute helper for the packages, invisible to type checkers
Three implementations of lazy module attributes had grown: the
hand-rolled __getattr__/__dir__ in mcp/__init__.py, the submodule
fallback factory used by the four package inits, and a one-name
__getattr__ in mcp.server.elicitation. They shared two problems.

An unconditional module-level __getattr__ is visible to type checkers,
so pyright typed every misspelled `mcp.<name>` (and `mcp.client.<name>`,
...) as `object` instead of reporting it. And the submodule fallback ran
a filesystem find_spec on every attribute miss and speculatively imported
whatever matched, so a name sweep (cloudpickle's whichmodule, hasattr
probes) could import real submodules as a side effect, while
dir(mcp.client) no longer listed submodules it would happily resolve.

mcp.shared._lazy.lazy_module_attrs now serves all of them: lazy exports
(a `(module, attr)` pair or a zero-argument loader, resolved once and
cached in the namespace) plus known submodules (an explicit set, or the
package's real submodules listed once on first need). A miss is a plain
AttributeError with no search and no import, and __dir__ reports the
exports and submodules. Every caller binds the pair under
`if not TYPE_CHECKING:`, so attribute typos are pyright errors again
while the TYPE_CHECKING mirrors keep the real names typed. The
mcp.server.auth package gets the same fallback so qualified annotations
such as `mcp.server.auth.provider.TokenVerifier` resolve on demand.

The elicitation gate's wire-schema type is resolved through the same
mechanism from a cached accessor, so validating rendered schemas no
longer re-executes the wire-package import on every call.
2026-07-29 21:59:46 +00:00
Max Isbey 2a13e6dd4a Keep the Client type-hints test green on Python 3.10
typing.get_type_hints(Client) raises TypeError on CPython 3.10 for any
dataclass using KW_ONLY (a stdlib bug fixed in 3.11), which has nothing to
do with the SDK and turned the test red on the 3.10 CI cells. Probe
Client.__init__ instead: it evaluates the same qualified mcp.server
annotation on every supported version.
2026-07-29 19:46:20 +00:00
Max Isbey ff6c36e29f Add an import-cost ratchet for the SDK's entry points
tests/test_import_guards.py runs every check in a fresh interpreter and pins
the module footprint each entry point is allowed to have: `import mcp` is a
lazy namespace, client entry points never load the server or web stack (and
httpx2 only for the HTTP transports), transport-agnostic server entry points
never load starlette / sse_starlette / uvicorn / opentelemetry / httpx2, and
the wire-schema packages load only when their protocol version is used.
A positive parametrized case imports every documented module as the first
import of a fresh process, warning-free, so the lazy resolution can never
grow an import-order dependency.

The earlier per-file fresh-interpreter probes are folded into this module,
which is now the single home for import-graph assertions.
2026-07-29 19:46:20 +00:00
Max Isbey 2a7fb0c739 Keep PrimitiveSchemaDefinition reachable on mcp.server.elicitation
Its module-level import moved into the validation function that uses it, so
the attribute would otherwise disappear from the module namespace. Resolve it
on first access via a module-level __getattr__ (and keep it in dir()) so
existing references to mcp.server.elicitation.PrimitiveSchemaDefinition keep
working without reintroducing the import at module load.
2026-07-29 19:46:20 +00:00
Max Isbey 0237ed9411 Load per-version wire packages lazily from the methods surface maps
mcp_types.methods imported both generated wire packages (_v2025_11_25 and
_v2026_07_28, roughly 200 pydantic models each) at module import solely to
fill the surface maps' values, although a connection negotiates exactly one
protocol version and nothing reads a value at import time.

The map rows now record the wire type's attribute name; the package a row
lives in follows from the key's protocol version and is imported by a cached
lookup on the first row read, then cached per row. The public maps stay
MappingProxyType objects over the resolved rows (same protocol, repr and
equality as before), so importing mcp_types.methods - and therefore mcp,
mcp.types and every entry point above them - no longer builds any wire
package; the first message parsed for a version builds that version once.

The elicitation module's single wire-schema import moves into the function
that uses it for the same reason.
2026-07-29 19:46:20 +00:00
Max Isbey 3ac881f1b4 Test HttpResource.read() instead of excluding it from coverage
The method body had been marked `# pragma: no cover` (widened further once
httpx2 moved into the method). Exercise it against an httpx2 MockTransport
instead, covering both the response body and the raise_for_status path, and
drop the pragma.
2026-07-29 19:46:20 +00:00
Max Isbey fcaf29741b Make server-side imports pay-for-what-you-use
The HTTP transport stack (starlette, sse_starlette, uvicorn) is no
longer imported by the transport-agnostic server modules at module
import: the lowlevel Server and MCPServer import the web stack inside
streamable_http_app() / sse_app() / custom_route(), with
annotation-only names moved under TYPE_CHECKING, so a stdio server
never loads it. The request access-token contextvar and
get_access_token, which the request-state boundary and handlers read
regardless of transport, move to a starlette-free module,
mcp.server.auth.access_token, and are re-exported from
mcp.server.auth.middleware.auth_context so the existing import path
keeps working; the boundary now reads the principal without the HTTP
stack. opentelemetry-api is imported on the first span instead of at
import (cached in module globals; otel_span takes the span kind by
name), and httpx2 is imported only when an HttpResource is read. The
streamable-HTTP request-body-size default moves to a leaf module so
the servers' signatures do not import the transport.
2026-07-29 19:45:40 +00:00
Max Isbey 5b2530332f Keep typing.get_type_hints(Client) resolvable at runtime
Making the server stack a typing-only import in the client module left
the `Client.server` annotation naming `Server` / `MCPServer`, which
`typing.get_type_hints` can then no longer evaluate: string annotations
are evaluated against the module dict, so a module-level `__getattr__`
would not be consulted either.

Spell the annotation through the `mcp.server` namespace instead. Evaluating
the hints then walks the lazy `mcp` package, which imports `mcp.server` at
that moment only; `import mcp.client` stays free of the server stack and the
evaluated hint is the same union of classes as before. The package's
TYPE_CHECKING mirror now also lists the subpackages that its `__getattr__`
resolves on first access, so type checkers see the same chains.
2026-07-29 19:45:28 +00:00
Max Isbey 1e00f4231d Load httpx2 with the HTTP transports only
The streamable-HTTP client transport (httpx2) is now imported when the
first URL Client is constructed instead of at import time, so a stdio-only
client (or a bare `import mcp.client`) never loads it. Tests cover the
resulting import contract: the client entry points load neither the
server stack nor httpx2 until they are used, and the package's lazy
server-side re-exports still resolve to their defining objects.

The test that patched `mcp.client.client.streamable_http_client` now
patches the transport at its defining module.
2026-07-29 19:45:15 +00:00
Max Isbey 1c1b7f83c1 Stop mcp.client from importing the server stack
Client only needs Server/MCPServer/InMemoryTransport/modern_on_request when it
is handed a live in-process server, and a Server instance can only exist once
the user has imported the server stack. Detect that case via sys.modules
instead of eager imports, keep the server types for static checking under
TYPE_CHECKING, and import the in-memory bridge inside _connect_inproc.
2026-07-29 19:45:15 +00:00
Max Isbey 2128b57a84 Resolve submodules of mcp.client, mcp.server, mcp.shared and mcp.os on attribute access
Adds a small PEP 562 __getattr__ factory (mcp.shared._lazy_submodules) and
installs it on the four packages, so attribute chains that used to resolve only
because the top-level package imported everything eagerly - e.g.
import mcp; mcp.client.stdio.stdio_client - keep resolving now that the mcp
package is lazy: touching pkg.name imports the submodule pkg.name if it exists,
raising AttributeError otherwise and surfacing a submodule's own missing
dependency as its real ImportError.
2026-07-29 19:45:15 +00:00
Max Isbey 622aed578e Resolve the mcp package's exports lazily (PEP 562)
`import mcp` used to import the protocol types plus the entire client and
server stacks (in-memory transport, lowlevel server, HTTP transports, otel,
auth) just to bind the names in `mcp.__all__`.

Each export is now resolved from its home module by a module-level
`__getattr__` on first access and cached in the package namespace; the
old eager import block is mirrored name-for-name under `TYPE_CHECKING`
so type checkers and the docs generator see the same bindings.
`__all__`, `dir(mcp)`, `from mcp import *`, object identity and the
`mcp.types` submodule binding are unchanged.

A bare `import mcp` no longer loads pydantic, mcp_types or any mcp
submodule; each entry point pays only for what it uses.
2026-07-29 19:45:15 +00:00
Max 6f69a3758e Present v2 as the stable release across the README, docs, and policies (#3178)
Conformance Tests / server-conformance (push) Has been cancelled
Conformance Tests / client-conformance (push) Has been cancelled
Deploy Docs / deploy-docs (push) Has been cancelled
GitHub Actions Security Analysis / zizmor (push) Has been cancelled
CI / checks (push) Failing after 1s
CI / all-green (push) Has been cancelled
v2.0.0
2026-07-28 14:31:36 +01:00
Max 78e6fbb7e4 Serve v2 docs at the site root, with permanent per-major paths (#3176) 2026-07-28 13:57:21 +01:00
Max af06330a31 Remove unused StreamableHTTPTransport.get_session_id() (#3205) 2026-07-28 13:55:02 +01:00
Max 68ca87e20b Document the two-line release process for stable v2 (#3179) 2026-07-28 13:51:31 +01:00
Max c9c431b71a Expose the middleware chain on MCPServer and stop sending unrequested change notifications (#3201) 2026-07-28 12:24:23 +01:00
Max 528e366558 Fail fast on server-to-client requests in JSON-response mode instead of hanging (#3195) 2026-07-28 11:04:51 +01:00
Max 27f5cc7a46 Remove unused mcpserver.exceptions.ValidationError (#3199) 2026-07-28 10:25:51 +01: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 b61ce388dd docs: fix off-by-one hl_lines in apps.md (#3196) 2026-07-28 00:04:57 +01:00
Max b7c9a916d6 Add mcp.types as a permanent alias for mcp_types (#3190) 2026-07-27 23:47:04 +01:00
Max 923341c98a Stop answering cancelled requests (#3188) 2026-07-27 23:26:00 +01:00
Max e8ef138153 docs: fill migration-guide gaps found by automated v1-to-v2 migration runs (#3187) 2026-07-27 23:17:17 +01:00
Max d3ffe87960 Split the registration request model from the registered-client record (#3181) 2026-07-27 23:11:01 +01:00
Max b9422f1c9b Make the per-version wire packages private (mcp_types._v*) (#3191) 2026-07-27 22:16:48 +01:00
Max 45f2a88a9a Point pre-release install pins at 2.0.0rc1 (#3186)
CI / checks (push) Failing after 1s
CI / all-green (push) Has been cancelled
v2.0.0rc1
2026-07-27 14:23:57 +01:00
Max 333aca7ac8 Repin conformance harness to the published 0.2.0-alpha.10 (#3184) 2026-07-27 14:03:06 +01:00
Max dcd9c1ee9f Lengthen the demo signing keys in the identity-assertion examples (#3180)
Conformance Tests / server-conformance (push) Has been cancelled
Conformance Tests / client-conformance (push) Has been cancelled
Deploy Docs / deploy-docs (push) Has been cancelled
GitHub Actions Security Analysis / zizmor (push) Has been cancelled
CI / all-green (push) Has been cancelled
CI / checks (push) Failing after 0s
2026-07-26 11:45:26 +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