文档索引 在以下地址获取完整的文档索引:https://docs.langchain.org.cn/llms.txt
在进一步探索之前,请使用此文件发现所有可用页面。
模型上下文协议 (MCP) 是一种开放协议,用于标准化应用程序如何向大型语言模型 (LLM) 提供工具和上下文。LangChain 智能体可以使用 langchain-mcp-adapters 库来使用 MCP 服务器上定义的工具。
快速入门
安装 langchain-mcp-adapters 库
pip install langchain-mcp-adapters
langchain-mcp-adapters 使智能体能够使用在一个或多个 MCP 服务器上定义的工具。
MultiServerMCPClient 默认是**无状态的**。每次工具调用都会创建一个新的 MCP ClientSession,执行工具,然后清理。有关更多详细信息,请参阅有状态会话 部分。
import asyncio
from langchain_mcp_adapters . client import MultiServerMCPClient
from langchain . agents import create_agent
async def main ():
client = MultiServerMCPClient (
{
"math" : {
"transport" : "stdio" , # Local subprocess communication
"command" : "python" ,
# Absolute path to your math_server.py file
"args" : [ "/path/to/math_server.py" ],
},
"weather" : {
"transport" : "http" , # HTTP-based remote server
# Ensure you start your weather server on port 8000
"url" : "https://:8000/mcp" ,
}
}
)
tools = await client . get_tools ()
agent = create_agent (
"claude-sonnet-4-6" ,
tools
)
math_response = await agent . ainvoke (
{ "messages" : [{ "role" : "user" , "content" : "what's (3 + 5) x 12?" }]}
)
weather_response = await agent . ainvoke (
{ "messages" : [{ "role" : "user" , "content" : "what is the weather in nyc?" }]}
)
print ( math_response )
print ( weather_response )
if __name__ == "__main__" :
asyncio . run ( main ())
自定义服务器
要创建自定义 MCP 服务器,请使用 FastMCP 库
要使用 MCP 工具服务器测试您的智能体,请使用以下示例
数学服务器(stdio 传输)
天气服务器(流式 HTTP 传输)
from fastmcp import FastMCP
mcp = FastMCP ( "Math" )
@mcp . tool ()
def add ( a : int , b : int ) -> int :
"""Add two numbers"""
return a + b
@mcp . tool ()
def multiply ( a : int , b : int ) -> int :
"""Multiply two numbers"""
return a * b
if __name__ == "__main__" :
mcp . run ( transport = "stdio" )
传输方式
MCP 支持不同的客户端-服务器通信传输机制。
HTTP
http 传输(也称为 streamable-http)使用 HTTP 请求进行客户端-服务器通信。有关更多详细信息,请参阅 MCP HTTP 传输规范 。
client = MultiServerMCPClient (
{
"weather" : {
"transport" : "http" ,
"url" : "https://:8000/mcp" ,
}
}
)
通过 HTTP 连接到 MCP 服务器时,您可以使用连接配置中的 headers 字段来包含自定义请求头(例如,用于身份验证或追踪)。这支持 sse(MCP 规范已弃用)和 streamable_http 传输方式。
使用 MultiServerMCPClient 传递请求头
from langchain_mcp_adapters . client import MultiServerMCPClient
from langchain . agents import create_agent
client = MultiServerMCPClient (
{
"weather" : {
"transport" : "http" ,
"url" : "https://:8000/mcp" ,
"headers" : {
"Authorization" : "Bearer YOUR_TOKEN" ,
"X-Custom-Header" : "custom-value"
},
}
}
)
tools = await client . get_tools ()
agent = create_agent ( "openai:gpt-5.4" , tools )
response = await agent . ainvoke ({ "messages" : "what is the weather in nyc?" })
身份验证
langchain-mcp-adapters 库底层使用了官方的 MCP SDK ,它允许您通过实现 httpx.Auth 接口来提供自定义身份验证机制。
from langchain_mcp_adapters . client import MultiServerMCPClient
client = MultiServerMCPClient (
{
"weather" : {
"transport" : "http" ,
"url" : "https://:8000/mcp" ,
"auth" : auth ,
}
}
)
stdio
客户端作为子进程启动服务器,并通过标准输入/输出进行通信。最适合本地工具和简单设置。
与 HTTP 传输不同,stdio 连接本质上是**有状态的**:子进程在客户端连接的整个生命周期内持续存在。但是,在使用 MultiServerMCPClient 而没有显式会话管理时,每次工具调用仍会创建一个新会话。有关管理持久连接的信息,请参阅有状态会话 。
client = MultiServerMCPClient (
{
"math" : {
"transport" : "stdio" ,
"command" : "python" ,
"args" : [ "/path/to/math_server.py" ],
}
}
)
有状态会话
默认情况下,MultiServerMCPClient 是**无状态的**:每次工具调用都会创建一个新的 MCP 会话,执行工具,然后清理。 如果您需要控制 MCP 会话的生命周期 (例如,当使用一个在工具调用之间维护上下文的有状态服务器时),您可以使用 client.session() 创建一个持久的 ClientSession。 使用 MCP ClientSession 实现有状态工具使用
from langchain_mcp_adapters . client import MultiServerMCPClient
from langchain_mcp_adapters . tools import load_mcp_tools
from langchain . agents import create_agent
client = MultiServerMCPClient ({ ... })
# Create a session explicitly
async with client . session ( "server_name" ) as session :
# Pass the session to load tools, resources, or prompts
tools = await load_mcp_tools ( session )
agent = create_agent (
"google_genai:gemini-3.1-pro-preview" ,
tools
)
核心功能
工具 允许 MCP 服务器公开可执行函数,LLM 可以调用这些函数来执行操作——例如查询数据库、调用 API 或与外部系统交互。LangChain 将 MCP 工具转换为 LangChain 工具 ,使其可以直接在任何 LangChain 智能体或工作流中使用。
使用 client.get_tools() 从 MCP 服务器检索工具并将其传递给您的智能体
from langchain_mcp_adapters . client import MultiServerMCPClient
from langchain . agents import create_agent
client = MultiServerMCPClient ({ ... })
tools = await client . get_tools ()
agent = create_agent ( "claude-sonnet-4-6" , tools )
结构化内容
MCP 工具可以在人类可读的文本响应之外返回结构化内容 。当工具除了向模型显示的文本之外,还需要返回机器可解析的数据(如 JSON)时,这非常有用。 当 MCP 工具返回 structuredContent 时,适配器会将其包装在 MCPToolArtifact 中,并作为工具的工件返回。您可以使用 ToolMessage 上的 artifact 字段访问它。您还可以使用拦截器 自动处理或转换结构化内容。 从工件中提取结构化内容 调用智能体后,您可以从响应中的工具消息中访问结构化内容: from langchain_mcp_adapters . client import MultiServerMCPClient
from langchain . agents import create_agent
from langchain . messages import ToolMessage
client = MultiServerMCPClient ({ ... })
tools = await client . get_tools ()
agent = create_agent ( "claude-sonnet-4-6" , tools )
result = await agent . ainvoke (
{ "messages" : [{ "role" : "user" , "content" : "Get data from the server" }]}
)
# Extract structured content from tool messages
for message in result [ " messages " ]:
if isinstance ( message , ToolMessage ) and message . artifact :
structured_content = message . artifact [ " structured_content " ]
通过拦截器附加结构化内容 如果您希望结构化内容在对话历史中可见(对模型可见),您可以使用拦截器 自动将结构化内容附加到工具结果中: import json
from langchain_mcp_adapters . client import MultiServerMCPClient
from langchain_mcp_adapters . interceptors import MCPToolCallRequest
from mcp . types import TextContent
async def append_structured_content ( request : MCPToolCallRequest , handler ):
"""Append structured content from artifact to tool message."""
result = await handler ( request )
if result . structuredContent :
result . content += [
TextContent ( type = "text" , text = json . dumps ( result . structuredContent )),
]
return result
client = MultiServerMCPClient ({ ... }, tool_interceptors = [ append_structured_content ])
多模态工具内容
MCP 工具可以在其响应中返回多模态内容 (图像、文本等)。当 MCP 服务器返回包含多个部分(例如文本和图像)的内容时,适配器会将其转换为 LangChain 的标准内容块 。您可以通过 ToolMessage 上的 content_blocks 属性访问标准化表示形式
from langchain_mcp_adapters . client import MultiServerMCPClient
from langchain . agents import create_agent
client = MultiServerMCPClient ({ ... })
tools = await client . get_tools ()
agent = create_agent ( "claude-sonnet-4-6" , tools )
result = await agent . ainvoke (
{ "messages" : [{ "role" : "user" , "content" : "Take a screenshot of the current page" }]}
)
# Access multimodal content from tool messages
for message in result [ " messages " ]:
if message . type == "tool" :
# Raw content in provider-native format
print ( f "Raw content: { message . content } " )
# Standardized content blocks #
for block in message . content_blocks :
if block [ " type " ] == "text" :
print ( f "Text: { block [ ' text ' ] } " )
elif block [ " type " ] == "image" :
print ( f "Image URL: { block . get ( 'url' ) } " )
print ( f "Image base64: { block . get ( 'base64' , '' )[: 50 ] } ..." )
这使您能够以与提供商无关的方式处理多模态工具响应,无论底层 MCP 服务器如何格式化其内容。
资源 允许 MCP 服务器公开数据(例如文件、数据库记录或 API 响应),这些数据可由客户端读取。LangChain 将 MCP 资源转换为 Blob 对象,该对象提供了处理文本和二进制内容的统一接口。
加载资源
使用 client.get_resources() 从 MCP 服务器加载资源
from langchain_mcp_adapters . client import MultiServerMCPClient
client = MultiServerMCPClient ({ ... })
# Load all resources from a server
blobs = await client . get_resources ( "server_name" )
# Or load specific resources by URI
blobs = await client . get_resources ( "server_name" , uris = [ "file:///path/to/file.txt" ])
for blob in blobs :
print ( f "URI: { blob . metadata [ ' uri ' ] } , MIME type: { blob . mimetype } " )
print ( blob . as_string ()) # For text content
您也可以直接将 load_mcp_resources 与会话一起使用以获得更多控制
from langchain_mcp_adapters . client import MultiServerMCPClient
from langchain_mcp_adapters . resources import load_mcp_resources
client = MultiServerMCPClient ({ ... })
async with client . session ( "server_name" ) as session :
# Load all resources
blobs = await load_mcp_resources ( session )
# Or load specific resources by URI
blobs = await load_mcp_resources ( session , uris = [ "file:///path/to/file.txt" ])
提示词 允许 MCP 服务器公开可重用的提示模板,客户端可以检索和使用这些模板。LangChain 将 MCP 提示词转换为消息 ,使其易于集成到基于聊天的流程中。
加载提示词
使用 client.get_prompt() 从 MCP 服务器加载提示词
from langchain_mcp_adapters . client import MultiServerMCPClient
client = MultiServerMCPClient ({ ... })
# Load a prompt by name
messages = await client . get_prompt ( "server_name" , "summarize" )
# Load a prompt with arguments
messages = await client . get_prompt (
"server_name" ,
"code_review" ,
arguments = { "language" : "python" , "focus" : "security" }
)
# Use the messages in your workflow
for message in messages :
print ( f " { message . type } : { message . content } " )
您也可以直接将 load_mcp_prompt 与会话一起使用以获得更多控制
from langchain_mcp_adapters . client import MultiServerMCPClient
from langchain_mcp_adapters . prompts import load_mcp_prompt
client = MultiServerMCPClient ({ ... })
async with client . session ( "server_name" ) as session :
# Load a prompt by name
messages = await load_mcp_prompt ( session , "summarize" )
# Load a prompt with arguments
messages = await load_mcp_prompt (
session ,
"code_review" ,
arguments = { "language" : "python" , "focus" : "security" }
)
高级特性
MCP 服务器作为单独的进程运行——它们无法访问 LangGraph 的运行时信息,例如存储 、上下文 或智能体状态。**拦截器通过在 MCP 工具执行期间为您提供对运行时上下文的访问来弥合这一差距。** 拦截器还提供类似中间件的工具调用控制:您可以修改请求、实现重试、动态添加请求头或完全短路执行。 部分 描述 访问运行时上下文 读取用户 ID、API 密钥、存储数据和智能体状态 状态更新和命令 使用 Command 更新智能体状态或控制图流程 编写拦截器 修改请求、组合拦截器和错误处理的模式
访问运行时上下文
当 MCP 工具在 LangChain 智能体(通过 create_agent)中使用时,拦截器可以访问 ToolRuntime 上下文。这提供了对工具调用 ID、状态、配置和存储的访问——从而实现了访问用户数据、持久化信息和控制智能体行为的强大模式。
访问在调用时传递的用户特定配置,如用户 ID、API 密钥或权限 from dataclasses import dataclass
from langchain_mcp_adapters . client import MultiServerMCPClient
from langchain_mcp_adapters . interceptors import MCPToolCallRequest
from langchain . agents import create_agent
@dataclass
class Context :
user_id : str
api_key : str
async def inject_user_context (
request : MCPToolCallRequest ,
handler ,
):
"""Inject user credentials into MCP tool calls."""
runtime = request . runtime
user_id = runtime . context . user_id
api_key = runtime . context . api_key
# Add user context to tool arguments
modified_request = request . override (
args = { ** request . args , "user_id" : user_id }
)
return await handler ( modified_request )
client = MultiServerMCPClient (
{ ... },
tool_interceptors = [ inject_user_context ],
)
tools = await client . get_tools ()
agent = create_agent ( "gpt-5.4" , tools , context_schema = Context )
# Invoke with user context
result = await agent . ainvoke (
{ "messages" : [{ "role" : "user" , "content" : "Search my orders" }]},
context = { "user_id" : "user_123" , "api_key" : "sk-..." }
)
访问长期记忆以检索用户偏好或在对话中持久化数据 from dataclasses import dataclass
from langchain_mcp_adapters . client import MultiServerMCPClient
from langchain_mcp_adapters . interceptors import MCPToolCallRequest
from langchain . agents import create_agent
from langgraph . store . memory import InMemoryStore
@dataclass
class Context :
user_id : str
async def personalize_search (
request : MCPToolCallRequest ,
handler ,
):
"""Personalize MCP tool calls using stored preferences."""
runtime = request . runtime
user_id = runtime . context . user_id
store = runtime . store
# Read user preferences from store
prefs = store . get (( "preferences" ,), user_id )
if prefs and request . name == "search" :
# Apply user's preferred language and result limit
modified_args = {
** request . args ,
"language" : prefs . value . get ( "language" , "en" ),
"limit" : prefs . value . get ( "result_limit" , 10 ),
}
request = request . override ( args = modified_args )
return await handler ( request )
client = MultiServerMCPClient (
{ ... },
tool_interceptors = [ personalize_search ],
)
tools = await client . get_tools ()
agent = create_agent (
"gpt-5.4" ,
tools ,
context_schema = Context ,
store = InMemoryStore ()
)
访问对话状态以根据当前会话做出决策 from langchain_mcp_adapters . client import MultiServerMCPClient
from langchain_mcp_adapters . interceptors import MCPToolCallRequest
from langchain . messages import ToolMessage
async def require_authentication (
request : MCPToolCallRequest ,
handler ,
):
"""Block sensitive MCP tools if user is not authenticated."""
runtime = request . runtime
state = runtime . state
is_authenticated = state . get ( "authenticated" , False )
sensitive_tools = [ "delete_file" , "update_settings" , "export_data" ]
if request . name in sensitive_tools and not is_authenticated :
# Return error instead of calling tool
return ToolMessage (
content = "Authentication required. Please log in first." ,
tool_call_id = runtime . tool_call_id ,
)
return await handler ( request )
client = MultiServerMCPClient (
{ ... },
tool_interceptors = [ require_authentication ],
)
访问工具调用 ID 以返回正确格式的响应或跟踪工具执行 from langchain_mcp_adapters . client import MultiServerMCPClient
from langchain_mcp_adapters . interceptors import MCPToolCallRequest
from langchain . messages import ToolMessage
async def rate_limit_interceptor (
request : MCPToolCallRequest ,
handler ,
):
"""Rate limit expensive MCP tool calls."""
runtime = request . runtime
tool_call_id = runtime . tool_call_id
# Check rate limit (simplified example)
if is_rate_limited ( request . name ):
return ToolMessage (
content = "Rate limit exceeded. Please try again later." ,
tool_call_id = tool_call_id ,
)
result = await handler ( request )
# Log successful tool call
log_tool_execution ( tool_call_id , request . name , success = True )
return result
client = MultiServerMCPClient (
{ ... },
tool_interceptors = [ rate_limit_interceptor ],
)
有关更多上下文工程模式,请参阅上下文工程 和工具 。
状态更新和命令
拦截器可以返回 Command 对象来更新智能体状态或控制图执行流程。这对于跟踪任务进度、在智能体之间切换或提前结束执行很有用。
from langchain . agents import AgentState , create_agent
from langchain_mcp_adapters . interceptors import MCPToolCallRequest
from langchain . messages import ToolMessage
from langgraph . types import Command
async def handle_task_completion (
request : MCPToolCallRequest ,
handler ,
):
"""Mark task complete and hand off to summary agent."""
result = await handler ( request )
if request . name == "submit_order" :
return Command (
update = {
"messages" : [ result ] if isinstance ( result , ToolMessage ) else [],
"task_status" : "completed" ,
},
goto = "summary_agent" ,
)
return result
使用 goto="__end__" 的 Command 来提前结束执行
async def end_on_success (
request : MCPToolCallRequest ,
handler ,
):
"""End agent run when task is marked complete."""
result = await handler ( request )
if request . name == "mark_complete" :
return Command (
update = { "messages" : [ result ], "status" : "done" },
goto = "__end__" ,
)
return result
自定义拦截器
拦截器是包装工具执行的异步函数,支持请求/响应修改、重试逻辑和其他横切关注点。它们遵循“洋葱”模式,列表中的第一个拦截器是最外层。 基本模式 拦截器是一个异步函数,它接收一个请求和一个处理程序。您可以在调用处理程序之前修改请求,在之后修改响应,或者完全跳过处理程序。 from langchain_mcp_adapters . client import MultiServerMCPClient
from langchain_mcp_adapters . interceptors import MCPToolCallRequest
async def logging_interceptor (
request : MCPToolCallRequest ,
handler ,
):
"""Log tool calls before and after execution."""
print ( f "Calling tool: { request . name } with args: { request . args } " )
result = await handler ( request )
print ( f "Tool { request . name } returned: { result } " )
return result
client = MultiServerMCPClient (
{ "math" : { "transport" : "stdio" , "command" : "python" , "args" : [ "/path/to/server.py" ]}},
tool_interceptors = [ logging_interceptor ],
)
修改请求 使用 request.override() 创建一个修改后的请求。这遵循不变模式,保持原始请求不变。 async def double_args_interceptor (
request : MCPToolCallRequest ,
handler ,
):
"""Double all numeric arguments before execution."""
modified_args = { k : v * 2 for k , v in request . args . items ()}
modified_request = request . override ( args = modified_args )
return await handler ( modified_request )
# Original call: add(a=2, b=3) becomes add(a=4, b=6)
在运行时修改请求头 拦截器可以根据请求上下文动态修改 HTTP 请求头: async def auth_header_interceptor (
request : MCPToolCallRequest ,
handler ,
):
"""Add authentication headers based on the tool being called."""
token = get_token_for_tool ( request . name )
modified_request = request . override (
headers = { "Authorization" : f "Bearer { token } " }
)
return await handler ( modified_request )
组合拦截器 多个拦截器以“洋葱”顺序组合——列表中的第一个拦截器是最外层: async def outer_interceptor ( request , handler ):
print ( "outer: before" )
result = await handler ( request )
print ( "outer: after" )
return result
async def inner_interceptor ( request , handler ):
print ( "inner: before" )
result = await handler ( request )
print ( "inner: after" )
return result
client = MultiServerMCPClient (
{ ... },
tool_interceptors = [ outer_interceptor , inner_interceptor ],
)
# Execution order:
# outer: before -> inner: before -> tool execution -> inner: after -> outer: after
错误处理 使用拦截器捕获工具执行错误并实现重试逻辑: import asyncio
async def retry_interceptor (
request : MCPToolCallRequest ,
handler ,
max_retries : int = 3 ,
delay : float = 1.0 ,
):
"""Retry failed tool calls with exponential backoff."""
last_error = None
for attempt in range ( max_retries ):
try :
return await handler ( request )
except Exception as e :
last_error = e
if attempt < max_retries - 1 :
wait_time = delay * ( 2 ** attempt ) # Exponential backoff
print ( f "Tool { request . name } failed (attempt { attempt + 1 } ), retrying in { wait_time } s..." )
await asyncio . sleep ( wait_time )
raise last_error
client = MultiServerMCPClient (
{ ... },
tool_interceptors = [ retry_interceptor ],
)
您还可以捕获特定的错误类型并返回备用值
async def fallback_interceptor (
request : MCPToolCallRequest ,
handler ,
):
"""Return a fallback value if tool execution fails."""
try :
return await handler ( request )
except TimeoutError :
return f "Tool { request . name } timed out. Please try again later."
except ConnectionError :
return f "Could not connect to { request . name } service. Using cached data."
进度通知
订阅长时间运行工具执行的进度更新
from langchain_mcp_adapters . client import MultiServerMCPClient
from langchain_mcp_adapters . callbacks import Callbacks , CallbackContext
async def on_progress (
progress : float ,
total : float | None ,
message : str | None ,
context : CallbackContext ,
):
"""Handle progress updates from MCP servers."""
percent = ( progress / total * 100 ) if total else progress
tool_info = f " ( { context . tool_name } )" if context . tool_name else ""
print ( f "[ { context . server_name }{ tool_info } ] Progress: { percent :.1f } % - { message } " )
client = MultiServerMCPClient (
{ ... },
callbacks = Callbacks ( on_progress = on_progress ),
)
CallbackContext 提供
server_name:MCP 服务器的名称
tool_name:正在执行的工具名称(在工具调用期间可用)
日志记录
MCP 协议支持来自服务器的日志 通知。使用 Callbacks 类订阅这些事件。
from langchain_mcp_adapters . client import MultiServerMCPClient
from langchain_mcp_adapters . callbacks import Callbacks , CallbackContext
from mcp . types import LoggingMessageNotificationParams
async def on_logging_message (
params : LoggingMessageNotificationParams ,
context : CallbackContext ,
):
"""Handle log messages from MCP servers."""
print ( f "[ { context . server_name } ] { params . level } : { params . data } " )
client = MultiServerMCPClient (
{ ... },
callbacks = Callbacks ( on_logging_message = on_logging_message ),
)
请求用户输入
请求用户输入 允许 MCP 服务器在工具执行期间请求用户的额外输入。服务器无需预先要求所有输入,而是可以在需要时交互式地请求信息。
服务器设置
定义一个使用 ctx.elicit() 并带有 schema 请求用户输入的工具
from pydantic import BaseModel
from mcp . server . fastmcp import Context , FastMCP
server = FastMCP ( "Profile" )
class UserDetails ( BaseModel ):
email : str
age : int
@server . tool ()
async def create_profile ( name : str , ctx : Context ) -> str :
"""Create a user profile, requesting details via elicitation."""
result = await ctx . elicit (
message = f "Please provide details for { name } 's profile:" ,
schema = UserDetails ,
)
if result . action == "accept" and result . data :
return f "Created profile for { name } : email= { result . data . email } , age= { result . data . age } "
if result . action == "decline" :
return f "User declined. Created minimal profile for { name } ."
return "Profile creation cancelled."
if __name__ == "__main__" :
server . run ( transport = "http" )
客户端设置
通过向 MultiServerMCPClient 提供回调来处理请求用户输入
from langchain_mcp_adapters . client import MultiServerMCPClient
from langchain_mcp_adapters . callbacks import Callbacks , CallbackContext
from mcp . shared . context import RequestContext
from mcp . types import ElicitRequestParams , ElicitResult
async def on_elicitation (
mcp_context : RequestContext ,
params : ElicitRequestParams ,
context : CallbackContext ,
) -> ElicitResult :
"""Handle elicitation requests from MCP servers."""
# In a real application, you would prompt the user for input
# based on params.message and params.requestedSchema
return ElicitResult (
action = "accept" ,
content = { "email" : "user@example.com" , "age" : 25 },
)
client = MultiServerMCPClient (
{
"profile" : {
"url" : "https://:8000/mcp" ,
"transport" : "http" ,
}
},
callbacks = Callbacks ( on_elicitation = on_elicitation ),
)
响应操作
请求用户输入回调可以返回以下三种操作之一
操作 描述 接受用户提供了有效输入。在 content 字段中包含数据。 拒绝用户选择不提供请求的信息。 取消用户完全取消了操作。
# Accept with data
ElicitResult ( action = "accept" , content = { "email" : "user@example.com" , "age" : 25 })
# Decline (user doesn't want to provide info)
ElicitResult ( action = "decline" )
# Cancel (abort the operation)
ElicitResult ( action = "cancel" )
附加资源
将这些文档 连接到 Claude、VSCode 等,以获得实时答案。