MCP协议与mcpman:安全扩展AI助手本地能力的完整指南
1. 项目概述与核心价值
最近在折腾一些本地AI应用和自动化工作流时,我遇到了一个挺普遍但有点烦人的问题:如何让我的AI助手(比如Claude Desktop、Cursor等)安全、可控地访问我本地的文件系统、数据库或者执行一些系统命令?直接开放权限风险太高,但每次手动复制粘贴文件内容又太麻烦。就在这个当口,我发现了tranhoangtu-it/mcpman这个项目。简单来说,它是一个Model Context Protocol (MCP) 服务器管理器,专门用来帮你轻松部署、管理和运行各种MCP服务器。
MCP这个概念可能对部分朋友还比较新,你可以把它理解为一个“安全协议”或“标准接口”。它定义了AI助手(客户端)如何与外部工具、数据源(服务器)进行安全、结构化的对话。比如,你想让AI帮你分析一个本地日志文件,AI不需要直接读取你的硬盘,而是通过一个符合MCP协议的“文件系统服务器”来请求文件内容。这个服务器就像是一个尽职的“管家”,只提供AI被授权访问的那部分信息。mcpman的价值就在于,它把这个“管家”的招聘、上岗和管理流程给自动化、可视化了。
对于开发者、AI应用爱好者或者任何希望提升本地AI工具能力的用户来说,mcpman解决的核心痛点就是“开箱即用”和“集中管理”。你不用再去一个个手动配置环境变量、写启动脚本、处理进程守护;mcpman提供了一个统一的命令行界面(CLI)和清晰的配置方式,让你能像安装手机App一样,轻松地为你的AI助手“安装”各种能力扩展。无论是读取本地目录、查询数据库状态,还是调用特定的API,都可以通过对应的MCP服务器来实现,而mcpman就是管理这些服务器的“应用商店”兼“后台管家”。
2. MCP协议与mcpman的定位解析
2.1 为什么需要MCP?一个安全与能力的平衡方案
在深入mcpman之前,我们必须先理解MCP协议诞生的背景。大型语言模型(LLM)本身是“无状态”且“无手无脚”的——它们擅长处理和生成文本,但无法直接操作外部世界。为了让AI变得更实用,我们需要赋予它们“感知”和“行动”的能力。传统做法有几种:
- 硬编码工具调用:在应用代码里写死一些函数,让AI可以调用。缺点是不灵活,每加一个新工具都要改代码。
- 开放API或插件系统:像ChatGPT插件那样。这提供了灵活性,但通常需要将数据或服务暴露在公网上,或者面临复杂的权限和审核问题。
- 直接系统访问:给AI脚本执行权限。这非常强大,但也极其危险,一个错误的指令可能导致数据丢失或系统损坏。
MCP协议试图在灵活性和安全性之间找到一个优雅的平衡点。它采用客户端-服务器(C-S)架构:
- 客户端 (Client):就是你的AI助手应用,如Claude Desktop。它知道如何按照MCP协议发送请求。
- 服务器 (Server):提供具体“能力”的独立进程。例如,一个“文件系统服务器”只提供读取指定目录文件的能力;一个“SQLite服务器”只提供执行查询的能力。
协议本身规定了通信的格式(通常是JSON-RPC over stdio或HTTP)和核心概念,如工具(Tools)、资源(Resources)和提示(Prompts)。服务器向客户端宣告自己有哪些工具可用,客户端在需要时调用这些工具,服务器执行并返回结果。整个过程中,AI客户端永远无法直接接触服务器背后的真实系统资源,它只能通过服务器定义好的、安全的接口来交互。
2.2 mcpman的核心功能:让MCP服务器管理变得简单
理解了MCP,再看mcpman就清晰了。它的核心定位是MCP Server Manager。想象一下,你找到了十几个有用的MCP服务器(GitHub上有很多开源实现),每个都可能用不同语言编写(Node.js, Python, Go等),有不同的依赖和启动方式。手动管理它们会是一场噩梦:
- 安装繁琐:每个都要
git clone,npm install或pip install。 - 配置复杂:需要正确设置环境变量、参数,并生成对应的配置片段,以便AI客户端能识别。
- 运行维护:需要手动启动进程,并确保它们常驻后台,崩溃了还要能自动重启。
- 更新困难:追踪每个项目的更新,并手动进行升级。
mcpman 就是为了解决上述所有问题而生的。它主要提供以下功能:
- 服务器发现与安装:可以从一个中央仓库(或指定Git仓库)发现可用的MCP服务器,并一键安装到本地。
- 统一配置管理:通过一个清晰的YAML配置文件(通常是
~/.config/mcpman/config.yml),集中定义所有你需要运行的服务器及其参数。 - 进程管理与守护:以可靠的方式启动和管理所有配置的服务器进程,提供类似“服务”的管理能力(启动、停止、查看状态、查看日志)。
- 客户端配置生成:自动生成适用于不同AI客户端(如Claude Desktop)的配置文件,你只需要简单引用即可,无需手动拼接复杂的命令行参数。
- 扩展性:支持添加自定义的服务器源,不局限于官方列表。
可以说,mcpman将MCP生态的使用门槛从“极客级别”降到了“普通用户级别”,是推动MCP协议普及和实用化的关键工具。
3. mcpman的安装与初始配置
3.1 环境准备与安装方式选择
mcpman本身是一个Go语言编写的二进制工具,这使得它的安装非常简便,几乎没有任何复杂的运行时依赖。在开始之前,请确保你的系统已经安装了较新版本的Go(1.20+),主要用于从源码编译安装的情况。对于大多数用户,我推荐直接下载预编译的二进制文件,这是最干净的方式。
安装步骤:
- 访问发布页面:打开项目的GitHub Releases页面(通常位于
https://github.com/tranhoangtu-it/mcpman/releases)。 - 选择合适版本:找到最新的稳定版(通常不带
-pre或-rc后缀)。根据你的操作系统和架构下载对应的压缩包。例如,对于macOS Apple Silicon芯片,选择mcpman_darwin_arm64.tar.gz;对于Linux x86_64,选择mcpman_linux_amd64.tar.gz。 - 解压并放置到PATH:
# 以Linux/macOS为例 tar -xzf mcpman_darwin_arm64.tar.gz # 将二进制文件移动到系统可执行路径,例如 /usr/local/bin(可能需要sudo) sudo mv mcpman /usr/local/bin/ # 或者移动到用户本地bin目录 mkdir -p ~/.local/bin mv mcpman ~/.local/bin/ # 确保 ~/.local/bin 在你的PATH环境变量中 echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc # 或 ~/.zshrc source ~/.bashrc - 验证安装:运行
mcpman --version,如果显示出版本号,说明安装成功。
注意:如果你热衷于使用最新开发版,也可以使用
go install从源码安装:go install github.com/tranhoangtu-it/mcpman@latest。但生产环境建议使用稳定的Release版本。
3.2 初始化配置与目录结构
安装完成后,第一次运行任何mcpman命令(如mcpman list)会自动在用户配置目录创建必要的文件夹和默认配置文件。我们来了解一下它创建的核心目录和文件:
~/.config/mcpman/ ├── config.yml # 主配置文件,定义要运行的服务器 ├── servers/ # 已安装的服务器二进制文件或脚本存放处 │ ├── filesystem/ # 例如,文件系统服务器 │ └── sqlite/ # 例如,SQLite服务器 └── logs/ # 各服务器的运行日志(如果配置了日志输出)最重要的就是config.yml文件。初始的配置文件可能很简单,甚至为空。我们需要按照自己的需求来编辑它。一个典型的配置结构如下:
# ~/.config/mcpman/config.yml servers: # 服务器1:本地文件系统访问(只读/home/user/projects目录) - name: "my-filesystem" command: "servers/filesystem/server" # 指向servers/目录下的可执行文件 args: ["--directory", "/home/your-username/projects"] env: MCP_SERVER_NAME: "Filesystem Server" autoStart: true # mcpman启动时自动运行此服务器 # 服务器2:SQLite数据库查询 - name: "my-sqlite" command: "node" args: ["/path/to/installed/sqlite-server/dist/index.js", "--db-path", "/path/to/your/database.db"] autoStart: true # 服务器3:自定义脚本或任意可执行文件 - name: "my-custom-tool" command: "/usr/bin/python3" args: ["/path/to/your/script.py"]每个服务器配置项都需要name(唯一标识符)、command(可执行命令)和args(参数列表)。env可以设置环境变量,autoStart控制是否随mcpman守护进程启动。
4. 核心操作:服务器的发现、安装与管理
4.1 探索与安装社区服务器
mcpman的强大之处在于它能连接到一个“服务器源”(registry),让你轻松发现和安装他人已经构建好的MCP服务器。默认情况下,mcpman可能会内置一个源,或者你需要通过配置来指定。
列出可用服务器:运行
mcpman search或mcpman list-available(具体命令请参考项目的README,不同版本可能有差异)来查看可以从源中安装的服务器列表。输出通常会包含服务器名称、简短描述和安装命令。安装服务器:假设你想安装一个名为
mcp-server-filesystem的服务器,命令可能类似于mcpman install mcp-server-filesystem。mcpman会:- 从源获取该服务器的元数据(如Git仓库地址、构建方式)。
- 将其克隆或下载到本地
~/.config/mcpman/servers/下的一个子目录中。 - 根据服务器类型(Node.js, Python等),自动或提示你安装必要的依赖。
- 执行构建脚本(如果存在),生成可执行文件或准备好运行环境。
- 最终,这个服务器的启动命令(
command和args)会被添加到你的config.yml中,或者生成一个独立的配置片段。
安装自定义服务器:如果你想安装一个不在官方源里的服务器,比如一个GitHub仓库,mcpman通常也支持直接通过Git URL安装。例如:
mcpman install https://github.com/someuser/mcp-server-awesome.git。这给了你极大的灵活性。
实操心得:在安装社区服务器前,最好先查看一下该服务器的GitHub仓库README。了解它的功能、需要的权限以及可能的配置选项。有些服务器可能需要你提前安装某些系统库(如
ffmpeg用于音频处理,sqlite3用于数据库访问)。
4.2 服务器的生命周期管理
安装好服务器并配置到config.yml后,就可以使用mcpman的统一命令来管理它们了。mcpman自身可以作为一个守护进程运行,管理所有配置为autoStart: true的服务器。
启动守护进程与所有服务器:
mcpman start这个命令会启动mcpman守护进程,然后根据
config.yml依次启动所有autoStart为true的服务器。你可以使用mcpman status来查看所有服务器的运行状态(Running, Stopped, Error)。单独控制单个服务器:
# 启动单个服务器(即使autoStart为false) mcpman start <server-name> # 停止单个服务器 mcpman stop <server-name> # 重启单个服务器(常用于配置更新后) mcpman restart <server-name> # 查看单个服务器的日志(如果配置了日志重定向) mcpman logs <server-name> -f # -f 参数可以跟踪实时日志停止所有服务器及守护进程:
mcpman stop-all # 或者 mcpman shutdown
一个关键技巧:进程管理与资源隔离。mcpman启动的每个服务器都是独立的子进程。这意味着:
- 崩溃隔离:一个服务器崩溃不会直接影响其他服务器或mcpman主进程。
- 资源限制:你可以通过系统工具(如
ulimit)或在配置中集成systemd等来限制单个服务器的CPU/内存使用。 - 日志分离:每个服务器的标准输出和错误可以被分别重定向到不同的日志文件,便于排查问题。你可以在服务器配置中添加
stdout和stderr参数来指定日志路径。
5. 与AI客户端集成:以Claude Desktop为例
服务器跑起来了,怎么让AI助手用上呢?这就需要配置你的AI客户端,让它知道去哪里找这些MCP服务器。这里以目前对MCP支持最完善的Claude Desktop为例。
5.1 配置Claude Desktop连接mcpman
Claude Desktop通过一个JSON配置文件来定义MCP服务器。mcpman可以简化这个配置过程。
找到Claude Desktop配置目录:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
- macOS:
使用mcpman生成配置:最方便的方法是让mcpman帮你生成配置片段。运行类似
mcpman config generate-for-claude的命令(具体命令请查证最新文档)。这个命令会读取你当前的config.yml,并生成一个JSON数组,其中包含了每个服务器通过标准输入输出(stdio)或网络套接字(socket)与Claude通信所需的配置。手动编辑配置(理解原理):如果mcpman没有自动生成功能,你需要手动编辑
claude_desktop_config.json。关键是在mcpServers对象中添加你的服务器。mcpman启动的服务器通常使用stdio方式通信。你需要知道每个服务器进程的启动命令。{ "mcpServers": { "my-filesystem": { "command": "/Users/your-username/.config/mcpman/servers/filesystem/server", "args": ["--directory", "/Users/your-username/projects"] }, "my-sqlite": { "command": "node", "args": ["/path/to/sqlite-server/dist/index.js", "--db-path", "/path/to/db.db"] } } }但是,这里有个问题:
claude_desktop_config.json要求的是直接的command和args。而mcpman是进程管理器。因此,更常见的集成模式是:- 模式A(推荐):配置Claude直接连接由mcpman启动的服务器监听的网络端口。这需要在mcpman的服务器配置中,让服务器以
socket模式运行(例如,通过--transport stdiovs--transport socket参数,取决于服务器实现),并在Claude配置中使用"url": "http://localhost:8080"这样的格式。 - 模式B:如果你坚持使用stdio,那么Claude配置中的
command应该指向一个能启动该服务器的脚本,而这个脚本本质上封装了mcpman启动单个服务器的逻辑。这稍微复杂一些。
实际上,许多MCP服务器设计时就更倾向于socket传输,因为它更稳定,且允许一个服务器被多个客户端连接。mcpman的配置需要与之配合。
- 模式A(推荐):配置Claude直接连接由mcpman启动的服务器监听的网络端口。这需要在mcpman的服务器配置中,让服务器以
重启Claude Desktop:保存配置文件后,完全退出并重新启动Claude Desktop应用。在Claude的界面中,你应该能看到新的工具可用(通常会在输入框附近出现工具图标,或者AI在回应时会表明它可以调用某些工具)。
5.2 验证与测试集成
配置完成后,如何测试是否成功?
- 在Claude中直接询问:你可以问Claude:“你现在可以使用哪些工具?” 或者 “你能帮我列出
/home/myuser/projects目录下的文件吗?” 如果配置正确,Claude会识别出可用的工具并尝试调用。 - 观察mcpman日志:在终端运行
mcpman logs <server-name> -f来实时查看指定服务器的日志。当你向Claude提出一个需要调用该服务器工具的请求时,你应该能在日志中看到相应的请求和响应记录,这能最直接地证明通信是成功的。 - 检查Claude Desktop开发者工具:某些客户端可能提供了更详细的日志或开发者工具,可以查看MCP通信的具体情况。
重要注意事项:权限和安全是重中之重。在配置文件系统服务器时,务必将其访问范围 (
--directory) 限制在必要的、不包含敏感信息的目录。永远不要将服务器配置为可访问根目录/或你的家目录~。对于数据库服务器,使用只读连接或限制特定SQL操作。MCP协议本身提供了安全框架,但最终的安全性取决于你如何配置这些服务器——最小权限原则是铁律。
6. 高级配置与自定义服务器开发
6.1 深入config.yml:环境变量、依赖与健康检查
基础的服务器配置只能满足简单需求。对于生产级或复杂的使用场景,我们需要更精细的控制。
环境变量与参数化:很多服务器的行为可以通过环境变量或命令行参数控制。在
config.yml中,你可以灵活设置:- name: "weather-api" command: "servers/weather/server" args: ["--units", "metric"] env: OPENWEATHER_API_KEY: "your-secret-api-key-here" # 敏感信息通过环境变量传递 TZ: "Asia/Shanghai" workingDir: "/tmp/weather-cache" # 设置服务器的工作目录将敏感信息(如API密钥)放在环境变量中,而不是硬编码在命令行参数里,是更安全的做法。
依赖管理与启动顺序:某些服务器可能依赖其他服务(如本地数据库)。虽然mcpman本身没有内置的依赖管理,但你可以通过巧妙配置来实现:
- 使用
autoStart: false先配置依赖项服务器(如数据库)。 - 编写一个启动脚本,在脚本中先启动依赖服务,再启动主服务器,然后将这个脚本作为
command。 - 或者,利用系统的服务管理器(如systemd)来管理依赖,mcpman只管理MCP服务器本身。
- 使用
健康检查与自动重启:一个健壮的服务管理器应该能处理进程崩溃。mcpman的基础版本可能只负责启动进程。为了实现自动重启,你可以:
- 结合使用
supervisor或systemd来托管mcpman及其子进程,利用它们强大的进程监控和重启功能。 - 或者,在服务器命令中使用一个包装脚本,该脚本内部实现一个简单的“无限循环”,在进程退出后重新启动它(但要小心避免崩溃循环)。
- 结合使用
6.2 构建你自己的MCP服务器
当社区服务器无法满足你的特定需求时,你可以选择自己开发一个。MCP协议有官方的SDK(如TypeScript/JavaScript的@modelcontextprotocol/sdk),让开发变得相对简单。
开发一个简单MCP服务器的步骤:
初始化项目:创建一个新的Node.js/Python/Go项目。
mkdir mcp-server-my-tool && cd mcp-server-my-tool npm init -y npm install @modelcontextprotocol/sdk实现服务器逻辑:你需要创建一个服务器实例,定义它提供的
Tools。以下是一个极简的TypeScript示例,提供一个“计算器”工具:// server.ts import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ToolSchema } from '@modelcontextprotocol/sdk/types.js'; const server = new Server( { name: 'my-calculator', version: '0.1.0' }, { capabilities: { tools: {} } } ); // 定义一个工具 const calculatorTool: ToolSchema = { name: 'calculate', description: 'Perform a basic arithmetic calculation.', inputSchema: { type: 'object', properties: { expression: { type: 'string', description: 'Arithmetic expression, e.g., "2 + 3 * 4"' } }, required: ['expression'] } }; // 注册工具处理函数 server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name === 'calculate') { const { expression } = request.params.arguments as { expression: string }; // 警告:在实际生产中,应对表达式进行严格的安全检查和沙箱计算! // 这里仅为演示,使用eval极其危险。 try { const result = eval(expression); // 仅作演示,切勿在生产环境使用eval! return { content: [{ type: 'text', text: `Result: ${result}` }] }; } catch (error) { return { content: [{ type: 'text', text: `Error: ${error}` }] }; } } throw new Error('Unknown tool'); }); // 启动服务器(通过stdio传输) const transport = new StdioServerTransport(); await server.connect(transport); console.error('MCP Calculator server running on stdio');构建与测试:编译TypeScript,然后你可以直接用Node.js运行这个服务器,并通过mcpman来管理它。首先,在
config.yml中添加:- name: "my-calculator" command: "node" args: ["/absolute/path/to/mcp-server-my-tool/dist/server.js"]然后通过
mcpman start my-calculator启动它,并配置到Claude Desktop中进行测试。
开发注意事项:
- 安全性是第一要务:永远不要相信来自客户端的任意输入。上面的
eval示例是极其危险的,仅用于演示协议调用流程。真实工具必须对输入进行严格的验证、消毒,或在沙箱中执行。 - 错误处理:工具函数必须有完善的错误处理,并返回结构化的错误信息,方便客户端(AI)理解。
- 文档清晰:为你工具定义的
description和inputSchema编写清晰、详细的描述,这直接决定了AI能否正确理解和使用你的工具。
7. 故障排查与性能优化
7.1 常见问题与解决方案
在实际使用mcpman和MCP服务器时,你可能会遇到以下典型问题:
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
mcpman start后服务器状态为Error或不断重启 | 1. 服务器命令或路径错误。 2. 服务器依赖未安装。 3. 服务器本身有bug,启动即崩溃。 4. 端口冲突(socket模式)。 | 1. 运行mcpman logs <server-name>查看详细错误输出。2. 手动在终端执行 config.yml中定义的command和args,看能否独立运行。3. 检查服务器所需的运行时(Node.js, Python版本)是否正确安装。 4. 使用 `netstat -an |
| Claude Desktop无法识别工具 | 1.claude_desktop_config.json配置错误。2. mcpman服务器未成功启动。 3. 传输方式不匹配(stdio vs socket)。 4. Claude Desktop未重启或缓存问题。 | 1. 使用mcpman status确认服务器是Running状态。2. 检查Claude配置中服务器的 command/args或url是否正确指向了mcpman管理的进程或端口。3. 确保服务器配置的传输方式与Claude配置的接收方式一致。 4. 彻底关闭Claude Desktop(包括后台进程)再重新打开。 |
| 工具调用超时或无响应 | 1. 服务器处理请求过慢或卡死。 2. 网络问题(socket模式)。 3. AI客户端超时时间设置过短。 | 1. 查看服务器日志,确认是否收到请求及处理耗时。 2. 优化服务器代码性能,对于耗时操作考虑异步或流式响应。 3. 检查防火墙或网络设置是否阻止了本地回环地址通信。 |
| 安装社区服务器失败 | 1. 网络问题,无法访问GitHub或源。 2. 系统缺少构建工具(如gcc, make)。 3. 项目本身的安装脚本有误。 | 1. 尝试手动git clone仓库,然后阅读其README进行手动安装。2. 确保系统已安装完整的开发环境。 3. 在项目的Issue页面搜索是否有类似问题。 |
一个关键的调试技巧:独立运行服务器。当遇到问题时,跳出mcpman,直接在终端用同样的命令和参数运行服务器。这能立刻告诉你问题是出在服务器本身,还是出在mcpman的管理或与客户端的集成环节。例如:node /path/to/server/index.js --directory ~/docs。
7.2 性能考量与资源管理
当你运行多个MCP服务器时,需要考虑系统资源。
- 内存与CPU占用:使用
htop,top或系统监控工具观察mcpman及其子进程的资源使用情况。一些用Python或Node.js写的服务器,如果处理大量数据,可能会占用较多内存。如果发现某个服务器异常占用资源,需要检查其代码是否有内存泄漏,或者考虑用更高效的语言(如Go, Rust)重写关键部分。 - 启动优化:对于解释型语言(如Python、Node.js)的服务器,冷启动可能会有一定延迟。如果对工具调用的响应速度要求极高,可以考虑:
- 使用像
uv这样的快速Python包安装器和运行器。 - 对于Node.js服务器,使用
pkg打包成单一可执行文件,避免模块加载开销。 - 确保服务器进程常驻(
autoStart: true),而不是每次调用时启动。
- 使用像
- 日志管理:持续运行的服务器会产生日志。定期清理
~/.config/mcpman/logs/目录下的旧日志文件,或者配置服务器的日志输出到系统的日志轮转服务(如logrotate)。
8. 生态展望与最佳实践建议
MCP协议和mcpman这样的工具,正在塑造下一代AI应用交互的新范式。它不再是把AI锁在一个封闭的聊天框里,而是将其变成了一个可以安全调度各种数字能力的“智能操作系统内核”。
对我个人而言,在实际部署和使用mcpman一段时间后,最深刻的体会是“边界感”的重要性。一开始,我总想给AI尽可能多的权限,让它能帮我做所有事。但很快我就意识到,这既不安全,也不高效。更好的做法是遵循“单一职责”和“最小权限”原则:
- 为每类任务创建专用服务器:不要试图打造一个“万能”服务器。一个只读的文件浏览器、一个只读的数据库查询器、一个发送邮件的工具、一个查询天气的API网关——各自独立。这样即使某个服务器出现问题,也不会影响其他功能,也更容易进行权限控制和审计。
- 配置文件版本化:将你的
~/.config/mcpman/config.yml纳入版本控制系统(如Git)。这样可以在多台机器间同步配置,也方便回滚。 - 敏感信息管理:切勿将API密钥、密码等硬编码在
config.yml中。使用环境变量,或者结合像direnv、1PasswordCLI这样的秘密管理工具,在启动mcpman前注入环境。 - 渐进式集成:不要一次性安装几十个服务器。从一个你最需要的服务器开始(比如文件系统),让它稳定运行几天,熟悉整个工作流后,再逐步添加新的。这有助于你隔离和解决问题。
最后,mcpman项目本身也在快速迭代。关注其Git仓库的更新,社区可能会不断加入新的功能,比如更直观的Web管理界面、更强大的服务器发现市场、或者与更多AI客户端的深度集成。这个领域正在蓬勃发展,而mcpman无疑是一个让你能轻松踏上这趟列车的优秀工具。
