AI Agent MCP 概念
Model Context Protocol,简称MCP,简单来说,它就是给AI大模型装了一个“万能接口”——让AI模型能够与不同的数据源和工具进行无缝交互。这就好比USB-C接口,提供了一种标准化的方法,把AI模型连接到各种数据源和工具上,不用再为每个设备单独配一根线。
MCP的目标很明确:替换掉那些碎片化的Agent代码集成,让AI系统更可靠、更高效。通过建立通用标准,服务商可以基于这个协议释放自己的AI能力,开发者也能更快地构建强大的AI应用,而不用重复造轮子。借助开源项目,一个强大的AI Agent生态正在快速成形。
更重要的是,MCP可以在不同的应用或服务之间保持上下文,从而增强整体自主执行任务的能力。它的工作流程可以概括为五个步骤:
- 连接:MCP主机连接到一个或多个MCP服务器。
- 请求:主机发送请求,获取数据或执行工具。
- 处理:服务器处理请求,访问相关数据源或外部服务。
- 返回:服务器将结果返回给主机。
- 生成响应:主机将信息提供给AI模型,用于生成用户响应。
MCP 存在的合理性
为什么AI会需要MCP这样的东西?答案其实很直白:
- 统一工具调用协议:MCP通过标准化的通信格式(如JSON-RPC),彻底解决了AI工具调用中的接口碎片化问题。开发者只需实现一次MCP接口,AI模型就能与所有支持该协议的工具交互。
- 提升开发效率:传统模式下,每个工具都需要单独编写连接代码,而MCP通过统一的协议,大幅降低了开发成本和复杂性。
- 支持动态工具加载:MCP允许AI动态发现和调用工具,扩展了AI的能力边界。比如,AI可以通过MCP调用实时天气API或企业内部数据库,完成复杂任务。
- 跨平台兼容性:MCP兼容多种主流大模型(如GPT、Claude等),被称为AI领域的“USB-C接口”,实现了“一次开发,全平台通用”的目标。
MCP 的时代局限性
虽然MCP的出现定义了一个应用开放给AI Agent链接的接口标准,但技术迭代总是很快,这套方案也逐渐暴露了一些不足。
问题出在每次对话开始前,MCP会把所有API方法的结构定义声明一股脑提供给Agent读取。也就是说,还没正式聊天,就已经消耗了一部分token和上下文。而且,随着安装和启用的MCP工具越来越多,这种消耗还会逐步加重。
正因为如此,现在已经有了一种新的AI Agent调用API的方式:CLI + Skill 的组合。关于这部分内容,下一篇AI提效系列文章会详细展开。
AI Agent MCP 的应用
TAPD 的应用
现代化的迭代项目,大多会使用TAPD来管理需求、缺陷等。如果能接入TAPD的MCP,让Agent接管手动操作,效率会提升不少。
从TAPD官方MCP的使用文档来看,它支持两种授权登录形式:用户密码登录和TOKEN授权。这里直接使用token授权的方式接入。
TAPD的个人Token获取路径:www.tapd.cn/personal_se…(注意:保存好个人token,刷新后就不会再明文显示,丢失只能重新创建)。
TAPD MCP配置参考:cloud.tencent.com/developer/m…。如果前面已经获取了TAPD的个人token,这里只需要填写TAPD_ACCESS_TOKEN这个配置项。
"mcp-server-tapd": {
"command": "uvx",
"args": ["mcp-server-tapd"],
"env": {
"TAPD_ACCESS_TOKEN": "TAPD 个人 Token",
"TAPD_API_USER": "",
"TAPD_API_PASSWORD": "",
"TAPD_API_BASE_URL": "https://api.tapd.cn",
"TAPD_BASE_URL": "https://www.tapd.cn",
"BOT_URL": ""
}
}
配置好之后,就可以通过AI直接进行TAPD需求的读写、迭代和开发任务的编排,甚至还能实现缺陷的流转和测试甩锅操作。
文档的读取与编写
开发迭代中,文档打交道是家常便饭——整理知识、写需求文档、方案文档……如果能通过AI Agent直接读取和编辑文档,那就能解放双手,加快输出速度,甚至加大输出量。
为什么选用飞书?原因很简单:免费,而且社区已经有现成的解决方案。语雀和腾讯文档理论上也可行,但它们的开放API需要充值账户。
飞书API的前置准备工作比较复杂,但飞书开放API能做的事情非常多,值得研究:
- 进入飞书开放平台
open.feishu.cn/注册登录。 - 创建企业应用(可以不用发布)。
- 点击进入创建的企业应用,拷贝AppID和AppSecret两个信息。
- 获取应用的token。有两种token:
t类型的(使用企业应用权限)和u类型的(使用当前授权用户权限)。推荐使用u类型的token接入MCP,因为它的权限更贴近实际用户。
飞书lark MCP配置参考:open.feishu.cn/document/mc…。配置示例如下:
"lark-mcp-server": {
"command": "npx",
"args": ["-y", "@larksuiteoapi/lark-mcp", "mcp", "-a", "" , "-s", "" , "-u", "" ]
}
接入飞书MCP后,能玩的操作就非常多了。比如,通过AI Agent的Plan模式构思好需求开发逻辑后,直接输出到飞书文档上形成需求开发方案(至于要不要拿这个方案去糊弄上级,就自己决定了)。还能直接丢一个飞书文档,让AI Agent通过飞书MCP读取内容,然后根据内容进行各种操作。
自动化测试
作为开发,即使有专门的测试人员,每次迭代开发完成后也得进行自测(冒烟测试)。那么,能不能让AI操作浏览器,通过自然语言描述下达指令,让AI操纵浏览器完成测试?甚至让测试人员直接写自然语言描述的测试路径,实现AI自动化测试?答案是肯定的——chrome-devtools这个MCP就是谷歌浏览器专门提供给AI使用的。
关于使用浏览器MCP实现AI自动化测试,实际体验下来,优缺点都很明显:
优点:如果已经有描述比较完善的测试路径,可以解放双手,交给AI Agent执行。一个非常重要的点是——可以完成上级派发的技术KPI,落地AI自动化测试,听起来就很能吹。
缺点:开发自己点击几下,可能比慢慢敲一大堆文字再交给AI Agent执行快多了。时间紧迫的时候,你会嫌弃一个点击只需要一两秒,而AI需要慢悠悠地扫页面、找点击位置、再触发操作。
首先需要启动debug模式的Chrome,在命令行执行对应的命令:
/Applications/Google Chrome.app/Contents/MacOS/Google Chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-mcp
Chrome DevTools MCP配置参考:github.com/ChromeDevTo…。配置如下:
"chrome-devtools-mcp-server": {
"command": "npx",
"args": ["-y", "chrome-devtools-mcp@latest"]
}
之后,就可以通过自然语言描述让AI Agent操作浏览器进行网页点击等操作,从而根据文档中预设的测试用例来验证开发质量。
代码管理
开发完代码,自然要提交。这里有一个git MCP,可以让AI Agent对代码进行操作。
git-mcp配置参考:github.com/github/gith…。配置示例:
"git-mcp-server": {
"command": "npx",
"args": ["@cyanheads/git-mcp-server"],
"env": {
"GIT_SIGN_COMMITS": "false",
"MCP_LOG_LEVEL": "info"
}
}
配置后,在AI Agent模式下输入指令:“通过文件的修改来生成符合commitlint格式的提交信息,并且自动进行提交和推送远程仓库”,AI就会自行通过MCP自动操作。
推送到远程库之后,就可以进行代码的create merge request操作。这里使用第三方MCP库(github.com/zereight/gi…),如果自己搭建了GitLab服务,GITLAB_API_URL参数要填自己的部署地址。
"gitlab-mcp-server": {
"command": "npx",
"args": ["-y", "@zereight/mcp-gitlab"],
"env": {
"GITLAB_API_URL": "https:///api/v4/mcp" ,
"GITLAB_PERSONAL_ACCESS_TOKEN": "your_gitlab_token",
"GITLAB_READ_ONLY_MODE": "false",
"USE_GITLAB_WIKI": "false",
"USE_MILESTONE": "false",
"USE_PIPELINE": "false"
}
}
配置后,在AI Agent模式下可以下达指令让它自动创建MR,甚至进行合并操作。
以上这些,是作为前端开发者在日常工作中比较常用的MCP服务,能有效优化开发工作流。不过要注意,MCP的接入和使用会加速消耗AI模型的token,需要留意账号的token消耗量。
AI Agent MCP 的自定义编写
MCP可以使用各种编程语言编写,作为前端开发者,自然优先选择Node.js。
官方MCP文档:github.com/modelcontex…
TypeScript语言版本:ts.sdk.modelcontextprotocol.io/
基础概念
先来了解一些MCP的基础概念。
@modelcontextprotocol/sdk
这是官方提供的MCP Server SDK,用于管理和操作模型上下文。它提供API和工具,帮助开发者处理模型的状态、参数和输入输出,支持模型的初始化、配置和状态管理。
通过该SDK提供的Server和StdioServerTransport启动服务。模型通过stdio通信通道与这个服务交互,这是AI模型与MCP的其中一种通讯方式。
const { Server } = require('@modelcontextprotocol/sdk/server/index.js');
const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
const server = new Server({
name: 'mcp-server',
version: '1.0.0',
}, {
capabilities: {
tools: {},
},
});
const transport = new StdioServerTransport();
server.connect(transport);
ListToolsRequestSchema
当AI模型与MCP建立连接时,会请求询问这个MCP能提供什么工具或方法调用。此时就会调用ListToolsRequestSchema,获取对应的MCP Server中定义的可用工具列表。
TOOLS是一个数组,包含所有工具方法的定义,每个工具方法的结构如下:
| 字段 | 类型 | 说明 |
|---|---|---|
name | string | 工具名称 |
description | string | 工具描述 |
inputSchema | object | JSON Schema 格式的参数定义 |
inputSchema是对方法参数的描述,具体结构如下:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | 是 | 固定值为字符串 'object' |
properties | Record | 是 | 调用方法时传入的参数数据结构描述 |
required | Array | 否 | 调用方法时必传的 properties 中的参数 |
properties内的对象是调用方法时传入的参数数据结构描述,结构如下:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | 是 | 参数类型字符串描述 |
description | string | 否 | 参数描述 |
const { ListToolsRequestSchema } = require('@modelcontextprotocol/sdk/types.js');
const TOOLS = [
{
name: 'get_current_user',
description: '获取当前 GitLab 用户信息',
inputSchema: {
type: 'object',
properties: {}
}
},
{
name: 'get_project_ids',
description: '搜索项目并获取项目 ID 映射',
inputSchema: {
type: 'object',
properties: {
projectName: {
type: 'string',
description: '项目名称'
}
},
required: ['projectName']
}
},
// ...
];
server.setRequestHandler(ListToolsRequestSchema, async () => {
return { tools: TOOLS };
});
CallToolRequestSchema
当AI模型触发MCP工具的调用时,会触发CallToolRequestSchema,传递一个结构化的调用参数。MCP Server需要根据这个参数进行相应的处理。
const { CallToolRequestSchema } = require('@modelcontextprotocol/sdk/types.js');
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
// 根据 name 调用对应的业务逻辑
});
实战例子:gitlab-mcp-server
有了上面的基础知识,现在尝试写一个操作GitLab的MCP。可能有人会问:前面不是已经有GitLab的MCP服务了吗(官方或第三方)?但公司使用的GitLab版本过于落后,API与现网的MCP不兼容,所以需要自己写一个。这里就进行一次真正的实战开发。
注意:这里不会实现最完整的GitLab所有操作,主要实现创建MR、合并MR以及一些必要的配套操作。文章重点在MCP服务的编写,不会详细解释GitLab MR操作的具体实现逻辑。
初始化配置项目
MCP Server的package.json文件:注意bin配置是关键,只有配置了这个,使用npx命令时才知道执行什么命令和文件。如果开发过npm包,应该不陌生。
{
"name": "@jesbrian/gitlab-mcp-server",
"version": "0.2.1",
"description": "GitLab MCP Server with Modular Configuration",
"license": "ISC",
"author": "JesBrian",
"type": "commonjs",
"main": "index.js",
"bin": {
"gitlab-mcp-server": "index.js"
},
"scripts": {
"start": "node index.js"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.27.1",
"axios": "^1.6.0"
}
}
定义相关API方法
封装配置文件Config.js,主要功能包括:服务器地址路由、授权token、超时等基本配置,以及最重要的——提供给AI Agent接入后使用的Tools信息定义。
// GitLab MCP Server 配置
const env = process.env;
const DEFAULT_CONFIG = {
gitlab: {
url: env.GITLAB_URL || env.gitlab_url,
privateToken: env.GITLAB_PRIVATE_TOKEN || env.gitlab_private_token,
},
client: {
timeout: parseInt(env.TIMEOUT) || 10000,
waitInterval: parseInt(env.WAIT_INTERVAL) || 2000,
},
server: {
name: 'gitlab-mcp-server',
version: '1.0.0',
},
};
const TOOLS = [
// ...(此处省略具体工具定义,详见完整代码)
];
module.exports = { DEFAULT_CONFIG, TOOLS };
MCP Server主执行文件index.js(注意首行必须设置#!/usr/bin/env node):
#!/usr/bin/env node
// GitLab MCP Server
const { Server } = require('@modelcontextprotocol/sdk/server/index.js');
const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
const { CallToolRequestSchema, ListToolsRequestSchema } = require('@modelcontextprotocol/sdk/types.js');
const GitLabClient = require('./lib/GitLabClient');
const { DEFAULT_CONFIG, TOOLS } = require('./config/Config');
const gitlabClient = new GitLabClient(
DEFAULT_CONFIG.gitlab.url,
DEFAULT_CONFIG.gitlab.privateToken,
DEFAULT_CONFIG.client
);
const server = new Server(DEFAULT_CONFIG.server, {
capabilities: { tools: {} },
});
server.setRequestHandler(ListToolsRequestSchema, async () => {
return { tools: TOOLS };
});
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
let result;
switch (name) {
case 'get_current_user':
result = await gitlabClient.getCurrentUser();
break;
// ... 其他 case 分支
default:
throw new Error(`未知的工具:${name}`);
}
return {
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }]
};
} catch (error) {
return {
content: [{ type: 'text', text: `错误:${error.message}` }],
isError: true
};
}
});
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.info('GitLab MCP Server 已启动');
}
main().catch(error => {
console.error('服务器启动失败:', error);
process.exit(1);
});
具体操作逻辑
封装GitLab操作文件GitLabClient.js,这里不逐一展开每个方法,感兴趣的可以自行研究。
const axios = require('axios');
class GitLabClient {
constructor(gitlabUrl, privateToken, options = {}) {
this.gitlabUrl = gitlabUrl;
this.privateToken = privateToken;
this.timeout = options.timeout || 10000;
this.waitInterval = options.waitInterval || 2000;
this.client = axios.create({
baseURL: this.gitlabUrl,
headers: {
'PRIVATE-TOKEN': this.privateToken,
'Content-Type': 'application/json'
},
timeout: this.timeout
});
this.client.interceptors.response.use(
response => response,
error => {
const message = error.response?.data?.message || error.message;
console.error(`[GitLab API 错误] ${error.config?.method?.toUpperCase()} ${error.config?.url}: ${message}`);
throw error;
}
);
}
// 具体方法省略,详见完整代码
}
module.exports = GitLabClient;
接入使用
完成自定义MCP Server后,可以发布到npm仓库,也可以配置本地启动。如果只是想自己使用,可以配置本地启动:
{
"mcpServers": {
"gitlab-mpc-server": {
"command": "npx",
"args": ["@jesbrian/gitlab-mcp-server"],
"env": {
"GITLAB_URL": "https://your-gitlab-url.com",
"GITLAB_PRIVATE_TOKEN": "your-private-token"
}
}
}
}
如果推送到npm仓库,则可以通过npx远程启动。这里回收前面的package.json中的bin命令和#!/usr/bin/env node的作用。这个MCP Server已推送到npm仓库:www.npmjs.com/package/@je…
{
"mcpServers": {
"gitlab-mcp-server": {
"command": "npx",
"args": ["@jesbrian/gitlab-mcp-server"],
"env": {
"GITLAB_URL": "https://your-gitlab-url.com",
"GITLAB_PRIVATE_TOKEN": "your-private-token"
}
}
}
}
参考资料
- 一文读懂 MCP——从起源到应用,解锁 AI 的“万能接口” :zhuanlan.zhihu.com/p/190527200
- GitHub - modelcontextprotocol/servers: Model Context Protocol Servers:github.com/modelcontex…
