Skip to content

fix(mcp): resolve sf CLI for quality hub and defect tools (B1/B2a)#151

Merged
mrdailey99 merged 3 commits into
developfrom
fix/sf-resolution-qualityhub
May 7, 2026
Merged

fix(mcp): resolve sf CLI for quality hub and defect tools (B1/B2a)#151
mrdailey99 merged 3 commits into
developfrom
fix/sf-resolution-qualityhub

Conversation

@mrdailey99
Copy link
Copy Markdown
Collaborator

@mrdailey99 mrdailey99 commented May 7, 2026

Summary

  • B2a: Added Windows standalone installer paths to getSfCommonPaths() — fixes SF_NOT_FOUND on systems using the official Salesforce CLI Windows installer (C:\Program Files\sf\bin\sf.cmd)
  • B1: Centralized sf resolution in sfSpawn.ts with 50 MB maxBuffer — prevents ENOBUFS on verbose Provar test runs for quality hub and defect tools
  • Architecture: Moved full sf resolution logic (two-phase PATH probe, needsWindowsShell, resolveSfExecutable, assertShellSafePath) from automationTools.ts into sfSpawn.ts; automationTools.ts re-exports helpers for backward compat
  • sf_path parameter: Added to all 6 quality hub tools and the defect create tool so users can point to a non-PATH sf executable directly

Root cause

provar_qualityhub_connect (and all quality hub / defect tools) called a stripped-down runSfCommand in sfSpawn.ts with no path probing, no maxBuffer, and no sf_path override. Meanwhile automationTools.ts had a full-featured version that was never shared.

Test plan

  • All 902 unit tests pass (yarn test:only)
  • 51/51 smoke tests pass (node scripts/mcp-smoke.cjs)
  • TypeScript clean (yarn compile)
  • New tests: sf_path threading for provar_qualityhub_connect and provar_qualityhub_display; SF_NOT_FOUND with explicit path on ENOENT; B2a Windows standalone paths in getSfCommonPaths
  • Manual: provar_qualityhub_connect without sf_path on Windows standalone installer auto-discovers; with explicit sf_path routes correctly

Notes for reviewers

  • docs/mcp.md should be updated to document the new sf_path parameter on quality hub tools — flagged for follow-up
  • No TOTAL_EXPECTED change in mcp-smoke.cjs — no new tools, only new optional params

Generated with Claude Code

…B2a)

RCA: qualityHubTools and defectTools used the simple sfSpawn runSfCommand with no maxBuffer, probing, or sf_path — causing SF_NOT_FOUND on Windows standalone installer path C:\Program Files\sf\bin\sf.cmd.

Fix: Elevate sfSpawn.ts to the central sf resolution module with 50 MB maxBuffer, two-phase PATH probe, Windows standalone installer paths in getSfCommonPaths, and sf_path param on all quality hub and defect tools.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 7, 2026 20:46
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 7, 2026

Quality Orchestrator

🟢 LOW · 8 / 100 · All changed files have mapped tests.


🧪 Tests to Run · Running 4 of 41 tests

  • unit/mcp/automationTools.test.ts
  • unit/mcp/defectTools.test.ts
  • unit/mcp/qualityHubTools.test.ts
  • unit/mcp/sfSpawn.test.ts
▶ Run command
npx playwright test \
  unit/mcp/automationTools.test.ts \
  unit/mcp/defectTools.test.ts \
  unit/mcp/qualityHubTools.test.ts \
  unit/mcp/sfSpawn.test.ts

⚡ quality-orchestrator  ·  @qo stub <file>  ·  @qo why?  ·  @qo run all

RCA: sfSpawn.ts was elevated to the central sf resolution module but had no dedicated test file, leaving 31 code paths (SfNotFoundError, soqlEscape, getSfCommonPaths, needsWindowsShell, runSfCommand probe logic, injection guard) uncovered by direct assertions.

Fix: Add test/unit/mcp/sfSpawn.test.ts covering all exported functions including two-phase probe, Windows shell injection guard, B2a standalone installer paths, and ENOENT handling.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes inconsistent Salesforce CLI (sf) resolution across MCP tools by centralizing discovery/spawn behavior in sfSpawn.ts, adding Windows standalone installer lookup paths, and threading an optional sf_path override through Quality Hub + defect tooling.

Changes:

  • Centralize sf discovery + spawning in src/mcp/tools/sfSpawn.ts, including a larger maxBuffer to avoid ENOBUFS.
  • Add Windows standalone installer locations to common sf path discovery.
  • Add optional sf_path to Quality Hub tools and the defect-create tool, and add/extend unit tests to cover the new behavior.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/mcp/tools/sfSpawn.ts Implements cached sf discovery, Windows shell handling, common-path fallback (incl. Windows installer), maxBuffer, and sf_path override support.
src/mcp/tools/automationTools.ts Removes duplicated sf resolution logic, uses runSfCommand from sfSpawn.ts, and re-exports helper APIs for backward compatibility.
src/mcp/tools/qualityHubTools.ts Adds sf_path input to all Quality Hub MCP tools and passes it into runSfCommand.
src/mcp/tools/defectTools.ts Adds sf_path input to defect-create tool and threads it through the internal sf calls.
test/unit/mcp/qualityHubTools.test.ts Adds tests for sf_path threading and getSfCommonPaths behavior.
test/unit/mcp/automationTools.test.ts Adds tests validating the new Windows standalone installer common paths via the (re-exported) helper.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/mcp/tools/sfSpawn.ts
Comment on lines +187 to +191
export function runSfCommand(args: string[], sfPath?: string): SpawnResult {
// Use explicit path if provided; otherwise use cached probe result
const executable = sfPath ?? resolveSfExecutable();
if (!executable) throw new SfNotFoundError();

Comment thread test/unit/mcp/qualityHubTools.test.ts Outdated
Comment on lines +449 to +453
paths.some((p) => p.includes('Program Files') && p.includes('sf') && p.includes('bin')),
'Expected C:\\Program Files\\sf\\bin\\sf.cmd in common paths'
);
assert.ok(
paths.some((p) => p.includes('Program Files') && p.includes('sf') && p.includes('client')),
RCA: Two issues flagged by Copilot review: (1) runSfCommand passed empty-string sfPath directly to spawnSync instead of falling through to auto-discovery, producing a misleading SF_NOT_FOUND with no hint; (2) getSfCommonPaths test predicate includes(bin) was too broad and would pass even if only the client path existed.

Fix: Normalize empty/whitespace sfPath to undefined in runSfCommand so auto-discovery runs; tighten qualityHubTools getSfCommonPaths assertions to exact path matching via path.join; add two tests for empty/whitespace sfPath normalization.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@mrdailey99 mrdailey99 merged commit f3a0dae into develop May 7, 2026
20 checks passed
@mrdailey99 mrdailey99 deleted the fix/sf-resolution-qualityhub branch May 7, 2026 21:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants