服务端基础
学习如何使用不同的传输选项创建、配置和启动 MCP 服务端。
创建服务端
任何 MCP 服务端的基础是 NewMCPServer() 函数。这会创建一个带有基本元数据和可选配置的服务端实例。
基本服务端创建
go
package main
import (
"github.com/mark3labs/mcp-go/server"
)
func main() {
// 创建基本服务端
s := server.NewMCPServer(
"My MCP Server", // 服务端名称
"1.0.0", // 服务端版本
)
// 启动服务端(stdio 传输)
server.ServeStdio(s)
}带选项的服务端
使用服务端选项配置能力和行为:
go
s := server.NewMCPServer(
"Advanced Server",
"2.0.0",
server.WithToolCapabilities(true), // 启用工具
server.WithResourceCapabilities(true, true), // 启用资源
server.WithPromptCapabilities(true), // 启用提示词
server.WithRecovery(), // 添加 panic 恢复
server.WithHooks(myHooks), // 添加生命周期钩子
server.WithIcons( // 添加服务端图标
mcp.Icon{
Src: "https://example.com/server-icon.png",
MIMEType: "image/png",
Sizes: []string{"48x48"},
},
),
)服务端配置
能力
能力告诉客户端你的服务端支持哪些功能:
go
// 启用特定能力
s := server.NewMCPServer(
"Specialized Server",
"1.0.0",
server.WithToolCapabilities(true), // 可以执行工具
server.WithResourceCapabilities(true, true), // 可以提供资源
server.WithPromptCapabilities(true), // 可以提供提示词
)
// 或启用所有能力
s := server.NewMCPServer(
"Full-Featured Server",
"1.0.0",
server.WithToolCapabilities(true),
server.WithResourceCapabilities(true, true),
server.WithPromptCapabilities(true),
)能力类型:
- 工具:服务端可以执行来自 LLM 的函数调用
- 资源:服务端可以向 LLM 提供数据/内容
- 提示词:服务端可以提供提示词模板
- 任务:服务端支持异步任务增强的工具执行(参见任务增强工具)
- 自动补全:服务端提供参数自动补全(参见自动补全)
- 征求意见:服务端可以请求额外的用户输入(参见征求意见)
- 根目录:服务端可以向客户端请求根目录信息
恢复中间件
添加自动 panic 恢复以防止服务端崩溃:
go
s := server.NewMCPServer(
"Robust Server",
"1.0.0",
server.WithRecovery(), // 从 panic 自动恢复
)这会捕获处理器中的 panic 并返回正确的错误响应而不是崩溃。
自定义元数据
添加额外服务端信息:
go
s := server.NewMCPServer(
"My Server",
"1.0.0",
server.WithInstructions("A server that does amazing things"),
)实现元数据
服务端的 Implementation 结构支持额外的可选字段,用于在初始化期间发送更丰富的元数据:
go
// 这些字段从 NewMCPServer 参数自动设置:
// Name string — 服务端名称
// Version string — 服务端版本
//
// mcp.Implementation 上的其他可选字段:
// Title string — 人类可读的显示标题
// Description string — 服务端简要描述
// WebsiteURL string — 服务端网站或文档的 URL
// Icons []Icon — 实现的视觉标识符你可以通过服务端选项设置这些:
go
s := server.NewMCPServer(
"My Server",
"1.0.0",
server.WithTitle("My Server"), // 人类可读的显示标题
server.WithDescription("A server that does amazing things"), // 简要描述
server.WithWebsiteURL("https://example.com"), // 网站或文档 URL
server.WithIcons( // 视觉标识符
mcp.Icon{
Src: "https://example.com/icon.png",
MIMEType: "image/png",
Sizes: []string{"48x48"},
},
),
)扩展 vs 实验性能力
服务端可以通告两种非标准能力:
- 扩展(
ServerCapabilities.Extensions)—— 用于通告已知扩展支持的标准化扩展点 - 实验性(
ServerCapabilities.Experimental)—— 非标准、实验性能力
go
s := server.NewMCPServer("My Server", "1.0.0",
// 设置实验性能力
server.WithExperimental(map[string]any{
"claude/channel": map[string]any{
"supported": true,
},
}),
)两个字段都是 map[string]any,并在初始化期间包含在服务端的能力中。相同的 Extensions 字段在 ClientCapabilities 上可用,客户端可以用它通告扩展支持。
启动服务端
MCP-Go 支持多种传输方式以适应不同的部署场景。
Stdio 传输
标准输入/输出 - 最常用于本地工具:
go
func main() {
s := server.NewMCPServer("My Server", "1.0.0")
// 启动 stdio 服务端(阻塞直到终止)
if err := server.ServeStdio(s); err != nil {
log.Fatal(err)
}
}适用于:
- 本地开发工具
- CLI 集成
- 桌面应用程序
- 单客户端场景
HTTP 传输
传统 HTTP 请求/响应:
go
func main() {
s := server.NewMCPServer("HTTP Server", "1.0.0")
// 创建 HTTP 服务端
httpServer := server.NewStreamableHTTPServer(s)
// 在端口 8080 启动 HTTP 服务端
if err := httpServer.Start(":8080"); err != nil {
log.Fatal(err)
}
}适用于:
- Web 服务
- 负载均衡部署
- REST 风格 API
- 缓存场景
Server-Sent Events (SSE)
基于 HTTP 的流式传输,用于实时更新:
go
func main() {
s := server.NewMCPServer("SSE Server", "1.0.0")
// 创建 SSE 服务端
sseServer := server.NewSSEServer(s)
// 在端口 8080 启动 SSE 服务端
if err := sseServer.Start(":8080"); err != nil {
log.Fatal(err)
}
}适用于:
- Web 应用程序
- 实时通知
- 多个并发客户端
- 基于浏览器的工具
自定义传输选项
配置传输特定选项:
go
// 带自定义选项的 HTTP
httpServer := server.NewStreamableHTTPServer(s,
server.WithEndpointPath("/mcp"),
server.WithStateLess(true),
server.WithTLSCert("/path/to/cert.pem", "/path/to/key.pem"),
)
if err := httpServer.Start(":8080"); err != nil {
log.Fatal(err)
}
// 带自定义选项的 SSE
sseServer := server.NewSSEServer(s,
server.WithSSEEndpoint("/events"),
server.WithMessageEndpoint("/message"),
server.WithKeepAlive(true),
)
if err := sseServer.Start(":8080"); err != nil {
log.Fatal(err)
}基于环境的配置
根据环境变量配置服务端:
go
func main() {
s := server.NewMCPServer("Configurable Server", "1.0.0")
// 根据环境选择传输
transport := os.Getenv("MCP_TRANSPORT")
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
switch transport {
case "http":
httpServer := server.NewStreamableHTTPServer(s)
httpServer.Start(":"+port)
case "sse":
sseServer := server.NewSSEServer(s)
sseServer.Start(":"+port)
default:
server.ServeStdio(s)
}
}
}服务端生命周期
理解服务端生命周期有助于正确的资源管理:
go
func main() {
hooks := &server.Hooks{}
// 添加会话生命周期钩子
hooks.AddOnRegisterSession(func(ctx context.Context, session server.ClientSession) {
log.Printf("Client %s connected", session.ID())
})
hooks.AddOnUnregisterSession(func(ctx context.Context, session server.ClientSession) {
log.Printf("Client %s disconnected", session.ID())
})
// 添加请求钩子
hooks.AddBeforeAny(func(ctx context.Context, id any, method mcp.MCPMethod, message any) {
log.Printf("Processing %s request", method)
})
hooks.AddOnError(func(ctx context.Context, id any, method mcp.MCPMethod, message any, err error) {
log.Printf("Error in %s: %v", method, err)
})
s := server.NewMCPServer("Lifecycle Server", "1.0.0",
server.WithHooks(hooks),
)
// 优雅关闭
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
log.Println("Shutting down server...")
s.Shutdown()
}()
server.ServeStdio(s)
}错误处理
正确的错误处理确保服务端健壮运行:
go
func main() {
s := server.NewMCPServer("Error-Safe Server", "1.0.0",
server.WithRecovery(), // Panic 恢复
)
// 添加服务端启动的错误处理
if err := server.ServeStdio(s); err != nil {
if errors.Is(err, server.ErrServerClosed) {
log.Println("Server closed gracefully")
} else {
log.Fatalf("Server error: %v", err)
}
}
}下一步
现在你了解了服务端基础,学习如何添加功能:

