fix: prevent attach/detach-server from repeating server arg on tab
Some checks failed
CI / lint (pull_request) Has been cancelled
CI / typecheck (pull_request) Has been cancelled
CI / test (pull_request) Has been cancelled
CI / build (pull_request) Has been cancelled
CI / package (pull_request) Has been cancelled

Added __mcpctl_needs_server_arg guard in fish and position check in
bash so completions stop after one server name is selected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Michal
2026-02-23 19:36:45 +00:00
parent 677d34b868
commit 65c340a03c
3 changed files with 36 additions and 9 deletions

View File

@@ -94,19 +94,20 @@ describe('fish completions', () => {
expect(resourceNamesFn, 'must handle instances via server.name').toContain('.server.name');
});
it('attach-server completes with available (unattached) servers', () => {
// Find the line that provides argument completions AFTER attach-server is selected
it('attach-server completes with available (unattached) servers and guards against repeat', () => {
const attachLine = fishFile.split('\n').find((l) =>
l.startsWith('complete') && l.includes('__fish_seen_subcommand_from attach-server'));
expect(attachLine, 'attach-server argument completion must exist').toBeDefined();
expect(attachLine, 'attach-server must use __mcpctl_available_servers').toContain('__mcpctl_available_servers');
expect(attachLine, 'attach-server must guard with __mcpctl_needs_server_arg').toContain('__mcpctl_needs_server_arg');
});
it('detach-server completes with project servers', () => {
it('detach-server completes with project servers and guards against repeat', () => {
const detachLine = fishFile.split('\n').find((l) =>
l.startsWith('complete') && l.includes('__fish_seen_subcommand_from detach-server'));
expect(detachLine, 'detach-server argument completion must exist').toBeDefined();
expect(detachLine, 'detach-server must use __mcpctl_project_servers').toContain('__mcpctl_project_servers');
expect(detachLine, 'detach-server must guard with __mcpctl_needs_server_arg').toContain('__mcpctl_needs_server_arg');
});
it('non-project commands do not show with --project', () => {
@@ -142,16 +143,18 @@ describe('bash completions', () => {
expect(bashFile).toMatch(/get\|describe\|delete\)[\s\S]*?_mcpctl_resource_names/);
});
it('attach-server filters out already-attached servers using project context', () => {
it('attach-server filters out already-attached servers and guards against repeat', () => {
const attachBlock = bashFile.match(/attach-server\)[\s\S]*?return ;;/)?.[0] ?? '';
expect(attachBlock, 'attach-server must use _mcpctl_get_project_value').toContain('_mcpctl_get_project_value');
expect(attachBlock, 'attach-server must query project servers to exclude').toContain('--project');
expect(attachBlock, 'attach-server must check position to prevent repeat').toContain('cword - subcmd_pos');
});
it('detach-server shows only project servers', () => {
it('detach-server shows only project servers and guards against repeat', () => {
const detachBlock = bashFile.match(/detach-server\)[\s\S]*?return ;;/)?.[0] ?? '';
expect(detachBlock, 'detach-server must use _mcpctl_get_project_value').toContain('_mcpctl_get_project_value');
expect(detachBlock, 'detach-server must query project servers').toContain('--project');
expect(detachBlock, 'detach-server must check position to prevent repeat').toContain('cword - subcmd_pos');
});
it('instances use server.name instead of name', () => {