Salesforce Headless! All agents, all access.
Salesforce just flipped a switch at TDX 2026 that matters more than most announcements in recent memory: your Salesforce org is now an MCP server. Every Developer Edition org ships with Salesforce Hosted MCP Servers at no cost, and any MCP-compatible AI agent — Claude, Claude Code, Cursor, Codex, Windsurf — can now read data, trigger flows, run SOQL, and invoke Apex directly, with no browser involved. This post walks through exactly how to wire that up: OAuth config, MCP connection, and what you can actually do once you're in. Before Headless 360, connecting an external agent to Salesforce meant either writing your own connected app + REST adapter or cobbling together a third-party library. The platform wasn't designed to be consumed by agents; it was designed for humans clicking through tabs. Headless 360 reframes the whole stack. Salesforce now exposes 60+ MCP tools covering: Data operations: query records, create, update, upsert, delete (any standard or custom object) Automation: invoke named Flows, trigger Process Builder actions, run Apex methods via REST Reporting: execute saved reports and return structured data Agentforce: start and resume Agentforce sessions, pass context, read session traces Metadata: describe objects, list picklist values, read field metadata The underlying transport is Model Context Protocol — JSON-RPC 2.0 over SSE or HTTP.1 Your agent calls a tool (salesforce_query, salesforce_run_flow, etc.) and Salesforce executes it under the user's OAuth token. Navigate to Setup → External Client Apps → New.2 You're creating an OAuth 2.0 client that your AI agent will use (claude for example). Key settings: Field Value App Name MCP Agent (or whatever labels your use case) API Name MCP_Agent OAuth Flow Authorization Code and Credentials Callback URL https://claude.ai/oauth/callback (for Claude Desktop) or http://localhost:7878/callback (for Claude Code / local agents) Selected OAuth Scopes api, refresh_token, sfap_api, einstein_gpt_api The sfap_api scope unlocks Salesforce API Platform — required for Agentforce features.3 Without it, the hosted MCP server returns 403s on agent-related tools. The einstein_gpt_api scope is needed if you're routing through Einstein or hitting Prompt Builder endpoints. Save and copy the Consumer Key. You'll need it in the next step. Every org's hosted MCP server endpoint follows this pattern: https://.my.salesforce.com/mcp/v1 Where is your org's My Domain name.4 You can confirm it under Setup → My Domain. For a scratch org or Developer Edition org, it looks like: https://myorgname-dev-ed.develop.my.salesforce.com/mcp/v1 Add this block to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows): { "mcpServers": { "salesforce": { "type": "oauth", "url": "https://myorgname-dev-ed.develop.my.salesforce.com/mcp/v1", "oauth": { "clientId": "YOUR_CONSUMER_KEY_HERE", "authorizationUrl": "https://login.salesforce.com/services/oauth2/authorize", "tokenUrl": "https://login.salesforce.com/services/oauth2/token", "scopes": ["api", "refresh_token", "sfap_api", "einstein_gpt_api"] } } } } Restart Claude Desktop, click the plug icon, and you'll be prompted to authorize against your org. After that, the salesforce server appears in the tools panel. In your project root, create or update .mcp.json: { "mcpServers": { "salesforce": { "type": "oauth", "url": "https://myorgname-dev-ed.develop.my.salesforce.com/mcp/v1", "oauth": { "clientId": "YOUR_CONSUMER_KEY_HERE", "authorizationUrl": "https://login.salesforce.com/services/oauth2/authorize", "tokenUrl": "https://login.salesforce.com/services/oauth2/token", "scopes": ["api", "refresh_token", "sfap_api"] } } } } Then run: claude mcp auth salesforce Claude Code opens a browser tab, you authenticate, and the token is stored locally. Subsequent runs reuse the refresh token. These clients follow the same JSON format — they read a config file (usually mcp.json or similar) and handle the OAuth flow on first connect. Consult your client's docs for the exact config file location. Once connected, here's a taste of what's now available to your agent without writing any integration code: The agent can call salesforce_query with a SOQL string: SELECT Id, Name, StageName, Amount, CloseDate FROM Opportunity WHERE StageName = 'Negotiation/Review' AND CloseDate = THIS_QUARTER ORDER BY Amount DESC LIMIT 20 Results come back as structured JSON. Your agent can reason over them, generate follow-up queries, or feed them into another tool. { "tool": "salesforce_run_flow", "parameters": { "flowApiName": "Case_Escalation_Auto_Assign", "inputs": { "caseId": "5001R00000EXAMPLE", "escalationReason": "SLA breach detected by monitoring agent" } } } The MCP server runs the Flow in the context of the authenticated user and returns output variables.5 If you've exposed an Apex class as a REST resource, the agent can call it directly:6 @RestResource(urlMapping='/agent/summarize-account/*') global class AccountSummaryResource { @HttpGet global static Map summarize() { String accountId = RestContext.request.requestURI.substringAfterLast('/'); Account acct = [SELECT Id, Name, Industry, AnnualRevenue, (SELECT Id, Name, Status FROM Cases ORDER BY CreatedDate DESC LIMIT 5) FROM Account WHERE Id = :accountId LIMIT 1]; return new Map{ 'accountName' => acct.Name, 'industry' => acct.Industry, 'annualRevenue' => acct.AnnualRevenue, 'recentCases' => acct.Cases }; } } The agent calls this via salesforce_apexRest with the endpoint path and method. Your Apex runs server-side with full platform access. sfap_api scope isn't showing in your External Client App? It's only available if Agentforce is provisioned in your org.3 Developer Edition orgs now include this by default post-TDX; sandbox orgs tied to Enterprise Edition may need Agentforce licensing enabled first. Token expiry: Salesforce access tokens expire after the session timeout configured in your org (default 2 hours).7 The refresh_token scope handles silent renewal, but if you've set a stricter session policy, agents will hit 401s mid-session. Check Setup → Session Settings → Force relogin after and set it to None for agent-facing External Client Apps. IP restrictions: If your org uses Login IP Ranges on the profile, agent requests coming from cloud-hosted AI services will fail. Either relax IP restrictions on the profile assigned to the External Client App, or use a dedicated Integration profile with no IP range restrictions. Read-only vs. read-write: You control what the MCP server can do by scoping the connected user's profile and permission sets. Run agents as a dedicated integration user with only the object-level permissions they need. Spin up a Developer Edition org — post-TDX, every new DE org comes with Hosted MCP Servers pre-enabled at no cost. Create your External Client App with the scopes above and wire it to Claude Desktop or Claude Code using the config shown here.[2] Start with read-only queries — verify the connection works by asking your agent to pull 10 open Opportunities. Layer in Flow invocation — pick a simple, well-tested Flow and let the agent trigger it from a natural language request.5 Add custom Apex REST endpoints for anything the 60+ built-in MCP tools don't cover — your business logic, your custom objects, your integration patterns.6 Headless 360 is the most architecturally significant thing Salesforce has shipped for developers in years. The platform is finally designed to be consumed by code — and agents — and not just browsers. Model Context Protocol specification — Official MCP spec. ↩ External Client Apps overview — Salesforce Help. ↩ OAuth scopes reference — Salesforce Help. ↩ My Domain overview — Salesforce Help. ↩ Invoke a Flow via REST — Salesforce REST API Dev Guide. ↩ Apex REST web services — Salesforce Apex Dev Guide. ↩ Session security settings - Salesforce Help. ↩
