2025-05-04 15:29:14 +08:00
# Model Context Protocol (MCP) Implementation
2025-04-27 23:06:37 +08:00
## Overview
2025-12-26 00:21:45 +08:00
This package provides a go-zero integration for the [Model Context Protocol (MCP) ](https://modelcontextprotocol.io/ ) using the official [go-sdk ](https://github.com/modelcontextprotocol/go-sdk ). It wraps the official MCP SDK to provide a seamless integration with go-zero's REST server framework.
2025-04-27 23:06:37 +08:00
2025-12-26 00:21:45 +08:00
## Features
2025-04-27 23:06:37 +08:00
2025-12-26 00:21:45 +08:00
- **Official SDK Integration**: Built on top of the official Model Context Protocol Go SDK
- **No SDK Import Required**: Use `mcp.AddTool()` directly without importing the official SDK
- **go-zero Integration**: Seamlessly integrates with go-zero's REST server and configuration system
- **Dual Transport Support**:
- SSE (Server-Sent Events) transport for 2024-11-05 MCP spec
- Streamable HTTP transport for 2025-03-26 MCP spec
- **CORS Support**: Configurable CORS settings for cross-origin requests
- **Type-Safe Tool Handlers**: Generic tool handlers with automatic JSON schema generation
- **Prompts and Resources**: Full support for MCP prompts and resources
2026-04-25 17:11:04 +08:00
- **Request Metadata Bridge**: Optional request metadata extraction into handler context
2025-04-27 23:06:37 +08:00
2025-12-26 00:21:45 +08:00
## Quick Start
2025-04-27 23:06:37 +08:00
2025-12-26 00:21:45 +08:00
### 1. Installation
2025-04-27 23:06:37 +08:00
2025-12-26 00:21:45 +08:00
``` bash
go get github.com/zeromicro/go-zero
```
2025-04-27 23:06:37 +08:00
2025-12-26 00:21:45 +08:00
**Note ** : The official MCP SDK is a transitive dependency and will be installed automatically. You don't need to import it directly in your code.
2025-04-27 23:06:37 +08:00
2025-12-26 00:21:45 +08:00
### 2. Configuration
2025-04-27 23:06:37 +08:00
2025-12-26 00:21:45 +08:00
Create a configuration file `config.yaml` :
2025-04-27 23:06:37 +08:00
2025-12-26 00:21:45 +08:00
``` yaml
name : my-mcp-server
host : localhost
port : 8080
mcp :
name : my-mcp-server
version : 1.0 .0
useStreamable : false # Use SSE transport (default), set to true for Streamable HTTP
sseEndpoint : /sse
messageEndpoint : /message
sseTimeout : 24h
messageTimeout : 30s
cors :
- http://localhost:3000
```
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
### 3. Create Your Server
2025-05-04 15:29:14 +08:00
``` go
package main
import (
2025-12-26 00:21:45 +08:00
"context"
"log"
2025-05-04 15:29:14 +08:00
"github.com/zeromicro/go-zero/core/conf"
"github.com/zeromicro/go-zero/mcp"
)
2025-12-26 00:21:45 +08:00
type GreetArgs struct {
Name string ` json:"name" jsonschema:"description=Name of the person to greet" `
}
2025-05-04 15:29:14 +08:00
func main ( ) {
2025-12-26 00:21:45 +08:00
// Load configuration
2025-05-04 15:29:14 +08:00
var c mcp . McpConf
conf . MustLoad ( "config.yaml" , & c )
// Create MCP server
server := mcp . NewMcpServer ( c )
2025-12-26 00:21:45 +08:00
// Register a tool with automatic schema generation using the SDK directly
tool := & mcp . Tool {
Name : "greet" ,
Description : "Greet someone by name" ,
}
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
handler := func ( ctx context . Context , req * mcp . CallToolRequest , args GreetArgs ) ( * mcp . CallToolResult , any , error ) {
return & mcp . CallToolResult {
Content : [ ] mcp . Content {
& mcp . TextContent { Text : "Hello, " + args . Name + "!" } ,
2025-05-04 15:29:14 +08:00
} ,
2025-12-26 00:21:45 +08:00
} , nil , nil
}
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
// Register tool with type-safe generics - no need to import official SDK
mcp . AddTool ( server , tool , handler )
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
// Start server
defer server . Stop ( )
server . Start ( )
2025-05-04 15:29:14 +08:00
}
```
2025-12-26 00:21:45 +08:00
## Adding Tools
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
Tools are functions that the MCP client can call. The SDK automatically generates JSON schemas from your struct tags. Use `sdkmcp.AddTool` with the server's underlying SDK server:
2025-05-04 15:29:14 +08:00
``` go
2025-12-26 00:21:45 +08:00
type CalculateArgs struct {
Operation string ` json:"operation" jsonschema:"enum=add,enum=subtract,enum=multiply,enum=divide" `
A float64 ` json:"a" jsonschema:"description=First number" `
B float64 ` json:"b" jsonschema:"description=Second number" `
2025-05-04 15:29:14 +08:00
}
2025-12-26 00:21:45 +08:00
tool := & mcp . Tool {
Name : "calculate" ,
Description : "Perform arithmetic operations" ,
}
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
handler := func ( ctx context . Context , req * mcp . CallToolRequest , args CalculateArgs ) ( * mcp . CallToolResult , any , error ) {
var result float64
switch args . Operation {
case "add" :
result = args . A + args . B
case "subtract" :
result = args . A - args . B
case "multiply" :
result = args . A * args . B
case "divide" :
if args . B == 0 {
return & mcp . CallToolResult { IsError : true } , nil , fmt . Errorf ( "division by zero" )
}
result = args . A / args . B
}
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
return & mcp . CallToolResult {
Content : [ ] mcp . Content {
& mcp . TextContent { Text : fmt . Sprintf ( "Result: %v" , result ) } ,
2025-05-04 15:29:14 +08:00
} ,
2025-12-26 00:21:45 +08:00
} , result , nil
2025-05-04 15:29:14 +08:00
}
2025-12-26 00:21:45 +08:00
// Register tool
mcp . AddTool ( server , tool , handler )
2025-05-04 15:29:14 +08:00
```
2025-12-26 00:21:45 +08:00
## Adding Prompts
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
Prompts provide reusable message templates:
2025-05-04 15:29:14 +08:00
``` go
2025-12-26 00:21:45 +08:00
prompt := & mcp . Prompt {
Name : "code-review" ,
Description : "Review code for best practices" ,
}
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
handler := func ( ctx context . Context , req * sdkmcp . GetPromptRequest , args map [ string ] string ) ( * mcp . GetPromptResult , error ) {
code := args [ "code" ]
language := args [ "language" ]
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
return & mcp . GetPromptResult {
Messages : [ ] mcp . PromptMessage {
2025-05-04 15:29:14 +08:00
{
2025-12-26 00:21:45 +08:00
Role : "user" ,
Content : & mcp . TextContent {
Text : fmt . Sprintf ( "Please review this %s code:\n\n%s" , language , code ) ,
2025-05-04 15:29:14 +08:00
} ,
} ,
2025-12-26 00:21:45 +08:00
} ,
} , nil
}
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
server . AddPrompt ( prompt , handler )
2025-05-04 15:29:14 +08:00
```
2025-12-26 00:21:45 +08:00
## Adding Resources
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
Resources provide access to data that the model can read:
2025-05-04 15:29:14 +08:00
``` go
2025-12-26 00:21:45 +08:00
resource := & mcp . Resource {
URI : "file:///docs/readme.md" ,
Name : "README" ,
Description : "Project documentation" ,
MimeType : "text/markdown" ,
}
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
handler := func ( ctx context . Context , req * sdkmcp . ReadResourceRequest , uri string ) ( * mcp . ReadResourceResult , error ) {
content , err := os . ReadFile ( "README.md" )
if err != nil {
return nil , err
}
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
return & mcp . ReadResourceResult {
Contents : [ ] mcp . ResourceContents {
2025-05-04 15:29:14 +08:00
{
2025-12-26 00:21:45 +08:00
URI : uri ,
MimeType : "text/markdown" ,
Text : string ( content ) ,
2025-05-04 15:29:14 +08:00
} ,
} ,
2025-12-26 00:21:45 +08:00
} , nil
}
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
server . AddResource ( resource , handler )
2025-05-04 15:29:14 +08:00
```
2025-12-26 00:21:45 +08:00
## Transport Options
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
### SSE Transport (Default)
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
The SSE (Server-Sent Events) transport is the original MCP transport from the 2024-11-05 specification:
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
``` yaml
mcp :
useStreamable : false
sseEndpoint : /sse
```
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
### Streamable HTTP Transport
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
The newer Streamable HTTP transport from the 2025-03-26 specification provides better connection management:
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
``` yaml
mcp :
useStreamable : true
messageEndpoint : /message
2025-05-04 15:29:14 +08:00
```
2026-04-25 17:11:04 +08:00
## Request Metadata Bridge
For multi-tenant or request-context-aware tools, you can extract selected HTTP request metadata once at the transport boundary and read it from `context.Context` in handlers.
``` go
server := mcp . NewMcpServerWithOptions ( c ,
mcp . WithRequestMetadataExtractor ( mcp . DefaultRequestMetadataExtractor ) ,
)
handler := func ( ctx context . Context , req * mcp . CallToolRequest , args SomeArgs ) ( * mcp . CallToolResult , any , error ) {
tenant , _ := mcp . HeaderFromContext ( ctx , "X-Tenant-Id" )
traceID , _ := mcp . QueryFromContext ( ctx , "trace" )
scope , _ := mcp . PathFromContext ( ctx , "scope" )
_ = tenant
_ = traceID
_ = scope
return & mcp . CallToolResult { } , nil , nil
}
```
Available helpers:
- `RequestMetadataFromContext(ctx)`
- `HeaderFromContext(ctx, key)`
- `QueryFromContext(ctx, key)`
- `PathFromContext(ctx, key)`
2025-12-26 00:21:45 +08:00
## Configuration Options
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `name` | string | | Server name (required, from RestConf) |
| `host` | string | | Server host (required, from RestConf) |
| `port` | int | | Server port (required, from RestConf) |
| `mcp.name` | string | | MCP server name (defaults to `name` ) |
| `mcp.version` | string | `1.0.0` | Server version |
| `mcp.useStreamable` | bool | `false` | Use Streamable HTTP transport instead of SSE |
| `mcp.sseEndpoint` | string | `/sse` | SSE endpoint path |
| `mcp.messageEndpoint` | string | `/message` | Message endpoint path |
| `mcp.sseTimeout` | duration | `24h` | SSE connection timeout |
| `mcp.messageTimeout` | duration | `30s` | Message processing timeout |
| `mcp.cors` | []string | | Allowed CORS origins |
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
## Examples
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
See the `adhoc/mcp` directory for a complete working example.
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
## Official SDK Documentation
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
For more details on the underlying MCP SDK, see:
- [Official Go SDK ](https://github.com/modelcontextprotocol/go-sdk )
- [MCP Specification ](https://modelcontextprotocol.io/ )
- [SDK Documentation ](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp )
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
## License
2025-05-04 15:29:14 +08:00
2025-12-26 00:21:45 +08:00
This implementation follows the go-zero project license (MIT).