Commit graph go-sdk/mcp/shared.go
Author SHA1 Message Date
Guglielmo Colombo
ec564f9ccb
mcp: cap negotiated protocolVersion in legacy initialize to protocolVersion20251125 (#1051)
Fixes #1033
2026-07-06 15:40:27 +00:00
Guglielmo Colombo
224a240875
mcp: do not exclude Notifications from carrying InitializeParams in Meta (#1049)
Fixes #1043
2026-07-06 17:10:26 +02:00
Guglielmo Colombo
65ece59643
mcp: Allow registration of custom JSON-RPC methods (#956)
## Description

This PR introduces support for custom (non-standard) JSON-RPC methods in
the MCP Go SDK.
This feature enables servers to handle arbitrary JSON-RPC methods and
clients to invoke them, all while maintaining full type safety and
integrating seamlessly with the SDK's existing middleware and session
management.

- Server-Side Registration: Added AddReceivingCustomMethod to allow
servers to register handlers for custom methods. Incoming requests are
automatically unmarshaled into user-defined parameter structs.
- Client-Side Calling: Added AddSendingCustomMethod which returns a
strongly-typed caller function that clients can use to invoke custom
methods and receive strongly-typed results.
- Helper Structs: Provided ParamsBase and ResultBase for users to embed
in their custom structs. This allows them to easily satisfy the SDK's
internal Params and Result interfaces.

Fixes #954
2026-06-25 23:13:17 +02:00
Guglielmo Colombo
7f4aa4a0ce
mcp: add 2026-07-28 to the supported protocol versions (#1020)
This PR adds the protocol version `2026-07-28` to the list of supported
protocol versions and fixes legacy tests hardcoding the legacy protocol
version for those use cases.
2026-06-24 12:02:56 +02:00
Guglielmo Colombo
cd7d80c591
mcp: Implement subscriptions/listen rpc (SEP-2575) (#1007)
Fixes #966
2026-06-22 18:57:36 +02:00
Guglielmo Colombo
3486f6bcaf
mco: update JSON-RPC error codes to align with updated MCP specification (#1016)
This PR updates the error codes to align with the updated specifications
in
https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2907

ErrServerClosing and ErrClientClosing are reverted to their 1.6.0
version codes, as they do not overlap anymore with the newly introduced
error codes.
2026-06-22 10:27:31 +02:00
Guglielmo Colombo
17029489ff
mcp: bump protocol version from 2026-06-30 to 2026-07-28 (#1015)
The new official date for the protocol version has been moved to
'2026-07-28'. Update all the references in the code of the old version.
2026-06-22 09:53:04 +02:00
Guglielmo Colombo
4dc99b48e1
mcp: Remove resumability and introduce MissingRequiredClientCapability error data (#1005)
Fixes #966
2026-06-15 09:47:42 +02:00
Guglielmo Colombo
dd978160ab
mcp: Implement server-side support for discover method (SEP-2575) (#987)
## Summary
Part 3 of the SEP-2575 ("Make MCP Stateless") implementation. Builds on
PR #975 which landed the client-side discover/fallback flow and the
per-request `_meta` plumbing. This PR adds the **server-side**
counterparts:

- `server/discover` handler (replaces the
stub),ProtocolVersionSupporter`
- transport hook for per-transport version filtering,
- transport-agnostic version validation and method-removal enforcement
in `ServerSession.handle`,
- HTTP-level wire compliance for SEP-2575 error codes/status codes,
- bug fix in `internal/jsonrpc2`,`processResult` with an `MCPGODEBUG`
opt-out for backward compatibility.
2026-06-08 17:52:10 +02:00
Guglielmo Colombo
00d3642840
mcp: add support for logging level (SEP-2575) (#997)
## Description

This PR adds the support for logging feature in meta.

Fixes #966
2026-06-08 15:56:38 +02:00
Guglielmo Colombo
d9714c61f1
mcp: Implement retry on advised supportedVersions in UnsupportedProtocolVersion error (#989)
## Description

This PR introduces a retry mechanism for the discover method according
to SEP-2575 (Issue #966)
2026-06-08 15:09:07 +02:00
Guglielmo Colombo
c60a318d22
mcp: Implement support for SEP-2575 on client side (#975)
Implements the client half of the SEP-2575 / `2026-06-30` protocol. This
CL is client-only; server-side `server/discover` is still a
`MethodNotFound` stub.
### Changes
- **`server/discover` probe in `Client.Connect()`** (`client.go`). When
the caller opts into `protocolVersion >= 2026-06-30`, the client probes
the server with `server/discover` before falling back to the legacy
`initialize`
  handshake.
- **Per-request `_meta` injection** (`shared.go`, `injectRequestMeta`).
For`>= 2026-06-30` sessions every outgoing request gets the SEP-2575
triple (`protocolVersion`, `clientInfo`, `clientCapabilities`).
- **Server-side fix**: `ServerSession.handle` no longer pre-populates
`state.InitializeParams` from a `server/discover` request's `_meta`, so
a subsequent fallback `initialize` is not rejected as a duplicate.
### Fallback rules
Client falls back to the legacy `initialize` handshake when discover
returns:
- `MethodNotFound` (-32601),
- `UnsupportedProtocolVersionError` (-32004),
- an HTTP `Bad Request` (substring-matched on the error message, to
interop
  with pre-2026-06-30 servers).

Fixes #966
2026-06-02 14:17:01 +02:00
Tomas Dabašinskas
8805aa85f7
mcp: add configurable keepalive failure threshold (#982)
mcp: add configurable keepalive failure threshold

Introduce `KeepAliveFailureThreshold` option in both `ClientOptions` and
`ServerOptions` to control how many consecutive keepalive ping failures
are tolerated before closing the session.

This aligns with the MCP spec's guidance that "multiple failed pings MAY
trigger a connection reset," allowing operators to tune resilience
against transient network hiccups without immediately tearing down
otherwise healthy sessions.

A threshold of 0 or 1 (the default) closes on the first failure,
preserving existing behavior. Higher values let isolated misses pass
while still closing the session once consecutive failures reach the
threshold. A successful ping resets the counter.

Tolerated failures are logged at WARN level; the final failure that
closes the session is logged at ERROR level.

This is rework of #979.
2026-05-31 10:25:49 +02:00
Guglielmo Colombo
4cbdd6a514
mcp: Implement stateless server (SEP-2275) (#965)
## Description

This PR lays the foundational server-side groundwork for the `>=
2026-06-30` sessionless and stateless feature introduced by
[SEP-2575](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2575)
and SEP-2567, tracked in
[design/stateless.md](614460a225/design/stateless.md).

### SEP-2575: Stateless MCP

*   **Per-request protocol detection in `ServerSession.handle()`**
Unmarshal `_meta` from the raw JSON-RPC params determines whether each
request follows the new protocol.

*   **Per-request typed accessors on `ServerRequest[P]`**
    ```go
    func (r *ServerRequest[P]) ProtocolVersion() string
    func (r *ServerRequest[P]) ClientInfo() *Implementation
    func (r *ServerRequest[P]) ClientCapabilities() *ClientCapabilities
    ```

* **Reject client->server `initialize`, `initialized` and `ping` for
new-protocol requests**

*   **Per-request `_meta` field name constants**
Three constants for the wire-protocol field names
(`MetaKeyProtocolVersion`, `MetaKeyClientInfo`,
`MetaKeyClientCapabilities`)

* **Stop synthesizing fake `InitializeParams` for new-protocol
requests**

Fixes: #966
2026-05-26 14:25:51 +00:00
Yaroslav
2b7c9937e6
mcp: align resource not found error code with sep-2164 (#931)
Change the error code returned by ResourceNotFoundError from -32002 to
-32602 (jsonrpc.CodeInvalidParams), aligning with
[SEP-2164](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2164).

* Not gated with a protocol version check, because the previous error
code was never formally specified and the behaviour varied across SDKs.
* In case clients which rely on the old error code exist, the previous
behaviour can be restored with `MCPGODEBUG=customresnotfounderrcode=1`.
* `CodeResourceNotFound` deprecated since its only purpose going forward
is backward compatibility. The new code should use
`jsonrpc.CodeInvalidParams` directly.
* `CodeResourceNotFound` changed to `var` so it can stay in sync with
`ResourceNotFoundError` and existing code doing `code ==
mcp.CodeResourceNotFound` keeps working in both the default and compat
modes.
2026-05-05 16:20:02 +02:00
Guglielmo Colombo
e01639a318
feat: HTTP Header Standardization for method and name (#907)
## Description

Implements SEP-2243
(https://modelcontextprotocol.io/seps/2243-http-standardization) (HTTP
Header Standardization) for Mcp-Method and Mcp-Name standard headers
(x-mcp-param custom headers will be covvered in separate PR).

Fixes #905
2026-04-29 17:33:39 +02:00
Maciej Kisiel
b37e497f0a
mcp: don't close session when keepalive ping returns method-not-found (#900)
Since ping is optional per the MCP spec, a peer that doesn't implement
it will respond with a -32601 (method not found) error. Previously,
startKeepalive treated all ping errors identically, closing the session
even when the peer was perfectly healthy.

Now, a method-not-found response stops the keepalive goroutine without
closing the session.

Fixes #897
2026-04-22 16:35:27 +02:00
Ravish Gupta
4c00594be6
mcp: log out-of-band errors instead of dropping them (#887)
## Summary

Two error sites in the MCP runtime were previously unobservable:

- **`mcp/shared.go` `startKeepalive`** — when a keepalive ping failed,
the session was closed silently with no indication of why.
- **`mcp/transport.go` `connect`** — `jsonrpc2.OnInternalError` printed
via the package-level `log.Printf`, bypassing the `*slog.Logger`
configured on `ServerOptions`/`ClientOptions`.

Both sites now report through the existing `*slog.Logger` that `Server`
and `Client` already guarantee non-nil via `ensureLogger`. The logger is
threaded into the unexported `startKeepalive` and `connect` helpers as a
parameter — **no new public API surface**.

## Context

Per @jba's [suggestion on
#865](https://github.com/modelcontextprotocol/go-sdk/pull/865#issuecomment-4156166474):

> Maybe we can just use the logger in all the places we currently drop
the error. Then it's still reported, but we don't have to add any API.

This PR is that smaller alternative. It addresses the concrete
observability gap in #218 without expanding `ServerOptions`. PR #865
(the `ErrorHandler` callback proposal) remains open pending community
input on whether a structured callback API is also wanted on top of
logging.

`notifySessions` already logs at `Warn` level on delivery errors and is
intentionally left untouched.

## Test plan

- [x] New regression test `TestKeepAliveFailure_Logged` asserts the
keepalive failure produces a log line on the configured logger.
- [x] Verified the test fails when the new `logger.Error(...)` call is
removed (sanity check that it pins the behavior).
- [x] `go test ./mcp/... -count=1` passes.
- [x] `go vet ./...` clean.
- [x] `go build ./...` clean.

Refs #218

---------

Co-authored-by: Maciej Kisiel <mkisiel@google.com>
2026-04-14 16:53:11 +02:00
Steven Chen
48879f01c9
mcp: fix setProgressToken when Meta is nil (#846)
When `SetProgressToken` is called on a `Params` struct with a nil `Meta`
field, the newly created map is never assigned back to the struct via
`SetMeta`, causing the progress token to be silently lost.

Call `p.SetMeta(m)` after creating the new map so the struct retains the
reference.

Fixes #845

Co-authored-by: Maciej Kisiel <mkisiel@google.com>
2026-03-18 10:57:45 +01:00
Robert Findley
4e1c3a34b5
mcp: update latestProtocolVersion to 2025-11-25 (#724)
Update the SDK to use protocol version 2025-11-25 as the latest
supported version. Fix tests and examples that had hardcoded
expectations for the previous version (2025-06-18).

---------

Co-authored-by: Maciej Kisiel <mkisiel@google.com>
2026-03-03 10:30:11 +01:00
Maciej Kisiel
7b8d81c264
all: use case-sensitive JSON unmarshaling (#807)
As reported in
https://github.com/modelcontextprotocol/go-sdk/issues/805, case
insensitive unmarshaling can pose security issues. This change adjusts
all non-test and non-example unmarshaling to use a case sensitive mode.

This introduces a new external dependency
`github.com/segmentio/encoding`.
2026-02-18 16:38:36 +01:00
Robert Findley
b3399e6730
mcp: use args struct for CloseSSEStream (#718)
Change CloseSSEStream from func(time.Duration) to
func(CloseSSEStreamArgs) for forward compatibility, allowing new fields
to be added without breaking existing callers.
2025-12-11 15:13:38 -05:00
Robert Findley
1a964ae23d
mcp: debounce server change notifications (#717)
Debounce and batch notifications for changes in server feature sets
(adding or removing tools, prompts, resources, or resource templates).

This PR handles server-side change notifications only. We could do the
same for client-side notifications (e.g. roots changed), but at the
moment we don't need to.

Fixes #649.
2025-12-11 15:11:32 -05:00
Robert Findley
a5e369ed12
mcp: fix broken client root capabilities (#698)
To address #607, add ClientCapabilities.RootsV2, and populate it when
constructing sending and receiving InitializeParams.

Fixes #607
2025-12-11 10:16:56 -05:00
Rob Findley
6f6e196c27 mcp: fix stray log.Printf in notifySessions
I encountered these logs, and they were distracting and noisy. We
shouldn't log to stderr unless configured by the user. Thread through
the logger.

Also, use ensureLogger in the streamable client to simplify call sites.

Updates #708
Updates #684
2025-12-10 18:15:54 -05:00
Markus Kusano
dd5a8ff77b mcp: clarify documentation for the streamable transports
After a deep dive with the team, document areas of the codebase
identified as unclear. For now, this is a documentation-only commit (apart
from one switch of jsonrpc2.Request.ID.IsValid->Request.IsCall). Special
TODO(cleanup) comments are added for additional code changes in
follow-up commits.

Also, include high level doc comments for server and client transports,
in new streamable_server.go and streamable_client.go. Eventually, the
server and client transport logic should be migrated to these files, as
streamable.go has gotten too large. However, we can do that at a future
date, to minimize diff.
2025-12-10 10:46:10 -05:00
Robert Findley
623780125c
mcp: support SSE polling and server disconnects (SEP-1699) (#663)
This CL implements support for SEP-1699, adding the following new API:

- Event.Retry corresponds to the 'retry' field of a server sent event.
This is used to signal client retry behavior.
- RequestExtra.CloseStream is set by the streamable transport to allow
closing a stream.

The streamable server transport is updated to set CloseStream for calls,
allowing server operations or middleware to close the underlying stream.
If the configured 'reconnectAfter' delay is set, a 'retry' message is
sent prior to terminating the stream.

The streamable client transport is updated to read the configured delay.

Fixes #630
2025-12-01 16:21:37 -05:00
Robert Findley
2ce44d45e9
all: expose JSON-RPC error codes, and support URLElicitationRequired errors (#655)
Expose the jsonrpc.Error type to allow access to underlying JSON-RPC
error codes. Also, expose common JSON-RPC error codes in the jsonrpc
package, and MCP error codes in the mcp package.

Also, implement support for the MCP URL elicitation required error
(-32042), enabling servers to request out-of-band user authorization and
clients to automatically handle these requests with retry logic.

Server-side:
- Add CodeURLElicitationRequired constant
- Add URLElicitationRequiredError() constructor.

Client-side:
- Add urlElicitationMiddleware to intercept URLElicitationRequired
  errors and retry calls.
- Update callElicitationCompleteHandler to signal waiting operations.
- Fix capability advertisement to support both form and URL modes.

Fixes #452
Fixes #623
2025-12-01 11:29:17 -05:00
Robert Findley
21fb03dd1a
mcp: support url mode elicitation (#646)
Add initial support for URL mode elicitation, by introducing the new
types, as well as both server and client-side validation.

A follow-up CL will add support for ErrURLElicitationRequired.

For #623
2025-11-23 12:58:28 -05:00
Robert Findley
1943780255
mcp: validate tool names (#640)
Implement SEP 986, enforcing restrictions on tool names. Since we're
already at v1 we couldn't turn this into a panic, so use an error log
instead. This is consistent with the typescript SDK. A note is left in
our 'rough edges' doc to panic in v2.

Fixes #621
2025-11-19 17:01:50 -05:00
Robert Findley
b2048cd73a
mcp: unexport incidentally exported error codes (#536)
Unexport error codes that were accidentally exported. I don't think it's
possible that they could be useful for users (see #535).

Fixes #535
2025-09-26 14:04:28 -04:00
Jonathan Amsterdam
5f05f8a43a
many: minor cosmetic changes (#529) 2025-09-25 16:06:24 -04:00
Rob Findley
5bbca40032 mcp: fix typo in protocolVersion20241105
This version was so last year.

Fixes #432
2025-09-09 11:21:18 -04:00
Rob Findley
5ccd97fafc mcp: allow requests before notifications/initialized
Upon a closer reading of the spec, it is OK for the server to response
to client requests before it has received notifications/initialized (as
long as it has received initialize). This effectively rolls back the fix
from #225.

Some hooks are left for enforcing strictness around server->client
requests prior to initialized. These will be revisited in subsequent
CLs.

For #395
2025-09-05 12:04:58 -04:00
Jonathan Amsterdam
4587941994
mcp: add Request.GetExtra (#350) 2025-08-22 11:04:01 -04:00
Rob Findley
79f063bc98 mcp: handle the Mcp-Protocol-Version header correctly
Handle the protocol version header according to section 2.7 of the spec
(and the other SDKs).

Fixes #198
2025-08-20 16:48:08 -04:00
Jonathan Amsterdam
73b8a7f134
mcp: make request headers available to tools (#333)
Add HTTP request headers to RequestExtra, so tools and other
user-defined handlers can access them.

Fixes #331.
2025-08-20 14:58:44 -04:00
Robert Findley
62d815922f
mcp: minor cleanup of some TODOs (#332)
Do a pass through TODOs to delete or address minor TODOs.
2025-08-20 12:55:19 -04:00
Shusaku Yasoda
719f68d0bf
improve error handling for tools and server methods (#311)
- Fix tool error handling to properly distinguish between protocol
errors and tool execution errors
- Return structured JSON-RPC errors directly for protocol-level issues
- Embed regular tool errors in CallToolResult as per MCP specification
- Improve server error responses for unknown prompts and tools
- Add comprehensive tests for both structured and regular error handling
2025-08-20 12:31:11 -04:00
Jonathan Amsterdam
8e6ab130d8
mcp: pass TokenInfo to server handler (#292)
If there is a TokenInfo in the request context of a
StreamableServerTransport, then propagate it through to the
ServerRequest that is passed to server methods like callTool.

Fixes #317.
2025-08-20 10:50:16 -04:00
Rob Findley
3db848abec mcp: implement a concurrency model for calls
Implement the concurrency model described in #26: notifications are
synchronous, but calls are asynchronous (except for 'initialize'). To
achieve this, implement jsonrpc2.Async(ctx) to signal asynchronous
handling. This is simpler to use than returning ErrAsyncResponse and
calling Respond, and since this is an internal detail we don't need to
worry too much about whether it's idiomatic.

Add tests that verify both features, for both client and server.

Also:
- replace req.ID.IsValid with req.IsCall
- remove the methodHandler type as we can just use MethodHandler

Fixes #26
2025-08-19 11:21:02 -04:00
Jonathan Amsterdam
6e03217c83
mcp: introduce Requests (#267)
Handlers and client/server methods take a single request argument
combining the session and params. This slightly simplifies the signature
for handlers, since there is no longer an often-ignored session
argument.

But more importantly, it opens the door to adding more information in
requests, such as auth info and HTTP request headers.

For #243.
2025-08-12 17:49:50 -04:00
Robert Findley
4e413da771
mcp: rename mcp{Params,Result} to is{Params,Result} (#270)
For some reason, when making these marker methods, the standard naming
convention escaped me.
2025-08-09 11:06:59 -04:00
Rob Findley
0375535db4 mcp: implement support for JSON responses in the MCP streamable server
Add a new (currently unexported) jsonResponse option to
StreamableServerTransportOptions, and use it to control the response
content type, serving application/json if set.

Additionally:
- A transportOptions field is added to the StreamableHTTPOptions.
- A messages iterator is added to encapsulate the iteration of stream
  messages, since the handling of JSON and SSE responses are otherwise
  very different.
- The serving flow is refactored to avoid returning (statusCode,
  message), primarily because this seemed liable to lead to redundant
  calls to WriteHeader, because only local logic knows whether or not
  any data has been written to the response.
- The serving flow is refactored to delegate to responseJSON and
  responseSSE, according to the currently unexported jsonResponse
  option.
- A bug is fixed where all GET streams were considered persistent: the
  terminal condition req.Method == http.MethodPost && nOutstanding == 0
  was not right: GET requests may implement stream resumption.

Updates #211
2025-08-08 12:38:43 -04:00
Rob Findley
8186bf39c7 mcp: lock down Params and Result
Add unexported methods to the Params and Result interface, so that
they're harder to implement outside the mcp package.

It looks like these are the only two interfaces we need to lock down:
others are either intentionally open (Transport, Connection), or already
closed (Session).

Fixes #263
2025-08-07 15:59:31 -04:00
cryo
0cde9623d3
mcp: fix comments (#221)
### change:
Fix typos in some comments.
2025-08-01 16:20:55 -04:00
Robert Findley
b34ba2149d
mcp: handle bad or missing params (#210)
Audit all cases where params must not be null, and enforce this using
methodInfo via a new methodFlags bitfield that parameterizes method
requirements. Write extensive conformance tests catching all the
(server-side) crashes that were possible.

We should go further and validate schema against the spec, but that is
more indirect, more complicated, and potentially slower. For now we
adopt this more explicit approach.

Still TODO in a subsequent CL: verify the client side of this with
client conformance tests.

Additionally, improve some error messages that were redundant or leaked
internal implementation details.

Fixes #195
2025-07-31 10:57:59 -04:00
Robert Findley
56734edf46
mcp: reject notifications with unexpected ID field (#204)
Use the new 'isRequest' field on methodInfo to also reject notifications
with an unexpected ID field.

For #196
2025-07-30 15:19:51 -04:00
Robert Findley
64493be392
mcp: reject requests with bad IDs (#202)
Add an isRequest field to methodInfo, used it to reject non-notification
requests that lack a valid ID. Furthermore, lift this validation to the
transport layer for HTTP server transports, so that we can preemptively
reject bad HTTP requests.

Fixes #194
Fixes #197
2025-07-30 12:26:40 -04:00
Koichi Shiraishi
619bc41581
internal/jsonrpc2,mcp: fix typos (#183)
- add links to doc strings
- use correct symbol and package names
2025-07-28 12:18:03 -04:00