Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
105 changes: 56 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,6 @@ software development kit (SDK) for the Model Context Protocol (MCP).
> changes. We aim to tag v1.0.0 in September, 2025. See
> https://github.com/modelcontextprotocol/go-sdk/issues/328 for details.

## Design

The design doc for this SDK is at [design.md](./design/design.md), which was
initially reviewed at
[modelcontextprotocol/discussions/364](https://github.com/orgs/modelcontextprotocol/discussions/364).

Further design discussion should occur in
[issues](https://github.com/modelcontextprotocol/go-sdk/issues) (for concrete
proposals) or
[discussions](https://github.com/modelcontextprotocol/go-sdk/discussions) for
open-ended discussion. See [CONTRIBUTING.md](/CONTRIBUTING.md) for details.

## Package documentation

The SDK consists of two importable packages:
Expand All @@ -42,12 +30,53 @@ The SDK consists of two importable packages:
- The
[`github.com/modelcontextprotocol/go-sdk/jsonrpc`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/jsonrpc) package is for users implementing
their own transports.

- The
[`github.com/modelcontextprotocol/go-sdk/auth`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth)
package provides some primitives for supporting oauth.

## 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:

```go
package main

import (
"context"
"log"

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

## Example
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)
}
}
```

In this example, an MCP client communicates with an MCP server running in a
sidecar process:
To communicate with that server, we can similarly create an `mcp.Client` and
connect it to the corresponding server, by running the server command and
communicating over its stdin/stdout:

```go
package main
Expand Down Expand Up @@ -92,42 +121,20 @@ func main() {
}
```

Here's an example of the corresponding server component, which communicates
with its client over stdin/stdout:

```go
package main

import (
"context"
"log"

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

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

func SayHi(ctx context.Context, req *mcp.CallToolRequest, args HiParams) (*mcp.CallToolResult, any, error) {
return &mcp.CallToolResult{
Content: []mcp.Content{&mcp.TextContent{Text: "Hi " + args.Name}},
}, nil, nil
}
The [`examples/`](/examples/) directory contains more example clients and
servers.

func main() {
// Create a server with a single tool.
server := mcp.NewServer(&mcp.Implementation{Name: "greeter", Version: "v1.0.0"}, nil)
## Design

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)
}
}
```
The design doc for this SDK is at [design.md](./design/design.md), which was
initially reviewed at
[modelcontextprotocol/discussions/364](https://github.com/orgs/modelcontextprotocol/discussions/364).

The [`examples/`](/examples/) directory contains more example clients and servers.
Further design discussion should occur in
[issues](https://github.com/modelcontextprotocol/go-sdk/issues) (for concrete
proposals) or
[discussions](https://github.com/modelcontextprotocol/go-sdk/discussions) for
open-ended discussion. See [CONTRIBUTING.md](/CONTRIBUTING.md) for details.

## Acknowledgements

Expand Down
146 changes: 146 additions & 0 deletions examples/server/toolschemas/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// Copyright 2025 The Go MCP SDK Authors. All rights reserved.
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

// The toolschemas example demonstrates how to create tools using both the
// low-level [ToolHandler] and high level [ToolHandlerFor], as well as how to
// customize schemas in both cases.
package main

import (
"context"
"encoding/json"
"fmt"
"log"

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

// Input is the input into all the tools handlers below.
type Input struct {
Name string `json:"name" jsonschema:"the person to greet"`
}

// Output is the structured output of the tool.
//
// Not every tool needs to have structured output.
type Output struct {
Greeting string `json:"greeting" jsonschema:"the greeting to send to the user"`
}

// simpleGreeting is an [mcp.ToolHandlerFor] that only cares about input and output.
func simpleGreeting(_ context.Context, _ *mcp.CallToolRequest, input Input) (*mcp.CallToolResult, Output, error) {
return nil, Output{"Hi " + input.Name}, nil
}

// manualGreeter handles the parsing and validation of input and output manually.
//
// Therfore, it needs to close over its resolved schemas, to use them in
// validation.
type manualGreeter struct {
inputSchema *jsonschema.Resolved
outputSchema *jsonschema.Resolved
}

func (t *manualGreeter) greet(_ context.Context, req *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
// errf produces a 'tool error', embedding the error in a CallToolResult.
errf := func(format string, args ...any) *mcp.CallToolResult {
return &mcp.CallToolResult{
Content: []mcp.Content{&mcp.TextContent{Text: fmt.Sprintf(format, args...)}},
IsError: true,
}
}
// Handle the parsing and validation of input and output.
//
// Note that errors here are treated as tool errors, not protocol errors.
var input Input
if err := json.Unmarshal(req.Params.Arguments, &input); err != nil {
return errf("failed to unmarshal arguments: %v", err), nil
}
if err := t.inputSchema.Validate(input); err != nil {
return errf("invalid input: %v", err), nil
}
output := Output{Greeting: "Hi " + input.Name}
if err := t.outputSchema.Validate(output); err != nil {
return errf("tool produced invalid output: %v", err), nil
}
outputJSON, err := json.Marshal(output)
if err != nil {
return errf("output failed to marshal: %v", err), nil
}
return &mcp.CallToolResult{
Content: []mcp.Content{&mcp.TextContent{Text: string(outputJSON)}},
StructuredContent: output,
}, nil
}

func main() {
server := mcp.NewServer(&mcp.Implementation{Name: "greeter"}, nil)

// Add the 'greeting' tool in a few different ways.

// First, we can just use [mcp.AddTool], and get the out-of-the-box handling
// it provides:
mcp.AddTool(server, &mcp.Tool{Name: "simple greeting"}, simpleGreeting)

// Next, we can create our schemas entirely manually, and add them using
// [mcp.Server.AddTool]. Since we're working manually, we can add some
// constraints on the length of the name.
//
// We don't need to do all this work: below, we use jsonschema.For to start
// from the default schema.
var (
manual manualGreeter
err error
)
inputSchema := &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"name": {Type: "string", MaxLength: jsonschema.Ptr(10)},
},
}
manual.inputSchema, err = inputSchema.Resolve(nil)
if err != nil {
log.Fatal(err)
}
outputSchema := &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"greeting": {Type: "string"},
},
}
manual.outputSchema, err = outputSchema.Resolve(nil)
if err != nil {
log.Fatal(err)
}
server.AddTool(&mcp.Tool{
Name: "manual greeting",
InputSchema: inputSchema,
OutputSchema: outputSchema,
}, manual.greet)

// Finally, note that we can also use custom schemas with a ToolHandlerFor.
// We can do this in two ways: by using one of the schema values constructed
// above, or by using jsonschema.For and adjusting the resulting schema.
mcp.AddTool(server, &mcp.Tool{
Name: "customized greeting 1",
InputSchema: inputSchema,
// OutputSchema will still be derived from Output.
}, simpleGreeting)

customSchema, err := jsonschema.For[Input](nil)
if err != nil {
log.Fatal(err)
}
customSchema.Properties["name"].MaxLength = jsonschema.Ptr(10)
mcp.AddTool(server, &mcp.Tool{
Name: "customized greeting 2",
InputSchema: customSchema,
}, simpleGreeting)

// Now run the server.
if err := server.Run(context.Background(), &mcp.StdioTransport{}); err != nil {
log.Printf("Server failed: %v", err)
}
}
46 changes: 26 additions & 20 deletions internal/readme/README.src.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,6 @@ software development kit (SDK) for the Model Context Protocol (MCP).
> changes. We aim to tag v1.0.0 in September, 2025. See
> https://github.com/modelcontextprotocol/go-sdk/issues/328 for details.

## Design

The design doc for this SDK is at [design.md](./design/design.md), which was
initially reviewed at
[modelcontextprotocol/discussions/364](https://github.com/orgs/modelcontextprotocol/discussions/364).

Further design discussion should occur in
[issues](https://github.com/modelcontextprotocol/go-sdk/issues) (for concrete
proposals) or
[discussions](https://github.com/modelcontextprotocol/go-sdk/discussions) for
open-ended discussion. See [CONTRIBUTING.md](/CONTRIBUTING.md) for details.

## Package documentation

The SDK consists of two importable packages:
Expand All @@ -41,21 +29,39 @@ The SDK consists of two importable packages:
- The
[`github.com/modelcontextprotocol/go-sdk/jsonrpc`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/jsonrpc) package is for users implementing
their own transports.

- The
[`github.com/modelcontextprotocol/go-sdk/auth`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth)
package provides some primitives for supporting oauth.

## Example
## Getting started

In this example, an MCP client communicates with an MCP server running in a
sidecar process:
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:

%include server/server.go -

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

%include client/client.go -

Here's an example of the corresponding server component, which communicates
with its client over stdin/stdout:
The [`examples/`](/examples/) directory contains more example clients and
servers.

%include server/server.go -
## Design

The [`examples/`](/examples/) directory contains more example clients and servers.
The design doc for this SDK is at [design.md](./design/design.md), which was
initially reviewed at
[modelcontextprotocol/discussions/364](https://github.com/orgs/modelcontextprotocol/discussions/364).

Further design discussion should occur in
[issues](https://github.com/modelcontextprotocol/go-sdk/issues) (for concrete
proposals) or
[discussions](https://github.com/modelcontextprotocol/go-sdk/discussions) for
open-ended discussion. See [CONTRIBUTING.md](/CONTRIBUTING.md) for details.

## Acknowledgements

Expand Down
13 changes: 7 additions & 6 deletions internal/readme/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,21 @@ import (
"github.com/modelcontextprotocol/go-sdk/mcp"
)

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

func SayHi(ctx context.Context, req *mcp.CallToolRequest, args HiParams) (*mcp.CallToolResult, any, error) {
return &mcp.CallToolResult{
Content: []mcp.Content{&mcp.TextContent{Text: "Hi " + args.Name}},
}, nil, nil
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 {
Expand Down
Loading
Loading