# @reinsjs/tools-mcp 中文文档

规范地址：https://npmcn.com/package/%40reinsjs/tools-mcp/

版本：0\.3\.3
npm 元数据更新时间：2026-11-02T06:36:21.365Z
中文译文更新时间：2026-11-02T07:56:13.853Z
软件包许可：MIT

本文由上游 README 机器翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40reinsjs/tools-mcp
原文对照：https://npmcn.com/package/%40reinsjs/tools-mcp/?lang=original
项目主页：https://github.com/AdRate-io/reins/tree/main/packages/tools-mcp#readme
源码仓库：https://github.com/AdRate-io/reins

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：77.7 kB，11 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=22
- 运行依赖：2 个
- 首次发布：2026-09-14T04:08:09.489Z
- 最新版本发布：2026-11-02T06:36:21.154Z
- 已发布版本数：8（近 12 个月 8 个）

## 中文简介

缰绳- MCP服务器作为套接字：每次运行一次工具/列表，工具/调用作为工具。执行、注释→风险/审批默认值。在web标准条目上的可流式HTTP，在。/node下的studio

## 安装

```sh
npm install @reinsjs/tools-mcp
```

也可以使用：`pnpm add @reinsjs/tools-mcp`、`yarn add @reinsjs/tools-mcp`、`bun add @reinsjs/tools-mcp`

## README

# @reinsjs / tools-mcp

插头一个 [MCP](https://modelcontextprotocol.io/) 将服务器作为一个REINS代理 `Socket`． 每个工具服务器 清单变成了缰绳 `Tool`;循环，大脑模块（泄漏，批准，预算，压缩……）和时间线治疗 它们就像进程内工具一样。服务器永远不会知道缰绳的存在。

```ts
import { httpTransport, mcpTools } from "@reinsjs/tools-mcp"
import { approval, spill } from "@reinsjs/brain"
import { createAgent } from "@reinsjs/agent"

const github = mcpTools({
  transport: httpTransport({
    url: "https://mcp.example.com/mcp",
    headers: { Authorization: `Bearer ${process.env.MCP_TOKEN}` },
  }),
})

export const agent = createAgent({
  model,
  store,
  tools: [myInProcessTool],
  sockets: [github, spill(), approval()],
})
```

仅节点的工作室服务器（通过stdin/stdout说JSON-RPC的子进程）位于 `/node` 条目:

```ts
import { stdioTransport } from "@reinsjs/tools-mcp/node"

const files = mcpTools({
  transport: stdioTransport({ command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "/data"] }),
  prefix: "fs_",
})
```

主入口只使用web标准api (`fetch`， `URL`， `Headers`)，并在Cloudflare Workers上运行 `nodejs_compat` (在2023兼容性日期验证，请参阅 `spikes/edge-runtime-check`)，在Bun上是Deno （`--allow-net` 就够了)，而Vercel的呢 `edge-runtime` （`spikes/runtime-matrix` - - - - - - `tools/list` + `tools/call` 针对每个服务器中的本地服务器)。只有 `/node` 导入 `node:*`.

## 在运行时发生了什么

**每次运行都绑定工具。** 当运行开始时，套接字调用 `tools/list` 一次，把结果变成 运行工具表。表不会改变，直到运行结束- a `notifications/tools/list_changed` 从 服务器只影响 _下一个_ 运行。这是经过深思熟虑的：稳定的工具表可以使提示缓存保持温暖，并且它可以使缓存保持温暖 这就是缰绳“不动态注册”立场的来源。循环将表记录在a中 `core.tools_bound` 事件 （对模型不可见），并且当它与之前运行的不同时，附加一个可见的 `system_note` 命名的 添加和删除工具，使模型知道它的手的变化。

**电话接通 `tools/call`.** 结果的 `content` 块成为缰绳内容部分(文本和图像按原样； 音频、资源链接和二进制资源变成了一行描述（有损，并如此说）。 `isError` 通过 通过。抛出的错误（未知工具、断开连接、超时）变成 `tool_result` 与 `isError: true`； 运行继续，模型决定做什么。

**注释设置默认值，而不是权限。** `readOnlyHint` → `risk: "low"`； `destructiveHint` → `risk: "high"` 和 `needsApproval: true`;其他任何内容（包括没有注释）→ `risk: "medium"`． MCP规范说注释是 提示和不受信任的服务器的注释不能驱动授权-因此缰绳只使用它们来 _默认的_ 这些领域 `@reinsjs/brain`的 `approval()` 政策阅读，以及 `override` 允许主机更改其中任何一个：

```ts
mcpTools({
  transport,
  override: (tool, info) => {
    if (info.name === "delete_repo") return false // never expose this one
    if (info.annotations?.openWorldHint) return { ...tool, needsApproval: true }
    return undefined // keep the default translation
  },
})
```

注意规范自己的默认for `destructiveHint` 是 `true` 当缺席。缰绳不将“未注释”视为 “破坏性的”——这将使每个休闲服务器的每个工具都处于审批提示之后。如果你想要的话 严格，加进去 `override` 或运行 `approval({ unmatched: "ask" })`.

## 连接的生命周期

`mcpTools()` 不连接。需要工具表的第一次运行打开连接；以后运行重用它。 如果传输关闭（服务器重新启动，网络断开），则需要它的下一个调用- a `tools/call` 在 相同的运行或 `tools/list` 在下次运行开始时-根据传输配方重新构建连接一次。有 调用内部没有重试策略：失败的调用作为错误结果报告给模型，失败的重新连接在 Run start在向日志写入任何内容之前抛出（失败关闭）。通过 `optional: true` 来代替 运行没有服务器的工具，并警告一次；然后，模型看到它们被列为已删除。

呼叫 `close()` 当您使用套接字时（进程关闭，或者主机替换了配置）。

为每个请求构建代理的主机应该 **按配置设置缓存套接字**，而不是每次都重建它们。 重建对每个请求强制进行一次新的MCP握手。 `examples/mcp/agent.ts` 控件键控的小缓存 服务器的配置JSON，关闭配置丢失的套接字。

## 不重启的热重新加载

没有重载API，因为不需要重载API。 `createAgent()` 只组装对象，工具表是 在运行开始时解决。将每个用户的MCP服务器存储在数据库中的平台读取该配置 当请求到达时，构建（或从缓存中获取）匹配 `mcpTools()` 套接字和运行。一个服务器 用户添加或删除的内容在其下一条消息中生效；这个循环告诉模型发生了什么变化。

需要了解的一个结果是：暂停审批的运行使用它所拥有的工具表进行签名。如果 暂停时配置发生更改，恢复被拒绝为配置漂移(`RunStateError` `config_mismatch`)。主机有三个诚实的选择：等待会话结束后再应用更改； 接受暂停的运行被放弃并开始一个新的运行，或者通过 `allowConfigDrift: true` 无论如何要继续—— 这份简历还会附上工具变更说明。什么图书馆不会做的是默默地恢复与不同 工具表比审批人看到的要多。

## 证书到期

一个固定的令牌可以驻留 `headers`． 过期的令牌不能： `headers` 在运输工具建成时是固定的， 虽然连接是惰性创建的，但可以跨运行重用，并在删除后从相同的recipe重新构建—所以只有一次 令牌过期，即使重新构建也会携带过期的令牌。通过 `auth` 而不是:

```ts
httpTransport({
  url: "https://business-api.tiktok.com/open_mcp/tt-ads-mcp-layer",
  auth: {
    token: () => db.accessToken(userId),          // called before every request
    onUnauthorized: () => db.refresh(userId),     // called on 401, then the request is retried once
  },
})
```

`auth` 和一个 `Authorization` 头是互斥的——在构造时传递两个抛出，而不是 让一个人默默获胜。

`McpAuth` 就是这两个方法，没有别的，也没有引用任何MCP SDK类型。事实并非如此 SDK的 `OAuthClientProvider`该界面的重要部分是驱动浏览器授权提示， 这是服务器端代理无法做到的。获取并存储令牌在您的web应用程序；循环只读取和 刷新。完整的OAuth流仍然没有包装-调用SDK `refreshAuthorization` （或者你自己的代码） 从内 `token` / `onUnauthorized`.

## Gateway-style服务器

一些服务器将数百个操作抛在脑后 **一个** 调度工具。TikTok for Business是当前的趋势 示例：它的分层端点注册了41个普通工具 `tool_list` / `tool_get` / `tool_execute`，和 其他约330个操作仅存在于服务器端注册表中，通过 `tool_execute({ tool_name, params })`.

这不会对循环造成任何损失——工具表在整个运行过程中是固定的，因此提示缓存前缀和配置散列是固定的 不受影响。 **但是它无声地挫败了针对工具名称编写的批准策略。** 创建一个活动， 修改预算和删除资产组都被称为 `tool_execute`;实际发生的是 参数。

```ts
// WRONG — this never matches. Every operation is named tool_execute.
approval({ deny: ["*_delete"], allow: ["*"] })

// RIGHT — decide on the operation name inside the arguments.
const operationOf = (args: unknown): string =>
  typeof args === "object" && args !== null && "tool_name" in args
    ? String((args as { tool_name?: unknown }).tool_name ?? "")
    : ""

approval({
  ask: [{
    id: "gateway.writes",
    match: (call) =>
      call.name === "tool_execute" && /_(create|update|delete|upload)$/.test(operationOf(call.args)),
    summary: (call) => `TikTok ${operationOf(call.args)}`,   // the approver sees the real operation
  }],
  allow: [
    { id: "gateway.reads", match: (call) =>
        call.name === "tool_execute" && /_(get|list|search)$/.test(operationOf(call.args)) },
    "tool_list",
    "tool_get",
  ],
})
```

此配方的可执行版本为 `packages/brain/src/gateway-tool.recipe.test.ts`，包括负面的 证明基于名称的规则允许删除的案例。

在没有配置规则的情况下，默认值是安全的，但很生硬：这样的服务器不声明注释，因此可以翻译 工具不携带 `risk`, `unmatched: "byRisk"` 发送 **每一个** 呼叫-包括读取-到一个人。这是 故障关闭设计；使用上面的recipe打开读路径，而不是允许dispatcher批发。

关于这种形状的服务器，还有两件事值得了解：

-   **注册表列表可能很大。** TikTok的 `tool_list` 返回~57 KB。下 `spill` 这就变成了预览 加上一个 `fetch_blob` Handle——无用，因为选择工具正是完整列表的目的。提高 这一工具的预算： `override: (tool, info) => info.name === "tool_list" ? { ...tool, resultPolicy: { maxTokens: 100_000, overflow: "spill" } } : tool`.
-   **上游业务错误可能不会设置 `isError`.** TikTok回报 `{"code": 40001, "message": "..."}` 作为一个 _成功的_ MCP的结果;只有mcp级故障（未知工具、传输错误） `isError`． 任何键控 从 `isError` -重试，你自己的政策， `onEvent` 观察者——除非你翻译它们，否则不会看到它们； 这个 `withBusinessErrors` 下一节中的包装器就是这样做的。

## 大型平面工作台

相反的形状：数百个普通的工具，每个都诚实地注释。TikTok的平面端点列出了其中的377个， 大约200次读取和130次写入，每个都有 `readOnlyHint`． 通常需要做两件事：保留写的内容 完全超出了模型的范围（它们通过您自己的工具，使用您自己的授权和审计跟踪）， 不要再为每个请求发送200个工具定义了。两者是一体的 `override` 加上 `@reinsjs/brain`的 `lazyTools()`：

```ts
import { lazyTools } from "@reinsjs/brain"
import { normalizeToolOutput, type Tool, type ToolResult } from "@reinsjs/core"

/** TikTok puts business errors in a successful result: text = {"code": <non-zero>, "message": ...} */
const businessErrorOf = (result: ToolResult): string | undefined => {
  if (result.isError) return undefined
  for (const part of result.content) {
    if (part.type !== "text") continue
    try {
      const body = JSON.parse(part.text) as { code?: unknown; message?: unknown }
      if (typeof body.code === "number" && body.code !== 0)
        return `Upstream error ${body.code}: ${String(body.message ?? "")}`
    } catch {
      // not JSON, not an error envelope
    }
  }
  return undefined
}

/** Keep the original text for the model, but mark it as an error so retries, policies and observers see it */
const withBusinessErrors = (tool: Tool): Tool => ({
  ...tool,
  async execute(input, ctx) {
    const result = normalizeToolOutput(await tool.execute?.(input, ctx))
    const error = businessErrorOf(result)
    return error ? { content: [...result.content, { type: "text", text: error }], isError: true } : result
  },
})

/** reads: on the menu, loaded on demand; everything else: not a tool the model has */
const readOnlyLazy = (tool: Tool, info: McpToolInfo) =>
  info.annotations?.readOnlyHint === true ? withBusinessErrors({ ...tool, lazy: true }) : false

const tiktok = mcpTools({ transport, override: readOnlyLazy })

createAgent({ sockets: [tiktok, lazyTools()] }) // order matters — see below
```

`lazyTools()` 从工具绑定中生成它的菜单 _之前_ 它：主机的，加上注册的每个套接字的 早些时候。所以它在 `mcpTools()`． 另一个订单不是错误，只是无用：MCP工具已经发送进来了 每个转弯都满了，而且 `lazyTools()` 警告一次，命名他们。有一个较低的层，它有一个原生的位置 延期工具(`@reinsjs/lowering-fetch` 在Anthropic上)加载工具甚至不会重新加热提示缓存；看到 大脑README的数字。

加载的定义像工具块本身一样受信任(`tool_find` 结果是 `trust: "system"`) - the 同样的描述已经在模型上展开了。一个200行的菜单大约需要1万个系统代币 提示;它位于缓存的前缀中，并且在运行中不会更改 `lazyTools({ summarize })` 可以缩短它。

此配方的可执行版本为 `packages/tools-mcp/src/readonly-lazy.recipe.test.ts`，包括 次序错了。

## 已验证的上游行为

请求的历史记录包含 `tool_use` / `tool_result` 对于不再在工具表中的工具 被DeepSeek的anthropic协议端点和OpenAI响应协议接受（两者都使用另一个工具） 有一个空的工具表)；该模型回答并正确列出了它当前的工具。所以 删除工具不需要在这些上游上创建新的会话。人类自己的终点，到达了 Cloudflare AI Gateway的直通路径，也接受这两种变体（2026-09-15）； `spikes/l1-deferred-tools` P8); 聚合器的Claude端点返回了一个截断的流，这是该代理的已知怪癖，而不是协议 被拒绝。脚本: `spikes/mcp-removed-tool-history`.

## 选项

| 选项 | 默认的 | 意义 |
| --- | --- | --- |
| `transport` | \- - - - - - | `httpTransport({ url, headers?, auth?, fetch?, requestInit? })` 或者 `stdioTransport({ command, args?, env?, cwd?, stderr? })` |
| `prefix` | 无 | 加在显示给模型的工具名称前；服务器仍然看到原始名称 |
| `callTimeoutMs` | 60 000 | 每 `tools/call` 超时;过期成为一个错误结果 |
| `optional` | `false` | 在 `tools/list` 运行开始时失败：抛出（默认）或不提供工具并警告一次 |
| `override(tool, info)` | \- - - - - - | 每个工具都重写;返回 `false` 放下工具 |
| `clientInfo` | `{ name: "reins", version }` | 发送MCP握手 |
| `warn` | `console.warn` | 哪里报告了退化 |

模型api拒绝的工具名称(`^[A-Za-z0-9_-]{1,64}$`)被重写(`files.read` → `files_read`)用… 一次性警告;电线上使用的是原始名称。

不支持：采样、启发、资源、提示、MCP应用程序和驱动OAuth授权 提示（在您的应用程序中获取令牌并将它们交给您） `auth`）。

## 许可证

MIT©2026 newate Limited

## 常见问题

### @reinsjs/tools-mcp 是什么？

缰绳- MCP服务器作为套接字：每次运行一次工具/列表，工具/调用作为工具。执行、注释→风险/审批默认值。在web标准条目上的可流式HTTP，在。/node下的studio

### 如何安装 @reinsjs/tools-mcp？

在项目目录运行 npm install @reinsjs/tools-mcp，或使用 pnpm add / yarn add / bun add。

### @reinsjs/tools-mcp 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @reinsjs/tools-mcp 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @reinsjs/tools-mcp 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=22。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @reinsjs/tools-mcp 可以商用吗？

@reinsjs/tools-mcp 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @reinsjs/tools-mcp 还在维护吗？

最新版本 0\.3\.3 发布于 2026/11/02（1 天前）；至今共发布 8 个版本，其中过去 12 个月发布了 8 个；首次发布于 2026/09/14。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

