Files
claude-mem/tests/services/sync/chroma-mcp-manager-cwd.test.ts
T
Ousama Ben Younes c7c4fd54d6 fix: set cwd to homedir when spawning chroma-mcp to prevent pydantic .env.local crash (#1297)
chroma-mcp uses pydantic-settings which auto-reads .env/.env.local from
the CWD. When the project directory contains non-chroma variables (e.g.
CELERY_TASK_ALWAYS_EAGER), pydantic rejects them with "Extra inputs are
not permitted", crashing the subprocess and triggering a permanent
backoff loop. Passing cwd: os.homedir() to StdioClientTransport ensures
pydantic never reads project env files.

Generated by Claude Code
Vibe coded by ousamabenyounes

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-10 09:55:02 +00:00

54 lines
2.2 KiB
TypeScript

import { describe, it, expect, mock } from 'bun:test';
import os from 'os';
import { readFileSync } from 'fs';
import { join } from 'path';
/**
* Regression test for issue #1297.
*
* When the worker spawns chroma-mcp via StdioClientTransport, if the CWD is
* the project directory and that directory contains a .env.local file with
* non-chroma env vars, pydantic-settings crashes with "Extra inputs are not
* permitted". The fix is to set `cwd: os.homedir()` so pydantic never reads
* the project's env files.
*/
const CHROMA_MCP_MANAGER_PATH = join(
import.meta.dir, '..', '..', '..', 'src', 'services', 'sync', 'ChromaMcpManager.ts'
);
describe('ChromaMcpManager: cwd isolation from project .env files (#1297)', () => {
it('StdioClientTransport is constructed with cwd set to homedir', () => {
// Source-level assertion: verify the fix is present in the source.
// ChromaMcpManager uses StdioClientTransport (from @modelcontextprotocol/sdk),
// which we cannot easily import in a unit test without spawning a real process.
// A source inspection is the appropriate guardrail here.
const source = readFileSync(CHROMA_MCP_MANAGER_PATH, 'utf-8');
// The StdioClientTransport constructor call must include `cwd: os.homedir()`
// (or equivalent) so that pydantic-settings in chroma-mcp does not read
// .env.local from the project directory.
expect(source).toContain('cwd: os.homedir()');
});
it('the cwd property appears inside the StdioClientTransport constructor call', () => {
const source = readFileSync(CHROMA_MCP_MANAGER_PATH, 'utf-8');
// Locate the StdioClientTransport constructor block and verify cwd is in it.
const transportBlockMatch = source.match(
/new StdioClientTransport\(\s*\{([\s\S]*?)\}\s*\)/
);
expect(transportBlockMatch).not.toBeNull();
const constructorBody = transportBlockMatch![1];
expect(constructorBody).toContain('cwd');
expect(constructorBody).toContain('homedir');
});
it('os module is imported (required for os.homedir())', () => {
const source = readFileSync(CHROMA_MCP_MANAGER_PATH, 'utf-8');
// os is already imported in the original file — confirm it's still there
expect(source).toMatch(/import os from ['"]os['"]/);
});
});