[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$ftJFsggetSu6FFpWt4lKEIZesKO1Rjf0Nw6qdDooKfxM":3,"$fAGeCrnAjf82vVe3UmyInstQgLHh01gUJAU8zlFI3a-I":43},[4],{"id":5,"type":6,"title":7,"slug":8,"summary":9,"body":10,"coverUrl":11,"productScreenshots":12,"productLinks":13,"authorName":14,"authorUrl":15,"authorSubject":16,"category":17,"tags":22,"sourceLabel":35,"sourceName":35,"sourceUrl":35,"status":36,"seoTitle":35,"seoDescription":35,"canonicalUrl":35,"isFeatured":37,"sno":38,"sortOrder":39,"publishedAt":40,"updatedAt":41,"createdAt":42},"544fc658-c911-4de6-93b0-d2520087119a","article","MCP：AI 的「USB-C」时刻","mcp-ai-usb-c-moment","以前每个 AI 应用都要为 GitHub、数据库、日历各写一套私有连接器，这是 M×N 的集成噩梦，直到 MCP 的出现","如果你用过笔记本电脑，一定熟悉那种「每个设备一根专属线」的烦躁：鼠标一个接口、打印机另一个、硬盘又一个。2025 年之前的 AI 应用，几乎就是这种状态——想让一个助手同时读你的代码仓库、查数据库、发日历邀请，开发团队得为每一个系统写一套私有「连接器」，又脆又难维护。\n\n## 背景：每个 Agent 都曾是孤岛\n\n大模型本身只会「说话」，它要真正干活，得去调工具、读数据。在 MCP（Model Context Protocol，模型上下文协议）出现之前，这套对接是组合爆炸：假设市面上有 M 个 AI 客户端、N 个工具，开发者就要写 M×N 套集成。一个代码助手要读 Git、查 Jira、搜文档，就得维护三条互不相通的管线。\n\n更糟的是，这些连接器大多只服务某一个产品，换个助手就得重写。结果就是：每个 Agent 都困在自己的小岛上，能力被锁死在少数几个硬编码的集成里。\n\n## MCP 是什么：AI 世界的「USB-C」\n\n2024 年底，Anthropic 发布了 MCP。它的目标很朴素：给「AI 连工具」定义一个统一接口，就像 USB-C 给「设备连外设」定义统一接口一样。\n\n打个比方——如果大模型是大脑，那 MCP 就是手。大脑再聪明，没有手也打不开文件、点不了按钮、查不了数据库。MCP 让任意符合规范的「大脑」（Claude、ChatGPT、Gemini、Cursor、VS Code Copilot）都能使用任意符合规范的「手」（一个封装好的工具服务），而且不用为每个组合单独适配。\n\n2025 年 12 月，Anthropic 把 MCP 捐给了 Linux 基金会，OpenAI、Google、Microsoft 作为联合发起人。到 2026 年，它的 SDK 月下载量超过 9700 万次，ChatGPT、Claude、Gemini 都支持同一个协议——某种意义上，这场标准之战已经赢了。\n\n## 它是怎么运作的：三层结构\n\nMCP 把「连工具」拆成三个角色，理解这三层就理解了全部：\n\n- **Host（宿主）**：你直接使用的应用，比如 Claude 桌面端、VS Code、一个自定义聊天机器人。\n- **Client（客户端）**：住在 Host 内部、专门负责管理 MCP 连接的小组件。\n- **Server（服务端）**：一个轻量程序，把某个能力「暴露」出来，比如一个 GitHub 服务、一个数据库查询服务。\n\n每个 Server 通过三种「原语」提供能力：`Tools`（AI 可以调用的可执行函数，如 `create_issue`）、`Resources`（AI 可以读取的数据，如文件内容、数据库表结构）、`Prompts`（可复用的提示词模板）。它们底层用 **JSON-RPC**（一种简单的远程调用格式）通信，远程服务走 HTTP 传输，本地服务走标准输入输出。\n\n整个调用流程是这样的：\n\n```mermaid\nflowchart LR\n    U[用户] --> H[Host 应用\u003Cbr\u002F>Claude \u002F Cursor \u002F VS Code]\n    H --> C[MCP Client\u003Cbr\u002F>连接管理器]\n    C -->|JSON-RPC| S1[MCP Server: GitHub]\n    C -->|JSON-RPC| S2[MCP Server: 数据库]\n    C -->|JSON-RPC| S3[MCP Server: 天气 API]\n    S1 --> D1[(代码仓库)]\n    S2 --> D2[(业务数据)]\n    S3 --> D3[(外部 API)]\n```\n\n关键点在于：Host 只要实现一次 Client 协议，Server 只要实现一次 Server 协议，从此任意 Host 能连任意 Server。集成成本从 M×N 降到了 M+N。\n\n## 一个最小可运行的例子\n\n下面用官方 Python SDK 写一个「天气查询」MCP 服务，只暴露一个工具：\n\n```python\nfrom mcp.server.fastmcp import FastMCP\n\nmcp = FastMCP(\"weather\")  # 服务名叫 weather\n\n@mcp.tool()\ndef get_weather(city: str) -> str:\n    \"\"\"查询某城市的天气（示例返回静态数据）\"\"\"\n    return f\"{city} 今天晴，25°C。\"\n\nif __name__ == \"__main__\":\n    mcp.run()  # 默认以 stdio 方式启动，等待 Host 来连\n```\n\n运行前只需 `pip install mcp`，然后用任意支持 MCP 的客户端（Claude 桌面端、Cursor 等）配置这个服务路径即可。AI 在对话里说「查下北京天气」，客户端就会通过 MCP 调用 `get_weather(\"北京\")`，拿到结果再组织成自然语言回答你。注意：这只是最小骨架，真实服务里要把静态返回值换成真正的天气 API 调用。\n\n## 取舍与边界：它解决了什么，没解决什么\n\nMCP 解决的是「连接标准」问题，但它不是银弹：\n\n- **它让集成变简单，但不保证工具安全。** 一个 MCP Server 可以是任何人所写，工具描述会直接喂给模型。如果 Server 既能读私有数据、又能访问不可信内容、还能对外发消息，就构成了安全风险（业界称之为「致命三件套」）。企业通常会加一层 **Gateway（网关）** 来做鉴权和审计——Uber、Amazon 都用了这种「网关 + 注册表」的控制平面。\n- **上下文膨胀是个真问题。** 接的 Server 一多，工具定义会塞满模型的上下文窗口。2026 年的常见解法是「按需加载」：只把当前 Agent 真正需要的工具暴露出来，而不是一次全塞进去。\n- **它定义「怎么连」，不定义「连上去说什么」。** 多 Agent 之间的协作语义，由另一套协议 A2A（Agent-to-Agent）负责——MCP 接工具，A2A 连同伴。\n\n## Tips\n\n- 下次看到「AI 连不上我的系统」，先问：有没有现成的 MCP Server？多数数据库、SaaS、开发工具都已有官方或社区实现。\n- 想自己动手：用官方 SDK（Python\u002FTypeScript 等）把内部的一个 API 包成 MCP Server，比写一套专属集成快得多。\n- 评估风险时记住三件事：私有数据、不可信输入、对外通信，三者叠加要格外小心，尽量放进网关管控。\n- 分清两层协议：接工具看 MCP，多 Agent 协作看 A2A，别混为一谈。\n- 把 MCP 当「基础设施」而非「功能」：它赢是因为无聊、通用、可复用，这正是它值得长期投入的原因。","https:\u002F\u002Foxqtewbrpuiouqqjrvdv.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fpublic-media\u002F2026-07-19\u002Fc3c06d99-a0ac-40ac-a283-7e77aabb4c4c.jpg",[],[],"Foundit AI","https:\u002F\u002Ffoundit.cn\u002Fabout","f39339b1-aaa6-4e86-b0c2-a6e6a21113b5",{"id":18,"name":19,"slug":20,"description":21},"6179d3b6-dc34-4483-9ded-3cd9f1b37a47","科普","abbreviation","介绍各领域新兴概念",[23,27,31],{"id":24,"name":25,"slug":26},"a202d639-99a6-488a-a712-4d4c6ffd7e15","开发","dev",{"id":28,"name":29,"slug":30},"7c76bfc2-f80f-4ee0-a95d-27bd8708b434","技术","slug",{"id":32,"name":33,"slug":34},"4c2bbea6-eab7-40a8-8447-1de478ff7749","分析","analyse",null,"published",false,46,0,"2026-07-20T00:00:00.000Z","2026-07-19T17:39:20.060Z","2026-07-19T16:13:40.316Z",[44,64,81],{"id":45,"type":6,"title":46,"slug":47,"summary":48,"body":49,"coverUrl":50,"productScreenshots":51,"productLinks":52,"authorName":14,"authorUrl":53,"authorSubject":16,"category":54,"tags":55,"sourceLabel":59,"sourceName":35,"sourceUrl":35,"status":36,"seoTitle":35,"seoDescription":35,"canonicalUrl":35,"isFeatured":37,"sno":60,"sortOrder":39,"publishedAt":61,"updatedAt":62,"createdAt":63},"74dedc2e-6a66-4481-aef2-5cffc3ba338d","嵌入模型（Embeddings）：向量数据库能搜「意思」，全靠它","embedding-models-vector-search","向量库怎么懂「意思相近」？靠嵌入模型把文字变成向量。本文讲清它的工作原理、余弦相似度检索，给出 sentence-transformers 最小示例，以及模型选型、维度统一、中英差异等取舍。","你让向量库「找意思相近的句子」，它怎么懂「意思」？靠嵌入模型（Embeddings）：把文字变成一串数字（向量），意思越近，数字越近。它是语义搜索和 RAG 真正的地基——没有它，模型只能靠关键词硬匹配。\n\n## 为什么需要嵌入\n\n传统搜索靠关键词匹配，搜「怎么给猫降温」找不到「猫咪中暑怎么办」。嵌入把文本映射到向量空间，把相近语义聚在一起，才能按「意思」而不是「字面」检索。\n\n## 它是怎么工作的\n\n嵌入模型（如 BGE、OpenAI text-embedding）是个神经网络，把变长文本压成定长向量（常见 768 或 1536 维）。训练目标是「语义相近的文本，向量距离小」。检索时把 query 也编码，算余弦相似度，找最近的那些。\n\n```mermaid\nflowchart LR\n    A[文本] --> B[嵌入模型]\n    B --> C[向量]\n    C --> D[存入向量库]\n    E[查询] --> B\n    D --> F[相似度检索]\n    B --> F\n    F --> G[返回相近文本]\n```\n\n## 取舍与边界\n\n- **模型要选对**：通用嵌入未必适合你的领域（法律、医疗），必要时用领域数据微调。\n- **维度与成本权衡**：维度越高通常越准，但存储、检索都更贵更慢，按场景取舍。\n- **中英文差异**：混用中英文语料要选多语言模型，否则跨语言检索会崩。\n- **维度必须统一**：检索和入库一定要用同一个模型、同一维度，否则向量不可比，检索全乱。\n\n## Tips\n\n- 任何「按意思搜」的需求，第一步就是选好嵌入模型。\n- 中文场景优先试 BGE、m3e 等多语言\u002F中文模型，别直接套英文默认。\n- 入库和检索用同一模型同一维度，这是铁律。\n- 领域强相关的语料，用该领域样本微调嵌入，召回率提升明显。\n- 嵌入质量直接决定 RAG 上限，值得在它上面多花时间。","https:\u002F\u002Foxqtewbrpuiouqqjrvdv.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fpublic-media\u002F2026-07-22\u002Facd40af8-276a-48bc-8d62-dcd52c124590.jpg",[],[],"https:\u002F\u002Ffoundit.cn",{"id":18,"name":19,"slug":20,"description":21},[56,57,58],{"id":32,"name":33,"slug":34},{"id":28,"name":29,"slug":30},{"id":24,"name":25,"slug":26},"资料来源",68,"2026-07-22T00:00:00.000Z","2026-07-23T01:16:32.032Z","2026-07-20T10:23:37.966Z",{"id":65,"type":6,"title":66,"slug":67,"summary":68,"body":69,"coverUrl":70,"productScreenshots":71,"productLinks":72,"authorName":14,"authorUrl":53,"authorSubject":16,"category":73,"tags":74,"sourceLabel":59,"sourceName":35,"sourceUrl":35,"status":36,"seoTitle":35,"seoDescription":35,"canonicalUrl":35,"isFeatured":37,"sno":78,"sortOrder":39,"publishedAt":61,"updatedAt":79,"createdAt":80},"8f7ce6a9-492b-4b45-afa4-d16905cc3b65","边缘函数：把代码跑在全球服务器","edge-functions","不想租服务器管运维？边缘函数把代码自动部署到全球几百个节点，毫秒级就近执行。","传统后端要你租服务器、装环境、管扩容、防宕机，一件小事背后是一整套运维。边缘函数（Edge Functions）把这件事彻底简化：你只写一段代码，平台把它自动部署到全球几百个节点，用户请求落到离他最近的那个，毫秒级响应，没有常驻服务器，也不用你管。Cloudflare Workers、Deno Deploy 是其中的代表。\n\n## 背景：为什么需要「边缘」\n\n用户在上海，服务器在美东，一次请求要跨半个地球来回，延迟动辄几百毫秒。把计算挪到离用户近的地方，是提速最直接的一招。边缘函数的思路是：不让你管服务器，而是把函数代码分发到全球边缘节点，在每个节点上按需、瞬时执行。\n\n## 它长什么样\n\n以 Cloudflare Workers 为例，一个函数就是一个 `fetch` 事件处理器，部署后立刻获得一个全球 URL：\n\n```javascript\nexport default {\n  async fetch(request) {\n    const url = new URL(request.url);\n    if (url.pathname === \"\u002Fhello\") {\n      return new Response(\"来自边缘的问候\");\n    }\n    return new Response(\"Not found\", { status: 404 });\n  }\n}\n```\n\n你 `deploy` 一下，这段代码就跑在了全球几百个数据中心，谁访问谁就近执行。\n\n## 一次请求怎么走\n\n```mermaid\nflowchart LR\n    A[用户 上海] --> B[最近边缘节点]\n    C[用户 纽约] --> D[最近边缘节点]\n    B --> E[你的函数代码 就近执行]\n    D --> E\n    E --> F[返回结果 毫秒级]\n```\n\n## 取舍与边界\n\n- **冷启动极快**：边缘函数通常是轻量隔离（如 V8 Isolate），启动以毫秒计，远快于传统容器。\n- **运行时受限**：为了快和轻，边缘环境不是完整 Node.js，部分 API（如某些文件系统、原生模块）不可用，写代码要适配。\n- **有状态数据要外置**：函数本身无状态、可能随时在哪个节点跑，数据库\u002F缓存要走外部服务（如边缘 KV）。\n- **适合「薄」逻辑**：鉴权、改写、A\u002FB、转发、轻计算最合适；重 CPU 或长任务仍交给中心化服务。\n\n## Tips\n\n- 入门只要写一个 `fetch` 处理器，二十行代码就能上线一个全球接口。\n- 适合做鉴权中间件、请求改写、A\u002FB 分流、轻量 API 网关。\n- 有状态数据（会话、计数）用平台提供的边缘 KV，别指望函数本地存。\n- 注意运行时差异：别用边缘不支持的 Node API，部署前本地跑一遍。\n- 重活（大模型推理、大计算）留给中心服务，边缘只做「快而薄」的那一层。","https:\u002F\u002Foxqtewbrpuiouqqjrvdv.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fpublic-media\u002F2026-07-22\u002F4e66dabf-7f69-4ba0-b66d-12774273f763.jpg",[],[],{"id":18,"name":19,"slug":20,"description":21},[75,76,77],{"id":28,"name":29,"slug":30},{"id":24,"name":25,"slug":26},{"id":32,"name":33,"slug":34},69,"2026-07-22T06:38:22.660Z","2026-07-20T01:11:48.654Z",{"id":82,"type":6,"title":83,"slug":84,"summary":85,"body":86,"coverUrl":87,"productScreenshots":88,"productLinks":89,"authorName":14,"authorUrl":53,"authorSubject":16,"category":90,"tags":91,"sourceLabel":35,"sourceName":35,"sourceUrl":35,"status":36,"seoTitle":35,"seoDescription":35,"canonicalUrl":35,"isFeatured":37,"sno":95,"sortOrder":39,"publishedAt":96,"updatedAt":97,"createdAt":98},"bce786d4-4fed-4186-a2b0-fee1a9762f28","大模型评测（LLM Evals）：为什么你的 AI 应用上线前必须做这件事","llm-evals-before-launch","模型「看起来能聊」和上生产是两回事。本文讲清 LLM Evals 为什么是 AI 应用的必需品：用带标准答案的题自动打分、建回归基线、用 LLM 当裁判，并给出 pytest 最小可运行示例与常见陷阱。","如果你做过 AI 应用，一定有过这种错觉：本地试聊几句，模型回答得头头是道，感觉「成了」。可一上线，用户随便问个边界问题，它就开始胡说、格式崩坏、甚至把上周还好好的功能改坏了。\n\n问题不在模型，在于你从来没用「可量化的标准」测过它。大模型评测（LLM Evals）就是解决这件事的：用一组带标准答案的题，自动跑、自动打分，把「行不行」变成数字。\n\n## 为什么需要 Evals\n\n靠人肉试聊有三个致命短板。第一是**回归陷阱**：你优化了一个 prompt，自己手感更好了，但可能悄悄搞砸了之前能答对的三类问题——没有对照基线，你根本发现不了。第二是**规模**：你不可能把上千种用户问法都手动试一遍。第三是**幻觉难察觉**：答案看起来通顺，事实却是错的，人眼抽查很容易漏。Evals 把「主观感觉」换成「可回归的指标体系」，每次改动都能看到分数涨跌。\n\n## Evals 的基本结构\n\n一套最小可用评测由四步串起来：准备数据集（输入 + 参考标准）、用被测模型跑出回答、用评分器打分、最后聚合出指标。评分器本身可以是硬规则、可以是另一个模型当裁判，也可以人工抽检。\n\n```mermaid\nflowchart LR\n    A[数据集 输入+参考答案] --> B[被测模型生成回答]\n    B --> C{评分器打分}\n    C -->|规则\u002F模型裁判\u002F人工| D[聚合指标 准确率\u002FF1\u002F通过率]\n    D --> E[对比基线 是否回归]\n```\n\n## 一个最小可运行的例子\n\n最朴素也最稳的做法，是用单元测试的框架（如 pytest）把「期望」写死：\n\n```python\nimport pytest\n\ncases = [\n    {\"q\": \"中国的首都是哪？\", \"expect\": \"北京\"},\n    {\"q\": \"1+1 等于几？\", \"expect\": \"2\"},\n]\n\ndef call_model(q: str) -> str:\n    # 这里换成你真实的模型调用\n    return \"北京\" if \"首都\" in q else \"2\"\n\n@pytest.mark.parametrize(\"c\", cases)\ndef test_basic(c):\n    got = call_model(c[\"q\"])\n    assert c[\"expect\"] in got, f\"期望含 {c['expect']}，实际 {got}\"\n```\n\n当你的场景变复杂（开放问答、长文本），再用「模型当裁判」（LLM-as-Judge）给定评分标准来打分，把分数也接进这套 pytest，就能在 CI 里跑回归。\n\n## 取舍与边界\n\n- **LLM 裁判有偏见**：它会偏爱长答案、会被措辞带偏，且每次调用要花钱、有延迟。关键场景一定要留人工抽检兜底。\n- **小样本不代表全量**：十道题全过，不等于线上万级流量没问题；数据集要持续收集真实 bad case 扩充。\n- **先建基线再优化**：没基线前别乱调 prompt，否则你永远不知道改动是变好还是变坏。\n- **指标要分层**：整体通过率之外，最好拆出「格式正确率」「事实准确率」「拒答恰当率」，定位问题更快。\n\n## Tips\n- 把最容易出错的 20 个真实问题整理成数据集，接进 pytest 跑通。\n- 把评测接进 CI：每次改 prompt \u002F 换模型，分数掉就拦下。\n- 开放问答类问题，引入 LLM-as-Judge，但保留 5% 人工抽检。\n- 线上一旦出现 bad case，立刻收录进数据集，让评测集跟着业务长。\n- 别追求「一个总分」，按格式 \u002F 事实 \u002F 安全分维度看，问题才好修。","https:\u002F\u002Foxqtewbrpuiouqqjrvdv.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fpublic-media\u002F2026-07-20\u002Fed78d51f-9c4c-4f9a-a9b7-fccde0c78f79.jpg",[],[],{"id":18,"name":19,"slug":20,"description":21},[92,93,94],{"id":28,"name":29,"slug":30},{"id":32,"name":33,"slug":34},{"id":24,"name":25,"slug":26},75,"2026-07-17T00:00:00.000Z","2026-07-20T01:19:14.428Z","2026-07-20T01:11:25.070Z"]