fix(mcp): fix .mcp.json, timeouts, txt outline, subprocess leaks, version pin, proxy stripping#2066
fix(mcp): fix .mcp.json, timeouts, txt outline, subprocess leaks, version pin, proxy stripping#2066thedotmack wants to merge 1 commit intomainfrom
Conversation
…sion pin, proxy stripping - Fix #1921: Populate root .mcp.json with mcp-search server declaration so Claude Code can discover the MCP server - Fix #1922: Add explicit timeoutMs to corpus operations (60s for prime/query/reprime, 120s for build/rebuild) instead of using the 3s health-check default - Fix #1923: Add fallback outline for files without tree-sitter grammar (e.g., .txt) that returns section headers found by scanning for Markdown #, ALL-CAPS lines, and colon-terminated lines - Fix #1924: Add shutdownSync() method to ChromaMcpManager and register process 'exit' handler to kill chroma-mcp subprocess on abrupt worker exit - Fix #1925: Save reference to stale transport/client before nulling and close them properly in callTool() error path to prevent subprocess leaks - Fix #1926: Pin chroma-mcp to version 0.2.3 in uvx command args to prevent stdio handshake breakage from incompatible upstream releases - Fix #1927: Strip ALL_PROXY, HTTP_PROXY, HTTPS_PROXY, NO_PROXY (and lowercase variants) from chroma-mcp subprocess environment to prevent SOCKS5 interference Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 4 minutes and 54 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Code ReviewGood set of targeted bug fixes addressing real operational issues. Overall the changes are well-scoped. A few things worth discussing:
|
| Area | Status |
|---|---|
.mcp.json registration |
✅ Correct, needs env-var resilience check |
| Timeout plumbing | ✅ Clean, suggest named constants |
| Fallback outline | ✅ Useful, heuristics could be tightened |
| Transport leak fix | ✅ Correct ordering |
shutdownSync / exit handler |
✅ Works, fragile SDK cast worth documenting |
| Version pinning | ✅ Correct, extract to constant |
| Proxy stripping | ✅ Well-justified |
The core logic is sound — these are mostly polish/robustness suggestions. The subprocess leak fix and proxy stripping in particular look correct and well-reasoned.
Greptile SummaryThis PR addresses seven bug fixes: registering the mcp-search server in Confidence Score: 5/5Safe to merge — all remaining findings are P2 style/robustness suggestions that do not block correctness. No P0 or P1 issues found. The three P2 comments cover: a fragile private-API cast consistent with existing code, a fixed token estimate that matches prior behavior, and a missing env-var fallback in the MCP config. None cause incorrect behavior today. .mcp.json warrants a quick sanity-check that CLAUDE_PLUGIN_ROOT is reliably set in all deployment scenarios before this ships. Important Files Changed
Sequence DiagramsequenceDiagram
participant Worker as Worker Process
participant MCP as mcp-server.ts
participant CM as ChromaMcpManager
participant Chroma as chroma-mcp subprocess
MCP->>CM: callTool(toolName, args)
CM->>Chroma: stdio request
alt Transport error (#1925 fix)
Chroma-->>CM: error
CM->>CM: save staleTransport / staleClient
CM->>CM: null this.transport / this.client
CM->>CM: staleTransport.close()
CM->>CM: staleClient.close()
CM->>Chroma: reconnect + retry
end
Note over Worker,Chroma: On process 'exit' (#1924 fix)
Worker->>CM: shutdownSync()
CM->>Chroma: SIGKILL(_process)
Note over MCP: Corpus ops use per-op timeouts (#1922 fix)
MCP->>MCP: corpus/create → 120s
MCP->>MCP: corpus/prime → 60s
MCP->>MCP: corpus/query → 60s
MCP->>MCP: corpus/rebuild → 120s
Reviews (1): Last reviewed commit: "fix(mcp): fix .mcp.json, timeouts, txt o..." | Re-trigger Greptile |
| const transportRef = this.transport as unknown as { _process?: import('child_process').ChildProcess } | null; | ||
| const childProcess = transportRef?._process; |
There was a problem hiding this comment.
Fragile private-API cast for
_process
_process is not part of StdioClientTransport's public contract — it's an internal property accessed via as unknown as { _process? }. If a future version of @modelcontextprotocol/sdk renames or removes this field, shutdownSync will silently become a no-op (no error, no kill, orphaned subprocess). The same cast already exists at line 505 for registerManagedProcess, so this is consistent with the existing pattern, but consider adding a fallback sentinel so any silent failures surface in logs:
if (!childProcess) {
logger.warn('CHROMA_MCP', 'shutdownSync: _process not available on transport (MCP SDK may have changed)');
}| return { | ||
| filePath, language, symbols: [], imports: [], | ||
| filePath, language, symbols: fallbackSymbols, imports: [], | ||
| totalLines: lines.length, foldedTokenEstimate: 50, | ||
| }; |
There was a problem hiding this comment.
foldedTokenEstimate ignores actual symbol count
The fallback path returns a hardcoded foldedTokenEstimate: 50 regardless of how many sections were detected. For a large .txt or configuration file with many headers, this underestimates the folded view and can throw off token-budget calculations downstream. The old parseFilesBatch code also used 50, so this is not a regression — but now that parseFile is called directly, computing an estimate from fallbackSymbols.length would be more accurate at almost no extra cost.
| return { | |
| filePath, language, symbols: [], imports: [], | |
| filePath, language, symbols: fallbackSymbols, imports: [], | |
| totalLines: lines.length, foldedTokenEstimate: 50, | |
| }; | |
| return { | |
| filePath, language, symbols: fallbackSymbols, imports: [], | |
| totalLines: lines.length, | |
| foldedTokenEstimate: Math.max(50, fallbackSymbols.length * 10), | |
| }; |
| "mcpServers": { | ||
| "mcp-search": { | ||
| "type": "stdio", | ||
| "command": "bun", |
There was a problem hiding this comment.
No fallback if
CLAUDE_PLUGIN_ROOT is unset
"${CLAUDE_PLUGIN_ROOT}/scripts/mcp-server.cjs" relies on Claude Code expanding the env var at load time. Every shell command in hooks.json has an explicit fallback chain ([ -z "$_R" ] && _R=$(ls -dt ...)) for the case where CLAUDE_PLUGIN_ROOT isn't populated. This MCP entry has no equivalent fallback, so if the variable is absent the literal string is passed as the executable path and the MCP server silently fails to start. Documenting the requirement or adding a wrapper script with fallback logic (matching the hooks pattern) would make the registration more robust.
…s env sanitizeEnv() currently strips only Claude Code internal vars. Secrets from the surrounding shell (AWS keys, GitHub tokens, npm auth, OpenAI / Anthropic API keys, etc.) are inherited by every MCP subprocess spawned via StdioClientTransport, including uvx chroma-mcp. This is a defence-in-depth gap: chroma-mcp is resolved at runtime from PyPI by uvx with no version pin declared in any project manifest (see also thedotmack#1926 / thedotmack#2066). A future compromised release of chroma-mcp or one of its transitive deps would have immediate read access to every credential in the user's shell. - Adds ENV_SECRET_PREFIXES (AWS_, GITHUB_, GH_, NPM_, OPENAI_, ANTHROPIC_, HF_, DD_, etc.) and ENV_SECRET_SUFFIXES (_TOKEN, _API_KEY, _SECRET, _PASSWORD, _PRIVATE_KEY, _CREDENTIAL, ...). - Existing ENV_PRESERVE allowlist still wins, so CLAUDE_CODE_OAUTH_TOKEN passes through unchanged. - CLAUDE_MEM_ENV_INHERIT_UNSAFE=1 escape hatch for users who need a specific secret to reach the subprocess. - 9 new tests covering AWS, GitHub, npm, LLM provider keys, suffix stripping, escape hatch, and allowlist priority. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Closing to start fresh from main — will redo fixes isolated in Docker container. |
Summary
Test plan
Closes #1921, closes #1922, closes #1923, closes #1924, closes #1925, closes #1926, closes #1927
🤖 Generated with Claude Code