Hey folks, Abhi here!
I’ve spent the last few weeks testing Salesforce Headless 360 hands-on: connecting Claude to my org through a custom MCP server and letting the agent call my own automation as a tool. When it works, it feels like magic. When it doesn’t, you get one very unhelpful sentence and a trip back into Setup.
In this post I’ll cover what I tested, what broke, how I debugged it, and what I think has to evolve before Headless 360 is ready for real-world agent work. I’ll also share what you can do today so your agents aren’t flying blind.
Let’s get into it.
First, a Quick Refresher on Headless 360
If you haven’t been following along, Headless 360 is Salesforce’s big push to make the platform usable without the UI. Salesforce made Hosted MCP Servers generally available in April, and followed up with the Headless 360 MCP Server in Beta in early July.
MCP (Model Context Protocol) is the open standard that lets AI clients like Claude, ChatGPT or Cursor call tools in other systems. With Hosted MCP Servers, Salesforce handles the hosting, authentication and permission enforcement for you.
The part admins should care about most is custom MCP servers. You can expose Apex Invocable Actions, @AuraEnabled methods, Apex REST methods, Flows and Named Queries as MCP tools without writing connector code. Your existing automation can become an agent tool with a bit of configuration in Setup.
Things have also moved quickly since spring. Salesforce has since expanded Headless 360 with a Data 360 MCP Server, a Slackbot MCP Client, more than 100 reusable Agent Skills, and capabilities across Marketing, Sales, Service, Commerce and more.
So the vision is clear: agents do the work, and Salesforce provides the trusted business logic underneath.
What I Tested
My setup was simple:
- A custom MCP server in my org, exposing one custom tool
- The tool takes a handful of inputs, creates a couple of records and returns two IDs as outputs
- Claude as the MCP client, connected through OAuth
I gave Claude the inputs in plain English, and it mapped them to the tool’s input schema and called it. On a successful run, I got both IDs back within seconds.
That’s the dream scenario: no clicking through tabs, no screen flows, just a conversation.
What Happened When It Failed
The first two attempts didn’t succeed. Here’s everything the agent got back:
UNKNOWN_EXCEPTIONAn error occurred when executing...
It didn’t include:
- Which step failed
- The actual error message
- Any field-level detail
- Anything about a validation rule, a duplicate rule, a missing field or a null value
The agent had nothing to work with. It couldn’t tell whether my inputs were wrong, whether I lacked a permission or whether the automation itself was broken. All it could do was tell me something failed and suggest places to look.
This is the core problem. An agent can only reason about what it can see. When a human hits an error in the UI, at least there’s a toast message or an error screen to go on. Here the agent got one generic line, which is less information than a human would see.
The Debugging Detour
So, back into Salesforce. Here’s the checklist I worked through, and it’s worth bookmarking if you’re building MCP tools.
Step 1: Figure Out Who the Call Runs As
My first question was whether this ran as an integration user or as me. For Hosted MCP, the answer is clear: every transaction runs as the authenticated user, scoped through an External Client App with the mcp_api scope, and CRUD, FLS, sharing rules, profile permissions and permission sets all apply.
In my case, that meant my own System Administrator user, which ruled out most permission issues right away.
Admin tip: You can confirm the running user by querying ApexLog and checking the LogUser field. The Operation field shows the exact action endpoint that was invoked, so you can match logs to tool calls.
Step 2: Set a Trace Flag
Go to Setup → Debug Logs and add a trace flag for the user who authenticated the MCP connection. Without one, you won’t capture anything.
Step 3: Raise the Debug Level
This one caught me. My first logs were tiny, around 1.5 KB for the whole transaction, because the default debug level barely logs declarative automation details.
Set the Workflow category to FINER, with Apex Code and Database at INFO or higher. After that change, the logs showed element-level detail.
Step 4: Read the Log
Search the log for error events. The line just before the error usually names the element that failed and the real underlying message. That’s the context the agent should have received in the first place.
A Twist
After I raised the debug levels and retried with identical inputs, the call succeeded. That makes it hard to say exactly what went wrong in the earlier runs, and it shows why capturing the real error at the moment of failure matters so much. If the tool response had carried the detail, I’d have my root cause instead of a guess.
Why This Matters More for Agents Than for Humans
You might think this is just normal Salesforce debugging, and you’d be right. Admins have been reading debug logs for years.
The context has changed, though. Headless means the person using the tool may never open Salesforce. It could be a sales rep in Claude, a support agent in Slack, or another agent in an automated chain. When something fails:
- The end user can’t debug it. They don’t have access to Setup and shouldn’t need it.
- The agent can’t recover. It doesn’t know whether to retry, fix an input or stop.
- The admin gets pulled in for issues the agent could have handled with a clear error.
Salesforce’s own pitch for the Headless 360 MCP Server is that agents understand the relationships, permissions, workflows, validation rules and governance behind how the business operates. I love that. But if the agent understands validation rules on the way in, it should also hear about them on the way out.
What Needs to Evolve
Here’s my wishlist for the Salesforce product team:
- Return the real fault message in the tool response. If a validation rule blocks the save, pass along the validation rule’s error message. If a required field is missing, name the field.
- Identify the failing step. Even just the element or method name would cut debugging time dramatically.
- Keep error codes specific.
UNKNOWN_EXCEPTIONshould be a last resort, not the default. - Give agents safe, scoped access to execution context, so a user with the right permissions doesn’t need a human to set trace flags and dig through logs.
- Add observability for MCP calls in Setup. A simple view of recent tool invocations, their inputs, outcomes and errors would be a big help.
Headless only really works if debugging works without the browser too.
What You Can Do Today
You don’t have to wait for Salesforce. Here’s how I’m building MCP tools now:
- Handle faults explicitly. Catch errors in your automation rather than letting them bubble up unhandled. An unhandled fault is what produces the generic exception.
- Return errors as outputs. Add output variables like
isSuccessanderrorMessage, and populate them in your fault handling. The agent then gets a readable error and can act on it. - Write helpful validation rule messages. “Phone must include country code, e.g. +91” gives an agent something to fix. “Invalid value” doesn’t.
- Describe your tools well. When an MCP client lists tools, the agent sees only a name, a description, an input schema and an output schema. Spell out input formats in the description, such as dates as YYYY-MM-DD and phone numbers with country code.
- Keep a debug checklist ready: the running user, a trace flag, Workflow at FINER, and a quick ApexLog query.
- Test in a sandbox first. Custom MCP servers can be deployed via Metadata API between sandboxes and production, so treat them like any other metadata and test before you promote.
Wrapping Up
I’m genuinely excited about Headless 360. Calling trusted Salesforce logic from any AI client, with permissions enforced for you, is a big shift for how our users will work.
But agents are only as good as the feedback they get. Right now, when a custom tool fails, the agent is mostly in the dark and an admin ends up in Setup reading logs. For headless to be production-ready, error handling has to evolve along with everything else.
Until then, build your tools defensively, return meaningful errors and keep your debug checklist handy.
Have you tried Headless 360 or custom MCP servers yet? Hit the same wall? Let me know in the comments. I’d love to hear how you’re handling it.
Happy building! 🚀
Leave a comment