argsbarg 2.1.1 → 3.0.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 +14 -1
- package/README.md +9 -7
- package/docs/install.md +2 -2
- package/docs/mcp.md +18 -13
- package/examples/mcp-test.ts +2 -2
- package/examples/minimal.ts +2 -0
- package/examples/nested.ts +3 -1
- package/examples/option-required.ts +2 -0
- package/index.d.ts +8 -7
- package/package.json +1 -1
- package/src/builtins/builtins.test.ts +8 -3
- package/src/builtins/dispatch.ts +22 -1
- package/src/builtins/export.ts +5 -1
- package/src/builtins/install.ts +2 -1
- package/src/builtins/presentation.ts +5 -1
- package/src/builtins/version.ts +10 -0
- package/src/capabilities.ts +2 -2
- package/src/index.test.ts +182 -122
- package/src/index.ts +0 -0
- package/src/install/index.ts +2 -1
- package/src/install/install.test.ts +2 -1
- package/src/install/paths.ts +2 -2
- package/src/install/plan.ts +3 -2
- package/src/install/uninstall.ts +2 -1
- package/src/invoke.ts +1 -1
- package/src/mcp/tools.ts +21 -24
- package/src/runtime.ts +1 -1
- package/src/skill/generate.ts +3 -3
- package/src/types.test.ts +3 -2
- package/src/types.ts +8 -7
- package/src/validate.ts +13 -3
package/src/index.ts
CHANGED
|
File without changes
|
package/src/install/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { readSync } from "node:fs";
|
|
2
|
+
import { resolveCapabilities } from "../capabilities.ts";
|
|
2
3
|
import { CliProgram } from "../types.ts";
|
|
3
4
|
import { cliSkillInstall } from "../skill/install.ts";
|
|
4
5
|
import { checkMcpConflict, expectedMcpEntry } from "./mcp-config.ts";
|
|
@@ -130,7 +131,7 @@ export async function cliInstall(root: CliProgram, rawOpts: Record<string, strin
|
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
// MCP conflict checks before planning
|
|
133
|
-
if (!opts.uninstall && root.
|
|
134
|
+
if (!opts.uninstall && resolveCapabilities(root).mcp && (opts.all || opts.mcp)) {
|
|
134
135
|
const entry = expectedMcpEntry(root);
|
|
135
136
|
const yes = !!opts.yes;
|
|
136
137
|
for (const p of [paths.cursorMcpPath, paths.claudeMcpPath]) {
|
package/src/install/paths.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { homedir } from "node:os";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { CliProgram } from "../types.ts";
|
|
4
|
-
import { sanitizeToolSegment } from "../mcp/tools.ts";
|
|
4
|
+
import { sanitizeToolSegment, mcpServerId } from "../mcp/tools.ts";
|
|
5
5
|
|
|
6
6
|
export interface InstallPaths {
|
|
7
7
|
bindir: string;
|
|
@@ -63,7 +63,7 @@ export function resolveInstallPaths(root: CliProgram, opts: { prefix?: string })
|
|
|
63
63
|
claudeMcpPath: join(home, ".claude.json"),
|
|
64
64
|
bashRc: join(home, ".bashrc"),
|
|
65
65
|
zshRc: join(home, ".zshrc"),
|
|
66
|
-
mcpName: root
|
|
66
|
+
mcpName: mcpServerId(root),
|
|
67
67
|
skillDirName,
|
|
68
68
|
};
|
|
69
69
|
}
|
package/src/install/plan.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
+
import { resolveCapabilities } from "../capabilities.ts";
|
|
3
4
|
import { CliProgram } from "../types.ts";
|
|
4
5
|
import { installBinary } from "./binary.ts";
|
|
5
6
|
import { installCompletions } from "./completions.ts";
|
|
@@ -46,7 +47,7 @@ function wantsSkill(opts: InstallOpts): boolean {
|
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
function wantsMcp(opts: InstallOpts, root: CliProgram): boolean {
|
|
49
|
-
return !!(opts.
|
|
50
|
+
return !!(opts.mcp || opts.all) && resolveCapabilities(root).mcp;
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
/** Builds install actions for normal mode (--all / scoped targets). */
|
|
@@ -154,7 +155,7 @@ export function buildUpdatePlan(root: CliProgram, paths: InstallPaths, opts: Ins
|
|
|
154
155
|
bin: true,
|
|
155
156
|
completions: detected.bashCompletion || detected.zshCompletion || detected.fishCompletion,
|
|
156
157
|
skill: detected.cursorSkill || detected.claudeSkill,
|
|
157
|
-
mcp: (detected.cursorMcp || detected.claudeMcp) && root.
|
|
158
|
+
mcp: (detected.cursorMcp || detected.claudeMcp) && resolveCapabilities(root).mcp,
|
|
158
159
|
dry: opts.dry,
|
|
159
160
|
};
|
|
160
161
|
const plan = buildInstallPlan(root, paths, scoped);
|
package/src/install/uninstall.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, rmSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
+
import { resolveCapabilities } from "../capabilities.ts";
|
|
3
4
|
import { CliProgram } from "../types.ts";
|
|
4
5
|
import { uninstallBinary } from "./binary.ts";
|
|
5
6
|
import { uninstallCompletions } from "./completions.ts";
|
|
@@ -77,7 +78,7 @@ export function buildUninstallPlan(
|
|
|
77
78
|
});
|
|
78
79
|
}
|
|
79
80
|
|
|
80
|
-
if ((all || opts.mcp) && root.
|
|
81
|
+
if ((all || opts.mcp) && resolveCapabilities(root).mcp) {
|
|
81
82
|
if (detected.cursorMcp) {
|
|
82
83
|
actions.push({
|
|
83
84
|
summary: `cursor mcp: ${paths.cursorMcpPath}`,
|
package/src/invoke.ts
CHANGED
package/src/mcp/tools.ts
CHANGED
|
@@ -3,14 +3,24 @@ This module maps CliProgram leaf nodes to MCP tool definitions and converts
|
|
|
3
3
|
flat JSON tool arguments into argv for cliInvoke.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { readFileSync } from "node:fs";
|
|
7
|
-
import { join } from "node:path";
|
|
8
6
|
import { collectOptionDefs } from "../parse.ts";
|
|
9
7
|
import { cliSchemaJson } from "../schema.ts";
|
|
10
8
|
import { CliProgram, CliLeaf, CliNode, CliOption, CliOptionKind, CliPositional, isCliLeaf, isCliRouter } from "../types.ts";
|
|
11
9
|
|
|
12
|
-
/** Default URI for the CLI schema MCP resource. */
|
|
13
|
-
export
|
|
10
|
+
/** Default URI pattern for the CLI schema MCP resource (`<mcpId>://schema`). */
|
|
11
|
+
export function defaultMcpSchemaUri(mcpId: string): string {
|
|
12
|
+
return `${mcpId}://schema`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Sanitizes a command key segment for MCP tool names and server identity. */
|
|
16
|
+
export function sanitizeToolSegment(key: string): string {
|
|
17
|
+
return key.replace(/[^a-zA-Z0-9]/g, "_");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** MCP server id derived from the program root key (sanitized). */
|
|
21
|
+
export function mcpServerId(root: CliProgram): string {
|
|
22
|
+
return sanitizeToolSegment(root.key);
|
|
23
|
+
}
|
|
14
24
|
|
|
15
25
|
/** One MCP tool derived from a leaf CLI command. */
|
|
16
26
|
export interface McpToolDef {
|
|
@@ -32,11 +42,6 @@ export function mcpToolDescription(path: string[], rootKey: string, description:
|
|
|
32
42
|
return `${prefix} — ${description}`;
|
|
33
43
|
}
|
|
34
44
|
|
|
35
|
-
/** Sanitizes a command key segment for MCP tool names. */
|
|
36
|
-
export function sanitizeToolSegment(key: string): string {
|
|
37
|
-
return key.replace(/[^a-zA-Z0-9]/g, "_");
|
|
38
|
-
}
|
|
39
|
-
|
|
40
45
|
/** Builds the MCP tool name for a leaf at the given path. */
|
|
41
46
|
export function mcpToolName(root: CliProgram, path: string[]): string {
|
|
42
47
|
if (path.length === 0) {
|
|
@@ -150,7 +155,7 @@ export function collectMcpTools(root: CliProgram): McpToolDef[] {
|
|
|
150
155
|
/** Walks the command tree and appends leaf tools. */
|
|
151
156
|
function walk(cmd: CliNode, path: string[]): void {
|
|
152
157
|
if (isCliLeaf(cmd)) {
|
|
153
|
-
if (cmd.key === "completion" || cmd.key === "install" || cmd.key === "mcp") {
|
|
158
|
+
if (cmd.key === "completion" || cmd.key === "install" || cmd.key === "mcp" || cmd.key === "version") {
|
|
154
159
|
return;
|
|
155
160
|
}
|
|
156
161
|
if (cmd.mcpTool?.enabled === false) {
|
|
@@ -181,28 +186,20 @@ export function collectMcpTools(root: CliProgram): McpToolDef[] {
|
|
|
181
186
|
return out;
|
|
182
187
|
}
|
|
183
188
|
|
|
184
|
-
/** Reads package.json version from cwd synchronously. */
|
|
185
|
-
function resolveMcpVersionFromPackageJson(): string | undefined {
|
|
186
|
-
try {
|
|
187
|
-
const text = readFileSync(join(process.cwd(), "package.json"), "utf8");
|
|
188
|
-
const version = (JSON.parse(text) as { version?: string }).version;
|
|
189
|
-
return typeof version === "string" ? version : undefined;
|
|
190
|
-
} catch {
|
|
191
|
-
return undefined;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
189
|
/** Resolves MCP server name and version for initialize. */
|
|
196
190
|
export function resolveMcpServerInfo(root: CliProgram): { name: string; version: string } {
|
|
197
191
|
return {
|
|
198
|
-
name: root
|
|
199
|
-
version: root.
|
|
192
|
+
name: mcpServerId(root),
|
|
193
|
+
version: root.version,
|
|
200
194
|
};
|
|
201
195
|
}
|
|
202
196
|
|
|
203
197
|
/** Resolves the schema resource URI for this app. */
|
|
204
198
|
export function resolveMcpSchemaUri(root: CliProgram): string {
|
|
205
|
-
|
|
199
|
+
if (root.mcpServer?.schemaResourceUri) {
|
|
200
|
+
return root.mcpServer.schemaResourceUri;
|
|
201
|
+
}
|
|
202
|
+
return defaultMcpSchemaUri(mcpServerId(root));
|
|
206
203
|
}
|
|
207
204
|
|
|
208
205
|
/** Converts flat MCP tool arguments to argv for cliInvoke. */
|
package/src/runtime.ts
CHANGED
|
@@ -32,7 +32,7 @@ export async function cliRun(program: CliProgram, argv: string[] = process.argv.
|
|
|
32
32
|
const caps = resolveCapabilities(program);
|
|
33
33
|
|
|
34
34
|
if (argv.length >= 1 && argv[0] === "mcp" && !caps.mcp) {
|
|
35
|
-
process.stderr.write("MCP is not enabled. Set mcpServer on the program root.\n");
|
|
35
|
+
process.stderr.write("MCP is not enabled. Set mcpServer: { enabled: true } on the program root.\n");
|
|
36
36
|
process.exit(1);
|
|
37
37
|
}
|
|
38
38
|
|
package/src/skill/generate.ts
CHANGED
|
@@ -4,7 +4,7 @@ This module generates Agent Skills content (SKILL.md + reference.md) from a CLI
|
|
|
4
4
|
|
|
5
5
|
import { collectOptionDefs } from "../parse.ts";
|
|
6
6
|
import { cliSchemaJson } from "../schema.ts";
|
|
7
|
-
import { collectMcpTools, sanitizeToolSegment } from "../mcp/tools.ts";
|
|
7
|
+
import { collectMcpTools, mcpServerId, sanitizeToolSegment } from "../mcp/tools.ts";
|
|
8
8
|
import { CliProgram, CliOptionKind } from "../types.ts";
|
|
9
9
|
|
|
10
10
|
export type SkillTarget = "cursor" | "claude";
|
|
@@ -75,7 +75,7 @@ function buildSkillMd(root: CliProgram, target: SkillTarget, dirName: string): s
|
|
|
75
75
|
"",
|
|
76
76
|
];
|
|
77
77
|
|
|
78
|
-
if (root.mcpServer
|
|
78
|
+
if (root.mcpServer?.enabled === true) {
|
|
79
79
|
lines.push(
|
|
80
80
|
"**Prefer MCP** when a host has the server connected:",
|
|
81
81
|
"",
|
|
@@ -89,7 +89,7 @@ function buildSkillMd(root: CliProgram, target: SkillTarget, dirName: string): s
|
|
|
89
89
|
JSON.stringify(
|
|
90
90
|
{
|
|
91
91
|
mcpServers: {
|
|
92
|
-
[root
|
|
92
|
+
[mcpServerId(root)]: {
|
|
93
93
|
command: root.key,
|
|
94
94
|
args: ["mcp"],
|
|
95
95
|
},
|
package/src/types.test.ts
CHANGED
|
@@ -18,8 +18,9 @@ const _leafOnly: CliLeaf = {
|
|
|
18
18
|
|
|
19
19
|
const _program: CliProgram = {
|
|
20
20
|
key: "app",
|
|
21
|
+
version: "0.0.0",
|
|
21
22
|
description: "",
|
|
22
|
-
mcpServer: {},
|
|
23
|
+
mcpServer: { enabled: true },
|
|
23
24
|
commands: [],
|
|
24
25
|
};
|
|
25
26
|
|
|
@@ -27,7 +28,7 @@ const _badMcpOnNode = {
|
|
|
27
28
|
key: "x",
|
|
28
29
|
description: "",
|
|
29
30
|
// @ts-expect-error mcpServer is program-root only
|
|
30
|
-
mcpServer: {},
|
|
31
|
+
mcpServer: { enabled: true },
|
|
31
32
|
commands: [],
|
|
32
33
|
} satisfies CliNode;
|
|
33
34
|
|
package/src/types.ts
CHANGED
|
@@ -89,13 +89,12 @@ export interface CliPositional {
|
|
|
89
89
|
|
|
90
90
|
/**
|
|
91
91
|
* Enables `myapp mcp` and MCP stdio server metadata (program root only).
|
|
92
|
+
* Must include `enabled: true`; omit `mcpServer` entirely to disable MCP.
|
|
92
93
|
*/
|
|
93
94
|
export interface CliMcpServerConfig {
|
|
94
|
-
/** `
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
version?: string;
|
|
98
|
-
/** Resource URI for schema export (default: `"argsbarg://schema"`). */
|
|
95
|
+
/** When `true`, enables the `mcp` built-in and MCP stdio server. */
|
|
96
|
+
enabled: boolean;
|
|
97
|
+
/** Resource URI for schema export (default: `<sanitized root key>://schema`). */
|
|
99
98
|
schemaResourceUri?: string;
|
|
100
99
|
/**
|
|
101
100
|
* Capture the user's login shell environment at MCP server start and merge it
|
|
@@ -110,7 +109,7 @@ export interface CliMcpServerConfig {
|
|
|
110
109
|
*/
|
|
111
110
|
envFile?: string;
|
|
112
111
|
/**
|
|
113
|
-
* Custom MCP resources exposed alongside the built-in
|
|
112
|
+
* Custom MCP resources exposed alongside the built-in schema resource.
|
|
114
113
|
* URIs must be unique and must not equal schemaResourceUri.
|
|
115
114
|
*/
|
|
116
115
|
resources?: CliMcpResource[];
|
|
@@ -209,7 +208,9 @@ export type CliNode = CliLeaf | CliRouter;
|
|
|
209
208
|
* May be a leaf or router, plus optional program-level MCP and install config.
|
|
210
209
|
*/
|
|
211
210
|
export type CliProgram = CliNode & {
|
|
212
|
-
/**
|
|
211
|
+
/** Program version (printed by the `version` built-in and MCP serverInfo). */
|
|
212
|
+
version: string;
|
|
213
|
+
/** When set with `enabled: true`, enables the `mcp` built-in subcommand. */
|
|
213
214
|
mcpServer?: CliMcpServerConfig;
|
|
214
215
|
/** Opt-out and defaults for `install`. */
|
|
215
216
|
install?: CliInstallConfig;
|
package/src/validate.ts
CHANGED
|
@@ -12,10 +12,20 @@ import {
|
|
|
12
12
|
isCliLeaf,
|
|
13
13
|
isCliRouter,
|
|
14
14
|
} from "./types.ts";
|
|
15
|
-
import {
|
|
15
|
+
import { resolveMcpSchemaUri } from "./mcp/tools.ts";
|
|
16
16
|
|
|
17
17
|
/** Validates a program schema. */
|
|
18
18
|
export function cliValidateProgram(program: CliProgram): void {
|
|
19
|
+
if (!program.version || program.version.trim().length === 0) {
|
|
20
|
+
throw new CliSchemaValidationError("CliProgram.version is required");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (program.mcpServer !== undefined && program.mcpServer.enabled !== true) {
|
|
24
|
+
throw new CliSchemaValidationError(
|
|
25
|
+
"mcpServer requires enabled: true; omit mcpServer to disable MCP",
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
19
29
|
const caps = resolveCapabilities(program);
|
|
20
30
|
const reserved = reservedCommandNames(caps);
|
|
21
31
|
|
|
@@ -58,8 +68,8 @@ function walkNode(node: CliNode, program: CliProgram, isRoot: boolean): void {
|
|
|
58
68
|
}
|
|
59
69
|
}
|
|
60
70
|
|
|
61
|
-
if (isRoot && program.mcpServer?.resources) {
|
|
62
|
-
const schemaUri = program
|
|
71
|
+
if (isRoot && program.mcpServer?.enabled === true && program.mcpServer.resources) {
|
|
72
|
+
const schemaUri = resolveMcpSchemaUri(program);
|
|
63
73
|
const uris = program.mcpServer.resources.map((r) => r.uri);
|
|
64
74
|
if (uris.includes(schemaUri)) {
|
|
65
75
|
throw new CliSchemaValidationError(
|