沙盒命令行工具

mcpbash是一个轻量级命令行沙盒工具,允许用户将MCP工具、TypeScript函数和CLI命令映射到沙盒环境中运行,提供内存、只读或读写文件系统选项,并支持网络策略和git集成。

  • by buremba
  • TypeScript
  • 本地部署
  • 36 星标
  • 更新于
在 GitHub 查看 buremba/1mcp

使用说明

mcpbash

使用MCP工具、TypeScript函数、CLI和 just-bash.

mcpbash 为您提供一个小的shell优先沙盒对象。您无需配置VM或容器,而是将功能映射到命令中,并通过受控运行时运行它们。

安装

pnpm add mcpbash
# or
npm install mcpbash

为什么要使用它?

  • 将MCP工具映射到shell命令
  • 将TypeScript函数映射到shell命令
  • 包装现有二进制文件
  • 选择内存中、只读或读写文件系统
  • 选择加入 git 需要时提供支持
  • 使用简单的网络策略控制出站MCP访问
  • 在运行时解析秘密,而不是对其进行硬编码

快速开始

这个例子创建了一个命令, slugify,并在沙箱中运行它。

import { createSandbox, fn } from "mcpbash";

const sandbox = await createSandbox({
  filesystem: { mode: "memory" },
  commands: {
    slugify: fn({
      input: { text: "$1" },
      handler: ({ text }: { text: string }) =>
        text.toLowerCase().replace(/\s+/g, "-"),
    }),
  },
});

const result = await sandbox.run('slugify "Hello World"');

console.log(result.stdout); // hello-world
console.log(result.exitCode); // 0

await sandbox.dispose();

常见模式

运行一个真正的MCP支持的命令

此示例完全可运行。它启动了一个小型本地HTTP服务器,其行为类似于MCP工具端点,将该工具映射到沙箱中 repos.search,并像shell命令一样调用它。

import http from "node:http";
import { createSandbox, mcp } from "mcpbash";

async function startToolServer(): Promise<{ url: string; close(): Promise<void> }> {
  return new Promise((resolve) => {
    const server = http.createServer((req, res) => {
      if (req.method !== "POST" || req.url !== "/tools/search_repositories") {
        res.statusCode = 404;
        res.end("not found");
        return;
      }

      let body = "";
      req.on("data", (chunk) => {
        body += chunk.toString("utf8");
      });
      req.on("end", () => {
        const { input } = JSON.parse(body) as { input?: { q?: string } };
        const query = input?.q ?? "";

        res.setHeader("content-type", "application/json");
        res.end(
          JSON.stringify({
            result: {
              query,
              repos: [
                `${query}-api`,
                `${query}-web`,
                `${query}-worker`,
              ],
            },
          })
        );
      });
    });

    server.listen(0, "127.0.0.1", () => {
      const address = server.address();
      if (!address || typeof address === "string") {
        throw new Error("failed to start tool server");
      }

      resolve({
        url: `http://127.0.0.1:${address.port}`,
        close: () =>
          new Promise<void>((done, reject) => {
            server.close((error) => {
              if (error) reject(error);
              else done();
            });
          }),
      });
    });
  });
}

const toolServer = await startToolServer();

try {
  const sandbox = await createSandbox({
    filesystem: { mode: "memory" },
    network: {
      allow: ["127.0.0.1"],
    },
    commands: {
      "repos.search": mcp({
        server: toolServer.url,
        tool: "search_repositories",
        input: { q: "$1" },
      }),
    },
  });

  const result = await sandbox.run('repos.search "billing"');
  console.log(result.stdout);
  // {
  //   "query": "billing",
  //   "repos": ["billing-api", "billing-web", "billing-worker"]
  // }

  await sandbox.dispose();
} finally {
  await toolServer.close();
}

另请参见: packages/mcpbash/examples/mcp-demo.ts

包装本地CLI

import { cli, createSandbox } from "mcpbash";

const sandbox = await createSandbox({
  commands: {
    upper: cli({
      command: process.execPath,
      args: [
        "-e",
        "process.stdout.write((process.argv[1] ?? '').toUpperCase())",
        "$1",
      ],
    }),
  },
});

console.log((await sandbox.run('upper "hello"')).stdout); // HELLO

使用git在可写目录中工作

import { createSandbox } from "mcpbash";

const sandbox = await createSandbox({
  filesystem: {
    mode: "readwrite",
    root: "./workspace",
  },
  integrations: {
    git: true,
  },
});

await sandbox.run("git init -q");
await sandbox.fs.write("README.md", "# demo\n");

const status = await sandbox.git?.status(["--short"]);
console.log(status?.stdout);

API一览

import { createSandbox, mcp, fn, cli, provider, secret } from "mcpbash";
  • createSandbox(...) 创建沙盒
  • mcp(...) 将MCP工具映射到命令
  • fn(...) 将TypeScript处理程序映射到命令
  • cli(...) 包装本地二进制文件
  • provider(...) 是的别名 cli(...) 用于外部运行时
  • secret.env("NAME") 在运行时解析秘密
  • sandbox.run(...) 执行命令
  • sandbox.fs 暴露 read, write, list,以及 exists
  • sandbox.git 暴露 status, diff,以及 log 启用git时

文件系统模式

  • memory:隔离在内存沙箱中
  • readonly:覆盖现有目录而不写入
  • readwrite:使用真实目录返回沙盒

此仓库中的示例

  • packages/mcpbash/examples/mixed-demo.ts
  • packages/mcpbash/examples/mcp-demo.ts
  • packages/mcpbash/examples/git-demo.ts
  • packages/mcpbash/examples/benchmark.ts

运行它们:

pnpm install
pnpm --filter mcpbash demo:mixed
pnpm --filter mcpbash demo:mcp
pnpm --filter mcpbash demo:git
pnpm --filter mcpbash bench

高级用法

看 ADVANCED.md 用于:

  • 文件系统允许/拒绝规则
  • 秘密
  • 网络策略
  • MCP认证和OAuth模式
  • Daytona、Uptash Box和Docker的提供者示例
  • 当前限制

演出

2026年4月9日,在搭载Bun 1.3.5的苹果M4 Pro上进行本地基准测试:

操作 平均值 P50 P95
createSandbox() 0.067毫秒 0.040毫秒 0.090毫秒
内置shell命令(echo) 0.460毫秒 0.406毫秒 0.687毫秒
地图 fn(...) 命令 0.350毫秒 0.319毫秒 0.550毫秒
地图 provider(...) 命令(true) 2.143毫秒 2.038毫秒 3.298毫秒
地图 cli(...) 命令(node -e) 4.160毫秒 3.878毫秒 7.314毫秒

重要的结论是类别层面: mcpbash 坚持走当地的快车道。它不会仅仅为了分派映射的命令而提供VM、容器或远程会话,因此启动和分派保持在低毫秒范围内。

在本地运行基准测试:

pnpm --filter mcpbash bench

发展

pnpm install
pnpm --filter mcpbash typecheck
pnpm --filter mcpbash build
pnpm --filter mcpbash test