ai-cli-mcp 2.3.1 → 2.3.2
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/dist/__tests__/e2e.test.js +3 -10
- package/dist/__tests__/edge-cases.test.js +3 -11
- package/dist/__tests__/utils/mcp-client.js +17 -0
- package/dist/__tests__/version-print.test.js +2 -6
- package/dist/server.js +2 -4
- package/package.json +1 -1
- package/src/__tests__/e2e.test.ts +3 -10
- package/src/__tests__/edge-cases.test.ts +5 -14
- package/src/__tests__/utils/mcp-client.ts +30 -0
- package/src/__tests__/version-print.test.ts +5 -10
- package/src/server.ts +2 -4
|
@@ -2,22 +2,17 @@ import { describe, it, expect, beforeEach, afterEach, afterAll } from 'vitest';
|
|
|
2
2
|
import { mkdtempSync, rmSync, readFileSync, existsSync } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
|
-
import {
|
|
5
|
+
import { createTestClient } from './utils/mcp-client.js';
|
|
6
6
|
import { getSharedMock, cleanupSharedMock } from './utils/persistent-mock.js';
|
|
7
7
|
describe('Claude Code MCP E2E Tests', () => {
|
|
8
8
|
let client;
|
|
9
9
|
let testDir;
|
|
10
|
-
const serverPath = 'dist/server.js';
|
|
11
10
|
beforeEach(async () => {
|
|
12
11
|
// Ensure mock exists
|
|
13
12
|
await getSharedMock();
|
|
14
13
|
// Create a temporary directory for test files
|
|
15
14
|
testDir = mkdtempSync(join(tmpdir(), 'claude-code-test-'));
|
|
16
|
-
|
|
17
|
-
client = new MCPTestClient(serverPath, {
|
|
18
|
-
MCP_CLAUDE_DEBUG: 'true',
|
|
19
|
-
CLAUDE_CLI_NAME: '/tmp/claude-code-test-mock/claudeMocked',
|
|
20
|
-
});
|
|
15
|
+
client = createTestClient();
|
|
21
16
|
await client.connect();
|
|
22
17
|
});
|
|
23
18
|
afterEach(async () => {
|
|
@@ -198,9 +193,7 @@ describe('Integration Tests (Local Only)', () => {
|
|
|
198
193
|
beforeEach(async () => {
|
|
199
194
|
testDir = mkdtempSync(join(tmpdir(), 'claude-code-integration-'));
|
|
200
195
|
// Initialize client without mocks for real Claude testing
|
|
201
|
-
client =
|
|
202
|
-
MCP_CLAUDE_DEBUG: 'true',
|
|
203
|
-
});
|
|
196
|
+
client = createTestClient({ claudeCliName: '' });
|
|
204
197
|
});
|
|
205
198
|
afterEach(async () => {
|
|
206
199
|
if (client) {
|
|
@@ -2,22 +2,17 @@ import { describe, it, expect, beforeEach, afterEach, afterAll } from 'vitest';
|
|
|
2
2
|
import { mkdtempSync, rmSync } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
|
-
import {
|
|
5
|
+
import { createTestClient } from './utils/mcp-client.js';
|
|
6
6
|
import { getSharedMock, cleanupSharedMock } from './utils/persistent-mock.js';
|
|
7
7
|
describe('Claude Code Edge Cases', () => {
|
|
8
8
|
let client;
|
|
9
9
|
let testDir;
|
|
10
|
-
const serverPath = 'dist/server.js';
|
|
11
10
|
beforeEach(async () => {
|
|
12
11
|
// Ensure mock exists
|
|
13
12
|
await getSharedMock();
|
|
14
13
|
// Create test directory
|
|
15
14
|
testDir = mkdtempSync(join(tmpdir(), 'claude-code-edge-'));
|
|
16
|
-
|
|
17
|
-
client = new MCPTestClient(serverPath, {
|
|
18
|
-
MCP_CLAUDE_DEBUG: 'true',
|
|
19
|
-
CLAUDE_CLI_NAME: '/tmp/claude-code-test-mock/claudeMocked',
|
|
20
|
-
});
|
|
15
|
+
client = createTestClient();
|
|
21
16
|
await client.connect();
|
|
22
17
|
});
|
|
23
18
|
afterEach(async () => {
|
|
@@ -80,10 +75,7 @@ describe('Claude Code Edge Cases', () => {
|
|
|
80
75
|
describe('Error Recovery', () => {
|
|
81
76
|
it('should handle Claude CLI not found gracefully', async () => {
|
|
82
77
|
// Create a client with a different binary name that doesn't exist
|
|
83
|
-
const errorClient =
|
|
84
|
-
MCP_CLAUDE_DEBUG: 'true',
|
|
85
|
-
CLAUDE_CLI_NAME: 'non-existent-claude',
|
|
86
|
-
});
|
|
78
|
+
const errorClient = createTestClient({ claudeCliName: 'non-existent-claude' });
|
|
87
79
|
await errorClient.connect();
|
|
88
80
|
await expect(errorClient.callTool('run', {
|
|
89
81
|
prompt: 'Test prompt',
|
|
@@ -102,3 +102,20 @@ export class MCPTestClient extends EventEmitter {
|
|
|
102
102
|
return response.result?.tools || [];
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Default server path
|
|
107
|
+
*/
|
|
108
|
+
const DEFAULT_SERVER_PATH = 'dist/server.js';
|
|
109
|
+
/**
|
|
110
|
+
* Create a test client with standard configuration
|
|
111
|
+
* Automatically unsets VITEST env so the server actually starts
|
|
112
|
+
*/
|
|
113
|
+
export function createTestClient(options = {}) {
|
|
114
|
+
const { serverPath = DEFAULT_SERVER_PATH, claudeCliName = '/tmp/claude-code-test-mock/claudeMocked', debug = true, env = {}, } = options;
|
|
115
|
+
return new MCPTestClient(serverPath, {
|
|
116
|
+
VITEST: '', // Unset so server starts
|
|
117
|
+
MCP_CLAUDE_DEBUG: debug ? 'true' : '',
|
|
118
|
+
CLAUDE_CLI_NAME: claudeCliName,
|
|
119
|
+
...env,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
@@ -2,13 +2,12 @@ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
|
2
2
|
import { mkdtempSync, rmSync } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
|
-
import {
|
|
5
|
+
import { createTestClient } from './utils/mcp-client.js';
|
|
6
6
|
import { getSharedMock } from './utils/persistent-mock.js';
|
|
7
7
|
describe('Version Print on First Use', () => {
|
|
8
8
|
let client;
|
|
9
9
|
let testDir;
|
|
10
10
|
let consoleErrorSpy;
|
|
11
|
-
const serverPath = 'dist/server.js';
|
|
12
11
|
beforeEach(async () => {
|
|
13
12
|
// Ensure mock exists
|
|
14
13
|
await getSharedMock();
|
|
@@ -16,10 +15,7 @@ describe('Version Print on First Use', () => {
|
|
|
16
15
|
testDir = mkdtempSync(join(tmpdir(), 'claude-code-test-'));
|
|
17
16
|
// Spy on console.error
|
|
18
17
|
consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
19
|
-
|
|
20
|
-
client = new MCPTestClient(serverPath, {
|
|
21
|
-
CLAUDE_CLI_NAME: '/tmp/claude-code-test-mock/claudeMocked',
|
|
22
|
-
});
|
|
18
|
+
client = createTestClient({ debug: false });
|
|
23
19
|
await client.connect();
|
|
24
20
|
});
|
|
25
21
|
afterEach(async () => {
|
package/dist/server.js
CHANGED
|
@@ -6,7 +6,6 @@ import { spawn } from 'node:child_process';
|
|
|
6
6
|
import { existsSync, readFileSync } from 'node:fs';
|
|
7
7
|
import { homedir } from 'node:os';
|
|
8
8
|
import { join, resolve as pathResolve } from 'node:path';
|
|
9
|
-
import { fileURLToPath } from 'node:url';
|
|
10
9
|
import * as path from 'path';
|
|
11
10
|
import { parseCodexOutput, parseClaudeOutput, parseGeminiOutput } from './parsers.js';
|
|
12
11
|
// Server version - update this when releasing new versions
|
|
@@ -766,9 +765,8 @@ export class ClaudeCodeServer {
|
|
|
766
765
|
await this.server.close();
|
|
767
766
|
}
|
|
768
767
|
}
|
|
769
|
-
// Create and run the server
|
|
770
|
-
|
|
771
|
-
if (process.argv[1] === __filename) {
|
|
768
|
+
// Create and run the server (skip during tests)
|
|
769
|
+
if (!process.env.VITEST) {
|
|
772
770
|
const server = new ClaudeCodeServer();
|
|
773
771
|
server.run().catch(console.error);
|
|
774
772
|
}
|
package/package.json
CHANGED
|
@@ -2,13 +2,12 @@ import { describe, it, expect, beforeEach, afterEach, afterAll } from 'vitest';
|
|
|
2
2
|
import { mkdtempSync, rmSync, readFileSync, existsSync } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
|
-
import { MCPTestClient } from './utils/mcp-client.js';
|
|
5
|
+
import { createTestClient, MCPTestClient } from './utils/mcp-client.js';
|
|
6
6
|
import { getSharedMock, cleanupSharedMock } from './utils/persistent-mock.js';
|
|
7
7
|
|
|
8
8
|
describe('Claude Code MCP E2E Tests', () => {
|
|
9
9
|
let client: MCPTestClient;
|
|
10
10
|
let testDir: string;
|
|
11
|
-
const serverPath = 'dist/server.js';
|
|
12
11
|
|
|
13
12
|
beforeEach(async () => {
|
|
14
13
|
// Ensure mock exists
|
|
@@ -17,11 +16,7 @@ describe('Claude Code MCP E2E Tests', () => {
|
|
|
17
16
|
// Create a temporary directory for test files
|
|
18
17
|
testDir = mkdtempSync(join(tmpdir(), 'claude-code-test-'));
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
client = new MCPTestClient(serverPath, {
|
|
22
|
-
MCP_CLAUDE_DEBUG: 'true',
|
|
23
|
-
CLAUDE_CLI_NAME: '/tmp/claude-code-test-mock/claudeMocked',
|
|
24
|
-
});
|
|
19
|
+
client = createTestClient();
|
|
25
20
|
|
|
26
21
|
await client.connect();
|
|
27
22
|
});
|
|
@@ -241,9 +236,7 @@ describe('Integration Tests (Local Only)', () => {
|
|
|
241
236
|
testDir = mkdtempSync(join(tmpdir(), 'claude-code-integration-'));
|
|
242
237
|
|
|
243
238
|
// Initialize client without mocks for real Claude testing
|
|
244
|
-
client =
|
|
245
|
-
MCP_CLAUDE_DEBUG: 'true',
|
|
246
|
-
});
|
|
239
|
+
client = createTestClient({ claudeCliName: '' });
|
|
247
240
|
});
|
|
248
241
|
|
|
249
242
|
afterEach(async () => {
|
|
@@ -2,27 +2,21 @@ import { describe, it, expect, beforeEach, afterEach, afterAll } from 'vitest';
|
|
|
2
2
|
import { mkdtempSync, rmSync } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
|
-
import { MCPTestClient } from './utils/mcp-client.js';
|
|
5
|
+
import { createTestClient, MCPTestClient } from './utils/mcp-client.js';
|
|
6
6
|
import { getSharedMock, cleanupSharedMock } from './utils/persistent-mock.js';
|
|
7
7
|
|
|
8
8
|
describe('Claude Code Edge Cases', () => {
|
|
9
9
|
let client: MCPTestClient;
|
|
10
10
|
let testDir: string;
|
|
11
|
-
const serverPath = 'dist/server.js';
|
|
12
11
|
|
|
13
12
|
beforeEach(async () => {
|
|
14
13
|
// Ensure mock exists
|
|
15
14
|
await getSharedMock();
|
|
16
|
-
|
|
15
|
+
|
|
17
16
|
// Create test directory
|
|
18
17
|
testDir = mkdtempSync(join(tmpdir(), 'claude-code-edge-'));
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
client = new MCPTestClient(serverPath, {
|
|
22
|
-
MCP_CLAUDE_DEBUG: 'true',
|
|
23
|
-
CLAUDE_CLI_NAME: '/tmp/claude-code-test-mock/claudeMocked',
|
|
24
|
-
});
|
|
25
|
-
|
|
18
|
+
|
|
19
|
+
client = createTestClient();
|
|
26
20
|
await client.connect();
|
|
27
21
|
});
|
|
28
22
|
|
|
@@ -106,10 +100,7 @@ describe('Claude Code Edge Cases', () => {
|
|
|
106
100
|
describe('Error Recovery', () => {
|
|
107
101
|
it('should handle Claude CLI not found gracefully', async () => {
|
|
108
102
|
// Create a client with a different binary name that doesn't exist
|
|
109
|
-
const errorClient =
|
|
110
|
-
MCP_CLAUDE_DEBUG: 'true',
|
|
111
|
-
CLAUDE_CLI_NAME: 'non-existent-claude',
|
|
112
|
-
});
|
|
103
|
+
const errorClient = createTestClient({ claudeCliName: 'non-existent-claude' });
|
|
113
104
|
await errorClient.connect();
|
|
114
105
|
|
|
115
106
|
await expect(
|
|
@@ -126,4 +126,34 @@ export class MCPTestClient extends EventEmitter {
|
|
|
126
126
|
const response = await this.sendRequest('tools/list');
|
|
127
127
|
return response.result?.tools || [];
|
|
128
128
|
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Default server path
|
|
133
|
+
*/
|
|
134
|
+
const DEFAULT_SERVER_PATH = 'dist/server.js';
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Create a test client with standard configuration
|
|
138
|
+
* Automatically unsets VITEST env so the server actually starts
|
|
139
|
+
*/
|
|
140
|
+
export function createTestClient(options: {
|
|
141
|
+
serverPath?: string;
|
|
142
|
+
claudeCliName?: string;
|
|
143
|
+
debug?: boolean;
|
|
144
|
+
env?: Record<string, string>;
|
|
145
|
+
} = {}): MCPTestClient {
|
|
146
|
+
const {
|
|
147
|
+
serverPath = DEFAULT_SERVER_PATH,
|
|
148
|
+
claudeCliName = '/tmp/claude-code-test-mock/claudeMocked',
|
|
149
|
+
debug = true,
|
|
150
|
+
env = {},
|
|
151
|
+
} = options;
|
|
152
|
+
|
|
153
|
+
return new MCPTestClient(serverPath, {
|
|
154
|
+
VITEST: '', // Unset so server starts
|
|
155
|
+
MCP_CLAUDE_DEBUG: debug ? 'true' : '',
|
|
156
|
+
CLAUDE_CLI_NAME: claudeCliName,
|
|
157
|
+
...env,
|
|
158
|
+
});
|
|
129
159
|
}
|
|
@@ -2,30 +2,25 @@ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
|
2
2
|
import { mkdtempSync, rmSync } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
|
-
import { MCPTestClient } from './utils/mcp-client.js';
|
|
5
|
+
import { createTestClient, MCPTestClient } from './utils/mcp-client.js';
|
|
6
6
|
import { getSharedMock } from './utils/persistent-mock.js';
|
|
7
7
|
|
|
8
8
|
describe('Version Print on First Use', () => {
|
|
9
9
|
let client: MCPTestClient;
|
|
10
10
|
let testDir: string;
|
|
11
11
|
let consoleErrorSpy: any;
|
|
12
|
-
const serverPath = 'dist/server.js';
|
|
13
12
|
|
|
14
13
|
beforeEach(async () => {
|
|
15
14
|
// Ensure mock exists
|
|
16
15
|
await getSharedMock();
|
|
17
|
-
|
|
16
|
+
|
|
18
17
|
// Create a temporary directory for test files
|
|
19
18
|
testDir = mkdtempSync(join(tmpdir(), 'claude-code-test-'));
|
|
20
|
-
|
|
19
|
+
|
|
21
20
|
// Spy on console.error
|
|
22
21
|
consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
client = new MCPTestClient(serverPath, {
|
|
26
|
-
CLAUDE_CLI_NAME: '/tmp/claude-code-test-mock/claudeMocked',
|
|
27
|
-
});
|
|
28
|
-
|
|
22
|
+
|
|
23
|
+
client = createTestClient({ debug: false });
|
|
29
24
|
await client.connect();
|
|
30
25
|
});
|
|
31
26
|
|
package/src/server.ts
CHANGED
|
@@ -12,7 +12,6 @@ import { spawn, ChildProcess } from 'node:child_process';
|
|
|
12
12
|
import { existsSync, readFileSync } from 'node:fs';
|
|
13
13
|
import { homedir } from 'node:os';
|
|
14
14
|
import { join, resolve as pathResolve } from 'node:path';
|
|
15
|
-
import { fileURLToPath } from 'node:url';
|
|
16
15
|
import * as path from 'path';
|
|
17
16
|
import { parseCodexOutput, parseClaudeOutput, parseGeminiOutput } from './parsers.js';
|
|
18
17
|
|
|
@@ -917,9 +916,8 @@ export class ClaudeCodeServer {
|
|
|
917
916
|
}
|
|
918
917
|
}
|
|
919
918
|
|
|
920
|
-
// Create and run the server
|
|
921
|
-
|
|
922
|
-
if (process.argv[1] === __filename) {
|
|
919
|
+
// Create and run the server (skip during tests)
|
|
920
|
+
if (!process.env.VITEST) {
|
|
923
921
|
const server = new ClaudeCodeServer();
|
|
924
922
|
server.run().catch(console.error);
|
|
925
923
|
}
|