argusai-mcp 0.1.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/dist/formatters/result-formatter.d.ts +44 -0
- package/dist/formatters/result-formatter.d.ts.map +1 -0
- package/dist/formatters/result-formatter.js +162 -0
- package/dist/formatters/result-formatter.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +90 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +34 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +184 -0
- package/dist/server.js.map +1 -0
- package/dist/session.d.ts +93 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +220 -0
- package/dist/session.js.map +1 -0
- package/dist/tools/build.d.ts +31 -0
- package/dist/tools/build.d.ts.map +1 -0
- package/dist/tools/build.js +110 -0
- package/dist/tools/build.js.map +1 -0
- package/dist/tools/clean.d.ts +40 -0
- package/dist/tools/clean.d.ts.map +1 -0
- package/dist/tools/clean.js +111 -0
- package/dist/tools/clean.js.map +1 -0
- package/dist/tools/init.d.ts +41 -0
- package/dist/tools/init.d.ts.map +1 -0
- package/dist/tools/init.js +96 -0
- package/dist/tools/init.js.map +1 -0
- package/dist/tools/logs.d.ts +28 -0
- package/dist/tools/logs.d.ts.map +1 -0
- package/dist/tools/logs.js +35 -0
- package/dist/tools/logs.js.map +1 -0
- package/dist/tools/mock-requests.d.ts +36 -0
- package/dist/tools/mock-requests.d.ts.map +1 -0
- package/dist/tools/mock-requests.js +62 -0
- package/dist/tools/mock-requests.js.map +1 -0
- package/dist/tools/run.d.ts +58 -0
- package/dist/tools/run.d.ts.map +1 -0
- package/dist/tools/run.js +190 -0
- package/dist/tools/run.js.map +1 -0
- package/dist/tools/setup.d.ts +47 -0
- package/dist/tools/setup.d.ts.map +1 -0
- package/dist/tools/setup.js +162 -0
- package/dist/tools/setup.js.map +1 -0
- package/dist/tools/status.d.ts +44 -0
- package/dist/tools/status.d.ts.map +1 -0
- package/dist/tools/status.js +79 -0
- package/dist/tools/status.js.map +1 -0
- package/dist/transports/http-transport.d.ts +41 -0
- package/dist/transports/http-transport.d.ts.map +1 -0
- package/dist/transports/http-transport.js +107 -0
- package/dist/transports/http-transport.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module tools/setup
|
|
3
|
+
* argus_setup — Start the test environment.
|
|
4
|
+
*
|
|
5
|
+
* Uses MultiServiceOrchestrator for config normalization and dependency
|
|
6
|
+
* ordering, while keeping Docker calls at this level for testability.
|
|
7
|
+
*/
|
|
8
|
+
import { ensureNetwork, startContainer, waitForHealthy, createMockServer, isPortInUse, parseTime, MultiServiceOrchestrator, } from 'argusai-core';
|
|
9
|
+
import { SessionError } from '../session.js';
|
|
10
|
+
function parsePorts(ports) {
|
|
11
|
+
return ports.map(p => {
|
|
12
|
+
const parts = p.split(':');
|
|
13
|
+
return {
|
|
14
|
+
host: parseInt(parts[0], 10),
|
|
15
|
+
container: parseInt(parts[1] ?? parts[0], 10),
|
|
16
|
+
};
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function buildHealthcheckCmd(svc) {
|
|
20
|
+
if (!svc.container.healthcheck)
|
|
21
|
+
return undefined;
|
|
22
|
+
return {
|
|
23
|
+
cmd: `wget -qO- http://localhost${svc.container.healthcheck.path} || exit 1`,
|
|
24
|
+
interval: svc.container.healthcheck.interval ?? '10s',
|
|
25
|
+
timeout: svc.container.healthcheck.timeout ?? '5s',
|
|
26
|
+
retries: svc.container.healthcheck.retries ?? 10,
|
|
27
|
+
startPeriod: svc.container.healthcheck.startPeriod ?? '30s',
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Handle the argus_setup MCP tool call.
|
|
32
|
+
* Creates Docker network, starts mock services and service containers,
|
|
33
|
+
* and waits for health checks in dependency order.
|
|
34
|
+
*
|
|
35
|
+
* @param params - Tool input with projectPath and optional health-check timeout override
|
|
36
|
+
* @param sessionManager - Session store for tracking project state
|
|
37
|
+
* @returns Setup results including network, service, and mock status
|
|
38
|
+
* @throws {SessionError} SESSION_NOT_FOUND if not initialized, PORT_CONFLICT on occupied ports
|
|
39
|
+
*/
|
|
40
|
+
export async function handleSetup(params, sessionManager) {
|
|
41
|
+
const session = sessionManager.getOrThrow(params.projectPath);
|
|
42
|
+
const config = session.config;
|
|
43
|
+
const totalStart = Date.now();
|
|
44
|
+
const healthTimeout = params.timeout ? parseTime(params.timeout) : 120_000;
|
|
45
|
+
const bus = sessionManager.eventBus;
|
|
46
|
+
const ts = () => Date.now();
|
|
47
|
+
bus?.emit('activity', {
|
|
48
|
+
event: 'activity_start',
|
|
49
|
+
data: { id: `setup-${totalStart}`, source: 'ai', operation: 'setup', project: config.project.name, status: 'running', startTime: totalStart },
|
|
50
|
+
});
|
|
51
|
+
bus?.emit('setup', { event: 'setup_start', data: { type: 'setup_start', project: config.project.name, timestamp: ts() } });
|
|
52
|
+
const orchestrator = new MultiServiceOrchestrator();
|
|
53
|
+
const services = orchestrator.normalizeServices(config);
|
|
54
|
+
const orderedServices = services.length > 0
|
|
55
|
+
? orchestrator.topologicalSort(services)
|
|
56
|
+
: [];
|
|
57
|
+
// Create Docker network
|
|
58
|
+
let networkCreated = false;
|
|
59
|
+
try {
|
|
60
|
+
await ensureNetwork(session.networkName);
|
|
61
|
+
networkCreated = true;
|
|
62
|
+
bus?.emit('setup', { event: 'network_created', data: { type: 'network_created', name: session.networkName, timestamp: ts() } });
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// Network may already exist
|
|
66
|
+
}
|
|
67
|
+
// Start mock services
|
|
68
|
+
const mockResults = [];
|
|
69
|
+
if (config.mocks) {
|
|
70
|
+
for (const [name, mockConfig] of Object.entries(config.mocks)) {
|
|
71
|
+
const mc = mockConfig;
|
|
72
|
+
try {
|
|
73
|
+
const portInUse = await isPortInUse(mc.port);
|
|
74
|
+
if (portInUse) {
|
|
75
|
+
throw new SessionError('PORT_CONFLICT', `Port ${mc.port} is already in use for mock "${name}"`);
|
|
76
|
+
}
|
|
77
|
+
bus?.emit('setup', { event: 'mock_starting', data: { type: 'mock_starting', name, port: mc.port, timestamp: ts() } });
|
|
78
|
+
const mockServer = createMockServer(mc);
|
|
79
|
+
await mockServer.listen({ port: mc.port, host: '0.0.0.0' });
|
|
80
|
+
session.mockServers.set(name, { server: mockServer, port: mc.port });
|
|
81
|
+
bus?.emit('setup', { event: 'mock_started', data: { type: 'mock_started', name, port: mc.port, timestamp: ts() } });
|
|
82
|
+
mockResults.push({
|
|
83
|
+
name,
|
|
84
|
+
port: mc.port,
|
|
85
|
+
status: 'running',
|
|
86
|
+
routeCount: mc.routes?.length ?? 0,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
if (err instanceof SessionError)
|
|
91
|
+
throw err;
|
|
92
|
+
mockResults.push({
|
|
93
|
+
name,
|
|
94
|
+
port: mc.port,
|
|
95
|
+
status: 'failed',
|
|
96
|
+
routeCount: mc.routes?.length ?? 0,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Start service containers in dependency order
|
|
102
|
+
const serviceResults = [];
|
|
103
|
+
for (const svc of orderedServices) {
|
|
104
|
+
try {
|
|
105
|
+
bus?.emit('setup', { event: 'service_starting', data: { type: 'service_starting', name: svc.name, image: svc.build.image, timestamp: ts() } });
|
|
106
|
+
const containerId = await startContainer({
|
|
107
|
+
name: svc.container.name,
|
|
108
|
+
image: svc.build.image,
|
|
109
|
+
ports: svc.container.ports,
|
|
110
|
+
environment: svc.container.environment,
|
|
111
|
+
volumes: svc.container.volumes,
|
|
112
|
+
network: session.networkName,
|
|
113
|
+
healthcheck: buildHealthcheckCmd(svc),
|
|
114
|
+
});
|
|
115
|
+
session.containerIds.set(svc.container.name, containerId);
|
|
116
|
+
let status = 'running';
|
|
117
|
+
let healthCheckDuration;
|
|
118
|
+
if (svc.container.healthcheck) {
|
|
119
|
+
const hcStart = Date.now();
|
|
120
|
+
const isHealthy = await waitForHealthy(svc.container.name, healthTimeout);
|
|
121
|
+
healthCheckDuration = Date.now() - hcStart;
|
|
122
|
+
status = isHealthy ? 'healthy' : 'unhealthy';
|
|
123
|
+
if (isHealthy) {
|
|
124
|
+
bus?.emit('setup', { event: 'service_healthy', data: { type: 'service_healthy', name: svc.name, duration: healthCheckDuration, timestamp: ts() } });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
serviceResults.push({
|
|
128
|
+
name: svc.name,
|
|
129
|
+
containerId,
|
|
130
|
+
status,
|
|
131
|
+
ports: parsePorts(svc.container.ports),
|
|
132
|
+
healthCheckDuration,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
serviceResults.push({
|
|
137
|
+
name: svc.name,
|
|
138
|
+
containerId: '',
|
|
139
|
+
status: 'failed',
|
|
140
|
+
ports: parsePorts(svc.container.ports),
|
|
141
|
+
error: err instanceof Error ? err.message : String(err),
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const allHealthy = serviceResults.every(s => s.status !== 'failed' && s.status !== 'unhealthy');
|
|
146
|
+
if (allHealthy && serviceResults.length > 0) {
|
|
147
|
+
sessionManager.transition(params.projectPath, 'running');
|
|
148
|
+
}
|
|
149
|
+
const totalDuration = Date.now() - totalStart;
|
|
150
|
+
bus?.emit('setup', { event: 'setup_end', data: { type: 'setup_end', duration: totalDuration, success: allHealthy, timestamp: ts() } });
|
|
151
|
+
bus?.emit('activity', {
|
|
152
|
+
event: 'activity_update',
|
|
153
|
+
data: { id: `setup-${totalStart}`, source: 'ai', operation: 'setup', project: config.project.name, status: allHealthy ? 'success' : 'failed', startTime: totalStart, endTime: Date.now() },
|
|
154
|
+
});
|
|
155
|
+
return {
|
|
156
|
+
network: { name: session.networkName, created: networkCreated },
|
|
157
|
+
services: serviceResults,
|
|
158
|
+
mocks: mockResults,
|
|
159
|
+
totalDuration,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/tools/setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module tools/status
|
|
3
|
+
* argus_status — Get current status of all managed resources.
|
|
4
|
+
*/
|
|
5
|
+
import { type ContainerStatus } from 'argusai-core';
|
|
6
|
+
import { SessionManager } from '../session.js';
|
|
7
|
+
export interface StatusResult {
|
|
8
|
+
state: 'initialized' | 'built' | 'running' | 'stopped';
|
|
9
|
+
network: {
|
|
10
|
+
name: string;
|
|
11
|
+
exists: boolean;
|
|
12
|
+
};
|
|
13
|
+
services: Array<{
|
|
14
|
+
name: string;
|
|
15
|
+
containerId?: string;
|
|
16
|
+
status: ContainerStatus;
|
|
17
|
+
ports: Array<{
|
|
18
|
+
host: number;
|
|
19
|
+
container: number;
|
|
20
|
+
accessible: boolean;
|
|
21
|
+
}>;
|
|
22
|
+
health?: 'healthy' | 'unhealthy' | 'starting' | 'none';
|
|
23
|
+
uptime?: number;
|
|
24
|
+
}>;
|
|
25
|
+
mocks: Array<{
|
|
26
|
+
name: string;
|
|
27
|
+
port: number;
|
|
28
|
+
status: 'running' | 'stopped';
|
|
29
|
+
requestCount: number;
|
|
30
|
+
}>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Handle the argus_status MCP tool call.
|
|
34
|
+
* Queries live status of containers, network, and mock services.
|
|
35
|
+
*
|
|
36
|
+
* @param params - Tool input with projectPath
|
|
37
|
+
* @param sessionManager - Session store for tracking project state
|
|
38
|
+
* @returns Current status of all managed resources
|
|
39
|
+
* @throws {SessionError} SESSION_NOT_FOUND if not initialized
|
|
40
|
+
*/
|
|
41
|
+
export declare function handleStatus(params: {
|
|
42
|
+
projectPath: string;
|
|
43
|
+
}, sessionManager: SessionManager): Promise<StatusResult>;
|
|
44
|
+
//# sourceMappingURL=status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/tools/status.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,aAAa,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IACvD,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IAC3C,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,EAAE,eAAe,CAAC;QACxB,KAAK,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,OAAO,CAAA;SAAE,CAAC,CAAC;QACvE,MAAM,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;QACvD,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;IACH,KAAK,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;QAC9B,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;CACJ;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,EAC/B,cAAc,EAAE,cAAc,GAC7B,OAAO,CAAC,YAAY,CAAC,CAoEvB"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module tools/status
|
|
3
|
+
* argus_status — Get current status of all managed resources.
|
|
4
|
+
*/
|
|
5
|
+
import { getContainerStatus, isPortInUse, } from 'argusai-core';
|
|
6
|
+
/**
|
|
7
|
+
* Handle the argus_status MCP tool call.
|
|
8
|
+
* Queries live status of containers, network, and mock services.
|
|
9
|
+
*
|
|
10
|
+
* @param params - Tool input with projectPath
|
|
11
|
+
* @param sessionManager - Session store for tracking project state
|
|
12
|
+
* @returns Current status of all managed resources
|
|
13
|
+
* @throws {SessionError} SESSION_NOT_FOUND if not initialized
|
|
14
|
+
*/
|
|
15
|
+
export async function handleStatus(params, sessionManager) {
|
|
16
|
+
const session = sessionManager.getOrThrow(params.projectPath);
|
|
17
|
+
// Check network
|
|
18
|
+
let networkExists = false;
|
|
19
|
+
try {
|
|
20
|
+
const { execFileSync } = await import('node:child_process');
|
|
21
|
+
const result = execFileSync('docker', ['network', 'inspect', session.networkName], {
|
|
22
|
+
encoding: 'utf-8',
|
|
23
|
+
timeout: 5000,
|
|
24
|
+
});
|
|
25
|
+
networkExists = result.length > 0;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
networkExists = false;
|
|
29
|
+
}
|
|
30
|
+
// Check containers
|
|
31
|
+
const services = [];
|
|
32
|
+
for (const [name, containerId] of session.containerIds) {
|
|
33
|
+
const containerStatus = await getContainerStatus(name);
|
|
34
|
+
const config = session.config;
|
|
35
|
+
const svcConfig = config.services?.find(s => s.container.name === name)
|
|
36
|
+
?? (config.service?.container.name === name ? config.service : undefined);
|
|
37
|
+
const portMappings = [];
|
|
38
|
+
if (svcConfig) {
|
|
39
|
+
for (const portStr of svcConfig.container.ports) {
|
|
40
|
+
const parts = portStr.split(':');
|
|
41
|
+
const host = parseInt(parts[0], 10);
|
|
42
|
+
const container = parseInt(parts[1] ?? parts[0], 10);
|
|
43
|
+
const accessible = await isPortInUse(host);
|
|
44
|
+
portMappings.push({ host, container, accessible });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
services.push({
|
|
48
|
+
name,
|
|
49
|
+
containerId,
|
|
50
|
+
status: containerStatus,
|
|
51
|
+
ports: portMappings,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
// Check mocks
|
|
55
|
+
const mocks = [];
|
|
56
|
+
for (const [name, mockInfo] of session.mockServers) {
|
|
57
|
+
let requestCount = 0;
|
|
58
|
+
try {
|
|
59
|
+
const resp = await fetch(`http://localhost:${mockInfo.port}/_mock/requests`, {
|
|
60
|
+
signal: AbortSignal.timeout(2000),
|
|
61
|
+
});
|
|
62
|
+
if (resp.ok) {
|
|
63
|
+
const data = await resp.json();
|
|
64
|
+
requestCount = data.count;
|
|
65
|
+
}
|
|
66
|
+
mocks.push({ name, port: mockInfo.port, status: 'running', requestCount });
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
mocks.push({ name, port: mockInfo.port, status: 'stopped', requestCount: 0 });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
state: session.state,
|
|
74
|
+
network: { name: session.networkName, exists: networkExists },
|
|
75
|
+
services,
|
|
76
|
+
mocks,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/tools/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module transports/http-transport
|
|
3
|
+
* HTTP transport layer for the MCP server.
|
|
4
|
+
*
|
|
5
|
+
* Wraps MCP SDK's StreamableHTTPServerTransport with:
|
|
6
|
+
* - Standalone HTTP server (for `--mode http`)
|
|
7
|
+
* - Fastify route handler (for unified server integration)
|
|
8
|
+
* - Optional API key authentication
|
|
9
|
+
*/
|
|
10
|
+
import { type IncomingMessage, type ServerResponse } from 'node:http';
|
|
11
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
12
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
13
|
+
export interface HttpTransportOptions {
|
|
14
|
+
port: number;
|
|
15
|
+
host?: string;
|
|
16
|
+
/** Path for the MCP endpoint (default: /mcp) */
|
|
17
|
+
path?: string;
|
|
18
|
+
/** API key for authentication (optional; if set, requests must include Authorization: Bearer <key>) */
|
|
19
|
+
apiKey?: string;
|
|
20
|
+
/** Enable CORS headers */
|
|
21
|
+
cors?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Start a standalone HTTP server for the MCP transport.
|
|
25
|
+
* Used when running `preflight-mcp --mode http --port 3100`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function startHttpTransport(mcpServer: McpServer, options: HttpTransportOptions): Promise<{
|
|
28
|
+
transport: StreamableHTTPServerTransport;
|
|
29
|
+
close: () => Promise<void>;
|
|
30
|
+
}>;
|
|
31
|
+
/**
|
|
32
|
+
* Create a Fastify-compatible route handler for mounting MCP on an existing Fastify app.
|
|
33
|
+
* Used by the unified `preflight server` to share the Dashboard's HTTP port.
|
|
34
|
+
*/
|
|
35
|
+
export declare function createFastifyMcpHandler(mcpServer: McpServer, options?: {
|
|
36
|
+
apiKey?: string;
|
|
37
|
+
}): {
|
|
38
|
+
transport: StreamableHTTPServerTransport;
|
|
39
|
+
handler: (req: IncomingMessage, res: ServerResponse, body?: unknown) => Promise<void>;
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=http-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-transport.d.ts","sourceRoot":"","sources":["../../src/transports/http-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAoC,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAExG,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACnG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uGAAuG;IACvG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC;IAAE,SAAS,EAAE,6BAA6B,CAAC;IAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CAuEnF;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,SAAS,EACpB,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,SAAS,EAAE,6BAA6B,CAAC;IAAC,OAAO,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAmBrI"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module transports/http-transport
|
|
3
|
+
* HTTP transport layer for the MCP server.
|
|
4
|
+
*
|
|
5
|
+
* Wraps MCP SDK's StreamableHTTPServerTransport with:
|
|
6
|
+
* - Standalone HTTP server (for `--mode http`)
|
|
7
|
+
* - Fastify route handler (for unified server integration)
|
|
8
|
+
* - Optional API key authentication
|
|
9
|
+
*/
|
|
10
|
+
import { createServer as createHttpServer } from 'node:http';
|
|
11
|
+
import { randomUUID } from 'node:crypto';
|
|
12
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
13
|
+
/**
|
|
14
|
+
* Start a standalone HTTP server for the MCP transport.
|
|
15
|
+
* Used when running `preflight-mcp --mode http --port 3100`.
|
|
16
|
+
*/
|
|
17
|
+
export async function startHttpTransport(mcpServer, options) {
|
|
18
|
+
const mcpPath = options.path ?? '/mcp';
|
|
19
|
+
const host = options.host ?? '0.0.0.0';
|
|
20
|
+
const transport = new StreamableHTTPServerTransport({
|
|
21
|
+
sessionIdGenerator: () => randomUUID(),
|
|
22
|
+
});
|
|
23
|
+
await mcpServer.connect(transport);
|
|
24
|
+
const httpServer = createHttpServer(async (req, res) => {
|
|
25
|
+
// CORS preflight
|
|
26
|
+
if (options.cors) {
|
|
27
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
28
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
|
|
29
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, Mcp-Session-Id');
|
|
30
|
+
res.setHeader('Access-Control-Expose-Headers', 'Mcp-Session-Id');
|
|
31
|
+
if (req.method === 'OPTIONS') {
|
|
32
|
+
res.writeHead(204);
|
|
33
|
+
res.end();
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Auth check
|
|
38
|
+
if (options.apiKey) {
|
|
39
|
+
const authHeader = req.headers.authorization;
|
|
40
|
+
if (!authHeader || authHeader !== `Bearer ${options.apiKey}`) {
|
|
41
|
+
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
42
|
+
res.end(JSON.stringify({ error: 'Unauthorized', message: 'Invalid or missing API key' }));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const url = new URL(req.url ?? '/', `http://${host}:${options.port}`);
|
|
47
|
+
if (url.pathname === mcpPath) {
|
|
48
|
+
// Parse JSON body for POST
|
|
49
|
+
if (req.method === 'POST') {
|
|
50
|
+
const chunks = [];
|
|
51
|
+
for await (const chunk of req) {
|
|
52
|
+
chunks.push(chunk);
|
|
53
|
+
}
|
|
54
|
+
const body = JSON.parse(Buffer.concat(chunks).toString('utf-8'));
|
|
55
|
+
await transport.handleRequest(req, res, body);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
await transport.handleRequest(req, res);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else if (url.pathname === '/health') {
|
|
62
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
63
|
+
res.end(JSON.stringify({ status: 'ok', service: 'preflight-mcp', mode: 'http', sessionId: transport.sessionId }));
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
67
|
+
res.end(JSON.stringify({ error: 'Not found', availableEndpoints: [mcpPath, '/health'] }));
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
return new Promise((resolve, reject) => {
|
|
71
|
+
httpServer.listen(options.port, host, () => {
|
|
72
|
+
resolve({
|
|
73
|
+
transport,
|
|
74
|
+
close: async () => {
|
|
75
|
+
await transport.close();
|
|
76
|
+
return new Promise((res, rej) => {
|
|
77
|
+
httpServer.close((err) => err ? rej(err) : res());
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
httpServer.on('error', reject);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Create a Fastify-compatible route handler for mounting MCP on an existing Fastify app.
|
|
87
|
+
* Used by the unified `preflight server` to share the Dashboard's HTTP port.
|
|
88
|
+
*/
|
|
89
|
+
export function createFastifyMcpHandler(mcpServer, options) {
|
|
90
|
+
const transport = new StreamableHTTPServerTransport({
|
|
91
|
+
sessionIdGenerator: () => randomUUID(),
|
|
92
|
+
});
|
|
93
|
+
// Connect will be called by the caller after getting the transport
|
|
94
|
+
const handler = async (req, res, body) => {
|
|
95
|
+
if (options?.apiKey) {
|
|
96
|
+
const authHeader = req.headers.authorization;
|
|
97
|
+
if (!authHeader || authHeader !== `Bearer ${options.apiKey}`) {
|
|
98
|
+
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
99
|
+
res.end(JSON.stringify({ error: 'Unauthorized' }));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
await transport.handleRequest(req, res, body);
|
|
104
|
+
};
|
|
105
|
+
return { transport, handler };
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=http-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-transport.js","sourceRoot":"","sources":["../../src/transports/http-transport.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "argusai-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "ArgusAI MCP server — expose E2E testing tools to AI coding agents via Model Context Protocol",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/jeffkit/preflight.git",
|
|
10
|
+
"directory": "packages/mcp"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"argusai",
|
|
14
|
+
"mcp",
|
|
15
|
+
"ai",
|
|
16
|
+
"testing",
|
|
17
|
+
"model-context-protocol",
|
|
18
|
+
"cursor",
|
|
19
|
+
"claude"
|
|
20
|
+
],
|
|
21
|
+
"main": "dist/index.js",
|
|
22
|
+
"types": "dist/index.d.ts",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"import": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"bin": {
|
|
30
|
+
"argusai-mcp": "./dist/index.js"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist/",
|
|
34
|
+
"README.md"
|
|
35
|
+
],
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@modelcontextprotocol/sdk": "^1.11.0",
|
|
38
|
+
"zod": "^3.23.0",
|
|
39
|
+
"argusai-core": "0.1.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "^22.0.0",
|
|
43
|
+
"typescript": "^5.6.0",
|
|
44
|
+
"vitest": "^2.1.0"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "tsc",
|
|
48
|
+
"test": "vitest",
|
|
49
|
+
"test:run": "vitest run"
|
|
50
|
+
}
|
|
51
|
+
}
|