Commit graph go-sdk/mcp
Author SHA1 Message Date
Robert Findley
272e0cd4f5
mcp: better handling for streamable context cancellation (#677)
After walking through our handling of streamable client context
cancellation (due to encountering a shutdown deadlock), I think I've
settled on a more coherent strategy for handling call cancellation:

- In our call handler, retire the request if the call exits due to
cancellation: the caller will never see the actual result anyway.
- In connectSSE, use the actual request context (the same context used
in Write) for the client request, so that it terminates when the context
is cancelled. Thread through the initialization context for the
standalone SSE request.

Also, a couple minor improvements:
- Use a detached context for the background context of the client
connection. We want to preserve context values (see #513), but it is not
right to cancel the connection after Connect has already returned, if
the context times out.
- Don't use Last-Event-ID != "" as the signal for whether the connectSSE
call is initial: if the standalone SSE stream disconnects without an
event ID, we'll still reconnect it, and don't want to do so without a
delay.

+ tests, updating the streamable client connection test harness to
accomodate the new aspects being exercised.

Fixes #662
2025-12-03 12:26:50 -05:00
Markus Kusano
5928940d5f
mcp/mcp_test: tests for elicit content validation (#676)
This adds a simple schema and checks that the content returned by an
elicitation handler is validated against the schema. Previously, we had
no test coverage checking if the content was validated (i.e., we would
see no test failures if we removed content validation against the
schema).

The bulk of the actual validation logic is handled by the jsonschema
library so adding comprehensive tests covering different schema-features
is redundant, we simply need to see that some validation is happening.

See https://github.com/modelcontextprotocol/go-sdk/issues/625 for more
details on the motivation of this change.

Fixes #625

---------

Co-authored-by: Markus Kusano <kusano@google.com>
2025-12-03 10:12:07 -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
isfzhang
1bec3c60a0
fix: handle Windows CRLF in MCP client(#664) (#665)
This change updates the MCP client stdio JSON decoder to correctly
handle
both Unix (`\n`) and Windows (`\r\n`) line endings. 

Fixes #664

Co-authored-by: qysz <i_zf@qq.com>
2025-12-01 12:16:39 -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
Markus Kusano
d9263f7e47
mcp: support elicitation defaults (#644)
Fixes #617

---------

Co-authored-by: Markus Kusano <kusano@google.com>
2025-11-21 16:15:21 -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
Raphael MANSUY
9ef2b2742e
Fix: Skip non-message SSE events in processStream (#637)
Fixes #636

## Problem
The StreamableClientTransport tries to JSON-decode ALL SSE events,
including ping events sent by servers for keep-alive purposes. This
causes errors like 'invalid character 'p' looking for beginning of
value' when encountering non-JSON event data.

## Solution
Modified processStream to check evt.Name and skip events that are not
'message' events (or unnamed events, which default to 'message' per SSE
spec).

## Changes
- Added event name check in processStream before attempting JSON decode
- Added test case for ping event filtering
- Added test for scanning multiple events including ping events

## Testing
- All existing tests pass
- New tests verify ping events are properly filtered
- Tested with DeepWiki MCP server which sends ping events
2025-11-13 20:48:23 -05:00
Suraj Bobade
faddd764aa
Implement SEP-973 (#570)
mcp/protocol: Implement SEP-973

- Define Icon structure, which includes source, mimeType and sizes.
- sizes is any array of strings. refer
https://github.com/modelcontextprotocol/modelcontextprotocol/pull/1531
- Support setting websiteUrl, icons for mcp.Implementation
- Support setting icons for mcp.Prompt
- Support setting icons for mcp.Tool
- Support setting icons for mcp.Resource

Fixes #552
2025-11-12 16:52:44 -05:00
Xie Zhihao
d297272705
mcp: relax SSE connection response handling in non-strict mode (#611)
Some MCP servers do not support SSE, but when receiving a request, they
return 400 Bad Request or 404 Not Found instead of the standard 405
Method Not Allowed. The TypeScript and Python SDK ignore this error,
while the Go SDK terminates the session. This patch addresses the issue
in the non-strict mode.

Fixes #610

---------

Signed-off-by: Xie Zhihao <zhihao.xie@bytedance.com>
2025-11-03 10:12:28 -05:00
Robert Findley
d256a9c109
mcp: don't persist failed streamable sessions (#605)
If a stateful streamable session fails to initialize, it is unusable.
Avoid allocating resources by closing the session immediately.

Also:
- Fix a bug where InitializeParams is not guarded with its mutex.
- Fix a resource leak where sessions are persisted with session id "",
even though they are unaddressable.
- Add a relevant benchmark, and update tests.

Fixes #578
2025-10-27 16:29:16 -04:00
Robert Findley
ae6bda692b
mcp: establish the streamable client standalone SSE stream in Connect (#604)
When Connect returns, client should be guaranteed that the streamable
SSE stream is connected.

Fixes #583
2025-10-27 14:03:22 -04:00
Robert Findley
f01e7faaf5
mcp: add StreamableHTTPOptions.SessionTimeout (#594)
Add a timeout option for the streamable HTTP handler that automatically
cleans up idle sessions.

Also, fix a bug in the streamable client, where we hang on a request
even though the client can never get a response (because the HTTP
request terminated without a response or Last-Event-Id).

Fixes #499
2025-10-23 09:17:20 -04:00
Robert Findley
cfa7a515a9
mcp: add StreamableHTTPOptions.EventStore (#593)
Allow users to enable streamable replay by setting a non-nil event
store.

Updates #587
2025-10-20 14:58:24 -04:00
Robert Findley
8aee8d39bd
mcp: clean up stream metadata after completion (#592)
Address longstanding TODOs to clean up stream metadata after streams are
complete:

- Interpret a missing stream as a complete stream.
- Remove the request->stream mapping when the request completes. Any
writes after that point will fail as there can be no recipient.

Tested using examples/client/loadtest, and updating
TestStreamableTransports to check in-band and out-of-band behavior.
2025-10-20 14:57:56 -04:00
Robert Findley
8fe64fc389
mcp: fix stale comment on StreamableServerTransport.EventStore (#588)
This was missed in #585.

Updates #580
2025-10-16 13:48:39 -04:00
Robert Findley
104d39c609
mcp: allow disabling stream replay; disable by default (#585)
This CL implements two changes that must be logically connected.

The first is to provide a mechanism for disabling stream replay.
Previously, our documentation stated that if
StreamableServerTransport.EventStore was nil, a default in-memory event
store would be used. In that case, there would be no way to completely
disable stream replay, and as described in #576, there are many cases
where replay is undesirable.

But of course changing the behavior of the transport zero value
implicitly affects its default behavior, and so this CL also implements
the proposal #580: stream replay is disabled by default.

Implementing this change required a significant refactoring, as
previously we were relying on the event store for serialized message
delivery from the JSON-RPC layer to the MCP layer: the connection would
write to the event store, and independently the stream (be it an
incoming POST or replay GET) would iterate and serve messages in the
stream.

In order to achieve the goals of this CL, it was necessary to decouple
storage from delivery. The 'stream' abstraction now tracks a delivery
callback that writes straight to the HTTP response. It would have been
convenient to store the ongoing http.ResponseWriter directly in the
stream (this is how typescript does it), but due to the design of our
EventStore API, only the HTTP handler knows the next event index, so a
'deliver' abstraction was an unfortunate requirement (suggestions for
how to further simplify this are welcome).

More simplification is possible: in particular, as a result of this
refactoring it should be entirely possible to clean up streams once
we've received all responses. Any replay would only need access to the
EventStore, if at all. This is left to a follow-up CL, to limit this
already significant change.

Furthermore, a nice consequence of this refactoring is that, when not
using event storage, servers can get synchronous feedback that message
delivery failed, which should avoid unnecessary work. We can
additionally cancel ongoing requests on early client termination, but
that is also left to a follow-up CL.

Throughout, the terminology 'standalone SSE stream' replaced 'hanging
GET' when referring to the non-replay GET request issued by the client.
This is consistent with other SDKs.

Fixes #576
Updates #580
2025-10-16 12:11:49 -04:00
Friedrich Große
010bdbc64d
mcp: fix goroutine leaks in unit tests (#496)
This PR fixes goroutine leaks in all unit tests.

To find the leaks I integrated https://github.com/uber-go/goleak and I
suggest to keep using it to catch any future regressions.

I used the folowing script to more easily find individual tests which
were leaking goroutines:

```
for t in $(go test -run=Nothing -list=. ./mcp | grep -v ok); do go test ./mcp -run="$t" > /dev/null && echo -n . || echo -e "\nDetected leak: $t"; done
```
2025-10-16 11:13:30 -04:00
Haokun Tang
14e776db6f
mcp: optimize re-marshalling of jsonschema.Schema (#581)
mcp: optimize re-marshalling of jsonschema.Schema

Avoid going through function remarshal when InputSchema/OutputSchema is
of type *jsonschema.Schema.
2025-10-16 09:06:15 -04:00
Robert Findley
9d6e3074f9
mcp: add a explicit test for concurrent streamable sessions (#584)
We seem not to have a test that explicitly exercises concurrent
streamable sessions. Add one.
2025-10-15 14:43:45 -04:00
Robert Findley
e8685b3022
mcp: don't close stdout when shutting down the stdio transport (#562)
We need to close stdin when the stdio transport is shut down, to unblock
its read loop. However, we don't technically need to close stdout.

Fixes #548
2025-10-07 11:08:38 -04:00
Robert Findley
547b5c1426
mcp: fix panics with nil logger; ensure test handlers do not panic (#557)
PR 501 added logging to the streamable server, but didn't pass a non-nil
logger to the streamable transport (an oversight). However, tests still
passed due to net/http's panic recovery.

Update test servers to enforce that handlers do not panic, and fix the
panic by:
1. Passing along the configured logger to the session transport.
2. Using ensureLogger in Connect, since we technically allow
StreamableServerTransports to be constructed by the user.

Fixes #556
2025-10-06 13:34:20 -04:00
Suraj Bobade
1dcbf62661
mcp/server: enable server logging (#501)
mcp/server.go: implement server‑side logging

- Thread a *slog.Logger through server paths to improve debuggability
- Introduce no‑op discard handler + ensureLogger so loggers are never
nil
- Use ensured loggers in Server
- address todo comments related to adding logging support

All tests are passing and no functionality should change with this PR

Fixes https://github.com/modelcontextprotocol/go-sdk/issues/170
2025-10-02 14:44:32 -04:00
Konstantin Alikhanov
49047aebe8
Add IOTransport for separate reader/writer (#376)
This commit adds ability to create a mcp.Transport with specific
io.ReadCloser and io.WriteCloser.
Ii is needed when you need create an mcp.Client for mcp.Server launched
in separate process and you need to communicate with it with it's own
stdin/stdout.
2025-09-30 16:24:07 -04:00
Robert Findley
1c3f38f777
all: more minor cleanup (#547)
Fix broken / missing links.
2025-09-30 16:07:07 -04:00
Robert Findley
6dbf6c6450
all: minor cleanup (#545)
Also fix a flaky test case in TestStreamableServerTransport.
2025-09-30 15:53:00 -04:00
Chuck Ha
b835e07c26
mcp: fix inconsistent logging new lines (#541)
This change keeps the logging consistent with a new line after each log
whether an error or not.

Fixes #540

Co-authored-by: Chuck Ha <cha@nvidia.com>
2025-09-29 14:19:05 -04:00
Robert Findley
ab092510d2
mcp: fix inaccurate package doc (#534) 2025-09-26 14:16:10 -04: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
Robert Findley
964574b818
mcp: allow any value for schemas (#517)
As discussed at length in
https://github.com/modelcontextprotocol/go-sdk/issues/518, coupling our
schema fields to
jsonschema.Schema limits our user's ability to use a different schema
package, and makes it impossible for our client to talk to some
backends.

This CL relaxes the type of `*jsonschema.Schema` fields to be of type
`any`, which is a breaking change but is unlikely to affect most server
code. (It *is* a nontrivial change for clients).

Fixes https://github.com/modelcontextprotocol/go-sdk/issues/518
2025-09-26 11:55:54 -04:00
Jonathan Amsterdam
5f05f8a43a
many: minor cosmetic changes (#529) 2025-09-25 16:06:24 -04:00
Robert Findley
07f6c490c6
mcp: make the streamable client transport less strict (#524)
In practice, the streamable client transport was having trouble
connecting to various backends, because they are nonconformant in
various ways.

While it would be nice if all servers conformed to the spec, in practice
there are certain spec violations that are recoverable, and we can and
should recover them. Specifically:

- tolerate 404 instead of 405 for the hanging GET (#393)
- tolerate (=ignore) spurious response body for notifications and
responses, since we know none are expected

Additionally, fix a bug that we weren't parsing Content-Type correctly.

Fixes #521
2025-09-24 14:07:27 -04:00
Manuel Ibar
5d64d61974
mcp: fix context propagation in StreamableClientTransport (#514)
## Problem
Context propagation was broken in `StreamableClientTransport` because:
1. `Connect()` used `context.Background()` instead of the parent context
2. `Close()` created a race condition where DELETE requests were
cancelled before completion

## Solution  
- Use parent context when creating the connection context in `Connect()`
- Reorder `Close()` operations to perform cleanup DELETE before
cancelling context

## Impact
- Request-scoped values (auth tokens, trace IDs) now propagate correctly
to background HTTP operations
- Eliminates race condition in cleanup operations  
- Maintains proper Go context semantics

Fixes #513
2025-09-23 12:27:39 -04:00
Jonathan Amsterdam
33ff851ef3
mcp: update to jsonschema that does not validate structs (#511)
Update to the latest jsonschema commit, which removes the ability to
validate structs and changes the type of ForOptions.TypeSchemas.
2025-09-22 15:28:04 -04:00
Suraj Bobade
8c42b69817
SSE: Add support for SSE handler options (#508)
mcp/sse: add support to provide for options for SSE transport

- Add SSEOptions struct to define SSE handler options.
- Update Signature of NewSSEHandler to accept SSEOptions [braking
change]
- Update unit test
- Update example test

Fixes https://github.com/modelcontextprotocol/go-sdk/issues/507,
https://github.com/modelcontextprotocol/go-sdk/issues/503
2025-09-19 13:01:57 -04:00
Jonathan Amsterdam
4e9a387d04
doc: document logging (#497)
For #442.
2025-09-19 11:58:58 -04:00
Jonathan Amsterdam
4fa725857c
docs: document resources (#505) 2025-09-19 11:46:50 -04:00
Robert Findley
5985a7cbba
docs: document tool support (#498)
Document tool support, and tweak the wording for prompts.

For #442
2025-09-19 10:48:59 -04:00
Robert Findley
1696b595c6
mcp: fix several goroutine leaks in tests (#494)
Fix some (but not all) goroutine leaks in tests. Others were nontrivial,
because they relate to streamable http.

For #489.
2025-09-18 14:24:45 -04:00
Jonathan Amsterdam
fed5106631
mcp: add prompt feature doc (#487) 2025-09-18 12:27:02 -04:00
Friedrich Große
02f0b25286
Move GetSessionID closure into ServerOptions (#488)
Fixes: #478.
2025-09-18 12:21:02 -04:00
Robert Findley
353d46ff86
mcp: remove the StreamID type (#490)
The streamID type did not carry its weight. Remove it.

Fixes #484.
2025-09-18 12:01:07 -04:00
Robert Findley
b636b1633b
mcp: fix flaky ExampleLoggingTransport (#483)
Reads are technically racy with writes. Sort for stability.
2025-09-18 08:30:53 -04:00
Jonathan Amsterdam
140b93980c
mcp: add CallToolResult.getError (#481)
Provide a way for middleware to get the error from a tool call,
demonstrating that we can add this functionality without making a
breaking change.

Leave getError unexported for now; we can export it (and setError) at
any time.

For #64.
2025-09-18 08:08:23 -04:00
Robert Findley
b615fa49b1
mcp: add a streamable serving benchmark
Add a benchmark using the streamable HTTP handler, and a more realistic input/output signature. Also expose this handler as an example (both a go example and a server in the examples/ directory).
2025-09-17 17:49:31 -04:00
Rob Findley
a3e753b8d8 mcp: correct the JSON used for unstructured content
Recently, I refactored to fix validation and default application for
structured output. However, I used the wrong byte slice for the
unstructured output. Fix it to use the same bytes as structured output,
with a test.

Fixes #475
2025-09-17 17:42:43 -04:00
Rob Findley
bd6ffe3b4c mcp: add an example customizing a nested type schema
Add an example that demonstrates how to customize a nested type schema,
which is a recurring problem for our users (see #467).

Fixes #467
Updates #368
2025-09-16 21:34:27 -04:00
Rob Findley
845c29f6b7 mcp: add a benchmark for the MemoryEventStore; remove validation
Add a new benchmark measuring the append and purge performance of the
MemoryEventStore. This benchmark revealed that the store is orders of
magnitude slower than it should be due to conservative validation
(hugely so: 300KB/s vs 568MB/s). Turn off this validation by default.

For #190
2025-09-16 15:50:31 -04:00
Robert Findley
ac2f175214
docs: add feature and troubleshooting documentation (#463)
Add a framework for feature documentation, and start populating it with
our SDK documentation.

This framework is as follows:
- internal/docs/**.src.md is the markdown source for the docs/
  directory.
- The x/example/internal/cmd/weave tool is used to compile these docs to
  the top-level docs, supporting both linked code samples and generated
  tables of contents.
- The readme-check workflow is updated to check these docs as well.
- The structure of these docs follows the MCP spec.
- Wherever possible, example code is linked from actual Go documentation
  examples, so that it is testable.

Some minor modifications to the weave tool were made to support this
framework.

Additionally, partially fill out this documentation with content on
base protocol and client features, as well as troubleshooting help.

Along the way, a bug was encountered that our LoggingTransport was not
concurrency safe. This is fixed with a mutex.

Fixes https://github.com/modelcontextprotocol/go-sdk/issues/466
Fixes https://github.com/modelcontextprotocol/go-sdk/issues/409
Updates https://github.com/modelcontextprotocol/go-sdk/issues/442
2025-09-16 11:13:40 -04:00