AI 函数调用与 MCP 协议深度解析:从 OpenAI tools 到 Model Context Protocol

4322 字
22 分钟
AI 函数调用与 MCP 协议深度解析:从 OpenAI tools 到 Model Context Protocol

如果你 2026 年还在手写”把工具描述拼成 prompt,解析 LLM 返回的 JSON 再调本地函数”——你正在错过 AI 工具生态最大的范式转移。

工具调用(Tool Use / Function Calling)这件事,已经从「各家闭源 API 各搞一套」演化成了一场事实标准的争夺战:

  • 2023 年 6 月,OpenAI 在 gpt-4-0613/gpt-3.5-turbo-0613 上线 tools 字段,把 JSON Schema 直接塞进 chat completion 请求
  • 2024 年 5 月,Anthropic 在 Claude 3 上线原生 Tool Use,格式与 OpenAI 类似但 input_schema 命名不同
  • 2024 年 11 月,Anthropic 联合多家厂商发布 Model Context Protocol(MCP),把”工具调用”从「模型 API 的一个参数」升格成了一个独立的、客户端-服务器架构的开放协议
  • 2025 年,OpenAI 宣布 Agent SDK 全面支持 MCP,Replit、Sourcegraph、Codeium 等头部厂商跟进
  • 2026 年,MCP 已经成为 Agent 工具生态的事实标准——Cursor、Claude Desktop、Continue、Zed 等 IDE 全栈接入

但工具调用与 MCP 协议,对绝大多数工程师来说还是两个模糊的概念。这篇文章的目标,就是把这件事讲透:

  1. 原理层:OpenAI tools、Claude Tool Use、Gemini Function Calling 三大协议的字段差异到底在哪
  2. 架构层:MCP 协议为什么不是”另一个工具调用 API”,它的 JSON-RPC + Resources/Prompts/Tools/Sampling 设计哲学是什么
  3. 工程层:从零写一个 MCP Server,接入 Claude Desktop 与 Claude Agent SDK 的全链路代码

读完后,你将能够独立设计一个支持多模型的工具调用层,并为任何 Agent 系统接入 MCP 生态。


一、为什么 Function Calling 是 Agent 时代的基石?#

1.1 没有工具调用时,LLM 只是个”聊天机器人”#

在 Function Calling 出现之前,LLM 接入外部系统只有两条路:

方式实现缺陷
Prompt 注入把”工具描述”塞进 system prompt,让模型输出 Action: get_weather({"city":"北京"}) 字符串输出格式不可控、需要正则解析、Token 浪费严重
RAG 检索把外部文档切片塞进 context window只能读,不能写、不能调用

Function Calling 的革命性在于:它把”调用工具”从”自然语言生成”变成了”结构化决策”。模型不再生成自由文本,而是输出一个机器可解析的结构化对象(通常是 JSON),由应用层决定下一步行为。

1.2 Function Calling 解决了三个核心问题#

┌─────────────────────────────────────────────────┐
│ ① 可靠性:从"75% JSON 合法率"提升到"99%+ 结构匹配" │
│ ② 可发现性:模型能"看到"可用工具,不需要记硬编码 prompt │
│ ③ 可组合性:多工具 + 多轮对话 = 复杂 Agent 任务 │
└─────────────────────────────────────────────────┘

这三点让 Function Calling 成为 Agent 时代的”TCP/IP”——没有它,Claude Computer Use、OpenAI o3 Deep Research、Manus 这种产品根本不可能存在。


二、三大 Function Calling 协议横评#

虽然 OpenAI tools 已经成为事实标准,但 Claude、Gemini、Qwen 在字段命名、Schema 约束、流式行为上仍有差异。下面用同一个”查询天气”工具对照三家的 API。

2.1 OpenAI tools(事实标准)#

from openai import OpenAI
import json
client = OpenAI()
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询指定城市的实时天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名称"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}
}
]
resp = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "北京今天天气怎么样?"}],
tools=tools,
tool_choice="auto" # "auto" | "none" | {"type":"function","function":{"name":"get_weather"}}
)
msg = resp.choices[0].message
if msg.tool_calls:
for tc in msg.tool_calls:
args = json.loads(tc.function.arguments)
print(f"模型想调用 {tc.function.name}({args})")
# → 模型想调用 get_weather({'city': '北京', 'unit': 'celsius'})

关键字段

  • type: "function":固定值(OpenAI 后续会扩展 type: "custom" 等)
  • function.name / description / parameters:JSON Schema
  • tool_choice:控制是否必须调用、调用哪一个
  • 响应在 message.tool_calls[i].function.arguments(字符串 JSON,需要自己解析)

2.2 Claude Tool Use(Anthropic)#

import anthropic
import json
client = anthropic.Anthropic()
tools = [
{
"name": "get_weather",
"description": "查询指定城市的实时天气",
"input_schema": { # ← 注意字段名不同
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名称"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}
]
resp = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
tools=tools,
messages=[{"role": "user", "content": "北京今天天气怎么样?"}]
)
for block in resp.content:
if block.type == "tool_use": # ← 块类型不同
print(f"模型想调用 {block.name}({block.input})")
# → 模型想调用 get_weather({'city': '北京', 'unit': 'celsius'})

关键差异

维度OpenAI toolsClaude Tool Use
Schema 字段function.parametersinput_schema
响应位置message.tool_calls[i].functioncontent[i] 块,type=tool_use
响应字段function.arguments(字符串)input(直接是 dict)
tool_choice字符串 + 对象默认 auto,强制调用通过 prompt 实现
流式通过 tool_calls[i].index 增量通过 content_block_delta 增量

2.3 Gemini Function Calling(Google)#

import google.generativeai as genai
genai.configure(api_key="YOUR_KEY")
weather_fn = {
"name": "get_weather",
"description": "查询指定城市的实时天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}
model = genai.GenerativeModel(
model_name="gemini-1.5-pro",
tools=[weather_fn]
)
chat = model.start_chat()
resp = chat.send_message("北京今天天气怎么样?")
for part in resp.parts:
if fn := part.function_call:
print(f"模型想调用 {fn.name}({dict(fn.args)})")

2.4 三家差异速查表#

维度OpenAIClaudeGemini
Schema 字段function.parametersinput_schemaparameters
响应包装tool_calls[] 数组content[]parts[]
并行调用✅ 原生支持(一次返回多个)✅ 单次响应可含多个 tool_use✅ 原生支持
强制调用tool_choice="required"prompt 引导 + system 约束tool_config
流式增量tool_calls.deltacontent_block_delta不支持流式 tool call
结构化输出response_format + strict: truetool_use + structured outputresponseSchema

实战建议:如果你写的是单一模型的应用,直接用对应 SDK 即可。如果写的是多模型抽象层,建议抽象成自己的 ToolDefinition + ToolCall,内部做协议转换。这正是 MCP 想要解决的痛点。


三、MCP 协议:工具调用的”USB-C 时刻”#

3.1 Function Calling 的局限:每个客户端都要重复实现#

MCP 出现之前,假设你想让自己的 IDE(Cursor、Claude Desktop、Continue)接入你的”团队知识库”,你必须:

  • 给 Cursor 写一个 Cursor Extension
  • 给 Claude Desktop 写一个 Desktop Plugin
  • 给 Continue 写一个 Continue Provider
  • 给 Zed 写一个 Zed Extension

每个 IDE 都要重复适配一次——和 1995 年之前每个外设都要为每台电脑写驱动一样混乱。

MCP 的核心承诺:你只写一次 MCP Server,所有支持 MCP 的客户端(IDE、Agent、桌面应用)都能用

┌──────────────────────────────────────────────────────────┐
│ MCP 生态 │
├──────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Cursor │ │ Claude │ │ Continue │ │ Zed │ │
│ │ (MCP │ │ Desktop │ │ (MCP │ │ (MCP │ │
│ │ Client) │ │ (Client) │ │ Client) │ │ Client) │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │ │
│ └─────────────┴──────┬───────┴─────────────┘ │
│ │ MCP 协议(JSON-RPC 2.0) │
│ ┌───────────┴───────────┐ │
│ │ │ │
│ ┌─────▼─────┐ ┌──────▼──────┐ │
│ │ Filesystem│ │ GitHub │ │
│ │ Server │ │ Server │ │
│ └───────────┘ └─────────────┘ │
│ ┌───────────┐ ┌─────────────┐ │
│ │ Postgres │ │ Brave │ │
│ │ Server │ │ Search │ │
│ └───────────┘ └─────────────┘ │
└──────────────────────────────────────────────────────────┘

3.2 MCP 的四大原语(Primitives)#

MCP 不是”又一个工具调用 API”,它把模型与外部资源的交互抽象成四个原语

原语角色类比典型用途
Tools模型主动调用的”动作”REST POST查数据库、发邮件、写文件
Resources应用读取的”数据”REST GET读文件、读数据库 schema、读知识库
Prompts预定义的 prompt 模板REST 静态资源/review-code、/explain-error
SamplingServer 让 Client 反向调用 LLM服务端回调让 MCP Server 也能”思考”

这个设计的妙处在于:Tools 是”模型 → 外部”的动作,Resources 是”应用 ← 外部”的数据。两者方向相反但都通过同一协议承载,让 LLM 和应用层共享同一套上下文。

3.3 MCP 的传输层(Transport)#

MCP 协议本身是 JSON-RPC 2.0,传输层支持三种:

传输方式适用场景实现
stdio本地进程,Claude Desktop 主流标准输入输出流
HTTP + SSE远程服务器,Streamable HTTP(2025 标准)Server-Sent Events 单向流 + HTTP POST
WebSocket双向长连接(已逐步被 Streamable HTTP 取代)全双工

对绝大多数本地工具来说,stdio 是最简单也最可靠的选择。你的 MCP Server 就是一个命令行进程,通过 stdin/stdout 跟 Client 通信。


四、自建 MCP Server:从零到接入 Claude Desktop#

下面我们手写一个”代码评审助手”MCP Server,让 Claude Desktop 在用户输入”review 一下这个文件”时,自动调用我们的评审逻辑。

4.1 项目结构#

mcp-code-reviewer/
├── pyproject.toml
├── README.md
└── src/
└── mcp_code_reviewer/
├── __init__.py
└── server.py # MCP Server 入口

4.2 安装依赖#

Terminal window
mkdir mcp-code-reviewer && cd mcp-code-reviewer
python -m venv .venv && source .venv/bin/activate
pip install "mcp[cli]">=1.0

4.3 server.py 完整实现(200 行)#

"""
MCP Server: 代码评审助手
功能:
- Tool: review_code(评审一段 Python 代码)
- Tool: check_security(检测常见安全问题)
- Resource: review://rules(评审规则文档)
- Prompt: review-pr(生成 PR 评审 prompt 模板)
"""
import asyncio
import ast
import re
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import (
Tool, TextContent, ImageContent, EmbeddedResource,
Prompt, PromptMessage, PromptArgument,
Resource,
)
# ============ 1. 创建 MCP Server ============
app = Server("code-reviewer")
# ============ 2. 列出可用工具 ============
@app.list_tools()
async def list_tools() -> list[Tool]:
return [
Tool(
name="review_code",
description="对一段 Python 代码进行多维度评审,返回结构化问题列表",
inputSchema={
"type": "object",
"properties": {
"code": {"type": "string", "description": "待评审的 Python 源码"},
"strictness": {
"type": "string",
"enum": ["loose", "normal", "strict"],
"default": "normal",
"description": "评审严格度"
}
},
"required": ["code"]
}
),
Tool(
name="check_security",
description="扫描代码中的常见安全问题(SQL 注入、硬编码密钥、eval、shell 注入等)",
inputSchema={
"type": "object",
"properties": {
"code": {"type": "string"}
},
"required": ["code"]
}
),
]
# ============ 3. 工具实现 ============
SECURITY_RULES = [
(r"\beval\s*\(", "使用了 eval(),存在任意代码执行风险"),
(r"\bexec\s*\(", "使用了 exec(),存在任意代码执行风险"),
(r"subprocess\.(?:call|run|Popen).*shell\s*=\s*True", "subprocess 启用了 shell=True,可能导致命令注入"),
(r"os\.system\s*\(", "os.system() 容易受 shell 注入影响,建议用 subprocess.run 并禁用 shell"),
(r"password\s*=\s*['\"][^'\"]+['\"]", "硬编码了 password 字段"),
(r"api_key\s*=\s*['\"][^'\"]+['\"]", "硬编码了 api_key 字段"),
(r"SELECT.*\+.*FROM", "疑似 SQL 拼接,请使用参数化查询"),
(r"\.format\(.*\).*(?:SELECT|INSERT|DELETE|UPDATE)", "疑似通过 .format() 拼接 SQL"),
(r"pickle\.loads?\s*\(", "pickle 反序列化存在 RCE 风险,请改用 json"),
]
STYLE_RULES = [
(r"except\s*:\s*$", "裸 except 会吞掉所有异常,包括 KeyboardInterrupt"),
(r"except\s+Exception\s*:\s*$", "过于宽泛的异常捕获"),
(r"^\s*print\s*\(", "代码中残留 print 调试语句"),
(r"TODO|FIXME|XXX", "存在未完成的 TODO/FIXME"),
(r"def\s+\w+\([^)]*\)\s*->\s*$", "函数签名末尾缺返回类型注解"),
]
def _review_python(code: str, strictness: str) -> dict:
"""执行评审逻辑"""
issues = []
severities = {"loose": ["high"], "normal": ["high", "medium"], "strict": ["high", "medium", "low"]}
# 静态文本扫描
for pattern, msg in SECURITY_RULES:
if re.search(pattern, code, re.IGNORECASE | re.MULTILINE):
issues.append({
"type": "security",
"severity": "high",
"message": msg,
"line": _find_line(code, pattern)
})
for pattern, msg in STYLE_RULES:
if strictness in ("normal", "strict") and re.search(pattern, code, re.MULTILINE):
issues.append({
"type": "style",
"severity": "medium",
"message": msg,
"line": _find_line(code, pattern)
})
# AST 分析
try:
tree = ast.parse(code)
issues.extend(_ast_analysis(tree, strictness))
except SyntaxError as e:
issues.append({
"type": "syntax",
"severity": "high",
"message": f"语法错误: {e.msg}",
"line": e.lineno
})
# 过滤严重等级
issues = [i for i in issues if i["severity"] in severities.get(strictness, ["high", "medium"])]
# 计算分数
high = sum(1 for i in issues if i["severity"] == "high")
medium = sum(1 for i in issues if i["severity"] == "medium")
low = sum(1 for i in issues if i["severity"] == "low")
score = max(0, 100 - high * 20 - medium * 5 - low * 1)
return {
"score": score,
"summary": f"发现 {len(issues)} 个问题(高:{high} 中:{medium} 低:{low})",
"issues": issues,
"lines_of_code": len(code.splitlines()),
}
def _ast_analysis(tree: ast.AST, strictness: str) -> list[dict]:
"""AST 层面的深度分析"""
issues = []
for node in ast.walk(tree):
# 函数过长
if isinstance(node, ast.FunctionDef):
length = (node.end_lineno or 0) - node.lineno + 1
if length > 50:
issues.append({
"type": "complexity",
"severity": "medium",
"message": f"函数 `{node.name}` 有 {length} 行,建议拆分",
"line": node.lineno,
})
# 圈复杂度估算(if/for/while/except 数)
complexity = sum(
1 for n in ast.walk(node)
if isinstance(n, (ast.If, ast.For, ast.While, ast.ExceptHandler, ast.BoolOp))
)
if complexity > 10:
issues.append({
"type": "complexity",
"severity": "high",
"message": f"函数 `{node.name}` 圈复杂度过高(≈{complexity}),建议提取子函数",
"line": node.lineno,
})
# 全局可变状态
if isinstance(node, ast.Global):
issues.append({
"type": "anti-pattern",
"severity": "medium",
"message": "使用了 global 语句,可能破坏封装",
"line": node.lineno,
})
return issues
def _find_line(code: str, pattern: str) -> int:
"""找到 pattern 第一次出现的行号"""
m = re.search(pattern, code, re.IGNORECASE | re.MULTILINE)
return m.start() // 80 + 1 if m else 0 # 粗略估算
# ============ 4. 工具分发 ============
@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
if name == "review_code":
result = _review_python(arguments["code"], arguments.get("strictness", "normal"))
return [TextContent(type="text", text=_format_review(result))]
elif name == "check_security":
issues = []
for pattern, msg in SECURITY_RULES:
if re.search(pattern, arguments["code"], re.IGNORECASE | re.MULTILINE):
issues.append(f"⚠️ 第 { _find_line(arguments['code'], pattern) } 行: {msg}")
text = "未发现安全问题 ✅" if not issues else "\n".join(issues)
return [TextContent(type="text", text=text)]
raise ValueError(f"未知工具: {name}")
def _format_review(result: dict) -> str:
out = [f"📊 代码评分: **{result['score']}/100**", result['summary'], ""]
for issue in result['issues']:
emoji = {"high": "🔴", "medium": "🟡", "low": "🟢"}[issue['severity']]
out.append(f"{emoji} [{issue['type']}] 第 {issue['line']} 行: {issue['message']}")
return "\n".join(out)
# ============ 5. Resources(应用读取的数据)============
@app.list_resources()
async def list_resources() -> list[Resource]:
return [
Resource(
uri="review://rules",
name="评审规则文档",
description="当前 MCP Server 使用的所有评审规则",
mimeType="text/markdown"
)
]
@app.read_resource()
async def read_resource(uri: str) -> str:
if uri == "review://rules":
rules_md = "# 评审规则\n\n## 安全规则\n"
for pattern, msg in SECURITY_RULES:
rules_md += f"- `{pattern}` → {msg}\n"
rules_md += "\n## 风格规则\n"
for pattern, msg in STYLE_RULES:
rules_md += f"- `{pattern}` → {msg}\n"
return rules_md
raise ValueError(f"未知资源: {uri}")
# ============ 6. Prompts(预定义模板)============
@app.list_prompts()
async def list_prompts() -> list[Prompt]:
return [
Prompt(
name="review-pr",
description="生成 PR 评审 prompt 模板",
arguments=[
PromptArgument(
name="diff",
description="PR 的 diff 内容",
required=True
)
]
)
]
@app.get_prompt()
async def get_prompt(name: str, arguments: dict) -> list[PromptMessage]:
if name == "review-pr":
return [
PromptMessage(
role="user",
content=TextContent(
type="text",
text=f"请评审以下 PR diff,重点关注正确性、安全性、性能:\n\n```diff\n{arguments['diff']}\n```"
)
)
]
raise ValueError(f"未知 prompt: {name}")
# ============ 7. 启动 Server ============
async def main():
async with stdio_server() as (read_stream, write_stream):
await app.run(
read_stream,
write_stream,
app.create_initialization_options()
)
if __name__ == "__main__":
asyncio.run(main())

4.4 接入 Claude Desktop#

编辑 ~/Library/Application Support/Claude/claude_desktop_config.json(macOS)或 %APPDATA%\Claude\claude_desktop_config.json(Windows):

{
"mcpServers": {
"code-reviewer": {
"command": "/绝对路径/mcp-code-reviewer/.venv/bin/python",
"args": ["-m", "mcp_code_reviewer.server"]
}
}
}

重启 Claude Desktop 后,你就能在对话中直接说”帮我 review 一下这段代码”,Claude 会自动调用我们的 review_code 工具。

4.5 用 MCP Inspector 调试#

Terminal window
# 安装官方调试工具
pip install "mcp[cli]"
# 启动 Inspector 调试你的 Server
mcp dev src/mcp_code_reviewer/server.py

打开 http://localhost:5173 就能可视化调用所有 Tools、读取 Resources、应用 Prompts。


五、用 Claude Agent SDK 消费 MCP Server#

5.1 什么是 Claude Agent SDK?#

Anthropic 在 2025 年发布的 claude-agent-sdk,把 Claude 的 tool use 能力封装成了一个完整的 Agent 运行时。它原生支持 MCP,意味着你可以直接用 Python SDK 调用任何 MCP Server。

Terminal window
pip install claude-agent-sdk

5.2 完整可运行示例#

"""
Claude Agent SDK + MCP Server:让 Claude 调用我们的代码评审工具
"""
import anyio
from claude_agent_sdk import query, ClaudeAgentOptions
async def main():
options = ClaudeAgentOptions(
model="claude-sonnet-4-5",
system_prompt="你是一个代码评审专家,使用 review_code 工具评审用户提交的代码。",
mcp_servers={
"code-reviewer": {
"command": "python",
"args": ["-m", "mcp_code_reviewer.server"],
}
},
allowed_tools=["review_code", "check_security"],
max_turns=5,
)
code_to_review = """
def get_user(user_id):
password = "admin123"
query = "SELECT * FROM users WHERE id = " + user_id
result = eval(query)
return result
"""
async for message in query(
prompt=f"请评审以下代码:\n```python\n{code_to_review}\n```",
options=options,
):
if hasattr(message, "content"):
print(message.content)
anyio.run(main)

运行后,Claude 会自动调用我们的 MCP Server 并返回结构化评审报告。


六、MCP 生态全景与选型建议#

6.1 主流 MCP Server 一览(截至 2026 年)#

类别官方/社区 Server能力
文件系统@modelcontextprotocol/server-filesystem读/写/搜索本地文件
Git@modelcontextprotocol/server-git查看 commit、diff、blame
GitHub@modelcontextprotocol/server-github读 issue、PR、code search
Postgres@modelcontextprotocol/server-postgresSQL 查询、schema 导出
Puppeteer@modelcontextprotocol/server-puppeteer浏览器自动化、截图
Brave Search@modelcontextprotocol/server-brave-search网络搜索
Slack@modelcontextprotocol/server-slack发消息、读频道

6.2 自建 MCP Server 的三个时机#

时机场景推荐方案
个人工具把自己的脚本暴露给 IDEstdio MCP Server + Claude Desktop
团队协作团队内部的”知识库工具集”Streamable HTTP MCP Server + 内部 IDE
商业产品SaaS 平台开放给客户 AgentRemote MCP Server + OAuth 鉴权

6.3 Function Calling 与 MCP 的关系#

很多团队会纠结:到底该直接用 Function Calling,还是上 MCP?

经验法则

  • 单一模型 + 单一客户端 → Function Calling 直接调 SDK 最简单
  • 多客户端复用 + 工具需要权限管理 → MCP Server 是更好的选择
  • 企业内部 Agent 平台 → MCP 是事实标准,建议直接拥抱

Function Calling 和 MCP 不是替代关系:MCP Server 内部还是要用 SDK 的 Function Calling 能力(Tool Use);Function Calling 是协议层,MCP 是架构层。


七、性能与安全注意事项#

7.1 性能优化#

  • stdio 进程池:每次调用 stdio MCP Server 都要启动一个新进程会有 ~100ms 开销,对短任务用进程池复用,对长任务用 HTTP+SSE
  • 工具描述要”短而精”:每个 Tool 的 description 占几百 token,多了会爆 context window
  • Streaming 优先:所有支持流式的 Client 都应该用 streaming,避免长任务阻塞

7.2 安全边界#

风险缓解措施
任意代码执行Tool description 明确权限范围,Client 端需要 user confirmation
密钥泄露MCP Server 通过环境变量读密钥,不要硬编码
SSRFHTTP 类 Tool 限制允许域名
Prompt InjectionTool 返回值要 sanitize,不要让 Tool 输出被解释为新指令

八、总结与延伸阅读#

核心要点#

  1. Function Calling 是工具调用的”协议层”——OpenAI tools、Claude Tool Use、Gemini Function Calling 在字段命名上有差异但思想一致
  2. MCP 是工具调用的”架构层”——通过 JSON-RPC + Resources/Prompts/Tools/Sampling 四原语 + stdio/HTTP/WebSocket 传输,实现”一次开发、多端复用”
  3. 2026 年,MCP 已成为 Agent 生态事实标准——Cursor、Claude Desktop、Continue、Zed 全栈接入,OpenAI Agent SDK 也已支持
  4. Function Calling 与 MCP 不是替代关系——MCP Server 内部仍然依赖各模型的 Function Calling 能力

行动清单#

  • ✅ 跑通官方 mcp-server-git 示例,理解 MCP 协议交互
  • ✅ 用 Python SDK 写一个 stdio MCP Server,对接 Claude Desktop
  • ✅ 在 Cursor 中配置 MCP Server,体验”一次开发、多端复用”
  • ✅ 阅读 Claude Agent SDK 文档,了解生产级 MCP 部署

延伸阅读#

资源链接
MCP 协议规范https://modelcontextprotocol.io
OpenAI Function Calling 文档https://platform.openai.com/docs/guides/function-calling
Claude Tool Use 指南https://docs.anthropic.com/en/docs/tool-use
Claude Agent SDK 文档https://docs.anthropic.com/en/api/agent-sdk
MCP Server 集合https://github.com/modelcontextprotocol/servers
Instructor(Python 结构化输出)https://github.com/jxnl/instructor
配套源码https://github.com/anthropics/mcp-python-sdk

工具调用这件事正在从”模型 API 的一个参数”演化成”Agent 时代的网络协议”。理解 MCP,不仅是为了接一个 IDE,而是为了在下一代 AI 应用架构里有一席之地。


作者:wyb_001 | 博客https://boke.hackerdream.xyz发布时间:2026-06-21

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

AI 函数调用与 MCP 协议深度解析:从 OpenAI tools 到 Model Context Protocol
https://boke.hackerdream.xyz/posts/ai-function-calling-mcp/
作者
晴天
发布于
2026-06-21
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
晴天
Hello, I'm 晴天.
公告
欢迎来到我的博客!这是一则示例公告。
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
155
分类
24
标签
387
总字数
345,424
运行时长
0
最后活动
0 天前

目录