Sfgraph
БесплатноНе проверенA local, privacy-first knowledge graph for Salesforce orgs. It live-syncs your org to a SQLite + vector index on your machine and exposes 26 MCP tools to Cursor
Описание
A local, privacy-first knowledge graph for Salesforce orgs. It live-syncs your org to a SQLite + vector index on your machine and exposes 26 MCP tools to Cursor, Claude Code/Desktop, and VS Code, so the AI you already use can reason about Apex, LWC, Flow, Vlocity, OmniStudio, security, and integrations without your code or schema ever leaving your laptop.
README
A local, privacy-first knowledge graph for Salesforce orgs. sfgraph live-syncs your org to a SQLite + vector index on your machine and exposes 28 MCP tools to Cursor, Claude Code/Desktop, and VS Code, so the AI you already use can reason about Apex, LWC, Flow, Vlocity, OmniStudio, security, and integrations without your code or schema ever leaving your laptop.
┌──────────────────────────────────────────────────────────────────────┐
│ Cursor / Claude / VS Code ←──── MCP stdio ────→ sfgraph │
│ │
│ read-only Salesforce APIs ──→ your org │
│ local SQLite + sqlite-vec ←── OS data dir │
└──────────────────────────────────────────────────────────────────────┘
Privacy in one line. Nothing leaves your machine — graph, vectors, logs all live under the platform's user-data directory (~/Library/Application Support/sfgraph/ on macOS, ~/.local/share/sfgraph/ on Linux, %APPDATA%\sfgraph\ on Windows; see docs/DATA_LOCATIONS.md). Salesforce auth is delegated to the sf CLI (token stays in ~/.sfdx/). Every connection is wrapped in a read-only Proxy. Full threat model: docs/PRIVACY.md.
Install
1. Prerequisites
| How | |
|---|---|
| Node.js ≥ 20 | nodejs.org or brew install node |
sf CLI |
npm install -g @salesforce/cli |
At least one sf login |
sf org login web --alias my-org && sf config set target-org=my-org |
Verify:
node --version # v20+ (v22 LTS recommended)
sf org list # at least one org marked as default
2. Install sfgraph
npm install -g @ryanstark24/sfgraph
Or run on-demand via npx @ryanstark24/sfgraph <command> without installing.
After install, sfgraph is on your PATH.
3. Wire it into your editor
sfgraph install
Idempotent. Copies 20 skill playbooks into ~/.claude/skills/ + ~/.cursor/rules/ and adds a sfgraph entry to your editor's MCP config. Existing MCP entries are preserved. Use --target=claude|cursor|vscode to wire only one, or --dry-run to preview. Start with sf-graph-router — it routes intent to the right skill and enforces grounding answers in the org graph before generating Salesforce code.
Using a different IDE or LLM client?
sfgraph install writes config for Claude / Cursor / VS Code automatically. For any other MCP-compatible client (Windsurf, Zed, Continue, Cline, an OpenAI- or Gemini-based agent with MCP support, your own custom host, etc.), add this entry to the client's MCP config file manually:
{
"mcpServers": {
"sfgraph": {
"command": "npx",
"args": ["-y", "@ryanstark24/sfgraph", "mcp"]
}
}
}
On Windows, use "npx.cmd" instead of "npx".
Pinning the Node binary. Some hosts (sandboxed Electron apps, IDE extensions) ship with a bundled Node whose ABI differs from your shell's. If that bundled Node lacks a matching better-sqlite3 prebuilt, the MCP child fails to load. Pin to your shell's Node:
{
"mcpServers": {
"sfgraph": {
"command": "/Users/you/.nvm/versions/node/v22.21.1/bin/node",
"args": ["/usr/local/bin/sfgraph", "mcp"]
}
}
}
Use which node and which sfgraph to fill in the paths. Same effect as sfgraph install --local --pin-node "$(which node)" but written by hand into a client we don't have a built-in target for.
Where each known client keeps its MCP config:
| Client | Config path |
|---|---|
| Claude Desktop | ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) · %APPDATA%\Claude\claude_desktop_config.json (Win) |
| Claude Code (CLI) | ~/.claude.json (user) or .mcp.json (project) |
| Cursor | ~/.cursor/mcp.json |
| VS Code | ~/Library/Application Support/Code/User/mcp.json (macOS) · %APPDATA%\Code\User\mcp.json (Win) |
| Windsurf | ~/.codeium/windsurf/mcp_config.json |
| Zed | ~/.config/zed/settings.json (under context_servers) |
| Continue (VS Code) | ~/.continue/config.json (under mcpServers) |
| Cline (VS Code) | ~/.cline/cline_mcp_settings.json |
After editing the file, fully restart the client so it re-reads the MCP server list. Then ask the agent something like "list orgs from sfgraph" to confirm the tools are visible.
The skill playbooks (sf-impact-from-diff, sf-security-audit, etc.) are Claude/Cursor-specific. On other clients, the agent still has direct access to all 28 MCP tools — it just routes by tool name instead of by skill trigger.
4. Verify the install
sfgraph doctor
End-to-end self-check: Node ABI, native bindings, code-signing (macOS), data dir, org DBs, sf CLI, IDE MCP configs. Each failed check prints a copy-paste fix.
If you see a bindings file not found / ABI mismatch (common after a Node upgrade or on a brand-new Node release with no prebuilts yet):
sfgraph rebuild-bindings
First ingest
The first sync of an org takes 2–6 minutes on a typical 50K-node sandbox. Subsequent syncs on Source-Tracking-enabled orgs are incremental (<30 s).
# Default org from `sf config target-org`
sfgraph ingest
# Or pick an org explicitly
sfgraph ingest --org my-prod
The graph lands in <data-dir>/<orgId>.sqlite (macOS: ~/Library/Application Support/sfgraph/, Linux: ~/.local/share/sfgraph/, Windows: %APPDATA%\sfgraph\). From this point every MCP tool reads only from that file — no network calls.
Keep it fresh. Re-run sfgraph ingest whenever you want current data. Skills warn the agent when the graph is older than 7 days.
For tuning, large-org options, multi-org ingest, and rebuild flags, see docs/CLI.md.
Use it from your editor
Restart your IDE so it picks up the new MCP entry. Then in any project ask the agent:
- "What does this PR break?"
- "Who reads
Account.Status__c?" - "What changed in prod since last week?"
- "Show me how
accountTileflows from UI to DB."
The agent routes to the right tool automatically via the installed skill playbooks. A short worked example:
User: I'm about to merge this PR. Anything I should worry about?
Agent: *invokes sf-impact-from-diff*
→ impact_from_git_diff(diff="…", depth=3)
→ test_gap_intelligence_from_git_diff(diff="…")
Your diff touches 3 nodes. 9 dependents at 3 hops:
• 4 covered by tests (green)
• 5 at-risk (no IS_TEST_FOR):
- LWC:opportunityTile
- ApexMethod:BillingSvc.run(2)
- ApexMethod:BillingSvc.dryRun(0)
- Flow:Order_Status_Update
- LWC:invoiceTile
Recommend adding test coverage for BillingSvc.run(2) before merging.
More worked examples: docs/SAMPLES.md.
Optional: web visualiser
sfgraph serve # http://localhost:7777
A 3D force-graph explorer for the ingested org. Loopback-only by default. See docs/WEB.md.
Reliability
Wedge isolation (Phase 1.5)
A slow or hung source no longer blocks neighbors. When the per-source watchdog (90s first-yield, 5min inactivity) fires, the source's slot is released and the next queued source runs. The wedge runs to completion in the background; late records are drained with attributes.lateYield: true.
You will see warnings of the form wedge:<source>:<reason>:... in the ingest run summary — these are now informational (the run continues), not fatal.
Socket-leak caveat (honest disclosure). The underlying HTTP request to Salesforce is NOT cancelled (jsforce 3.10.15 does not expose AbortController). Wedged sockets are reaped by Node's idle-timeout (~10min). Worst-case memory: 4 wedges × ~1MB ≈ 4MB per ingest, garbage-collected at process exit. The cap is SFGRAPH_MAX_BACKGROUND_WEDGES (default 4).
Detect-deletions drop-ratio guard (Phase 1.5)
When run with --detect-deletions --rebuild, sfgraph refuses to wipe a label whose drop ratio exceeds SFGRAPH_DETECT_DELETIONS_MAX_DROP_RATIO (default 0.30). A wedge-induced empty stream emits a wedge:detect-deletions:refuse:label=<L>:reason=empty-stream warning instead of silently destroying the label. Refused labels keep their previous last_seen_at so the staleness clock keeps ticking — staleness reports will still surface them.
Diagnostics
When ingest reports skips you don't understand, use the diagnose subcommand:
sfgraph diagnose <orgId>
diagnose forces source / Tooling / Metadata / Data pool concurrency to 1 and writes a structured JSON report capturing per-source timing, wedge events, capability probes, and detect-deletions refusals. By default it writes to a temporary graph DB so your main org graph is untouched.
Note: wall-clock is NOT comparable to a production run — diagnose names wedges, it does not predict prod throughput.
Default report path (platform-aware, under the same data dir as the graph):
| Platform | Path |
|---|---|
| macOS | ~/Library/Application Support/sfgraph/diagnostics/<orgId>-<ISO-timestamp>.json |
| Linux | ~/.local/share/sfgraph/diagnostics/<orgId>-<ISO-timestamp>.json |
| Windows | %APPDATA%\sfgraph\diagnostics\<orgId>-<ISO-timestamp>.json |
Flags:
| Flag | Default | Effect |
|---|---|---|
--output <path> |
(auto) | Override the default report path. |
--max-duration <seconds> |
600 |
Overall diagnose timeout (10 min). |
--verbose |
false |
Stream per-source timing to stdout in addition to the JSON report. |
--keep-graph |
false |
Write to the real org graph DB instead of a temp DB. |
MCP staleness signal
Every MCP tool response carries a _meta.staleness block:
{
generation: number, // monotonic per-org sync counter
in_progress: boolean, // true if an ingest is currently rewriting the graph
started_at: string | null, // ISO timestamp of the in-progress ingest
last_sync_at: string | null // ISO timestamp of the most recent completed sync
}
Reader-side contract. MCP clients should check staleness.in_progress === true to warn users that the graph is being rewritten and results may reflect partial state. Tools that don't carry an orgId argument (e.g. ping, list_orgs) omit the block instead of guessing.
Environment variables
Authoritative inventory — every SFGRAPH_* env var read at runtime, sorted alphabetically. Verified via grep -rn "process.env.SFGRAPH_" packages/ --include="*.ts".
| Name | Type | Default | Purpose | Since |
|---|---|---|---|---|
SFGRAPH_ALLOW_ANY_DB |
bool (1) |
unset | Bypass the "graph DB must live under data dir" safety check. | 1.0 |
SFGRAPH_APEX_PARSER |
string | regex |
Apex class parser strategy (regex is the default; other values reserved). |
1.0 |
SFGRAPH_AUTO_RETRY_THRESHOLD |
int | 10 |
Skip-count threshold above which ingest auto-retries the wedged sources. |
1.0 |
SFGRAPH_BISECT_MAX_DEPTH |
int | 6 |
Tooling SOQL adaptive bisection depth cap. | 1.0 |
SFGRAPH_CACHE_DIR |
path | platform default | Override OS cache directory. | 1.0 |
SFGRAPH_CONFIG_DIR |
path | platform default | Override OS config directory. | 1.0 |
SFGRAPH_DATA_DIR |
path | platform default | Override OS data directory (where <orgId>.sqlite lives). |
1.0 |
SFGRAPH_DATA_POOL |
int | varies | Data API pool concurrency. | 1.0 |
SFGRAPH_DEBUG_INGEST |
bool (1) |
unset | Verbose ingest logging (per-source counters, dispatch table, etc.). | 1.0 |
SFGRAPH_DEBUG_POOLS |
bool (1) |
unset | Print pool-counter snapshots during ingest. | 1.0 |
SFGRAPH_DETECT_DELETIONS_MAX_DROP_RATIO |
float | 0.30 |
Per-label drop-ratio threshold above which --detect-deletions sweep refuses to act. |
1.5 |
SFGRAPH_EMBED_MODEL_DIM |
int | model default | Embedding model dimensionality override. | 1.0 |
SFGRAPH_EMBED_MODEL_ID |
string | model default | Embedding model identifier override. | 1.0 |
SFGRAPH_EMBED_MODEL_PATH |
path | (auto) | Local path to a custom embedding model file. | 1.0 |
SFGRAPH_INCLUDE_ALL_GENERIC |
bool (1) |
unset | Disable GENERIC_TYPE_WHITELIST filter — route every discovered metadata type through the generic extractor. |
1.0 |
SFGRAPH_INCLUDE_ALL_SOBJECTS |
bool (1) |
unset | Skip the EntityDefinition.IsCustomizable filter and include every queryable SObject. |
1.0 |
SFGRAPH_INCLUDE_MANAGED |
bool (1) |
unset | Include managed-namespace components globally (Apex body, generic metadata, LWC source). | 1.0 |
SFGRAPH_INCLUDE_MANAGED_LWC |
bool (1) |
unset | LWC-only override for managed-namespace inclusion (independent of the global flag). | 1.0 |
SFGRAPH_INCLUDE_SYSTEM_SOBJECTS |
bool (1) |
unset | Include platform telemetry SObjects (ApexLog, EventLogFile, etc.). |
1.0 |
SFGRAPH_LATE_DRAIN_BUDGET_MS |
int (ms) | (impl default) | Per-wedge late-yield drain budget — how long the background runner gets to drain late records before being abandoned. | 1.5 |
SFGRAPH_LOG_DIR |
path | platform default | Override OS log directory. | 1.0 |
SFGRAPH_MAX_BACKGROUND_WEDGES |
int | 4 |
Cap on simultaneous background wedges per ingest. | 1.5 |
SFGRAPH_METADATA_POOL |
int | varies | Metadata API pool concurrency. | 1.0 |
SFGRAPH_METADATA_READ_CHUNK_SIZE |
int | 10 |
metadata.read composite batch size. |
1.0 |
SFGRAPH_NO_AUTO_RETRY |
bool (1) |
unset | Disable automatic retry on watchdog wedge / skip cascade. | 1.0 |
SFGRAPH_NO_LIVENESS_PROBE |
bool (1) |
unset | Skip the pre-ingest liveness probe. | 1.0 |
SFGRAPH_SEQUENTIAL_SOURCES |
bool (1) |
unset | Force serial source execution (debug aid; bypasses the sliding-window merger). | 1.0 |
SFGRAPH_SKIP_LWC |
csv | unset | Skip specific LWC bundle DeveloperNames (also accepts 1 to skip the source entirely). |
1.0 |
SFGRAPH_SKIP_SOBJECT |
csv | unset | Skip specific SObjects by QualifiedApiName (escape hatch for describe()-crashing tables). |
1.0 |
SFGRAPH_SKIP_THRESHOLD |
int | (impl default) | Skip-count threshold for ingest-level retry/abort behavior. |
1.0 |
SFGRAPH_SOURCE_CONCURRENCY |
int | 12 |
Concurrency of the sliding-window source merger in bulk-retrieve.ts. |
1.0 |
SFGRAPH_TEMP_DIR |
path | platform default | Override OS temp directory. | 1.0 |
SFGRAPH_TOOLING_POOL |
int | 5 |
Tooling API pool concurrency. | 1.0 |
SFGRAPH_TRAVERSAL_NODE_CAP |
int | (impl default) | Cap on nodes visited by dependents / dependencies traversal in the analysis layer. | 1.0 |
SFGRAPH_WATCHDOG_FIRST_YIELD_MS |
int (ms) | 90000 |
Per-source first-yield watchdog timeout. | 1.5 |
SFGRAPH_WATCHDOG_INACTIVITY_MS |
int (ms) | 300000 |
Per-source inactivity watchdog timeout (5 min). | 1.5 |
Honest disclosures — known limitations
sfgraph aims to be honest about gaps. Read this section before relying on it for security or compliance audits.
- Security model gaps. Profile / PermissionSet / SharingRules are ingested as first-class nodes with
GRANTS_*edges. However, PermissionSetGroup, MutingPermissionSet, ProfileSessionSetting, ProfilePasswordPolicy are ingested as opaque generic nodes WITHOUTGRANTS_*orDENIES_*edges — they exist as nodes but their security semantics are not modeled. Audits that rely on these edges will not surface findings for those types until a future Security phase. - Security analysis caps. The analysis layer caps results at 5000 per label (
SECURITY_PER_LABEL_CAP). On orgs with more than 5k Profiles or PermissionSets, analysis is truncated with atruncated: trueflag — but graph storage is complete. - Generic-type whitelist. sfgraph dispatches ~80 of the ~327 metadata types Salesforce returns from
describeMetadata()to the parsed extractor path. The rest are recorded only as opaque generic nodes when matched by the whitelist; everything else is filtered out. SetSFGRAPH_INCLUDE_ALL_GENERIC=1to override (every discovered type runs through the generic extractor — longer ingest, more opaque nodes). The full type list is documented in docs/COVERAGE.md. - LWC empty-bundle behavior change (Phase 1.5). Prior versions yielded a stub
RawMemberwithfiles: {}on per-bundle resource-fetch failure, creating empty bundle nodes in the graph. Phase 1.5 emits awedge:lwc:bundleFetchFailed:...warning and no record. Users who upgrade may see previously-recorded empty LWC bundles disappear from their graph on the next re-ingest. This is correct. - Socket leak on wedged HTTP requests. When the per-source watchdog fires, sfgraph releases the slot but the underlying jsforce HTTP request is NOT cancelled (no
AbortControllerexposed by jsforce 3.10.15). The socket is reaped by Node's idle-timeout (~10min). Worst case:SFGRAPH_MAX_BACKGROUND_WEDGES(default 4) × ~1MB ≈ 4MB transient memory per ingest, GC'd at process exit. Tracked as future hardening; an upstream jsforce PR or fork is needed for true in-flight HTTP cancellation.
Coverage
sfgraph mixes deep parsing (Apex, LWC, Flow, Object, Profile/PermissionSet, NamedCredential, Vlocity, OmniStudio) with opaque-node fallback for the long tail of metadata types. Coverage is dynamic, not hardcoded — at ingest start, conn.metadata.describe(apiVersion) asks the org for its full supported type list, which automatically includes types added by managed packages or future Salesforce releases. Each type is routed to a named extractor, the generic opaque-node path, or filtered out.
See docs/COVERAGE.md for the full status matrix: every type, the edges it emits, known limitations, and the source file that implements it.
Documentation
| docs/CLI.md | Full CLI reference — every command, every flag |
| docs/TOOLS.md | The 28 MCP tools — schemas, examples, algorithms |
| docs/SKILLS.md | The 20 skill playbooks installed into your editor |
| docs/SAMPLES.md | Worked agent-conversation examples |
| docs/COVERAGE.md | Metadata coverage matrix and SObject classification logic |
| docs/WEB.md | Local web visualiser |
| docs/TROUBLESHOOTING.md | Diagnose and fix common install / ingest issues |
| docs/DESIGN.md | Architecture decisions, analysis pipeline, TS rewrite rationale |
| docs/ARCHITECTURE.md | Storage model + ingestion pipeline deep-dive |
| docs/PRIVACY.md | Read-only enforcement, sanitizer, telemetry threat model |
| docs/DATA_LOCATIONS.md | What lives where on your machine |
| docs/DEVELOPMENT.md | Build, test, contribute |
| CHANGELOG.md | Per-release notes |
License
MIT
Установка Sfgraph
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/ryanStark24/sfgraphFAQ
Sfgraph MCP бесплатный?
Да, Sfgraph MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для Sfgraph?
Нет, Sfgraph работает без API-ключей и переменных окружения.
Sfgraph — hosted или self-hosted?
Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.
Как установить Sfgraph в Claude Desktop, Claude Code или Cursor?
Открой Sfgraph на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
wenb1n-dev/SmartDB_MCP
A universal database MCP server supporting simultaneous connections to multiple databases. It provides tools for database operations, health analysis, SQL optim
автор: wenb1n-devPostgres Server
This server enables interaction with PostgreSQL databases through the Model Context Protocol, optimized for the AWS Bedrock AgentCore Runtime. It provides tools
автор: madhurprashPostgres
Query your database in natural language
автор: AnthropicPostgreSQL
Read-only database access with schema inspection.
автор: modelcontextprotocolCompare Sfgraph with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории data
