关于 MCP Server Go
MCP Server Go 是用于构建 MCP 服务的 Go 实现,面向需要连接大模型应用与数据、工具的开发者。它提供工具、资源和提示词的高级 API,协议支持仍在开发中。
主要功能
- 01高级 Go 服务端 API
- 02注册工具
- 03静态与动态资源
- 04可复用提示词定义
- 05协议与连接管理
适用场景
- 01用 Go 构建 MCP 服务
- 02将应用数据作为资源提供
- 03向大模型应用提供操作工具
- 04定义可复用交互提示词
MCP 相关
该库实现 MCP 服务端,向 MCP 客户端提供工具、资源和提示词。项目目标是覆盖核心规范,部分高级能力仍在开发中。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
MCP Server Go
提示
Model Context Protocol(MCP)的 Go 实现,可让大模型应用与外部数据源和工具无缝集成。
package main
import (
"context"
"fmt"
"github.com/shaneholloman/mcp-server-go/mcp"
"github.com/shaneholloman/mcp-server-go/server"
)
func main() {
// Create MCP server
s := server.NewMCPServer(
"Demo",
"1.0.0",
)
// Add tool
tool := mcp.NewTool("hello_world",
mcp.WithDescription("Say hello to someone"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the person to greet"),
),
)
// Add tool handler
s.AddTool(tool, helloHandler)
// Start the stdio server
if err := server.ServeStdio(s); err != nil {
fmt.Printf("Server error: %v\n", err)
}
}
func helloHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
name, ok := request.Params.Arguments["name"].(string)
if !ok {
return mcp.NewToolResultError("name must be a string"), nil
}
return mcp.NewToolResultText(fmt.Sprintf("Hello, %s!", name)), nil
}
就是这样!
MCP Go 会处理所有复杂的协议细节和服务管理,让你专注于构建出色的工具。它力求提供高层级且易于使用的体验。
主要特性
- 快速:高层级接口意味着更少的代码和更快的开发
- 简单:只需少量样板代码即可构建 MCP 服务
- 完整*:MCP Go 力求完整实现 MCP 核心规范
重要
MCP Go 正在积极开发中,MCP 规范本身也在不断完善。核心功能已可使用,但一些高级功能仍在开发中。
目录
安装
go get github.com/shaneholloman/mcp-server-go
快速开始
我们来创建一个简单的 MCP 服务,提供计算器工具和一些数据:
package main
import (
"context"
"fmt"
"github.com/shaneholloman/mcp-server-go/mcp"
"github.com/shaneholloman/mcp-server-go/server"
)
func main() {
// Create a new MCP server
s := server.NewMCPServer(
"Calculator Demo",
"1.0.0",
server.WithResourceCapabilities(true, true),
server.WithLogging(),
)
// Add a calculator tool
calculatorTool := mcp.NewTool("calculate",
mcp.WithDescription("Perform basic arithmetic operations"),
mcp.WithString("operation",
mcp.Required(),
mcp.Description("The operation to perform (add, subtract, multiply, divide)"),
mcp.Enum("add", "subtract", "multiply", "divide"),
),
mcp.WithNumber("x",
mcp.Required(),
mcp.Description("First number"),
),
mcp.WithNumber("y",
mcp.Required(),
mcp.Description("Second number"),
),
)
// Add the calculator handler
s.AddTool(calculatorTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
op := request.Params.Arguments["operation"].(string)
x := request.Params.Arguments["x"].(float64)
y := request.Params.Arguments["y"].(float64)
var result float64
switch op {
case "add":
result = x + y
case "subtract":
result = x - y
case "multiply":
result = x * y
case "divide":
if y == 0 {
return mcp.NewToolResultError("Cannot divide by zero"), nil
}
result = x / y
}
return mcp.NewToolResultText(fmt.Sprintf("%.2f", result)), nil
})
// Start the server
if err := server.ServeStdio(s); err != nil {
fmt.Printf("Server error: %v\n", err)
}
}
什么是 MCP?
Model Context Protocol(MCP) 让你能够构建以安全、标准化的方式向大模型应用提供数据和功能的服务。可以把它看作专为大模型交互设计的 Web API。MCP 服务可以:
- 通过资源提供数据(可以把它们看作类似 GET 端点的东西;用于将信息加载到大模型的上下文中)
- 通过工具提供功能(可以把它们看作类似 POST 端点的东西;用于执行代码或产生其他副作用)
- 通过提示词定义交互模式(用于大模型交互的可复用模板)
- 以及更多!
核心概念
服务
显示服务示例
服务是 MCP 协议的核心接口,负责连接管理、协议合规和消息路由:
// Create a basic server
s := server.NewMCPServer(
"My Server", // Server name
"1.0.0", // Version
)
// Start the server using stdio
if err := server.ServeStdio(s); err != nil {
log.Fatalf("Server error: %v", err)
}
资源
显示资源示例
资源是向大模型提供数据的方式。它们可以是各种内容——文件、API 响应、数据库查询结果、系统信息等。资源可以是:- 静态(固定 URI)
- 动态(使用 URI 模板)
以下是一个静态资源的简单示例:
// Static resource example - exposing a README file
resource := mcp.NewResource(
"docs://readme",
"Project README",
mcp.WithResourceDescription("The project's README file"),
mcp.WithMIMEType("text/markdown"),
mcp.WithAnnotations([]mcp.Role{mcp.RoleAssistant}, 0.8),
)
// Add resource with its handler
s.AddResource(resource, func(ctx context.Context, request mcp.ReadResourceRequest) ([]interface{}, error) {
content, err := os.ReadFile("README.md")
if err != nil {
return nil, err
}
return []interface{}{
mcp.TextResourceContents{
ResourceContents: mcp.ResourceContents{
URI: "docs://readme",
MIMEType: "text/markdown",
},
Text: string(content),
},
}, nil
})
以下是使用模板的动态资源示例:
// Dynamic resource example - user profiles by ID
template := mcp.NewResourceTemplate(
"users://{id}/profile",
"User Profile",
mcp.WithTemplateDescription("Returns user profile information"),
mcp.WithTemplateMIMEType("application/json"),
mcp.WithTemplateAnnotations([]mcp.Role{mcp.RoleAssistant, mcp.RoleUser}, 0.5),
)
// Add template with its handler
s.AddResourceTemplate(template, func(ctx context.Context, request mcp.ReadResourceRequest) ([]interface{}, error) {
userID := request.Params.URI // Extract ID from the full URI
profile, err := getUserProfile(userID) // Your DB/API call here
if err != nil {
return nil, err
}
return []interface{}{
mcp.TextResourceContents{
ResourceContents: mcp.ResourceContents{
URI: fmt.Sprintf("users://%s/profile", userID),
MIMEType: "application/json",
},
Text: profile,
},
}, nil
})
这些示例虽然简单,但展示了核心概念。资源还可以复杂得多,例如提供多个内容、使用注解、与数据库或外部 API 集成等。
工具
显示工具示例
工具让大模型能够通过你的服务执行操作。与资源不同,工具需要执行计算并产生副作用。它们类似于 REST API 中的 POST 端点。
简单计算示例:
calculatorTool := mcp.NewTool("calculate",
mcp.WithDescription("Perform basic arithmetic calculations"),
mcp.WithString("operation",
mcp.Required(),
mcp.Description("The arithmetic operation to perform"),
mcp.Enum("add", "subtract", "multiply", "divide"),
),
mcp.WithNumber("x",
mcp.Required(),
mcp.Description("First number"),
),
mcp.WithNumber("y",
mcp.Required(),
mcp.Description("Second number"),
),
)
s.AddTool(calculatorTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
op := request.Params.Arguments["operation"].(string)
x := request.Params.Arguments["x"].(float64)
y := request.Params.Arguments["y"].(float64)
var result float64
switch op {
case "add":
result = x + y
case "subtract":
result = x - y
case "multiply":
result = x * y
case "divide":
if y == 0 {
return mcp.NewToolResultError("Division by zero is not allowed"), nil
}
result = x / y
}
return mcp.FormatNumberResult(result), nil
})
HTTP 请求示例:
httpTool := mcp.NewTool("http_request",
mcp.WithDescription("Make HTTP requests to external APIs"),
mcp.WithString("method",
mcp.Required(),
mcp.Description("HTTP method to use"),
mcp.Enum("GET", "POST", "PUT", "DELETE"),
),
mcp.WithString("url",
mcp.Required(),
mcp.Description("URL to send the request to"),
mcp.Pattern("^https?://.*"),
),
mcp.WithString("body",
mcp.Description("Request body (for POST/PUT)"),
),
)
s.AddTool(httpTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
method := request.Params.Arguments["method"].(string)
url := request.Params.Arguments["url"].(string)
body := ""
if b, ok := request.Params.Arguments["body"].(string); ok {
body = b
}
// Create and send request
var req *http.Request
var err error
if body != "" {
req, err = http.NewRequest(method, url, strings.NewReader(body))
} else {
req, err = http.NewRequest(method, url, nil)
}
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("Failed to create request: %v", err)), nil
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("Request failed: %v", err)), nil
}
defer resp.Body.Close()
// Return response
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("Failed to read response: %v", err)), nil
}
return mcp.NewToolResultText(fmt.Sprintf("Status: %d\nBody: %s", resp.StatusCode, string(respBody))), nil
})
工具可以用于执行任何类型的计算或产生副作用:
- 数据库查询
- 文件操作
- 外部 API 调用
- 计算
- 系统操作
每个工具都应:
- 有清晰的描述
- 验证输入
- 妥善处理错误
- 返回结构化响应
- 使用合适的结果类型
显示提示词示例
提示词是可重复使用的模板,可帮助大模型与服务器有效交互。它们就像编码在服务器中的“最佳实践”。以下是一些示例:
// Simple greeting prompt
s.AddPrompt(mcp.NewPrompt("greeting",
mcp.WithPromptDescription("A friendly greeting prompt"),
mcp.WithArgument("name",
mcp.ArgumentDescription("Name of the person to greet"),
),
), func(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
name := request.Params.Arguments["name"].(string)
if name == "" {
name = "friend"
}
return mcp.NewGetPromptResult(
"A friendly greeting",
[]mcp.PromptMessage{
mcp.NewPromptMessage(
mcp.RoleAssistant,
mcp.NewTextContent(fmt.Sprintf("Hello, %s! How can I help you today?", name)),
),
},
), nil
})
// Code review prompt with embedded resource
s.AddPrompt(mcp.NewPrompt("code_review",
mcp.WithPromptDescription("Code review assistance"),
mcp.WithArgument("pr_number",
mcp.ArgumentDescription("Pull request number to review"),
mcp.RequiredArgument(),
),
), func(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
prNumber := request.Params.Arguments["pr_number"].(string)
if prNumber == "" {
return nil, fmt.Errorf("pr_number is required")
}
return mcp.NewGetPromptResult(
"Code review assistance",
[]mcp.PromptMessage{
mcp.NewPromptMessage(
mcp.RoleSystem,
mcp.NewTextContent("You are a helpful code reviewer. Review the changes and provide constructive feedback."),
),
mcp.NewPromptMessage(
mcp.RoleAssistant,
mcp.NewEmbeddedResource(mcp.ResourceContents{
URI: fmt.Sprintf("git://pulls/%s/diff", prNumber),
MIMEType: "text/x-diff",
}),
),
},
), nil
})
// Database query builder prompt
s.AddPrompt(mcp.NewPrompt("query_builder",
mcp.WithPromptDescription("SQL query builder assistance"),
mcp.WithArgument("table",
mcp.ArgumentDescription("Name of the table to query"),
mcp.RequiredArgument(),
),
), func(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
tableName := request.Params.Arguments["table"].(string)
if tableName == "" {
return nil, fmt.Errorf("table name is required")
}
return mcp.NewGetPromptResult(
"SQL query builder assistance",
[]mcp.PromptMessage{
mcp.NewPromptMessage(
mcp.RoleSystem,
mcp.NewTextContent("You are a SQL expert. Help construct efficient and safe queries."),
),
mcp.NewPromptMessage(
mcp.RoleAssistant,
mcp.NewEmbeddedResource(mcp.ResourceContents{
URI: fmt.Sprintf("db://schema/%s", tableName),
MIMEType: "application/json",
}),
),
},
), nil
})
提示词可以包含:
- 系统指令
- 必需参数
- 嵌入的资源
- 多条消息
- 不同的内容类型(文本、图像等)
- 自定义 URI 方案
示例
示例请参见 examples/ 目录。
参与贡献
打开开发者指南
先决条件
Go 版本 >= 1.23
开发环境安装
创建此仓库的分叉,然后克隆它:
git clone https://github.com/shaneholloman/mcp-server-go.git
cd mcp-server-go
测试
请务必测试任何新功能。测试应当简单且独立,并预见变化,而不是固化复杂模式。
从根目录运行测试:
go test -v './...'
创建拉取请求
分叉此仓库并创建一个新分支:
git checkout -b my-branch
进行更改并提交:
git add . && git commit -m "My changes"
将更改推送到你的分叉:
git push origin my-branch
如有任何疑问,欢迎在 GitHub issue 或讨论区中联系!
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。