ai agent---mcp知识汇总
ai agent---mcpç¥è¯æ±æ»
snowæ¥äº 2026-08-22 18 é 读3åéä¸.agentå®ä¹èªå·±çå·¥å ·ï¼å¹¶ç»å®ä»ï¼æ§è¡ä»ã
//å®ä¹å¤§æ¨¡å
const model = new ChatOpenAI({
modelName: process.env.MODEL_NAME,
apiKey: process.env.OPENAI_API_KEY,
temperature: 0,
configuration: {
baseURL: process.env.OPENAI_BASE_URL
}
})
//å¼å
¥å·¥å
·
const tools = [
readFileTool,
writeTool,
executeCommandTool,
listDirectoryTool
]
//大模åç»å®å·¥å
·
const modelWithTool = model.bindTools(tools);
const messages=[
new SystemMessage(`
ä½ æ¯ä¸ä¸ªé¡¹ç®ç®¡ç婿ï¼ä½¿ç¨å·¥å
·å®æä»»å¡ï¼ããã
`),
new HumanMessage('ä½ å¸®æå¹²ä¸ªå¥å¢')
]
//ç»å®å·¥å
·åçå¤§æ¨¡åæ§è¡message
const response = await modelWithTool.invoke(messages);
//çä¸ä¸éè¦æ§è¡åªä¸ªå·¥å
·
for(const toolCall of response.tool_calls){
const foundTool = tools.find(t=>t.name===toolCall.name);
if(foundTool){
// è¿æ¯âè°ç¨å¤§è¯è¨æ¨¡åï¼LLMï¼âï¼å¯¹åºAgentçãæè/å³çãç¯èï¼
const toolResult = await foundTool.invoke(toolCall.args);
messages.push(new ToolMessage({
content: toolResult,
tool_call_id: toolCall.id
}))
}
}
return messages[messages.length-1].content;
代ç é»è¾ï¼
- å®ä¹å·¥å ·ï¼ä½¿ç¨import {tool } from '@langchain/core/tools';
- å®ä¹å¤§æ¨¡åï¼import {ChatOpenAI} from '@langchain/openai';
- 大模ååå·¥å ·ç¸äºç»å®
- æ§è¡invokeï¼ï¼æ§è¡æç¤º
- 大模åéè¿response.tool_callsä»éè¦çå·¥å ·ï¼å·¥å ·æ§è¡invoke()è·åç»æã
å®ä¹å·¥å ·çåæ³ï¼
import {tool } from '@langchain/core/tools';
import fs from 'node:fs/promises';//nodeä¹åçè§èåæ³
import path from 'node:path';
import {spawn} from 'node:child_process';
import {z} from 'zod';
//1.读åæä»¶
const readFileTool = tool(
async({filePath})=>{
const content = await fs.readFile(filePath, 'utf-8');
return `æä»¶å
å®¹ï¼ ${content}`
},{
name: 'read_file',
description: '读åæä»¶',
schema: z.object({
filePath: z.string().describe('æä»¶è·¯å¾')
})
}
)
äº.å©ç¨MCPå®ä¹è¿ç¨å·¥å ·ï¼ç¶å使ç¨ä»
æå¡ç«¯ä»£ç
#!/usr/bin/env node
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import fs from "node:fs/promises";
import path from "path";
import { fileURLToPath } from "url";
import { resolve } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const dataBase = {
users: {
'001': { id: '001', name: 'å¼ ä¸', age: 30 },
'002': { id: '002', name: 'æå', age: 28 },
'003': { id: '003', name: 'çäº', age: 35 },
'004': { id: '004', name: 'èµµå
', age: 32 },
'005': { id: '005', name: 'åä¸', age: 29 },
'006': { id: '006', name: 'å¨å
«', age: 27 },
'007': { id: '007', name: 'å´ä¹', age: 31 },
'008': { id: '008', name: 'éå', age: 33 },
}
};
// â
1. å建 MCP Server
const server = new McpServer({
name: 'my-mcp-server',
version: '1.0.0',
});
server.tool(
"Query_user",
"æ¥è¯¢æ°æ®åºä¸ç¨æ·ä¿¡æ¯ï¼è¾å
¥ç¨æ·IDï¼è¿åè¯¥ç¨æ·ç详ç»ä¿¡æ¯ï¼idï¼nameï¼ageï¼",
{
userId: z.string().describe('ç¨æ· id,ä¾å¦ "001"')
},
async ({ userId }) => {
const user = dataBase.users[userId];
if (!user) {
// â
ä¸¥æ ¼æ åæ ¼å¼ï¼å¤å±æ¯å¯¹è±¡ï¼contentæ¯æ°ç»ï¼å
ç´ å¿
é¡»æ¯{type:"text", text:å符串}
return {
content: [
{
type: "text",
text: `æ¥è¯¢å¤±è´¥ï¼ç¨æ· ${userId} ä¸åå¨`
}
],
// å¯éï¼æ 记为éè¯¯ç»æï¼ä¸å½±åè¿åæ ¼å¼
isError: true
};
}
return {
content: [
{
type: "text",
text: `æ¥è¯¢æåï¼ç¨æ·ä¿¡æ¯å¦ä¸ï¼ ${JSON.stringify(user, null, 2)}`
}
]
};
}
);
// â
2. 注å Resourceï¼éç¹ï¼
server.resource(
"ä½¿ç¨æå", // resource name
"docs://guide", // è¿ä¸ªæ¯è¯»åèµæºçååï¼å¨clientçæ¶å使ç¨
async (uri) => {
const filePath = resolve(__dirname, 'docs', 'guide.md');// 读åçå®çæ¬å°guide.mdæä»¶ï¼è·¯å¾ï¼å½åèæ¬ç®å½ä¸çdocs/guide.mdï¼
let content = '';
try {
content = await fs.readFile(filePath, 'utf-8');
} catch (err) {
content = err.message;
}
return {
contents: [
{
uri: uri.href,
mimeType: "text/plain",
text: content
}
]
};
}
);
// â
4. å¯å¨ Server
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("â
MCP Resource Server is running...");
客æ·ç«¯ä»£ç
import 'dotenv/config'
import { MultiServerMCPClient } from'@langchain/mcp-adapters';
import { ChatOpenAI } from'@langchain/openai';
import chalk from'chalk';
import { HumanMessage, ToolMessage } from'@langchain/core/messages'
const model = new ChatOpenAI({
modelName:"qwen-plus",
apiKey: process.env.OPENAI_API_KEY,
configuration: {
baseURL: process.env.OPENAI_BASE_URL,
}
});
const mcpClient = new MultiServerMCPClient({
"my-mcp-server": {
command: "node",
args: ["src/mcp-test/my-mcp-server.mjs"],
cwd: process.cwd(), // 强å¶ç¨å½åç»ç«¯çå·¥ä½ç®å½ä½ä¸ºåºåï¼é¿å
è·¯å¾éä½
// å
³é®æ°å¢ï¼æ¾å¼æå®stdioä¼ è¾åè®®
transport: "stdio"
}
});
const tools = await mcpClient.getTools();
const modelWithTools = model.bindTools(tools);
async function runAgentWithTools(query,maxIterations = 30) {
const messages = [
new HumanMessage(query)
];
for (let i= 0; i < maxIterations; i++) {
console.log(chalk.bgGreen(`æ£å¨çå¾
AIæè...`));
const response = await modelWithTools.invoke(messages);
messages.push(response);
// æ£æ¥æ¯å¦æå·¥å
·è°ç¨
if (!response.tool_calls || response.tool_calls.length === 0) {
console.log(` AI æç»åå¤:${response.content}`);
return response.content;
}
console.log(chalk.bgBlue( `æ£æµå° ${response.tool_calls.length} 个工å
·è°ç¨~`));
// æ§è¡å·¥å
·è°ç¨
for (const toolCall of response.tool_calls) {
const foundTool = tools.find(t => t.name ===toolCall.name);
if (foundTool) {
const toolResult = await foundTool.invoke(toolCall.args);
messages.push(new ToolMessage({
content: toolResult,
tool_call_id: toolCall.id,
}));
}else{
console.log(chalk.bgRed(`æ¾ä¸å°å为 ${toolCall.name} çå·¥å
·`));
return `æ¾ä¸å°å为 ${toolCall.name} çå·¥å
·`;
}
}
}
return messages[messages.length - 1].content;
}
console.log( 12121212);
//await runAgentWithTools("æ¥ä¸ä¸ç¨æ· 002 çä¿¡æ¯?");
//const res = await mcpClient.listResources("my-mcp-server");
const res = await mcpClient.readResource(
"my-mcp-server",
"docs://guide"//æå¡ç«¯æå¾å¤ä¸ªè¯»åéæèµæºç代ç ï¼ä½ è¦è¯´æ¸
æ¥æ¯åªä¸ªèµæºï¼æè¿éç¨çæ¯guide.mdæä»¶ï¼å¦æä¸åï¼clientå°±ä¸ç¥éä½ è¦è¯»åçæ¯è°ãæä»¥å¨æç¨éé¢ä¸åæ¯ä¸è¡ç
);
console.log(res)
await mcpClient.close();
ä½ èªå·±çæ¬å°çtoolï¼å°±ç¨model.bindToolsç»å®å°±å¥½äºï¼ç°å¨å¦ææ¯è¿ç¨çtoolså¢ï¼å°±è¦ç¨å°MCPäºï¼MCPæ¯ä»ä¹å°±åèè¿ä¸ªæç« ï¼cloud.tencent.com/developer/aâ¦
ä»å°±æ¯ä¸ªåè®®ï¼å¾åhttpsï¼å¨äºèç½ä¸çtoolsé½å¯ä»¥éè¿MCPå¼è¿æ¥ï¼èªå·±ç¨ã
1.éæèµæºè·å
å¨ä¸é¢ä»£ç éé¢
server.resource(
"ä½¿ç¨æå", // resource name
"docs://guide", // è¿ä¸ªæ¯è¯»åèµæºçååï¼å¨clientçæ¶å使ç¨
async (uri) => {
const filePath = resolve(__dirname, 'docs', 'guide.md');// 读åçå®çæ¬å°guide.mdæä»¶ï¼è·¯å¾ï¼å½åèæ¬ç®å½ä¸çdocs/guide.mdï¼
let content = '';
try {
content = await fs.readFile(filePath, 'utf-8');
} catch (err) {
content = err.message;
}
return {
contents: [
{
uri: uri.href,
mimeType: "text/plain",
text: content
}
]
};
}
);
æ¯è·åéæèµæºçï¼å端è°ç¨çæ¶åï¼å°±éè¦æå®èµæºçåå
妿䏿å®ï¼å°±ä¸ç¥éä½ æ³è¦çè·åçæ¯åªä¸ªéæèµæºäºã
2.å·¥å ·ä½¿ç¨
serverå®ä¹äºå·¥å ·ï¼è¿å½åäºå·¥å ·åï¼ä½æ¯å¨ä½¿ç¨çæ¶å,å´æ²¡ææå®å·¥å ·åï¼é£å¤§æ¨¡åå ·ä½ä½¿ç¨åªä¸ªï¼
åå¤å¦ä¸ï¼
è¨å¤ä¹æå°±æ¯ï¼å·¥å ·æ¯æå¼åçï¼å·¥å ·çdescriptionå¾éè¦ï¼å¤§æ¨¡åå°±æ¯é çdescriptionæ¥å³å®å°åºè¦ç¨åªä¸ªå·¥å ·ï¼å¼åè ä¸éè¦æå¨å®ä¹ã
ä¸.使ç¨å«äººçtool
import 'dotenv/config';
import { MultiServerMCPClient } from'@langchain/mcp-adapters';
import {ChatOpenAI} from'@langchain/openai';
import {HumanMessage, SystemMessage,ToolMessage} from'@langchain/core/messages';
import chalk from 'chalk'
const model = new ChatOpenAI({
modelName:'qwen-plus',
apiKey: process.env.OPENAI_API_KEY,
configuration: {
baseURL: process.env.OPENAI_BASE_URL,
}
});
const mcpClient = new MultiServerMCPClient({
//è¿éå¯ä»¥å¼å
¥å¾å¤ä¸ªmcpæå¡ï¼è¿éåªå¼å
¥é«å¾·å°å¾çmcpæå¡
"amap-maps-streamableHttp":{
"url": "https://mcp.amap.com/mcp?key="+ process.env.GAODE_MAP_API_KEY,
"transport": "http",
},
//è¿éæè¦å¼å
¥mcpèªå·±å®ä¹çæä»¶å¤çtoolsæå¡
"file-system": {
command: "npx",//è¿éç¨çnpxæ¯å ä¸ºææ¬å°å®è£
äº@modelcontextprotocol/server-filesystemï¼å¦æè¦å
¨å±å®è£
åå¯ä»¥ä¸ç¨npx
args: [
"-y",
"@modelcontextprotocol/server-filesystem",
"E:/AITool/tool-test", // â å¿
å¡«ï¼å
许访é®çæ ¹ç®å½
],
},
//è¦å¤§æ¨¡å帮æä»¬æå¼æµè§å¨ï¼ç¶åèªå¨å¤çç½é¡µçå·¥å
·ï¼è¿éç¨çæ¯chrome-devtools-mcpå·¥å
·å
"chrome-devtools":{
"command":"npx",
"args": [
"-y",
"chrome-devtools-mcp@latest"
]
}
})
const tools = await mcpClient.getTools();
const modelWithTools = model.bindTools(tools);
async function runAgentWithTools(query,maxIterations = 30) {
const messages = [
new HumanMessage(query)
];
for (let i= 0; i < maxIterations; i++) {
console.log(chalk.bgGreen(`æ£å¨çå¾
AIæè...`));
const response = await modelWithTools.invoke(messages);
messages.push(response);
// æ£æ¥æ¯å¦æå·¥å
·è°ç¨
if (!response.tool_calls || response.tool_calls.length === 0) {
console.log(` AI æç»åå¤:${response.content}`);
return response.content;
}
// æ§è¡å·¥å
·è°ç¨
for (const toolCall of response.tool_calls) {
const foundTool = tools.find(t => t.name ===toolCall.name);
if (foundTool) {
const toolResult = await foundTool.invoke(toolCall.args);
let res = '';
if(typeof toolResult === 'string'){
res= toolResult;
}else if(toolResult && toolResult.text){
res= toolResult.text;
}
messages.push(new ToolMessage({
content: res,
tool_call_id: toolCall.id,
}));
}else{
console.log(chalk.bgRed(`æ¾ä¸å°å为 ${toolCall.name} çå·¥å
·`));
return `æ¾ä¸å°å为 ${toolCall.name} çå·¥å
·`;
}
}
}
return messages[messages.length - 1].content;
}
console.log( 12121212);
//await runAgentWithTools("å京åç«éè¿çé
åºï¼ä»¥åè¿å»ç路线");
//await runAgentWithTools("å京åç«éè¿ç5个é
åºï¼ä»¥åå»ç路线ï¼è·¯çº¿è§åçæææ¡£ï¼ä¿åå° E:/AITool/tool-test/test.md æä»¶éï¼å¹¶è¿åä¿åçè·¯å¾ã");
await runAgentWithTools("å京åç«éè¿çé
åºï¼æè¿ç 3 个é
åºï¼æ¿å°é
åºå¾çï¼ç¶åç¨æµè§å¨æå¼ï¼ä¸ä¸ªå¾ç对åºä¸ä¸ªæµè§å¨æ ç¾é¡µï¼å¹¶ä¸æå¯¹åºé¡µé¢çæ 颿¹æé
åºåå");
await mcpClient.close();
æä»¬ç¨é«å¾·å°å¾çmcpæ¿å°é
åºå°åï¼ç¨file-systemçæä»¶å¤çå·¥å
·å¨æ¬å°å»ºäºä¸ä¸ªæä»¶ï¼ç¶åæé
åºä¿¡æ¯åå¨å¨æä»¶éï¼åå©ç¨chrome-devtoolså·¥å
·å°é
åºå¾çå±ç¤ºå°æµè§å¨ä¸ã
ä¸è¿°ä»£ç çå
³ç³»å½¢å¼ï¼
æèé®é¢1ï¼
ä¸å¾ï¼ä¸ºä»ä¹æçå·¥å ·ç¨stdioåè®®ï¼æç使ç¨httpåè®®ï¼ä»å°åºæ¯è°æ¥å³å®çï¼
å¨ MCPï¼Model Context Protocolï¼æ¶æä¸ï¼stdio å httpï¼é常æ Streamable HTTP ææ©æç SSEï¼æ¯ä¸¤ç§ä¸åçä¼ è¾å±åè®®ï¼Transportï¼ ï¼è´è´£å®¢æ·ç«¯ï¼MCP Adapterï¼ä¸æå¡ç«¯ï¼MCP Serverï¼ä¹é´ä¼ éæ¶æ¯ã
å³å®ä½¿ç¨åªç§åè®®çï¼æ¯æå¡ç«¯çé¨ç½²å½¢æãè¿è¡ä½ç½®ä»¥åä½ å¨å®¢æ·ç«¯ä»£ç ä¸çé ç½®ã
æ¬å°éä¿¡ç¨stdio è¿ç¨éä¿¡ç¨http
å¼åè å¨å®ä¹toolçæ¶åæ¯å¯ä»¥è§å®çï¼æ¯å¦ï¼
// é
ç½®æ¬å° stdio æå¡
const fileSystemServer = {
command: "node",
args: ["path/to/filesystem-server.js"],
transport: "stdio" // ð å³å®ç¨ stdio
};
// é
ç½®è¿ç¨ http æå¡
const amapServer = {
url: "https://mcp.amap.com/xxx",
transport: "http" // ð å³å®ç¨ http
};
æ»ç»
- æ¬å°å·¥å
·ï¼è·å¨èªå·±çµèä¸çèæ¬ãæ¬å°æä»¶ãæ¬å°æµè§å¨ï¼ï¼ç¨
stdioï¼ç®åãå¿«ãå®å ¨ã - è¿ç¨æå¡ï¼äºç«¯ç APIãç¬¬ä¸æ¹å¼æ¾å¹³å°å¦é«å¾·ï¼ï¼ç¨
httpï¼è·¨ç½ç»ãå¯å ±äº«ã
ä¸å¥è¯æ¦æ¬ï¼è°å³å®çï¼æ¯ä¸å¡åºæ¯åä½ ç客æ·ç«¯é ç½®å³å®çãæ¬å°èµ·åè¿ç¨å°±ç¨ stdioï¼è°ç¨äºç«¯ç½åå°±ç¨ httpã
Aitishiku.com