内容
<div align="center">
# 铜
**AI 代理工具调用的 `tail -f`**
铜是由 [Basematter](https://basematter.dev) 开发的开源命令行界面(CLI),用于观察 [MCP(模型上下文协议)](https://modelcontextprotocol.io) 工具调用。只需一行代码即可包装您的 MCP 客户端。实时查看代理发出的每个工具调用。秘密信息会被遮蔽。风险调用会被标记。无需服务器,无需数据库,无需仪表板 —— 只需一个小而精的 CLI。
<br />
<img src="https://raw.githubusercontent.com/noelschwarz/copper/main/docs/demo-screenshot.png" alt="Copper 在终端中记录 MCP 工具调用,显示风险级别和遮蔽的秘密信息" width="720" />
</div>
<br />
## 为什么
构建代理意味着观察它们执行您未预期的操作。大多数情况下,您通过在 12 步运行结束后读取结果来发现问题 —— 而此时有趣的时刻已经在 JSON 墙中滚动过去。Copper 打印每个工具调用,格式化后便于快速阅读,让您在调用发生时看到正在发生的事情。
这是对问题的最小化回答:“我的代理现在到底在做什么?”
## 五秒钟试用
```bash
npx @basematter/copper demo
```
这将运行一个模拟代理,发出几个工具调用,让您在将自己的代理连接到 Copper 之前看到输出效果。从依赖此软件包的项目中,`npm exec copper demo` 将使用本地的 `copper` 二进制文件运行相同的演示。
## 安装
```bash
npm install @basematter/copper
```
需要 **Node.js 20** 或更新版本。
## 使用
```ts
import { Client } from "@modelcontextprotocol/sdk/client/index.js"
import { watch } from "@basematter/copper"
const client = watch(new Client(/* ... */))
// 正常使用客户端 —— 每个工具调用都会被记录
await client.callTool({
name: "read_file",
arguments: { path: "./README.md" },
})
```
这就是整个 API。`watch()` 函数包装现有的 MCP 客户端,并返回一个具有相同接口的新客户端。您的代理代码不会改变。工具调用会在 stdout 上实时显示。
## 您将看到的内容
每个调用打印为一个小块:
```text
▸ write_file ⚠ medium 127ms
args: { path: "/tmp/notes.txt", content: "Meeting notes from <REDACTED:email>..." }
→ ok
```
请注意以下三点:
- 参数在渲染之前会被 **遮蔽**。秘密信息永远不会离开您的进程。
- 风险指示器(`× high`、`⚠ medium`,低风险不显示图标)会根据工具执行的操作而非工具名称出现在调用旁边。
- 错误会以红色打印,失败原因内联显示 —— 无需回滚查找错误原因。
如果 stdout 不是 TTY(您正在将输出重定向到文件或在 CI 中运行),颜色和图标会消失,以便输出保持 grep 友好。
## 配置
`watch()` 函数接受一个可选的第二个参数:
```ts
watch(client, {
stream: process.stderr, // 默认:process.stdout
redact: customRedactor, // 默认:内置模式
risk: customRiskScorer, // 默认:内置启发式算法
})
```
默认配置针对常见情况进行了优化 —— MCP 客户端调用典型的文件系统、Shell、网络和数据库工具。大多数用户无需覆盖这些默认设置。
## 遮蔽内容
Copper 配备了一组内置模式,涵盖常见情况:
- **OpenAI**、**Anthropic**、**Stripe** API 密钥(`sk-...`、`sk-ant-...`、`sk_live_...`)
- **AWS** 访问密钥(`AKIA...`)
- **GitHub** 个人访问令牌(`ghp_...`、`gho_...`、`ghs_...`)
- **Slack** 令牌(`xoxb-...`、`xoxp-...`)
- 电子邮件地址、电话号码(E.164)、信用卡号码(Luhn 验证)
- 高熵字符串(32+ 个字符的十六进制或 base64 字符串,看起来像秘密信息)
这不是一个详尽的列表,涵盖了每个供应商的令牌格式。如果您正在调用传递 Google Cloud 密钥、Azure 连接字符串、JWT、私钥、数据库连接 URI 或上述未列出的供应商特定令牌的工具,Copper 的默认设置将无法捕获它们。
目前,您应该将 Copper 的内置遮蔽功能视为一个有用的初步步骤,而不是一个保证。如果您需要更广泛的覆盖范围,请传递您自己的遮蔽函数:
```ts
watch(client, {
redact: (args) => myCustomRedactor(args),
})
```
一个更全面的秘密检测规则集 —— 涵盖数百种供应商令牌格式 —— 计划在 v0.2 中实现。请参阅 [TODO.md](./TODO.md)。
## 风险标记
一个小型启发式评分器根据工具名称和参数为每个调用分配一个风险级别:
- **高** —— 子进程执行(`exec`、`run_command`、`shell`)、破坏性 SQL(`DROP`、`DELETE`、`TRUNCATE`、`ALTER`)、与秘密信息相邻的读取操作
- **中等** —— 文件写入、删除、非允许列表域的网络调用
- **低** —— 读取、查找、获取样式调用
评分故意保持简单。如果您想要更智能的评分,请完全替换它:
```ts
watch(client, {
risk: (toolName, args) => {
if (toolName === "deploy_to_prod") return { level: "high", score: 100 }
return { level: "low", score: 0 }
},
})
```
## 这不是什么
- **不是 LLM 跟踪平台。** Copper 看不到提示或补全信息。它只了解工具调用。
- **不是托管服务。** 没有后端。没有任何信息会发送到服务器。该软件包完全在您的进程中运行。
- **不是安全工具。** Copper **观察**。它不 **强制执行**。如果调用存在风险,Copper 会标记它;它不会阻止它。
## 路线图
- **v0.1** —— 当前。MCP 客户端包装器、遮蔽、风险标记、终端输出。
- **v0.2** —— 全面的秘密检测规则集、其他工具调用 SDK 的适配器、JSON 输出模式、持久文件日志记录。
- **后续** —— 如果有兴趣,可能是一个小的静态 HTML 视图。也可能没有。这是个人项目。
## 贡献
欢迎提出问题和拉取请求。代码库足够小,可以在一个下午阅读 —— 所有内容都位于 `src/` 目录下,分为几个 TypeScript 模块。
尤其欢迎以下首次贡献:
- 应内置但未内置的遮蔽模式
- 工具名称或参数形状应比当前评分更高的贡献
- 显示 Copper 与您使用的真实 MCP 服务器一起运行的小示例
如果您是首次贡献,请阅读 [行为准则](./CODE_OF_CONDUCT.md)。
## 许可证
MIT。参见 [LICENSE](./LICENSE)。