背景

随着 AI 领域中 USB 协议 —— MCP 协议的火爆,越来越多的人希望体验这一协议,但往往由于需要本地部署而止步。我们可通过集成 MCP 服务,在 API 调用中实现“开罐即用”,免去本地部署的繁琐步骤。接下来,将详细说明如何实现该集成。


API 调用示例

在标准的 OpenAI API 调用方式基础上,新增最外层的 mcps 字段(标准接口会忽略无效字段,仅在我们的服务中生效),每个 MCP 协议工具对应一个 name 字段,该字段必须与 MCP SERVER 中对应工具的 Name 保持一致。

示例 1:使用时间工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
curl --location 'http://localhost:8094/api/v1/chat-with-mcp' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer sk-xxxx' \
--data '{
"model": "deepseek-v3-tool",
"stream": true,
"messages": [
{
"role": "user",
"content": "东京时间几点了"
}
],
"max_tokens": 2048,
"temperature": 1,
"mcps": [
{
"name": "time"
}
]
}'

调用后,通过时间工具获取当前东京时间,返回结果示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"id": "chatcmpl-68d11dee3f3a25431297ea9b8b715002",
"object": "chat.completion",
"created": 1744182433,
"model": "deepseek-v3-tool",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "当前东京时间是 2025年4月9日 16:07(日本标准时间)。"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 0,
"completion_tokens": 0,
"total_tokens": 0
}
}

MCP 协议的工具说明

MCP 协议本质上是对某个专项服务的 tools 包装,使之具备通用性和灵活性。下面分别介绍两种常见场景所提供的 tools 列表。

获取时间工具

  • get_current_time
    获取指定时区的当前时间

  • convert_time
    实现不同时区之间时间的转换

QINIU 云存储工具

  • ListBuckets
    返回当前认证用户拥有的所有 bucket 列表。使用此操作需要具有 s3:ListAllMyBuckets 权限。

  • ListObjectsV2
    每次请求返回 bucket 中部分或全部(最多 100 个)对象。可通过设置参数选择性返回。如果需要继续列出对象,请设置 start_after 为上一次返回结果中最后一个文件的 key。

  • GetObject
    用于从 Amazon S3 检索对象。需要在请求中指定对象的完整 key 名称。支持通用和目录 bucket 的虚拟托管请求。注意:目录 bucket 只支持虚拟托管方式,并需通过 Zonal endpoint 发出请求。


集成 MCP 协议示例

我们采用了 MCP-GOEino 两个开源项目来实现 MCP 服务集成。下面给出具体实现过程。

1. 启动 MCP 服务

假设已经通过如下命令启动 MCP 服务(该命令也适用于其它服务如 npm、uv 等):

1
docker run -it --rm mcp/time

2. 创建 MCP 客户端

通过以下代码启动 MCP 服务客户端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import (
"context"
mcpeino "github.com/cloudwego/eino-ext/components/tool/mcp"
client "github.com/mark3labs/mcp-go/client"
)

func McpClient(ctx context.Context, command string, envs []string, args ...string) (client.MCPClient, error) {
cli, err := client.NewStdioMCPClient(command, envs, args...)
if err != nil {
return nil, fmt.Errorf("failed to create client: %v", err)
}
_, err = cli.Initialize(ctx, mcp.InitializeRequest{})
if err != nil {
return nil, fmt.Errorf("failed to initialize client: %v", err)
}
return cli, nil
}

通过如下调用启动 MCP 服务:

1
2
3
4
5
6
cli, err := McpClient(
ctx,
mcpConfig.Command,
mcp.Env, // 使用用户配置的环境变量
mcpConfig.Args...,
)

3. 获取 MCP 服务中的 tools

使用以下代码获取服务中注册的 tools:

1
tools, err := mcpeino.GetTools(ctx, &mcpeino.Config{Cli: cli})

4. 集成 Agent 实现 API 调用

通过 Eino 平台,实现与 MCP 服务的对接,示例代码如下:

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
package xxx

import (
"chat/globals"
"context"
"errors"
"io"

"github.com/cloudwego/eino-ext/components/model/openai"
"github.com/cloudwego/eino/flow/agent/react"
"github.com/cloudwego/eino/schema"
)

func createAgentRequest(props *adaptercommon.AgentProps) error {
ctx := context.Background()
endpoint := "xxxx"
config := &openai.ChatModelConfig{
Model: props.Model,
APIKey: conf.GetRandomSecret(),
BaseURL: endpoint,
}
llm, err := openai.NewChatModel(ctx, config)
if err != nil {
return err
}
agent, err := react.NewAgent(ctx, &react.AgentConfig{
Model: llm,
ToolsConfig: props.EinoTools,
})
if err != nil {
return err
}

message, err := getMessage(props)
if err != nil {
return err
}
stream, err := agent.Stream(ctx, message)
if err != nil {
return err
}
defer stream.Close()

for {
response, err := stream.Recv()
if errors.Is(err, io.EOF) {
break
}
fmt.Println(response.Content)
}

return nil
}

func getMessage(props *adaptercommon.AgentProps) ([]*schema.Message, error) {
var message []*schema.Message
for _, msg := range props.Message {
message = append(message, &schema.Message{
Role: schema.RoleType(msg.Role),
Content: msg.Content,
})
}
return message, nil
}

通过以上步骤,即可实现 MCP 服务的云端集成,从而避免本地部署带来的复杂性。