Skip to content

toolcraft always injects approvals commands into CLI and MCP roots with no opt-out #400

Description

@kamilio

Summary

toolcraft@0.0.16 unconditionally injects an approvals group into roots passed to both runCLI and createMCPServer. There is no supported option to disable this for applications that do not expose human-in-loop approvals.

Reproduction

import { defineCommand, defineGroup, S } from "toolcraft";
import { runCLI } from "toolcraft/cli";
import { createMCPServer } from "toolcraft/mcp";

const root = defineGroup({
  name: "example",
  children: [
    defineCommand({
      name: "hello",
      params: S.Object({}),
      handler: async () => "hello",
    }),
  ],
});

await runCLI(root, { rootUsageName: "example" });
const server = createMCPServer(root, { name: "example", version: "1.0.0" });

Observed:

  • CLI help includes an unrelated approvals command group.
  • MCP tools/list includes approval-management tools unless consumers add a tool allowlist.
  • createMCPServer/runCLI pass the root through mergeApprovalsGroup unconditionally.

Relevant packaged code:

  • dist/cli.js: runCLI calls mergeApprovalsGroup(normalizeRoots(...))
  • dist/mcp.js: createMCPServer calls mergeApprovalsGroup(normalizeRoots(...))

Expected

Provide a supported option such as approvals: false or inject approvals only when human-in-loop behavior is configured. Application-defined roots should otherwise remain unchanged.

Why this matters

Libraries using one shared tool definition tree for CLI and MCP cannot expose an exact application-owned API without cloning/filtering/mutating the generated tree or maintaining a separate allowlist. Those are fragile downstream workarounds.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions