简介
这篇文章将带你了解如何使用 TypeScript 构建一个 Model Context Protocol (MCP) 服务器,以连接 Azure AI Agent 和 Claude Desktop 或其他支持 MCP 的客户端。通过本文,你将学习搭建服务器、配置连接以及以编程方式处理 AI Agent 的交互。
为什么需要 MCP 服务器?
Azure AI Agent 是 Azure AI Foundry 生态系统的一部分,提供强大的对话式 AI 功能。然而,要将这些 Agent 集成到桌面应用程序中,往往需要定制化的解决方案。MCP 提供了一个标准化协议,可以无缝连接 Azure AI Agent 和支持 MCP 的客户端(如 Claude Desktop)。
准备工作
在开始之前,请确保你已准备以下条件:
- 安装 Node.js 16 或更高版本。
- 配置 TypeScript 开发环境。
- 拥有 Claude Desktop 或其他 MCP 兼容客户端。
- 配置 Azure CLI 并拥有权限。
- Azure AI Foundry 中配置了现有 Azure AI Agent。
搭建 TypeScript MCP 服务器
第一步:创建项目
首先,创建一个新的项目目录并安装必要的依赖:
1
2
3
4
5
6
7
8
9
10
11
12
|
# 创建项目目录
mkdir azure-agent-mcp
cd azure-agent-mcp
# 初始化 npm 项目
npm init -y
# 安装依赖
npm install @modelcontextprotocol/sdk zod dotenv @azure/ai-projects @azure/identity
# 安装开发依赖
npm install -D typescript @types/node
|
第二步:配置 TypeScript
创建 tsconfig.json
文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"esModuleInterop": true,
"outDir": "./dist",
"strict": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"ts-node": {
"esm": true
}
}
|
第三步:环境变量设置
创建 .env
文件以存储 Azure 凭据:
1
2
|
PROJECT_CONNECTION_STRING=your-project-connection-string
DEFAULT_AGENT_ID=your-default-agent-id # 可选
|
第四步:编写 MCP 服务器代码
创建 src/index.ts
文件并开始编写服务器代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import * as dotenv from "dotenv";
import { AIProjectsClient } from "@azure/ai-projects";
import { DefaultAzureCredential } from "@azure/identity";
dotenv.config();
const PROJECT_CONNECTION_STRING = process.env.PROJECT_CONNECTION_STRING;
const DEFAULT_AGENT_ID = process.env.DEFAULT_AGENT_ID || "";
let aiClient: AIProjectsClient | null = null;
|
第五步:实现核心功能
添加初始化和查询 Agent 的功能:
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
|
function initializeServer(): boolean {
if (!PROJECT_CONNECTION_STRING) {
console.error("ERROR: 缺少环境变量 PROJECT_CONNECTION_STRING");
return false;
}
try {
const credential = new DefaultAzureCredential();
aiClient = AIProjectsClient.fromConnectionString(PROJECT_CONNECTION_STRING, credential);
return true;
} catch (error) {
console.error(`ERROR: 初始化 AIProjectClient 失败: ${error instanceof Error ? error.message : String(error)}`);
return false;
}
}
async function queryAgent(agentId: string, userQuery: string, existingThreadId?: string): Promise<{ response: string; threadId: string }> {
if (!aiClient) {
throw new Error("AI 客户端未初始化");
}
try {
await aiClient.agents.getAgent(agentId);
let threadId = existingThreadId;
if (!threadId) {
const thread = await aiClient.agents.createThread();
threadId = thread.id;
}
await aiClient.agents.createMessage(threadId, {
role: "user" as MessageRole,
content: userQuery,
});
let run = await aiClient.agents.createRun(threadId, agentId);
while (["queued", "in_progress", "requires_action"].includes(run.status)) {
await new Promise((resolve) => setTimeout(resolve, 1000));
run = await aiClient.agents.getRun(threadId, run.id);
}
if (run.status === "failed") {
return {
response: `错误: Agent 运行失败: ${run.lastError?.message || "未知错误"}`,
threadId,
};
}
const messages = await aiClient.agents.listMessages(threadId);
const assistantMessages = messages.data.filter((m) => m.role === "assistant");
const lastMessage = assistantMessages[assistantMessages.length - 1];
let responseText = "";
if (lastMessage) {
for (const content of lastMessage.content) {
if (content.type === "text" && content.text?.value) {
responseText += content.text.value + "\n";
}
}
}
return { response: responseText.trim(), threadId };
} catch (error) {
throw new Error(`Agent 查询失败: ${error instanceof Error ? error.message : String(error)}`);
}
}
|
第六步:注册 MCP 工具
创建 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
|
const serverInitialized = initializeServer();
const mcp = new McpServer({
name: "azure-agent",
version: "1.0.0",
description: "用于集成 Azure AI Agent 服务的 MCP 服务器",
});
mcp.tool(
"query_agent",
"查询指定的 Azure AI Agent",
{
agent_id: z.string().describe("Azure AI Agent 的 ID"),
query: z.string().describe("发送给 Agent 的问题或请求"),
thread_id: z.string().optional().describe("用于继续对话的线程 ID"),
},
async ({ agent_id, query, thread_id }) => {
try {
const { response, threadId } = await queryAgent(agent_id, query, thread_id);
return {
content: [
{
type: "text",
text: `## Azure AI Agent 的响应\n\n${response}\n\n(thread_id: ${threadId})`,
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `查询 Agent 时出错: ${error instanceof Error ? error.message : String(error)}`,
},
],
};
}
}
);
|
第七步:运行服务器
添加项目构建和运行脚本:
1
2
3
4
5
6
7
|
{
"type": "module",
"scripts": {
"build": "tsc",
"start": "node dist/index.js"
}
}
|
运行以下命令:
1
2
|
npm run build
npm start
|
与 Claude Desktop 集成
为了将 MCP 服务器与 Claude Desktop 集成,需要更新其配置文件 claude_desktop_config.json
:
1
2
3
4
5
6
7
8
9
10
11
12
|
{
"mcpServers": {
"azure-agent": {
"command": "node",
"args": ["/ABSOLUTE/PATH/TO/azure-agent-mcp/dist/index.js"],
"env": {
"PROJECT_CONNECTION_STRING": "your-project-connection-string",
"DEFAULT_AGENT_ID": "your-default-agent-id"
}
}
}
}
|
实际使用示例
-
查询指定 Agent
在 Claude Desktop 中询问:能否使用 azure-agent 检查西雅图是否有天气警报?
Claude 会调用 query_agent
工具并使用指定 Agent ID。
-
使用默认 Agent
在 Claude Desktop 中询问:使用默认 Azure Agent 总结最新的 NBA 新闻。
-
发现可用的 Agent
在 Claude Desktop 中询问:我有哪些可用的 Azure AI Agent?
总结
通过使用 TypeScript 构建 Azure AI Agent 的 MCP 服务器,你能够在 Azure AI Foundry 服务 和 MCP 客户端之间创建桥梁。这种集成方式不仅增强了服务的能力,还通过 MCP 协议明确职责分工,让开发过程更高效。
原文链接:Azure AI Foundry: Create an MCP Server with Azure AI Agent Service (TypeScript Edition)