@modelcontextprotocol/core Schemas
Purpose and Scope
@modelcontextprotocol/core is the package to reach for when your code holds raw MCP or OAuth JSON rather than already-validated SDK objects. The high-level Client and server APIs usually hide this layer: a connected client lists tools, calls tools, reads resources, fetches prompts, negotiates capabilities, and handles authentication through typed helpers. Core schemas are for the boundary cases around those helpers, such as gateways, proxies, conformance harnesses, custom transports, and middleware that must decide whether an upstream or downstream payload is valid before forwarding it.
Sources: docs/clients/connect.md, docs/clients/calling.md, docs/clients/oauth.md
The important distinction is between SDK object flow and wire-payload flow. In SDK object flow, Client.connect() completes the initialize handshake and stores the server version, capabilities, and instructions; later methods such as listTools(), callTool(), and readResource() expose typed result shapes. In wire-payload flow, your application receives unknown JSON from an HTTP response, a queue, a log replay, or another MCP implementation. @modelcontextprotocol/core gives you the same Zod schema constants the SDK uses so you can validate that JSON without constructing a client or server.
Sources: docs/clients/connect.md, docs/clients/calling.md
Relevant Source Files
docs/clients/connect.md- Defines the normal client lifecycle, includingClient, transports,connect(), negotiated server metadata, and clean shutdown; this shows what core schemas are not needed for when the SDK owns the handshake.docs/clients/calling.md- Describes typed client calls forlistTools(),callTool(),readResource(), prompts, pagination, structured output, and tool-result validation; these are the protocol payload families most commonly validated with core schemas when handled as raw JSON.docs/clients/oauth.md- Documents end-user OAuth provider types and flow state, includingOAuthClientProvider,OAuthClientMetadata,OAuthTokens, discovery state, issuer binding,UnauthorizedError, and callback completion; these identify OAuth payloads that may need wire validation in custom integrations.docs/clients/machine-auth.md- Covers machine authentication helpers such asClientCredentialsProvider,PrivateKeyJwtProvider,CrossAppAccessProvider,AuthProvider, issuer pinning, token refresh, and bearer token behavior; these map to OAuth and OpenID-adjacent payload validation concerns.docs/clients/caching.md- Explains response cache hints, cache modes,ResponseCacheStore,InMemoryResponseCacheStore, and per-user partitions; this is useful context for validating cached protocol results before storing or replaying them.docs/clients/middleware.md- Shows HTTP client middleware throughcreateMiddleware,applyMiddlewares,withLogging, and OAuth middleware; this is a common place to inspect or validate raw request and response bodies before the transport consumes them.
When to Use Core Schemas
Use core schemas when your program is closer to the wire than to the SDK API. A gateway that forwards tools/call responses, a worker fleet that persists advertisements, a test harness that replays JSON-RPC transcripts, or a proxy that validates OAuth metadata should not have to reimplement MCP shape checks. Importing a schema such as CallToolResultSchema from @modelcontextprotocol/core and calling safeParse() gives you a typed success value or a structured Zod failure without throwing. That lets boundary code reject invalid JSON while keeping protocol-aware error messages near the integration point.
Sources: docs/clients/calling.md, docs/clients/middleware.md
Do not add @modelcontextprotocol/core just because you are building a normal MCP client. The client guide shows that Client methods already aggregate paginated list results, surface content arrays, expose structured tool output as unknown for application narrowing, validate known structured output when the tool schema was seen earlier, and throw only for protocol-level failures such as unknown tools or timeouts. If your code calls those methods directly, the SDK has already performed the protocol work that core schemas are designed to support at lower layers.
Sources: docs/clients/calling.md
The same rule applies to connection setup and authentication. The connect guide shows Client.connect() running initialization and retaining negotiated server metadata. The OAuth and machine-auth guides show transports accepting an authProvider, discovering authorization servers, refreshing or retrying after 401, and protecting issuer-sensitive credentials. If you rely on OAuthClientProvider, ClientCredentialsProvider, PrivateKeyJwtProvider, or CrossAppAccessProvider, the SDK owns the request sequence. Core schemas become relevant when you store, replay, inspect, or validate those discovery, token, or metadata documents outside that managed sequence.
Sources: docs/clients/connect.md, docs/clients/oauth.md, docs/clients/machine-auth.md
System-to-Code Mapping
The client documentation provides a useful map from public API behavior to the raw payload families exposed by @modelcontextprotocol/core. connect() corresponds to initialization messages and server metadata. listTools(), listPrompts(), listResources(), and listResourceTemplates() correspond to list result schemas, including pagination fields such as nextCursor. callTool() corresponds to tool-call request and result schemas, including content, structuredContent, and isError. readResource() corresponds to resource contents containing uri, mimeType, text, or base64 blob. These are the same conceptual objects you validate when JSON enters your system without a Client wrapper.
Sources: docs/clients/connect.md, docs/clients/calling.md
Authentication maps to a second family of wire shapes. The user OAuth guide names provider-owned state such as client registrations, tokens, PKCE verifier state, discovery state, redirect URL, client metadata, and issuer-keyed credential storage. The machine-auth guide adds client credentials, bearer tokens, private-key JWT assertions, cross-app access exchanges, expected issuer checks, and refresh-on-unauthorized behavior. Core schemas for OAuth and OpenID payload validation are most valuable where those documents cross a trust boundary: dynamic client registration responses, token endpoint responses, authorization server metadata, protected resource metadata, or identity-provider grant material.
Sources: docs/clients/oauth.md, docs/clients/machine-auth.md
Caching and middleware show two practical insertion points for schema validation. A shared ResponseCacheStore can outlive a single client and may serve many principals, so a gateway should validate protocol results before writing them and partition private entries by authorization context. HTTP middleware sees outbound requests and inbound Response objects, including SDK-generated calls such as initialize and notifications/initialized. If middleware reads response bodies for logging, tracing, policy, or replay, core schemas let it validate the copied JSON while preserving the transport’s normal behavior.
Sources: docs/clients/caching.md, docs/clients/middleware.md
Compact Reference
| Area | Public names from the SDK docs | Core-schema validation use |
|---|---|---|
| Protocol results | CallToolResultSchema, safeParse(), listTools(), callTool(), readResource() | Validate raw tool, list, resource, prompt, and completion payloads before forwarding, caching, or asserting in tests. |
| Connection metadata | Client, StreamableHTTPClientTransport, SSEClientTransport, StdioClientTransport, connect(), getServerVersion(), getServerCapabilities(), getInstructions() | Validate initialize responses and metadata only when you are handling the handshake outside the high-level client. |
| OAuth user flow | OAuthClientProvider, OAuthClientMetadata, OAuthTokens, OAuthDiscoveryState, OAuthClientInformationMixed, UnauthorizedError | Validate discovery, registration, token, and callback-related JSON in custom storage, callback handlers, or nonstandard transports. |
| Machine auth | ClientCredentialsProvider, PrivateKeyJwtProvider, CrossAppAccessProvider, AuthProvider, AuthorizationServerMismatchError | Validate token endpoint and authorization-server metadata in service-account, private-key JWT, and cross-app access integrations. |
| Cache boundaries | ResponseCacheStore, InMemoryResponseCacheStore, cacheMode, cachePartition, cacheHints | Validate stored results before writing shared caches or replaying cached protocol responses across clients. |
| HTTP inspection | createMiddleware, applyMiddlewares, withLogging, withOAuth | Validate copied request or response JSON inside fetch middleware without replacing the transport. |
The typical validation pattern is intentionally small. Import the schema constant for the message you hold, parse the unknown value, and branch on success. safeParse() is preferable at protocol boundaries because malformed upstream data becomes a normal failure object rather than an exception that bypasses your forwarding, diagnostics, or retry policy. Once parsing succeeds, parsed.data is the typed wire value for that schema. If parsing fails, Zod issues identify the offending path, which is useful for producing gateway diagnostics or conformance-test output.
Implementation Guidance
Start by deciding which layer owns the protocol. If the owner is Client, prefer the client methods. Use listTools() to get aggregated tools, callTool() to invoke by name with arguments, readResource() to fetch contents, and the connection accessors to read negotiated metadata. Add application-level narrowing for fields that remain intentionally unknown, such as structuredContent, because the client guide treats structured output as data whose final semantic meaning belongs to the application even when schema validation is available.
Sources: docs/clients/calling.md, docs/clients/connect.md
If the owner is a proxy, gateway, middleware layer, or test harness, validate before committing to side effects. For example, validate an upstream tool-call result before storing it in a shared response cache, because the caching guide shows one store may back many clients and can be partitioned by user. Validate OAuth metadata before saving issuer-keyed client credentials, because the OAuth guide emphasizes that credentials registered with one authorization server must not be reused with another. Validate token responses before retrying a request after 401, because machine-auth providers may automatically refresh and retry once.
Sources: docs/clients/caching.md, docs/clients/oauth.md, docs/clients/machine-auth.md
Be careful when schema validation is added to fetch middleware. The middleware guide defines middleware as a wrapper around the transport’s fetch, and the examples include SDK-generated traffic that application code did not explicitly send. Reading a Response body directly can consume it; production middleware should clone responses or otherwise preserve the body for the transport. Core schemas are useful there, but they should remain observational unless the middleware is explicitly responsible for policy enforcement. For normal tracing, use withLogging; for validation gates, fail early and include the Zod issue path in the diagnostic.
Sources: docs/clients/middleware.md
Next Steps
Install @modelcontextprotocol/core only in packages that validate raw wire JSON. Keep ordinary clients on @modelcontextprotocol/client, and let transports, auth providers, response caching, and call helpers manage the protocol. If you are writing a gateway or conformance tool, make a short inventory of every raw payload you accept, choose the matching *Schema export, and add safeParse() checks before forwarding, caching, or asserting. Then read the client calling, OAuth, machine-auth, caching, and middleware pages to place validation at the safest boundary.