رفتن به محتوا

اتصال به ابزارهای بیرونی با MCP

Model Context Protocol (MCP) یک استانداردِ باز برای اتصالِ ایجنت‌های AI به ابزارها و منابعِ داده‌ی بیرونی است. با MCP، ایجنتِ تو می‌تواند به پایگاه‌های داده query بزند، با APIهایی مثلِ Slack و GitHub یکپارچه شود، و بدونِ نوشتنِ پیاده‌سازیِ سفارشیِ ابزار به سرویس‌های دیگر متصل شود.

سرورهای MCP می‌توانند به‌صورتِ فرایندهای محلی اجرا شوند، روی HTTP متصل شوند، یا مستقیماً درونِ برنامه‌ی SDKِ تو اجرا شوند.

این مثال با استفاده از HTTP transport به سرورِ MCPِ مستنداتِ Claude Code متصل می‌شود و با allowedTools و یک wildcard همه‌ی ابزارهای آن سرور را مجاز می‌کند.

import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Use the docs MCP server to explain what hooks are in Claude Code",
options: {
mcpServers: {
"claude-code-docs": {
type: "http",
url: "https://code.claude.com/docs/mcp"
}
},
allowedTools: ["mcp__claude-code-docs__*"]
}
})) {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
async def main():
options = ClaudeAgentOptions(
mcp_servers={
"claude-code-docs": {
"type": "http",
"url": "https://code.claude.com/docs/mcp",
}
},
allowed_tools=["mcp__claude-code-docs__*"],
)
async for message in query(
prompt="Use the docs MCP server to explain what hooks are in Claude Code",
options=options,
):
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)
asyncio.run(main())

ایجنت به سرورِ مستندات متصل می‌شود، اطلاعات درباره‌ی hooks را جست‌وجو می‌کند، و نتایج را برمی‌گرداند.

می‌توانی سرورهای MCP را هنگامِ فراخوانیِ query() در کد پیکربندی کنی، یا در یک فایلِ .mcp.json که از طریقِ settingSources بارگذاری می‌شود.

سرورهای MCP را مستقیماً در گزینه‌ی mcpServers پاس بده:

import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "List files in my project",
options: {
mcpServers: {
filesystem: {
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects"]
}
},
allowedTools: ["mcp__filesystem__*"]
}
})) {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
async def main():
options = ClaudeAgentOptions(
mcp_servers={
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/me/projects",
],
}
},
allowed_tools=["mcp__filesystem__*"],
)
async for message in query(prompt="List files in my project", options=options):
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)
asyncio.run(main())

یک فایلِ .mcp.json در ریشه‌ی پروژه‌ات بساز. این فایل وقتی برداشته می‌شود که setting sourceِ project فعال باشد، که برای گزینه‌های پیش‌فرضِ query() همین‌طور است. اگر settingSources را صریحاً تنظیم کنی، برای بارگذاریِ این فایل "project" را بگنجان:

{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects"]
}
}
}

ابزارهای MCP پیش از اینکه Claude بتواند از آن‌ها استفاده کند، به مجوزِ صریح نیاز دارند. بدونِ مجوز، Claude می‌بیند که ابزارها در دسترس‌اند اما نمی‌تواند آن‌ها را فراخوانی کند.

قراردادِ نام‌گذاریِ ابزار

Section titled “قراردادِ نام‌گذاریِ ابزار”

ابزارهای MCP الگوی نام‌گذاریِ mcp__<server-name>__<tool-name> را دنبال می‌کنند. برای مثال، یک سرورِ GitHub با نامِ "github" و ابزارِ list_issues به mcp__github__list_issues تبدیل می‌شود.

تأییدِ خودکار با allowedTools

Section titled “تأییدِ خودکار با allowedTools”

از allowedTools برای تأییدِ خودکارِ ابزارهای مشخصِ MCP استفاده کن تا Claude بتواند بدونِ پرامپتِ مجوز از آن‌ها استفاده کند:

const _ = {
options: {
mcpServers: {
// your servers
},
allowedTools: [
"mcp__github__*", // All tools from the github server
"mcp__db__query", // Only the query tool from db server
"mcp__slack__send_message" // Only send_message from slack server
]
}
};

wildcardها (*) به تو امکان می‌دهند همه‌ی ابزارهای یک سرور را بدونِ فهرست‌کردنِ تک‌تکِ آن‌ها مجاز کنی.

ابزارهای در دسترس را کشف کن

Section titled “ابزارهای در دسترس را کشف کن”

برای دیدنِ اینکه یک سرورِ MCP چه ابزارهایی ارائه می‌دهد، مستنداتِ سرور را بررسی کن یا به سرور متصل شو و پیامِ init از نوعِ system را بازرسی کن:

for await (const message of query({ prompt: "...", options })) {
if (message.type === "system" && message.subtype === "init") {
console.log("Available MCP tools:", message.mcp_servers);
}
}

سرورهای MCP با ایجنتِ تو از طریقِ پروتکل‌های transportِ مختلف ارتباط برقرار می‌کنند. مستنداتِ سرور را بررسی کن تا ببینی کدام transport را پشتیبانی می‌کند:

  • اگر مستندات یک دستور برای اجرا به تو می‌دهند (مثلِ npx @modelcontextprotocol/server-github)، از stdio استفاده کن
  • اگر مستندات یک URL به تو می‌دهند، از HTTP یا SSE استفاده کن
  • اگر داری ابزارهای خودت را در کد می‌سازی، از یک سرورِ SDK MCP استفاده کن

فرایندهای محلی که از طریقِ stdin/stdout ارتباط برقرار می‌کنند. این را برای سرورهای MCPی که روی همان ماشین اجرا می‌کنی به کار ببر:

const _ = {
options: {
mcpServers: {
github: {
command: "npx",
args: ["-y", "@modelcontextprotocol/server-github"],
env: {
GITHUB_TOKEN: process.env.GITHUB_TOKEN
}
}
},
allowedTools: ["mcp__github__list_issues", "mcp__github__search_issues"]
}
};
options = ClaudeAgentOptions(
mcp_servers={
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {"GITHUB_TOKEN": os.environ["GITHUB_TOKEN"]},
}
},
allowed_tools=["mcp__github__list_issues", "mcp__github__search_issues"],
)

برای سرورهای MCPِ میزبانی‌شده در فضای ابری و APIهای راه‌دور از HTTP یا SSE استفاده کن:

const _ = {
options: {
mcpServers: {
"remote-api": {
type: "sse",
url: "https://api.example.com/mcp/sse",
headers: {
Authorization: `Bearer ${process.env.API_TOKEN}`
}
}
},
allowedTools: ["mcp__remote-api__*"]
}
};
options = ClaudeAgentOptions(
mcp_servers={
"remote-api": {
"type": "sse",
"url": "https://api.example.com/mcp/sse",
"headers": {"Authorization": f"Bearer {os.environ['API_TOKEN']}"},
}
},
allowed_tools=["mcp__remote-api__*"],
)

برای transportِ streamable HTTP، به‌جای آن از "type": "http" استفاده کن. در .mcp.json و دیگر فایل‌های پیکربندیِ JSON، مقدارِ "streamable-http" به‌عنوانِ نامِ مستعارِ "http" پذیرفته می‌شود. گزینه‌ی برنامه‌نویسیِ mcpServers فقط "http" را می‌پذیرد.

ابزارهای سفارشی را به‌جای اجرای یک فرایندِ سرورِ جداگانه، مستقیماً در کدِ برنامه‌ات تعریف کن. برای جزئیاتِ پیاده‌سازی به راهنمای ابزارهای سفارشی نگاه کن.

وقتی ابزارهای MCPِ زیادی پیکربندی کرده‌ای، تعاریفِ ابزار می‌توانند بخشِ قابلِ‌توجهی از پنجره‌ی کانتکستت را مصرف کنند. جست‌وجوی ابزار این را با نگه‌داشتنِ تعاریفِ ابزار بیرونِ کانتکست و بارگذاریِ فقط آن‌هایی که Claude در هر نوبت لازم دارد حل می‌کند.

جست‌وجوی ابزار به‌صورتِ پیش‌فرض فعال است. برای گزینه‌های پیکربندی و جزئیات به Tool search نگاه کن.

برای جزئیاتِ بیشتر، از جمله بهترین شیوه‌ها و استفاده از جست‌وجوی ابزار با ابزارهای سفارشیِ SDK، به راهنمای جست‌وجوی ابزار نگاه کن.

بیشترِ سرورهای MCP برای دسترسی به سرویس‌های بیرونی به احراز هویت نیاز دارند. اعتبارنامه‌ها را از طریقِ متغیرهای محیطی در پیکربندیِ سرور پاس بده.

پاس‌دادنِ اعتبارنامه‌ها از طریقِ متغیرهای محیطی

Section titled “پاس‌دادنِ اعتبارنامه‌ها از طریقِ متغیرهای محیطی”

از فیلدِ env برای پاس‌دادنِ کلیدهای API، توکن‌ها و دیگر اعتبارنامه‌ها به سرورِ MCP استفاده کن:

const _ = {
options: {
mcpServers: {
github: {
command: "npx",
args: ["-y", "@modelcontextprotocol/server-github"],
env: {
GITHUB_TOKEN: process.env.GITHUB_TOKEN
}
}
},
allowedTools: ["mcp__github__list_issues"]
}
};
options = ClaudeAgentOptions(
mcp_servers={
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {"GITHUB_TOKEN": os.environ["GITHUB_TOKEN"]},
}
},
allowed_tools=["mcp__github__list_issues"],
)

برای یک مثالِ کاملِ کارا با لاگ‌گیریِ debug به فهرست‌کردنِ issueها از یک مخزن نگاه کن.

هدرهای HTTP برای سرورهای راه‌دور

Section titled “هدرهای HTTP برای سرورهای راه‌دور”

برای سرورهای HTTP و SSE، هدرهای احراز هویت را مستقیماً در پیکربندیِ سرور پاس بده:

const _ = {
options: {
mcpServers: {
"secure-api": {
type: "http",
url: "https://api.example.com/mcp",
headers: {
Authorization: `Bearer ${process.env.API_TOKEN}`
}
}
},
allowedTools: ["mcp__secure-api__*"]
}
};
options = ClaudeAgentOptions(
mcp_servers={
"secure-api": {
"type": "http",
"url": "https://api.example.com/mcp",
"headers": {"Authorization": f"Bearer {os.environ['API_TOKEN']}"},
}
},
allowed_tools=["mcp__secure-api__*"],
)

مشخصاتِ MCP از OAuth 2.1 پشتیبانی می‌کند برای authorization. SDK جریان‌های OAuth را خودکار مدیریت نمی‌کند، اما می‌توانی بعد از تکمیلِ جریانِ OAuth در برنامه‌ات، توکن‌های دسترسی را از طریقِ هدرها پاس بدهی:

// After completing OAuth flow in your app
const accessToken = await getAccessTokenFromOAuthFlow();
const options = {
mcpServers: {
"oauth-api": {
type: "http",
url: "https://api.example.com/mcp",
headers: {
Authorization: `Bearer ${accessToken}`
}
}
},
allowedTools: ["mcp__oauth-api__*"]
};
# After completing OAuth flow in your app
access_token = await get_access_token_from_oauth_flow()
options = ClaudeAgentOptions(
mcp_servers={
"oauth-api": {
"type": "http",
"url": "https://api.example.com/mcp",
"headers": {"Authorization": f"Bearer {access_token}"},
}
},
allowed_tools=["mcp__oauth-api__*"],
)

فهرست‌کردنِ issueها از یک مخزن

Section titled “فهرست‌کردنِ issueها از یک مخزن”

این مثال به سرورِ MCPِ GitHub متصل می‌شود تا issueهای اخیر را فهرست کند. مثال شاملِ لاگ‌گیریِ debug است تا اتصالِ MCP و فراخوانی‌های ابزار را تأیید کند.

پیش از اجرا، یک personal access tokenِ GitHub با scopeِ repo بساز و آن را به‌عنوانِ متغیرِ محیطی تنظیم کن:

Terminal window
export GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "List the 3 most recent issues in anthropics/claude-code",
options: {
mcpServers: {
github: {
command: "npx",
args: ["-y", "@modelcontextprotocol/server-github"],
env: {
GITHUB_TOKEN: process.env.GITHUB_TOKEN
}
}
},
allowedTools: ["mcp__github__list_issues"]
}
})) {
// Verify MCP server connected successfully
if (message.type === "system" && message.subtype === "init") {
console.log("MCP servers:", message.mcp_servers);
}
// Log when Claude calls an MCP tool
if (message.type === "assistant") {
for (const block of message.message.content) {
if (block.type === "tool_use" && block.name.startsWith("mcp__")) {
console.log("MCP tool called:", block.name);
}
}
}
// Print the final result
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}
import asyncio
import os
from claude_agent_sdk import (
query,
ClaudeAgentOptions,
ResultMessage,
SystemMessage,
AssistantMessage,
)
async def main():
options = ClaudeAgentOptions(
mcp_servers={
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {"GITHUB_TOKEN": os.environ["GITHUB_TOKEN"]},
}
},
allowed_tools=["mcp__github__list_issues"],
)
async for message in query(
prompt="List the 3 most recent issues in anthropics/claude-code",
options=options,
):
# Verify MCP server connected successfully
if isinstance(message, SystemMessage) and message.subtype == "init":
print("MCP servers:", message.data.get("mcp_servers"))
# Log when Claude calls an MCP tool
if isinstance(message, AssistantMessage):
for block in message.content:
if hasattr(block, "name") and block.name.startswith("mcp__"):
print("MCP tool called:", block.name)
# Print the final result
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)
asyncio.run(main())

query زدن به یک پایگاه داده

Section titled “query زدن به یک پایگاه داده”

این مثال از سرورِ MCPِ Postgres برای query زدن به یک پایگاه داده استفاده می‌کند. رشته‌ی اتصال به‌عنوانِ یک آرگومان به سرور پاس داده می‌شود. ایجنت خودکار schemaِ پایگاه داده را کشف می‌کند، query‌ی SQL را می‌نویسد و نتایج را برمی‌گرداند:

import { query } from "@anthropic-ai/claude-agent-sdk";
// Connection string from environment variable
const connectionString = process.env.DATABASE_URL;
for await (const message of query({
// Natural language query - Claude writes the SQL
prompt: "How many users signed up last week? Break it down by day.",
options: {
mcpServers: {
postgres: {
command: "npx",
// Pass connection string as argument to the server
args: ["-y", "@modelcontextprotocol/server-postgres", connectionString]
}
},
// Allow only read queries, not writes
allowedTools: ["mcp__postgres__query"]
}
})) {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}
import asyncio
import os
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
async def main():
# Connection string from environment variable
connection_string = os.environ["DATABASE_URL"]
options = ClaudeAgentOptions(
mcp_servers={
"postgres": {
"command": "npx",
# Pass connection string as argument to the server
"args": [
"-y",
"@modelcontextprotocol/server-postgres",
connection_string,
],
}
},
# Allow only read queries, not writes
allowed_tools=["mcp__postgres__query"],
)
# Natural language query - Claude writes the SQL
async for message in query(
prompt="How many users signed up last week? Break it down by day.",
options=options,
):
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)
asyncio.run(main())

سرورهای MCP می‌توانند به دلایلِ گوناگون در اتصال شکست بخورند: ممکن است فرایندِ سرور نصب نشده باشد، اعتبارنامه‌ها نامعتبر باشند، یا یک سرورِ راه‌دور در دسترس نباشد.

SDK در آغازِ هر query یک پیامِ system با subtypeِ init منتشر می‌کند. این پیام وضعیتِ اتصالِ هر سرورِ MCP را در بر دارد. فیلدِ status را بررسی کن تا پیش از شروعِ کارِ ایجنت، شکست‌های اتصال را تشخیص بدهی:

import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Process data",
options: {
mcpServers: {
"data-processor": dataServer
}
}
})) {
if (message.type === "system" && message.subtype === "init") {
const failedServers = message.mcp_servers.filter((s) => s.status !== "connected");
if (failedServers.length > 0) {
console.warn("Failed to connect:", failedServers);
}
}
if (message.type === "result" && message.subtype === "error_during_execution") {
console.error("Execution failed");
}
}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, SystemMessage, ResultMessage
async def main():
options = ClaudeAgentOptions(mcp_servers={"data-processor": data_server})
async for message in query(prompt="Process data", options=options):
if isinstance(message, SystemMessage) and message.subtype == "init":
failed_servers = [
s
for s in message.data.get("mcp_servers", [])
if s.get("status") != "connected"
]
if failed_servers:
print(f"Failed to connect: {failed_servers}")
if (
isinstance(message, ResultMessage)
and message.subtype == "error_during_execution"
):
print("Execution failed")
asyncio.run(main())

سرور وضعیتِ “failed” نشان می‌دهد

Section titled “سرور وضعیتِ “failed” نشان می‌دهد”

پیامِ init را بررسی کن تا ببینی کدام سرورها در اتصال شکست خوردند:

if (message.type === "system" && message.subtype === "init") {
for (const server of message.mcp_servers) {
if (server.status === "failed") {
console.error(`Server ${server.name} failed to connect`);
}
}
}

علت‌های رایج:

  • متغیرهای محیطیِ گم‌شده: مطمئن شو توکن‌ها و اعتبارنامه‌های لازم تنظیم شده‌اند. برای سرورهای stdio، بررسی کن فیلدِ env با آنچه سرور انتظار دارد مطابقت دارد.
  • سرور نصب‌نشده: برای دستورهای npx، تأیید کن پکیج وجود دارد و Node.js در PATHِ توست.
  • رشته‌ی اتصالِ نامعتبر: برای سرورهای پایگاه داده، قالبِ رشته‌ی اتصال و دسترس‌پذیریِ پایگاه داده را تأیید کن.
  • مشکلاتِ شبکه: برای سرورهای راه‌دورِ HTTP/SSE، بررسی کن URL در دسترس است و فایروال‌ها اتصال را مجاز می‌کنند.

ابزارها فراخوانی نمی‌شوند

Section titled “ابزارها فراخوانی نمی‌شوند”

اگر Claude ابزارها را می‌بیند اما از آن‌ها استفاده نمی‌کند، بررسی کن که با allowedTools مجوز داده‌ای:

const _ = {
options: {
mcpServers: {
// your servers
},
allowedTools: ["mcp__servername__*"] // Auto-approve calls from this server
}
};

MCP SDK یک timeoutِ پیش‌فرضِ ۶۰ ثانیه‌ای برای اتصالِ سرورها دارد. اگر سرورت برای شروع بیشتر طول بکشد، اتصال شکست می‌خورد. برای سرورهایی که به زمانِ راه‌اندازیِ بیشتری نیاز دارند، این‌ها را در نظر بگیر:

  • استفاده از یک سرورِ سبک‌تر اگر در دسترس است
  • گرم‌کردنِ سرور پیش از شروعِ ایجنتت
  • بررسیِ لاگ‌های سرور برای علت‌های راه‌اندازیِ کند