mcp-golang is an unofficial implementation of the Model Context Protocol in Go.
Write MCP servers and clients in golang with a few lines of code.
Docs at https://mcpgolang.com
Install with go get github.com/metoro-io/mcp-golang
package main import ( "fmt" "github.com/metoro-io/mcp-golang" "github.com/metoro-io/mcp-golang/transport/stdio" ) // Tool arguments are just structs, annotated with jsonschema tags // More at https://mcpgolang.com/tools#schema-generation type Content struct { Title string `json:"title" jsonschema:"required,description=The title to submit"` Description *string `json:"description" jsonschema:"description=The description to submit"` } type MyFunctionsArguments struct { Submitter string `json:"submitter" jsonschema:"required,description=The name of the thing calling this tool (openai, google, claude, etc)"` Content Content `json:"content" jsonschema:"required,description=The content of the message"` } func main() { done := make(chan struct{}) server := mcp_golang.NewServer(stdio.NewStdioServerTransport()) err := server.RegisterTool("hello", "Say hello to a person", func(arguments MyFunctionsArguments) (*mcp_golang.ToolResponse, error) { return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(fmt.Sprintf("Hello, %server!", arguments.Submitter))), nil }) if err != nil { panic(err) } err = server.RegisterPrompt("promt_test", "This is a test prompt", func(arguments Content) (*mcp_golang.PromptResponse, error) { return mcp_golang.NewPromptResponse("description", mcp_golang.NewPromptMessage(mcp_golang.NewTextContent(fmt.Sprintf("Hello, %server!", arguments.Title)), mcp_golang.RoleUser)), nil }) if err != nil { panic(err) } err = server.RegisterResource("test://resource", "resource_test", "This is a test resource", "application/json", func() (*mcp_golang.ResourceResponse, error) { return mcp_golang.NewResourceResponse(mcp_golang.NewTextEmbeddedResource("test://resource", "This is a test resource", "application/json")), nil }) err = server.Serve() if err != nil { panic(err) } <-done }
You can also create an HTTP-based server using either the standard HTTP transport or Gin framework:
// Standard HTTP transport := http.NewHTTPTransport("/mcp") transport.WithAddr(":8080") server := mcp_golang.NewServer(transport) // Or with Gin framework transport := http.NewGinTransport() router := gin.Default() router.POST("/mcp", transport.Handler()) server := mcp_golang.NewServer(transport)
Note: HTTP transports are stateless and don't support bidirectional features like notifications. Use stdio transport if you need those features.
Checkout the examples/client directory for a more complete example.
package main import ( "context" "log" mcp "github.com/metoro-io/mcp-golang" "github.com/metoro-io/mcp-golang/transport/stdio" ) // Define type-safe arguments type CalculateArgs struct { Operation string `json:"operation"` A int `json:"a"` B int `json:"b"` } func main() { cmd := exec.Command("go", "run", "./server/main.go") stdin, err := cmd.StdinPipe() if err != nil { log.Fatalf("Failed to get stdin pipe: %v", err) } stdout, err := cmd.StdoutPipe() if err != nil { log.Fatalf("Failed to get stdout pipe: %v", err) } if err := cmd.Start(); err != nil { log.Fatalf("Failed to start server: %v", err) } defer cmd.Process.Kill() // Create and initialize client transport := stdio.NewStdioServerTransportWithIO(stdout, stdin) client := mcp.NewClient(transport) if _, err := client.Initialize(context.Background()); err != nil { log.Fatalf("Failed to initialize: %v", err) } // Call a tool with typed arguments args := CalculateArgs{ Operation: "add", A: 10, B: 5, } response, err := client.CallTool(context.Background(), "calculate", args) if err != nil { log.Fatalf("Failed to call tool: %v", err) } if response != nil && len(response.Content) > 0 { log.Printf("Result: %s", response.Content[0].TextContent.Text) } }Using with Claude Desktop
Create a file in ~/Library/Application Support/Claude/claude_desktop_config.json with the following contents:
{ "mcpServers": { "golang-mcp-server": { "command": "<your path to golang MCP server go executable>", "args": [], "env": {} } } }
Contributions are more than welcome! Please check out our contribution guidelines.
Got any suggestions, have a question on the api or usage? Ask on the discord server. A maintainer will be happy to help you out.
Some more extensive examples using the library found here:
Open a PR to add your own projects!
Server Feature ImplementationRetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4