Mirror of https://github.com/modelcontextprotocol/go-sdk — The official Go SDK for Model Context Protocol servers and clients. Maintained in collaboration with Google.
  • Go 99.7%
  • Shell 0.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
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
.devcontainer feat(devcontainer): Adds Dev Container configuration (#154) 2025-07-30 12:54:41 -04:00
.github .github: fix quoting in docs check error message (#568) 2025-10-10 12:03:22 -04:00
auth oauthex: move internal/oauthex to oauthex (#559) 2025-10-07 08:39:49 -04:00
design mcp: introduce Requests (#267) 2025-08-12 17:49:50 -04:00
docs all: more minor cleanup (#547) 2025-09-30 16:07:07 -04:00
examples docs: improve documentation clarity and client integration steps (#567) 2025-10-13 11:47:58 -04:00
internal oauthex: update fake oauth server (#564) 2025-10-09 10:38:54 -04:00
jsonrpc many: minor cosmetic changes (#529) 2025-09-25 16:06:24 -04:00
mcp mcp: allow disabling stream replay; disable by default (#585) 2025-10-16 12:11:49 -04:00
oauthex Add Check PCKE Support (#563) 2025-10-14 11:09:28 -04:00
.gitignore .gitignore: add 2025-08-11 08:33:50 -04:00
CONTRIBUTING.md Update readme generation instructions 2025-10-06 10:57:13 -04:00
copyright_test.go all: add a test that checks for missing or mismatching file copyright 2025-09-11 13:53:22 -04:00
go.mod mcp: add client-side OAuth flow (#544) 2025-09-30 16:16:30 -04:00
go.sum mcp: add client-side OAuth flow (#544) 2025-09-30 16:16:30 -04:00
LICENSE Initial commit: add LICENSE 2025-06-23 17:17:37 +00:00
README.md Update readme generation instructions 2025-10-06 10:57:13 -04:00

MCP Go SDK

Open in GitHub Codespaces

PkgGoDev

This repository contains an implementation of the official Go software development kit (SDK) for the Model Context Protocol (MCP).

Package / Feature documentation

The SDK consists of several importable packages:

The SDK endeavors to implement the full MCP spec. The docs/ directory contains feature documentation, mapping the MCP spec to the packages above.

Getting started

To get started creating an MCP server, create an mcp.Server instance, add features to it, and then run it over an mcp.Transport. For example, this server adds a single simple tool, and then connects it to clients over stdin/stdout:

package main

import (
	"context"
	"log"

	"github.com/modelcontextprotocol/go-sdk/mcp"
)

type Input struct {
	Name string `json:"name" jsonschema:"the name of the person to greet"`
}

type Output struct {
	Greeting string `json:"greeting" jsonschema:"the greeting to tell to the user"`
}

func SayHi(ctx context.Context, req *mcp.CallToolRequest, input Input) (
	*mcp.CallToolResult,
	Output,
	error,
) {
	return nil, Output{Greeting: "Hi " + input.Name}, nil
}

func main() {
	// Create a server with a single tool.
	server := mcp.NewServer(&mcp.Implementation{Name: "greeter", Version: "v1.0.0"}, nil)
	mcp.AddTool(server, &mcp.Tool{Name: "greet", Description: "say hi"}, SayHi)
	// Run the server over stdin/stdout, until the client disconnects.
	if err := server.Run(context.Background(), &mcp.StdioTransport{}); err != nil {
		log.Fatal(err)
	}
}

To communicate with that server, create an mcp.Client and connect it to the corresponding server, by running the server command and communicating over its stdin/stdout:

package main

import (
	"context"
	"log"
	"os/exec"

	"github.com/modelcontextprotocol/go-sdk/mcp"
)

func main() {
	ctx := context.Background()

	// Create a new client, with no features.
	client := mcp.NewClient(&mcp.Implementation{Name: "mcp-client", Version: "v1.0.0"}, nil)

	// Connect to a server over stdin/stdout.
	transport := &mcp.CommandTransport{Command: exec.Command("myserver")}
	session, err := client.Connect(ctx, transport, nil)
	if err != nil {
		log.Fatal(err)
	}
	defer session.Close()

	// Call a tool on the server.
	params := &mcp.CallToolParams{
		Name:      "greet",
		Arguments: map[string]any{"name": "you"},
	}
	res, err := session.CallTool(ctx, params)
	if err != nil {
		log.Fatalf("CallTool failed: %v", err)
	}
	if res.IsError {
		log.Fatal("tool failed")
	}
	for _, c := range res.Content {
		log.Print(c.(*mcp.TextContent).Text)
	}
}

The examples/ directory contains more example clients and servers.

Contributing

We welcome contributions to the SDK! Please see CONTRIBUTING.md for details of how to contribute.

Acknowledgements / Alternatives

Several third party Go MCP SDKs inspired the development and design of this official SDK, and continue to be viable alternatives, notably mcp-go, originally authored by Ed Zynda. We are grateful to Ed as well as the other contributors to mcp-go, and to authors and contributors of other SDKs such as mcp-golang and go-mcp. Thanks to their work, there is a thriving ecosystem of Go MCP clients and servers.

License

This project is licensed under the MIT License - see the LICENSE file for details.