前言

官方sdk仓库:https://github.com/modelcontextprotocol/go-sdk

环境准备

创建工作目录:mcp-server

1
2
3
4
5
# 创建&进入工作目录
mkdir mcp-server && cd mcp-server

# 初始化go mod
go mod init mcp-server

Mcp demo

测试-stdio(本地)测试

将下面的代码保存为main.go文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package main

import (
"context"
"fmt"
"log"
"strings"

"github.com/modelcontextprotocol/go-sdk/mcp"
)

// AddArgs 定义加法工具的输入参数
type AddArgs struct {
A int `json:"a"`
B int `json:"b"`
}

func main() {
// 创建 MCP 服务器
s := mcp.NewServer("Demo", "1.0.0", nil)

// 添加加法工具
addTool := mcp.NewServerTool(
"add",
"Add two numbers",
func(ctx context.Context, ss *mcp.ServerSession, params *mcp.CallToolParamsFor[AddArgs]) (*mcp.CallToolResultFor[int], error) {
sum := params.Arguments.A + params.Arguments.B
return &mcp.CallToolResultFor[int]{
Content: []mcp.Content{&mcp.TextContent{Text: fmt.Sprintf("%d", sum)}},
}, nil
},
)
s.AddTools(addTool)

// 添加动态问候资源模板
greetingTemplate := &mcp.ServerResourceTemplate{
ResourceTemplate: &mcp.ResourceTemplate{
URITemplate: "greeting://{name}",
MIMEType: "text/plain",
},
Handler: func(ctx context.Context, ss *mcp.ServerSession, params *mcp.ReadResourceParams) (*mcp.ReadResourceResult, error) {
// 从 URI 中提取 name 参数
name := strings.TrimPrefix(params.URI, "greeting://")
greeting := fmt.Sprintf("Hello, %s!", name)

return &mcp.ReadResourceResult{
Contents: []*mcp.ResourceContents{
{
URI: params.URI,
MIMEType: "text/plain",
Text: greeting,
},
},
}, nil
},
}
s.AddResourceTemplates(greetingTemplate)

// Run the server over stdin/stdout, until the client disconnects
if err := s.Run(context.Background(), mcp.NewStdioTransport()); err != nil {
log.Fatal(err)
}
}

将go代码编译成可执行二进制文件:

1
go build -o mcp-server main.go

执行下面的命令启动mcp inspector:

1
npx @modelcontextprotocol/inspector

会有类似的输出:

1
2
3
4
5
6
7
8
9
Starting MCP inspector...
⚙️ Proxy server listening on 127.0.0.1:6277
🔑 Session token: f53ad695ef69e8b0dce5c340ba7515ef5cad6eeb71938cdedeaaf37a01862166
Use this token to authenticate requests or set DANGEROUSLY_OMIT_AUTH=true to disable auth

🔗 Open inspector with token pre-filled:
http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=5191d3a4eec39eb2c355275d0b0152624b61e518f5224b02bcb27e198ea51040#resources

🔍 MCP Inspector is up and running at http://127.0.0.1:6274 🚀

根据提示在前端访问:http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=5191d3a4eec39eb2c355275d0b0152624b61e518f5224b02bcb27e198ea51040#resources

前端需设置的参数:

  • Transport Type:STDIO
  • Command参数:./mcp-server
  • Arguments参数:–directory /Users/king/workspace-test/mcp-server

这里的mcp-server就是上面编译出来的可执行二进制文件

img_11.png

测试:

img_12.png

img_13.png

测试-sse(远程)测试

将下面的代码保存为main.go文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package main

import (
"context"
"fmt"
"log"
"net/http"
"strings"

"github.com/modelcontextprotocol/go-sdk/mcp"
)

// AddArgs 定义加法工具的输入参数
type AddArgs struct {
A int `json:"a"`
B int `json:"b"`
}

func main() {
// 创建 MCP 服务器
s := mcp.NewServer("Demo", "1.0.0", nil)
// 添加加法工具
addTool := mcp.NewServerTool(
"add",
"Add two numbers",
func(ctx context.Context, ss *mcp.ServerSession, params *mcp.CallToolParamsFor[AddArgs]) (*mcp.CallToolResultFor[int], error) {
sum := params.Arguments.A + params.Arguments.B
return &mcp.CallToolResultFor[int]{
Content: []mcp.Content{&mcp.TextContent{Text: fmt.Sprintf("%d", sum)}},
}, nil
},
)
s.AddTools(addTool)

// 添加动态问候资源模板
greetingTemplate := &mcp.ServerResourceTemplate{
ResourceTemplate: &mcp.ResourceTemplate{
URITemplate: "greeting://{name}",
MIMEType: "text/plain",
},
Handler: func(ctx context.Context, ss *mcp.ServerSession, params *mcp.ReadResourceParams) (*mcp.ReadResourceResult, error) {
// 从 URI 中提取 name 参数
name := strings.TrimPrefix(params.URI, "greeting://")
greeting := fmt.Sprintf("Hello, %s!", name)

return &mcp.ReadResourceResult{
Contents: []*mcp.ResourceContents{
{
URI: params.URI,
MIMEType: "text/plain",
Text: greeting,
},
},
}, nil
},
}
s.AddResourceTemplates(greetingTemplate)

// 启动服务器
// 创建SSE处理器
sseHandler := mcp.NewSSEHandler(func(request *http.Request) *mcp.Server {
return s
})

// 设置HTTP路由
http.Handle("/sse", sseHandler)

// 启动HTTP服务器
log.Println("Starting MCP server on :8000...")
if err := http.ListenAndServe(":8000", nil); err != nil {
log.Fatalf("HTTP server failed: %v", err)
}
}

执行下面的命令启动mcp inspector:

1
npx @modelcontextprotocol/inspector

会有类似的输出:

1
2
3
4
5
6
7
8
9
Starting MCP inspector...
⚙️ Proxy server listening on 127.0.0.1:6277
🔑 Session token: 6b62eff25370b4bc483516c39e58fa9c25f37c2ecdbabad4ade0ca1d81683687
Use this token to authenticate requests or set DANGEROUSLY_OMIT_AUTH=true to disable auth

🔗 Open inspector with token pre-filled:
http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=6b62eff25370b4bc483516c39e58fa9c25f37c2ecdbabad4ade0ca1d81683687

🔍 MCP Inspector is up and running at http://127.0.0.1:6274 🚀

根据提示在前端访问:http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=5191d3a4eec39eb2c355275d0b0152624b61e518f5224b02bcb27e198ea51040#resources

前端需设置的参数:

此处的8000端口根据实际情况修改

img_14.png

img_15.png

测试:

img_16.png

img_17.png

测试-streamable http

将下面的代码保存为main.go文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package main

import (
"context"
"fmt"
"log"
"net/http"
"strings"

"github.com/modelcontextprotocol/go-sdk/mcp"
)

// AddArgs 定义加法工具的输入参数
type AddArgs struct {
A int `json:"a"`
B int `json:"b"`
}

func main() {
// 创建 MCP 服务器
s := mcp.NewServer("Demo", "1.0.0", nil)
// 添加加法工具
addTool := mcp.NewServerTool(
"add",
"Add two numbers",
func(ctx context.Context, ss *mcp.ServerSession, params *mcp.CallToolParamsFor[AddArgs]) (*mcp.CallToolResultFor[int], error) {
sum := params.Arguments.A + params.Arguments.B
return &mcp.CallToolResultFor[int]{
Content: []mcp.Content{&mcp.TextContent{Text: fmt.Sprintf("%d", sum)}},
}, nil
},
)
s.AddTools(addTool)

// 添加动态问候资源模板
greetingTemplate := &mcp.ServerResourceTemplate{
ResourceTemplate: &mcp.ResourceTemplate{
URITemplate: "greeting://{name}",
MIMEType: "text/plain",
},
Handler: func(ctx context.Context, ss *mcp.ServerSession, params *mcp.ReadResourceParams) (*mcp.ReadResourceResult, error) {
// 从 URI 中提取 name 参数
name := strings.TrimPrefix(params.URI, "greeting://")
greeting := fmt.Sprintf("Hello, %s!", name)

return &mcp.ReadResourceResult{
Contents: []*mcp.ResourceContents{
{
URI: params.URI,
MIMEType: "text/plain",
Text: greeting,
},
},
}, nil
},
}
s.AddResourceTemplates(greetingTemplate)

// 启动服务器
// 创建SSE处理器
sseHandler := mcp.NewStreamableHTTPHandler(func(request *http.Request) *mcp.Server {
return s
}, nil)

// 设置HTTP路由
http.Handle("/mcp", sseHandler)

// 启动HTTP服务器
log.Println("Starting MCP server on :8000...")
if err := http.ListenAndServe(":8000", nil); err != nil {
log.Fatalf("HTTP server failed: %v", err)
}
}

并将脚本运行起来!

执行下面的命令启动mcp inspector:

1
npx @modelcontextprotocol/inspector

会有类似的输出:

1
2
3
4
5
6
7
8
9
Starting MCP inspector...
⚙️ Proxy server listening on 127.0.0.1:6277
🔑 Session token: 6b62eff25370b4bc483516c39e58fa9c25f37c2ecdbabad4ade0ca1d81683687
Use this token to authenticate requests or set DANGEROUSLY_OMIT_AUTH=true to disable auth

🔗 Open inspector with token pre-filled:
http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=6b62eff25370b4bc483516c39e58fa9c25f37c2ecdbabad4ade0ca1d81683687

🔍 MCP Inspector is up and running at http://127.0.0.1:6274 🚀

根据提示在前端访问:http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=5191d3a4eec39eb2c355275d0b0152624b61e518f5224b02bcb27e198ea51040#resources

前端需设置的参数:

此处的8000端口根据实际情况修改

img_18.png

img_19.png

测试:

img_20.png

img_21.png