toolcapsule 0.1.0-alpha.10 → 0.1.0-alpha.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -86,7 +86,7 @@ toolcapsule import --name feishu --target claude
86
86
  toolcapsule tools feishu --brief
87
87
  toolcapsule schema feishu create-doc
88
88
  toolcapsule call feishu create-doc @args.json --save-run
89
- toolcapsule retry runs/2026-06-06T10-00-00-000Z
89
+ toolcapsule retry .toolcapsule/runs/feishu/2026-06-06T10-00-00-000Z
90
90
  ```
91
91
 
92
92
  Short alias:
@@ -103,7 +103,10 @@ tcap call feishu create-doc @args.json --save-run
103
103
  SKILL.md # lightweight Agent Skill entrypoint
104
104
  toolcapsule.config.json # MCP transport/profile config
105
105
  scripts/README.md
106
- runs/ # auditable tool call records
106
+
107
+ .toolcapsule/
108
+ profiles/feishu.json # local MCP profile
109
+ runs/feishu/ # auditable tool call records
107
110
  ```
108
111
 
109
112
  This lets your agent discover the Skill instead of carrying the full MCP schema in every turn.
@@ -130,7 +133,7 @@ toolcapsule call feishu create-doc @args.json --save-run
130
133
  # 2. Patch args.json or content.md
131
134
 
132
135
  # 3. Retry deterministically
133
- toolcapsule retry runs/2026-06-06T10-00-00-000Z
136
+ toolcapsule retry .toolcapsule/runs/feishu/2026-06-06T10-00-00-000Z
134
137
  ```
135
138
 
136
139
  This is especially useful for MCP tools that create documents, tickets, pages, dashboards, reports, or batch operations.
package/dist/cli.js CHANGED
@@ -140,6 +140,22 @@ async function writeJson(path, value) {
140
140
  await writeFile(path, `${JSON.stringify(value, null, 2)}
141
141
  `);
142
142
  }
143
+ async function ensureToolCapsuleIgnored() {
144
+ const gitignorePath = ".gitignore";
145
+ const entry = ".toolcapsule/";
146
+ let content = "";
147
+ try {
148
+ content = await readFile(gitignorePath, "utf8");
149
+ } catch (error) {
150
+ if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) throw error;
151
+ }
152
+ const lines = content.split(/\r?\n/).map((line) => line.trim());
153
+ const alreadyIgnored = lines.some((line) => line === entry || line === `/${entry}` || line === ".toolcapsule");
154
+ if (alreadyIgnored) return;
155
+ const prefix = content.length > 0 && !content.endsWith("\n") ? "\n" : "";
156
+ await writeFile(gitignorePath, `${content}${prefix}${entry}
157
+ `);
158
+ }
143
159
 
144
160
  // src/mcp/importer.ts
145
161
  var workspaceSources = [
@@ -365,7 +381,7 @@ This skill wraps an MCP server as a lightweight, lazy-loaded, file-first workflo
365
381
  toolcapsule tools {{profileName}} --brief
366
382
  toolcapsule describe {{profileName}} <tool>
367
383
  toolcapsule call {{profileName}} <tool> @args.json
368
- toolcapsule retry <run-dir>
384
+ toolcapsule retry .toolcapsule/runs/{{profileName}}/<run-id>
369
385
  \`\`\`
370
386
 
371
387
  ## Workflow
@@ -386,7 +402,6 @@ toolcapsule retry <run-dir>
386
402
  async function generateSkillAt(profile, outputDir) {
387
403
  const skillName = profile.skill?.name || `${profile.name}-mcp`;
388
404
  await mkdir2(join3(outputDir, "scripts"), { recursive: true });
389
- await mkdir2(join3(outputDir, "runs"), { recursive: true });
390
405
  const template = Handlebars.compile(skillTemplate);
391
406
  const description = profile.skill?.description || `Use when operating tools from the ${profile.name} MCP server. Lazy-load schemas, call tools through local files, and retry failed calls by patching artifacts.`;
392
407
  const markdown = template({
@@ -471,7 +486,7 @@ tcap call <name> <tool> @args.json --save-run
471
486
  6. If the call fails, patch the local file and retry:
472
487
 
473
488
  \`\`\`bash
474
- tcap retry runs/<run-id>
489
+ tcap retry .toolcapsule/runs/<name>/<run-id>
475
490
  \`\`\`
476
491
 
477
492
  ## Safety
@@ -563,9 +578,13 @@ function readSkillTarget(raw) {
563
578
  if (["copilot", "claude", "opencode", "agents", "all"].includes(target)) return target;
564
579
  throw new Error("Invalid --target. Use one of: copilot, claude, opencode, agents, all");
565
580
  }
581
+ function runBaseDir(profileName) {
582
+ return join6(".toolcapsule", "runs", profileName);
583
+ }
566
584
  cli.command("init <name>", "Create a profile and generated Agent Skill for an MCP server").option("--url <url>", "Remote MCP URL").option("--command <command>", "stdio MCP command").option("--arg <arg>", "stdio MCP argument, repeatable", { type: [String] }).option("--output <dir>", "Skill output directory").option("--target <target>", "Skill target: copilot, claude, opencode, agents, all", { default: defaultSkillTarget }).action(async (name, options) => {
567
585
  if (!options.url && !options.command) throw new Error("Provide --url for remote MCP or --command for stdio MCP");
568
586
  const profile = options.url ? { name, transport: { type: "remote", url: options.url } } : { name, transport: { type: "stdio", command: options.command, args: options.arg ?? [] } };
587
+ await ensureToolCapsuleIgnored();
569
588
  await writeProfile(join6(".toolcapsule", "profiles", `${name}.json`), profile);
570
589
  const out = await generateSkill(profile, options.output ? { outputDir: options.output } : { target: readSkillTarget(options.target) });
571
590
  console.log(pc.green(`Created profile and skill at ${out}`));
@@ -593,6 +612,7 @@ cli.command("import", "Import existing MCP configuration into ToolCapsule profil
593
612
  throw new Error("Multiple MCP servers found. Re-run with --dry-run, then pass --name <server> or --all.");
594
613
  }
595
614
  for (const server of selected) {
615
+ await ensureToolCapsuleIgnored();
596
616
  await writeProfile(join6(".toolcapsule", "profiles", `${server.profile.name}.json`), server.profile);
597
617
  const out = await generateSkill(server.profile, { target: readSkillTarget(options.target) });
598
618
  console.log(pc.green(`Imported ${server.name} from ${server.source.path} -> ${out}`));
@@ -621,7 +641,7 @@ cli.command("schema <profile> <tool>", "Print a compact schema for one MCP tool"
621
641
  if (!tool) throw new Error(`Tool not found: ${toolName}`);
622
642
  console.log(JSON.stringify(summarizeTool(tool), null, 2));
623
643
  });
624
- cli.command("call <profile> <tool> <args>", "Call an MCP tool with JSON args or @args.json").option("--save-run", "Save request, response, and command under runs/").action(async (profileName, toolName, argsRaw, options) => {
644
+ cli.command("call <profile> <tool> <args>", "Call an MCP tool with JSON args or @args.json").option("--save-run", "Save request, response, and command under .toolcapsule/runs/<profile>/").action(async (profileName, toolName, argsRaw, options) => {
625
645
  const argsPath = readArgsPath(argsRaw);
626
646
  const toolArgs = argsRaw.startsWith("@") ? await readJson(argsPath) : JSON.parse(argsRaw);
627
647
  const profile = await loadProfile(profileName);
@@ -632,10 +652,11 @@ cli.command("call <profile> <tool> <args>", "Call an MCP tool with JSON args or
632
652
  const response = await withClient(profile, (client) => client.callTool(toolName, toolArgs));
633
653
  console.log(JSON.stringify(response, null, 2));
634
654
  if (options.saveRun) {
635
- const dir = await saveRun("runs", {
655
+ await ensureToolCapsuleIgnored();
656
+ const dir = await saveRun(runBaseDir(profile.name), {
636
657
  id: runId,
637
658
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
638
- profile: profileName,
659
+ profile: profile.name,
639
660
  tool: toolName,
640
661
  argsFile: argsPath,
641
662
  status: "success",
@@ -647,10 +668,11 @@ cli.command("call <profile> <tool> <args>", "Call an MCP tool with JSON args or
647
668
  }
648
669
  } catch (error) {
649
670
  if (options.saveRun) {
650
- const dir = await saveRun("runs", {
671
+ await ensureToolCapsuleIgnored();
672
+ const dir = await saveRun(runBaseDir(profile.name), {
651
673
  id: runId,
652
674
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
653
- profile: profileName,
675
+ profile: profile.name,
654
676
  tool: toolName,
655
677
  argsFile: argsPath,
656
678
  status: "error",
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/mcp/client.ts","../src/mcp/importer.ts","../src/utils/fs.ts","../src/profile.ts","../src/schema/brief.ts","../src/schema/summarize.ts","../src/skill/generator.ts","../src/skill/installer.ts","../src/runs/recorder.ts","../src/utils/tokens.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { cac } from \"cac\";\nimport pc from \"picocolors\";\nimport type { ProfileConfig } from \"./types.js\";\nimport { McpClient } from \"./mcp/client.js\";\nimport { discoverMcpServers, selectImportedServers } from \"./mcp/importer.js\";\nimport { loadProfile } from \"./profile.js\";\nimport { briefTools } from \"./schema/brief.js\";\nimport { summarizeTool, summarizeTools } from \"./schema/summarize.js\";\nimport { defaultSkillTarget, generateSkill, type SkillTarget, writeProfile } from \"./skill/generator.js\";\nimport { installAgentSkill } from \"./skill/installer.js\";\nimport { createRunId, loadRun, saveRun } from \"./runs/recorder.js\";\nimport { writeFile } from \"node:fs/promises\";\nimport { readJson } from \"./utils/fs.js\";\nimport { percentReduction, roughTokens } from \"./utils/tokens.js\";\n\nconst cli = cac(\"toolcapsule\");\n\nasync function readPackageVersion(): Promise<string> {\n try {\n const pkg = JSON.parse(await readFile(new URL(\"../package.json\", import.meta.url), \"utf8\")) as { version?: string };\n return pkg.version || \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\nconst packageVersion = await readPackageVersion();\n\nasync function withClient<T>(profile: ProfileConfig, fn: (client: McpClient) => Promise<T>): Promise<T> {\n const client = new McpClient(profile, { clientVersion: packageVersion });\n try {\n await client.init();\n return await fn(client);\n } finally {\n await client.close();\n }\n}\n\nfunction readArgsPath(raw: string): string {\n return raw.startsWith(\"@\") ? raw.slice(1) : raw;\n}\n\nfunction readSkillTarget(raw: string | undefined): SkillTarget {\n const target = raw || defaultSkillTarget;\n if ([\"copilot\", \"claude\", \"opencode\", \"agents\", \"all\"].includes(target)) return target as SkillTarget;\n throw new Error(\"Invalid --target. Use one of: copilot, claude, opencode, agents, all\");\n}\n\ncli\n .command(\"init <name>\", \"Create a profile and generated Agent Skill for an MCP server\")\n .option(\"--url <url>\", \"Remote MCP URL\")\n .option(\"--command <command>\", \"stdio MCP command\")\n .option(\"--arg <arg>\", \"stdio MCP argument, repeatable\", { type: [String] })\n .option(\"--output <dir>\", \"Skill output directory\")\n .option(\"--target <target>\", \"Skill target: copilot, claude, opencode, agents, all\", { default: defaultSkillTarget })\n .action(async (name: string, options: { url?: string; command?: string; arg?: string[]; output?: string; target?: string }) => {\n if (!options.url && !options.command) throw new Error(\"Provide --url for remote MCP or --command for stdio MCP\");\n const profile: ProfileConfig = options.url\n ? { name, transport: { type: \"remote\", url: options.url } }\n : { name, transport: { type: \"stdio\", command: options.command!, args: options.arg ?? [] } };\n await writeProfile(join(\".toolcapsule\", \"profiles\", `${name}.json`), profile);\n const out = await generateSkill(profile, options.output ? { outputDir: options.output } : { target: readSkillTarget(options.target) });\n console.log(pc.green(`Created profile and skill at ${out}`));\n });\n\ncli\n .command(\"install-skill\", \"Install the generic ToolCapsule Agent Skill into this workspace\")\n .option(\"--output <dir>\", \"Skill output directory\")\n .option(\"--target <target>\", \"Skill target: copilot, claude, opencode, agents, all\", { default: defaultSkillTarget })\n .action(async (options: { output?: string; target?: string }) => {\n const out = await installAgentSkill(options.output, readSkillTarget(options.target));\n console.log(pc.green(`Installed ToolCapsule Agent Skill at ${out}`));\n });\n\ncli\n .command(\"import\", \"Import existing MCP configuration into ToolCapsule profiles and skills\")\n .option(\"--include-user\", \"Also inspect user-level MCP config files\")\n .option(\"--name <name>\", \"Import only one MCP server by name\")\n .option(\"--all\", \"Import all discovered MCP servers\")\n .option(\"--target <target>\", \"Skill target: copilot, claude, opencode, agents, all\", { default: defaultSkillTarget })\n .option(\"--dry-run\", \"List importable MCP servers without writing files\")\n .action(\n async (options: { includeUser?: boolean; name?: string; all?: boolean; target?: string; dryRun?: boolean }) => {\n const discovered = await discoverMcpServers(options.includeUser ? { includeUser: true } : {});\n if (discovered.length === 0) {\n console.log(\"No importable MCP servers found.\");\n return;\n }\n\n if (options.dryRun) {\n for (const server of discovered) {\n console.log(`${server.name}\\t${server.source.tool}\\t${server.source.path}`);\n for (const warning of server.warnings) console.log(pc.yellow(` warning: ${warning}`));\n }\n return;\n }\n\n const selected = selectImportedServers(discovered, options.name, options.all);\n if (selected.length === 0) {\n throw new Error(\"Multiple MCP servers found. Re-run with --dry-run, then pass --name <server> or --all.\");\n }\n\n for (const server of selected) {\n await writeProfile(join(\".toolcapsule\", \"profiles\", `${server.profile.name}.json`), server.profile);\n const out = await generateSkill(server.profile, { target: readSkillTarget(options.target) });\n console.log(pc.green(`Imported ${server.name} from ${server.source.path} -> ${out}`));\n for (const warning of server.warnings) console.log(pc.yellow(` warning: ${warning}`));\n }\n },\n );\n\ncli\n .command(\"tools <profile>\", \"List MCP tools\")\n .option(\"--brief\", \"Print compact tool summaries\")\n .option(\"--names\", \"Print tool names only\")\n .option(\"--json\", \"Print raw JSON\")\n .action(async (profileName: string, options: { brief?: boolean; names?: boolean; json?: boolean }) => {\n const profile = await loadProfile(profileName);\n const result = await withClient(profile, (client) => client.listTools());\n if (options.json) console.log(JSON.stringify(result, null, 2));\n else if (options.names) console.log(result.tools.map((tool) => tool.name).join(\"\\n\"));\n else console.log(briefTools(result.tools));\n });\n\ncli\n .command(\"describe <profile> <tool>\", \"Describe one MCP tool\")\n .option(\"--brief\", \"Print summarized schema instead of raw schema\")\n .action(async (profileName: string, toolName: string, options: { brief?: boolean }) => {\n const profile = await loadProfile(profileName);\n const result = await withClient(profile, (client) => client.listTools());\n const tool = result.tools.find((item) => item.name === toolName);\n if (!tool) throw new Error(`Tool not found: ${toolName}`);\n console.log(JSON.stringify(options.brief ? summarizeTool(tool) : tool, null, 2));\n });\n\ncli.command(\"schema <profile> <tool>\", \"Print a compact schema for one MCP tool\").action(async (profileName: string, toolName: string) => {\n const profile = await loadProfile(profileName);\n const result = await withClient(profile, (client) => client.listTools());\n const tool = result.tools.find((item) => item.name === toolName);\n if (!tool) throw new Error(`Tool not found: ${toolName}`);\n console.log(JSON.stringify(summarizeTool(tool), null, 2));\n});\n\ncli\n .command(\"call <profile> <tool> <args>\", \"Call an MCP tool with JSON args or @args.json\")\n .option(\"--save-run\", \"Save request, response, and command under runs/\")\n .action(async (profileName: string, toolName: string, argsRaw: string, options: { saveRun?: boolean }) => {\n const argsPath = readArgsPath(argsRaw);\n const toolArgs = argsRaw.startsWith(\"@\") ? await readJson(argsPath) : JSON.parse(argsRaw);\n const profile = await loadProfile(profileName);\n const request = { name: toolName, arguments: toolArgs };\n const command = `toolcapsule call ${profileName} ${toolName} ${argsRaw}`;\n const runId = createRunId();\n try {\n const response = await withClient(profile, (client) => client.callTool(toolName, toolArgs));\n console.log(JSON.stringify(response, null, 2));\n if (options.saveRun) {\n const dir = await saveRun(\"runs\", {\n id: runId,\n createdAt: new Date().toISOString(),\n profile: profileName,\n tool: toolName,\n argsFile: argsPath,\n status: \"success\",\n command,\n request,\n response,\n });\n console.error(pc.green(`Saved run: ${dir}`));\n }\n } catch (error) {\n if (options.saveRun) {\n const dir = await saveRun(\"runs\", {\n id: runId,\n createdAt: new Date().toISOString(),\n profile: profileName,\n tool: toolName,\n argsFile: argsPath,\n status: \"error\",\n command,\n request,\n error: error instanceof Error ? error.message : String(error),\n });\n console.error(pc.yellow(`Saved failed run: ${dir}`));\n }\n throw error;\n }\n });\n\ncli.command(\"retry <runDir>\", \"Retry a saved run, re-reading the args file\").action(async (runDir: string) => {\n const run = await loadRun(runDir);\n const toolArgs = await readJson(run.argsFile);\n const profile = await loadProfile(run.profile);\n const response = await withClient(profile, (client) => client.callTool(run.tool, toolArgs));\n console.log(JSON.stringify(response, null, 2));\n});\n\ncli.command(\"summarize <profile>\", \"Summarize all tools into compact JSON\").action(async (profileName: string) => {\n const profile = await loadProfile(profileName);\n const result = await withClient(profile, (client) => client.listTools());\n console.log(JSON.stringify(summarizeTools(result.tools), null, 2));\n});\n\ncli\n .command(\"benchmark <profile>\", \"Estimate schema savings for a profile\")\n .option(\"--markdown\", \"Print a Markdown report\")\n .option(\"--out <file>\", \"Write report to a file\")\n .action(async (profileName: string, options: { markdown?: boolean; out?: string }) => {\n const profile = await loadProfile(profileName);\n const result = await withClient(profile, (client) => client.listTools());\n const nativeTokens = roughTokens(result);\n const brief = summarizeTools(result.tools);\n const briefTokens = roughTokens(brief);\n const summary = {\n profile: profileName,\n tools: result.tools.length,\n nativeToolsRoughTokens: nativeTokens,\n summarizedToolsRoughTokens: briefTokens,\n estimatedReductionPct: Number(percentReduction(nativeTokens, briefTokens).toFixed(2)),\n };\n const output = options.markdown\n ? `# ToolCapsule benchmark: ${profileName}\\n\\n| Metric | Value |\\n|---|---:|\\n| MCP tools | ${summary.tools} |\\n| Native MCP schema rough tokens | ${summary.nativeToolsRoughTokens} |\\n| ToolCapsule summary rough tokens | ${summary.summarizedToolsRoughTokens} |\\n| Estimated reduction | ${summary.estimatedReductionPct}% |\\n\\n> Rough tokens are estimated from serialized schema length. Use this report to compare schema footprint before and after capsule summaries.\\n`\n : JSON.stringify(summary, null, 2);\n if (options.out) await writeFile(options.out, output);\n console.log(output);\n});\n\ncli.command(\"render-readme\", \"Print website hero copy snippets\").action(async () => {\n console.log(await readFile(new URL(\"../docs/hero-copy.md\", import.meta.url), \"utf8\"));\n});\n\ncli.help();\ncli.version(packageVersion);\n\ntry {\n cli.parse();\n} catch (error) {\n console.error(pc.red(error instanceof Error ? error.message : String(error)));\n process.exit(1);\n}\n","import { spawn, type ChildProcessWithoutNullStreams } from \"node:child_process\";\nimport { once } from \"node:events\";\nimport { resolve } from \"node:path\";\nimport type { JsonRpcMessage, ProfileConfig, ToolsListResult } from \"../types.js\";\n\nexport type McpClientOptions = {\n timeoutMs?: number;\n debug?: boolean;\n clientVersion?: string;\n};\n\nexport class McpClient {\n private child: ChildProcessWithoutNullStreams;\n private nextId = 1;\n private buffer = \"\";\n private pending = new Map<\n number,\n { resolve: (value: JsonRpcMessage) => void; reject: (error: Error) => void }\n >();\n private timeoutMs: number;\n private debug: boolean;\n private clientVersion: string;\n\n constructor(profile: ProfileConfig, opts: McpClientOptions = {}) {\n this.timeoutMs = opts.timeoutMs ?? Number(process.env.TOOLCAPSULE_TIMEOUT_MS || \"45000\");\n this.debug = opts.debug ?? process.env.TOOLCAPSULE_DEBUG === \"1\";\n this.clientVersion = opts.clientVersion ?? \"0.0.0\";\n if (profile.transport.type === \"remote\") {\n this.child = spawn(\"npx\", [\"-y\", \"mcp-remote\", profile.transport.url, ...headersToArgs(profile.transport.headers)], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env: { ...process.env, ...profile.transport.env },\n });\n } else {\n this.child = spawn(profile.transport.command, profile.transport.args ?? [], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env: { ...process.env, ...profile.transport.env },\n cwd: profile.transport.cwd ? resolve(profile.transport.cwd) : undefined,\n });\n }\n this.child.stdout.setEncoding(\"utf8\");\n this.child.stdout.on(\"data\", (chunk: string) => this.onStdout(chunk));\n this.child.stderr.on(\"data\", (chunk: Buffer) => this.onStderr(chunk));\n this.child.on(\"exit\", (code, signal) => {\n const error = new Error(`MCP process exited early (code=${code}, signal=${signal})`);\n for (const waiter of this.pending.values()) waiter.reject(error);\n this.pending.clear();\n });\n }\n\n private onStderr(chunk: Buffer): void {\n if (!this.debug) return;\n process.stderr.write(redactSecrets(chunk.toString(\"utf8\")));\n }\n\n private onStdout(chunk: string): void {\n this.buffer += chunk;\n let newlineIndex: number;\n while ((newlineIndex = this.buffer.indexOf(\"\\n\")) >= 0) {\n const line = this.buffer.slice(0, newlineIndex).trim();\n this.buffer = this.buffer.slice(newlineIndex + 1);\n if (!line) continue;\n let message: JsonRpcMessage;\n try {\n message = JSON.parse(line) as JsonRpcMessage;\n } catch {\n process.stderr.write(`${line}\\n`);\n continue;\n }\n if (typeof message.id === \"number\") {\n const waiter = this.pending.get(message.id);\n if (waiter) {\n this.pending.delete(message.id);\n waiter.resolve(message);\n }\n }\n }\n }\n\n async init(): Promise<void> {\n await this.request(\"initialize\", {\n protocolVersion: \"2025-03-26\",\n capabilities: {},\n clientInfo: { name: \"toolcapsule\", version: this.clientVersion },\n });\n this.notify(\"notifications/initialized\", {});\n }\n\n async request(method: string, params?: unknown): Promise<unknown> {\n const id = this.nextId++;\n const responsePromise = new Promise<JsonRpcMessage>((resolve, reject) => {\n this.pending.set(id, { resolve, reject });\n });\n this.child.stdin.write(`${JSON.stringify({ jsonrpc: \"2.0\", id, method, params })}\\n`);\n const response = await this.withTimeout(responsePromise, method);\n if (response.error) throw new Error(`${method} failed: ${JSON.stringify(response.error, null, 2)}`);\n return response.result;\n }\n\n notify(method: string, params?: unknown): void {\n this.child.stdin.write(`${JSON.stringify({ jsonrpc: \"2.0\", method, params })}\\n`);\n }\n\n async listTools(): Promise<ToolsListResult> {\n return (await this.request(\"tools/list\", {})) as ToolsListResult;\n }\n\n async callTool(name: string, args: unknown): Promise<unknown> {\n return await this.request(\"tools/call\", { name, arguments: args });\n }\n\n async close(): Promise<void> {\n if (!this.child.killed) this.child.kill();\n if (this.child.exitCode === null) await Promise.race([once(this.child, \"exit\"), new Promise((resolve) => setTimeout(resolve, 500))]);\n }\n\n private async withTimeout<T>(promise: Promise<T>, label: string): Promise<T> {\n let timer: NodeJS.Timeout | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new Error(`${label} timed out after ${this.timeoutMs}ms`)), this.timeoutMs);\n });\n try {\n return await Promise.race([promise, timeout]);\n } finally {\n if (timer) clearTimeout(timer);\n }\n }\n}\n\nfunction headersToArgs(headers: Record<string, string> | undefined): string[] {\n if (!headers) return [];\n return Object.entries(headers).flatMap(([key, value]) => [\"--header\", `${key}:${value}`]);\n}\n\nfunction redactSecrets(text: string): string {\n return text\n .replace(/https:\\/\\/mcp\\.feishu\\.cn\\/mcp\\/[^\\s\"']+/g, \"https://mcp.feishu.cn/mcp/[redacted]\")\n .replace(/(Bearer\\s+)[A-Za-z0-9._~+/=-]+/gi, \"$1[redacted]\")\n .replace(/(token=)[^\\s&\"']+/gi, \"$1[redacted]\")\n .replace(/(api[_-]?key=)[^\\s&\"']+/gi, \"$1[redacted]\");\n}\n","import { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { ProfileConfig, TransportConfig } from \"../types.js\";\nimport { readJson } from \"../utils/fs.js\";\n\nexport type McpConfigSource = {\n tool: \"vscode\" | \"claude\" | \"opencode\" | \"gemini\" | \"cursor\" | \"generic\";\n path: string;\n userLevel?: boolean;\n};\n\nexport type ImportedMcpServer = {\n name: string;\n source: McpConfigSource;\n profile: ProfileConfig;\n warnings: string[];\n};\n\ntype ServerRecord = Record<string, unknown>;\n\nconst workspaceSources: McpConfigSource[] = [\n { tool: \"vscode\", path: join(\".vscode\", \"mcp.json\") },\n { tool: \"claude\", path: \".mcp.json\" },\n { tool: \"opencode\", path: \"opencode.json\" },\n { tool: \"gemini\", path: join(\".gemini\", \"settings.json\") },\n { tool: \"cursor\", path: join(\".cursor\", \"mcp.json\") },\n];\n\nconst userSources: McpConfigSource[] = [\n { tool: \"claude\", path: join(homedir(), \".claude.json\"), userLevel: true },\n { tool: \"opencode\", path: join(homedir(), \".config\", \"opencode\", \"opencode.json\"), userLevel: true },\n { tool: \"gemini\", path: join(homedir(), \".gemini\", \"settings.json\"), userLevel: true },\n];\n\nfunction asRecord(value: unknown): ServerRecord | undefined {\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as ServerRecord) : undefined;\n}\n\nfunction stringArray(value: unknown): string[] | undefined {\n return Array.isArray(value) && value.every((item) => typeof item === \"string\") ? value : undefined;\n}\n\nfunction stringRecord(value: unknown): Record<string, string> | undefined {\n const record = asRecord(value);\n if (!record) return undefined;\n const entries = Object.entries(record).filter((entry): entry is [string, string] => typeof entry[1] === \"string\");\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n}\n\nfunction cleanName(name: string): string {\n const cleaned = name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .replace(/-{2,}/g, \"-\");\n return cleaned || \"imported-mcp\";\n}\n\nfunction mapServer(name: string, source: McpConfigSource, raw: unknown): ImportedMcpServer | undefined {\n const server = asRecord(raw);\n if (!server) return undefined;\n\n const warnings: string[] = [];\n let transport: TransportConfig | undefined;\n const type = typeof server.type === \"string\" ? server.type : undefined;\n const url = typeof server.url === \"string\" ? server.url : typeof server.httpUrl === \"string\" ? server.httpUrl : undefined;\n const commandValue = server.command;\n const headers = stringRecord(server.headers);\n const env = stringRecord(server.env) ?? stringRecord(server.environment);\n const cwd = typeof server.cwd === \"string\" ? server.cwd : undefined;\n\n if (url && (!type || [\"http\", \"streamable-http\", \"remote\", \"sse\", \"ws\"].includes(type))) {\n transport = { type: \"remote\", url, ...(headers ? { headers } : {}), ...(env ? { env } : {}) };\n if (type === \"sse\" || type === \"ws\") warnings.push(`Imported ${type} server as remote URL; verify transport compatibility.`);\n } else if (typeof commandValue === \"string\") {\n transport = {\n type: \"stdio\",\n command: commandValue,\n args: stringArray(server.args) ?? [],\n ...(env ? { env } : {}),\n ...(cwd ? { cwd } : {}),\n };\n } else if (Array.isArray(commandValue) && commandValue.every((item) => typeof item === \"string\") && commandValue.length > 0) {\n transport = { type: \"stdio\", command: commandValue[0]!, args: commandValue.slice(1), ...(env ? { env } : {}), ...(cwd ? { cwd } : {}) };\n }\n\n if (!transport) return undefined;\n if (server.headers && !headers) warnings.push(\"Headers were present but not copied because they were not string values.\");\n if ((server.env || server.environment) && !env) warnings.push(\"Environment variables were present but not copied because they were not string values.\");\n if (server.includeTools || server.excludeTools) warnings.push(\"Tool include/exclude filters were not copied; use ToolCapsule brief/schema commands to choose tools manually.\");\n\n const profileName = cleanName(name);\n return {\n name: profileName,\n source,\n warnings,\n profile: {\n name: profileName,\n transport,\n },\n };\n}\n\nfunction serverEntries(source: McpConfigSource, config: ServerRecord): Array<[string, unknown]> {\n if (source.tool === \"vscode\" || source.tool === \"cursor\") return Object.entries(asRecord(config.servers) ?? {});\n if (source.tool === \"opencode\") return Object.entries(asRecord(config.mcp) ?? {});\n if (source.tool === \"claude\") {\n const projectEntries = Object.entries(asRecord(config.mcpServers) ?? {});\n const projectConfigs = Object.entries(asRecord(config.projects) ?? {}).flatMap(([, project]) =>\n Object.entries(asRecord(asRecord(project)?.mcpServers) ?? {}),\n );\n return [...projectEntries, ...projectConfigs];\n }\n return Object.entries(asRecord(config.mcpServers) ?? {});\n}\n\nexport async function discoverMcpServers(opts: { includeUser?: boolean } = {}): Promise<ImportedMcpServer[]> {\n const sources = opts.includeUser ? [...workspaceSources, ...userSources] : workspaceSources;\n const discovered: ImportedMcpServer[] = [];\n\n for (const source of sources) {\n if (!existsSync(source.path)) continue;\n const config = asRecord(await readJson(source.path));\n if (!config) continue;\n for (const [name, raw] of serverEntries(source, config)) {\n const imported = mapServer(name, source, raw);\n if (imported) discovered.push(imported);\n }\n }\n\n return discovered;\n}\n\nexport function selectImportedServers(servers: ImportedMcpServer[], name?: string, all?: boolean): ImportedMcpServer[] {\n if (all) return servers;\n if (!name) return servers.length === 1 ? servers : [];\n const normalized = cleanName(name);\n return servers.filter((server) => server.name === normalized || server.name === name);\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\n\nexport async function readJson<T>(path: string): Promise<T> {\n return JSON.parse(await readFile(path, \"utf8\")) as T;\n}\n\nexport async function writeJson(path: string, value: unknown): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, `${JSON.stringify(value, null, 2)}\\n`);\n}\n\nexport async function writeText(path: string, value: string): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, value);\n}\n\nexport function abs(path: string): string {\n return resolve(process.cwd(), path);\n}\n","import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\nimport type { ProfileConfig } from \"./types.js\";\nimport { readJson } from \"./utils/fs.js\";\n\nconst profileSchema = z.object({\n name: z.string().min(1),\n transport: z.union([\n z.object({\n type: z.literal(\"remote\"),\n url: z.string().url(),\n headers: z.record(z.string()).optional(),\n env: z.record(z.string()).optional(),\n }),\n z.object({\n type: z.literal(\"stdio\"),\n command: z.string().min(1),\n args: z.array(z.string()).optional(),\n env: z.record(z.string()).optional(),\n cwd: z.string().optional(),\n }),\n ]),\n skill: z\n .object({\n name: z.string().optional(),\n description: z.string().optional(),\n })\n .optional(),\n shortcuts: z\n .record(\n z.object({\n tool: z.string(),\n description: z.string().optional(),\n args: z.record(z.enum([\"string\", \"file\", \"json\", \"boolean\", \"number\"])).optional(),\n }),\n )\n .optional(),\n});\n\nexport async function loadProfile(profilePathOrName: string): Promise<ProfileConfig> {\n const candidates = [\n profilePathOrName,\n `${profilePathOrName}.json`,\n join(\".toolcapsule\", \"profiles\", `${profilePathOrName}.json`),\n join(\".github\", \"skills\", `${profilePathOrName}-mcp`, \"toolcapsule.config.json\"),\n ];\n const found = candidates.find((path) => existsSync(path));\n if (!found) throw new Error(`Profile not found: ${profilePathOrName}`);\n return profileSchema.parse(await readJson(found)) as ProfileConfig;\n}\n","import type { McpTool } from \"../types.js\";\n\nexport function toolTitle(tool: McpTool): string {\n return tool.annotations?.title || tool.description?.split(/\\n/)[0]?.slice(0, 100) || tool.name;\n}\n\nexport function briefTool(tool: McpTool): string {\n const schema = tool.inputSchema as any;\n const required = Array.isArray(schema?.required) ? schema.required : [];\n const properties = schema?.properties && typeof schema.properties === \"object\" ? Object.keys(schema.properties) : [];\n const flags = [\n tool.annotations?.readOnlyHint ? \"read-only\" : undefined,\n tool.annotations?.destructiveHint ? \"destructive\" : undefined,\n ].filter(Boolean);\n return `- ${tool.name}: ${toolTitle(tool)}${flags.length ? ` [${flags.join(\", \")}]` : \"\"}${required.length ? ` required=${required.join(\"|\")}` : \"\"}${properties.length ? ` args=${properties.slice(0, 12).join(\"|\")}` : \"\"}`;\n}\n\nexport function briefTools(tools: McpTool[]): string {\n return tools.map(briefTool).join(\"\\n\");\n}\n","import type { McpTool } from \"../types.js\";\n\nexport function summarizeTool(tool: McpTool): unknown {\n const schema = tool.inputSchema as any;\n const properties = schema?.properties && typeof schema.properties === \"object\" ? schema.properties : {};\n return {\n name: tool.name,\n title: tool.annotations?.title,\n description: tool.description?.split(/\\n\\n/)[0]?.slice(0, 500),\n annotations: tool.annotations,\n required: Array.isArray(schema?.required) ? schema.required : [],\n arguments: Object.fromEntries(\n Object.entries(properties).map(([key, value]: [string, any]) => [\n key,\n { type: value?.type, enum: value?.enum, description: value?.description?.slice?.(0, 160) },\n ]),\n ),\n };\n}\n\nexport function summarizeTools(tools: McpTool[]): unknown[] {\n return tools.map(summarizeTool);\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport Handlebars from \"handlebars\";\nimport type { ProfileConfig } from \"../types.js\";\nimport { writeJson } from \"../utils/fs.js\";\n\nexport type SkillTarget = \"copilot\" | \"claude\" | \"opencode\" | \"agents\" | \"all\";\n\nexport const defaultSkillTarget: SkillTarget = \"claude\";\n\nexport function skillOutputDir(skillName: string, target: Exclude<SkillTarget, \"all\">): string {\n if (target === \"copilot\") return join(\".github\", \"skills\", skillName);\n if (target === \"claude\") return join(\".claude\", \"skills\", skillName);\n if (target === \"opencode\") return join(\".opencode\", \"skills\", skillName);\n return join(\".agents\", \"skills\", skillName);\n}\n\nexport function expandSkillTargets(target: SkillTarget): Exclude<SkillTarget, \"all\">[] {\n return target === \"all\" ? [\"copilot\", \"claude\", \"opencode\", \"agents\"] : [target];\n}\n\nconst skillTemplate = `---\nname: {{skillName}}\ndescription: '{{description}}'\nargument-hint: 'MCP task, tool name, or args file to run'\n---\n\n# {{title}}\n\nThis skill wraps an MCP server as a lightweight, lazy-loaded, file-first workflow.\n\n## Why use this skill\n\n- Keep full MCP tool schemas out of the model context until needed.\n- Use brief tool summaries for everyday work.\n- Store large payloads in local files such as \\`args.json\\` or \\`content.md\\`.\n- Patch local artifacts and retry failed calls deterministically.\n\n## Commands\n\n\\`\\`\\`bash\ntoolcapsule tools {{profileName}} --brief\ntoolcapsule describe {{profileName}} <tool>\ntoolcapsule call {{profileName}} <tool> @args.json\ntoolcapsule retry <run-dir>\n\\`\\`\\`\n\n## Workflow\n\n1. Use \\`tools --brief\\` to find the likely tool.\n2. Use \\`describe <tool>\\` only when the brief schema is insufficient.\n3. Put complex arguments in a local JSON file.\n4. Call with \\`@args.json\\` and save the run.\n5. On failure, patch the local file and run \\`retry\\`.\n\n## Safety\n\n- Do not fabricate IDs, URLs, user IDs, or opaque tokens.\n- Prefer local files for large payloads.\n- Do not print secrets.\n- Review destructive tools before calling.\n`;\n\nexport type GenerateSkillOptions = {\n outputDir?: string;\n target?: SkillTarget;\n};\n\nasync function generateSkillAt(profile: ProfileConfig, outputDir: string): Promise<string> {\n const skillName = profile.skill?.name || `${profile.name}-mcp`;\n await mkdir(join(outputDir, \"scripts\"), { recursive: true });\n await mkdir(join(outputDir, \"runs\"), { recursive: true });\n\n const template = Handlebars.compile(skillTemplate);\n const description =\n profile.skill?.description ||\n `Use when operating tools from the ${profile.name} MCP server. Lazy-load schemas, call tools through local files, and retry failed calls by patching artifacts.`;\n const markdown = template({\n skillName,\n profileName: profile.name,\n title: `${profile.name} MCP Skill`,\n description: description.replace(/'/g, \"''\"),\n });\n await writeFile(join(outputDir, \"SKILL.md\"), markdown);\n await writeJson(join(outputDir, \"toolcapsule.config.json\"), profile);\n await writeFile(\n join(outputDir, \"scripts\", \"README.md\"),\n `# Scripts\\n\\nThis skill uses the project-level \\`toolcapsule\\` CLI.\\n`,\n );\n return outputDir;\n}\n\nexport async function generateSkill(profile: ProfileConfig, opts: GenerateSkillOptions = {}): Promise<string> {\n const skillName = profile.skill?.name || `${profile.name}-mcp`;\n const target = opts.target || defaultSkillTarget;\n const outputs = opts.outputDir\n ? [await generateSkillAt(profile, opts.outputDir)]\n : await Promise.all(expandSkillTargets(target).map((item) => generateSkillAt(profile, skillOutputDir(skillName, item))));\n return outputs.join(\", \");\n}\n\nexport async function writeProfile(path: string, profile: ProfileConfig): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n await writeJson(path, profile);\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { defaultSkillTarget, expandSkillTargets, skillOutputDir, type SkillTarget } from \"./generator.js\";\n\nconst agentSkill = `---\nname: toolcapsule\ndescription: 'Use when: converting MCP servers into lightweight Agent Skills, installing ToolCapsule, lazy-loading MCP schemas, calling MCP tools through local args files, or using patch-and-retry workflows for heavy MCP tools.'\nargument-hint: 'MCP server URL/command, tool name, args file, or retry task'\n---\n\n# ToolCapsule Agent Skill\n\nUse ToolCapsule when an agent needs to work with heavy MCP servers without carrying every tool schema in the prompt.\n\n## Install\n\nIf \\`toolcapsule\\` or \\`tcap\\` is missing:\n\n\\`\\`\\`bash\nnpm install -g toolcapsule\n\\`\\`\\`\n\n## Core workflow\n\n1. Initialize a profile and generated Skill:\n\n\\`\\`\\`bash\ntcap init <name> --url <remote-mcp-url>\n# or\ntcap init <name> --command <stdio-command> --arg <arg>\n\\`\\`\\`\n\n2. Discover tools briefly:\n\n\\`\\`\\`bash\ntcap tools <name> --brief\n\\`\\`\\`\n\n3. Inspect one tool only when needed:\n\n\\`\\`\\`bash\ntcap schema <name> <tool>\n\\`\\`\\`\n\n4. Put complex arguments in a local JSON file.\n\n5. Call the MCP tool through the local args file:\n\n\\`\\`\\`bash\ntcap call <name> <tool> @args.json --save-run\n\\`\\`\\`\n\n6. If the call fails, patch the local file and retry:\n\n\\`\\`\\`bash\ntcap retry runs/<run-id>\n\\`\\`\\`\n\n## Safety\n\n- Do not print or commit private MCP URLs, tokens, API keys, user IDs, or document IDs.\n- Keep generated profiles and run artifacts local unless reviewed.\n- Use \\`TOOLCAPSULE_DEBUG=1\\` only when debugging; normal transport logs are quiet by default.\n- Prefer \\`--brief\\` and \\`schema\\` before reading full MCP schemas.\n\n## When to use\n\nUse ToolCapsule for MCP servers with:\n\n- many tools;\n- long schemas;\n- large Markdown/JSON payloads;\n- document, ticket, wiki, dashboard, or batch workflows;\n- failures that benefit from patching local artifacts instead of regenerating a full tool call.\n`;\n\nexport async function installAgentSkill(outputDir?: string, target: SkillTarget = defaultSkillTarget): Promise<string> {\n const outputDirs = outputDir ? [outputDir] : expandSkillTargets(target).map((item) => skillOutputDir(\"toolcapsule\", item));\n await Promise.all(\n outputDirs.map(async (dir) => {\n await mkdir(dir, { recursive: true });\n await writeFile(join(dir, \"SKILL.md\"), agentSkill);\n }),\n );\n return outputDirs.join(\", \");\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { RunRecord } from \"../types.js\";\nimport { writeJson } from \"../utils/fs.js\";\n\nexport function createRunId(): string {\n return new Date().toISOString().replace(/[:.]/g, \"-\");\n}\n\nexport async function saveRun(baseDir: string, record: RunRecord): Promise<string> {\n const dir = join(baseDir, record.id);\n await mkdir(dir, { recursive: true });\n await writeJson(join(dir, \"run.json\"), record);\n await writeJson(join(dir, \"request.json\"), record.request);\n if (record.response !== undefined) await writeJson(join(dir, \"response.json\"), record.response);\n if (record.error) await writeFile(join(dir, \"error.txt\"), record.error);\n await writeFile(join(dir, \"command.txt\"), `${record.command}\\n`);\n return dir;\n}\n\nexport async function loadRun(runDir: string): Promise<RunRecord> {\n return JSON.parse(await readFile(join(runDir, \"run.json\"), \"utf8\")) as RunRecord;\n}\n","export function roughTokens(value: unknown): number {\n const text = typeof value === \"string\" ? value : JSON.stringify(value);\n return Math.ceil(text.length / 4);\n}\n\nexport function percentReduction(before: number, after: number): number {\n return before === 0 ? 0 : ((before - after) / before) * 100;\n}\n"],"mappings":"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","names":["readFile","join","resolve","resolve","existsSync","join","join","existsSync","mkdir","writeFile","dirname","join","join","mkdir","writeFile","dirname","mkdir","writeFile","join","mkdir","writeFile","join","mkdir","readFile","writeFile","join","join","mkdir","writeFile","readFile","writeFile","readFile","join","writeFile"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/mcp/client.ts","../src/mcp/importer.ts","../src/utils/fs.ts","../src/profile.ts","../src/schema/brief.ts","../src/schema/summarize.ts","../src/skill/generator.ts","../src/skill/installer.ts","../src/runs/recorder.ts","../src/utils/tokens.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { cac } from \"cac\";\nimport pc from \"picocolors\";\nimport type { ProfileConfig } from \"./types.js\";\nimport { McpClient } from \"./mcp/client.js\";\nimport { discoverMcpServers, selectImportedServers } from \"./mcp/importer.js\";\nimport { loadProfile } from \"./profile.js\";\nimport { briefTools } from \"./schema/brief.js\";\nimport { summarizeTool, summarizeTools } from \"./schema/summarize.js\";\nimport { defaultSkillTarget, generateSkill, type SkillTarget, writeProfile } from \"./skill/generator.js\";\nimport { installAgentSkill } from \"./skill/installer.js\";\nimport { createRunId, loadRun, saveRun } from \"./runs/recorder.js\";\nimport { writeFile } from \"node:fs/promises\";\nimport { ensureToolCapsuleIgnored, readJson } from \"./utils/fs.js\";\nimport { percentReduction, roughTokens } from \"./utils/tokens.js\";\n\nconst cli = cac(\"toolcapsule\");\n\nasync function readPackageVersion(): Promise<string> {\n try {\n const pkg = JSON.parse(await readFile(new URL(\"../package.json\", import.meta.url), \"utf8\")) as { version?: string };\n return pkg.version || \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\nconst packageVersion = await readPackageVersion();\n\nasync function withClient<T>(profile: ProfileConfig, fn: (client: McpClient) => Promise<T>): Promise<T> {\n const client = new McpClient(profile, { clientVersion: packageVersion });\n try {\n await client.init();\n return await fn(client);\n } finally {\n await client.close();\n }\n}\n\nfunction readArgsPath(raw: string): string {\n return raw.startsWith(\"@\") ? raw.slice(1) : raw;\n}\n\nfunction readSkillTarget(raw: string | undefined): SkillTarget {\n const target = raw || defaultSkillTarget;\n if ([\"copilot\", \"claude\", \"opencode\", \"agents\", \"all\"].includes(target)) return target as SkillTarget;\n throw new Error(\"Invalid --target. Use one of: copilot, claude, opencode, agents, all\");\n}\n\nfunction runBaseDir(profileName: string): string {\n return join(\".toolcapsule\", \"runs\", profileName);\n}\n\ncli\n .command(\"init <name>\", \"Create a profile and generated Agent Skill for an MCP server\")\n .option(\"--url <url>\", \"Remote MCP URL\")\n .option(\"--command <command>\", \"stdio MCP command\")\n .option(\"--arg <arg>\", \"stdio MCP argument, repeatable\", { type: [String] })\n .option(\"--output <dir>\", \"Skill output directory\")\n .option(\"--target <target>\", \"Skill target: copilot, claude, opencode, agents, all\", { default: defaultSkillTarget })\n .action(async (name: string, options: { url?: string; command?: string; arg?: string[]; output?: string; target?: string }) => {\n if (!options.url && !options.command) throw new Error(\"Provide --url for remote MCP or --command for stdio MCP\");\n const profile: ProfileConfig = options.url\n ? { name, transport: { type: \"remote\", url: options.url } }\n : { name, transport: { type: \"stdio\", command: options.command!, args: options.arg ?? [] } };\n await ensureToolCapsuleIgnored();\n await writeProfile(join(\".toolcapsule\", \"profiles\", `${name}.json`), profile);\n const out = await generateSkill(profile, options.output ? { outputDir: options.output } : { target: readSkillTarget(options.target) });\n console.log(pc.green(`Created profile and skill at ${out}`));\n });\n\ncli\n .command(\"install-skill\", \"Install the generic ToolCapsule Agent Skill into this workspace\")\n .option(\"--output <dir>\", \"Skill output directory\")\n .option(\"--target <target>\", \"Skill target: copilot, claude, opencode, agents, all\", { default: defaultSkillTarget })\n .action(async (options: { output?: string; target?: string }) => {\n const out = await installAgentSkill(options.output, readSkillTarget(options.target));\n console.log(pc.green(`Installed ToolCapsule Agent Skill at ${out}`));\n });\n\ncli\n .command(\"import\", \"Import existing MCP configuration into ToolCapsule profiles and skills\")\n .option(\"--include-user\", \"Also inspect user-level MCP config files\")\n .option(\"--name <name>\", \"Import only one MCP server by name\")\n .option(\"--all\", \"Import all discovered MCP servers\")\n .option(\"--target <target>\", \"Skill target: copilot, claude, opencode, agents, all\", { default: defaultSkillTarget })\n .option(\"--dry-run\", \"List importable MCP servers without writing files\")\n .action(\n async (options: { includeUser?: boolean; name?: string; all?: boolean; target?: string; dryRun?: boolean }) => {\n const discovered = await discoverMcpServers(options.includeUser ? { includeUser: true } : {});\n if (discovered.length === 0) {\n console.log(\"No importable MCP servers found.\");\n return;\n }\n\n if (options.dryRun) {\n for (const server of discovered) {\n console.log(`${server.name}\\t${server.source.tool}\\t${server.source.path}`);\n for (const warning of server.warnings) console.log(pc.yellow(` warning: ${warning}`));\n }\n return;\n }\n\n const selected = selectImportedServers(discovered, options.name, options.all);\n if (selected.length === 0) {\n throw new Error(\"Multiple MCP servers found. Re-run with --dry-run, then pass --name <server> or --all.\");\n }\n\n for (const server of selected) {\n await ensureToolCapsuleIgnored();\n await writeProfile(join(\".toolcapsule\", \"profiles\", `${server.profile.name}.json`), server.profile);\n const out = await generateSkill(server.profile, { target: readSkillTarget(options.target) });\n console.log(pc.green(`Imported ${server.name} from ${server.source.path} -> ${out}`));\n for (const warning of server.warnings) console.log(pc.yellow(` warning: ${warning}`));\n }\n },\n );\n\ncli\n .command(\"tools <profile>\", \"List MCP tools\")\n .option(\"--brief\", \"Print compact tool summaries\")\n .option(\"--names\", \"Print tool names only\")\n .option(\"--json\", \"Print raw JSON\")\n .action(async (profileName: string, options: { brief?: boolean; names?: boolean; json?: boolean }) => {\n const profile = await loadProfile(profileName);\n const result = await withClient(profile, (client) => client.listTools());\n if (options.json) console.log(JSON.stringify(result, null, 2));\n else if (options.names) console.log(result.tools.map((tool) => tool.name).join(\"\\n\"));\n else console.log(briefTools(result.tools));\n });\n\ncli\n .command(\"describe <profile> <tool>\", \"Describe one MCP tool\")\n .option(\"--brief\", \"Print summarized schema instead of raw schema\")\n .action(async (profileName: string, toolName: string, options: { brief?: boolean }) => {\n const profile = await loadProfile(profileName);\n const result = await withClient(profile, (client) => client.listTools());\n const tool = result.tools.find((item) => item.name === toolName);\n if (!tool) throw new Error(`Tool not found: ${toolName}`);\n console.log(JSON.stringify(options.brief ? summarizeTool(tool) : tool, null, 2));\n });\n\ncli.command(\"schema <profile> <tool>\", \"Print a compact schema for one MCP tool\").action(async (profileName: string, toolName: string) => {\n const profile = await loadProfile(profileName);\n const result = await withClient(profile, (client) => client.listTools());\n const tool = result.tools.find((item) => item.name === toolName);\n if (!tool) throw new Error(`Tool not found: ${toolName}`);\n console.log(JSON.stringify(summarizeTool(tool), null, 2));\n});\n\ncli\n .command(\"call <profile> <tool> <args>\", \"Call an MCP tool with JSON args or @args.json\")\n .option(\"--save-run\", \"Save request, response, and command under .toolcapsule/runs/<profile>/\")\n .action(async (profileName: string, toolName: string, argsRaw: string, options: { saveRun?: boolean }) => {\n const argsPath = readArgsPath(argsRaw);\n const toolArgs = argsRaw.startsWith(\"@\") ? await readJson(argsPath) : JSON.parse(argsRaw);\n const profile = await loadProfile(profileName);\n const request = { name: toolName, arguments: toolArgs };\n const command = `toolcapsule call ${profileName} ${toolName} ${argsRaw}`;\n const runId = createRunId();\n try {\n const response = await withClient(profile, (client) => client.callTool(toolName, toolArgs));\n console.log(JSON.stringify(response, null, 2));\n if (options.saveRun) {\n await ensureToolCapsuleIgnored();\n const dir = await saveRun(runBaseDir(profile.name), {\n id: runId,\n createdAt: new Date().toISOString(),\n profile: profile.name,\n tool: toolName,\n argsFile: argsPath,\n status: \"success\",\n command,\n request,\n response,\n });\n console.error(pc.green(`Saved run: ${dir}`));\n }\n } catch (error) {\n if (options.saveRun) {\n await ensureToolCapsuleIgnored();\n const dir = await saveRun(runBaseDir(profile.name), {\n id: runId,\n createdAt: new Date().toISOString(),\n profile: profile.name,\n tool: toolName,\n argsFile: argsPath,\n status: \"error\",\n command,\n request,\n error: error instanceof Error ? error.message : String(error),\n });\n console.error(pc.yellow(`Saved failed run: ${dir}`));\n }\n throw error;\n }\n });\n\ncli.command(\"retry <runDir>\", \"Retry a saved run, re-reading the args file\").action(async (runDir: string) => {\n const run = await loadRun(runDir);\n const toolArgs = await readJson(run.argsFile);\n const profile = await loadProfile(run.profile);\n const response = await withClient(profile, (client) => client.callTool(run.tool, toolArgs));\n console.log(JSON.stringify(response, null, 2));\n});\n\ncli.command(\"summarize <profile>\", \"Summarize all tools into compact JSON\").action(async (profileName: string) => {\n const profile = await loadProfile(profileName);\n const result = await withClient(profile, (client) => client.listTools());\n console.log(JSON.stringify(summarizeTools(result.tools), null, 2));\n});\n\ncli\n .command(\"benchmark <profile>\", \"Estimate schema savings for a profile\")\n .option(\"--markdown\", \"Print a Markdown report\")\n .option(\"--out <file>\", \"Write report to a file\")\n .action(async (profileName: string, options: { markdown?: boolean; out?: string }) => {\n const profile = await loadProfile(profileName);\n const result = await withClient(profile, (client) => client.listTools());\n const nativeTokens = roughTokens(result);\n const brief = summarizeTools(result.tools);\n const briefTokens = roughTokens(brief);\n const summary = {\n profile: profileName,\n tools: result.tools.length,\n nativeToolsRoughTokens: nativeTokens,\n summarizedToolsRoughTokens: briefTokens,\n estimatedReductionPct: Number(percentReduction(nativeTokens, briefTokens).toFixed(2)),\n };\n const output = options.markdown\n ? `# ToolCapsule benchmark: ${profileName}\\n\\n| Metric | Value |\\n|---|---:|\\n| MCP tools | ${summary.tools} |\\n| Native MCP schema rough tokens | ${summary.nativeToolsRoughTokens} |\\n| ToolCapsule summary rough tokens | ${summary.summarizedToolsRoughTokens} |\\n| Estimated reduction | ${summary.estimatedReductionPct}% |\\n\\n> Rough tokens are estimated from serialized schema length. Use this report to compare schema footprint before and after capsule summaries.\\n`\n : JSON.stringify(summary, null, 2);\n if (options.out) await writeFile(options.out, output);\n console.log(output);\n});\n\ncli.command(\"render-readme\", \"Print website hero copy snippets\").action(async () => {\n console.log(await readFile(new URL(\"../docs/hero-copy.md\", import.meta.url), \"utf8\"));\n});\n\ncli.help();\ncli.version(packageVersion);\n\ntry {\n cli.parse();\n} catch (error) {\n console.error(pc.red(error instanceof Error ? error.message : String(error)));\n process.exit(1);\n}\n","import { spawn, type ChildProcessWithoutNullStreams } from \"node:child_process\";\nimport { once } from \"node:events\";\nimport { resolve } from \"node:path\";\nimport type { JsonRpcMessage, ProfileConfig, ToolsListResult } from \"../types.js\";\n\nexport type McpClientOptions = {\n timeoutMs?: number;\n debug?: boolean;\n clientVersion?: string;\n};\n\nexport class McpClient {\n private child: ChildProcessWithoutNullStreams;\n private nextId = 1;\n private buffer = \"\";\n private pending = new Map<\n number,\n { resolve: (value: JsonRpcMessage) => void; reject: (error: Error) => void }\n >();\n private timeoutMs: number;\n private debug: boolean;\n private clientVersion: string;\n\n constructor(profile: ProfileConfig, opts: McpClientOptions = {}) {\n this.timeoutMs = opts.timeoutMs ?? Number(process.env.TOOLCAPSULE_TIMEOUT_MS || \"45000\");\n this.debug = opts.debug ?? process.env.TOOLCAPSULE_DEBUG === \"1\";\n this.clientVersion = opts.clientVersion ?? \"0.0.0\";\n if (profile.transport.type === \"remote\") {\n this.child = spawn(\"npx\", [\"-y\", \"mcp-remote\", profile.transport.url, ...headersToArgs(profile.transport.headers)], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env: { ...process.env, ...profile.transport.env },\n });\n } else {\n this.child = spawn(profile.transport.command, profile.transport.args ?? [], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env: { ...process.env, ...profile.transport.env },\n cwd: profile.transport.cwd ? resolve(profile.transport.cwd) : undefined,\n });\n }\n this.child.stdout.setEncoding(\"utf8\");\n this.child.stdout.on(\"data\", (chunk: string) => this.onStdout(chunk));\n this.child.stderr.on(\"data\", (chunk: Buffer) => this.onStderr(chunk));\n this.child.on(\"exit\", (code, signal) => {\n const error = new Error(`MCP process exited early (code=${code}, signal=${signal})`);\n for (const waiter of this.pending.values()) waiter.reject(error);\n this.pending.clear();\n });\n }\n\n private onStderr(chunk: Buffer): void {\n if (!this.debug) return;\n process.stderr.write(redactSecrets(chunk.toString(\"utf8\")));\n }\n\n private onStdout(chunk: string): void {\n this.buffer += chunk;\n let newlineIndex: number;\n while ((newlineIndex = this.buffer.indexOf(\"\\n\")) >= 0) {\n const line = this.buffer.slice(0, newlineIndex).trim();\n this.buffer = this.buffer.slice(newlineIndex + 1);\n if (!line) continue;\n let message: JsonRpcMessage;\n try {\n message = JSON.parse(line) as JsonRpcMessage;\n } catch {\n process.stderr.write(`${line}\\n`);\n continue;\n }\n if (typeof message.id === \"number\") {\n const waiter = this.pending.get(message.id);\n if (waiter) {\n this.pending.delete(message.id);\n waiter.resolve(message);\n }\n }\n }\n }\n\n async init(): Promise<void> {\n await this.request(\"initialize\", {\n protocolVersion: \"2025-03-26\",\n capabilities: {},\n clientInfo: { name: \"toolcapsule\", version: this.clientVersion },\n });\n this.notify(\"notifications/initialized\", {});\n }\n\n async request(method: string, params?: unknown): Promise<unknown> {\n const id = this.nextId++;\n const responsePromise = new Promise<JsonRpcMessage>((resolve, reject) => {\n this.pending.set(id, { resolve, reject });\n });\n this.child.stdin.write(`${JSON.stringify({ jsonrpc: \"2.0\", id, method, params })}\\n`);\n const response = await this.withTimeout(responsePromise, method);\n if (response.error) throw new Error(`${method} failed: ${JSON.stringify(response.error, null, 2)}`);\n return response.result;\n }\n\n notify(method: string, params?: unknown): void {\n this.child.stdin.write(`${JSON.stringify({ jsonrpc: \"2.0\", method, params })}\\n`);\n }\n\n async listTools(): Promise<ToolsListResult> {\n return (await this.request(\"tools/list\", {})) as ToolsListResult;\n }\n\n async callTool(name: string, args: unknown): Promise<unknown> {\n return await this.request(\"tools/call\", { name, arguments: args });\n }\n\n async close(): Promise<void> {\n if (!this.child.killed) this.child.kill();\n if (this.child.exitCode === null) await Promise.race([once(this.child, \"exit\"), new Promise((resolve) => setTimeout(resolve, 500))]);\n }\n\n private async withTimeout<T>(promise: Promise<T>, label: string): Promise<T> {\n let timer: NodeJS.Timeout | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new Error(`${label} timed out after ${this.timeoutMs}ms`)), this.timeoutMs);\n });\n try {\n return await Promise.race([promise, timeout]);\n } finally {\n if (timer) clearTimeout(timer);\n }\n }\n}\n\nfunction headersToArgs(headers: Record<string, string> | undefined): string[] {\n if (!headers) return [];\n return Object.entries(headers).flatMap(([key, value]) => [\"--header\", `${key}:${value}`]);\n}\n\nfunction redactSecrets(text: string): string {\n return text\n .replace(/https:\\/\\/mcp\\.feishu\\.cn\\/mcp\\/[^\\s\"']+/g, \"https://mcp.feishu.cn/mcp/[redacted]\")\n .replace(/(Bearer\\s+)[A-Za-z0-9._~+/=-]+/gi, \"$1[redacted]\")\n .replace(/(token=)[^\\s&\"']+/gi, \"$1[redacted]\")\n .replace(/(api[_-]?key=)[^\\s&\"']+/gi, \"$1[redacted]\");\n}\n","import { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { ProfileConfig, TransportConfig } from \"../types.js\";\nimport { readJson } from \"../utils/fs.js\";\n\nexport type McpConfigSource = {\n tool: \"vscode\" | \"claude\" | \"opencode\" | \"gemini\" | \"cursor\" | \"generic\";\n path: string;\n userLevel?: boolean;\n};\n\nexport type ImportedMcpServer = {\n name: string;\n source: McpConfigSource;\n profile: ProfileConfig;\n warnings: string[];\n};\n\ntype ServerRecord = Record<string, unknown>;\n\nconst workspaceSources: McpConfigSource[] = [\n { tool: \"vscode\", path: join(\".vscode\", \"mcp.json\") },\n { tool: \"claude\", path: \".mcp.json\" },\n { tool: \"opencode\", path: \"opencode.json\" },\n { tool: \"gemini\", path: join(\".gemini\", \"settings.json\") },\n { tool: \"cursor\", path: join(\".cursor\", \"mcp.json\") },\n];\n\nconst userSources: McpConfigSource[] = [\n { tool: \"claude\", path: join(homedir(), \".claude.json\"), userLevel: true },\n { tool: \"opencode\", path: join(homedir(), \".config\", \"opencode\", \"opencode.json\"), userLevel: true },\n { tool: \"gemini\", path: join(homedir(), \".gemini\", \"settings.json\"), userLevel: true },\n];\n\nfunction asRecord(value: unknown): ServerRecord | undefined {\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as ServerRecord) : undefined;\n}\n\nfunction stringArray(value: unknown): string[] | undefined {\n return Array.isArray(value) && value.every((item) => typeof item === \"string\") ? value : undefined;\n}\n\nfunction stringRecord(value: unknown): Record<string, string> | undefined {\n const record = asRecord(value);\n if (!record) return undefined;\n const entries = Object.entries(record).filter((entry): entry is [string, string] => typeof entry[1] === \"string\");\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n}\n\nfunction cleanName(name: string): string {\n const cleaned = name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .replace(/-{2,}/g, \"-\");\n return cleaned || \"imported-mcp\";\n}\n\nfunction mapServer(name: string, source: McpConfigSource, raw: unknown): ImportedMcpServer | undefined {\n const server = asRecord(raw);\n if (!server) return undefined;\n\n const warnings: string[] = [];\n let transport: TransportConfig | undefined;\n const type = typeof server.type === \"string\" ? server.type : undefined;\n const url = typeof server.url === \"string\" ? server.url : typeof server.httpUrl === \"string\" ? server.httpUrl : undefined;\n const commandValue = server.command;\n const headers = stringRecord(server.headers);\n const env = stringRecord(server.env) ?? stringRecord(server.environment);\n const cwd = typeof server.cwd === \"string\" ? server.cwd : undefined;\n\n if (url && (!type || [\"http\", \"streamable-http\", \"remote\", \"sse\", \"ws\"].includes(type))) {\n transport = { type: \"remote\", url, ...(headers ? { headers } : {}), ...(env ? { env } : {}) };\n if (type === \"sse\" || type === \"ws\") warnings.push(`Imported ${type} server as remote URL; verify transport compatibility.`);\n } else if (typeof commandValue === \"string\") {\n transport = {\n type: \"stdio\",\n command: commandValue,\n args: stringArray(server.args) ?? [],\n ...(env ? { env } : {}),\n ...(cwd ? { cwd } : {}),\n };\n } else if (Array.isArray(commandValue) && commandValue.every((item) => typeof item === \"string\") && commandValue.length > 0) {\n transport = { type: \"stdio\", command: commandValue[0]!, args: commandValue.slice(1), ...(env ? { env } : {}), ...(cwd ? { cwd } : {}) };\n }\n\n if (!transport) return undefined;\n if (server.headers && !headers) warnings.push(\"Headers were present but not copied because they were not string values.\");\n if ((server.env || server.environment) && !env) warnings.push(\"Environment variables were present but not copied because they were not string values.\");\n if (server.includeTools || server.excludeTools) warnings.push(\"Tool include/exclude filters were not copied; use ToolCapsule brief/schema commands to choose tools manually.\");\n\n const profileName = cleanName(name);\n return {\n name: profileName,\n source,\n warnings,\n profile: {\n name: profileName,\n transport,\n },\n };\n}\n\nfunction serverEntries(source: McpConfigSource, config: ServerRecord): Array<[string, unknown]> {\n if (source.tool === \"vscode\" || source.tool === \"cursor\") return Object.entries(asRecord(config.servers) ?? {});\n if (source.tool === \"opencode\") return Object.entries(asRecord(config.mcp) ?? {});\n if (source.tool === \"claude\") {\n const projectEntries = Object.entries(asRecord(config.mcpServers) ?? {});\n const projectConfigs = Object.entries(asRecord(config.projects) ?? {}).flatMap(([, project]) =>\n Object.entries(asRecord(asRecord(project)?.mcpServers) ?? {}),\n );\n return [...projectEntries, ...projectConfigs];\n }\n return Object.entries(asRecord(config.mcpServers) ?? {});\n}\n\nexport async function discoverMcpServers(opts: { includeUser?: boolean } = {}): Promise<ImportedMcpServer[]> {\n const sources = opts.includeUser ? [...workspaceSources, ...userSources] : workspaceSources;\n const discovered: ImportedMcpServer[] = [];\n\n for (const source of sources) {\n if (!existsSync(source.path)) continue;\n const config = asRecord(await readJson(source.path));\n if (!config) continue;\n for (const [name, raw] of serverEntries(source, config)) {\n const imported = mapServer(name, source, raw);\n if (imported) discovered.push(imported);\n }\n }\n\n return discovered;\n}\n\nexport function selectImportedServers(servers: ImportedMcpServer[], name?: string, all?: boolean): ImportedMcpServer[] {\n if (all) return servers;\n if (!name) return servers.length === 1 ? servers : [];\n const normalized = cleanName(name);\n return servers.filter((server) => server.name === normalized || server.name === name);\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\n\nexport async function readJson<T>(path: string): Promise<T> {\n return JSON.parse(await readFile(path, \"utf8\")) as T;\n}\n\nexport async function writeJson(path: string, value: unknown): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, `${JSON.stringify(value, null, 2)}\\n`);\n}\n\nexport async function writeText(path: string, value: string): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, value);\n}\n\nexport async function ensureToolCapsuleIgnored(): Promise<void> {\n const gitignorePath = \".gitignore\";\n const entry = \".toolcapsule/\";\n let content = \"\";\n try {\n content = await readFile(gitignorePath, \"utf8\");\n } catch (error) {\n if (!(error instanceof Error && \"code\" in error && error.code === \"ENOENT\")) throw error;\n }\n\n const lines = content.split(/\\r?\\n/).map((line) => line.trim());\n const alreadyIgnored = lines.some((line) => line === entry || line === `/${entry}` || line === \".toolcapsule\");\n if (alreadyIgnored) return;\n\n const prefix = content.length > 0 && !content.endsWith(\"\\n\") ? \"\\n\" : \"\";\n await writeFile(gitignorePath, `${content}${prefix}${entry}\\n`);\n}\n\nexport function abs(path: string): string {\n return resolve(process.cwd(), path);\n}\n","import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\nimport type { ProfileConfig } from \"./types.js\";\nimport { readJson } from \"./utils/fs.js\";\n\nconst profileSchema = z.object({\n name: z.string().min(1),\n transport: z.union([\n z.object({\n type: z.literal(\"remote\"),\n url: z.string().url(),\n headers: z.record(z.string()).optional(),\n env: z.record(z.string()).optional(),\n }),\n z.object({\n type: z.literal(\"stdio\"),\n command: z.string().min(1),\n args: z.array(z.string()).optional(),\n env: z.record(z.string()).optional(),\n cwd: z.string().optional(),\n }),\n ]),\n skill: z\n .object({\n name: z.string().optional(),\n description: z.string().optional(),\n })\n .optional(),\n shortcuts: z\n .record(\n z.object({\n tool: z.string(),\n description: z.string().optional(),\n args: z.record(z.enum([\"string\", \"file\", \"json\", \"boolean\", \"number\"])).optional(),\n }),\n )\n .optional(),\n});\n\nexport async function loadProfile(profilePathOrName: string): Promise<ProfileConfig> {\n const candidates = [\n profilePathOrName,\n `${profilePathOrName}.json`,\n join(\".toolcapsule\", \"profiles\", `${profilePathOrName}.json`),\n join(\".github\", \"skills\", `${profilePathOrName}-mcp`, \"toolcapsule.config.json\"),\n ];\n const found = candidates.find((path) => existsSync(path));\n if (!found) throw new Error(`Profile not found: ${profilePathOrName}`);\n return profileSchema.parse(await readJson(found)) as ProfileConfig;\n}\n","import type { McpTool } from \"../types.js\";\n\nexport function toolTitle(tool: McpTool): string {\n return tool.annotations?.title || tool.description?.split(/\\n/)[0]?.slice(0, 100) || tool.name;\n}\n\nexport function briefTool(tool: McpTool): string {\n const schema = tool.inputSchema as any;\n const required = Array.isArray(schema?.required) ? schema.required : [];\n const properties = schema?.properties && typeof schema.properties === \"object\" ? Object.keys(schema.properties) : [];\n const flags = [\n tool.annotations?.readOnlyHint ? \"read-only\" : undefined,\n tool.annotations?.destructiveHint ? \"destructive\" : undefined,\n ].filter(Boolean);\n return `- ${tool.name}: ${toolTitle(tool)}${flags.length ? ` [${flags.join(\", \")}]` : \"\"}${required.length ? ` required=${required.join(\"|\")}` : \"\"}${properties.length ? ` args=${properties.slice(0, 12).join(\"|\")}` : \"\"}`;\n}\n\nexport function briefTools(tools: McpTool[]): string {\n return tools.map(briefTool).join(\"\\n\");\n}\n","import type { McpTool } from \"../types.js\";\n\nexport function summarizeTool(tool: McpTool): unknown {\n const schema = tool.inputSchema as any;\n const properties = schema?.properties && typeof schema.properties === \"object\" ? schema.properties : {};\n return {\n name: tool.name,\n title: tool.annotations?.title,\n description: tool.description?.split(/\\n\\n/)[0]?.slice(0, 500),\n annotations: tool.annotations,\n required: Array.isArray(schema?.required) ? schema.required : [],\n arguments: Object.fromEntries(\n Object.entries(properties).map(([key, value]: [string, any]) => [\n key,\n { type: value?.type, enum: value?.enum, description: value?.description?.slice?.(0, 160) },\n ]),\n ),\n };\n}\n\nexport function summarizeTools(tools: McpTool[]): unknown[] {\n return tools.map(summarizeTool);\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport Handlebars from \"handlebars\";\nimport type { ProfileConfig } from \"../types.js\";\nimport { writeJson } from \"../utils/fs.js\";\n\nexport type SkillTarget = \"copilot\" | \"claude\" | \"opencode\" | \"agents\" | \"all\";\n\nexport const defaultSkillTarget: SkillTarget = \"claude\";\n\nexport function skillOutputDir(skillName: string, target: Exclude<SkillTarget, \"all\">): string {\n if (target === \"copilot\") return join(\".github\", \"skills\", skillName);\n if (target === \"claude\") return join(\".claude\", \"skills\", skillName);\n if (target === \"opencode\") return join(\".opencode\", \"skills\", skillName);\n return join(\".agents\", \"skills\", skillName);\n}\n\nexport function expandSkillTargets(target: SkillTarget): Exclude<SkillTarget, \"all\">[] {\n return target === \"all\" ? [\"copilot\", \"claude\", \"opencode\", \"agents\"] : [target];\n}\n\nconst skillTemplate = `---\nname: {{skillName}}\ndescription: '{{description}}'\nargument-hint: 'MCP task, tool name, or args file to run'\n---\n\n# {{title}}\n\nThis skill wraps an MCP server as a lightweight, lazy-loaded, file-first workflow.\n\n## Why use this skill\n\n- Keep full MCP tool schemas out of the model context until needed.\n- Use brief tool summaries for everyday work.\n- Store large payloads in local files such as \\`args.json\\` or \\`content.md\\`.\n- Patch local artifacts and retry failed calls deterministically.\n\n## Commands\n\n\\`\\`\\`bash\ntoolcapsule tools {{profileName}} --brief\ntoolcapsule describe {{profileName}} <tool>\ntoolcapsule call {{profileName}} <tool> @args.json\ntoolcapsule retry .toolcapsule/runs/{{profileName}}/<run-id>\n\\`\\`\\`\n\n## Workflow\n\n1. Use \\`tools --brief\\` to find the likely tool.\n2. Use \\`describe <tool>\\` only when the brief schema is insufficient.\n3. Put complex arguments in a local JSON file.\n4. Call with \\`@args.json\\` and save the run.\n5. On failure, patch the local file and run \\`retry\\`.\n\n## Safety\n\n- Do not fabricate IDs, URLs, user IDs, or opaque tokens.\n- Prefer local files for large payloads.\n- Do not print secrets.\n- Review destructive tools before calling.\n`;\n\nexport type GenerateSkillOptions = {\n outputDir?: string;\n target?: SkillTarget;\n};\n\nasync function generateSkillAt(profile: ProfileConfig, outputDir: string): Promise<string> {\n const skillName = profile.skill?.name || `${profile.name}-mcp`;\n await mkdir(join(outputDir, \"scripts\"), { recursive: true });\n\n const template = Handlebars.compile(skillTemplate);\n const description =\n profile.skill?.description ||\n `Use when operating tools from the ${profile.name} MCP server. Lazy-load schemas, call tools through local files, and retry failed calls by patching artifacts.`;\n const markdown = template({\n skillName,\n profileName: profile.name,\n title: `${profile.name} MCP Skill`,\n description: description.replace(/'/g, \"''\"),\n });\n await writeFile(join(outputDir, \"SKILL.md\"), markdown);\n await writeJson(join(outputDir, \"toolcapsule.config.json\"), profile);\n await writeFile(\n join(outputDir, \"scripts\", \"README.md\"),\n `# Scripts\\n\\nThis skill uses the project-level \\`toolcapsule\\` CLI.\\n`,\n );\n return outputDir;\n}\n\nexport async function generateSkill(profile: ProfileConfig, opts: GenerateSkillOptions = {}): Promise<string> {\n const skillName = profile.skill?.name || `${profile.name}-mcp`;\n const target = opts.target || defaultSkillTarget;\n const outputs = opts.outputDir\n ? [await generateSkillAt(profile, opts.outputDir)]\n : await Promise.all(expandSkillTargets(target).map((item) => generateSkillAt(profile, skillOutputDir(skillName, item))));\n return outputs.join(\", \");\n}\n\nexport async function writeProfile(path: string, profile: ProfileConfig): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n await writeJson(path, profile);\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { defaultSkillTarget, expandSkillTargets, skillOutputDir, type SkillTarget } from \"./generator.js\";\n\nconst agentSkill = `---\nname: toolcapsule\ndescription: 'Use when: converting MCP servers into lightweight Agent Skills, installing ToolCapsule, lazy-loading MCP schemas, calling MCP tools through local args files, or using patch-and-retry workflows for heavy MCP tools.'\nargument-hint: 'MCP server URL/command, tool name, args file, or retry task'\n---\n\n# ToolCapsule Agent Skill\n\nUse ToolCapsule when an agent needs to work with heavy MCP servers without carrying every tool schema in the prompt.\n\n## Install\n\nIf \\`toolcapsule\\` or \\`tcap\\` is missing:\n\n\\`\\`\\`bash\nnpm install -g toolcapsule\n\\`\\`\\`\n\n## Core workflow\n\n1. Initialize a profile and generated Skill:\n\n\\`\\`\\`bash\ntcap init <name> --url <remote-mcp-url>\n# or\ntcap init <name> --command <stdio-command> --arg <arg>\n\\`\\`\\`\n\n2. Discover tools briefly:\n\n\\`\\`\\`bash\ntcap tools <name> --brief\n\\`\\`\\`\n\n3. Inspect one tool only when needed:\n\n\\`\\`\\`bash\ntcap schema <name> <tool>\n\\`\\`\\`\n\n4. Put complex arguments in a local JSON file.\n\n5. Call the MCP tool through the local args file:\n\n\\`\\`\\`bash\ntcap call <name> <tool> @args.json --save-run\n\\`\\`\\`\n\n6. If the call fails, patch the local file and retry:\n\n\\`\\`\\`bash\ntcap retry .toolcapsule/runs/<name>/<run-id>\n\\`\\`\\`\n\n## Safety\n\n- Do not print or commit private MCP URLs, tokens, API keys, user IDs, or document IDs.\n- Keep generated profiles and run artifacts local unless reviewed.\n- Use \\`TOOLCAPSULE_DEBUG=1\\` only when debugging; normal transport logs are quiet by default.\n- Prefer \\`--brief\\` and \\`schema\\` before reading full MCP schemas.\n\n## When to use\n\nUse ToolCapsule for MCP servers with:\n\n- many tools;\n- long schemas;\n- large Markdown/JSON payloads;\n- document, ticket, wiki, dashboard, or batch workflows;\n- failures that benefit from patching local artifacts instead of regenerating a full tool call.\n`;\n\nexport async function installAgentSkill(outputDir?: string, target: SkillTarget = defaultSkillTarget): Promise<string> {\n const outputDirs = outputDir ? [outputDir] : expandSkillTargets(target).map((item) => skillOutputDir(\"toolcapsule\", item));\n await Promise.all(\n outputDirs.map(async (dir) => {\n await mkdir(dir, { recursive: true });\n await writeFile(join(dir, \"SKILL.md\"), agentSkill);\n }),\n );\n return outputDirs.join(\", \");\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { RunRecord } from \"../types.js\";\nimport { writeJson } from \"../utils/fs.js\";\n\nexport function createRunId(): string {\n return new Date().toISOString().replace(/[:.]/g, \"-\");\n}\n\nexport async function saveRun(baseDir: string, record: RunRecord): Promise<string> {\n const dir = join(baseDir, record.id);\n await mkdir(dir, { recursive: true });\n await writeJson(join(dir, \"run.json\"), record);\n await writeJson(join(dir, \"request.json\"), record.request);\n if (record.response !== undefined) await writeJson(join(dir, \"response.json\"), record.response);\n if (record.error) await writeFile(join(dir, \"error.txt\"), record.error);\n await writeFile(join(dir, \"command.txt\"), `${record.command}\\n`);\n return dir;\n}\n\nexport async function loadRun(runDir: string): Promise<RunRecord> {\n return JSON.parse(await readFile(join(runDir, \"run.json\"), \"utf8\")) as RunRecord;\n}\n","export function roughTokens(value: unknown): number {\n const text = typeof value === \"string\" ? value : JSON.stringify(value);\n return Math.ceil(text.length / 4);\n}\n\nexport function percentReduction(before: number, after: number): number {\n return before === 0 ? 0 : ((before - after) / before) * 100;\n}\n"],"mappings":"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","names":["readFile","join","resolve","resolve","existsSync","join","join","existsSync","mkdir","writeFile","dirname","join","join","mkdir","writeFile","dirname","mkdir","writeFile","join","mkdir","writeFile","join","mkdir","readFile","writeFile","join","join","mkdir","writeFile","readFile","writeFile","readFile","join","writeFile"]}
@@ -0,0 +1,368 @@
1
+ # Lazy MCP:我们为什么做 ToolCapsule
2
+
3
+ > 重型 MCP 工具不应该常驻 Prompt。把它们装进 ToolCapsule。
4
+
5
+ MCP 正在成为 AI Agent 连接工具的标准方式。
6
+
7
+ Agent Skills 正在成为封装可复用工作流的标准方式。
8
+
9
+ 但当我们真正把越来越多的 SaaS、文档系统、项目管理系统、内部平台接入 Agent 之后,一个新的问题开始出现:**MCP server 变重了**。
10
+
11
+ 很多 MCP server 不再只是几个轻量函数。它们可能包含大量工具、复杂 schema、很长的工具描述,以及动辄几 KB、几十 KB 的 Markdown 或 JSON payload。对于模型来说,这些内容一旦进入上下文,就会带来直接成本:更多 token、更大的注意力负担、更难调试的失败调用。
12
+
13
+ 我们做 ToolCapsule,就是想探索一种更轻的工作流:
14
+
15
+ - 让 MCP 继续作为工具能力层;
16
+ - 让 Agent Skill 成为面向 Agent 的工作流层;
17
+ - 让大 payload 回到本地文件系统;
18
+ - 让每次工具调用都可记录、可审计、可 patch、可重试。
19
+
20
+ 一句话:**ToolCapsule 是面向重型 MCP 工具的 MCP-to-Skill 工作流层。**
21
+
22
+ ---
23
+
24
+ ## MCP 很强,但重型 MCP 有上下文成本
25
+
26
+ MCP 的价值很清晰:它给 Agent 提供了一种标准方式来发现工具、理解工具 schema,并调用外部系统。
27
+
28
+ 这对于小工具非常自然。例如读取一个文件、查询一个状态、调用一个简单 API,模型看到 schema、直接调用工具,成本不高。
29
+
30
+ 但当 MCP server 连接的是飞书、Notion、Jira、Linear、Confluence、Google Docs、GitHub 管理后台,或者企业内部 SaaS 时,情况会变得不一样。
31
+
32
+ 这些工具往往有几个特点:
33
+
34
+ 1. **工具数量多**:一个 server 可能暴露几十个甚至更多工具。
35
+ 2. **schema 很长**:创建文档、更新页面、批量操作、生成报表时,参数结构经常很复杂。
36
+ 3. **payload 很大**:正文、表格、Markdown、JSON 配置不适合一直放在 prompt 里。
37
+ 4. **调用失败后很难恢复**:一旦参数有一点问题,模型经常需要重新生成整个工具调用。
38
+ 5. **审计依赖宿主环境**:不同 Agent host 对工具调用记录、错误信息、重试方式的支持不一致。
39
+
40
+ 结果就是:MCP 明明是为了让 Agent 更好地使用工具,但重型 MCP 可能反过来开始消耗 Agent 的上下文窗口。
41
+
42
+ 这不是 MCP 的问题,而是工作流层缺了一块。
43
+
44
+ ---
45
+
46
+ ## Prompt 不应该承载整个工具系统
47
+
48
+ 很多 Agent 工作流里,一个隐含假设是:模型应该在上下文里理解完整工具系统,然后直接生成完整工具调用。
49
+
50
+ 这在轻量工具场景中可行。
51
+
52
+ 但对于重型 SaaS / 文档 / 工作流 MCP,这个假设并不总是合理。
53
+
54
+ 例如,让 Agent 创建一篇飞书文档时,真正需要被模型持续关注的,可能只是:
55
+
56
+ - 用户想写什么;
57
+ - 文档的大纲是什么;
58
+ - 应该调用哪个工具;
59
+ - 参数文件在哪里;
60
+ - 如果失败,应该修改哪一部分。
61
+
62
+ 模型不一定需要在每一轮都看到完整的 MCP schema,也不一定需要把整篇 Markdown 正文和所有 JSON 参数都塞进上下文。
63
+
64
+ 更合理的方式是:
65
+
66
+ - schema 按需加载;
67
+ - 大内容放在文件里;
68
+ - 工具参数以 `args.json` 形式存在;
69
+ - 调用结果保存成运行记录;
70
+ - 失败时 patch 文件,然后确定性 retry。
71
+
72
+ 这就是 ToolCapsule 的核心思路。
73
+
74
+ ---
75
+
76
+ ## ToolCapsule 是什么
77
+
78
+ ToolCapsule 可以理解为一个 file-first 的工具调用包。
79
+
80
+ ```text
81
+ capsule = MCP tool + args.json + payload files + run metadata + retry history
82
+ ```
83
+
84
+ 也就是说,ToolCapsule 不试图替代 MCP。MCP 仍然是工具能力的来源。
85
+
86
+ ToolCapsule 做的是把 MCP 工具包装成更适合 Agent 使用的工作流:
87
+
88
+ ```text
89
+ Heavy MCP server
90
+ → MCP-to-Skill workflow layer
91
+ → compact Agent Skill
92
+ → local args/content files
93
+ → auditable tool runs
94
+ → patch-and-retry recovery
95
+ ```
96
+
97
+ 它会为 MCP server 生成轻量的 Agent Skill,让 Agent 通过 Skill 了解什么时候该加载 schema、什么时候该编辑本地文件、什么时候该调用工具、什么时候该重试。
98
+
99
+ 换句话说:
100
+
101
+ - MCP 是能力层;
102
+ - Skill 是工作流层;
103
+ - 本地文件是 payload 层;
104
+ - run directory 是审计和恢复层。
105
+
106
+ 这就是我们说的 **MCP-to-Skill**。
107
+
108
+ ---
109
+
110
+ ## 一个典型工作流
111
+
112
+ 假设你已经有一个飞书 MCP server,希望让 Agent 创建文档。
113
+
114
+ 使用 ToolCapsule,可以这样开始:
115
+
116
+ ```bash
117
+ npm i -g toolcapsule
118
+ ```
119
+
120
+ 初始化一个 MCP profile,并生成对应的 Agent Skill:
121
+
122
+ ```bash
123
+ tcap init feishu --url <remote-mcp-url> --target claude
124
+ ```
125
+
126
+ 或者,如果你已经在 Claude Code、VS Code / GitHub Copilot、OpenCode、Gemini CLI、Cursor 等工具里配置过 MCP,可以直接导入:
127
+
128
+ ```bash
129
+ tcap import --dry-run
130
+ tcap import --name feishu --target claude
131
+ ```
132
+
133
+ 查看工具列表时,只加载简短摘要:
134
+
135
+ ```bash
136
+ tcap tools feishu --brief
137
+ ```
138
+
139
+ 需要某个工具时,再查看具体 schema:
140
+
141
+ ```bash
142
+ tcap schema feishu create-doc
143
+ ```
144
+
145
+ 准备一个本地参数文件:
146
+
147
+ ```bash
148
+ tcap call feishu create-doc @args.json --save-run
149
+ ```
150
+
151
+ 如果调用失败,不需要让模型重新生成整个工具调用。直接修改 `args.json` 或正文文件,然后重试:
152
+
153
+ ```bash
154
+ tcap retry .toolcapsule/runs/feishu/<run-id>
155
+ ```
156
+
157
+ 整个过程的重点是:Agent 不需要一直背着完整 MCP schema 和大 payload 前进。它只需要知道文件在哪里、当前步骤是什么、失败后该 patch 哪个 artifact。
158
+
159
+ ---
160
+
161
+ ## File-first tool calls:让大 payload 回到文件系统
162
+
163
+ ToolCapsule 的一个核心设计是 file-first。
164
+
165
+ 传统工具调用常常把参数和正文直接嵌进一次工具调用里。如果正文很长,或者参数结构很复杂,模型需要在上下文中同时处理用户需求、工具 schema、正文内容和 JSON 参数。
166
+
167
+ ToolCapsule 更倾向于把这些内容拆开:
168
+
169
+ ```text
170
+ args.json # 工具调用参数
171
+ content.md # 大段 Markdown 正文
172
+ .toolcapsule/runs/<profile>/<id>/ # 请求、响应、错误、重试信息
173
+ ```
174
+
175
+ 这样做有几个好处。
176
+
177
+ 第一,**模型上下文更轻**。
178
+
179
+ 模型可以只阅读必要文件,而不是每轮都看到所有内容。
180
+
181
+ 第二,**失败更容易修复**。
182
+
183
+ 如果 API 返回“某个字段格式错误”,Agent 可以直接 patch `args.json` 中对应字段,而不是重新构造完整调用。
184
+
185
+ 第三,**调用可审计**。
186
+
187
+ 每次保存运行记录后,都可以回看当时的 request、response、error 和 retry history。
188
+
189
+ 第四,**工作流更接近真实开发体验**。
190
+
191
+ 开发者调试 API 时,本来就是改文件、跑命令、看错误、再改文件。ToolCapsule 把这个模式带回 Agent 工具调用。
192
+
193
+ ---
194
+
195
+ ## Patch-and-retry:失败不必重新生成整个调用
196
+
197
+ 工具调用失败是常态,尤其是调用复杂 SaaS API 时。
198
+
199
+ 问题不在于失败本身,而在于失败后的恢复方式。
200
+
201
+ 如果一次工具调用包含很长的 JSON 和 Markdown,失败后让模型重新生成全部内容,容易出现几个问题:
202
+
203
+ - 原本正确的字段被改坏;
204
+ - 长正文被意外压缩、改写或丢失;
205
+ - 重试成本高;
206
+ - 失败原因和修复动作混在上下文里,不容易审计。
207
+
208
+ ToolCapsule 的方式是:
209
+
210
+ 1. 第一次调用时保存 run;
211
+ 2. 失败后查看错误;
212
+ 3. 修改本地 `args.json` 或 payload 文件;
213
+ 4. 使用同一个 run 目录重试。
214
+
215
+ ```bash
216
+ tcap call feishu create-doc @args.json --save-run
217
+ # patch args.json or content.md
218
+ tcap retry .toolcapsule/runs/feishu/2026-06-06T10-00-00-000Z
219
+ ```
220
+
221
+ 这个模式的关键是“确定性”。
222
+
223
+ 不是让模型再次凭记忆生成一份新的调用,而是在已有 artifact 上做最小修改。
224
+
225
+ 这对于文档创建、任务批量更新、报表生成、工单同步、页面发布等场景尤其重要。
226
+
227
+ ---
228
+
229
+ ## Native MCP vs ToolCapsule
230
+
231
+ ToolCapsule 不是说 Native MCP 不好。
232
+
233
+ 相反,ToolCapsule 建立在 MCP 之上。我们只是认为,不同工具需要不同工作流。
234
+
235
+ 小型、高频、低 payload 的工具,直接 MCP 调用很自然。
236
+
237
+ 大型、低频、高 payload、复杂 schema 的工具,更适合 ToolCapsule 这种 file-first 和 Skill-guided 的方式。
238
+
239
+ | Concern | Native MCP | ToolCapsule |
240
+ |---|---|---|
241
+ | Tool schemas | Often visible every turn | Loaded on demand |
242
+ | Agent workflow | Direct tool call | Skill-guided workflow |
243
+ | Large payloads | Generated inside tool calls | Stored as files |
244
+ | Failed calls | Regenerate full tool call | Patch local file and retry |
245
+ | Auditability | Host dependent | Run directory with request/response/error |
246
+ | Best for | Small, high-frequency tools | Heavy SaaS/document/workflow MCPs |
247
+
248
+ 这也是为什么我们把 ToolCapsule 定位为 MCP-to-Skill,而不是 MCP replacement。
249
+
250
+ ---
251
+
252
+ ## Benchmark:少 88.4% input tokens
253
+
254
+ 我们在一个飞书 MCP benchmark 中测试了 ToolCapsule 的效果。
255
+
256
+ 结果是:
257
+
258
+ - **88.4% fewer input tokens**;
259
+ - **87.6% fewer total tokens**;
260
+ - planning success rate 保持 **100%**。
261
+
262
+ 这个结果并不意味着所有 MCP server 都会得到完全相同的收益。实际效果会受到 server schema、模型、Agent host、任务类型等因素影响。
263
+
264
+ 但它说明了一个方向:
265
+
266
+ > 对于重型 MCP 工具,把 schema 和 payload 从 prompt 中移出去,是有明显价值的。
267
+
268
+ 这也是 Lazy MCP 的核心。
269
+
270
+ 不是不用 MCP,而是不要让重型 MCP 在每一轮都压在 prompt 里。
271
+
272
+ ---
273
+
274
+ ## ToolCapsule 会生成什么
275
+
276
+ 以飞书 MCP 为例,ToolCapsule 会生成类似这样的结构:
277
+
278
+ ```text
279
+ .claude/skills/feishu-mcp/
280
+ SKILL.md # lightweight Agent Skill entrypoint
281
+ toolcapsule.config.json # MCP transport/profile config
282
+ scripts/README.md
283
+
284
+ .toolcapsule/
285
+ profiles/feishu.json # local MCP profile
286
+ runs/feishu/ # auditable tool call records
287
+ ```
288
+
289
+ `SKILL.md` 是 Agent 看到的轻量入口。
290
+
291
+ `toolcapsule.config.json` 保存 MCP profile 信息。
292
+
293
+ `.toolcapsule/runs/` 保存每次工具调用的记录。
294
+
295
+ 这样的结构让 Agent 不需要直接背完整 MCP server,而是通过 Skill 学会如何按需使用它。
296
+
297
+ ---
298
+
299
+ ## 谁适合试试 ToolCapsule
300
+
301
+ 如果你的 MCP server 符合下面任意几个条件,ToolCapsule 可能会有帮助:
302
+
303
+ - schema-heavy;
304
+ - 文档或工作流导向;
305
+ - 不是每轮都调用,但一调用就很复杂;
306
+ - payload 很大,比如 Markdown、JSON、表格、配置;
307
+ - 失败后不希望模型重新生成整个调用;
308
+ - 希望工具调用有本地记录,方便审计和复现。
309
+
310
+ 典型例子包括:
311
+
312
+ - 飞书 / Lark;
313
+ - Notion;
314
+ - Jira;
315
+ - Linear;
316
+ - Confluence;
317
+ - Google Docs;
318
+ - GitHub 管理工具;
319
+ - 企业内部 SaaS MCP。
320
+
321
+ ToolCapsule 尤其适合那些“不是一直用,但一用就很重”的工具。
322
+
323
+ ---
324
+
325
+ ## 安装和试用
326
+
327
+ ToolCapsule 目前是 early alpha,API 可能在 v1.0 前变化。
328
+
329
+ 如果你愿意尝试,可以这样安装:
330
+
331
+ ```bash
332
+ npm i -g toolcapsule
333
+ ```
334
+
335
+ 常用命令:
336
+
337
+ ```bash
338
+ tcap import --dry-run
339
+ tcap import --name feishu --target claude
340
+ tcap tools feishu --brief
341
+ tcap schema feishu create-doc
342
+ tcap call feishu create-doc @args.json --save-run
343
+ tcap retry .toolcapsule/runs/feishu/<run-id>
344
+ ```
345
+
346
+ `tcap` 是 `toolcapsule` 的短别名。
347
+
348
+ 项目地址:
349
+
350
+ - GitHub: https://github.com/RainSunMe/toolcapsule
351
+ - npm: https://www.npmjs.com/package/toolcapsule
352
+ - Website: https://toolcapsule.studio
353
+
354
+ ---
355
+
356
+ ## 结语
357
+
358
+ MCP 让 Agent 更容易连接外部工具。
359
+
360
+ Agent Skills 让 Agent 更容易复用工作流。
361
+
362
+ ToolCapsule 试图连接这两者:保留 MCP 作为能力层,同时把重型工具变成轻量、按需加载、文件优先、可 patch、可 retry 的 Agent Skill 工作流。
363
+
364
+ 我们相信,随着 MCP server 越来越多、越来越复杂,Agent 不应该在 prompt 里长期背负完整工具系统。
365
+
366
+ 重型 MCP 工具不应该常驻 Prompt。
367
+
368
+ 把它们装进 ToolCapsule。
@@ -121,5 +121,5 @@ tcap call github create-issue @args.json --save-run
121
121
  If the call fails, patch `args.json` and retry:
122
122
 
123
123
  ```bash
124
- tcap retry runs/<run-id>
124
+ tcap retry .toolcapsule/runs/github/<run-id>
125
125
  ```
package/docs/launch.md CHANGED
@@ -61,5 +61,5 @@ Ask a human/function-caller to capture:
61
61
  3. Run `tcap call ... --save-run`.
62
62
  4. Show failure or saved run artifacts.
63
63
  5. Patch `args.json`.
64
- 6. Run `tcap retry runs/<id>`.
64
+ 6. Run `tcap retry .toolcapsule/runs/<profile>/<id>`.
65
65
  7. Show success.
@@ -94,7 +94,7 @@ The demo should show:
94
94
  tcap init feishu --url ...
95
95
  tcap tools feishu --brief
96
96
  tcap call feishu create-doc @create-doc.args.json --save-run
97
- tcap retry runs/...
97
+ tcap retry .toolcapsule/runs/feishu/...
98
98
  ```
99
99
 
100
100
  Goal: a new user should understand MCP-to-Skill → file-first call → patch-and-retry in one example.
@@ -201,7 +201,7 @@ Because ToolCapsule can call tools, store artifacts, and connect to MCP servers,
201
201
 
202
202
  - Do not commit secrets.
203
203
  - Run artifacts may contain sensitive data.
204
- - `/runs/` is ignored by default.
204
+ - `.toolcapsule/` is ignored by default and stores local profiles plus run artifacts.
205
205
  - Generated files should be reviewed before sharing.
206
206
  - Enterprise users should audit local artifacts.
207
207
 
@@ -10,12 +10,12 @@ toolcapsule call feishu create-doc @args.json --save-run
10
10
 
11
11
  If the call fails:
12
12
 
13
- 1. inspect `runs/<id>/error.txt`;
13
+ 1. inspect `.toolcapsule/runs/<profile>/<id>/error.txt`;
14
14
  2. patch `args.json` or the referenced Markdown file;
15
15
  3. retry:
16
16
 
17
17
  ```bash
18
- toolcapsule retry runs/<id>
18
+ toolcapsule retry .toolcapsule/runs/feishu/<id>
19
19
  ```
20
20
 
21
21
  This makes failures reproducible and local.
@@ -51,7 +51,7 @@ docs/assets/saved-run.png
51
51
  Command:
52
52
 
53
53
  ```bash
54
- tcap retry runs/<run-id>
54
+ tcap retry .toolcapsule/runs/feishu/<run-id>
55
55
  ```
56
56
 
57
57
  Placeholder:
@@ -67,5 +67,5 @@ docs/assets/patch-and-retry.gif
67
67
  3. Run `tcap tools <profile> --brief`.
68
68
  4. Run a call with `--save-run`.
69
69
  5. Patch `args.json`.
70
- 6. Run `tcap retry runs/<run-id>`.
70
+ 6. Run `tcap retry .toolcapsule/runs/feishu/<run-id>`.
71
71
  7. End on the generated run directory and the ToolCapsule slogan.
@@ -45,7 +45,7 @@ If the call fails:
45
45
 
46
46
  ```bash
47
47
  # edit examples/feishu/create-doc.args.json or examples/feishu/demo.md
48
- tcap retry runs/<run-id>
48
+ tcap retry .toolcapsule/runs/feishu/<run-id>
49
49
  ```
50
50
 
51
51
  ## Files
@@ -12,7 +12,7 @@ Large Feishu documents often contain Markdown, tables, diagrams, mentions, and o
12
12
  2. Reference it from `create-doc.args.json`.
13
13
  3. Call the MCP tool with `tcap call ... --save-run`.
14
14
  4. If Feishu rejects a block, patch this file.
15
- 5. Run `tcap retry runs/<id>`.
15
+ 5. Run `tcap retry .toolcapsule/runs/feishu/<id>`.
16
16
 
17
17
  ## Checklist
18
18
 
@@ -9,7 +9,7 @@ tcap init mock --command node --arg tests/fixtures/mock-mcp-server.mjs
9
9
  tcap tools mock --brief
10
10
  tcap schema mock create-doc
11
11
  tcap call mock create-doc @examples/generic-stdio/create-doc.args.json --save-run
12
- tcap retry runs/<run-id>
12
+ tcap retry .toolcapsule/runs/mock/<run-id>
13
13
  ```
14
14
 
15
15
  For a real stdio MCP server, replace the command and args:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolcapsule",
3
- "version": "0.1.0-alpha.10",
3
+ "version": "0.1.0-alpha.11",
4
4
  "description": "MCP-to-Skill for lazy-loaded, patchable Agent Skills from heavy MCP tools.",
5
5
  "type": "module",
6
6
  "bin": {