What makes an MCP Headless?

What makes an MCP Headless?
A disorderly mob is no more an army than a heap of building materials is a house -Socrates

"Headless" is a programming term, and it's older than the AI conversation now borrowing it. It describes a simple situation: a program wants to work with an application through its APIs, and it isn't going to use the web page to do it. The "head" is the user interface. The browser, the screens, the buttons. Run without the head, and you're headless.

The classic example is the headless browser. A headless copy of Chrome fetches pages, runs the JavaScript, renders the layout, and no window ever appears. You get the web page without going to the web page. Test suites do this. Crawlers do this. It's mundane, well-understood plumbing: expose the capability, skip the browser.

So far, headless just sounds like "use the API instead of the UI." If that were all it meant, it wouldn't be worth a blog post. You shipped headless the day you published API docs.

Tutorial on Headless Builds

The part everyone misses: the head is where the logic lives

Here's the thing about twenty-five years of web application development: the API and the user interface were never equals. The API returns records. The application, the part that makes those records useful, lives in the head.

The GUI knows which of the forty fields on a record actually matter. It knows what order to ask questions in. It knows that this status value is fine and that one is a problem, that these three screens are really one workflow, that this button shouldn't be pressed until that check passes. None of that is in the API. The API is a parts bin; the GUI is the assembled machine.

You don't have to take that on faith, because you can audit it on any screen you own. Open a record in your own product's console and watch the network tab. In our product, opening a single investigation case fires half a dozen calls: the record itself, the lookups that turn raw identifiers into names a human can read, and a bounded search the page derived on its own, with the right entities and the right time window already chosen. The API's answer to "get this case" is a dozen lines of JSON. The screen the analyst sees was assembled from six calls and a decade of judgment about what matters. That assembly exists in no single API response. It exists only in the head.

That's why "just use the API" has always been harder than it sounds. Strip the head off a typical application and what's left isn't the application. It's raw material. Every integration team that has glued API calls together knows this: you end up rebuilding the application logic yourself, call by call, in your own code, badly.

What headless means in the AI world

Now the term crosses into AI, and its meaning shifts in an important way.

When we say an application is headless in the AI world, we don't just mean the agent can reach the APIs. We mean the application logic that used to live in the GUI is now accessible through the MCP, the Model Context Protocol surface the agent connects to.

That's the whole difference. An agent pointed at raw APIs inherits the parts bin: it has to guess which fields matter, guess the sequencing, guess what a value means. An agent connected to a real headless application inherits the assembled machine: the capabilities it discovers already carry the workflow, the interpretation, the guardrails, everything the screens used to carry.

Put another way: the GUI existed to teach a person how to operate the application. The MCP exists to teach an agent the same thing. The teaching target moved. The head didn't disappear. It was rebuilt for a different kind of operator.

The version of this that ships constantly, and fails constantly, is the press-release MCP. A vendor announces support, you connect your agent, and you get one tool: search_events(query: string). Ask it the question an operator actually asks on a Monday morning, which of my log sources went quiet this week?, and count what the agent has to invent. It fabricates query syntax it has never seen, guesses which of three candidate fields carries a source's identity, and picks a staleness threshold that your product has an answer for and the tool doesn't carry. Underneath all of that sits a problem no search can solve: a source that stopped reporting isn't in the results at all. You cannot search your way to an absence.

Then comes the finale. The invented query runs, matches nothing, and the agent reports back with complete confidence: everything looks healthy. Understand what kind of problem this is. It is not an AI problem, because a smarter model makes the same guesses more eloquently. It is not a prompting problem, because you cannot prompt your way into knowledge the surface never carried. It is a tool design problem, and in operational software an empty answer that arrives as reassurance is the single most dangerous thing you can hand a caller.

The fix is a design decision, and you can see it in one comparison. Here are two returns for the same question over the same window:

{ "sources": [] }

Raw Call Response

{ "sources": [],  "expected_source_count": 14,  "query_status": "completed",  "coverage": "0 of 14 expected sources returned data",  "interpretation": "no_sources_reporting",  "severity": "critical" }

AI Ready Call Response

Same data. The agent reads the first as good news and the second as an incident, and one of them gets a customer breached. It is not the one that looks alarming.

Designing the capability surface

Converting an application, then, is not exposing endpoints. It is extracting what the screens know and rebuilding it as capabilities, and one rule governs the work: name every capability after an outcome an operator asks for, never after a resource. get_datasource(id) describes what the system stores. Evaluate this tenant's data-source health describes what someone wants. The test for the whole surface is simple. If the agent has to chain four calls and apply your thresholds itself to answer a routine question, you haven't converted the screen. You've moved the parts bin to a new protocol. One capability answers one question, completely.

What moves into each capability is everything the screen used to know. The gathering moves, so the caller asks once instead of orchestrating the page's call sequence by hand. The judgment moves with it: a health capability returns the verdict that a source is stale and the reason why, not a raw timestamp for the caller to threshold on its own, because a threshold that ships inside the tool is versioned and testable in a way a color in the CSS never was. And the screen's honesty about gaps moves too. When data is missing, the capability says so in a populated field with a stated reason, and when a precondition fails, it refuses with the reason and the remedy. The disabled button becomes a structured no. We already know what an empty result becomes.

Even the field names carry weight here. A field called score forces the agent to guess: score of what, out of what, and is higher better or worse? A field name is documentation the agent actually gets to see. Spend it.

The headless SIEM

Apply this to our own field, security operations, and you get the headless SIEM. It is the worked example behind everything above.

A SIEM's head is enormous. Dashboards that tell you which telemetry sources are healthy. Case screens that walk an analyst through triage. Query builders that encode what a sensible question looks like. Report pages that know what a monthly SOC summary contains. Decades of operational knowledge, all of it expressed as screens, which means all of it locked behind a human who has been trained on those screens.

A headless SIEM takes that operating logic out of the screens and exposes it through MCP as governed capabilities: check this tenant's data-source healthexpand this case with its captured events and historybuild the monthly report for this customer. The person's role changes accordingly. They stop operating the console and start describing outcomes. "Is this case real?" "Which sources went quiet this week?" "Build the board report." Their agent works the surface; the platform underneath stays deterministic and auditable.

But nothing in the conversion is SIEM-specific. The same method applies to any product whose screens know things its API doesn't, which is to say nearly every web application ever shipped.

Security moves to the MCP line

The trust boundary used to sit between the browser and the API, and that's where twenty years of security engineering lives: keys, routes, access lists. The conversion has an uncomfortable consequence for that line. It can no longer hold the security, because the agent never touches it directly. One capability call fans out into six API calls underneath, and a key that authorizes those endpoints authorizes them for every purpose, in any combination, forever. The API sees traffic. It cannot see the question.

The MCP line is different in kind. It is where the operator's intent arrives whole, as one call with one question and one scope, which makes it the only place authorization can mean anything. So the controls get rebuilt there, as part of the surface itself. Access control starts before any call is made, because the role decides what the surface even looks like: a tenant operator's surface simply never contains cross-tenant capabilities, not refused but absent, and in that sense the tool list itself is access control. Each call then resolves to the signed-in principal with entitlement checked server-side, since a caller-supplied tenant identifier can never be trusted. An agent is a very fluent, very confident source of arguments it made up. A capability that changes anything says so in its description and demands that the caller say so in the call, because a mutation must never be a side effect of a question; asking about a case must never close the case. And the audit log finally records the thing compliance always wanted. Not page views. Not requests. Intent: who asked what, of which tenant, and what they learned, answerable in one query.

Trust stops being a wrapper you put around the surface. Trust becomes surface design.

Why this matters now, and how you know you're done

The interface to operational software has already changed, whether or not the tools have caught up. Increasingly, the person doesn't read the dashboard; their AI assistant does. Engineering effort spent making screens that teach humans is effort spent on an operator who is no longer the one looking. And the agent is the least forgiving integrator you will ever ship to. A person fills your product's gaps with experience. An agent fills them with confident guesses.

There is a number that tells you the conversion is working, and it is not tool count or endpoint coverage, both of which are measurable while the thing still doesn't work. Take an agent with no custom prompting, no examples, no hand-holding. Point it at your surface, cold, and give it the twenty questions your operators actually ask, in their own words. The number that answers correctly on the first try is your conversion score. It moves when the names get clearer, the descriptions get sharper, and the judgments get ported, and it is worth running every release.

Because in the end, your tool list is your product's vocabulary. It is the set of words an agent gets to think in. Headless doesn't mean the application lost its head. It means the head was rebuilt for the operator who actually showed up.