test(filesystem): add MCP SDK regression coverage for directory_tree (#3245)

* test(filesystem): add directory_tree MCP SDK regression coverage

* docs(filesystem): drop troubleshooting note from README
This commit is contained in:
Ryan Lopopolo 2026-08-27 19:17:32 -07:00 • committed by GitHub
commit 71e3cfbd1e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 60 additions and 1 deletions

View file

@ -0,0 +1,57 @@
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import * as fs from 'fs/promises';
import * as path from 'path';
import * as os from 'os';
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
describe('directory_tree MCP SDK regression', () => {
let client: Client;
let transport: StdioClientTransport;
let testDir: string;
beforeEach(async () => {
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), 'mcp-fs-tree-'));
testDir = await fs.realpath(tmp);
await fs.writeFile(path.join(testDir, 'root.txt'), 'root');
await fs.mkdir(path.join(testDir, 'nested'));
await fs.writeFile(path.join(testDir, 'nested', 'child.txt'), 'child');
const serverPath = path.resolve(__dirname, '../dist/index.js');
transport = new StdioClientTransport({
command: 'node',
args: [serverPath, testDir],
});
client = new Client(
{ name: 'directory-tree-regression-test', version: '1.0.0' },
{ capabilities: {} },
);
await client.connect(transport);
});
afterEach(async () => {
await client?.close();
await fs.rm(testDir, { recursive: true, force: true });
});
it('returns structuredContent.content as a string (not an array) when called via MCP SDK', async () => {
const result = await client.callTool({
name: 'directory_tree',
arguments: { path: testDir },
});
// Regression test for issues where structuredContent was returned as an array,
// which causes MCP SDK validation to throw -32602 (invalid structured content).
const structured = result.structuredContent as { content: unknown };
expect(structured).toBeDefined();
expect(typeof structured.content).toBe('string');
expect(Array.isArray(structured.content)).toBe(false);
const parsed = JSON.parse(structured.content as string);
expect(Array.isArray(parsed)).toBe(true);
expect(parsed.length).toBeGreaterThan(0);
});
});

View file

@ -22,7 +22,9 @@ describe('structuredContent schema compliance', () => {
beforeEach(async () => {
// Create a temp directory for testing
testDir = await fs.mkdtemp(path.join(os.tmpdir(), 'mcp-fs-test-'));
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'mcp-fs-test-'));
// macOS temp dirs may be symlinked (/var -> /private/var); resolve for server allowlist checks.
testDir = await fs.realpath(tmpDir);
// Create test files
await fs.writeFile(path.join(testDir, 'test.txt'), 'test content');