Skip to content

Commit cedc0d2

Browse files
committed
refactor(cli): use manifest-declared CLI names instead of prefix stripping
- Add explicit cli: names to 6 swift-package manifests - Remove getBaseToolName() from output.ts and register-tool-commands.ts - Remove global CLI name uniqueness check from loadManifest
1 parent e2c5d6e commit cedc0d2

9 files changed

Lines changed: 13 additions & 57 deletions

manifests/tools/swift_package_build.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ id: swift_package_build
22
module: mcp/tools/swift-package/swift_package_build
33
names:
44
mcp: swift_package_build
5+
cli: build
56
description: swift package target build.
67
predicates:
78
- hideWhenXcodeAgentMode

manifests/tools/swift_package_clean.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ id: swift_package_clean
22
module: mcp/tools/swift-package/swift_package_clean
33
names:
44
mcp: swift_package_clean
5+
cli: clean
56
description: swift package clean.
67
annotations:
78
title: Swift Package Clean

manifests/tools/swift_package_list.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ id: swift_package_list
22
module: mcp/tools/swift-package/swift_package_list
33
names:
44
mcp: swift_package_list
5+
cli: list
56
description: List SwiftPM processes.
67
routing:
78
stateful: true

manifests/tools/swift_package_run.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ id: swift_package_run
22
module: mcp/tools/swift-package/swift_package_run
33
names:
44
mcp: swift_package_run
5+
cli: run
56
description: swift package target run.
67
routing:
78
stateful: true

manifests/tools/swift_package_stop.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ id: swift_package_stop
22
module: mcp/tools/swift-package/swift_package_stop
33
names:
44
mcp: swift_package_stop
5+
cli: stop
56
description: Stop SwiftPM run.
67
routing:
78
stateful: true

manifests/tools/swift_package_test.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ id: swift_package_test
22
module: mcp/tools/swift-package/swift_package_test
33
names:
44
mcp: swift_package_test
5+
cli: test
56
description: Run swift package target tests.
67
predicates:
78
- hideWhenXcodeAgentMode

src/cli/output.ts

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,6 @@ function printToolResponseText(response: ToolResponse): void {
5252
}
5353
}
5454

55-
/**
56-
* Get the base tool name without workflow prefix.
57-
* For disambiguated tools, strips the workflow prefix.
58-
*/
59-
function getBaseToolName(cliName: string, workflow: string): string {
60-
const prefix = `${workflow}-`;
61-
if (cliName.startsWith(prefix)) {
62-
return cliName.slice(prefix.length);
63-
}
64-
return cliName;
65-
}
66-
6755
/**
6856
* Format a tool list for display.
6957
*/
@@ -74,7 +62,6 @@ export function formatToolList(
7462
const lines: string[] = [];
7563

7664
if (options.grouped) {
77-
// Group by workflow - show subcommand names
7865
const byWorkflow = new Map<string, typeof tools>();
7966
for (const tool of tools) {
8067
const existing = byWorkflow.get(tool.workflow) ?? [];
@@ -85,37 +72,28 @@ export function formatToolList(
8572
for (const workflow of sortedWorkflows) {
8673
lines.push(`\n${workflow}:`);
8774
const workflowTools = byWorkflow.get(workflow) ?? [];
88-
// Sort by base name (without prefix)
89-
const sortedTools = workflowTools.sort((a, b) => {
90-
const aBase = getBaseToolName(a.cliName, a.workflow);
91-
const bBase = getBaseToolName(b.cliName, b.workflow);
92-
return aBase.localeCompare(bBase);
93-
});
75+
const sortedTools = workflowTools.sort((a, b) => a.cliName.localeCompare(b.cliName));
9476

9577
for (const tool of sortedTools) {
96-
// Show subcommand name (without workflow prefix)
97-
const toolName = getBaseToolName(tool.cliName, tool.workflow);
9878
const statefulMarker = tool.stateful ? ' [stateful]' : '';
9979
if (options.verbose && tool.description) {
100-
lines.push(` ${toolName}${statefulMarker}`);
80+
lines.push(` ${tool.cliName}${statefulMarker}`);
10181
lines.push(` ${tool.description}`);
10282
} else {
10383
const desc = tool.description ? ` - ${truncate(tool.description, 60)}` : '';
104-
lines.push(` ${toolName}${statefulMarker}${desc}`);
84+
lines.push(` ${tool.cliName}${statefulMarker}${desc}`);
10585
}
10686
}
10787
}
10888
} else {
109-
// Flat list - show full workflow-scoped command
11089
const sortedTools = [...tools].sort((a, b) => {
111-
const aFull = `${a.workflow} ${getBaseToolName(a.cliName, a.workflow)}`;
112-
const bFull = `${b.workflow} ${getBaseToolName(b.cliName, b.workflow)}`;
90+
const aFull = `${a.workflow} ${a.cliName}`;
91+
const bFull = `${b.workflow} ${b.cliName}`;
11392
return aFull.localeCompare(bFull);
11493
});
11594

11695
for (const tool of sortedTools) {
117-
const toolName = getBaseToolName(tool.cliName, tool.workflow);
118-
const fullCommand = `${tool.workflow} ${toolName}`;
96+
const fullCommand = `${tool.workflow} ${tool.cliName}`;
11997
const statefulMarker = tool.stateful ? ' [stateful]' : '';
12098
if (options.verbose && tool.description) {
12199
lines.push(`${fullCommand}${statefulMarker}`);

src/cli/register-tool-commands.ts

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,7 @@ function registerToolSubcommand(
9595
const yargsOptions = schemaToYargsOptions(tool.cliSchema);
9696
const unsupportedKeys = getUnsupportedSchemaKeys(tool.cliSchema);
9797

98-
// Use the base CLI name without workflow prefix since it's already scoped
99-
const commandName = getBaseToolName(tool);
98+
const commandName = tool.cliName;
10099

101100
yargs.command(
102101
commandName,
@@ -188,15 +187,3 @@ function registerToolSubcommand(
188187
},
189188
);
190189
}
191-
192-
/**
193-
* Get the base tool name without any workflow prefix.
194-
* For tools that were disambiguated with workflow prefix, strip it.
195-
*/
196-
function getBaseToolName(tool: ToolDefinition): string {
197-
const prefix = `${tool.workflow}-`;
198-
if (tool.cliName.startsWith(prefix)) {
199-
return tool.cliName.slice(prefix.length);
200-
}
201-
return tool.cliName;
202-
}

src/core/manifest/load-manifest.ts

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import {
1313
type ToolManifestEntry,
1414
type WorkflowManifestEntry,
1515
type ResolvedManifest,
16-
getEffectiveCliName,
1716
} from './schema.ts';
1817

1918
// Re-export types for consumers
@@ -226,20 +225,6 @@ export function loadManifest(): ResolvedManifest {
226225
mcpNames.set(tool.names.mcp, toolId);
227226
}
228227

229-
// Validate CLI name uniqueness (after derivation)
230-
const cliNames = new Map<string, string>(); // cliName -> toolId
231-
for (const [toolId, tool] of tools) {
232-
const cliName = getEffectiveCliName(tool);
233-
const existing = cliNames.get(cliName);
234-
if (existing) {
235-
throw new ManifestValidationError(
236-
`Duplicate CLI name '${cliName}' used by tools '${existing}' and '${toolId}'. ` +
237-
`Set explicit 'names.cli' in one of the tool manifests to resolve.`,
238-
);
239-
}
240-
cliNames.set(cliName, toolId);
241-
}
242-
243228
return { tools, workflows };
244229
}
245230

0 commit comments

Comments
 (0)