# sfdmu-mcp

> An MCP server for intelligent Salesforce SFDMU data migrations — generate, validate, preview, and execute `export.json` configs from natural language using the sf sfdmu plugin.

[![npm version](https://img.shields.io/npm/v/sfdmu-mcp.svg)](https://www.npmjs.com/package/sfdmu-mcp)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

---

## Overview

**sfdmu-mcp** bridges your AI editor (VS Code Copilot, Cursor, Claude Desktop, Windsurf) and the [SFDMU](https://github.com/forcedotcom/SFDX-Data-Move-Utility) Salesforce data migration plugin. Instead of hand-crafting `export.json` files, you describe your migration in plain English and the MCP server handles the rest.

### sfdmu-mcp vs Salesforce DX MCP

| Feature | sfdmu-mcp | Salesforce DX MCP |
|---------|-----------|-------------------|
| Natural language → export.json | ✓ | ✗ |
| Schema validation (AJV + SFDMU schema) | ✓ | ✗ |
| Pre-migration record count preview | ✓ | ✗ |
| sObject dependency analysis (topological sort) | ✓ | ✗ |
| Source/target field conflict detection | ✓ | ✗ |
| Org record count comparison | ✓ | ✗ |
| Execute sf sfdmu run with confirm gate | ✓ | ✗ |
| Credential sanitisation in all responses | ✓ | Partial |
| Docker containerisation | ✓ | ✗ |

---

## Quick Start

### Using npx (no install required)

```bash
npx sfdmu-mcp
```

### Install globally

```bash
npm install -g sfdmu-mcp
sfdmu-mcp
```

---

## Prerequisites

| Tool | Version | Install |
|------|---------|---------|
| Node.js | ≥ 20 LTS | https://nodejs.org or `nvm install 20` |
| Salesforce CLI | latest | `npm install -g @salesforce/cli` |
| SFDMU plugin | latest | `sf plugins install sfdmu` |

Verify:

```bash
node --version        # v20.x.x or higher
sf --version          # @salesforce/cli/2.x.x
sf plugins | grep sfdmu  # sfdmu x.x.x
```
**Authentication**: Orgs must be authenticated via SF CLI before use:

```bash
# Authenticate your source org
sf org login web --alias my-source-org

# Authenticate your target org
sf org login web --alias my-target-org

# Set a default org (used when sourceOrg/targetOrg are omitted)
sf config set target-org my-source-org
```

The MCP server delegates all credential retrieval to SF CLI via `sf org display`. No access tokens or passwords are ever passed as environment variables or tool arguments.
---

## Editor Integration

### VS Code (Copilot / MCP extension)

**Auto-install (VS Code 1.99+)**: Open the Command Palette (`Cmd/Ctrl + Shift + P`) → **MCP: Install Server** → search for `sfdmu-mcp`. VS Code reads the server configuration directly from the npm package — no prompts for command, arguments, or environment variables. The server starts automatically.

**Manual configuration** — add to `.vscode/mcp.json`:

```json
{
  "servers": {
    "sfdmu-mcp": {
      "type": "stdio",
      "command": "npx",
      "args": ["sfdmu-mcp@latest"]
    }
  }
}
```

### Cursor

Add to `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project):

```json
{
  "mcpServers": {
    "sfdmu-mcp": {
      "command": "npx",
      "args": ["-y", "sfdmu-mcp@latest"]
    }
  }
}
```

### Claude Desktop

Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):

```json
{
  "mcpServers": {
    "sfdmu-mcp": {
      "command": "npx",
      "args": ["-y", "sfdmu-mcp@latest"]
    }
  }
}
```

### Windsurf

Add to `~/.codeium/windsurf/mcp_config.json`:

```json
{
  "mcpServers": {
    "sfdmu-mcp": {
      "serverType": "stdio",
      "command": "npx",
      "args": ["-y", "sfdmu-mcp@latest"]
    }
  }
}
```

---

## Configuration

All configuration is done via environment variables passed to the server process. To override defaults, add an `env` object to your editor's MCP server configuration.

### Available Environment Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `SF_API_VERSION` | `62.0` | Salesforce API version used for all org queries |
| `DEBUG` | _(unset)_ | Set to `sfdmu-mcp:*` to enable verbose debug logging to stderr |

### Example: VS Code `.vscode/mcp.json`

```json
{
  "servers": {
    "sfdmu-mcp": {
      "type": "stdio",
      "command": "npx",
      "args": ["sfdmu-mcp@latest"],
      "env": {
        "SF_API_VERSION": "61.0",
        "DEBUG": "sfdmu-mcp:*"
      }
    }
  }
}
```

### Example: Cursor / Claude Desktop `mcp.json`

```json
{
  "mcpServers": {
    "sfdmu-mcp": {
      "command": "npx",
      "args": ["-y", "sfdmu-mcp@latest"],
      "env": {
        "SF_API_VERSION": "61.0"
      }
    }
  }
}
```

---

## Tool Reference

| Tool | Description | Key Parameters |
|------|-------------|----------------|
| `sfdmu_check_prerequisites` | Verify sf CLI and sfdmu plugin are installed and reachable | — |
| `sfdmu_generate_export_config` | Generate a schema-valid `export.json` from a natural language migration intent | `sourceOrg`, `targetOrg`, `objects[]` |
| `sfdmu_validate_export_config` | Validate any `export.json` against the official SFDMU JSON schema | `exportConfig` |
| `sfdmu_dry_run_preview` | Query source org record counts and detect blocking errors without touching the target | `exportConfig`, `sourceOrg` |
| `sfdmu_analyze_dependencies` | Compute correct sObject migration order via topological sort | `objects[]`, `sourceOrg` |
| `sfdmu_detect_conflicts` | Compare source and target org field metadata for type mismatches and missing fields | `objects[]`, `sourceOrg`, `targetOrg` |
| `sfdmu_compare_orgs` | Diff record counts between source and target orgs | `objects[]`, `sourceOrg`, `targetOrg` |
| `sfdmu_execute_migration` | Execute `sf sfdmu run` — requires `confirm: true` to proceed | `exportConfig`, `sourceOrg`, `targetOrg`, `confirm` |

---

## Environment Variables

| Variable | Required | Description |
|----------|----------|-------------|
| `SF_API_VERSION` | Optional | Salesforce API version override (default: `62.0`) |
| `DEBUG` | Optional | Set to `sfdmu-mcp:*` for verbose debug logging to stderr |

**Authentication** is handled entirely by SF CLI. Use `sf org login web --alias <name>` to authenticate orgs. The MCP server calls `sf org display --target-org <alias>` to retrieve session credentials at runtime — no tokens or passwords are ever passed via environment variables.

---

## Docker

### Build and run

```bash
docker build -t sfdmu-mcp:latest .

# Mount the SF CLI auth store so the container can use your authenticated orgs
docker run --rm \
  -v ~/.sf:/home/sfdmuuser/.sf:ro \
  sfdmu-mcp:latest
```

### docker-compose

```bash
docker compose up
```

---

## CLI Options

```
npx sfdmu-mcp              Start with stdio transport (default)
npx sfdmu-mcp --http       Start Streamable HTTP transport on $PORT (default 3000)
npx sfdmu-mcp --version    Print version
npx sfdmu-mcp --help       Show help
```

> **⚠️ HTTP transport security**: The `--http` transport has **no built-in authentication**.
> If you expose the server outside `localhost`, you **MUST** place it behind a reverse proxy
> (nginx, Caddy, Traefik) or VPN that handles authentication. Direct public exposure is
> unsupported and unsafe — any caller would have full access to all migration tools.
> For local editor use, the default stdio transport is always preferred.

---

## Troubleshooting

**`sfdmu_check_prerequisites` returns failing checks**
- Ensure Salesforce CLI is installed: `npm install -g @salesforce/cli`
- Install the sfdmu plugin: `sf plugins install sfdmu`
- Verify: `sf plugins | grep sfdmu`

**`ORG_AUTH_FAILED` error**
- The org alias is not authenticated. Run: `sf org login web --alias <alias>`
- To see all authenticated orgs: `sf org list`
- To check a specific org: `sf org display --target-org <alias>`

**`SCHEMA_VALIDATION_FAILED` error**
- Use `sfdmu_validate_export_config` to get detailed AJV error paths
- Ensure each object has `query`, `operation`, and (for Upsert) `externalId`

**Server not appearing in editor**
- Confirm Node.js ≥ 20: `node --version`
- Try running `npx sfdmu-mcp --version` directly in your terminal to confirm it starts
- Check editor logs for MCP server startup errors

---

## License

[MIT](LICENSE)
