MCP HubMCP Hub
metoro-io

mcp-golang

by: metoro-io

Write Model Context Protocol servers in few lines of go code. Docs at https://mcpgolang.com

709created 07/12/2024
Visit
Go
Protocol

📌Overview

Purpose: To provide a framework for developing servers and clients that implement the Model Context Protocol (MCP) in the Go programming language.

Overview: mcp-golang is an unofficial Go implementation of the Model Context Protocol, designed to facilitate the quick and efficient creation of MCP servers and clients. It offers type safety, modularity, and low boilerplate code, making it easier for developers to integrate this protocol into their applications.

Key Features:

  • Type Safety: Utilize native Go structs for tool arguments, enabling automatic schema generation, deserialization, and error handling.

  • Custom Transports: Choose from built-in transport options (stdio for full features, HTTP for stateless communication) or create custom transports as needed.

  • Low Boilerplate: Automatically generate all required MCP endpoints, minimizing the amount of code developers must write for functionality.

  • Modular Design: The library consists of separate components for transport, protocol, and server/client, allowing developers to use only what they need.

  • Bi-directional Communication: Supports both server and client implementations through stdio transport, facilitating interactive applications.


mcp-golang

mcp-golang is an unofficial implementation of the Model Context Protocol in Go. Write MCP servers and clients in Go with minimal code.

Docs at https://mcpgolang.com

Highlights

  • 🛡️ Type safety - Define your tool arguments as native Go structs. Automatic schema generation, deserialization, error handling, etc.
  • 🚛 Custom transports - Use built-in transports (stdio for full feature support, HTTP for stateless communication) or write your own.
  • Low boilerplate - mcp-golang generates all MCP endpoints except for your tools, prompts, and resources.
  • 🧩 Modular - The library is split into transport, protocol, and server/client components. Use all or what you need.
  • 🔄 Bi-directional - Full support for both server and client implementations through stdio transport.

Example Usage

Install with:

go get github.com/metoro-io/mcp-golang

Server Example

package main

import (
	"fmt"
	mcp_golang "github.com/metoro-io/mcp-golang"
	"github.com/metoro-io/mcp-golang/transport/stdio"
)

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 caller"`
	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
}

HTTP Server Example

Create an HTTP-based server using 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 for those features.

Client Example

package main

import (
    "context"
    "log"
    mcp "github.com/metoro-io/mcp-golang"
    "github.com/metoro-io/mcp-golang/transport/stdio"
    "os/exec"
)

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()
    
   transport := stdio.NewStdioServerTransportWithIO(stdout, stdin)
   client := mcp.NewClient(transport)
    
   if _, err := client.Initialize(context.Background()); err != nil {
       log.Fatalf("Failed to initialize: %v", err)
   }

   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 at ~/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

Contributions are welcome! Please check out our contribution guidelines.

Discord

Have suggestions or questions about the API or usage? Ask on the discord server. A maintainer will be happy to help.

Examples

Some extensive examples using the library can be found here:

Open a PR to add your own projects!

Server Feature Implementation

Tools

  • Tool Calls
  • Native Go structs as arguments
  • Programmatically generated tool list endpoint
  • Change notifications
  • Pagination

Prompts

  • Prompt Calls
  • Programmatically generated prompt list endpoint
  • Change notifications
  • Pagination

Resources

  • Resource Calls
  • Programmatically generated resource list endpoint
  • Change notifications
  • Pagination

Transports

  • Stdio - Full support for all features including bidirectional communication
  • HTTP - Stateless transport for simple request-response (no notifications support)
  • Gin - HTTP transport with Gin framework integration (stateless, no notifications support)
  • SSE
  • Custom transport support
  • HTTPS with custom auth support (in progress)

Client

  • Call tools
  • Call prompts
  • Call resources
  • List tools
  • List prompts
  • List resources