Klavis CLI MCP Server:为 AI Agent 构建安全可控的命令行执行能力

📅 发布时间:2026/9/17 17:13:48
Klavis CLI MCP Server:为 AI Agent 构建安全可控的命令行执行能力
Klavis CLI MCP Server为 AI Agent 构建安全可控的命令行执行能力【免费下载链接】klavisKlavis AI: MCP integration platforms that let AI agents use tools reliably at any scale项目地址: https://gitcode.com/GitHub_Trending/kl/klavis导读CLI MCP Server 是 Klavis 开源仓库中位于mcp_servers/local/terminal/的一个本地 MCPModel Context Protocol服务器它把在终端执行命令这一能力以受控、可审计的方式暴露给 Claude Desktop、Cursor 等 MCP 客户端。本文以该模块的 README 为核心脉络结合 server.py 源码逐层拆解其安全模型、环境变量配置、两个内置工具run_command与show_security_rules、错误处理体系以及构建发布流程。读完本文你将掌握如何把该服务器接入主流 MCP 客户端理解命令白名单、路径穿越防护、Shell 操作符注入防护等安全机制在源码中的具体实现方式。项目定位给 LLM 一把上了锁的终端直接让大语言模型执行任意命令行存在明显的安全风险模型可能误触危险命令、路径可能越界访问敏感目录、Shell 操作符可能被用来拼接恶意指令。CLI MCP Server 的核心设计目标就是在把终端能力交给 LLM与维持安全边界之间取得平衡。正如 README 所述它是一个用于执行受控命令行操作、并附带全面安全特性的 MCP 服务器实现适合为 LLM 应用提供受控的 CLI 访问。从源码结构看该模块只有两个文件构成核心实现src/cli_mcp_server/server.py全部业务与安全逻辑和 src/cli_mcp_server/init.py包入口通过asyncio.run(server.main())启动 stdio 服务配合 pyproject.toml 完成打包与命令行入口注册。仓库的文档索引页 docs/mcp-server/local/terminal.mdx 也将其归类为本地 MCP 服务器——即运行在用户自己机器上、通过 stdio 与客户端通信的服务器。核心特性一览README 明确列出的能力包括 严格校验的安全命令执行⚙️ 可配置的命令与 flag 白名单支持all通配选项️ 路径穿越directory traversal防护与路径校验 Shell 操作符注入防护⏱️ 执行超时与命令长度限制 详细的错误报告 异步操作支持 工作目录限制与校验环境变量配置六个开关决定安全边界服务启动时完全通过环境变量进行安全配置load_security_config() 负责读取并解析这些变量。完整参数表如下来源README 配置章节默认值可与源码逐一对应变量说明默认值ALLOWED_DIR命令执行的基础目录必填无必填ALLOWED_COMMANDS允许的命令列表逗号分隔或allls,cat,pwdALLOWED_FLAGS允许的 flag 列表逗号分隔或all-l,-a,--helpMAX_COMMAND_LENGTH命令字符串最大长度1024COMMAND_TIMEOUT命令执行超时时间秒30ALLOW_SHELL_OPERATORS是否允许 Shell 操作符、\|\|、\|、等false注意将ALLOWED_COMMANDS或ALLOWED_FLAGS设为all将分别放行任意命令或任意 flag务必在受信任的环境中使用。源码中的解析细节对照源码可以发现几个容易忽略的细节all的大小写不敏感load_security_config使用allowed_commands.lower() all判断通配模式因此ALL、All均有效server.py。ALLOW_SHELL_OPERATORS的取值语义只有true或1不区分大小写会被视为开启其他任意值均视为关闭server.py。白名单去重命令与 flag 会被解析为set天然去重且all模式下白名单集合为空集、仅靠布尔标志判断server.py。ALLOWED_DIR启动即校验CommandExecutor.__init__会检查目录是否存在否则抛出ValueError(Valid ALLOWED_DIR is required)server.py这说明该变量虽然只标注为必填但缺失或无效时服务会直接启动失败而非静默降级。目录会做规范化allowed_dir被存储为os.path.abspath(os.path.realpath(allowed_dir))即先解析符号链接再取绝对路径作为后续所有路径安全判断的基准server.py。这些配置会被封装进SecurityConfigdataclassserver.py成为整个执行链路的唯一安全事实来源。内置工具run_command 与 show_security_rules该服务器通过 handle_list_tools() 向客户端注册两个工具所有工具调用统一由 handle_call_tool() 分发处理。run_command受控命令执行执行白名单内命令的核心工具。其输入 Schema 为{ command: { type: string, description: Single command to execute (e.g., ls -l or cat file.txt) } }一个值得注意的细节是run_command的工具描述description是动态生成的会包含当前工作目录、可用命令列表、可用 flag 列表以及 Shell 操作符支持状态server.py。这意味着 LLM 在调用前就能看到自己可以做什么从而减少无效调用。README 强调的安全约束如下Shell 操作符、|、、等默认不支持可通过ALLOW_SHELL_OPERATORStrue开启命令必须命中白名单除非ALLOWED_COMMANDSallflag 必须命中白名单除非ALLOWED_FLAGSall所有路径都会被校验确保位于ALLOWED_DIR之内。show_security_rules运行时安全状态自省无参数工具输出当前生效的安全配置包括工作目录、允许的命令、允许的 flag、安全限制最大命令长度与超时时间server.py。这一工具对 LLM 特别有用——当模型不确定自己能执行什么时可以先调用它获取环境约束再规划命令。输出格式为纯文本的安全配置摘要如Security Configuration: Working Directory: /path/to/allowed/dir Allowed Commands: ---------------- cat, ls, pwd Allowed Flags: ------------- -a, -l, --help Security Limits: --------------- Max Command Length: 1024 characters Command Timeout: 30 seconds安全机制深度解析从声明到源码实现README 的安全特性清单Security Features 章节每一项都能在CommandExecutor中找到对应实现。下面逐条对照。1. 命令白名单与 flag 校验_validate_single_command使用shlex.split将命令字符串拆分为[命令, 参数...]server.py命令部分非all模式下若命令不在allowed_commands集合中抛出CommandSecurityError(fCommand {command} is not allowed)参数部分以-开头的参数被视为 flag非all模式下必须命中allowed_flags否则拒绝执行。2. 路径穿越防护与路径规范化这是最核心的安全环节分两层实现显式路径识别参数以./、../、/开头但不以//开头或参数本身是.时被判定为显式路径必须走路径校验server.py此外包含/且拼接到allowed_dir后真实存在的参数也会被视为路径参数。边界检查_normalize_path先对相对路径做os.path.join(allowed_dir, path)拼接再统一经过os.path.abspath(os.path.realpath(...))解析——realpath会解析符号链接因此allowed_dir内部的 symlink 若指向外部目录也会被识破。随后_is_path_safe检查解析后的绝对路径是否以allowed_dir的绝对路径开头server.py。从源码结构看realpathstartswith的组合是双重保险既防../字面量穿越也防符号链接逃逸。另外值得一提的是_is_url_pathserver.py对http:///https://开头的参数如curl https://example.com服务器不做路径规范化、直接放行避免将 URL 误判为本地路径。3. Shell 操作符注入防护源码中定义了完整的操作符黑名单[, ||, |, , , , , ;]server.py。当命令中包含任一操作符时若ALLOW_SHELL_OPERATORS未开启直接抛出CommandSecurityError并提示Set ALLOW_SHELL_OPERATORStrue to enableserver.py若已开启则进入_validate_command_with_operators用正则把命令按操作符切段逐段独立执行_validate_single_command校验确保ls -l; rm -rf /这类拼接中的每一段都合法只有全部通过后才以shellTrue方式执行原始字符串server.py。4. 命令长度限制与执行超时execute方法在执行前先检查len(command_string) max_command_length超限即抛CommandSecurityErrorserver.py随后调用subprocess.run时传入timeoutcommand_timeout与cwdallowed_dir超时由subprocess.TimeoutExpired捕获并转换为CommandTimeoutErrorserver.py。5. shellTrue 与 shellFalse 的区分执行execute的执行策略体现了最小特权思想server.py命令不含Shell 操作符时用shellFalse并传入[command] args列表——不经过 shell 解析参数注入风险显著降低命令包含Shell 操作符且已获授权时才以shellTrue执行原始字符串。两种模式都使用textTrue、capture_outputTrue同时捕获 stdout 与 stderr。错误处理体系README 的 Error Handling 章节 定义了完整的异常层级源码中全部位于 server.py异常类型触发场景CommandError命令相关错误的基类CommandSecurityError安全违规命令/flag 不在白名单、路径越界、长度超限、Shell 操作符被禁CommandExecutionError命令执行失败进程启动/运行异常CommandTimeoutError命令执行超时在工具调用层handle_call_tool会把这些异常转换为带errorTrue标记的TextContent返回给客户端server.py例如安全违规会返回Security violation: ...。正常执行时则返回 stdout、stderr 以及Command completed with return code: N三部分内容server.pyLLM 可以据此判断命令是否真正成功。接入 MCP 客户端以 Claude Desktop 为例安装方式README 提供了两条安装路径方式一通过 Smithery 自动安装到 Claude Desktopnpx smithery/cli install cli-mcp-server --client claude方式二手动配置 Claude Desktop编辑~/Library/Application\ Support/Claude/claude_desktop_config.json按部署形态选择以下两种配置之一。开发/未发布服务器配置从仓库源码目录启动{ mcpServers: { cli-mcp-server: { command: uv, args: [ --directory, path/to/the/repo/cli-mcp-server, run, cli-mcp-server ], env: { ALLOWED_DIR: /your/desired/dir, ALLOWED_COMMANDS: ls,cat,pwd,echo, ALLOWED_FLAGS: -l,-a,--help,--version, MAX_COMMAND_LENGTH: 1024, COMMAND_TIMEOUT: 30, ALLOW_SHELL_OPERATORS: false } } } }已发布服务器配置通过uvx从 PyPI 拉取{ mcpServers: { cli-mcp-server: { command: uvx, args: [ cli-mcp-server ], env: { ALLOWED_DIR: /your/desired/dir, ALLOWED_COMMANDS: ls,cat,pwd,echo, ALLOWED_FLAGS: -l,-a,--help,--version, MAX_COMMAND_LENGTH: 1024, COMMAND_TIMEOUT: 30, ALLOW_SHELL_OPERATORS: false } } } }如果客户端界面中看不到该服务器或配置不生效README 建议先执行uv clean清理缓存后再重启客户端。配置建议从源码行为可以给出几条实际配置建议ALLOWED_DIR务必收敛到最小需要的目录如项目工作区切勿设为/或~因为_is_path_safe的startswith判断意味着白名单目录越宽LLM 可触碰的文件面就越大白名单命令越少越好默认的ls,cat,pwd已经覆盖最常见的文件浏览需求需要新增命令时如echo、git status按需追加即可默认 flag 只有-l,-a,--helpls -la这类常见组合恰好覆盖但rm -rf的-rf不在默认白名单内这是有意为之的防护生产环境保持ALLOW_SHELL_OPERATORSfalse仅在受信任的沙箱场景下才开启。开发、构建与发布环境要求Python 3.10pyproject.toml 声明requires-python 3.10MCP 协议库依赖mcp1.10.1构建与发布基于 uv 工具链# 1. 同步依赖并更新 lockfile uv sync # 2. 构建分发包生成 source 与 wheel 到 dist/ 目录 uv build # 3. 发布到 PyPI uv publish --token {{YOUR_PYPI_API_TOKEN}}其中命令行入口在 pyproject.toml 的[project.scripts]段注册cli-mcp-server cli_mcp_server:main指向init.py 中的main()——该函数通过asyncio.run启动 stdio 服务。另可注意到pyproject.toml中包版本为0.2.5而服务初始化时向客户端宣告的server_version为0.2.1server.py两者在源码中目前并不完全一致。调试使用 MCP Inspector由于 MCP 服务器基于 stdio 通信调试较为困难。README 推荐使用 MCP Inspector通过 npx 启动npx modelcontextprotocol/inspector uv --directory {{your source code local directory}}/cli-mcp-server run cli-mcp-server启动后 Inspector 会输出一个可在浏览器中访问的 URL用于交互式地浏览工具列表、手动触发run_command/show_security_rules调用并观察返回内容——这是验证安全配置是否生效的最快途径。许可证与更多参考本项目以 MIT 许可证发布见 LICENSE。相关参考资源模块 READMEmcp_servers/local/terminal/README.md核心实现mcp_servers/local/terminal/src/cli_mcp_server/server.py包入口mcp_servers/local/terminal/src/cli_mcp_server/init.py打包配置mcp_servers/local/terminal/pyproject.toml文档索引页docs/mcp-server/local/terminal.mdx该服务器与仓库中mcp_servers/local/目录下的 filesystem、git、memory 等同属本地 MCP 服务器家族均可通过相同的方式接入 MCP 客户端。如果你需要在自有环境中让 AI Agent 安全地操作终端以 terminal/README.md 为起点、配合本文的源码级剖析即可快速完成部署与定制。【免费下载链接】klavisKlavis AI: MCP integration platforms that let AI agents use tools reliably at any scale项目地址: https://gitcode.com/GitHub_Trending/kl/klavis创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考