ai-cli-mcp 2.2.0 → 2.3.1

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.
@@ -76,7 +76,7 @@ describe('Process Management Tests', () => {
76
76
  const server = new ClaudeCodeServer();
77
77
  return { server, module, handlers };
78
78
  }
79
- describe('claude_code tool with PID return', () => {
79
+ describe('run tool with PID return', () => {
80
80
  it('should return PID immediately when starting a process', async () => {
81
81
  const { handlers } = await setupServer();
82
82
  // Create a mock process
@@ -89,7 +89,7 @@ describe('Process Management Tests', () => {
89
89
  const callToolHandler = handlers.get('callTool');
90
90
  const result = await callToolHandler({
91
91
  params: {
92
- name: 'claude_code',
92
+ name: 'run',
93
93
  arguments: {
94
94
  prompt: 'test prompt',
95
95
  workFolder: '/tmp'
@@ -99,7 +99,7 @@ describe('Process Management Tests', () => {
99
99
  const response = JSON.parse(result.content[0].text);
100
100
  expect(response.pid).toBe(12345);
101
101
  expect(response.status).toBe('started');
102
- expect(response.message).toBe('Claude Code process started successfully');
102
+ expect(response.message).toBe('claude process started successfully');
103
103
  });
104
104
  it('should handle process with model parameter', async () => {
105
105
  const { handlers } = await setupServer();
@@ -112,7 +112,7 @@ describe('Process Management Tests', () => {
112
112
  const callToolHandler = handlers.get('callTool');
113
113
  await callToolHandler({
114
114
  params: {
115
- name: 'claude_code',
115
+ name: 'run',
116
116
  arguments: {
117
117
  prompt: 'test prompt',
118
118
  workFolder: '/tmp',
@@ -137,7 +137,7 @@ describe('Process Management Tests', () => {
137
137
  const callToolHandler = handlers.get('callTool');
138
138
  const result = await callToolHandler({
139
139
  params: {
140
- name: 'claude_code',
140
+ name: 'run',
141
141
  arguments: {
142
142
  prompt: japanesePrompt,
143
143
  workFolder: '/tmp'
@@ -152,7 +152,7 @@ describe('Process Management Tests', () => {
152
152
  // Verify the prompt is stored correctly in process manager
153
153
  const getResult = await callToolHandler({
154
154
  params: {
155
- name: 'get_claude_result',
155
+ name: 'get_result',
156
156
  arguments: {
157
157
  pid: 12360
158
158
  }
@@ -197,7 +197,7 @@ describe('Process Management Tests', () => {
197
197
  const callToolHandler = handlers.get('callTool');
198
198
  const result = await callToolHandler({
199
199
  params: {
200
- name: 'claude_code',
200
+ name: 'run',
201
201
  arguments: {
202
202
  prompt: longJapanesePrompt,
203
203
  workFolder: '/tmp',
@@ -210,18 +210,18 @@ describe('Process Management Tests', () => {
210
210
  expect(response.pid).toBe(12361);
211
211
  // Verify spawn was called with the complete long prompt
212
212
  expect(mockSpawn).toHaveBeenCalledWith(expect.any(String), expect.arrayContaining(['-p', longJapanesePrompt]), expect.any(Object));
213
- // Check list_claude_processes truncates long prompts correctly
213
+ // Verify list_processes returns basic info
214
214
  const listResult = await callToolHandler({
215
215
  params: {
216
- name: 'list_claude_processes',
216
+ name: 'list_processes',
217
217
  arguments: {}
218
218
  }
219
219
  });
220
220
  const processes = JSON.parse(listResult.content[0].text);
221
221
  const process = processes.find((p) => p.pid === 12361);
222
- expect(process.prompt).toHaveLength(103); // 100 chars + '...'
223
- expect(process.prompt.endsWith('...')).toBe(true);
224
- expect(process.prompt).toContain('タスク:ファイル管理システムの作成');
222
+ expect(process.pid).toBe(12361);
223
+ expect(process.agent).toBe('claude');
224
+ expect(process.status).toBe('running');
225
225
  });
226
226
  it('should handle prompts with special characters and escape sequences', async () => {
227
227
  const { handlers } = await setupServer();
@@ -242,7 +242,7 @@ Unicodeテスト: 🎌 🗾 ✨
242
242
  const callToolHandler = handlers.get('callTool');
243
243
  const result = await callToolHandler({
244
244
  params: {
245
- name: 'claude_code',
245
+ name: 'run',
246
246
  arguments: {
247
247
  prompt: specialPrompt,
248
248
  workFolder: '/tmp'
@@ -265,16 +265,16 @@ Unicodeテスト: 🎌 🗾 ✨
265
265
  const callToolHandler = handlers.get('callTool');
266
266
  await expect(callToolHandler({
267
267
  params: {
268
- name: 'claude_code',
268
+ name: 'run',
269
269
  arguments: {
270
270
  prompt: 'test prompt',
271
271
  workFolder: '/tmp/test'
272
272
  }
273
273
  }
274
- })).rejects.toThrow('Failed to start Claude CLI process');
274
+ })).rejects.toThrow('Failed to start claude CLI process');
275
275
  });
276
276
  });
277
- describe('list_claude_processes tool', () => {
277
+ describe('list_processes tool', () => {
278
278
  it('should list all processes', async () => {
279
279
  const { handlers } = await setupServer();
280
280
  // Start a process first
@@ -288,7 +288,7 @@ Unicodeテスト: 🎌 🗾 ✨
288
288
  // Start a process
289
289
  await callToolHandler({
290
290
  params: {
291
- name: 'claude_code',
291
+ name: 'run',
292
292
  arguments: {
293
293
  prompt: 'test prompt for listing',
294
294
  workFolder: '/tmp',
@@ -305,7 +305,7 @@ Unicodeテスト: 🎌 🗾 ✨
305
305
  // List processes
306
306
  const listResult = await callToolHandler({
307
307
  params: {
308
- name: 'list_claude_processes',
308
+ name: 'list_processes',
309
309
  arguments: {}
310
310
  }
311
311
  });
@@ -313,11 +313,9 @@ Unicodeテスト: 🎌 🗾 ✨
313
313
  expect(processes).toHaveLength(1);
314
314
  expect(processes[0].pid).toBe(12347);
315
315
  expect(processes[0].status).toBe('running');
316
- expect(processes[0].prompt).toContain('test prompt for listing');
317
- expect(processes[0].model).toBe('sonnet');
318
- expect(processes[0].session_id).toBe('list-test-session-789');
316
+ expect(processes[0].agent).toBe('claude');
319
317
  });
320
- it('should truncate long prompts in list', async () => {
318
+ it('should list process with correct agent type', async () => {
321
319
  const { handlers } = await setupServer();
322
320
  const mockProcess = new EventEmitter();
323
321
  mockProcess.pid = 12348;
@@ -326,13 +324,12 @@ Unicodeテスト: 🎌 🗾 ✨
326
324
  mockProcess.kill = vi.fn();
327
325
  mockSpawn.mockReturnValue(mockProcess);
328
326
  const callToolHandler = handlers.get('callTool');
329
- // Start a process with a very long prompt
330
- const longPrompt = 'a'.repeat(150);
327
+ // Start a process
331
328
  await callToolHandler({
332
329
  params: {
333
- name: 'claude_code',
330
+ name: 'run',
334
331
  arguments: {
335
- prompt: longPrompt,
332
+ prompt: 'test prompt',
336
333
  workFolder: '/tmp'
337
334
  }
338
335
  }
@@ -340,16 +337,17 @@ Unicodeテスト: 🎌 🗾 ✨
340
337
  // List processes
341
338
  const listResult = await callToolHandler({
342
339
  params: {
343
- name: 'list_claude_processes',
340
+ name: 'list_processes',
344
341
  arguments: {}
345
342
  }
346
343
  });
347
344
  const processes = JSON.parse(listResult.content[0].text);
348
- expect(processes[0].prompt).toHaveLength(103); // 100 chars + '...'
349
- expect(processes[0].prompt.endsWith('...')).toBe(true);
345
+ expect(processes[0].pid).toBe(12348);
346
+ expect(processes[0].agent).toBe('claude');
347
+ expect(processes[0].status).toBe('running');
350
348
  });
351
349
  });
352
- describe('get_claude_result tool', () => {
350
+ describe('get_result tool', () => {
353
351
  it('should get process output', async () => {
354
352
  const { handlers } = await setupServer();
355
353
  const mockProcess = new EventEmitter();
@@ -362,7 +360,7 @@ Unicodeテスト: 🎌 🗾 ✨
362
360
  // Start a process
363
361
  await callToolHandler({
364
362
  params: {
365
- name: 'claude_code',
363
+ name: 'run',
366
364
  arguments: {
367
365
  prompt: 'test prompt',
368
366
  workFolder: '/tmp'
@@ -380,7 +378,7 @@ Unicodeテスト: 🎌 🗾 ✨
380
378
  // Get result
381
379
  const result = await callToolHandler({
382
380
  params: {
383
- name: 'get_claude_result',
381
+ name: 'get_result',
384
382
  arguments: {
385
383
  pid: 12349
386
384
  }
@@ -389,7 +387,7 @@ Unicodeテスト: 🎌 🗾 ✨
389
387
  const processInfo = JSON.parse(result.content[0].text);
390
388
  expect(processInfo.pid).toBe(12349);
391
389
  expect(processInfo.status).toBe('running');
392
- expect(processInfo.claudeOutput).toEqual(claudeJsonOutput);
390
+ expect(processInfo.agentOutput).toEqual(claudeJsonOutput);
393
391
  expect(processInfo.session_id).toBe('test-session-123');
394
392
  });
395
393
  it('should show completed status when process exits', async () => {
@@ -404,7 +402,7 @@ Unicodeテスト: 🎌 🗾 ✨
404
402
  // Start a process
405
403
  await callToolHandler({
406
404
  params: {
407
- name: 'claude_code',
405
+ name: 'run',
408
406
  arguments: {
409
407
  prompt: 'test prompt',
410
408
  workFolder: '/tmp'
@@ -423,7 +421,7 @@ Unicodeテスト: 🎌 🗾 ✨
423
421
  // Get result
424
422
  const result = await callToolHandler({
425
423
  params: {
426
- name: 'get_claude_result',
424
+ name: 'get_result',
427
425
  arguments: {
428
426
  pid: 12350
429
427
  }
@@ -432,7 +430,7 @@ Unicodeテスト: 🎌 🗾 ✨
432
430
  const processInfo = JSON.parse(result.content[0].text);
433
431
  expect(processInfo.status).toBe('completed');
434
432
  expect(processInfo.exitCode).toBe(0);
435
- expect(processInfo.claudeOutput).toEqual(completedJsonOutput);
433
+ expect(processInfo.agentOutput).toEqual(completedJsonOutput);
436
434
  expect(processInfo.session_id).toBe('completed-session-456');
437
435
  });
438
436
  it('should throw error for non-existent PID', async () => {
@@ -440,7 +438,7 @@ Unicodeテスト: 🎌 🗾 ✨
440
438
  const callToolHandler = handlers.get('callTool');
441
439
  await expect(callToolHandler({
442
440
  params: {
443
- name: 'get_claude_result',
441
+ name: 'get_result',
444
442
  arguments: {
445
443
  pid: 99999
446
444
  }
@@ -452,7 +450,7 @@ Unicodeテスト: 🎌 🗾 ✨
452
450
  const callToolHandler = handlers.get('callTool');
453
451
  await expect(callToolHandler({
454
452
  params: {
455
- name: 'get_claude_result',
453
+ name: 'get_result',
456
454
  arguments: {
457
455
  pid: 'not-a-number'
458
456
  }
@@ -471,7 +469,7 @@ Unicodeテスト: 🎌 🗾 ✨
471
469
  // Start a process
472
470
  await callToolHandler({
473
471
  params: {
474
- name: 'claude_code',
472
+ name: 'run',
475
473
  arguments: {
476
474
  prompt: 'test prompt',
477
475
  workFolder: '/tmp'
@@ -484,7 +482,7 @@ Unicodeテスト: 🎌 🗾 ✨
484
482
  // Get result
485
483
  const result = await callToolHandler({
486
484
  params: {
487
- name: 'get_claude_result',
485
+ name: 'get_result',
488
486
  arguments: {
489
487
  pid: 12355
490
488
  }
@@ -499,7 +497,7 @@ Unicodeテスト: 🎌 🗾 ✨
499
497
  expect(processInfo.session_id).toBeUndefined();
500
498
  });
501
499
  });
502
- describe('kill_claude_process tool', () => {
500
+ describe('kill_process tool', () => {
503
501
  it('should kill a running process', async () => {
504
502
  const { handlers } = await setupServer();
505
503
  const mockProcess = new EventEmitter();
@@ -512,7 +510,7 @@ Unicodeテスト: 🎌 🗾 ✨
512
510
  // Start a process
513
511
  await callToolHandler({
514
512
  params: {
515
- name: 'claude_code',
513
+ name: 'run',
516
514
  arguments: {
517
515
  prompt: 'test prompt',
518
516
  workFolder: '/tmp'
@@ -522,7 +520,7 @@ Unicodeテスト: 🎌 🗾 ✨
522
520
  // Kill the process
523
521
  const killResult = await callToolHandler({
524
522
  params: {
525
- name: 'kill_claude_process',
523
+ name: 'kill_process',
526
524
  arguments: {
527
525
  pid: 12351
528
526
  }
@@ -545,7 +543,7 @@ Unicodeテスト: 🎌 🗾 ✨
545
543
  // Start and complete a process
546
544
  await callToolHandler({
547
545
  params: {
548
- name: 'claude_code',
546
+ name: 'run',
549
547
  arguments: {
550
548
  prompt: 'test prompt',
551
549
  workFolder: '/tmp'
@@ -557,7 +555,7 @@ Unicodeテスト: 🎌 🗾 ✨
557
555
  // Try to kill the already completed process
558
556
  const killResult = await callToolHandler({
559
557
  params: {
560
- name: 'kill_claude_process',
558
+ name: 'kill_process',
561
559
  arguments: {
562
560
  pid: 12352
563
561
  }
@@ -573,7 +571,7 @@ Unicodeテスト: 🎌 🗾 ✨
573
571
  const callToolHandler = handlers.get('callTool');
574
572
  await expect(callToolHandler({
575
573
  params: {
576
- name: 'kill_claude_process',
574
+ name: 'kill_process',
577
575
  arguments: {
578
576
  pid: 99999
579
577
  }
@@ -606,7 +604,7 @@ Unicodeテスト: 🎌 🗾 ✨
606
604
  // Start a process
607
605
  await callToolHandler({
608
606
  params: {
609
- name: 'claude_code',
607
+ name: 'run',
610
608
  arguments: {
611
609
  prompt: 'test prompt',
612
610
  workFolder: '/tmp'
@@ -618,7 +616,7 @@ Unicodeテスト: 🎌 🗾 ✨
618
616
  // Get result to check error was recorded
619
617
  const result = await callToolHandler({
620
618
  params: {
621
- name: 'get_claude_result',
619
+ name: 'get_result',
622
620
  arguments: {
623
621
  pid: 12353
624
622
  }
@@ -23,11 +23,13 @@ vi.mock('@modelcontextprotocol/sdk/types.js', () => ({
23
23
  MethodNotFound: 'MethodNotFound',
24
24
  InvalidParams: 'InvalidParams'
25
25
  },
26
- McpError: vi.fn().mockImplementation((code, message) => {
27
- const error = new Error(message);
28
- error.code = code;
29
- return error;
30
- })
26
+ McpError: class extends Error {
27
+ code;
28
+ constructor(code, message) {
29
+ super(message);
30
+ this.code = code;
31
+ }
32
+ }
31
33
  }));
32
34
  vi.mock('@modelcontextprotocol/sdk/server/index.js', () => ({
33
35
  Server: vi.fn().mockImplementation(function () {
@@ -350,12 +352,14 @@ describe('ClaudeCodeServer Unit Tests', () => {
350
352
  // Test the handler
351
353
  const handler = listToolsCall[1];
352
354
  const result = await handler();
353
- expect(result.tools).toHaveLength(4);
354
- expect(result.tools[0].name).toBe('claude_code');
355
- expect(result.tools[0].description).toContain('Claude Code Agent');
356
- expect(result.tools[1].name).toBe('list_claude_processes');
357
- expect(result.tools[2].name).toBe('get_claude_result');
358
- expect(result.tools[3].name).toBe('kill_claude_process');
355
+ expect(result.tools).toHaveLength(6);
356
+ expect(result.tools[0].name).toBe('run');
357
+ expect(result.tools[0].description).toContain('AI Agent Runner');
358
+ expect(result.tools[1].name).toBe('list_processes');
359
+ expect(result.tools[2].name).toBe('get_result');
360
+ expect(result.tools[3].name).toBe('wait');
361
+ expect(result.tools[4].name).toBe('kill_process');
362
+ expect(result.tools[5].name).toBe('cleanup_processes');
359
363
  });
360
364
  it('should handle CallToolRequest', async () => {
361
365
  mockHomedir.mockReturnValue('/home/user');
@@ -383,14 +387,14 @@ describe('ClaudeCodeServer Unit Tests', () => {
383
387
  const handler = callToolCall[1];
384
388
  const result = await handler({
385
389
  params: {
386
- name: 'claude_code',
390
+ name: 'run',
387
391
  arguments: {
388
392
  prompt: 'test prompt',
389
393
  workFolder: '/tmp'
390
394
  }
391
395
  }
392
396
  });
393
- // claude_code now returns PID immediately
397
+ // run now returns PID immediately
394
398
  expect(result.content[0].type).toBe('text');
395
399
  const response = JSON.parse(result.content[0].text);
396
400
  expect(response.pid).toBe(12345);
@@ -410,14 +414,20 @@ describe('ClaudeCodeServer Unit Tests', () => {
410
414
  const callToolCall = mockServerInstance.setRequestHandler.mock.calls.find((call) => call[0].name === 'callTool');
411
415
  const handler = callToolCall[1];
412
416
  // Test missing workFolder
413
- await expect(handler({
414
- params: {
415
- name: 'claude_code',
416
- arguments: {
417
- prompt: 'test'
417
+ try {
418
+ await handler({
419
+ params: {
420
+ name: 'run',
421
+ arguments: {
422
+ prompt: 'test'
423
+ }
418
424
  }
419
- }
420
- })).rejects.toThrow('Missing or invalid required parameter: workFolder');
425
+ });
426
+ expect.fail('Should have thrown');
427
+ }
428
+ catch (error) {
429
+ expect(error.message).toContain('Missing or invalid required parameter: workFolder');
430
+ }
421
431
  });
422
432
  it('should handle non-existent workFolder', async () => {
423
433
  mockHomedir.mockReturnValue('/home/user');
@@ -440,15 +450,21 @@ describe('ClaudeCodeServer Unit Tests', () => {
440
450
  const callToolCall = mockServerInstance.setRequestHandler.mock.calls.find((call) => call[0].name === 'callTool');
441
451
  const handler = callToolCall[1];
442
452
  // Should throw error for non-existent workFolder
443
- await expect(handler({
444
- params: {
445
- name: 'claude_code',
446
- arguments: {
447
- prompt: 'test',
448
- workFolder: '/nonexistent'
453
+ try {
454
+ await handler({
455
+ params: {
456
+ name: 'run',
457
+ arguments: {
458
+ prompt: 'test',
459
+ workFolder: '/nonexistent'
460
+ }
449
461
  }
450
- }
451
- })).rejects.toThrow('Working folder does not exist');
462
+ });
463
+ expect.fail('Should have thrown');
464
+ }
465
+ catch (error) {
466
+ expect(error.message).toContain('Working folder does not exist');
467
+ }
452
468
  });
453
469
  it('should handle session_id parameter', async () => {
454
470
  mockHomedir.mockReturnValue('/home/user');
@@ -474,7 +490,7 @@ describe('ClaudeCodeServer Unit Tests', () => {
474
490
  mockSpawn.mockReturnValue(mockProcess);
475
491
  const result = await handler({
476
492
  params: {
477
- name: 'claude_code',
493
+ name: 'run',
478
494
  arguments: {
479
495
  prompt: 'test prompt',
480
496
  workFolder: '/tmp',
@@ -523,7 +539,7 @@ describe('ClaudeCodeServer Unit Tests', () => {
523
539
  mockSpawn.mockReturnValue(mockProcess);
524
540
  const result = await handler({
525
541
  params: {
526
- name: 'claude_code',
542
+ name: 'run',
527
543
  arguments: {
528
544
  prompt_file: '/tmp/prompt.txt',
529
545
  workFolder: '/tmp'
@@ -533,7 +549,7 @@ describe('ClaudeCodeServer Unit Tests', () => {
533
549
  // Verify file was read and spawn was called with content
534
550
  expect(mockSpawn).toHaveBeenCalledWith(expect.any(String), expect.arrayContaining(['-p', 'Content from file']), expect.any(Object));
535
551
  });
536
- it('should resolve model aliases when calling claude_code tool', async () => {
552
+ it('should resolve model aliases when calling run tool', async () => {
537
553
  mockHomedir.mockReturnValue('/home/user');
538
554
  mockExistsSync.mockReturnValue(true);
539
555
  // Set up spawn mock to return a process
@@ -555,7 +571,7 @@ describe('ClaudeCodeServer Unit Tests', () => {
555
571
  // Test with haiku alias
556
572
  const result = await handler({
557
573
  params: {
558
- name: 'claude_code',
574
+ name: 'run',
559
575
  arguments: {
560
576
  prompt: 'test prompt',
561
577
  workFolder: '/tmp',
@@ -590,7 +606,7 @@ describe('ClaudeCodeServer Unit Tests', () => {
590
606
  // Test with non-alias model name
591
607
  const result = await handler({
592
608
  params: {
593
- name: 'claude_code',
609
+ name: 'run',
594
610
  arguments: {
595
611
  prompt: 'test prompt',
596
612
  workFolder: '/tmp',
@@ -618,7 +634,7 @@ describe('ClaudeCodeServer Unit Tests', () => {
618
634
  try {
619
635
  await handler({
620
636
  params: {
621
- name: 'claude_code',
637
+ name: 'run',
622
638
  arguments: {
623
639
  prompt: 'test prompt',
624
640
  prompt_file: '/tmp/prompt.txt',
@@ -649,7 +665,7 @@ describe('ClaudeCodeServer Unit Tests', () => {
649
665
  try {
650
666
  await handler({
651
667
  params: {
652
- name: 'claude_code',
668
+ name: 'run',
653
669
  arguments: {
654
670
  workFolder: '/tmp'
655
671
  }
@@ -31,11 +31,14 @@ vi.mock('@modelcontextprotocol/sdk/types.js', () => ({
31
31
  MethodNotFound: 'MethodNotFound',
32
32
  InvalidParams: 'InvalidParams'
33
33
  },
34
- McpError: vi.fn().mockImplementation((code, message) => {
35
- const error = new Error(message);
36
- error.code = code;
37
- return error;
38
- })
34
+ McpError: class McpError extends Error {
35
+ code;
36
+ constructor(code, message) {
37
+ super(message);
38
+ this.code = code;
39
+ this.name = 'McpError';
40
+ }
41
+ }
39
42
  }));
40
43
  const mockExistsSync = vi.mocked(existsSync);
41
44
  const mockHomedir = vi.mocked(homedir);
@@ -164,21 +167,49 @@ describe('Argument Validation Tests', () => {
164
167
  });
165
168
  });
166
169
  describe('Runtime Argument Validation', () => {
167
- it('should validate workFolder is a string when provided', async () => {
168
- mockHomedir.mockReturnValue('/home/user');
169
- mockExistsSync.mockReturnValue(true);
170
- setupServerMock();
170
+ let handlers;
171
+ let mockServerInstance;
172
+ async function setupServer() {
173
+ // Reset modules to ensure fresh import
174
+ vi.resetModules();
175
+ // Re-setup mocks after reset
176
+ const { existsSync } = await import('node:fs');
177
+ const { homedir } = await import('node:os');
178
+ vi.mocked(existsSync).mockReturnValue(true);
179
+ vi.mocked(homedir).mockReturnValue('/home/user');
180
+ const { Server } = await import('@modelcontextprotocol/sdk/server/index.js');
181
+ vi.mocked(Server).mockImplementation(() => {
182
+ mockServerInstance = {
183
+ setRequestHandler: vi.fn((schema, handler) => {
184
+ handlers.set(schema.name, handler);
185
+ }),
186
+ connect: vi.fn(),
187
+ close: vi.fn(),
188
+ onerror: undefined
189
+ };
190
+ return mockServerInstance;
191
+ });
171
192
  const module = await import('../server.js');
172
193
  // @ts-ignore
173
194
  const { ClaudeCodeServer } = module;
174
195
  const server = new ClaudeCodeServer();
175
- const mockServerInstance = vi.mocked(Server).mock.results[0].value;
176
- const callToolCall = mockServerInstance.setRequestHandler.mock.calls.find((call) => call[0].name === 'callTool');
177
- const handler = callToolCall[1];
196
+ return { server, handlers };
197
+ }
198
+ beforeEach(() => {
199
+ handlers = new Map();
200
+ // Re-setup mocks after vi.resetModules() in outer beforeEach
201
+ mockHomedir.mockReturnValue('/home/user');
202
+ mockExistsSync.mockReturnValue(true);
203
+ });
204
+ it('should validate workFolder is a string when provided', async () => {
205
+ mockHomedir.mockReturnValue('/home/user');
206
+ mockExistsSync.mockReturnValue(true);
207
+ await setupServer();
208
+ const handler = handlers.get('callTool');
178
209
  // Test with non-string workFolder
179
210
  await expect(handler({
180
211
  params: {
181
- name: 'claude_code',
212
+ name: 'run',
182
213
  arguments: {
183
214
  prompt: 'test',
184
215
  workFolder: 123 // Invalid type
@@ -187,26 +218,18 @@ describe('Argument Validation Tests', () => {
187
218
  })).rejects.toThrow();
188
219
  });
189
220
  it('should reject empty string prompt', async () => {
190
- mockHomedir.mockReturnValue('/home/user');
191
- mockExistsSync.mockReturnValue(true);
192
- setupServerMock();
193
- const module = await import('../server.js');
194
- // @ts-ignore
195
- const { ClaudeCodeServer } = module;
196
- const server = new ClaudeCodeServer();
197
- const mockServerInstance = vi.mocked(Server).mock.results[0].value;
198
- const callToolCall = mockServerInstance.setRequestHandler.mock.calls.find((call) => call[0].name === 'callTool');
199
- const handler = callToolCall[1];
221
+ await setupServer();
222
+ const handler = handlers.get('callTool');
200
223
  // Empty string prompt should be rejected
201
224
  await expect(handler({
202
225
  params: {
203
- name: 'claude_code',
226
+ name: 'run',
204
227
  arguments: {
205
228
  prompt: '', // Empty prompt
206
229
  workFolder: '/tmp'
207
230
  }
208
231
  }
209
- })).rejects.toThrow('Missing or invalid required parameter: prompt');
232
+ })).rejects.toThrow('Either prompt or prompt_file must be provided');
210
233
  });
211
234
  });
212
235
  });
@@ -32,7 +32,7 @@ describe('Version Print on First Use', () => {
32
32
  });
33
33
  it('should print version and startup time only on first use', async () => {
34
34
  // First tool call
35
- await client.callTool('claude_code', {
35
+ await client.callTool('run', {
36
36
  prompt: 'echo "test 1"',
37
37
  workFolder: testDir,
38
38
  });
@@ -40,17 +40,17 @@ describe('Version Print on First Use', () => {
40
40
  const findVersionCall = (calls) => {
41
41
  return calls.find(call => {
42
42
  const str = call[1] || call[0]; // message might be first or second param
43
- return typeof str === 'string' && str.includes('claude_code v') && str.includes('started at');
43
+ return typeof str === 'string' && str.includes('ai_cli_mcp v') && str.includes('started at');
44
44
  });
45
45
  };
46
46
  // Check that version was printed on first use
47
47
  const versionCall = findVersionCall(consoleErrorSpy.mock.calls);
48
48
  expect(versionCall).toBeDefined();
49
- expect(versionCall[1]).toMatch(/claude_code v[0-9]+\.[0-9]+\.[0-9]+ started at \d{4}-\d{2}-\d{2}T/);
49
+ expect(versionCall[1]).toMatch(/ai_cli_mcp v[0-9]+\.[0-9]+\.[0-9]+ started at \d{4}-\d{2}-\d{2}T/);
50
50
  // Clear the spy but keep the spy active
51
51
  consoleErrorSpy.mockClear();
52
52
  // Second tool call
53
- await client.callTool('claude_code', {
53
+ await client.callTool('run', {
54
54
  prompt: 'echo "test 2"',
55
55
  workFolder: testDir,
56
56
  });
@@ -58,7 +58,7 @@ describe('Version Print on First Use', () => {
58
58
  const secondVersionCall = findVersionCall(consoleErrorSpy.mock.calls);
59
59
  expect(secondVersionCall).toBeUndefined();
60
60
  // Third tool call
61
- await client.callTool('claude_code', {
61
+ await client.callTool('run', {
62
62
  prompt: 'echo "test 3"',
63
63
  workFolder: testDir,
64
64
  });