toolcapsule 0.1.0-alpha.3 → 0.1.0-alpha.4

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
@@ -48,6 +48,7 @@ Instead of making the model hold everything in the prompt, ToolCapsule stores he
48
48
  ```bash
49
49
  npm i -g toolcapsule
50
50
 
51
+ toolcapsule install-skill
51
52
  toolcapsule init feishu --url https://mcp.example.com/mcp/xxx
52
53
  toolcapsule tools feishu --brief
53
54
  toolcapsule schema feishu create-doc
@@ -116,6 +117,7 @@ Results vary by MCP server, model, and host.
116
117
  ```text
117
118
  toolcapsule init <name> --url <remote-mcp-url>
118
119
  toolcapsule init <name> --command <stdio-command> --arg <arg>
120
+ toolcapsule install-skill
119
121
  toolcapsule tools <profile> --brief
120
122
  toolcapsule describe <profile> <tool> --brief
121
123
  toolcapsule schema <profile> <tool>
@@ -151,6 +153,7 @@ Early alpha. APIs may change before v1.0.
151
153
  - [Benchmark methodology](docs/benchmark-methodology.md)
152
154
  - [Releasing](docs/releasing.md)
153
155
  - [Launch notes](docs/launch.md)
156
+ - [Screenshots and recordings](docs/screenshots.md)
154
157
  - [Next steps](docs/next-steps.md)
155
158
  - [Release checklist](docs/release-checklist.md)
156
159
  - [Roadmap](ROADMAP.md)
package/dist/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/cli.ts
4
4
  import { readFile as readFile3 } from "fs/promises";
5
- import { join as join4 } from "path";
5
+ import { join as join5 } from "path";
6
6
  import { cac } from "cac";
7
7
  import pc from "picocolors";
8
8
 
@@ -278,29 +278,109 @@ async function writeProfile(path, profile) {
278
278
  await writeJson(path, profile);
279
279
  }
280
280
 
281
- // src/runs/recorder.ts
282
- import { mkdir as mkdir3, readFile as readFile2, writeFile as writeFile3 } from "fs/promises";
281
+ // src/skill/installer.ts
282
+ import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
283
283
  import { join as join3 } from "path";
284
+ var agentSkill = `---
285
+ name: toolcapsule
286
+ description: '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.'
287
+ argument-hint: 'MCP server URL/command, tool name, args file, or retry task'
288
+ ---
289
+
290
+ # ToolCapsule Agent Skill
291
+
292
+ Use ToolCapsule when an agent needs to work with heavy MCP servers without carrying every tool schema in the prompt.
293
+
294
+ ## Install
295
+
296
+ If \`toolcapsule\` or \`tcap\` is missing:
297
+
298
+ \`\`\`bash
299
+ npm install -g toolcapsule
300
+ \`\`\`
301
+
302
+ ## Core workflow
303
+
304
+ 1. Initialize a profile and generated Skill:
305
+
306
+ \`\`\`bash
307
+ tcap init <name> --url <remote-mcp-url>
308
+ # or
309
+ tcap init <name> --command <stdio-command> --arg <arg>
310
+ \`\`\`
311
+
312
+ 2. Discover tools briefly:
313
+
314
+ \`\`\`bash
315
+ tcap tools <name> --brief
316
+ \`\`\`
317
+
318
+ 3. Inspect one tool only when needed:
319
+
320
+ \`\`\`bash
321
+ tcap schema <name> <tool>
322
+ \`\`\`
323
+
324
+ 4. Put complex arguments in a local JSON file.
325
+
326
+ 5. Call the MCP tool through the local args file:
327
+
328
+ \`\`\`bash
329
+ tcap call <name> <tool> @args.json --save-run
330
+ \`\`\`
331
+
332
+ 6. If the call fails, patch the local file and retry:
333
+
334
+ \`\`\`bash
335
+ tcap retry runs/<run-id>
336
+ \`\`\`
337
+
338
+ ## Safety
339
+
340
+ - Do not print or commit private MCP URLs, tokens, API keys, user IDs, or document IDs.
341
+ - Keep generated profiles and run artifacts local unless reviewed.
342
+ - Use \`TOOLCAPSULE_DEBUG=1\` only when debugging; normal transport logs are quiet by default.
343
+ - Prefer \`--brief\` and \`schema\` before reading full MCP schemas.
344
+
345
+ ## When to use
346
+
347
+ Use ToolCapsule for MCP servers with:
348
+
349
+ - many tools;
350
+ - long schemas;
351
+ - large Markdown/JSON payloads;
352
+ - document, ticket, wiki, dashboard, or batch workflows;
353
+ - failures that benefit from patching local artifacts instead of regenerating a full tool call.
354
+ `;
355
+ async function installAgentSkill(outputDir = ".github/skills/toolcapsule") {
356
+ await mkdir3(outputDir, { recursive: true });
357
+ await writeFile3(join3(outputDir, "SKILL.md"), agentSkill);
358
+ return outputDir;
359
+ }
360
+
361
+ // src/runs/recorder.ts
362
+ import { mkdir as mkdir4, readFile as readFile2, writeFile as writeFile4 } from "fs/promises";
363
+ import { join as join4 } from "path";
284
364
  function createRunId() {
285
365
  return (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
286
366
  }
287
367
  async function saveRun(baseDir, record) {
288
- const dir = join3(baseDir, record.id);
289
- await mkdir3(dir, { recursive: true });
290
- await writeJson(join3(dir, "run.json"), record);
291
- await writeJson(join3(dir, "request.json"), record.request);
292
- if (record.response !== void 0) await writeJson(join3(dir, "response.json"), record.response);
293
- if (record.error) await writeFile3(join3(dir, "error.txt"), record.error);
294
- await writeFile3(join3(dir, "command.txt"), `${record.command}
368
+ const dir = join4(baseDir, record.id);
369
+ await mkdir4(dir, { recursive: true });
370
+ await writeJson(join4(dir, "run.json"), record);
371
+ await writeJson(join4(dir, "request.json"), record.request);
372
+ if (record.response !== void 0) await writeJson(join4(dir, "response.json"), record.response);
373
+ if (record.error) await writeFile4(join4(dir, "error.txt"), record.error);
374
+ await writeFile4(join4(dir, "command.txt"), `${record.command}
295
375
  `);
296
376
  return dir;
297
377
  }
298
378
  async function loadRun(runDir) {
299
- return JSON.parse(await readFile2(join3(runDir, "run.json"), "utf8"));
379
+ return JSON.parse(await readFile2(join4(runDir, "run.json"), "utf8"));
300
380
  }
301
381
 
302
382
  // src/cli.ts
303
- import { writeFile as writeFile4 } from "fs/promises";
383
+ import { writeFile as writeFile5 } from "fs/promises";
304
384
 
305
385
  // src/utils/tokens.ts
306
386
  function roughTokens(value) {
@@ -337,10 +417,14 @@ function readArgsPath(raw) {
337
417
  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").action(async (name, options) => {
338
418
  if (!options.url && !options.command) throw new Error("Provide --url for remote MCP or --command for stdio MCP");
339
419
  const profile = options.url ? { name, transport: { type: "remote", url: options.url } } : { name, transport: { type: "stdio", command: options.command, args: options.arg ?? [] } };
340
- await writeProfile(join4(".toolcapsule", "profiles", `${name}.json`), profile);
420
+ await writeProfile(join5(".toolcapsule", "profiles", `${name}.json`), profile);
341
421
  const out = await generateSkill(profile, options.output ? { outputDir: options.output } : {});
342
422
  console.log(pc.green(`Created profile and skill at ${out}`));
343
423
  });
424
+ cli.command("install-skill", "Install the generic ToolCapsule Agent Skill into this workspace").option("--output <dir>", "Skill output directory", { default: ".github/skills/toolcapsule" }).action(async (options) => {
425
+ const out = await installAgentSkill(options.output);
426
+ console.log(pc.green(`Installed ToolCapsule Agent Skill at ${out}`));
427
+ });
344
428
  cli.command("tools <profile>", "List MCP tools").option("--brief", "Print compact tool summaries").option("--names", "Print tool names only").option("--json", "Print raw JSON").action(async (profileName, options) => {
345
429
  const profile = await loadProfile(profileName);
346
430
  const result = await withClient(profile, (client) => client.listTools());
@@ -440,7 +524,7 @@ cli.command("benchmark <profile>", "Estimate schema savings for a profile").opti
440
524
 
441
525
  > Rough tokens are estimated from serialized schema length. Use this report to compare schema footprint before and after capsule summaries.
442
526
  ` : JSON.stringify(summary, null, 2);
443
- if (options.out) await writeFile4(options.out, output);
527
+ if (options.out) await writeFile5(options.out, output);
444
528
  console.log(output);
445
529
  });
446
530
  cli.command("render-readme", "Print website hero copy snippets").action(async () => {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/mcp/client.ts","../src/profile.ts","../src/utils/fs.ts","../src/schema/brief.ts","../src/schema/summarize.ts","../src/skill/generator.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 { loadProfile } from \"./profile.js\";\nimport { briefTools } from \"./schema/brief.js\";\nimport { summarizeTool, summarizeTools } from \"./schema/summarize.js\";\nimport { generateSkill, writeProfile } from \"./skill/generator.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\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 .action(async (name: string, options: { url?: string; command?: string; arg?: string[]; output?: 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 } : {});\n console.log(pc.green(`Created profile and skill at ${out}`));\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 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], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n } else {\n this.child = spawn(profile.transport.command, profile.transport.args ?? [], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\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 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 { 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({ type: z.literal(\"remote\"), url: z.string().url() }),\n z.object({ type: z.literal(\"stdio\"), command: z.string().min(1), args: z.array(z.string()).optional() }),\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 { 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 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\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};\n\nexport async function generateSkill(profile: ProfileConfig, opts: GenerateSkillOptions = {}): Promise<string> {\n const skillName = profile.skill?.name || `${profile.name}-mcp`;\n const outputDir = opts.outputDir || join(\".github\", \"skills\", skillName);\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 writeProfile(path: string, profile: ProfileConfig): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n await writeJson(path, profile);\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","mkdir","writeFile","dirname","join","join","mkdir","writeFile","dirname","mkdir","readFile","writeFile","join","join","mkdir","writeFile","readFile","writeFile","readFile","join","writeFile"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/mcp/client.ts","../src/profile.ts","../src/utils/fs.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 { loadProfile } from \"./profile.js\";\nimport { briefTools } from \"./schema/brief.js\";\nimport { summarizeTool, summarizeTools } from \"./schema/summarize.js\";\nimport { generateSkill, 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\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 .action(async (name: string, options: { url?: string; command?: string; arg?: string[]; output?: 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 } : {});\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\", { default: \".github/skills/toolcapsule\" })\n .action(async (options: { output: string }) => {\n const out = await installAgentSkill(options.output);\n console.log(pc.green(`Installed ToolCapsule Agent Skill at ${out}`));\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 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], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n } else {\n this.child = spawn(profile.transport.command, profile.transport.args ?? [], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\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 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 { 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({ type: z.literal(\"remote\"), url: z.string().url() }),\n z.object({ type: z.literal(\"stdio\"), command: z.string().min(1), args: z.array(z.string()).optional() }),\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 { 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 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\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};\n\nexport async function generateSkill(profile: ProfileConfig, opts: GenerateSkillOptions = {}): Promise<string> {\n const skillName = profile.skill?.name || `${profile.name}-mcp`;\n const outputDir = opts.outputDir || join(\".github\", \"skills\", skillName);\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 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\";\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 = \".github/skills/toolcapsule\"): Promise<string> {\n await mkdir(outputDir, { recursive: true });\n await writeFile(join(outputDir, \"SKILL.md\"), agentSkill);\n return outputDir;\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","mkdir","writeFile","dirname","join","join","mkdir","writeFile","dirname","mkdir","writeFile","join","mkdir","readFile","writeFile","join","join","mkdir","writeFile","readFile","writeFile","readFile","join","writeFile"]}
@@ -0,0 +1,71 @@
1
+ # Screenshots and recordings
2
+
3
+ Use this document to collect launch assets.
4
+
5
+ ## Required screenshots
6
+
7
+ ### 1. Website hero
8
+
9
+ Source:
10
+
11
+ ```text
12
+ https://toolcapsule.studio
13
+ ```
14
+
15
+ Placeholder:
16
+
17
+ ```text
18
+ docs/assets/website-hero.png
19
+ ```
20
+
21
+ ### 2. Tool discovery
22
+
23
+ Command:
24
+
25
+ ```bash
26
+ tcap tools feishu --brief
27
+ ```
28
+
29
+ Placeholder:
30
+
31
+ ```text
32
+ docs/assets/tcap-tools-brief.png
33
+ ```
34
+
35
+ ### 3. Saved run
36
+
37
+ Command:
38
+
39
+ ```bash
40
+ tcap call feishu create-doc @args.json --save-run
41
+ ```
42
+
43
+ Placeholder:
44
+
45
+ ```text
46
+ docs/assets/saved-run.png
47
+ ```
48
+
49
+ ### 4. Patch and retry
50
+
51
+ Command:
52
+
53
+ ```bash
54
+ tcap retry runs/<run-id>
55
+ ```
56
+
57
+ Placeholder:
58
+
59
+ ```text
60
+ docs/assets/patch-and-retry.gif
61
+ ```
62
+
63
+ ## Recording script
64
+
65
+ 1. Show the website hero.
66
+ 2. Open terminal.
67
+ 3. Run `tcap tools <profile> --brief`.
68
+ 4. Run a call with `--save-run`.
69
+ 5. Patch `args.json`.
70
+ 6. Run `tcap retry runs/<run-id>`.
71
+ 7. End on the generated run directory and the ToolCapsule slogan.
@@ -0,0 +1,21 @@
1
+ # Generic stdio MCP demo
2
+
3
+ This example proves ToolCapsule is not Feishu-specific.
4
+
5
+ It uses the mock MCP server from the test fixtures:
6
+
7
+ ```bash
8
+ tcap init mock --command node --arg tests/fixtures/mock-mcp-server.mjs
9
+ tcap tools mock --brief
10
+ tcap schema mock create-doc
11
+ tcap call mock create-doc @examples/generic-stdio/create-doc.args.json --save-run
12
+ tcap retry runs/<run-id>
13
+ ```
14
+
15
+ For a real stdio MCP server, replace the command and args:
16
+
17
+ ```bash
18
+ tcap init github --command npx --arg -y --arg @modelcontextprotocol/server-github
19
+ ```
20
+
21
+ Do not commit secrets or private MCP configuration.
@@ -0,0 +1,4 @@
1
+ {
2
+ "title": "Generic ToolCapsule demo",
3
+ "markdown": "## Hello\n\nThis call uses a generic stdio MCP profile, not a Feishu-specific integration."
4
+ }
package/llms.txt ADDED
@@ -0,0 +1,79 @@
1
+ # ToolCapsule
2
+
3
+ ToolCapsule turns schema-heavy MCP servers into lightweight, lazy-loaded Agent Skills with file-first calls and patch-and-retry recovery.
4
+
5
+ Use it when an AI agent needs to operate a heavy MCP server without carrying full tool schemas in every prompt.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install -g toolcapsule
11
+ ```
12
+
13
+ Short command:
14
+
15
+ ```bash
16
+ tcap --help
17
+ ```
18
+
19
+ ## Install the Agent Skill
20
+
21
+ Inside a workspace:
22
+
23
+ ```bash
24
+ tcap install-skill
25
+ ```
26
+
27
+ This creates:
28
+
29
+ ```text
30
+ .github/skills/toolcapsule/SKILL.md
31
+ ```
32
+
33
+ ## Convert an MCP server into a Skill workflow
34
+
35
+ Remote MCP:
36
+
37
+ ```bash
38
+ tcap init <name> --url <remote-mcp-url>
39
+ ```
40
+
41
+ stdio MCP:
42
+
43
+ ```bash
44
+ tcap init <name> --command <command> --arg <arg>
45
+ ```
46
+
47
+ ## Discover tools cheaply
48
+
49
+ ```bash
50
+ tcap tools <name> --brief
51
+ ```
52
+
53
+ ## Inspect one tool schema
54
+
55
+ ```bash
56
+ tcap schema <name> <tool>
57
+ ```
58
+
59
+ ## Call a tool with local args
60
+
61
+ ```bash
62
+ tcap call <name> <tool> @args.json --save-run
63
+ ```
64
+
65
+ ## Retry after patching local files
66
+
67
+ ```bash
68
+ tcap retry runs/<run-id>
69
+ ```
70
+
71
+ ## Benchmark schema footprint
72
+
73
+ ```bash
74
+ tcap benchmark <name> --markdown --out toolcapsule-report.md
75
+ ```
76
+
77
+ ## Safety
78
+
79
+ Do not print or commit remote MCP URLs, tokens, API keys, private document IDs, user IDs, or run artifacts. Transport stderr is quiet by default. Use `TOOLCAPSULE_DEBUG=1` only when debugging.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolcapsule",
3
- "version": "0.1.0-alpha.3",
3
+ "version": "0.1.0-alpha.4",
4
4
  "description": "File-first, patchable Agent Skills for heavy MCP tools.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,7 +12,8 @@
12
12
  "README.md",
13
13
  "LICENSE",
14
14
  "docs",
15
- "examples"
15
+ "examples",
16
+ "llms.txt"
16
17
  ],
17
18
  "scripts": {
18
19
  "build": "tsup",