LangChain上手 MCP:从用别人工具到自己写工具

作者:颜酱日期:2026/6/12

LangChain上手 MCP:从用别人工具到自己写工具

读完这篇文章,你将能:用别人的 MCP Server(比如百度地图)、自己写一个 MCP Server(比如计算器)、用 Agent 自动调度多个工具


先看效果

用别人的:百度地图 MCP

十几行代码,让 AI 变成地图助手:

1import asyncio
2from langchain_mcp_adapters.client import MultiServerMCPClient
3from langchain.agents import create_agent
4from llm import llm
5
6async def main():
7    client = MultiServerMCPClient({
8        "baidu_map": {
9            "transport": "streamable_http",
10            "url": "https://mcp.map.baidu.com/mcp?ak=你的AK",
11        }
12    })
13    tools = await client.get_tools()
14    print("✅ 工具列表:", [t.name for t in tools])
15
16    agent = create_agent(
17        llm, tools,
18        system_prompt="你是地图助手,必须使用工具查询。",
19    )
20    result = await agent.ainvoke({
21        "messages": [("user", "北京今天天气怎么样?")]
22    })
23    print(result["messages"][-1].content)
24
25asyncio.run(main())
26

输出:

1 工具列表:['map_geocode', 'map_reverse_geocode', 'map_weather', ...]
2北京今天晴朗,温度23°C,微风...
3

自己写的:计算器 MCP Server

1from mcp.server.fastmcp import FastMCP
2
3mcp = FastMCP("计算器")
4
5@mcp.tool()
6def add(a: float, b: float) -> float:
7    return a + b
8
9mcp.run()  # 就这样,一个 MCP Server 写好了
10

MCP 是什么

一句话:MCP 是工具和大模型之间的"USB 接口"。

以前你写 @tool def cal(...),这个工具只能给 LangChain 用。写成 MCP Server 后,LangChain、Claude Desktop、ChatGPT、Go 写的 Agent——谁都能调

1┌──────────┐                  ┌──────────┐
2  MCP                         MCP     
3  Server   ←── 标准协议 ──→    Client  
4 (工具端)                     (模型端)  
5└──────────┘                  └──────────┘
6
  • MCP Server:暴露工具(数据库、文件、API、你的计算器)
  • MCP Client:连到大模型,负责调用 Server 提供的工具
  • 协议:JSON-RPC,就是 JSON 格式的"调哪个函数、传什么参数、返回什么结果"

📖 官方文档:LangChain MCP | MCP 协议 | FastMCP


3 分钟上手:用别人的 MCP Server

安装

1pip install langchain-mcp-adapters
2

百度地图 MCP 实战

  1. lbsyun.baidu.com 申请 AK(应用类别选"服务端",勾选 MCP 服务,要实名认证)
  2. 设置环境变量 export BAIDU_MAP_AK="你的AK"
  3. 跑代码:
1import asyncio
2from langchain_mcp_adapters.client import MultiServerMCPClient
3from langchain.agents import create_agent
4from llm import llm
5import os
6
7async def main():
8    client = MultiServerMCPClient({
9        "baidu_map": {
10            "transport": "streamable_http",
11            "url": f"https://mcp.map.baidu.com/mcp?ak={os.getenv('BAIDU_MAP_AK')}",
12        }
13    })
14    tools = await client.get_tools()
15    print("✅ 工具列表:", [t.name for t in tools])
16
17    # 先直接调用,不用 Agent —— 看看工具能返回什么
18    tool = {t.name: t for t in tools}
19    r = await tool["map_geocode"].ainvoke({"address": "北京市朝阳区国贸中心"})
20    print(f"📍 经纬度:{r}")
21
22    # 再用 Agent —— 让大模型自动判断调哪个工具
23    agent = create_agent(
24        llm, tools,
25        system_prompt="你是地图助手,当用户询问天气、地址、路线、地点等信息时,必须使用工具查询。",
26    )
27    result = await agent.ainvoke({
28        "messages": [("user", "北京今天天气怎么样?")]
29    })
30    print(f"\n🌤 {result['messages'][-1].content}")
31
32asyncio.run(main())
33

关键点: MCP 和 Agent 是解耦的。client.get_tools() 拿到工具后,可以直接调,也可以交给 Agent 自动调。


两种传输方式(必知)

MCP 支持两种通信方式,你都要知道:

1. stdio — 本地开发首选

Client 自动拉起 Server 作为子进程,不需要启动 HTTP 服务:

1client = MultiServerMCPClient({
2    "math": {
3        "transport": "stdio",
4        "command": "python",
5        "args": ["demo/mcp-server-stdio.py"],
6    }
7})
8tools = await client.get_tools()
9

这段配置翻译成人话就是一句命令行:python demo/mcp-server-stdio.py

Client 自动帮你执行这个命令,然后通过 stdin/stdout 和它对话。你不需要手动开终端去启动 Server。

2. streamable_http — 远程生产环境

Server 作为 HTTP 服务运行,可以跨机器调用:

1# 服务端
2mcp = FastMCP("服务", host="0.0.0.0", port=8080)
3mcp.run(transport="streamable-http")
4
5# 客户端
6client = MultiServerMCPClient({
7    "service": {
8        "transport": "streamable_http",
9        "url": "http://localhost:8080/mcp",
10    }
11})
12

这段配置翻译成人话:Client 向 http://localhost:8080/mcp 发 HTTP 请求,Server 在那等着响应。

和 stdio 的区别是:Server 是一个独立的 HTTP 服务,你需要先手动启动它,可以部署在任何机器上。

对比

stdiostreamable_http
需要先启动 Server❌ 自动拉起✅ 手动启动
跨机器
鉴权不需要支持 headers
场景本地开发生产环境

SSE 呢?

老版本 MCP 用 SSE(Server-Sent Events)做远程通信,但连接单向、实现复杂。2025 年 3 月官方推出 streamable_http 替代 SSE,新项目直接用 streamable_http,不用管 SSE。


自己写一个 MCP Server

最小版本 — stdio 模式

服务端:

1# demo/mcp-server-stdio.py
2from mcp.server.fastmcp import FastMCP
3
4mcp = FastMCP("计算器服务")
5
6@mcp.tool()
7def add(a: float, b: float) -> float:
8    return a + b
9
10@mcp.tool()
11def multiply(a: float, b: float) -> float:
12    return a * b
13
14if __name__ == "__main__":
15    mcp.run()  # 默认 stdio
16

客户端:

1# demo/mcp-client-stdio.py
2import asyncio
3from pathlib import Path
4from langchain_mcp_adapters.client import MultiServerMCPClient
5
6async def main():
7    client = MultiServerMCPClient({
8        "math": {
9            "transport": "stdio",
10            "command": "python",
11            "args": [str(Path(__file__).parent / "mcp-server-stdio.py")],
12        }
13    })
14    tools = await client.get_tools()
15    tool = {t.name: t for t in tools}
16    r = await tool["add"].ainvoke({"a": 100, "b": 50})
17    print(f"100 + 50 = {r}")
18
19asyncio.run(main())
20

多工具版 — streamable_http 模式

服务端:

1# demo/mcp-server-calculator.py
2from mcp.server.fastmcp import FastMCP
3
4mcp = FastMCP("计算器服务", host="0.0.0.0", port=8080)
5
6@mcp.tool()
7def add(a: float, b: float) -> float:
8    return a + b
9
10@mcp.tool()
11def multiply(a: float, b: float) -> float:
12    return a * b
13
14@mcp.tool()
15def divide(a: float, b: float) -> float:
16    if b == 0:
17        raise ValueError("除数不能为0")
18    return a / b
19
20if __name__ == "__main__":
21    mcp.run(transport="streamable-http")
22

启动:

1python3 demo/mcp-server-calculator.py
2#  监听 http://localhost:8080/mcp
3

客户端:

1# demo/mcp-client-calculator.py
2client = MultiServerMCPClient({
3    "my_calculator": {
4        "transport": "streamable_http",
5        "url": "http://localhost:8080/mcp",
6    }
7})
8tools = await client.get_tools()
9
10# 直接调
11tool = {t.name: t for t in tools}
12r = await tool["add"].ainvoke({"a": 100, "b": 50})
13
14# Agent 
15agent = create_agent(llm, tools, system_prompt="你是数学助手,计算必须用工具。")
16result = await agent.ainvoke({
17    "messages": [("user", "100乘以50再加20等于多少?")]
18})
19

完整流程

1┌────────────────────┐         ┌────────────────────┐
2 mcp-server.py                mcp-client.py      
3                      HTTP                       
4 @mcp.tool() add    │◄───────►│ MultiServerMCPClient│
5 @mcp.tool() multi    JSON     get_tools()      
6 :8080/mcp            -RPC     tool.ainvoke()   
7                               create_agent()   
8└────────────────────┘         └────────────────────┘
9

对比之前在 LangChain 里 @tool def cal(...):MCP 版多了一步 mcp.run(),但换来的是任何语言、任何框架都能调。


多 Server 同时接入 + 鉴权

一个 Agent 可以同时连多个 MCP Server:

1client = MultiServerMCPClient({
2    "math": {
3        "transport": "stdio",
4        "command": "python",
5        "args": ["/path/to/math_server.py"],
6    },
7    "baidu_map": {
8        "transport": "streamable_http",
9        "url": "https://mcp.map.baidu.com/mcp?ak=xxx",
10    }
11})
12tools = await client.get_tools()
13# tools = math  add/multiply + baidu_map  13 个地图工具
14agent = create_agent(llm, tools)
15

带 Token 鉴权:

企业场景下,Server 通常需要带 Token 鉴权。在写服务端的时候增加一个鉴权中间件,Client 调用时在 headers 里带上 Token 就好:

1client = MultiServerMCPClient({
2    "service": {
3        "transport": "streamable_http",
4        "url": "http://localhost:8000/mcp",
5        "headers": {"Authorization": "Bearer YOUR_TOKEN"},
6    }
7})
8

总结

  1. MCP = 工具和模型的 USB 接口,谁的 Server 都能给谁的 Client 用
  2. 会用别人的:MultiServerMCPClient({...})get_tools() → 直接调或放 Agent
  3. 会写自己的:FastMCP + @mcp.tool() + mcp.run()
  4. 本地开发用 stdio,生产用 streamable_http
  5. 多个 Server 自由组合,Agent 自动判断调哪个

附录 A:MCP 是什么协议?JSON-RPC 详解

MCP 底层是 JSON-RPC(JSON Remote Procedure Call)。没有 HTTP Headers、没有 REST 语义——就是用 JSON 格式请求远程服务器执行一个函数,然后返回结果

请求:

1{
2  "jsonrpc": "2.0",
3  "method": "tools/call",
4  "params": { "name": "add", "arguments": { "a": 100, "b": 50 } },
5  "id": 1
6}
7

响应:

1{
2  "jsonrpc": "2.0",
3  "result": { "content": [{ "type": "text", "text": "150" }] },
4  "id": 1
5}
6

为什么不是 REST?

RESTJSON-RPC
通信方式URL 路径 + HTTP 动词单一端点,方法名在 body
工具调用POST /api/tools/cal{"method": "tools/call", ...}
批量调用多次请求一次请求数组
实时推送需要 WebSocket同一连接支持 notification

工具调用天然是"调用函数",和 JSON-RPC 的语义完全匹配。

三种消息类型

类型说明有 id?
RequestClient → Server,请求执行
ResponseServer → Client,返回结果
Notification单向通知,无需回复

一句话:请求-响应是对话,通知是广播。


附录 B:MCP Server 功能分类

按"工具是干嘛的"分,常见 9 大类:

类别场景例子
文件系统读写本地文件FileSystem MCP
数据库执行 SQLPostgreSQL MCP
搜索网页抓取、搜索Brave Search MCP
云存储管理云端文件S3 MCP
版本控制Git 操作GitHub MCP
开发工具终端、Lint命令行 MCP
通信平台发消息Slack MCP
监控查日志、指标可观测性 MCP
其他地图、支付、笔记百度地图 MCP

任何能被 AI 调用的能力,都能做成一个 MCP Server。


附录 C:常见踩坑

Q1:TypeError: FastMCP.run() got an unexpected keyword argument 'host'

host/port 写在构造函数里,不是 run() 里:

1#  正确
2mcp = FastMCP("服务", host="0.0.0.0", port=8080)
3mcp.run(transport="streamable-http")
4
5#  错误
6mcp.run(transport="streamable-http", host="0.0.0.0", port=8080)
7

Q2:NotImplementedError: MultiServerMCPClient cannot be used as a context manager

0.1.0 版本去掉了 async with,直接创建就行:

1#  新版
2client = MultiServerMCPClient({...})
3tools = await client.get_tools()
4
5#  旧版
6async with MultiServerMCPClient({...}) as client:
7    ...
8

Q3:MCP 工具 Agent 调用报错

MCP 工具只支持异步。用 agent.ainvoke() 而不是 agent.invoke()

Q4:stdio 模式 Server 找不到

用绝对路径,或者在客户端用 Path(__file__).parent 拼接。



LangChain上手 MCP:从用别人工具到自己写工具》 是转载文章,点击查看原文


相关推荐


女程序媛多肉的 AI 小绿书,短短 3 天 220 粉
threerocks2026/6/5

微信公众号近 1~2 年,主推贴图类型作品,并且对这类内容有比较明显的流量倾斜。再叠加这两年 AI 生图的成熟,Nano Banana Pro 和 GPT-Image-2 先后出世,既然图片生产不再是卡点,那很多人会很自然地想到一个项目:用 OpenClaw、Codex、Claude Code 这类 Agent 工具,把公众号贴图自动化做起来。 理论上,这听起来像一个很好且成本不高的生意。AI 负责生图,Agent 负责写文案,公众号负责推荐流。人只要选图、点发布,甚至再往后一点,连选图都可以交


AI 大模型核心五:从 Transformer、RAG 到 Agent 架构
zhangxingchao2026/5/29

一、如果去掉多头只用单头,Transformer 会出现什么问题? 一句话概括: 单头注意力会把所有关系都压到一个注意力分布里,导致模型很难同时关注语法、语义、位置、指代、长程依赖等多种信息,表达能力会明显下降。 这里要注意,单头不是完全不能用,而是会形成明显的信息瓶颈。 1. 多头注意力到底解决什么问题? Multi-Head Attention 的关键价值,不只是“多算几次 attention”,而是让不同的 head 在不同子空间里学习不同类型的关系。 一段文本里,模型可能同时需要关注


深度学习(13)PyTorch神经网络基础
β添砖java2026/5/7

1. 层和块 ① nn.Sequential 定义了一种特殊的Module。 # 回顾一下多层感知机 import torch #基础计算(类似 numpy) from torch import nn #神经网络工具(层、模型) from torch.nn import functional as F #一些函数(比如激活函数) #搭建神经网络结构 net = nn.Sequential(nn.Linear(20,256),nn.ReLU(),nn.Linear(256,10))


Claude Code 从零上手:国内用户保姆级安装教程
易安说AI2026/4/27

Claude Code 是目前公认最强的 AI  编程 Agent 框架。很多人以为它必须配合 Claude 官方模型才能用,但实际上,Claude Code 本质是一个 Agent 框架,搭配任何模型都能运行。本文手把手教你从零安装 Claude Code,并用国产模型 GLM-5.1 接入,全程不需要海外手机号、Visa 卡,甚至不需要代理。  操作系统:macOS 或 Windows 均可 网络:有代理最好,没有也能用(本文两种方案都覆盖) 模型选择:推荐 GLM-5.1(国内效果最接近


js的深拷贝和浅拷贝?啥情况讲解下??底层堆栈空间??object.prototype.toString.call(),还有bind,的具体使用?
神の愛2026/4/19

js的深拷贝和浅拷贝?啥情况讲解下??底层堆栈空间??object.prototype.toString.call(),还有bind,的具体使用?还有instanceof对象的实例,还有哪个方法可以直接获取到我定义的数据是什么类型的。哟哪几种数据类型?包括哪些? 1. 堆(Heap)与 栈(Stack):内存的真相 在 JS 里,内存被分为两块: 栈(Stack):空间小、速度快。存放基本数据类型(String, Number, Boolean, Null, Undefined, Sy


如何实现分布式锁
哈里谢顿2026/4/10

分布式锁是分布式系统中协调多个节点对共享资源访问的关键机制。我来从原理到实现,系统性地讲解。 核心要求 一个可靠的分布式锁必须满足: 特性说明互斥性同一时间只有一个客户端能持有锁防死锁锁必须有过期机制,避免客户端崩溃后锁永远不被释放可重入性(可选)同一客户端可以多次获取同一把锁容错性大部分节点存活时,锁服务仍能正常工作 方案一:基于 Redis(最常用) 1. 基础版(SETNX + EXPIRE) SETNX lock:resource "


Ospf网络类型:P2P和Broadcast
24zhgjx-fuhao2026/4/2

一、P2P (一)、P2P的作用及特点 P2P(点到点)网络类型 1.作用: 适用于连接两台路由器的链路‌,例如通过PPP(点对点协议)或HDLC(高级数据链路控制)封装的串行链路。不需要进行DR(指定路由器)和BDR(备份指定路由器)的选举。路由器之间可以直接建立邻接关系(Full状态),无需通过DR/BDR进行LSA(链路状态通告)的泛洪。 2.特点: 无需选举DR/BDR‌:因为只有两个设备通信。自动发现邻居‌:通过发送Hello报文自动发现邻居。组播发送协议报文‌:使用组播地


Linux中基础IO知识全解
顶点多余2026/3/25

1.什么是文件 文件是指内容+属性,所以文件永远不是只有内容; 1.1狭义上: ①文件的存储特性 永久性存储:磁盘是永久性存储介质,文件在磁盘上的存储是永久性的(断电不丢失) ②磁盘的设备属性 外部设备:磁盘属于外设(I/O设备) 双重角色:既是输出设备(写入数据),也是输入设备(读取数据) ③文件操作的本质 I/O操作:对磁盘上文件的所有操作,本质上都是对外设的输入和输出 统称IO:所有文件读写操作,都可以简称为IO 1.2广义上: Linux 下⼀切皆⽂件(键盘、显⽰器、⽹卡、


Windows 11 上搭建 YouTube 视频下载工具:yt-dlp + FFmpeg
liulilittle2026/3/17

Windows 11 上搭建 YouTube 视频下载工具:yt-dlp + FFmpeg 作为经常需要下载 YouTube 视频的人,你一定遇到过这样的烦恼:在线下载网站不稳定、广告多,或者限制大小。今天我就来分享一套本地搭建的下载方案,使用 yt-dlp(youtube-dl 的活跃分支)配合 FFmpeg,在 Windows 11 上轻松下载单条视频或整个播放列表,全部转为 MP4 格式。最重要的是,完全免费、无广告、速度快! 准备工作 一台 Windows 11 电脑,且有管理


Android MediatorLiveData
louisgeek2026/3/8

Android MediatorLiveData 可以监听多个 LiveData 源,并且能动态添加和移除源 合并多个 LiveData 源 public class CombineViewModel extends ViewModel { private final MutableLiveData<One> _oneLiveData = new MutableLiveData<>(); public final LiveData<One> oneLiveData = _on

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 聚合阅读