AI prompts
base on Write Model Context Protocol servers in few lines of go code. Docs at https://mcpgolang.com <div align="center">
<img src="./resources/mcp-golang-logo.webp" height="300" alt="Statusphere logo">
</div>
<br/>
<div align="center">







[](https://pkg.go.dev/github.com/metoro-io/mcp-golang)
[](https://goreportcard.com/report/github.com/metoro-io/mcp-golang)

</div>
# mcp-golang
mcp-golang is an unofficial implementation of the [Model Context Protocol](https://modelcontextprotocol.io/) in Go.
Write MCP servers and clients in golang with a few lines of code.
Docs at [https://mcpgolang.com](https://mcpgolang.com)
## Highlights
- 🛡️**Type safety** - Define your tool arguments as native go structs, have mcp-golang handle the rest. Automatic schema generation, deserialization, error handling etc.
- 🚛 **Custom transports** - Use the built-in transports (stdio for full feature support, HTTP for stateless communication) or write your own.
- ⚡ **Low boilerplate** - mcp-golang generates all the MCP endpoints for you apart from your tools, prompts and resources.
- 🧩 **Modular** - The library is split into three components: transport, protocol and server/client. Use them all or take 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
```go
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
}
```
### HTTP Server Example
You can also create an HTTP-based server using either the standard HTTP transport or Gin framework:
```go
// 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.
### Client Example
Checkout the [examples/client](./examples/client) directory for a more complete example.
```go
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:
```json
{
"mcpServers": {
"golang-mcp-server": {
"command": "<your path to golang MCP server go executable>",
"args": [],
"env": {}
}
}
}
```
## Contributions
Contributions are more than welcome! Please check out [our contribution guidelines](./CONTRIBUTING.md).
## Discord
Got any suggestions, have a question on the api or usage? Ask on the [discord server](https://discord.gg/33saRwE3pT).
A maintainer will be happy to help you out.
## Examples
Some more extensive examples using the library found here:
- <img height="12" width="12" src="https://metoro.io/static/images/logos/Metoro.svg" /> **[Metoro](https://github.com/metoro-io/metoro-mcp-server)** - Query and interact with kubernetes environments monitored by Metoro
Open a PR to add your own projects!
## Server Feature Implementation
### Tools
- [x] Tool Calls
- [x] Native go structs as arguments
- [x] Programatically generated tool list endpoint
- [x] Change notifications
- [x] Pagination
### Prompts
- [x] Prompt Calls
- [x] Programatically generated prompt list endpoint
- [x] Change notifications
- [x] Pagination
### Resources
- [x] Resource Calls
- [x] Programatically generated resource list endpoint
- [x] Change notifications
- [x] Pagination
### Transports
- [x] Stdio - Full support for all features including bidirectional communication
- [x] HTTP - Stateless transport for simple request-response scenarios (no notifications support)
- [x] Gin - HTTP transport with Gin framework integration (stateless, no notifications support)
- [x] SSE
- [x] Custom transport support
- [ ] HTTPS with custom auth support - in progress. Not currently part of the spec but we'll be adding experimental support for it.
### Client
- [x] Call tools
- [x] Call prompts
- [x] Call resources
- [x] List tools
- [x] List prompts
- [x] List resources
", Assign "at most 3 tags" to the expected json: {"id":"13190","tags":[]} "only from the tags list I provide: [{"id":77,"name":"3d"},{"id":89,"name":"agent"},{"id":17,"name":"ai"},{"id":54,"name":"algorithm"},{"id":24,"name":"api"},{"id":44,"name":"authentication"},{"id":3,"name":"aws"},{"id":27,"name":"backend"},{"id":60,"name":"benchmark"},{"id":72,"name":"best-practices"},{"id":39,"name":"bitcoin"},{"id":37,"name":"blockchain"},{"id":1,"name":"blog"},{"id":45,"name":"bundler"},{"id":58,"name":"cache"},{"id":21,"name":"chat"},{"id":49,"name":"cicd"},{"id":4,"name":"cli"},{"id":64,"name":"cloud-native"},{"id":48,"name":"cms"},{"id":61,"name":"compiler"},{"id":68,"name":"containerization"},{"id":92,"name":"crm"},{"id":34,"name":"data"},{"id":47,"name":"database"},{"id":8,"name":"declarative-gui "},{"id":9,"name":"deploy-tool"},{"id":53,"name":"desktop-app"},{"id":6,"name":"dev-exp-lib"},{"id":59,"name":"dev-tool"},{"id":13,"name":"ecommerce"},{"id":26,"name":"editor"},{"id":66,"name":"emulator"},{"id":62,"name":"filesystem"},{"id":80,"name":"finance"},{"id":15,"name":"firmware"},{"id":73,"name":"for-fun"},{"id":2,"name":"framework"},{"id":11,"name":"frontend"},{"id":22,"name":"game"},{"id":81,"name":"game-engine "},{"id":23,"name":"graphql"},{"id":84,"name":"gui"},{"id":91,"name":"http"},{"id":5,"name":"http-client"},{"id":51,"name":"iac"},{"id":30,"name":"ide"},{"id":78,"name":"iot"},{"id":40,"name":"json"},{"id":83,"name":"julian"},{"id":38,"name":"k8s"},{"id":31,"name":"language"},{"id":10,"name":"learning-resource"},{"id":33,"name":"lib"},{"id":41,"name":"linter"},{"id":28,"name":"lms"},{"id":16,"name":"logging"},{"id":76,"name":"low-code"},{"id":90,"name":"message-queue"},{"id":42,"name":"mobile-app"},{"id":18,"name":"monitoring"},{"id":36,"name":"networking"},{"id":7,"name":"node-version"},{"id":55,"name":"nosql"},{"id":57,"name":"observability"},{"id":46,"name":"orm"},{"id":52,"name":"os"},{"id":14,"name":"parser"},{"id":74,"name":"react"},{"id":82,"name":"real-time"},{"id":56,"name":"robot"},{"id":65,"name":"runtime"},{"id":32,"name":"sdk"},{"id":71,"name":"search"},{"id":63,"name":"secrets"},{"id":25,"name":"security"},{"id":85,"name":"server"},{"id":86,"name":"serverless"},{"id":70,"name":"storage"},{"id":75,"name":"system-design"},{"id":79,"name":"terminal"},{"id":29,"name":"testing"},{"id":12,"name":"ui"},{"id":50,"name":"ux"},{"id":88,"name":"video"},{"id":20,"name":"web-app"},{"id":35,"name":"web-server"},{"id":43,"name":"webassembly"},{"id":69,"name":"workflow"},{"id":87,"name":"yaml"}]" returns me the "expected json"