Skip to content

Salesforce Headless 360 — surgical adoption, not wholesale replacement

ADR-013: Salesforce Headless 360 — surgical adoption, not wholesale replacement

Section titled “ADR-013: Salesforce Headless 360 — surgical adoption, not wholesale replacement”

Status: Blocked on tenant business decision (Kahuna Agentforce purchase) Date: 2026-04-20 (resolved 2026-04-22) Deciders: Mishaal Murawala

Probe executed against Kahuna Workforce Solutions SFDC prod via V5 gateway:

License inventory — from SELECT Name, Status, UsedLicenses, TotalLicenses FROM UserLicense:

  • Salesforce: 23/23 (standard Enterprise/Unlimited edition seats)
  • Identity: 0/100
  • Chatter Free, Chatter External, Cloud Integration User, Analytics Cloud Integration User
  • NO Agentforce license
  • NO Einstein AI license
  • NO MCP-related license

Endpoint probeGET /services/mcp/v1, /.well-known/mcp-server-card.json: HTTP 404 (“URL No Longer Exists” — Salesforce’s standard 404 page).

Conclusion: Kahuna’s current SFDC edition does NOT include Hosted MCP Server access. To unblock salesforce_mcp pass-through, Kahuna must purchase Agentforce (Flex Credits, Conversations, or per-user plan) OR negotiate Hosted MCP Server beta enablement with their SFDC AE.

Engineering disposition: ADR-013 remains a valid technical design. Implementation is blocked pending Kahuna business decision to purchase Agentforce. No V5 work proceeds until that gate opens. If Kahuna declines, ADR-013 becomes “won’t fix” — we keep shipping salesforce_query + salesforce_crm as the SFDC integration surface.

Follow-up for Mishaal: raise this with Kahuna leadership when the Agentforce pricing conversation becomes relevant. Not a Q2 2026 priority at current scale. Relates to: existing salesforce_query + salesforce_crm tools; Kahuna tenant (live on SFDC prod v67.0, PKCE OAuth); docs/daily-ai-review/2026-04-20.md item #1

At TDX 2026 (2026-04-15), Salesforce launched Headless 360. Core claim: “No browser required. Our API is the UI.” Concrete ship:

  • 60+ new MCP tools exposing Data 360, Customer 360, Agentforce, and Slack as first-class agent surface.
  • 30 preconfigured coding skills for Claude Code, Cursor, Codex, Windsurf.
  • Agentforce Vibes 2.0 (GA) — platform agent runtime.
  • DevOps Center MCP (GA) — natural-language deploys via CI/CD.
  • Session Tracing (GA) — per-agent observability.
  • Agentforce Experience Layer (GA) — one agent, renders natively across Slack + Voice without rebuild.
  • Custom Scoring Evals — early access. Testing Center — May. Salesforce Catalog — June.

Kahuna runs on SFDC prod and is our biggest SFDC integration surface. If V5’s salesforce_query and salesforce_crm are materially behind what Headless 360 exposes natively, we may be maintaining hand-rolled code with no edge.

ToolPathCapabilitiesLOC
salesforce_queryGET /services/data/{v}/query?q=SOQLRead only, SOQL~55
salesforce_crmPOST/PATCH/GET /services/data/{v}/sobjects/{obj}insert, update, describe~78
  • Version pinned in KV at api_config:salesforce.version (currently v67.0).
  • Auth via per-tenant per-account OAuth bearer, DO-managed refresh.
  • Instance URL per account from tenant_config.providers.salesforce.accounts[].instance_url.
  • No DevOps, no metadata ops, no platform events, no Agentforce invocation, no Slack bridge.

What Headless 360 adds that V5 doesn’t have

Section titled “What Headless 360 adds that V5 doesn’t have”
  1. Agentforce invocation as MCP tool — triggering agents from Claude Code / Cursor / V5.
  2. DevOps Center MCP — metadata retrieves, deploys, validations via natural language.
  3. Agent Experience Layer — one agent appearing in both Slack and Voice without rebuild. This is the path to Kahuna-as-a-Slack-bot without us maintaining Slack surface code.
  4. Session Tracing — first-class observability.
  5. Salesforce Catalog (June) — discovery index of available APIs per org. Equivalent to a live discover_apis for SFDC-only.
  6. 60+ specific object/workflow tools covering edges our salesforce_crm doesn’t hit (Flow triggers, CDC events, Platform Events, Einstein predictions, etc.).
  1. Multi-tenant isolation — V5 serves many tenants with distinct SFDC orgs. Headless 360 is per-org.
  2. Cross-provider unificationbatch_execute spans SFDC + HubSpot + Google Ads + GA4 + Gmail in one call. Headless 360 is SFDC-only.
  3. Our auth, rate-limit, routing, error-categorization, kv_audit layer — transparent to callers, provider-independent.
  4. Fail-fast contract + Slack alerting via waitUntil — our operational posture.
  5. Hand-curated schemas for the actions we actually use — ergonomic for common paths.

Adopt Headless 360 surgically, not wholesale. Three concrete changes:

Change 1 (required): Add salesforce_mcp pass-through tool

Section titled “Change 1 (required): Add salesforce_mcp pass-through tool”

A single new MCP tool in V5 that forwards calls to Salesforce’s Headless 360 MCP endpoint, layering our tenant auth + rate limit + error categorization on top.

src/tools/salesforce-mcp.ts
// Accepts: {tool, args, account_id?}
// Resolves Salesforce Headless 360 MCP endpoint from tenant_config
// (provider.salesforce.accounts[].headless360_endpoint)
// Calls through with our OAuth bearer; returns the MCP tool response.

Why: gives Kahuna access to all 60 Headless 360 tools without us re-implementing each. We still own the tenant dimension, rate limits, and observability. Pattern is the same as our existing call_api generic proxy, but specialized for SFDC MCP’s schema.

Change 2 (required): Keep salesforce_query and salesforce_crm

Section titled “Change 2 (required): Keep salesforce_query and salesforce_crm”

Do NOT retire them. They’re ergonomically cleaner than an MCP-over-MCP pass-through for the 80% case (a SOQL query, a contact insert). They’re tested, they work on Kahuna, and they’re an artifact of our cross-provider uniformity — callers can script HubSpot + SFDC with identical mental models.

Change 3 (optional, H2): Add 3 curated wrappers for specific Headless 360 capabilities

Section titled “Change 3 (optional, H2): Add 3 curated wrappers for specific Headless 360 capabilities”

Pick capabilities that genuinely expand V5 beyond what pass-through gives:

  • salesforce_devops — wrap DevOps Center MCP. Natural-language deploys are a V5-native workflow for multi-tenant SFDC config mgmt.
  • salesforce_agent_invoke — trigger Agentforce agents from V5 calls. Bridges our batch_execute to Agentforce’s agent runtime.
  • salesforce_platform_events — subscribe/publish to SFDC platform events. Pairs naturally with our DO-based token model.

Defer these until Change 1 is live and we see real Kahuna demand.

  • Do not mirror all 60 MCP tools. Maintenance burden outweighs ergonomic gain. Pass-through wins.
  • Do not adopt the Agentforce Experience Layer for Slack yet. It replaces our current Slack approach but bakes Kahuna into Salesforce’s agent pricing model. Evaluate pricing first (see risks).
  • Do not rebuild V5 on Headless 360’s agent runtime. V5’s orchestration lives on CF Workers for good reasons (edge latency, cost, multi-tenant). Headless 360 is a provider surface, not a platform substitute.
  1. Edition tier required. Is Headless 360 MCP available on Kahuna’s current SFDC edition, or does it require an Agentforce Enterprise add-on? Action: verify with SFDC before writing code. Blocker if paywalled.
  2. Pricing model. Agentforce bills per conversation/action. Does invoking a Headless 360 MCP tool count as a billable agent action, or is it closer to a free API call? Batch workloads could get expensive fast. Action: get pricing in writing before production.
  3. Authentication. Existing V5 SFDC OAuth should work for Headless 360 MCP (same org, same scopes) — but SFDC may require additional agent_write / mcp_tools scopes. Action: verify scope inventory before migration.
  4. Versioning. Headless 360 MCP tools may version independently of REST Data API v66. Our api_config:salesforce.version may need a second field (mcp_version). Minor schema change.
  • Pricing cliff. If Agentforce conversation pricing makes batch workflows unaffordable, Change 1 becomes a liability, not a win.
  • Availability skew. Headless 360 GA’d 2026-04-15 but Testing Center and Salesforce Catalog don’t land until May/June. We’d be building against a moving target.
  • Salesforce can turn off generous free-tier access at any time. Hand-rolled tools keep us insulated.
  • Minimal engineering. One new tool (~100 LOC). Kahuna gets expanded SFDC surface without us maintaining it.
  • Still locked into SFDC’s pricing and availability.
  • Deeper but more brittle. DevOps Center MCP in particular has real ops value for Kahuna and is stable enough.
  • V5 stays where it is. Kahuna keeps running on salesforce_query + salesforce_crm. We’re not worse off — but we’re not benefiting from 60+ tools that Salesforce is maintaining for us.

Ship Change 1 (salesforce_mcp pass-through) in the next build sprint, pending the 3 pre-implementation answers (edition, pricing, scopes). Defer Change 3 until Kahuna has a concrete use case that the pass-through can’t cleanly serve. Do not touch Changes marked non-goals.


Research Addendum (2026-04-20) — wire-level validation + refinement

Section titled “Research Addendum (2026-04-20) — wire-level validation + refinement”

The original recommendation (salesforce_mcp pass-through, keep existing curated tools, defer broader federation) is still correct. Deep research against MCP spec + Cloudflare constraints + MCP-gateway state-of-art confirms the direction but sharpens the implementation.

Wire-level facts (MCP Streamable HTTP spec, 2025-06-18)

Section titled “Wire-level facts (MCP Streamable HTTP spec, 2025-06-18)”

Headless 360 MCP, by virtue of interop with Claude Code / Cursor / Codex / Windsurf, is standard MCP over Streamable HTTP. The protocol is:

  • Single endpoint (POST + GET).
  • POST carries client→server JSON-RPC. Server responds either Content-Type: application/json (single response) or text/event-stream (SSE stream terminating with the JSON-RPC response).
  • GET opens a server→client SSE channel for server-initiated messages (important — this means not purely request/response; the server can push notifications, progress events, and sampling requests back).
  • Mcp-Session-Id header established at InitializeResult, required on all subsequent requests in the session.
  • MCP-Protocol-Version header required after initialize.
  • Resumability via Last-Event-ID.

Implication for our proxy:

  • Dumb HTTP reverse proxy is NOT sufficient for full MCP semantics (bidirectional server-push and sampling break it).
  • BUT for the 95% case (single tool call → single response), a single POST forward with SSE passthrough is perfectly adequate.
  • Durable Objects are the right home for session state if/when we need long-lived sessions.

State-of-art MCP gateway patterns (Gravitee / IBM ContextForge / AgentGateway / Arcade / Composio)

Section titled “State-of-art MCP gateway patterns (Gravitee / IBM ContextForge / AgentGateway / Arcade / Composio)”

Across production MCP gateways shipped Q1–Q2 2026, the dominant pattern is federation: one gateway endpoint aggregates many upstream MCP servers, with three levels of sophistication:

LevelPatternWhen to adopt
A. Single-tool pass-throughOne gateway tool salesforce_mcp(tool, args) forwards explicit tool calls to the upstream MCP endpoint.Starting point. ≤100 LOC. No session state.
B. Full tool federationGateway calls upstream tools/list at init, prefixes tool names (salesforce.query, salesforce.devops.deploy), merges into the gateway’s own tools/list response. Clients see one unified tool catalog.Once 2+ upstream MCPs matter AND total tool count stays under client caps (~40 on Cursor).
C. Retrieval-first federationGateway exposes a meta-tool find_tools(query) that BM25-searches upstream tool descriptions, returns top-K. Keeps context small even at 200+ tools.When total tool count exceeds client caps. Premature for us.

Cloudflare Workers as MCP gateway — constraint check

Section titled “Cloudflare Workers as MCP gateway — constraint check”
  • Worker request CPU limit: default 30s; our invariant #11 (30s outbound fetch) already aligns.
  • Worker bundle size: current 2,052 KiB / 397 KiB gzipped. Adding a mcp_federate primitive + salesforce_mcp wrapper estimated <50 KiB delta. Fits comfortably.
  • Native fetch supports SSE passthrough (streaming body). No proxy issue.
  • Durable Objects already in use for token management — extends naturally to MCP session state if we ever need Level B/C.
  • CF’s managed “AI Gateway” product has documented MCP buffering limitations. We are not using AI Gateway — V5 is custom Worker code, so those limitations don’t apply to us.

Keep the ADR-013 recommendation in shape but upgrade the abstraction from “one SFDC wrapper” to “generic MCP federation primitive, first consumer = SFDC.”

  1. Core primitive: src/core/mcp-proxy.ts (~200 LOC, not a provider-specific wrapper). Accepts a registered upstream MCP endpoint from KV config, handles JSON-RPC envelope, forwards tools/call requests, streams SSE responses back. Stateless per request (no session across requests). Session state lives in a Durable Object if/when needed.

  2. Tool: src/tools/salesforce_mcp.ts — thin binding that uses mcp-proxy with the upstream headless360_endpoint from tenant_config.providers.salesforce.accounts[]. Accepts {tool, args, account_id?}. ~40 LOC.

  3. Meta-tool: salesforce_mcp_list_tools — cached proxy of SFDC’s tools/list. Cache in KV at mcp_tools:salesforce:{account_id} with 1-hour TTL. Gives agents discoverability of 60+ tools without forcing V5’s top-level tool count to balloon.

  4. KV schema extensiontenant_config.providers.salesforce.accounts[].headless360_endpoint (string, e.g., https://kahuna.my.salesforce.com/services/mcp/v1) and .headless360_version (string, tracked separately from REST api_config:salesforce.version).

  5. DO NOT prefix-federate 60 SFDC tools into V5’s top-level tools/list. Level B is premature — it inflates the client’s context and we have no proven multi-upstream use case yet.

  • Lite: one generic primitive (mcp-proxy) serves any future upstream MCP server (Notion, HubSpot when they ship, anything). No per-provider mirror code. Bundle impact <50 KiB.
  • Powerful: Kahuna gets all 60 Headless 360 tools via one MCP tool call, with our tenant auth + rate limit + error contract intact. Adding a second upstream MCP in H2 is a KV config change, not an engineering project.
  • Cutting-edge without being naïve: we’re adopting the pattern Gravitee / IBM ContextForge / AgentGateway validated in Q1 2026 at the simplest tier (Level A), with a documented upgrade path (Level B → C) and no premature complexity.
  1. MCP sampling semantics. Some MCP tools invoke client-LLM “sampling” callbacks mid-execution. A stateless POST-forward proxy breaks this case. Mitigation: in the mcp-proxy primitive, detect sampling/createMessage in the response stream and return METHOD_NOT_SUPPORTED for now (or route back through an explicit client-capability check). Defer full sampling support to a later change.
  2. Session ID lifecycle. If Salesforce’s MCP server assigns a session ID on initialize, our proxy needs to track it across multiple client calls. For the initial Level-A pass-through used as a single tool call, we can initialize-then-close per invocation (stateless). Extra round trip per call (~80–150ms to SFDC) but no session bookkeeping. Acceptable tradeoff for v1.
  3. OAuth scope drift. Headless 360 likely wants agent_tools/mcp_invoke scopes. Existing Kahuna SFDC OAuth refresh will fail if the token was issued under old scopes. Pre-implementation blocker: re-issue Kahuna’s SFDC OAuth under the expanded scope set before shipping.

Is the salesforce_mcp pass-through the best thing to do?

Yes — but implemented as a generic mcp-proxy primitive with SFDC as the first consumer, not as a one-off SFDC wrapper. This keeps V5 lite (one primitive serves N upstreams), powerful (full Headless 360 surface accessible from one V5 tool), and cutting-edge (matches 2026 MCP-gateway state-of-art without the premature Level B/C complexity). Ship Level A, document the upgrade path, revisit when usage data demands it.

Non-negotiables before any code lands:

  • Verify Kahuna SFDC edition includes Headless 360 MCP access (not just Enterprise-gated).
  • Get Agentforce pricing-per-MCP-tool-call in writing.
  • Confirm the OAuth scopes needed, re-issue Kahuna’s token under expanded scopes.