argsbarg 7.0.11 → 7.1.0
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/CHANGELOG.md +19 -1
- package/README.md +3 -2
- package/docs/ai-skills.md +2 -2
- package/docs/cli-program.md +3 -5
- package/docs/developing.md +3 -3
- package/docs/mcp.md +20 -7
- package/docs/output-schema.md +1 -1
- package/examples/full-example/AGENTS.md +20 -12
- package/examples/full-example/README.md +57 -12
- package/examples/full-example/biome.json +5 -4
- package/examples/full-example/bunfig.toml +3 -0
- package/examples/full-example/justfile +22 -27
- package/examples/full-example-json/AGENTS.md +14 -12
- package/examples/full-example-json/README.md +63 -15
- package/examples/full-example-json/biome.json +1 -3
- package/examples/full-example-json/bunfig.toml +3 -0
- package/examples/full-example-json/justfile +22 -27
- package/examples/mcp-plugin/.claude-plugin/plugin.json +11 -0
- package/examples/mcp-plugin/.cursor/hooks/run-tests-on-stop.ts +56 -0
- package/examples/mcp-plugin/.cursor/hooks.json +12 -0
- package/examples/mcp-plugin/.cursor-plugin/plugin.json +12 -0
- package/examples/mcp-plugin/.mcp.json +6 -0
- package/examples/mcp-plugin/AGENTS.md +90 -0
- package/examples/mcp-plugin/CLAUDE.md +1 -0
- package/examples/mcp-plugin/README.md +70 -0
- package/examples/mcp-plugin/biome.json +20 -0
- package/examples/mcp-plugin/bun.lock +48 -0
- package/examples/mcp-plugin/bunfig.toml +3 -0
- package/examples/mcp-plugin/docs/README.md +27 -0
- package/examples/mcp-plugin/docs/cli-schema.json +2085 -0
- package/examples/mcp-plugin/docs/cli.md +2026 -0
- package/examples/mcp-plugin/docs/http.md +92 -0
- package/examples/mcp-plugin/docs/mcp.md +116 -0
- package/examples/mcp-plugin/docs/openapi.json +1243 -0
- package/examples/mcp-plugin/justfile +89 -0
- package/examples/mcp-plugin/mcp.json +8 -0
- package/examples/mcp-plugin/package.json +23 -0
- package/examples/mcp-plugin/scripts/create-identity.ts +12 -0
- package/examples/mcp-plugin/scripts/mcp.mjs +11106 -0
- package/examples/mcp-plugin/scripts/release.ts +225 -0
- package/examples/mcp-plugin/skills/mcp-plugin/SKILL.md +59 -0
- package/examples/mcp-plugin/src/commands/echo/command.ts +26 -0
- package/examples/mcp-plugin/src/commands/render-json/__generated__/RenderJsonInputSchema.json +15 -0
- package/examples/mcp-plugin/src/commands/render-json/__generated__/index.ts +5 -0
- package/examples/mcp-plugin/src/commands/render-json/command.test.ts +46 -0
- package/examples/mcp-plugin/src/commands/render-json/command.ts +30 -0
- package/examples/mcp-plugin/src/commands/render-json/types.ts +9 -0
- package/examples/mcp-plugin/src/commands/status/__generated__/StatusJsonOutputSchema.json +15 -0
- package/examples/mcp-plugin/src/commands/status/__generated__/index.ts +5 -0
- package/examples/mcp-plugin/src/commands/status/command.test.ts +10 -0
- package/examples/mcp-plugin/src/commands/status/command.ts +28 -0
- package/examples/mcp-plugin/src/commands/status/types.ts +6 -0
- package/examples/mcp-plugin/src/commands/workspaces/__generated__/WorkspaceNameInputSchema.json +15 -0
- package/examples/mcp-plugin/src/commands/workspaces/__generated__/index.ts +5 -0
- package/examples/mcp-plugin/src/commands/workspaces/command.test.ts +58 -0
- package/examples/mcp-plugin/src/commands/workspaces/command.ts +94 -0
- package/examples/mcp-plugin/src/commands/workspaces/types.ts +6 -0
- package/examples/mcp-plugin/src/db/index.test.ts +86 -0
- package/examples/mcp-plugin/src/db/index.ts +77 -0
- package/examples/mcp-plugin/src/db/tables/workspaces.ts +58 -0
- package/examples/mcp-plugin/src/index.ts +10 -0
- package/examples/mcp-plugin/src/program.ts +32 -0
- package/examples/mcp-plugin/src/types/argsbarg.d.ts +11 -0
- package/examples/mcp-plugin/src/types/md.d.ts +4 -0
- package/examples/mcp-plugin/tsconfig.json +17 -0
- package/index.d.ts +12 -0
- package/package.json +1 -1
- package/src/builtins/mcp.ts +1 -1
- package/src/cli-tool/create.test.ts +5 -0
- package/src/cli-tool/create.ts +9 -1
- package/src/config/manifest.ts +56 -0
- package/src/config/resolve.test.ts +12 -12
- package/src/configure/configure.test.ts +5 -3
- package/src/core/parse.test.ts +6 -5
- package/src/core/types.ts +12 -0
- package/src/exports/mcp.ts +12 -0
- package/src/mcp/bundle.ts +12 -3
- package/src/mcp/claude.test.ts +2 -7
- package/src/mcp/claude.ts +49 -67
- package/src/mcp/cursor.test.ts +151 -0
- package/src/mcp/cursor.ts +155 -0
- package/src/mcp/hidden-mcpb.test.ts +34 -1
- package/src/mcp/plugin-shared.ts +107 -0
- package/src/mcp/result.ts +5 -1
- package/src/mcp/server.ts +3 -2
- package/src/test/fixtures.ts +13 -0
- package/src/test/integration/mcp.test.ts +8 -7
- package/examples/full-example/scripts/print-identity.ts +0 -28
- package/examples/full-example-json/scripts/print-identity.ts +0 -28
package/src/mcp/result.ts
CHANGED
|
@@ -38,6 +38,7 @@ export interface McpBinaryRespondContent {
|
|
|
38
38
|
export function buildToolCallSuccessFromResponse(response: CliRespondOptions): McpToolCallSuccess {
|
|
39
39
|
const { body, contentType = "application/json; charset=utf-8" } = response;
|
|
40
40
|
let structuredContent: unknown;
|
|
41
|
+
let text = "";
|
|
41
42
|
|
|
42
43
|
if (body instanceof Uint8Array) {
|
|
43
44
|
structuredContent = {
|
|
@@ -45,17 +46,20 @@ export function buildToolCallSuccessFromResponse(response: CliRespondOptions): M
|
|
|
45
46
|
contentType,
|
|
46
47
|
encoding: "base64",
|
|
47
48
|
} satisfies McpBinaryRespondContent;
|
|
49
|
+
text = `[Binary data: ${contentType}, ${body.length} bytes]`;
|
|
48
50
|
} else if (typeof body === "string") {
|
|
49
51
|
structuredContent = {
|
|
50
52
|
content: body,
|
|
51
53
|
contentType,
|
|
52
54
|
} satisfies McpStringRespondContent;
|
|
55
|
+
text = body;
|
|
53
56
|
} else {
|
|
54
57
|
structuredContent = body;
|
|
58
|
+
text = typeof body === "object" && body !== null ? JSON.stringify(body, null, 2) : String(body ?? "");
|
|
55
59
|
}
|
|
56
60
|
|
|
57
61
|
return {
|
|
58
|
-
content: [{ type: "text", text
|
|
62
|
+
content: [{ type: "text", text }],
|
|
59
63
|
structuredContent,
|
|
60
64
|
isError: false,
|
|
61
65
|
};
|
package/src/mcp/server.ts
CHANGED
|
@@ -253,8 +253,9 @@ async function handleRequestLine(cli: Cli, line: string): Promise<void> {
|
|
|
253
253
|
/** Runs the MCP NDJSON read loop on stdin until EOF. */
|
|
254
254
|
export async function mcpServeStdioLoop(cli: Cli): Promise<void> {
|
|
255
255
|
let buffer = "";
|
|
256
|
-
|
|
257
|
-
|
|
256
|
+
const decoder = new TextDecoder();
|
|
257
|
+
for await (const chunk of process.stdin) {
|
|
258
|
+
buffer += typeof chunk === "string" ? chunk : decoder.decode(chunk);
|
|
258
259
|
let nl = buffer.indexOf("\n");
|
|
259
260
|
while (nl !== -1) {
|
|
260
261
|
const line = buffer.slice(0, nl).trim();
|
package/src/test/fixtures.ts
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
import type { CliProgram } from "../core/types.ts";
|
|
2
2
|
import { CliFallbackMode, CliOptionKind } from "../core/types.ts";
|
|
3
|
+
import type { McpToolDef } from "../mcp/tools.ts";
|
|
3
4
|
|
|
4
5
|
export function testProgram(prog: Record<string, unknown> & { key: string; description: string }): CliProgram {
|
|
5
6
|
return { version: "0.0.0", ...prog } as CliProgram;
|
|
6
7
|
}
|
|
7
8
|
|
|
9
|
+
/** MCP tool with `name` from `collectMcpTools`, or throw. */
|
|
10
|
+
export function requireMcpTool(
|
|
11
|
+
/** Tools from `collectMcpTools`. */
|
|
12
|
+
tools: McpToolDef[],
|
|
13
|
+
/** MCP tool name to find. */
|
|
14
|
+
name: string,
|
|
15
|
+
): McpToolDef {
|
|
16
|
+
const tool = tools.find((t) => t.name === name);
|
|
17
|
+
if (!tool) throw new Error(`expected MCP tool ${name}`);
|
|
18
|
+
return tool;
|
|
19
|
+
}
|
|
20
|
+
|
|
8
21
|
export const nestedMcpFixture = testProgram({
|
|
9
22
|
key: "nested.ts",
|
|
10
23
|
description: "Nested groups demo.",
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
mcpToolName,
|
|
17
17
|
sanitizeToolSegment,
|
|
18
18
|
} from "../../mcp/tools.ts";
|
|
19
|
-
import { mcpRequest, nestedMcpFixture, testProgram } from "../fixtures.ts";
|
|
19
|
+
import { mcpRequest, nestedMcpFixture, requireMcpTool, testProgram } from "../fixtures.ts";
|
|
20
20
|
|
|
21
21
|
test("sanitizeToolSegment normalizes dotted app keys", () => {
|
|
22
22
|
expect(sanitizeToolSegment("minimal.ts")).toBe("minimal_ts");
|
|
@@ -39,7 +39,7 @@ test("collectMcpTools lists user leaf commands only", () => {
|
|
|
39
39
|
const tools = collectMcpTools(nestedMcpFixture);
|
|
40
40
|
const names = tools.map((t) => t.name);
|
|
41
41
|
expect(names).toContain("stat_owner_lookup");
|
|
42
|
-
const lookup = tools
|
|
42
|
+
const lookup = requireMcpTool(tools, "stat_owner_lookup");
|
|
43
43
|
expect(lookup.description).toBe("stat owner lookup — Resolve owner info.");
|
|
44
44
|
expect(names).toContain("read");
|
|
45
45
|
expect(names).not.toContain("hidden");
|
|
@@ -155,7 +155,7 @@ test("outputSchema must be a JSON Schema object", () => {
|
|
|
155
155
|
|
|
156
156
|
test("collectMcpTools uses leaf-local options in inputSchema", () => {
|
|
157
157
|
const tools = collectMcpTools(nestedMcpFixture);
|
|
158
|
-
const lookup = tools
|
|
158
|
+
const lookup = requireMcpTool(tools, "stat_owner_lookup");
|
|
159
159
|
const schema = lookup.inputSchema as { properties: Record<string, unknown>; required?: string[] };
|
|
160
160
|
expect(schema.properties.json).toBeUndefined();
|
|
161
161
|
expect(schema.properties["user-name"]).toBeDefined();
|
|
@@ -193,13 +193,13 @@ test("collectMcpTools includes outputSchema when set on leaf", () => {
|
|
|
193
193
|
|
|
194
194
|
test("collectMcpTools omits outputSchema when leaf has none", () => {
|
|
195
195
|
const tools = collectMcpTools(nestedMcpFixture);
|
|
196
|
-
const lookup = tools
|
|
196
|
+
const lookup = requireMcpTool(tools, "stat_owner_lookup");
|
|
197
197
|
expect(lookup.outputSchema).toBeUndefined();
|
|
198
198
|
});
|
|
199
199
|
|
|
200
200
|
test("mcpToolCallToArgv builds nested lookup argv", () => {
|
|
201
201
|
const tools = collectMcpTools(nestedMcpFixture);
|
|
202
|
-
const lookup = tools
|
|
202
|
+
const lookup = requireMcpTool(tools, "stat_owner_lookup");
|
|
203
203
|
const argv = mcpToolCallToArgv(nestedMcpFixture, lookup, {
|
|
204
204
|
"user-name": "alice",
|
|
205
205
|
path: "./x",
|
|
@@ -209,7 +209,7 @@ test("mcpToolCallToArgv builds nested lookup argv", () => {
|
|
|
209
209
|
|
|
210
210
|
test("mcpToolCallToArgv expands varargs positionals", () => {
|
|
211
211
|
const tools = collectMcpTools(nestedMcpFixture);
|
|
212
|
-
const read = tools
|
|
212
|
+
const read = requireMcpTool(tools, "read");
|
|
213
213
|
const argv = mcpToolCallToArgv(nestedMcpFixture, read, { files: ["a", "b"] });
|
|
214
214
|
expect(argv).toEqual(["read", "a", "b"]);
|
|
215
215
|
});
|
|
@@ -318,7 +318,7 @@ test("buildToolCallSuccessFromResponse maps JSON object", () => {
|
|
|
318
318
|
const result = buildToolCallSuccessFromResponse({ body: { a: 1 } });
|
|
319
319
|
expect(result.isError).toBe(false);
|
|
320
320
|
expect(result.structuredContent).toEqual({ a: 1 });
|
|
321
|
-
expect(result.content[0]?.text).toBe(
|
|
321
|
+
expect(result.content[0]?.text).toBe(JSON.stringify({ a: 1 }, null, 2));
|
|
322
322
|
});
|
|
323
323
|
|
|
324
324
|
test("buildToolCallSuccessFromResponse maps string body", () => {
|
|
@@ -330,6 +330,7 @@ test("buildToolCallSuccessFromResponse maps string body", () => {
|
|
|
330
330
|
content: "lookup user=x",
|
|
331
331
|
contentType: "text/plain; charset=utf-8",
|
|
332
332
|
});
|
|
333
|
+
expect(result.content[0]?.text).toBe("lookup user=x");
|
|
333
334
|
});
|
|
334
335
|
|
|
335
336
|
test("buildToolCallSuccessFromResponse maps binary body as base64", () => {
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
/** Print a field from scripts/create-identity.ts for justfile backticks. */
|
|
3
|
-
|
|
4
|
-
import { createIdentity } from "./create-identity.ts";
|
|
5
|
-
|
|
6
|
-
const field = process.argv[2];
|
|
7
|
-
if (!field) {
|
|
8
|
-
console.error("Usage: bun scripts/print-identity.ts <key|className|tap|tapOrg|tapRepo|releaseRepo|envPrefix>");
|
|
9
|
-
process.exit(1);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const [tapOrg, tapRepo] = createIdentity.tap.split("/");
|
|
13
|
-
const values: Record<string, string> = {
|
|
14
|
-
key: createIdentity.key,
|
|
15
|
-
className: createIdentity.className,
|
|
16
|
-
tap: createIdentity.tap,
|
|
17
|
-
tapOrg: tapOrg ?? "",
|
|
18
|
-
tapRepo: tapRepo ?? "",
|
|
19
|
-
envPrefix: createIdentity.envPrefix,
|
|
20
|
-
releaseRepo: createIdentity.releaseRepo,
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const value = values[field];
|
|
24
|
-
if (value === undefined) {
|
|
25
|
-
console.error(`Unknown field: ${field}`);
|
|
26
|
-
process.exit(1);
|
|
27
|
-
}
|
|
28
|
-
process.stdout.write(value);
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
/** Print a field from scripts/create-identity.ts for justfile backticks. */
|
|
3
|
-
|
|
4
|
-
import { createIdentity } from "./create-identity.ts";
|
|
5
|
-
|
|
6
|
-
const field = process.argv[2];
|
|
7
|
-
if (!field) {
|
|
8
|
-
console.error("Usage: bun scripts/print-identity.ts <key|className|tap|tapOrg|tapRepo|releaseRepo|envPrefix>");
|
|
9
|
-
process.exit(1);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const [tapOrg, tapRepo] = createIdentity.tap.split("/");
|
|
13
|
-
const values: Record<string, string> = {
|
|
14
|
-
key: createIdentity.key,
|
|
15
|
-
className: createIdentity.className,
|
|
16
|
-
tap: createIdentity.tap,
|
|
17
|
-
tapOrg: tapOrg ?? "",
|
|
18
|
-
tapRepo: tapRepo ?? "",
|
|
19
|
-
envPrefix: createIdentity.envPrefix,
|
|
20
|
-
releaseRepo: createIdentity.releaseRepo,
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const value = values[field];
|
|
24
|
-
if (value === undefined) {
|
|
25
|
-
console.error(`Unknown field: ${field}`);
|
|
26
|
-
process.exit(1);
|
|
27
|
-
}
|
|
28
|
-
process.stdout.write(value);
|