1. 项目概述:为什么我们需要 mcp-run?
如果你最近在折腾 AI 编程,特别是想让 Claude、Cursor 这类智能助手帮你处理一些本地操作,比如读取文件、执行脚本或者查询系统状态,那你大概率已经接触过 MCP(Model Context Protocol)这个概念了。简单来说,MCP 是一个让大模型安全、可控地使用外部工具和数据的协议。但问题来了,官方提供的 MCP Server 开发框架,对于只是想快速验证一个想法、或者做一个一次性小工具的人来说,有点“杀鸡用牛刀”的感觉。你需要配置环境、理解复杂的项目结构、处理繁琐的启动参数……还没开始写核心逻辑,热情可能就被消耗了一半。
这就是mcp-run这类工具出现的背景。它的核心目标就一个:让你能用最简单、最直接的方式,把一个想法变成一个 AI 可用的工具。你可以把它想象成 MCP 世界里的“脚本运行器”。不需要复杂的项目脚手架,不需要理解完整的 Server 生命周期,甚至对协议细节一知半解也没关系。你只需要关注工具本身的逻辑:输入是什么,处理过程是什么,输出是什么。mcp-run负责帮你处理剩下的所有“脏活累活”,比如启动一个符合 MCP 协议的服务器、处理与 AI 客户端的通信、管理工具的生命周期等等。
我最初想做一个能让我用自然语言查询服务器磁盘空间的小工具,如果走标准流程,我可能得花半天时间。但用mcp-run的思路,我写了一个不到 50 行的 Python 脚本,五分钟就让它跑起来了,并且立刻就能在 Claude Desktop 里调用。这种快速将想法落地的体验,对于探索 AI 能力的边界至关重要。
2. mcp-run 的核心设计思路与工作原理
2.1 化繁为简:从标准 MCP Server 到轻量脚本
要理解mcp-run的设计,首先得看看一个标准的 MCP Server 有多“重”。一个典型的 MCP 服务器,比如用官方 TypeScript SDK 创建的项目,通常包含以下部分:
- 协议实现:必须实现
initialize,tools/list,tools/call等核心 MCP 协议端点。 - 工具注册与管理:需要显式地定义工具(
Tool)的输入输出 Schema(通常用 JSON Schema),并注册到服务器实例中。 - 生命周期管理:需要处理服务器的启动、信号监听、优雅关闭。
- 传输层配置:需要配置 STDIO(标准输入输出)或 SSE(服务器发送事件)等传输方式,以便与 AI 客户端(如 Claude Desktop)通信。
- 依赖与构建:一个完整的
package.json或pyproject.toml,以及可能的构建步骤。
这对于一个成熟的、需要长期维护的工具集是必要的。但对于一个“简单工具”呢?我们可能只想写一个函数。mcp-run的设计哲学就是面向函数编程。它假设你的工具核心就是一个函数:接收一些参数,执行一些操作,返回一个结果。至于这个函数如何被包装成 MCP 工具、如何启动服务器、如何与客户端握手,这些统统交给mcp-run来处理。
2.2 底层工作原理:一个精妙的封装器
mcp-run本身并不是一个 MCP 协议的完整实现者,而是一个封装器和胶水层。它的工作流程可以拆解为以下几个步骤:
- 脚本加载与解析:
mcp-run读取你提供的脚本文件(比如my_tool.py)。它会通过约定的方式(例如,查找特定的函数名、装饰器,或者解析脚本的导出对象)来识别出你想要暴露为 MCP 工具的函数。 - 动态工具包装:对于识别出的每个函数,
mcp-run会在内存中动态创建一个符合 MCP 协议规范的Tool对象。它会自动分析函数的参数(通过类型注解或默认值),并尝试将其映射为 JSON Schema,作为工具的输入描述。函数的文档字符串(docstring)则会被用作工具的“描述”。 - 内嵌服务器启动:
mcp-run内部启动了一个轻量级的、符合 MCP 协议的服务器。这个服务器只做最少的事情:在初始化时,向客户端宣告它动态包装好的那几个工具;在收到tools/call调用时,找到对应的函数,传入参数,执行它,并将返回值格式化成 MCP 要求的响应格式。 - 进程与通信管理:
mcp-run负责管理这个内嵌服务器的整个进程生命周期。它通常通过 STDIO 与 AI 客户端通信,这意味着 AI 客户端只需要像启动一个子进程一样启动mcp-run,并通过标准输入输出流交换 JSON 消息即可。mcp-run处理了所有消息的解析、路由和序列化。
这种设计带来的最大好处是关注点分离。作为工具开发者,你只需要关心你的业务逻辑函数写得对不对。作为工具使用者,你只需要知道如何运行mcp-run命令。中间的协议复杂性被完全隐藏了。
2.3 与同类方案的对比:为什么不是直接写脚本?
你可能会问:我直接写个脚本,让 AI 去调用系统命令执行这个脚本不也一样吗?这里有几个关键区别:
- 安全性:直接执行任意脚本是极高风险的行为。MCP 协议要求工具必须预先声明其输入参数和类型,AI 客户端在调用前可以进行校验,并且工具的执行是在一个受控的、预先定义好的上下文中进行的。
mcp-run继承了这种安全模型。 - 结构化交互:通过 MCP 调用工具,输入和输出都是结构化的 JSON 数据。你的脚本函数可以直接接收字典、列表等复杂对象,并返回同样结构化的数据。而通过系统命令调用,你通常只能传递字符串参数,并且需要自己解析标准输出。
- 发现与集成:MCP 工具可以被 AI 客户端自动发现和描述。在 Claude Desktop 中,连接后,AI 就能知道你有“查询磁盘空间”、“格式化文档”等工具,并理解它们的用途和参数。这是通过系统命令调用无法实现的体验。
- 状态与性能:
mcp-run启动的服务器是常驻进程。如果你的工具需要加载大型模型或建立数据库连接,这个成本只需要在启动时支付一次。后续的每次调用都非常快速。而每次通过系统命令调用脚本,都需要启动一个新的 Python 解释器进程,重复加载资源,效率低下。
3. 手把手实战:从零编写并运行你的第一个 mcp-run 工具
理论说得再多,不如动手做一遍。我们以 Python 环境为例,创建一个最简单的工具:一个能够对两个数进行加减乘除运算的计算器工具。
3.1 环境准备与依赖安装
首先,你需要一个 Python 环境(3.8+)。然后,安装mcp-run。目前它可能不是一个通过pip install mcp-run就能直接获取的包,因为它更像一个概念或一个社区工具的原型。我们可以模拟实现一个最简单的版本。
为了理解原理,我们不直接使用某个特定的mcp-run实现,而是利用现有的、最接近的库来搭建:mcp官方 Python SDK 的底层库,以及asyncio来处理异步通信。
# 创建一个新的项目目录 mkdir my-mcp-tools && cd my-mcp-tools # 创建虚拟环境(推荐) python -m venv .venv # 激活虚拟环境 # Windows: .venv\Scripts\activate # macOS/Linux: source .venv/bin/activate # 安装 MCP 协议的基础库和必要的依赖 pip install mcp注意:这里安装的
mcp包是协议底层库,它提供了构建 MCP 服务器和客户端的基础组件,但并不包含一个现成的mcp-run命令行工具。我们正是要用它来理解mcp-run是如何工作的。
3.2 编写工具函数脚本
现在,我们创建一个名为calculator_tool.py的脚本。这个脚本将包含我们想要暴露的工具逻辑。
# calculator_tool.py import asyncio from typing import Literal # 这是我们的核心工具函数 async def calculate( a: float, b: float, operation: Literal['add', 'subtract', 'multiply', 'divide'] ) -> str: """ 执行简单的算术运算。 Args: a: 第一个操作数。 b: 第二个操作数。 operation: 要执行的运算,可选值:'add'(加), 'subtract'(减), 'multiply'(乘), 'divide'(除)。 Returns: 运算结果的字符串表示。 """ if operation == 'add': result = a + b elif operation == 'subtract': result = a - b elif operation == 'multiply': result = a * b elif operation == 'divide': if b == 0: return "错误:除数不能为零。" result = a / b else: return "错误:未知的运算类型。" return f"{a} {operation} {b} = {result}" # 为了让“mcp-run”类工具能发现这个函数,我们需要以某种方式导出它。 # 一个常见的约定是提供一个 `tools` 列表或字典。 __all__ = ['calculate'] tools = [calculate] # 将函数放入一个列表中关键点解析:
- 异步函数:我们使用了
async def。这是因为 MCP 服务器通常是异步的,以高效处理并发请求。你的工具函数最好也是异步的,特别是当它可能涉及 I/O 操作(如读写文件、网络请求)时。 - 类型注解:
a: float,b: float,operation: Literal[...]。这些类型注解至关重要!它们是我们自动生成工具输入 Schema 的依据。Literal明确指出了operation参数只能取那几个特定的字符串值。 - 文档字符串(Docstring):函数下的三引号注释。这将成为 AI 客户端中看到的工具描述,帮助 AI 理解何时以及如何使用这个工具。
- 工具导出:我们创建了一个
tools列表。这是我们的脚本与“运行器”之间的一个简单约定:“运行器”会来查找这个变量,并将其中的每个函数注册为一个 MCP 工具。
3.3 实现一个简易的 mcp-run 启动器
由于没有现成的mcp-run,我们来写一个简化的启动脚本simple_mcp_runner.py,模拟它的核心行为。
# simple_mcp_runner.py import sys import asyncio import inspect import json from typing import Any, Dict, List import importlib.util from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client async def main(): if len(sys.argv) != 2: print("用法: python simple_mcp_runner.py <工具脚本路径>", file=sys.stderr) sys.exit(1) script_path = sys.argv[1] # 1. 动态加载工具脚本 spec = importlib.util.spec_from_file_location("tool_module", script_path) tool_module = importlib.util.module_from_spec(spec) spec.loader.exec_module(tool_module) # 2. 从模块中获取工具函数列表(遵循我们的约定) tool_functions = getattr(tool_module, 'tools', []) if not tool_functions: print(f"错误:在 {script_path} 中未找到 'tools' 列表。", file=sys.stderr) sys.exit(1) # 3. 为每个工具函数创建 MCP 工具描述 mcp_tools = [] for func in tool_functions: # 解析函数签名以生成 JSON Schema sig = inspect.signature(func) parameters_schema = { "type": "object", "properties": {}, "required": [] } for param_name, param in sig.parameters.items(): param_schema = {} # 处理类型注解(简化版,实际需要更复杂的类型映射) if param.annotation != inspect.Parameter.empty: # 这里只是一个简单演示,实际需要将 Python 类型映射为 JSON Schema 类型 if param.annotation in (int, float): param_schema["type"] = "number" elif param.annotation is str: param_schema["type"] = "string" elif hasattr(param.annotation, '__origin__') and param.annotation.__origin__ is Literal: param_schema["type"] = "string" param_schema["enum"] = list(param.annotation.__args__) else: param_schema["type"] = "string" # 默认回退到字符串 else: param_schema["type"] = "string" # 从文档字符串或参数默认值获取描述(此处简化) param_schema["description"] = f"参数 {param_name}" parameters_schema["properties"][param_name] = param_schema if param.default == inspect.Parameter.empty: parameters_schema["required"].append(param_name) tool_def = { "name": func.__name__, "description": func.__doc__ or f"执行 {func.__name__} 操作", "inputSchema": parameters_schema } mcp_tools.append(tool_def) # 4. 创建并运行 MCP 服务器(这里我们实际上创建一个客户端会话,并通过自定义逻辑模拟服务器) # 这是最简化的演示,真实实现需要实现完整的 MCP 服务器协议。 # 我们使用 mcp 库的底层客户端来模拟一个“反向”服务:我们主动连接到一个 Stdio 流。 server_params = StdioServerParameters( command=sys.executable, # 这里是个技巧,我们用自己作为“命令” args=['-c', 'print("MCP stdio server ready")'] # 实际上我们需要一个真正的服务器进程 ) # 注意:以下是一个概念性代码,真实环境需要更复杂的处理。 # 为了演示,我们直接打印出工具定义,并进入一个简单的读取-求值-打印循环。 print(json.dumps({ "jsonrpc": "2.0", "method": "notify", "params": { "method": "tools/list", "params": {"tools": mcp_tools} } }), flush=True) # 简单循环,读取 stdin 的调用请求,执行函数,打印结果 print("简易 MCP 工具运行器已启动,等待调用...", file=sys.stderr) while True: try: line = sys.stdin.readline() if not line: break request = json.loads(line.strip()) if request.get('method') == 'tools/call': tool_name = request['params']['name'] arguments = request['params'].get('arguments', {}) # 查找对应的函数 target_func = None for f in tool_functions: if f.__name__ == tool_name: target_func = f break if target_func: # 执行函数 try: # 注意:这里需要异步执行,我们简化用 asyncio.run # 实际应在异步上下文中 result = await target_func(**arguments) response = { "jsonrpc": "2.0", "id": request.get('id'), "result": { "content": [{"type": "text", "text": str(result)}] } } except Exception as e: response = { "jsonrpc": "2.0", "id": request.get('id'), "error": {"message": str(e)} } print(json.dumps(response), flush=True) else: print(json.dumps({ "jsonrpc": "2.0", "id": request.get('id'), "error": {"message": f"Tool not found: {tool_name}"} }), flush=True) except json.JSONDecodeError: continue except KeyboardInterrupt: break if __name__ == "__main__": asyncio.run(main())这个simple_mcp_runner.py脚本做了以下几件事:
- 加载用户指定的工具脚本。
- 从脚本中提取
tools列表。 - 通过反射(
inspect模块)分析每个函数的签名和文档,动态生成 MCP 协议要求的工具定义(inputSchema)。 - 启动一个简单的循环,从标准输入读取 JSON-RPC 格式的调用请求,找到对应的函数执行,并将结果通过标准输出以 JSON-RPC 格式返回。
这本质上就是一个极度简化的mcp-run。
3.4 连接与测试
要测试这个工具,我们需要一个 MCP 客户端。最方便的就是 Claude Desktop。
配置 Claude Desktop:找到 Claude Desktop 的 MCP 配置文件。通常在以下位置:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
- macOS:
编辑配置文件:在
mcpServers部分添加我们的“服务器”。{ "mcpServers": { "my-calculator": { "command": "python", "args": [ "/ABSOLUTE/PATH/TO/YOUR/simple_mcp_runner.py", "/ABSOLUTE/PATH/TO/YOUR/calculator_tool.py" ], "env": { "PYTHONPATH": "/ABSOLUTE/PATH/TO/YOUR/PROJECT" } } } }command: 我们使用python解释器。args: 第一个参数是我们的运行器脚本,第二个参数是工具脚本。env: 确保 Python 能找到你的脚本和可能安装的mcp库。
重启 Claude Desktop:保存配置文件并完全重启 Claude Desktop。
测试:重启后,在 Claude 的聊天框中,你应该能看到它已经加载了新工具。你可以尝试输入:“请用计算器工具计算一下 15.7 乘以 4.2。” Claude 应该会识别出
calculate工具,并请求你提供operation参数,或者它可能直接推断出使用multiply,然后调用工具并返回结果。
实操心得:第一次配置时,最常见的失败原因是路径错误或权限问题。务必使用绝对路径。可以在终端中先手动运行一下配置的命令,看看脚本是否能正常启动、有无报错(如模块导入错误)。另外,Claude Desktop 的配置是热加载的,但有时需要彻底重启(完全退出再打开)才能生效。
4. 进阶技巧:打造更实用的 mcp-run 工具
掌握了基础之后,我们可以让工具变得更强大、更健壮。
4.1 处理复杂参数与类型映射
上面的简易运行器对类型的处理非常粗糙。一个健壮的mcp-run应该能更好地处理复杂的 Python 类型到 JSON Schema 的映射。例如,处理List[str]、Dict[str, int]、Optional[float]等。我们可以利用pydantic库来极大地简化这个过程。
首先,安装pydantic:
pip install pydantic然后,我们可以用 Pydantic 的BaseModel来定义工具的输入,这样类型检查和 Schema 生成都会变得非常简单和准确。
# advanced_tool.py from typing import List, Optional from pydantic import BaseModel, Field import asyncio # 使用 Pydantic Model 定义输入结构 class SummarizeInput(BaseModel): text: str = Field(..., description="需要总结的文本内容") max_length: Optional[int] = Field(100, description="总结的最大长度,默认为100字符") keywords: List[str] = Field(default_factory=list, description="需要重点关注的关键词列表") async def summarize_text(input_data: SummarizeInput) -> str: """ 对提供的文本进行智能总结。 该工具会提取文本的核心内容,并根据可选的关键词进行侧重。 """ # 这里是一个简单的模拟实现 words = input_data.text.split() if input_data.keywords: # 简单模拟:如果有关键词,在总结中提及 summary = f"本文涉及{', '.join(input_data.keywords)}等概念。核心内容:{' '.join(words[:20])}..." else: summary = f"核心内容:{' '.join(words[:20])}..." if input_data.max_length and len(summary) > input_data.max_length: summary = summary[:input_data.max_length-3] + "..." return summary # 导出工具 tools = [summarize_text]在我们的simple_mcp_runner.py中,需要增加对 Pydantic Model 的检测。如果函数的参数是一个 Pydantic Model,那么直接使用model.schema()或model.model_json_schema()来生成inputSchema,这比手动解析inspect.signature要可靠和强大得多。
4.2 工具的多功能与组合
一个脚本可以暴露多个工具函数。mcp-run应该能自动将它们全部注册。只需确保你的tools列表包含了所有你想暴露的函数。
# multi_tool.py import asyncio import os from datetime import datetime async def get_current_time(timezone: str = "UTC") -> str: """获取指定时区的当前时间。""" # 简化处理,实际应使用pytz等库 now = datetime.utcnow() return f"Current UTC time is: {now.isoformat()} (Timezone: {timezone})" async def list_files(directory: str = ".") -> str: """列出指定目录下的文件和文件夹。""" try: files = os.listdir(directory) return f"Files in '{directory}':\n" + "\n".join(files) except FileNotFoundError: return f"错误:目录 '{directory}' 不存在。" except PermissionError: return f"错误:没有权限访问目录 '{directory}'。" # 导出多个工具 tools = [get_current_time, list_files]这样,当你运行这个脚本时,AI 客户端就能同时看到“获取当前时间”和“列出文件”两个工具。
4.3 错误处理与日志输出
在工具函数中,良好的错误处理非常重要。不要因为一个异常导致整个 MCP 服务器崩溃。应该用try...except捕获异常,并返回友好的错误信息。
此外,工具执行过程中的日志信息不应该污染返回给 AI 的结构化内容。通常,日志应该输出到标准错误(stderr),而工具的结果通过return返回,由运行器包装后从标准输出(stdout)以 JSON-RPC 格式发送。
async def safe_file_operation(filepath: str) -> str: """ 执行一个安全的文件操作示例。 """ import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) logger.info(f"开始处理文件: {filepath}") try: with open(filepath, 'r', encoding='utf-8') as f: content = f.read() # 模拟一些处理 processed = content.upper()[:500] # 取前500字符并转大写 logger.info("文件处理成功。") return processed except FileNotFoundError: error_msg = f"文件未找到: {filepath}" logger.error(error_msg) return error_msg except Exception as e: error_msg = f"处理文件时发生未知错误: {e}" logger.exception(error_msg) # 这会打印完整的堆栈跟踪到 stderr return error_msg注意事项:在真正的
mcp-run环境中,标准错误输出可能会被 AI 客户端的日志系统捕获。确保你的工具日志是清晰且有用的,便于在出现问题时进行调试。同时,返回给 AI 的错误信息应当简洁、明确,指导用户(或 AI)下一步该怎么做。
5. 常见问题与排查技巧实录
在实际使用和模拟实现mcp-run的过程中,我遇到了不少坑。这里记录下最常见的问题和解决方法。
5.1 连接与通信问题
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| Claude Desktop 启动后提示“无法连接 MCP 服务器”或工具列表为空。 | 1. 配置文件路径或语法错误。 2. 命令或参数错误,特别是路径不是绝对路径。 3. Python 环境问题(依赖未安装,或使用了错误的 Python 解释器)。 4. 脚本本身有语法错误,导致进程立即崩溃。 | 1.检查配置文件:使用 JSON 验证工具检查claude_desktop_config.json的语法。确保mcpServers对象格式正确。2.手动测试命令:在终端中,切换到配置中指定的工作目录(如果有 cwd设置),然后完整地运行command和args组成的命令。观察输出,看脚本是否能正常启动并停留在等待输入的状态,还是报错退出。3.检查环境变量:确保 PYTHONPATH或虚拟环境已正确配置。在配置中显式设置env字段可能更可靠。4.查看客户端日志:Claude Desktop 通常有日志文件。在 macOS 上,可以在 ~/Library/Logs/Claude/找到;Windows 在%APPDATA%\Claude\logs。查看日志中的错误信息。 |
| AI 客户端能连接,但调用工具时超时或无响应。 | 1. 工具函数是同步的,但被放在异步上下文中执行,导致阻塞。 2. 工具函数执行时间过长。 3. 运行器的通信循环逻辑有 bug,没有正确返回响应。 | 1.确保工具函数是异步的:除非你的运行器明确支持同步函数并在独立线程中运行它们,否则最好始终使用async def定义工具函数,并在内部使用await进行 I/O 操作。2.为长时间运行的任务添加超时:在工具函数内部实现超时逻辑,或者考虑将任务拆分为更小的步骤。 3.调试运行器:在运行器的通信循环中添加调试打印语句(输出到 stderr),查看是否收到了调用请求,以及是否发送了响应。 |
5.2 工具定义与调用问题
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| AI 无法正确识别工具参数,或调用时参数类型错误。 | 1. 工具输入 Schema 生成不正确。 2. 函数类型注解不明确或不被运行器支持。 3. AI 客户端对 Schema 的解析有差异。 | 1.简化类型:初期尽量使用基础类型(str,int,float,bool)和Literal。避免使用复杂的泛型如List[Dict[str, Any]],除非你的运行器能完美处理。2.使用 Pydantic:如前所述,使用 Pydantic BaseModel是生成准确 Schema 的最可靠方法。它能明确地定义字段类型、默认值、描述和验证规则。3.检查生成的 Schema:修改你的运行器,在启动时将生成的工具定义( inputSchema)打印到 stderr。用这个 JSON 去 JSON Schema 验证网站 检查其正确性。 |
| 工具被调用,但返回的结果 AI 无法理解或格式错误。 | 1. 返回的数据类型不是字符串或可序列化的简单结构。 2. 运行器没有按照 MCP 协议格式化响应。 3. 返回了过多无关信息(如调试日志)。 | 1.返回文本或简单结构:MCP 工具的content字段通常期望是文本。确保你的函数返回一个字符串。如果需要返回结构化数据,可以返回一个 JSON 字符串,并在工具描述中说明。2.遵循协议:确保运行器返回的 JSON-RPC 响应格式正确,特别是 result.content是一个包含type和text的对象列表。3.净化输出:确保工具函数的所有输出都通过 return语句,而不是print。将调试信息输出到logging或sys.stderr。 |
5.3 性能与资源管理
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| 工具调用速度慢,尤其是首次调用。 | 1. 工具函数内部有昂贵的初始化操作(如加载机器学习模型)。 2. 每次调用都启动新的进程或连接。 | 1.利用缓存或全局状态:在脚本的全局作用域或模块级别进行一次性初始化。例如,将模型加载放在函数外部。mcp-run服务器是常驻进程,全局变量会在多次调用间保持。2.连接池:如果需要访问数据库或外部 API,考虑在服务器启动时创建连接池,而不是每次调用都新建连接。 |
| 内存使用量随时间增长。 | 1. 工具函数导致内存泄漏(如不断追加到全局列表)。 2. 运行器本身有资源未释放。 | 1.审查工具代码:避免在全局范围内无限制地累积数据。对于需要缓存的数据,设置大小限制或过期策略。 2.使用轻量级运行器:如果你实现的运行器有复杂逻辑,确保没有不当的引用循环。对于长时间运行的服务,这是正常挑战,需要按常规服务进行内存剖析。 |
我个人在实际操作中的体会是,mcp-run这类工具的价值在于极大地降低了为 AI 构建工具的门槛。它把“与 MCP 协议对接”这个复杂的工程问题,简化成了“写一个 Python 函数”的简单问题。这使得产品经理、数据分析师甚至是有编程兴趣的用户,都能快速将自己的专业知识封装成 AI 可用的能力。虽然我们上面实现的是一个非常简易的版本,但它清晰地揭示了其核心原理。社区中已经出现了一些更成熟的实现,它们提供了更友好的 CLI、更完善的类型系统支持和错误处理。探索这些工具,或者基于这个思路去构建更适合自己工作流的工具,是拥抱 AI 时代编程方式的一个非常有趣的切入点。