sf-intelligence

MCP serverDocs & knowledge

Your AI can answer questions about one Salesforce org's metadata, how its pieces depend on each other, and what a change might affect. It draws on an offline, read-only knowledge base, so it works without a live connection and cannot modify the org. It covers a single org at a time.

Unavailable. This server has no hosted endpoint yet, so Ahel can't serve it.

Add to setup to save this item as a reference. Ahel cannot run it, and signing in will not install it.

What your AI can do with it

  • Look up metadata from a single Salesforce org
  • Trace dependencies between components in that org
  • Assess the impact of a change before it is made
  • Answer questions about the org while offline
  • Keep the org untouched with read-only access

Getting started

  1. Save this item in Your setup as a reference.
  2. Read the source or reference documentation for its setup requirements. Saving it here does not connect it to your AI.
  3. Check this page for availability before trying to install it through Ahel.

From the project's README

As published by pranavnagrecha/salesforce-intelligence in README.md.

sf-intelligence

A grounded, fail-closed backend for AI assistants working in one Salesforce org. Your AI host (Claude, or any MCP client) asks it questions in plain language; it answers from the org's real metadata — never a guess — and labels every claim with how much to lean on it.

sf-intelligence is an offline, read-only, MCP-first knowledge base for a single Salesforce org. You run one retrieve (sf project retrieve); it builds a local Markdown vault and a DuckDB dependency graph. From then on every answer is served locally by default — offline-first, no network egress for vault answers. An opt-in live read-only plane (sfi.live_*) can answer record counts and samples when enabled. Private by design. MIT + Commons Clause.

It is not a standalone chatbot — it has no chat surface. It is the evidence layer an AI host consumes: a router that advises (ranked tool candidates plus explicit disclosures), a host LLM that decides (picks and runs the tools), and an engine that grounds every answer in the vault and fails closed — refusing, disclosing a gap, or asking a clarifying question — when it cannot.

Ask it like a person

You don't need to know the exact API name of anything. The front door is a typo-tolerant resolver that turns messy phrasing into the right component — and when it isn't sure, it asks you a clarifying question instead of guessing:

You: where's the emale field?

It: I found several matches for "email" — which did you mean? · Email__c on Account · Email__c on Contact · Alternate_Email__c on Lead

You: what about the paymnet object?

It: Payment__c — one confident match.

You: is there a "warranty fee" field?

It: Nothing matched that confidently. Your vault was last refreshed on 2026-05-20 — want to pull fresh metadata from the org (/sfi-refresh) in case it's new, or rephrase?

That is the headline behavior for resolution and routing: they never silently commit to a guess. Resolution is always heuristic and labeled as such. When several components are plausible it hands you a clarifying question; when nothing matches it offers to refresh from the org or stop. A high match score is string similarity, not proof. Source grep tools (sfi.search_apex_source, sfi.search_flow_metadata) walk the vaulted source/ tree from your last refresh — run /sfi-refresh before trusting an empty grep result.

Advisory routing — the funnel advises, the host decides

Under the hood a semantic router (sfi.route_question) reads each question and returns a meaning-ranked shortlist (toolCandidates) of the sfi.* tools that can answer it — so your AI host picks and runs them without you ever typing a tool name. It runs fully offline (a small TF-IDF model over the tool catalog — no network, no embeddings service) and it advises rather than dictates: the candidates are the primary output; the deterministic route that rides along is a non-authoritative hint. The host LLM decides which tools to run, in what order.

Confidence semantics are explicit. When no deterministic intent matches but the semantic funnel's top candidate scores above a fixed floor, the router returns a funnel-advisory route — the top funnel tools, confidence low by construction, reason flagged FUNNEL-DERIVED — an advisory pick for the host to verify (resolve the named component, then ground), never a command. Each candidate row also carries cosine, its raw semantic score, so a host can tell real semantic support from a regex-rule assertion.

The router also tags each question with the plane that answers it — the offline vault (metadata, dependencies, permissions), the live org (counts, samples, limits, inactive users — read-only, opt-in), or a hybrid of both (e.g. "is this field actually populated?"). Every answer is stamped with its provenance (offline_snapshot, live_org, or hybrid) and freshness. Clarifying questions are a last resort: a qualifier already in the question ("the X object", an object word next to a same-named field, a literal API name) auto-resolves instead of blocking, and offered options are hygienic — fuzzy lookalike junk never appears as a choice. But when two genuinely competing components remain, or the best-fitting tools diverge on something consequential (one destructive-simulation, one read-only), the router stops and asks which you meant instead of letting the host silently commit. When nothing fits, it says so rather than guessing (and can log the gap locally — opt-in via logGap: true). (A deterministic, no-LLM routing mode is available via SFI_ROUTER_MODE=offline for CI / air-gapped hosts.)

An experimental, opt-in RRF hybrid embeddings layer is available for early adopters (SFI_EMBEDDINGS=1 + npm i @huggingface/transformers). It fuses the TF-IDF candidates with a locally cached neural model (~23 MB) via Reciprocal Rank Fusion. The model is not bundled with the npm package and isn't fetched automatically — it requires the separate peer-dependency install above, and the download-on-first-use path is still being hardened, so treat it as a manual opt-in step, not something that happens for you. Off by default either way — the lexical path is byte-identical when unset, and if the model isn't installed or cached the funnel silently falls back to lexical-only. The honesty/refusal decision and the deterministic route.tools plan are not affected. See docs/configuration.md for details.

Refusal behavior — fail closed, offer the read

Some questions should never route to an executable tool, no matter how well they score. Score-independent refusal gates run on the raw question before any intent matching, and a refusal is non-executable by shape (tools: [] plus a structured route.refusal disclosure):

  • Write imperatives ("delete the X field for me", "go ahead and merge these profiles") → refused-write, with a read-only alternative offered instead (safe_to_delete_field, what_if_merge_profiles, get_impact, … by verb family) — the product has no write path; the refusal names the simulation that answers the underlying question safely.
  • Prompt injection / record-value exfiltration ("ignore your previous instructions…", "dump all SSN values") → refused-injection, with candidates and guidance suppressed entirely.
  • Runtime telemetry no tool models → honest-gap-runtime, naming the nearest real reads. Non-Salesforce asks → out-of-scope.

Legitimate reads are explicit excluders — "am I allowed to edit…", "who can delete…", "is it safe to…" are permission questions and route normally. On a 2,000-question real-org evaluation, the gates cut genuine over-confident routes from 69 to 11 with zero answerable questions falsely refused.

Conversation context — follow-ups without server-side memory

The product stores no conversation state. Instead, the host may pass an optional context.previous on each route_question call describing what the prior turn was about, and terse follow-ups ("does it fire on delete too?", "what about on Contact?", "the second one") resolve against it — pronoun substitution is an exact-id lookup (never fuzzy), an inherited tool is an advisory continuation capped at medium confidence, and a clarification pick re-dispatches through the normal clarification contract (out-of-range ordinals re-ask, stale ids are rejected). A self-contained question ignores context entirely, and refusal gates run before any context logic — context never bypasses them. Host-side, after routing "who can edit the SSN field?" and running the tools:

// next turn: "can Support Agents specifically edit it?"
{
  "question": "can Support Agents specifically edit it?",
  "context": {
    "previous": {
      "question": "who can edit the SSN field?",
      "tool": "sfi.field_access_audit",
      "componentId": "CustomField:Contact.SSN__c"
    }
  }
}

When (and only when) context changes the route, the response discloses it in route.contextApplied. See docs/routing.md for the full host contract.

Honesty guarantees

The design rule across the surface is fail closed, disclose first:

  • Grounded or refused. Every answer path ends in real tool output against the vault (or the consented live org); when no tool covers the ask, the router returns an honest gap — never a lookalike tool, never general Salesforce knowledge dressed up as org fact.
  • Premise checks. A question naming a component the resolver cannot find still routes (the tools fail closed on the unknown id), but confidence is downgraded and a PREMISE CHECK disclosure warns that no such component exists in the vault — and a funnel-advisory route is never granted on a failed premise.
  • Disclosure-first. Coverage caveats, staleness warnings, live-consent notices, refusals, and context application are structured fields the host renders before the answer — not fine print after it.

How it works

One read-only refresh turns your org into a local vault; from then on every question is answered offline — your AI host asks the router for a shortlist, picks the tools, runs them against the vault, and grounds the answer. The host decides; the router only advises.

flowchart TB
    subgraph REFRESH["Refresh — once, and whenever the org changes"]
        direction LR
        ORG[("Salesforce org")] -->|"sf project retrieve (read-only)"| SRC["source/ raw metadata"]
        SRC -->|"extract + parse Apex / Flow / XML"| VAULT[("Graph A · Local vault<br/>your org, grounded<br/>Markdown + DuckDB graph")]
    end

    subgraph CONCEPT["Concept Model — ships with the package · no org data, ever"]
        CM[["Graph B · Concept Model<br/>143 org-independent concepts / 195 rules<br/>save-order · relationships · sharing · code-shape"]]
    end

    subgraph ASK["Ask — every question, offline on your machine"]
        direction TB
        Q["Your question<br/>(plain language)"] --> HOST["Host LLM<br/>(Claude, etc.)"]
        HOST -->|"1 · route_question"| FUNNEL["Semantic funnel<br/>offline TF-IDF — no network"]
        FUNNEL -->|"toolCandidates + guidance<br/>(ranked shortlist — advises)"| HOST
        HOST -->|"2a · retrieve: picks and runs"| TOOLS["sfi.* retrieval tools"]
        TOOLS -->|"read"| VAULT
        TOOLS -.->|"opt-in, read-only, capped"| LIVE[("Live org")]
        HOST -->|"2b · reason: resolve"| RESOLVE["sfi.resolve<br/>fix the component"]
        RESOLVE -->|"interpret"| INTERPRET["sfi.interpret · deterministic OFFLINE JOIN<br/>Concept Model × grounded vault slice<br/>no LLM · no live org read"]
        INTERPRET -->|"cited, confidence-tiered<br/>structural-implication claims"| SYNTH["3 · synthesize_answer"]
        TOOLS --> SYNTH
        SYNTH --> ANS["Grounded answer<br/>+ provenance + freshness<br/>+ cited canonical ids"]
    end

    VAULT ==>|"grounded slice · Graph A"| INTERPRET
    CM ==>|"concept rules · Graph B"| INTERPRET

Every box on the Ask path runs on your machine; the dotted edge to the live org is the only one that can touch Salesforce, and only after you opt in. Retrieval (route_question → sfi.* → synthesize_answer) reports what's in the org; the reasoning path (resolve → interpret → synthesize_answer) reports what its shape implies. sfi.interpret is a deterministic, offline join of the org-independent Concept Model (Graph B — 143 concepts / 195 rules, which never touches your org) against a grounded slice of the vault (Graph A); it runs with no LLM and no live read, and every claim it feeds synthesize_answer is cited and confidence-tiered. The deterministic SFI_ROUTER_MODE=offline mode collapses step 1 to a single routed plan for hosts with no LLM in the loop.

Reasoning, not just retrieval

Retrieval tells you what's in the org. It doesn't tell you what a structure implies — that a master-detail parent delete cascade-deletes its children, that two active before-save flows on one object run in an undefined order, or that an @AuraEnabled method is an entry point where Apex does not auto-enforce field-level security. SfIntelligence answers those with a small second graph.

Alongside the org's grounded vault, the product ships a Concept Model: 143 org-independent, curated concepts and 195 rules that encode general Salesforce truth — save-order phases, relationship semantics, sharing posture, code-shape signals. No org data lives in it; the org enters reasoning only through the grounded slice at query time. The sfi.interpret tool joins the two: it assembles a minimal graph slice around one component and fires the applicable rules to produce cited, confidence-tiered structural-implication claims. It is deterministic and offline — no LLM, no live org read — and its claims are also folded into sfi.synthesize_answer so they reach a normal answer, hedged and attributed, on any MCP host.

The concept families are curated structural patterns, not vulnerability detection. A sample of what fires today:

  • Relationships — master-detail cascade-delete + read-only roll-up summary; junction (two-master) many-to-many; formula/roll-up fields are read-only, so a write to one is write-hostile.
  • Automation — multiple active record-triggered flows in one trigger context (undefined execution order); a firing condition that tests a field another automation writes in the same save (cross-phase coupling); before/after trigger phases; a flow fault-path rollback gap.
  • Sharing & security surface — organization-wide default (OWD) posture; without sharing system-context Apex; an external API surface (@RestResource / @AuraEnabled / @InvocableMethod) where FLS/CRUD are not auto-enforced; async boundaries; connected-app OAuth scope.
  • Code shape — Apex SOQL-injection / bulkification / CRUD-FLS / swallowed- exception / hardcoded-id gaps; a test with no assertions.

Every claim is grounded or it does not exist. Each interpretation carries a groundedIn list of the exact component ids it matched — no citation ⇒ no claim — and its confidence is computed, never asserted: the weakest of the rule's ceiling and the grounding edges it matched (see the two-axis note below). An empty result means "no concept rule fired," never "nothing depends on it." And the governor/security concepts reason about static code shape — they name a surface or a coupling, not a live limit breach or a proven runtime vulnerability. For a worked resolve → interpret → synthesize example, see docs/guides/asking-questions.md §2b; for the design rationale, ADR-008.

What you can ask

Eight capability areas, each answerable in natural language (ask sfi.capabilities, or just "what can you do?", for the live map):

AreaExample questions
Find & identify"where is the email field?" · "what's the payment object called?"
Understand"what does this validation rule do?" · "what happens when an Account is saved?" (automation on standard objects works even when the object file was not retrieved; objectModeled: false is surfaced)
Impact & dependencies"what breaks if I delete this field?" · "is it safe to deactivate this flow?"
Permissions & sharing"why can't this user see this record?" · "who can edit the Salary field?" · "who holds the Sales Manager permission set?" (live) · "what does user Jane hold?" (live) · "who's in the Support queue?" (live) · "which active users have zero permission-set assignments?" (live)
Automation & code"what runs on Case create?" · "which Apex methods have no real test coverage?" · "decode this Apex debug log / governor-limit exception to the class that ran"
Decision-support (before you build/change)"before I add automation to this object, what already runs there?" · "building Apex here — what should I watch out for?" · "before I change/require this field, what breaks?"
Architect & developer"are there circular Apex dependencies?" · "which classes have no test reference?" · "does the vault still match the live org?"
Integrations"what external systems does this org talk to?" · "list every outbound endpoint"
Documentation"give me a tour of this org" · "generate a data dictionary" · "which reports / objects / permission sets have no description?" (list_components with missingDescription: true)
Health & audit"is my vault fresh?" · "where is PII stored?" · "how has the org changed across refreshes?"

These are advisory, read-only briefings — e.g. automation_build_advisor, apex_build_advisor, field_change_advisor synthesize what the org already shows so you make a better build decision; find_dependency_cycles, apex_test_coverage, live_drift_check, and org_history serve architects and developers. None of them write to the org.

Every org artifact the product names is backed by a tool call and cited with its canonical ID (CustomObject:Account, CustomField:Account.Industry__c), and every relationship is cited with its confidence (declared, parsed, or heuristic).

Trust & confidence glossary

Every answer is tagged so you know how much to lean on it. These tags match the runtime values verbatim (the trust block on analysis tools, the per-edge confidence, and synthesize_answer's provenance.stamp).

Edge confidence — how a relationship was derived. This is the per-edge tier you see on dependency answers:

  • declared — Salesforce metadata states it directly (a layout assignment, a field's referenceTo, a permission grant). Highest trust.
  • parsed — produced by AST/XML parsing of source (the parser-grade Apex pass that runs on every refresh by default — resolved field reads/writes, cross-class calls, field-level SOQL — plus the formula tokenizer, Flow elements, a profile's <layoutAssignments>). High trust.
  • heuristic — produced by regex / token / dynamic-string analysis (the Apex recall scanner that supplements the parsed pass, name-pattern detection). May have false positives — spot-check before acting.

Claim confidence — a different axis: how well a reasoning claim from sfi.interpret is grounded. It uses the same declared | parsed | heuristic words, but it is computed, not read off one edge: a claim's confidence is the weakest of the concept rule's ceiling and the grounding edges the claim matched. An absence-shaped claim under non-complete coverage reads unknown. Do not conflate the two — edge confidence describes a single relationship; claim confidence describes an interpretation that rests on one or more such edges and can never exceed the weakest of them.

Provenance — where the answer came from:

  • offline_snapshot — the last /sfi-refresh vault. The default for every vault tool.
  • live_org — an opt-in, capped, read-only sfi.live_* SOQL read.
  • hybrid — fuses vault + live and discloses both provenances.

Completeness — how much of what the answer depends on was actually retrieved:

  • complete — the refresh modeled every metadata family the answer needs.
  • partial — a family the answer depends on was not retrieved; absence means "not checked", never "none" (a coverageCaveat names the gap).
  • unknown — coverage could not be determined.

Two tools make this concrete. sfi.coverage_report lists what the retrieve manifest requested and returned; sfi.retrieve_blindspot_report lists what the graph references but never retrieved — automation/code/config that depends on a component the vault never pulled — so an "X is unused / nothing references X" answer carries a known-coverage caveat instead of a silent blind spot.

How much it models

MCP rosterEvery sfi.* tool is registered in code; run sfi.capabilities (see productManifest) for the live registered/advertised counts — never a handwritten number
Graph modelA broad ComponentType union across 103 component types (objects, fields, Flows, Apex, layouts, permissions, sharing, UI, legacy automation, integrations, CPQ, OmniStudio, reports, FlexiPages, and more) connected by 23 typed edge types — see sfi.capabilities for how tools group those families. Counts are pinned by eval/product-manifest.json.
Concept ModelConcept Model (143 concepts / 195 rules) — org-independent, curated — JOIN against the grounded vault to produce cited structural-implication claims via sfi.interpret. No org data lives in the model. Same figures in eval/product-manifest.json.
26skills + 5 slash commands + 4 subagents (Claude Code plugin layer) that auto-activate in a session

What it does NOT do

Boundaries are explicit, and the product tells you plainly when it hits one rather than papering over the gap with general Salesforce knowledge:

Shortened here. Read the whole README on GitHub.

Signals

GitHub stars
2
Last commit
Oct 2026
Weekly downloads
363
Weekly_downloads
112 weekly_downloads
Advanced
Delivery
sf-intelligence MCP server → your Ahel connector (mcp.ahel.ai) → your AI.
Item type
mcp-server
Key
io-github-pranavnagrecha-sf-intelligence
Source
github.com/pranavnagrecha/salesforce-intelligence