@haviq/mcp
v1.8.0
Published
HAV-IQ MCP Server — deploy Salesforce metadata in plain English from Claude Code, Cursor, Windsurf, or OpenCode (stdio + HTTP/SSE transports)
Maintainers
Readme
HAV-IQ MCP Server
Deploy Salesforce metadata in plain English from Claude Code, Cursor, Windsurf, OpenCode, or any MCP-compatible AI IDE.
"What's ready to deploy in the Acme pipeline?"
"Show me branches with high risk scores"
"Deploy AccountService and ContactTrigger from DEV to QA"
"What changed between DEV and QA?"
"Retry the failed deployment"Prerequisites
- HAV-IQ package installed in your Salesforce org
sfCLI installed and authenticated against that org (sf org login web --alias prod)- Node.js 18+
Quick Start
npm install -g @haviq/mcp
sf org login web --alias prod # one-time per org
haviq-mcp --setupThe wizard lists your sf-CLI-authenticated orgs, asks you to pick the HAV-IQ control plane, probes that it has the managed package installed, then saves ~/.haviq.json. No Connected App, no RSA keys, no JWT to manage — all auth is delegated to sf CLI, which auto-refreshes tokens.
If you haven't authenticated an org yet, hit n at the prompt and the wizard will launch sf org login web for you.
Two-org model
HAV-IQ MCP talks to two kinds of Salesforce orgs:
| Role | Has HAV-IQ package? | What MCP does there |
|-------------------|---------------------|--------------------------------------------------------------|
| Control plane | Yes | Calls /services/apexrest/haviq/v1/* for pipelines, stages, deployments, promote, rollback, risk scoring, data pack. One per org-group (typically Production). |
| Target orgs | No | Direct metadata push/pull via sf CLI (push_to_org, retrieve_from_org). Any Dev / UAT / QA sandbox the user works in. |
Typical flow for IRIS users: edit code in a Dev sandbox → push_to_org writes it to that sandbox for instant feedback → create_delta_deployment against the Prod control plane kicks off the pipeline to promote Dev → QA → UAT → Prod.
Manual Configuration
haviq-mcp --setup writes this for you, but if you prefer to write it by hand:
// ~/.haviq.json (or .haviq.json in your project root)
{
"controlPlane": {
"orgAlias": "prod"
},
"defaultTargetOrg": "my-dev-sandbox"
}That's the whole file. orgAlias is an sf CLI alias — MCP resolves URL + access token at runtime via sf org display --json. Both the control plane and every target sandbox must be authenticated in sf CLI:
sf org login web --alias prod # HAV-IQ control plane
sf org login web --alias my-dev-sandbox # Dev sandbox
sf org login web --alias my-uat-sandbox # UAT, etc.Then list_target_orgs inside the MCP will see all of them.
Environment variables (useful for CI / containerized setups):
| Variable | Description |
|----------------------------|-----------------------------------------------------------------------|
| HAVIQ_ORG_ALIAS | sf CLI alias of the control plane (overrides config file) |
| HAVIQ_DEFAULT_TARGET_ORG | sf CLI alias used by push_to_org when no orgAlias is supplied |
Naming convention
Register the MCP server in each IDE using an IDE-specific name — haviq-cursor, haviq-claude, haviq-opencode, haviq-codex, haviq-duo. The binary is always haviq-mcp; only the registration key changes. This way, when support asks "which IDE is showing the error?", the answer is in the config name.
Add to Claude Code (haviq-claude)
In your Claude Code MCP settings (~/.claude/mcp.json for the VS Code extension, or ~/.claude.json for the CLI):
{
"mcpServers": {
"haviq-claude": {
"type": "stdio",
"command": "haviq-mcp"
}
}
}Restart Claude Code (Cmd+Shift+P → Developer: Reload Window in VS Code, or exit + re-launch claude in the terminal).
Add to Cursor (haviq-cursor)
Settings → MCP → Add Server:
{
"name": "haviq-cursor",
"command": "haviq-mcp"
}Restart Cursor.
Add to OpenCode (haviq-opencode)
OpenCode is an open-source AI coding agent that speaks the same MCP protocol as Claude Code. HAV-IQ MCP works with OpenCode out-of-the-box — no client-specific build.
Edit ~/.config/opencode/opencode.json (or ~/.opencode.json) and add an mcp block:
{
"mcp": {
"haviq-opencode": {
"type": "local",
"command": ["haviq-mcp"],
"enabled": true
}
}
}If haviq-mcp is not on PATH, use npx instead:
{
"mcp": {
"haviq-opencode": {
"type": "local",
"command": ["npx", "-y", "@haviq/mcp"],
"enabled": true
}
}
}Restart OpenCode.
Add to OpenAI Codex CLI (haviq-codex)
The OpenAI Codex CLI reads its MCP server list from ~/.codex/config.toml. Add:
[mcp_servers.haviq-codex]
command = "haviq-mcp"If haviq-mcp is not on PATH:
[mcp_servers.haviq-codex]
command = "npx"
args = ["-y", "@haviq/mcp"]Restart codex.
Add to GitLab Duo Chat (haviq-duo)
GitLab Duo Chat has two MCP integration modes — pick the one that matches your setup.
Mode A — IDE plugin (GitLab Workflow extension for VS Code / JetBrains)
In the GitLab Workflow extension settings (VS Code: Cmd+, → search "GitLab Duo MCP"):
{
"gitlab.duo.mcpServers": {
"haviq-duo": {
"command": "haviq-mcp"
}
}
}Reload the IDE. Duo Chat will list haviq tools alongside its built-in tools.
Mode B — Server-side Duo (gitlab.com web UI or Duo Agent Platform)
Server-side Duo can't spawn local processes — it needs the MCP reachable over HTTPS. Run haviq-mcp as an HTTP/SSE server (see npm run start:http), front it with TLS + auth, then register it via .gitlab/duo/mcp.yml at the repo root:
mcp:
servers:
- name: haviq-duo
url: https://haviq-mcp.your-domain.example.com/sse
auth:
type: bearer
token: ${HAVIQ_MCP_AUTH_TOKEN}Note: Mode B is currently single-tenant — every team using the hosted endpoint shares the same
HAVIQ_MCP_AUTH_TOKEN. Multi-tenant OAuth 2.0 for hosted MCP is on the roadmap; until then, run onehaviq-mcpdeployment per customer if more than one customer needs server-side Duo.
Available Tools
| Tool | What it does |
|------|-------------|
| get_pipelines | List all HAV-IQ pipelines with IDs |
| get_stages | List stages (DEV, QA, UAT, PROD) for a pipeline |
| list_deployments | Recent deployments with status and AI review summary |
| get_branches | Feature branches with AI risk scores (0–100) |
| get_delta_manifest | Compute changed components between two stages |
| create_deployment | Deploy specific components from source to target |
| create_delta_deployment | Deploy all changed components (AI-computed delta) |
| retry_deployment | Re-trigger a failed deployment |
| override_deployment | Override a stuck deployment status |
| list_target_orgs | List all sf-CLI-authenticated orgs (Dev / UAT sandboxes) |
| push_to_org | Direct-write metadata to a Dev / UAT sandbox (no pipeline, no MR) |
| retrieve_from_org | Pull metadata from a Dev / UAT sandbox to local files |
Typical Workflow
You: "What pipelines do we have?"
Claude: [calls get_pipelines] → "Acme Pipeline (active) — ID: a0B..."
You: "Show me the stages"
Claude: [calls get_stages] → "DEV → QA → UAT → PROD (all authenticated)"
You: "What's changed between DEV and QA?"
Claude: [calls get_delta_manifest] → "3 components changed: AccountService, ContactTrigger, OpportunityHelper"
You: "Deploy all of them to QA"
Claude: [calls create_delta_deployment] → "✅ Delta deployment created. Deployment ID: a1C..."
You: "Check the status"
Claude: [calls list_deployments] → "🔄 DEV → QA | running | Apr 3, 2:14 PM"IRIS flow (direct-write + promote)
You: "Save this to my Dev sandbox and push it to QA"
Claude: [push_to_org orgAlias=my-dev force-app/main/default/classes/Foo.cls]
→ "Deploy to my-dev — Succeeded. 1 component."
[get_delta_manifest sourceStage=DEV targetStage=QA]
→ "1 component changed: Foo"
[create_delta_deployment sourceStageId=DEV targetStageId=QA ...]
→ "✅ Delta deployment created. Kicks off Dev → QA promote."Security
Git provider tokens are transmitted to your Salesforce org via HTTPS and stored as EncryptedText fields. They are never stored locally by the MCP server. The server holds no state — all data lives in your Salesforce org.
License
MIT
