<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Conor</title>
    <description>The latest articles on DEV Community by Conor (@conor_61d358cde152bb5800a).</description>
    <link>https://dev.to/conor_61d358cde152bb5800a</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3890612%2Fc2dd7522-9d3a-410f-b432-35c12fcd89ec.png</url>
      <title>DEV Community: Conor</title>
      <link>https://dev.to/conor_61d358cde152bb5800a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/conor_61d358cde152bb5800a"/>
    <language>en</language>
    <item>
      <title>Salesforce Headless! All agents, all access.</title>
      <dc:creator>Conor</dc:creator>
      <pubDate>Tue, 21 Apr 2026 22:30:34 +0000</pubDate>
      <link>https://dev.to/conor_61d358cde152bb5800a/salesforce-headless-all-agents-all-access-19ka</link>
      <guid>https://dev.to/conor_61d358cde152bb5800a/salesforce-headless-all-agents-all-access-19ka</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;This post walks through exactly how to wire that up: OAuth config, MCP connection, and what you can actually do once you're in.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Headless 360 Actually Changes
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Headless 360 reframes the whole stack. Salesforce now exposes 60+ MCP tools covering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data operations&lt;/strong&gt;: query records, create, update, upsert, delete (any standard or custom object)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation&lt;/strong&gt;: invoke named Flows, trigger Process Builder actions, run Apex methods via REST&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reporting&lt;/strong&gt;: execute saved reports and return structured data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agentforce&lt;/strong&gt;: start and resume Agentforce sessions, pass context, read session traces&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metadata&lt;/strong&gt;: describe objects, list picklist values, read field metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The underlying transport is &lt;a href="https://spec.modelcontextprotocol.io/specification/" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt; — JSON-RPC 2.0 over SSE or HTTP.&lt;sup id="fnref1"&gt;1&lt;/sup&gt; Your agent calls a tool (&lt;code&gt;salesforce_query&lt;/code&gt;, &lt;code&gt;salesforce_run_flow&lt;/code&gt;, etc.) and Salesforce executes it under the user's OAuth token.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Create an External Client App in Salesforce Setup
&lt;/h2&gt;

&lt;p&gt;Navigate to &lt;strong&gt;Setup → External Client Apps → New&lt;/strong&gt;.&lt;sup id="fnref2"&gt;2&lt;/sup&gt; You're creating an OAuth 2.0 client that your AI agent will use (claude for example).&lt;/p&gt;

&lt;p&gt;Key settings:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;App Name&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;MCP Agent&lt;/code&gt; (or whatever labels your use case)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API Name&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MCP_Agent&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OAuth Flow&lt;/td&gt;
&lt;td&gt;Authorization Code and Credentials&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Callback URL&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;https://claude.ai/oauth/callback&lt;/code&gt; (for Claude Desktop) or &lt;code&gt;http://localhost:7878/callback&lt;/code&gt; (for Claude Code / local agents)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Selected OAuth Scopes&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;api&lt;/code&gt;, &lt;code&gt;refresh_token&lt;/code&gt;, &lt;code&gt;sfap_api&lt;/code&gt;, &lt;code&gt;einstein_gpt_api&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;sfap_api&lt;/code&gt; scope unlocks Salesforce API Platform — required for Agentforce features.&lt;sup id="fnref3"&gt;3&lt;/sup&gt; Without it, the hosted MCP server returns 403s on agent-related tools. The &lt;code&gt;einstein_gpt_api&lt;/code&gt; scope is needed if you're routing through Einstein or hitting Prompt Builder endpoints.&lt;/p&gt;

&lt;p&gt;Save and copy the &lt;strong&gt;Consumer Key&lt;/strong&gt;. You'll need it in the next step.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Locate Your Org's MCP Server URL
&lt;/h2&gt;

&lt;p&gt;Every org's hosted MCP server endpoint follows this pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://&amp;lt;my-domain&amp;gt;.my.salesforce.com/mcp/v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;&amp;lt;my-domain&amp;gt;&lt;/code&gt; is your org's My Domain name.&lt;sup id="fnref4"&gt;4&lt;/sup&gt; You can confirm it under &lt;strong&gt;Setup → My Domain&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For a scratch org or Developer Edition org, it looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://myorgname-dev-ed.develop.my.salesforce.com/mcp/v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 3: Configure Your AI Client
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Claude Desktop
&lt;/h3&gt;

&lt;p&gt;Add this block to &lt;code&gt;~/Library/Application Support/Claude/claude_desktop_config.json&lt;/code&gt; (macOS) or &lt;code&gt;%APPDATA%\Claude\claude_desktop_config.json&lt;/code&gt; (Windows):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"salesforce"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"oauth"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://myorgname-dev-ed.develop.my.salesforce.com/mcp/v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"oauth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"clientId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YOUR_CONSUMER_KEY_HERE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"authorizationUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://login.salesforce.com/services/oauth2/authorize"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"tokenUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://login.salesforce.com/services/oauth2/token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"scopes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"refresh_token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sfap_api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"einstein_gpt_api"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart Claude Desktop, click the plug icon, and you'll be prompted to authorize against your org. After that, the &lt;code&gt;salesforce&lt;/code&gt; server appears in the tools panel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Claude Code (CLI)
&lt;/h3&gt;

&lt;p&gt;In your project root, create or update &lt;code&gt;.mcp.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"salesforce"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"oauth"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://myorgname-dev-ed.develop.my.salesforce.com/mcp/v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"oauth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"clientId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YOUR_CONSUMER_KEY_HERE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"authorizationUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://login.salesforce.com/services/oauth2/authorize"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"tokenUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://login.salesforce.com/services/oauth2/token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"scopes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"refresh_token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sfap_api"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp auth salesforce
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Code opens a browser tab, you authenticate, and the token is stored locally. Subsequent runs reuse the refresh token.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cursor / Windsurf / Other MCP Clients
&lt;/h3&gt;

&lt;p&gt;These clients follow the same JSON format — they read a config file (usually &lt;code&gt;mcp.json&lt;/code&gt; or similar) and handle the OAuth flow on first connect. Consult your client's docs for the exact config file location.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: What You Can Do With It
&lt;/h2&gt;

&lt;p&gt;Once connected, here's a taste of what's now available to your agent without writing any integration code:&lt;/p&gt;

&lt;h3&gt;
  
  
  SOQL Query
&lt;/h3&gt;

&lt;p&gt;The agent can call &lt;code&gt;salesforce_query&lt;/code&gt; with a SOQL string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StageName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CloseDate&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Opportunity&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;StageName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Negotiation/Review'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;CloseDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;THIS_QUARTER&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Results come back as structured JSON. Your agent can reason over them, generate follow-up queries, or feed them into another tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trigger a Flow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tool"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"salesforce_run_flow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"flowApiName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Case_Escalation_Auto_Assign"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"inputs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"caseId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5001R00000EXAMPLE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"escalationReason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SLA breach detected by monitoring agent"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The MCP server runs the Flow in the context of the authenticated user and returns output variables.&lt;sup id="fnref5"&gt;5&lt;/sup&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Invoke Apex via REST
&lt;/h3&gt;

&lt;p&gt;If you've exposed an Apex class as a REST resource, the agent can call it directly:&lt;sup id="fnref6"&gt;6&lt;/sup&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight apex"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RestResource(&lt;/span&gt;&lt;span class="n"&gt;urlMapping&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s2"&gt;/agent/summarize-account/*'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;global&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AccountSummaryResource&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@HttpGet&lt;/span&gt;
    &lt;span class="kd"&gt;global&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;summarize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;accountId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RestContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;requestURI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substringAfterLast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s2"&gt;/'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Account&lt;/span&gt; &lt;span class="n"&gt;acct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Industry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AnnualRevenue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Status&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Cases&lt;/span&gt; &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;CreatedDate&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Account&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;accountId&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s2"&gt;accountName'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;acct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s2"&gt;industry'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;acct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Industry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s2"&gt;annualRevenue'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;acct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;AnnualRevenue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s2"&gt;recentCases'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;acct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Cases&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent calls this via &lt;code&gt;salesforce_apexRest&lt;/code&gt; with the endpoint path and method. Your Apex runs server-side with full platform access.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scope Gotchas and Common Issues
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;sfap_api&lt;/code&gt; scope isn't showing in your External Client App?&lt;/strong&gt; It's only available if Agentforce is provisioned in your org.&lt;sup id="fnref3"&gt;3&lt;/sup&gt; Developer Edition orgs now include this by default post-TDX; sandbox orgs tied to Enterprise Edition may need Agentforce licensing enabled first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token expiry&lt;/strong&gt;: Salesforce access tokens expire after the session timeout configured in your org (default 2 hours).&lt;sup id="fnref7"&gt;7&lt;/sup&gt; The &lt;code&gt;refresh_token&lt;/code&gt; scope handles silent renewal, but if you've set a stricter session policy, agents will hit 401s mid-session. Check &lt;strong&gt;Setup → Session Settings → Force relogin after&lt;/strong&gt; and set it to &lt;code&gt;None&lt;/code&gt; for agent-facing External Client Apps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IP restrictions&lt;/strong&gt;: 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read-only vs. read-write&lt;/strong&gt;: 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.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where to Start
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Spin up a Developer Edition org&lt;/strong&gt; — post-TDX, every new DE org comes with Hosted MCP Servers pre-enabled at no cost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create your External Client App&lt;/strong&gt; with the scopes above and wire it to Claude Desktop or Claude Code using the config shown here.[2]&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Start with read-only queries&lt;/strong&gt; — verify the connection works by asking your agent to pull 10 open Opportunities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Layer in Flow invocation&lt;/strong&gt; — pick a simple, well-tested Flow and let the agent trigger it from a natural language request.&lt;sup id="fnref5"&gt;5&lt;/sup&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add custom Apex REST endpoints&lt;/strong&gt; for anything the 60+ built-in MCP tools don't cover — your business logic, your custom objects, your integration patterns.&lt;sup id="fnref6"&gt;6&lt;/sup&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;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.&lt;/p&gt;







&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://spec.modelcontextprotocol.io/specification/" rel="noopener noreferrer"&gt;Model Context Protocol specification&lt;/a&gt; — Official MCP spec. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;&lt;a href="https://help.salesforce.com/s/articleView?id=sf.external_client_apps_overview.htm&amp;amp;type=5" rel="noopener noreferrer"&gt;External Client Apps overview&lt;/a&gt; — Salesforce Help. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;&lt;a href="https://help.salesforce.com/s/articleView?id=sf.remoteaccess_oauth_scopes.htm&amp;amp;type=5" rel="noopener noreferrer"&gt;OAuth scopes reference&lt;/a&gt; — Salesforce Help. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;&lt;a href="https://help.salesforce.com/s/articleView?id=sf.domain_name_overview.htm&amp;amp;type=5" rel="noopener noreferrer"&gt;My Domain overview&lt;/a&gt; — Salesforce Help. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn5"&gt;
&lt;p&gt;&lt;a href="https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_process_rules.htm" rel="noopener noreferrer"&gt;Invoke a Flow via REST&lt;/a&gt; — Salesforce REST API Dev Guide. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn6"&gt;
&lt;p&gt;&lt;a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_rest.htm" rel="noopener noreferrer"&gt;Apex REST web services&lt;/a&gt; — Salesforce Apex Dev Guide. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn7"&gt;
&lt;p&gt;&lt;a href="https://help.salesforce.com/s/articleView?id=sf.security_networkaccess.htm&amp;amp;type=5" rel="noopener noreferrer"&gt;Session security settings&lt;/a&gt; - Salesforce Help. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>salesforce</category>
      <category>agentforce</category>
      <category>ai</category>
      <category>mcp</category>
    </item>
  </channel>
</rss>
