从源码角度深度剖析MCP协议:AI工具调用的「USB-C」时刻来了

作者说: 2025年,Anthropic扔出了MCP(Model Context Protocol)协议,宣称要让AI工具调用像USB-C一样即插即用。这不是营销话术——从源码拆解来看,MCP确实解决了一个真实痛点。本文从协议设计、源码实现、实战踩坑三个维度,把MCP说透。


目录


1. 背景:为什么AI工具调用这么痛苦

1.1 工具调用范式的演进

在MCP出现之前,AI Agent调用外部工具经历了三个阶段:

第一阶段:Function Calling(2023)
├── 每个模型有自己的function calling格式
├── OpenAI用function call,Claude用tool use
└── 问题:格式不通用,换模型要重写

第二阶段:Tool Use协议(2023-2024)
├── 各平台逐步标准化
├── JSON Schema定义工具签名
└── 问题:每个工具集都要独立适配,没有统一传输层

第三阶段:MCP协议(2025)
├── 统一的工具发现 + 调用 + 传输协议
├── 服务端/客户端分离架构
└── 核心解决:一次实现,到处调用

1.2 MCP解决的核心问题

MCP解决的不是「如何让AI调用工具」,而是**「如何让工具以一种标准方式被任何AI调用」**。

没有MCP时:
AI模型A → [专有适配器] → 工具X
AI模型B → [专有适配器] → 工具X  ← 重写!
AI模型C → [专有适配器] → 工具X  ← 又要重写!

有MCP后:
工具X → [MCP Server] → MCP Client(通用)→ AI模型A/B/C

MCP的本质:把「工具适配」变成一次性的基础设施工作。


2. MCP协议架构解析

2.1 协议分层

MCP采用三层协议架构:

┌─────────────────────────────────────┐
│     Application Layer(应用层)      │  ← AI模型理解的部分
│   prompts / resources / tools        │
├─────────────────────────────────────┤
│     Protocol Layer(协议层)          │  ← JSON-RPC 2.0消息格式
│   JSON-RPC 2.0 + MCP Message Types   │
├─────────────────────────────────────┤
│     Transport Layer(传输层)         │  ← 支持stdio / HTTP(SSE)
│       stdio / HTTP + SSE              │
└─────────────────────────────────────┘

2.2 核心消息类型

MCP定义了三类核心能力,通过JSON-RPC 2.0协议传输:

// 1. 工具调用请求(Client → Server)
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "filesystem_read_file",
    "arguments": {
      "path": "/data/config.json"
    }
  }
}

// 2. 工具列表响应(Server → Client)
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "filesystem_read_file",
        "description": "读取文件内容",
        "inputSchema": {
          "type": "object",
          "properties": {
            "path": {
              "type": "string",
              "description": "文件路径"
            }
          },
          "required": ["path"]
        }
      }
    ]
  }
}

// 3. 资源访问请求(Client → Server)
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "resources/list",
  "params": {}
}

2.3 传输层:stdio vs HTTP

MCP支持两种传输方式,适用于不同场景:

传输方式适用场景优点缺点
stdio本地进程通信(Claude Desktop等)简单、安全、易调试不适合远程
HTTP+SSE远程服务支持分布式部署需要处理连接管理
# stdio模式:子进程启动
# MCP Server作为子进程,通过stdin/stdout通信

# HTTP+SSE模式:远程服务
# MCP Server作为HTTP服务,Client通过HTTP请求通信

3. 源码级协议实现拆解

3.1 MCP SDK核心类图

以官方Python SDK(mcp-sdk)为例,核心类的设计:

# mcp/server/models.py(简化版核心模型)

class Tool:
    """工具定义"""
    def __init__(
        self,
        name: str,                    # 工具唯一标识
        description: str,              # AI模型用于理解工具用途
        inputSchema: dict,            # JSON Schema格式的参数定义
    ):
        self.name = name
        self.description = description
        self.inputSchema = inputSchema

class Resource:
    """资源定义 - 供AI读取的上下文数据"""
    def __init__(
        self,
        uri: str,                     # 资源唯一标识(格式:scheme://path)
        name: str,
        description: str = None,
        mimeType: str = "text/plain",
    ):
        self.uri = uri
        self.name = name
        self.description = description
        self.mimeType = mimeType

class Prompt:
    """提示模板 - AI可调用的提示工程组件"""
    def __init__(
        self,
        name: str,
        description: str,
        arguments: list[PromptArgument] = None,  # 可选参数
    ):
        self.name = name
        self.description = description
        self.arguments = arguments or []

3.2 Server生命周期源码解析

# mcp/server/server.py(核心逻辑简化)

class MCPServer:
    """MCP Server主类"""
    
    def __init__(self, name: str):
        self.name = name
        self._tools: dict[str, Tool] = {}
        self._resources: dict[str, Resource] = {}
        self._prompts: dict[str, Prompt] = {}
        self._request_handlers: dict[str, Callable] = {}
        
        # 注册内置的协议方法处理器
        self._register_protocol_handlers()
    
    def _register_protocol_handlers(self):
        """MCP协议规定必须支持的6个基础方法"""
        self._request_handlers["initialize"] = self._handle_initialize
        self._request_handlers["tools/list"] = self._handle_tools_list
        self._request_handlers["tools/call"] = self._handle_tools_call
        self._request_handlers["resources/list"] = self._handle_resources_list
        self._request_handlers["resources/read"] = self._handle_resources_read
        self._request_handlers["prompts/list"] = self._handle_prompts_list
    
    async def _handle_initialize(self, params: dict) -> dict:
        """
        握手初始化 - MCP协议的第一步
        Client发送AI模型的能力,Server回复自己支持的能力
        """
        client_info = params.get("clientInfo", {})
        protocol_version = params.get("protocolVersion", "2024-11-05")
        
        return {
            "protocolVersion": protocol_version,
            "serverInfo": {
                "name": self.name,
                "version": "1.0.0"
            },
            "capabilities": {
                "tools": {"listChanged": True},  # 声明支持工具变更通知
                "resources": {"subscribe": True, "listChanged": True},
                "prompts": {"listChanged": True}
            }
        }
    
    async def _handle_tools_list(self, params: dict) -> dict:
        """返回所有可用工具"""
        return {
            "tools": [
                {
                    "name": tool.name,
                    "description": tool.description,
                    "inputSchema": tool.inputSchema
                }
                for tool in self._tools.values()
            ]
        }
    
    async def _handle_tools_call(self, params: dict) -> dict:
        """
        工具调用 - 核心方法
        AI模型通过这个方法真正执行工具逻辑
        """
        tool_name = params["name"]
        arguments = params.get("arguments", {})
        
        if tool_name not in self._tools:
            raise McpError(f"Unknown tool: {tool_name}")
        
        tool = self._tools[tool_name]
        
        # 参数验证(基于JSON Schema)
        self._validate_arguments(tool.inputSchema, arguments)
        
        # 调用工具处理函数
        handler = self._tool_handlers[tool_name]
        result = await handler(**arguments)
        
        return {
            "content": [
                {
                    "type": "text",
                    "text": json.dumps(result, ensure_ascii=False)
                }
            ],
            "isError": False
        }

3.3 JSON Schema验证逻辑

工具调用的参数验证是MCP的核心安全机制:

# mcp/server/validation.py(参数验证核心逻辑)

def validate_input_schema(schema: dict, arguments: dict) -> list[str]:
    """
    验证工具调用参数是否符合inputSchema定义
    返回错误信息列表,空列表表示验证通过
    """
    errors = []
    
    # 检查必填参数
    required = schema.get("required", [])
    for field in required:
        if field not in arguments:
            errors.append(f"Missing required field: {field}")
    
    # 检查每个提供的参数
    properties = schema.get("properties", {})
    for key, value in arguments.items():
        if key not in properties:
            errors.append(f"Unknown field: {key}")
            continue
        
        prop_schema = properties[key]
        type_expected = prop_schema.get("type")
        
        # 类型检查
        if type_expected and not _check_type(value, type_expected):
            errors.append(
                f"Field '{key}' expected type '{type_expected}', "
                f"got '{type(value).__name__}'"
            )
        
        # 枚举值检查
        if "enum" in prop_schema and value not in prop_schema["enum"]:
            errors.append(
                f"Field '{key}' must be one of {prop_schema['enum']}, "
                f"got '{value}'"
            )
    
    return errors

4. 实战:5分钟跑通MCP Server

4.1 环境准备

# 安装MCP Python SDK
pip install mcp

# 验证安装
python -c "import mcp; print(mcp.__version__)"

4.2 最简MCP Server:5步创建

完整代码(server.py):

#!/usr/bin/env python3
"""
MCP Server 极简示例:文件搜索工具
功能:AI可以通过此Server搜索本地文件内容
"""

import mcp.server.stdio
import mcp.types as types
from pathlib import Path
import json
import asyncio


class FileSearchServer:
    """文件搜索MCP Server"""
    
    def __init__(self):
        self.search_history = []  # 记录搜索历史
    
    # ========== 工具定义 ==========
    
    def get_tools(self) -> list[types.Tool]:
        """定义Server提供的工具"""
        return [
            types.Tool(
                name="file_search",
                description=(
                    "在指定目录中搜索包含关键词的文件。"
                    "支持TXT、MD、JSON、PY文件类型。"
                    "返回匹配文件的路径和行号。"
                ),
                inputSchema={
                    "type": "object",
                    "properties": {
                        "directory": {
                            "type": "string",
                            "description": "要搜索的目录路径"
                        },
                        "keyword": {
                            "type": "string",
                            "description": "搜索关键词(支持正则)"
                        },
                        "file_type": {
                            "type": "string",
                            "description": "文件类型过滤,如 'py', 'md'",
                            "enum": ["py", "md", "txt", "json", "all"],
                            "default": "all"
                        },
                        "max_results": {
                            "type": "integer",
                            "description": "最大返回结果数",
                            "default": 20,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    "required": ["directory", "keyword"]
                }
            ),
            types.Tool(
                name="file_read",
                description="读取文件内容并返回指定行范围",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "path": {
                            "type": "string",
                            "description": "文件完整路径"
                        },
                        "start_line": {
                            "type": "integer",
                            "description": "起始行号(1-based)",
                            "default": 1
                        },
                        "end_line": {
                            "type": "integer",
                            "description": "结束行号(含)",
                            "default": 100
                        }
                    },
                    "required": ["path"]
                }
            )
        ]
    
    # ========== 工具处理逻辑 ==========
    
    async def handle_tool_call(
        self,
        name: str,
        arguments: dict
    ) -> list[types.ContentBlock]:
        """工具调用入口"""
        if name == "file_search":
            return await self._handle_file_search(**arguments)
        elif name == "file_read":
            return await self._handle_file_read(**arguments)
        else:
            raise ValueError(f"Unknown tool: {name}")
    
    async def _handle_file_search(
        self,
        directory: str,
        keyword: str,
        file_type: str = "all",
        max_results: int = 20
    ) -> list[types.ContentBlock]:
        """执行文件搜索"""
        import re
        
        dir_path = Path(directory)
        if not dir_path.exists():
            return [types.TextContent(
                text=json.dumps({"error": f"目录不存在: {directory}"}, ensure_ascii=False)
            )]
        
        # 确定搜索的文件类型
        extensions = {
            "py": [".py"],
            "md": [".md"],
            "txt": [".txt"],
            "json": [".json"],
            "all": [".py", ".md", ".txt", ".json", ".yaml", ".yml"]
        }.get(file_type, [".py", ".md", ".txt", ".json"])
        
        results = []
        pattern = re.compile(keyword, re.IGNORECASE)
        
        for ext in extensions:
            for file_path in dir_path.rglob(f"*{ext}"):
                try:
                    with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
                        for line_no, line in enumerate(f, 1):
                            if pattern.search(line):
                                results.append({
                                    "file": str(file_path),
                                    "line": line_no,
                                    "content": line.strip()[:200]
                                })
                                if len(results) >= max_results:
                                    break
                except Exception:
                    continue
                
                if len(results) >= max_results:
                    break
            
            if len(results) >= max_results:
                break
        
        self.search_history.append({
            "keyword": keyword,
            "directory": directory,
            "results_count": len(results)
        })
        
        return [types.TextContent(
            text=json.dumps({
                "keyword": keyword,
                "total_matches": len(results),
                "results": results
            }, ensure_ascii=False, indent=2)
        )]
    
    async def _handle_file_read(
        self,
        path: str,
        start_line: int = 1,
        end_line: int = 100
    ) -> list[types.ContentBlock]:
        """读取文件指定行范围"""
        file_path = Path(path)
        
        if not file_path.exists():
            return [types.TextContent(
                text=json.dumps({"error": f"文件不存在: {path}"}, ensure_ascii=False)
            )]
        
        try:
            with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
                lines = f.readlines()
            
            # 提取指定范围(处理越界情况)
            start = max(0, start_line - 1)
            end = min(len(lines), end_line)
            content_lines = lines[start:end]
            
            result = {
                "path": str(file_path),
                "total_lines": len(lines),
                "read_range": f"{start_line}-{end_line}",
                "content": "".join(content_lines)
            }
            
            return [types.TextContent(
                text=json.dumps(result, ensure_ascii=False, indent=2)
            )]
        except Exception as e:
            return [types.TextContent(
                text=json.dumps({"error": str(e)}, ensure_ascii=False)
            )]


# ========== MCP Server启动 ==========

async def main():
    """MCP Server主入口"""
    server = FileSearchServer()
    
    # 使用stdio传输层启动
    # stdin接收请求,stdout返回响应
    async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
        await mcp.server.Server(
            name="file-search-server",
            version="1.0.0",
            tools=server.get_tools(),
        ).run(
            read_stream,
            write_stream,
            server.handle_tool_call,
        )


if __name__ == "__main__":
    asyncio.run(main())

4.3 调试与验证

# 方式1:使用MCP Inspector调试
npx @anthropic-ai/mcp-inspector python server.py

# 方式2:直接运行测试stdio通信
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \
  | python server.py

# 预期输出:返回tools列表(JSON格式)

4.4 接入Claude Desktop

// ~/.config/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "file-search": {
      "command": "python",
      "args": ["/path/to/server.py"]
    }
  }
}

重启Claude Desktop后,说出指令:

“帮我搜索 /project/src 目录下所有包含 async def 的Python文件”

Claude会通过MCP协议自动调用 file_search 工具。


5. 生产级实战:构建RAG检索MCP Server

5.1 需求场景

构建一个向量检索MCP Server,让AI能够:

  1. 检索知识库中的相关文档
  2. 获取文档片段作为上下文
  3. 支持语义相似度搜索

5.2 完整实现

#!/usr/bin/env python3
"""
RAG检索MCP Server
功能:提供向量语义检索能力,支持本地知识库问答
依赖:pip install mcp chromadb sentence-transformers
"""

import mcp.server.stdio
import mcp.types as types
import chromadb
from chromadb.config import Settings
from sentence_transformers import SentenceTransformer
import json
import asyncio
import os
from pathlib import Path


class RAGMCPServer:
    """基于向量数据库的RAG检索服务"""
    
    def __init__(
        self,
        collection_name: str = "knowledge_base",
        model_name: str = "paraphrase-multilingual-MiniLM-L12-v2"
    ):
        # 初始化向量数据库(Chroma持久化存储)
        self.client = chromadb.Client(Settings(
            persist_directory="./chroma_db",
            anonymized_telemetry=False
        ))
        
        # 获取或创建集合
        try:
            self.collection = self.client.get_collection(collection_name)
        except Exception:
            self.collection = self.client.create_collection(
                name=collection_name,
                metadata={"description": "知识库向量集合"}
            )
        
        # 加载Embedding模型
        self.encoder = SentenceTransformer(model_name)
        self.collection_name = collection_name
        
        # 索引映射(ID → 元数据)
        self._id_metadata: dict[str, dict] = {}
    
    def get_tools(self) -> list[types.Tool]:
        return [
            types.Tool(
                name="rag_search",
                description=(
                    "在知识库中检索与查询最相关的文档片段。"
                    "使用语义相似度搜索,返回最相关的N条结果。"
                    "适用于:技术问题解答、文档查询、代码检索等场景。"
                ),
                inputSchema={
                    "type": "object",
                    "properties": {
                        "query": {
                            "type": "string",
                            "description": "语义检索查询"
                        },
                        "top_k": {
                            "type": "integer",
                            "description": "返回的最相关结果数量",
                            "default": 5,
                            "minimum": 1,
                            "maximum": 20
                        },
                        "min_similarity": {
                            "type": "number",
                            "description": "最小相似度阈值(0-1)",
                            "default": 0.5,
                            "minimum": 0.0,
                            "maximum": 1.0
                        }
                    },
                    "required": ["query"]
                }
            ),
            types.Tool(
                name="rag_index_document",
                description=(
                    "将文档内容索引到知识库。"
                    "支持自动分块、向量化和存储。"
                    "块大小默认500字符,重叠50字符。"
                ),
                inputSchema={
                    "type": "object",
                    "properties": {
                        "content": {
                            "type": "string",
                            "description": "要索引的文档内容"
                        },
                        "doc_id": {
                            "type": "string",
                            "description": "文档唯一标识"
                        },
                        "metadata": {
                            "type": "object",
                            "description": "文档元数据(如标题、来源、时间)",
                            "properties": {
                                "title": {"type": "string"},
                                "source": {"type": "string"},
                                "tags": {"type": "array", "items": {"type": "string"}}
                            }
                        },
                        "chunk_size": {
                            "type": "integer",
                            "description": "分块大小(字符数)",
                            "default": 500,
                            "minimum": 100,
                            "maximum": 2000
                        }
                    },
                    "required": ["content", "doc_id"]
                }
            ),
            types.Tool(
                name="rag_get_stats",
                description="获取知识库统计信息:文档数、块数、集合配置",
                inputSchema={
                    "type": "object",
                    "properties": {}
                }
            )
        ]
    
    async def handle_tool_call(
        self,
        name: str,
        arguments: dict
    ) -> list[types.ContentBlock]:
        if name == "rag_search":
            return await self._handle_search(**arguments)
        elif name == "rag_index_document":
            return await self._handle_index(**arguments)
        elif name == "rag_get_stats":
            return await self._handle_stats()
        raise ValueError(f"Unknown tool: {name}")
    
    def _chunk_text(self, text: str, chunk_size: int, overlap: int = 50) -> list[str]:
        """将长文本按指定大小分块,支持重叠"""
        chunks = []
        start = 0
        while start < len(text):
            end = start + chunk_size
            chunks.append(text[start:end])
            start = end - overlap
        return chunks
    
    async def _handle_index(
        self,
        content: str,
        doc_id: str,
        metadata: dict = None,
        chunk_size: int = 500
    ) -> list[types.ContentBlock]:
        """索引文档"""
        metadata = metadata or {}
        
        # 分块处理
        chunks = self._chunk_text(content, chunk_size)
        
        # 批量生成向量
        embeddings = self.encoder.encode(chunks).tolist()
        
        # 批量添加(带ID)
        ids = [f"{doc_id}_chunk_{i}" for i in range(len(chunks))]
        
        # 存储元数据
        for i, chunk in enumerate(chunks):
            self._id_metadata[ids[i]] = {
                "doc_id": doc_id,
                "chunk_index": i,
                "total_chunks": len(chunks),
                **metadata
            }
        
        self.collection.add(
            embeddings=embeddings,
            documents=chunks,
            ids=ids,
            metadatas=[self._id_metadata[uid] for uid in ids]
        )
        
        return [types.TextContent(
            text=json.dumps({
                "success": True,
                "doc_id": doc_id,
                "chunks_indexed": len(chunks),
                "chunk_size": chunk_size
            }, ensure_ascii=False)
        )]
    
    async def _handle_search(
        self,
        query: str,
        top_k: int = 5,
        min_similarity: float = 0.5
    ) -> list[types.ContentBlock]:
        """语义检索"""
        # 生成查询向量
        query_embedding = self.encoder.encode([query]).tolist()[0]
        
        # 向量检索
        results = self.collection.query(
            query_embeddings=[query_embedding],
            n_results=top_k,
            include=["documents", "metadatas", "distances"]
        )
        
        # 整理结果
        documents = results.get("documents", [[]])[0]
        metadatas = results.get("metadatas", [[]])[0]
        distances = results.get("distances", [[]])[0]
        
        # 过滤低相似度结果(Chroma用L2距离,转为相似度)
        similarity_scores = [1 - d / 2 for d in distances]  # 近似转换
        filtered = [
            {
                "content": doc,
                "metadata": meta,
                "similarity": round(score, 4)
            }
            for doc, meta, score in zip(documents, metadatas, similarity_scores)
            if score >= min_similarity
        ]
        
        return [types.TextContent(
            text=json.dumps({
                "query": query,
                "results_count": len(filtered),
                "results": filtered
            }, ensure_ascii=False, indent=2)
        )]
    
    async def _handle_stats(self) -> list[types.ContentBlock]:
        return [types.TextContent(
            text=json.dumps({
                "collection_name": self.collection_name,
                "total_chunks": self.collection.count(),
                "unique_docs": len(set(
                    m.get("doc_id") 
                    for m in self._id_metadata.values()
                )),
                "embedding_model": self.encoder.model_name
            }, ensure_ascii=False)
        )]


async def main():
    server = RAGMCPServer()
    
    async with mcp.server.stdio.stdio_server() as (read, write):
        await mcp.server.Server(
            name="rag-search-server",
            version="1.0.0",
            tools=server.get_tools()
        ).run(read, write, server.handle_tool_call)


if __name__ == "__main__":
    asyncio.run(main())

5.3 完整使用流程

# 使用示例:通过Claude自然语言调用

"""
用户: "我之前写过一篇关于PostgreSQL索引优化的笔记,
      里面提到BRIN索引的适用场景,能帮我找出来吗?"

Claude通过MCP调用:
  → rag_search(query="PostgreSQL BRIN索引 适用场景", top_k=5)

返回结果(JSON格式):
  {
    "query": "PostgreSQL BRIN索引 适用场景",
    "results_count": 2,
    "results": [
      {
        "content": "BRIN索引适合时序数据...\n列如日志表...",
        "metadata": {"doc_id": "postgres_notes_001", "title": "索引优化实践"},
        "similarity": 0.8723
      }
    ]
  }
"""

6. 当前局限性与未来方向

6.1 当前版本的局限性

问题说明当前解决方案
无状态限制stdio模式下无会话管理,复杂Agent需要自己维护状态外部状态存储(如Redis)
安全保障缺失Server可以读写任意文件/执行任意命令目前靠信任链,未来需要权限模型
性能瓶颈Python GIL限制高并发场景可用uvicorn包装为HTTP服务
模型适配各AI模型对MCP的Tool调用策略不同需要针对模型调整Prompt
调试困难stdio模式下错误信息不够友好使用MCP Inspector辅助调试

6.2 社区动态与未来方向

根据2025-2026年MCP社区的演进趋势:

2025 Q1: 工具发现协议稳定
2025 Q2: MCP Hub发布,支持Server注册与发现
2025 Q3: 安全认证模型草案(MCP Auth)
2025 Q4: 多模态MCP扩展(图像、音频工具支持)
2026 Q1: 企业级MCP Gateway(认证、限流、审计)

7. 总结与参考资料

7.1 核心要点回顾

┌──────────────────────────────────────────────────────────┐
│                     MCP 核心知识图谱                      │
├──────────────────────────────────────────────────────────┤
│ 协议架构:Application Layer → Protocol Layer → Transport │
│ 传输方式:stdio(本地)| HTTP+SSE(远程)                 │
│ 消息格式:JSON-RPC 2.0                                    │
│ 三大能力:Tools(工具调用)/ Resources(资源访问)/        │
│           Prompts(提示模板)                             │
│ 参数验证:JSON Schema + 类型检查                          │
│ 工具发现:tools/list → tools/call 两步流程               │
└──────────────────────────────────────────────────────────┘

7.2 快速开发 Checklist

  • 明确Server能力边界(不要做太多,也不要太少)
  • 工具description写清楚(这是AI理解你的工具的唯一依据)
  • inputSchema用JSON Schema规范定义
  • 参数验证要全面(防止AI传非法参数)
  • 返回结果用结构化JSON,便于AI解析
  • 添加错误处理,不要让Server直接crash
  • 优先实现stdio模式,验证通过后再扩展HTTP

7.3 参考资料

  1. MCP官方文档
  2. MCP Python SDK源码
  3. Anthropic MCP Specification
  4. Chroma向量数据库文档
  5. Sentence-Transformers文档

写在最后

MCP的价值不在于「有没有」,而在于「生态成熟度」。当前阶段,它解决的是协议层的问题,但工具的安全性、性能、企业级治理,还需要社区进一步推进。如果你有具体的MCP开发场景,欢迎在评论区交流。

相关项目代码已上传至:[GitHub仓库链接](如需)

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐