《NestJS智能体开发》(七):模型上下文协议(MCP)

什么是MCP?

Model Context Protocol(MCP)是一种开放协议,旨在标准化大型语言模型(LLM)与外部数据源和工具之间的通信。它由 Anthropic 推出,允许 LLM 与服务器进行交互,以获取信息、执行操作并完成更复杂的任务。

调用外部工具

安装MCP SDK

bash 复制代码
pnpm add @modelcontextprotocol/sdk

创建MCP服务器和客户端

ts 复制代码
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";

const transport = new StdioClientTransport({
    command: "npx",
    args: [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        `${process.cwd()}/test`
    ],
    stderr: process.stderr,
});

const client = new Client(
    {
        name: "fs",
        version: "1.0.0",
    }
);
await client.connect(transport);

代码解释:

  1. new StdioClientTransport()

    • 创建一个新的 StdioClientTransport 实例,用于通过标准输入输出流(stdin/stdout)与 MCP 服务器进行通信。
  2. command: "npx"

    • 指定要运行的命令是 npx,它是 Node.js 包运行工具,用于运行安装在项目中的 npm 包的命令行工具。
  3. args

    • args 是一个数组,包含传递给命令的参数:

      • "-y":通常用于自动确认提示,避免交互式输入。
      • "@modelcontextprotocol/server-filesystem":指定要运行的 MCP 文件系统服务器包。
      • ${process.cwd()}/test:使用模板字符串插入当前工作目录下的 test 文件夹路径,作为 MCP 文件系统服务器的工作目录。
  4. stderr: process.stderr

    • 将 MCP 服务器的标准错误输出(stderr)重定向到当前 Node.js 进程的标准错误输出,以便在控制台中查看错误信息。

test目录中创建一个index.js文件,然后通过LLM调用工具读取它的内容

ts 复制代码
import { generateText, jsonSchema, tool } from "ai";

const fsTool = {
    description: "读取一个本地文件的内容",
    parameters: jsonSchema({
        type: "object",
        properties: {
            path: { type: "string", description: "文件路径" },
        },
        required: ["path"],
    }),
    execute: async (args) => {
        const result = await client.callTool({
            name: "read_file",
            arguments: args,
        });
        return JSON.stringify(result);
    },
};

const model = this.agent.createQWenModel();
const result = await generateText({
    model,
    tools: {
        fsTool
    },
    toolChoice: 'required',
    prompt: "test文件夹中index.js的内容是什么?"
});
console.log(result.toolResults);

成功调用fsTool读取了index.js的内容

json 复制代码
[
    {
      "type": "tool-result",
      "toolCallId": "call-zpJwmR2spvsUYiIppilkzHi6m0xe9aLp",
      "toolName": "fsTool",
      "args": {
        "path": "test/index.js"
      },
      "result": "{\"content\":[{\"type\":\"text\",\"text\":\"function main() {\\n    console.log('main');\\n}\"}]}"
    }
]

MCP Tool转换成AI SDK Tool

AISDK MCP Bridge 是一个桥接包,它使得模型MCPAI SDK之间能够实现无缝集成,允许MCP服务器和AI模型之间进行高效的通信和工具调用。

安装AISDK MCP Bridge

bash 复制代码
pnpm add aisdk-mcp-bridge

使用AISDK MCP Bridge我们只需创建mcp.config.json配置文件

json 复制代码
{
    "mcpServers": {
        "filesystem": {
            "command": "npx",
            "args": [
                "-y",
                "@modelcontextprotocol/server-filesystem",
                "./test"
            ]
        }
    }
}

通过桥接器自动将MCP Tool转换成AI SDK Tool

ts 复制代码
try {
    await initializeMcp({ debug: true });
    const tools = await getMcpTools({ debug: true });

    const model = this.agent.createQWenModel();
    const result = await generateText({
        model,
        tools,
        toolChoice: 'required',
        prompt: "test文件夹中index.js的内容是什么?"
    });
    console.log(result.toolResults);
} finally {
    await cleanupMcp();
}

实现了相同的效果

json 复制代码
[
  {
    "type": "tool-result",
    "toolCallId": "call-ZnX8AdWB32Pp4nT1unF5Dxpeh7AYcIo7",
    "toolName": "read_file",
    "args": {
      "path": "test/index.js"
    },
    "result": {
      "type": "function",
      "function": {
        "name": "read_file",
        "arguments": "{\"path\":\"test/index.js\"}"
      },
      "content": [
        {
          "type": "text",
          "text": "function main() {\n    console.log('main');\n}"
        }
      ]
    }
  }
]

市场中寻找可用的MCP Servers

json 复制代码
{
    "mcpServers": {
        "filesystem": {
            "command": "npx",
            "args": [
                "-y",
                "@modelcontextprotocol/server-filesystem",
                "./test"
            ]
        },
        "docker-mcp": {
            "command": "uvx",
            "args": [
                "docker-mcp"
            ]
        }
    }
}
ts 复制代码
try {
    await initializeMcp({ debug: true });
    const tools = await getMcpTools({ debug: true });

    const model = this.agent.createQWenModel();
    const result = await generateText({
        model,
        tools,
        toolChoice: 'required',
        prompt: "使用docker运行一个Nginx容器"
    });
    console.log(result.toolResults);
} finally {
    await cleanupMcp();
}
json 复制代码
[
  {
    "type": "tool-result",
    "toolCallId": "call-RkyU2khsEoXlXVq6C5SH4DNw3CrCaQCu",
    "toolName": "create-container",
    "args": {
      "image": "nginx",
      "name": "nginx_container"
    },
    "result": {
      "type": "function",
      "function": {
        "name": "create-container",
        "arguments": "{\"image\":\"nginx\",\"name\":\"nginx_container\"}"
      },
      "content": [
        {
          "type": "text",
          "text": "Created container 'nginx_container' (ID: b6bb7f0fa3a924f3d86b49de90561f3d0bff2172b49b42594bde0703948df269)"
        }
      ]
    }
  }
]

成功运行了一个Nginx容器

总结

MCP 协议为 LLM 与外部工具和数据源的集成提供了标准化、高效且安全的解决方案,通过 MCP SDK 和 AISDK MCP Bridge 等工具,可以方便地创建和调用各种 MCP 服务器,实现 LLM 在不同场景下的应用扩展,如文件操作、容器管理等,为智能体的开发和集成带来了新的可能性和便利性。

相关推荐
美酒没故事°8 小时前
Open WebUI安装指南。搭建自己的自托管 AI 平台
人工智能·windows·ai
涡能增压发动积8 小时前
同样的代码循环 10次正常 循环 100次就抛异常?自定义 Comparator 的 bug 让我丢尽颜面
后端
云烟成雨TD8 小时前
Spring AI Alibaba 1.x 系列【6】ReactAgent 同步执行 & 流式执行
java·人工智能·spring
Wenweno0o8 小时前
0基础Go语言Eino框架智能体实战-chatModel
开发语言·后端·golang
于慨8 小时前
Lambda 表达式、方法引用(Method Reference)语法
java·前端·servlet
石小石Orz8 小时前
油猴脚本实现生产环境加载本地qiankun子应用
前端·架构
swg3213218 小时前
Spring Boot 3.X Oauth2 认证服务与资源服务
java·spring boot·后端
从前慢丶8 小时前
前端交互规范(Web 端)
前端
tyung8 小时前
一个 main.go 搞定协作白板:你画一笔,全世界都看见
后端·go
AI攻城狮8 小时前
用 Obsidian CLI + LLM 构建本地 RAG:让你的笔记真正「活」起来
人工智能·云原生·aigc