Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
<!-- Autogenerated by weave; DO NOT EDIT -->
# MCP Go SDK

***BREAKING CHANGES***

The latest version contains breaking changes:

- Server.AddTools is replaced by Server.AddTool.

- NewServerTool is replaced by AddTool. AddTool takes a Tool rather than a name and description, so you can
set any field on the Tool that you want before associating it with a handler.

- ToolOptions are gone. If you don't want AddTool to infer a JSON Schema for you, you can construct one
as a struct literal.

- AddPrompts, AddResources and AddResourceTemplates are similarly replaced by singular methods which pair the
feature with a handler. The ServerXXX types have been removed.

[![PkgGoDev](https://pkg.go.dev/badge/github.com/modelcontextprotocol/go-sdk)](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk)

This repository contains an unreleased implementation of the official Go
Expand Down Expand Up @@ -99,7 +114,7 @@ import (
)

type HiParams struct {
Name string `json:"name"`
Name string `json:"name", mcp:"the name of the person to greet"`
}

func SayHi(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[HiParams]) (*mcp.CallToolResultFor[any], error) {
Expand All @@ -111,11 +126,8 @@ func SayHi(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParam
func main() {
// Create a server with a single tool.
server := mcp.NewServer("greeter", "v1.0.0", nil)
server.AddTools(
mcp.NewServerTool("greet", "say hi", SayHi, mcp.Input(
mcp.Property("name", mcp.Description("the name of the person to greet")),
)),
)

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.NewStdioTransport()); err != nil {
log.Fatal(err)
Expand Down
24 changes: 8 additions & 16 deletions examples/hello/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
var httpAddr = flag.String("http", "", "if set, use streamable HTTP at this address, instead of stdin/stdout")

type HiArgs struct {
Name string `json:"name"`
Name string `json:"name" mcp:"the name to say hi to"`
}

func SayHi(ctx context.Context, ss *mcp.ServerSession, params *mcp.CallToolParamsFor[HiArgs]) (*mcp.CallToolResultFor[struct{}], error) {
Expand All @@ -43,21 +43,13 @@ func main() {
flag.Parse()

server := mcp.NewServer("greeter", "v0.0.1", nil)
server.AddTools(mcp.NewServerTool("greet", "say hi", SayHi, mcp.Input(
mcp.Property("name", mcp.Description("the name to say hi to")),
)))
server.AddPrompts(&mcp.ServerPrompt{
Prompt: &mcp.Prompt{Name: "greet"},
Handler: PromptHi,
})
server.AddResources(&mcp.ServerResource{
Resource: &mcp.Resource{
Name: "info",
MIMEType: "text/plain",
URI: "embedded:info",
},
Handler: handleEmbeddedResource,
})
mcp.AddTool(server, &mcp.Tool{Name: "greet", Description: "say hi"}, SayHi)
server.AddPrompt(&mcp.Prompt{Name: "greet"}, PromptHi)
server.AddResource(&mcp.Resource{
Name: "info",
MIMEType: "text/plain",
URI: "embedded:info",
}, handleEmbeddedResource)

if *httpAddr != "" {
handler := mcp.NewStreamableHTTPHandler(func(*http.Request) *mcp.Server {
Expand Down
6 changes: 3 additions & 3 deletions examples/sse/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ func main() {
}

server1 := mcp.NewServer("greeter1", "v0.0.1", nil)
server1.AddTools(mcp.NewServerTool("greet1", "say hi", SayHi))
mcp.AddTool(server1, &mcp.Tool{Name: "greet1", Description: "say hi"}, SayHi)

server2 := mcp.NewServer("greeter2", "v0.0.1", nil)
server2.AddTools(mcp.NewServerTool("greet2", "say hello", SayHi))
mcp.AddTool(server2, &mcp.Tool{Name: "greet2", Description: "say hello"}, SayHi)

log.Printf("MCP servers serving at %s\n", *httpAddr)
log.Printf("MCP servers serving at %s", *httpAddr)
handler := mcp.NewSSEHandler(func(request *http.Request) *mcp.Server {
url := request.URL.Path
log.Printf("Handling request for URL %s\n", url)
Expand Down
15 changes: 15 additions & 0 deletions internal/readme/README.src.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# MCP Go SDK

***BREAKING CHANGES***

The latest version contains breaking changes:

- Server.AddTools is replaced by Server.AddTool.

- NewServerTool is replaced by AddTool. AddTool takes a Tool rather than a name and description, so you can
set any field on the Tool that you want before associating it with a handler.

- ToolOptions are gone. If you don't want AddTool to infer a JSON Schema for you, you can construct one
as a struct literal.

- AddPrompts, AddResources and AddResourceTemplates are similarly replaced by singular methods which pair the
feature with a handler. The ServerXXX types have been removed.

[![PkgGoDev](https://pkg.go.dev/badge/github.com/modelcontextprotocol/go-sdk)](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk)

This repository contains an unreleased implementation of the official Go
Expand Down
9 changes: 3 additions & 6 deletions internal/readme/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
)

type HiParams struct {
Name string `json:"name"`
Name string `json:"name", mcp:"the name of the person to greet"`
}

func SayHi(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[HiParams]) (*mcp.CallToolResultFor[any], error) {
Expand All @@ -25,11 +25,8 @@ func SayHi(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParam
func main() {
// Create a server with a single tool.
server := mcp.NewServer("greeter", "v1.0.0", nil)
server.AddTools(
mcp.NewServerTool("greet", "say hi", SayHi, mcp.Input(
mcp.Property("name", mcp.Description("the name of the person to greet")),
)),
)

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.NewStdioTransport()); err != nil {
log.Fatal(err)
Expand Down
58 changes: 24 additions & 34 deletions mcp/client_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ func TestList(t *testing.T) {
defer serverSession.Close()

t.Run("tools", func(t *testing.T) {
toolA := mcp.NewServerTool("apple", "apple tool", SayHi)
toolB := mcp.NewServerTool("banana", "banana tool", SayHi)
toolC := mcp.NewServerTool("cherry", "cherry tool", SayHi)
tools := []*mcp.ServerTool{toolA, toolB, toolC}
wantTools := []*mcp.Tool{toolA.Tool, toolB.Tool, toolC.Tool}
server.AddTools(tools...)
var wantTools []*mcp.Tool
for _, name := range []string{"apple", "banana", "cherry"} {
t := &mcp.Tool{Name: name, Description: name + " tool"}
wantTools = append(wantTools, t)
mcp.AddTool(server, t, SayHi)
}
t.Run("list", func(t *testing.T) {
res, err := clientSession.ListTools(ctx, nil)
if err != nil {
Expand All @@ -43,12 +43,13 @@ func TestList(t *testing.T) {
})

t.Run("resources", func(t *testing.T) {
resourceA := &mcp.ServerResource{Resource: &mcp.Resource{URI: "http://apple"}}
resourceB := &mcp.ServerResource{Resource: &mcp.Resource{URI: "http://banana"}}
resourceC := &mcp.ServerResource{Resource: &mcp.Resource{URI: "http://cherry"}}
wantResources := []*mcp.Resource{resourceA.Resource, resourceB.Resource, resourceC.Resource}
resources := []*mcp.ServerResource{resourceA, resourceB, resourceC}
server.AddResources(resources...)
var wantResources []*mcp.Resource
for _, name := range []string{"apple", "banana", "cherry"} {
r := &mcp.Resource{URI: "http://" + name}
wantResources = append(wantResources, r)
server.AddResource(r, nil)
}

t.Run("list", func(t *testing.T) {
res, err := clientSession.ListResources(ctx, nil)
if err != nil {
Expand All @@ -64,15 +65,12 @@ func TestList(t *testing.T) {
})

t.Run("templates", func(t *testing.T) {
resourceTmplA := &mcp.ServerResourceTemplate{ResourceTemplate: &mcp.ResourceTemplate{URITemplate: "http://apple/{x}"}}
resourceTmplB := &mcp.ServerResourceTemplate{ResourceTemplate: &mcp.ResourceTemplate{URITemplate: "http://banana/{x}"}}
resourceTmplC := &mcp.ServerResourceTemplate{ResourceTemplate: &mcp.ResourceTemplate{URITemplate: "http://cherry/{x}"}}
wantResourceTemplates := []*mcp.ResourceTemplate{
resourceTmplA.ResourceTemplate, resourceTmplB.ResourceTemplate,
resourceTmplC.ResourceTemplate,
var wantResourceTemplates []*mcp.ResourceTemplate
for _, name := range []string{"apple", "banana", "cherry"} {
rt := &mcp.ResourceTemplate{URITemplate: "http://" + name + "/{x}"}
wantResourceTemplates = append(wantResourceTemplates, rt)
server.AddResourceTemplate(rt, nil)
}
resourceTemplates := []*mcp.ServerResourceTemplate{resourceTmplA, resourceTmplB, resourceTmplC}
server.AddResourceTemplates(resourceTemplates...)
t.Run("list", func(t *testing.T) {
res, err := clientSession.ListResourceTemplates(ctx, nil)
if err != nil {
Expand All @@ -88,12 +86,12 @@ func TestList(t *testing.T) {
})

t.Run("prompts", func(t *testing.T) {
promptA := newServerPrompt("apple", "apple prompt")
promptB := newServerPrompt("banana", "banana prompt")
promptC := newServerPrompt("cherry", "cherry prompt")
wantPrompts := []*mcp.Prompt{promptA.Prompt, promptB.Prompt, promptC.Prompt}
prompts := []*mcp.ServerPrompt{promptA, promptB, promptC}
server.AddPrompts(prompts...)
var wantPrompts []*mcp.Prompt
for _, name := range []string{"apple", "banana", "cherry"} {
p := &mcp.Prompt{Name: name, Description: name + " prompt"}
wantPrompts = append(wantPrompts, p)
server.AddPrompt(p, testPromptHandler)
}
t.Run("list", func(t *testing.T) {
res, err := clientSession.ListPrompts(ctx, nil)
if err != nil {
Expand Down Expand Up @@ -123,14 +121,6 @@ func testIterator[T any](ctx context.Context, t *testing.T, seq iter.Seq2[*T, er
}
}

// testPromptHandler is used for type inference newServerPrompt.
func testPromptHandler(context.Context, *mcp.ServerSession, *mcp.GetPromptParams) (*mcp.GetPromptResult, error) {
panic("not implemented")
}

func newServerPrompt(name, desc string) *mcp.ServerPrompt {
return &mcp.ServerPrompt{
Prompt: &mcp.Prompt{Name: name, Description: desc},
Handler: testPromptHandler,
}
}
3 changes: 1 addition & 2 deletions mcp/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ func runServer() {
ctx := context.Background()

server := mcp.NewServer("greeter", "v0.0.1", nil)
server.AddTools(mcp.NewServerTool("greet", "say hi", SayHi))

mcp.AddTool(server, &mcp.Tool{Name: "greet", Description: "say hi"}, SayHi)
if err := server.Run(ctx, mcp.NewStdioTransport()); err != nil {
log.Fatal(err)
}
Expand Down
12 changes: 6 additions & 6 deletions mcp/features_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ func SayHi(ctx context.Context, cc *ServerSession, params *CallToolParamsFor[Say
}

func TestFeatureSetOrder(t *testing.T) {
toolA := NewServerTool("apple", "apple tool", SayHi).Tool
toolB := NewServerTool("banana", "banana tool", SayHi).Tool
toolC := NewServerTool("cherry", "cherry tool", SayHi).Tool
toolA := &Tool{Name: "apple", Description: "apple tool"}
toolB := &Tool{Name: "banana", Description: "banana tool"}
toolC := &Tool{Name: "cherry", Description: "cherry tool"}

testCases := []struct {
tools []*Tool
Expand All @@ -52,9 +52,9 @@ func TestFeatureSetOrder(t *testing.T) {
}

func TestFeatureSetAbove(t *testing.T) {
toolA := NewServerTool("apple", "apple tool", SayHi).Tool
toolB := NewServerTool("banana", "banana tool", SayHi).Tool
toolC := NewServerTool("cherry", "cherry tool", SayHi).Tool
toolA := &Tool{Name: "apple", Description: "apple tool"}
toolB := &Tool{Name: "banana", Description: "banana tool"}
toolC := &Tool{Name: "cherry", Description: "cherry tool"}

testCases := []struct {
tools []*Tool
Expand Down
Loading
Loading