test(windows): add stdio fixtures
This commit is contained in:
parent
51b3ae1303
commit
02d27423a8
63
tests/fixtures/stdio-filesystem-server.mjs
vendored
Normal file
63
tests/fixtures/stdio-filesystem-server.mjs
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import process from 'node:process';
|
||||
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
||||
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
||||
import { z } from 'zod';
|
||||
|
||||
const rootDir = path.resolve(process.argv[2] ?? process.cwd());
|
||||
|
||||
const server = new McpServer({ name: 'fs-fixture', version: '1.0.0' });
|
||||
|
||||
server.registerTool(
|
||||
'list_files',
|
||||
{
|
||||
title: 'List Files',
|
||||
description: 'List the files in the configured root',
|
||||
inputSchema: {},
|
||||
outputSchema: {
|
||||
files: z.array(z.string()),
|
||||
},
|
||||
},
|
||||
async () => {
|
||||
const entries = await fs.readdir(rootDir);
|
||||
return {
|
||||
content: [{ type: 'text', text: entries.join('\n') }],
|
||||
structuredContent: { files: entries },
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
server.registerTool(
|
||||
'read_text_file',
|
||||
{
|
||||
title: 'Read Text File',
|
||||
description: 'Read a UTF-8 file relative to the MCP root',
|
||||
inputSchema: {
|
||||
path: z.string().describe('Relative path inside the root directory'),
|
||||
},
|
||||
outputSchema: {
|
||||
contents: z.string(),
|
||||
},
|
||||
},
|
||||
async ({ path: relativePath }) => {
|
||||
const targetPath = path.resolve(rootDir, relativePath);
|
||||
if (!targetPath.startsWith(rootDir)) {
|
||||
throw new Error('path escapes configured root');
|
||||
}
|
||||
const data = await fs.readFile(targetPath, 'utf8');
|
||||
return {
|
||||
content: [{ type: 'text', text: data }],
|
||||
structuredContent: { contents: data },
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const transport = new StdioServerTransport();
|
||||
await server.connect(transport);
|
||||
await new Promise((resolve, reject) => {
|
||||
transport.onclose = resolve;
|
||||
transport.onerror = reject;
|
||||
});
|
||||
58
tests/fixtures/stdio-memory-server.mjs
vendored
Normal file
58
tests/fixtures/stdio-memory-server.mjs
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
||||
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
||||
import { z } from 'zod';
|
||||
|
||||
const server = new McpServer({ name: 'memory-fixture', version: '1.0.0' });
|
||||
const memory = new Set();
|
||||
|
||||
server.registerTool(
|
||||
'create_entities',
|
||||
{
|
||||
title: 'Create Entities',
|
||||
description: 'Insert the provided entity names into the in-memory store',
|
||||
inputSchema: {
|
||||
entities: z.array(z.string()),
|
||||
},
|
||||
outputSchema: {
|
||||
count: z.number(),
|
||||
},
|
||||
},
|
||||
async ({ entities }) => {
|
||||
for (const entity of entities) {
|
||||
if (entity.trim().length > 0) {
|
||||
memory.add(entity.trim());
|
||||
}
|
||||
}
|
||||
return {
|
||||
content: [{ type: 'text', text: `Stored ${memory.size} entities` }],
|
||||
structuredContent: { count: memory.size },
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
server.registerTool(
|
||||
'list_entities',
|
||||
{
|
||||
title: 'List Entities',
|
||||
description: 'Return all previously stored entities',
|
||||
inputSchema: {},
|
||||
outputSchema: {
|
||||
entities: z.array(z.string()),
|
||||
},
|
||||
},
|
||||
async () => {
|
||||
return {
|
||||
content: [{ type: 'text', text: JSON.stringify(Array.from(memory)) }],
|
||||
structuredContent: { entities: Array.from(memory) },
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const transport = new StdioServerTransport();
|
||||
await server.connect(transport);
|
||||
await new Promise((resolve, reject) => {
|
||||
transport.onclose = resolve;
|
||||
transport.onerror = reject;
|
||||
});
|
||||
@ -2,6 +2,7 @@ import { execFile } from 'node:child_process';
|
||||
import fs from 'node:fs/promises';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import process from 'node:process';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
||||
|
||||
@ -48,6 +49,9 @@ describe('stdio MCP servers (filesystem + memory)', () => {
|
||||
let configPath: string;
|
||||
let fsRoot: string;
|
||||
|
||||
const filesystemServerScript = fileURLToPath(new URL('./fixtures/stdio-filesystem-server.mjs', import.meta.url));
|
||||
const memoryServerScript = fileURLToPath(new URL('./fixtures/stdio-memory-server.mjs', import.meta.url));
|
||||
|
||||
beforeAll(async () => {
|
||||
await ensureDistBuilt();
|
||||
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'mcporter-stdio-e2e-'));
|
||||
@ -62,13 +66,13 @@ describe('stdio MCP servers (filesystem + memory)', () => {
|
||||
mcpServers: {
|
||||
'fs-test': {
|
||||
description: 'Filesystem MCP for stdio e2e tests',
|
||||
command: 'npx',
|
||||
args: ['-y', '@modelcontextprotocol/server-filesystem', fsRoot],
|
||||
command: process.execPath,
|
||||
args: [filesystemServerScript, fsRoot],
|
||||
},
|
||||
'memory-test': {
|
||||
description: 'Knowledge graph MCP for stdio e2e tests',
|
||||
command: 'npx',
|
||||
args: ['-y', '@modelcontextprotocol/server-memory'],
|
||||
command: process.execPath,
|
||||
args: [memoryServerScript],
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -83,14 +87,12 @@ describe('stdio MCP servers (filesystem + memory)', () => {
|
||||
await fs.rm(tempDir, { recursive: true, force: true }).catch(() => {});
|
||||
});
|
||||
|
||||
it(
|
||||
'lists filesystem tools and reads files via stdio MCP',
|
||||
async () => {
|
||||
const listResult = await runCli(['list', 'fs-test'], configPath);
|
||||
expect(listResult.stdout).toContain('Filesystem MCP for stdio e2e tests');
|
||||
const callResult = await runCli(
|
||||
[
|
||||
'call',
|
||||
it('lists filesystem tools and reads files via stdio MCP', async () => {
|
||||
const listResult = await runCli(['list', 'fs-test'], configPath);
|
||||
expect(listResult.stdout).toContain('Filesystem MCP for stdio e2e tests');
|
||||
const callResult = await runCli(
|
||||
[
|
||||
'call',
|
||||
'fs-test.read_text_file',
|
||||
'--output',
|
||||
'json',
|
||||
@ -98,11 +100,9 @@ describe('stdio MCP servers (filesystem + memory)', () => {
|
||||
JSON.stringify({ path: path.join(fsRoot, 'hello.txt') }),
|
||||
],
|
||||
configPath
|
||||
);
|
||||
expect(callResult.stdout).toContain('hello from stdio mcp');
|
||||
},
|
||||
20000
|
||||
);
|
||||
);
|
||||
expect(callResult.stdout).toContain('hello from stdio mcp');
|
||||
}, 20000);
|
||||
|
||||
const memoryTest = process.platform === 'win32' ? it.skip : it;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user