# Only Inert Definitions Cross the Boundary

> Source: <https://dev.to/synthaicode_commander/only-inert-definitions-cross-the-boundary-1jdf>
> Published: 2026-06-26 13:57:32+00:00

In my previous two posts, I argued that MCP is more useful as a context distribution layer than as RPC, and that `AGENTS.md`

should be a bootloader, not a knowledge base.

Both posts described context as something delivered **in stages**.

Startup context first.

Skill catalog next.

Domain rules when routed.

Authoritative documents when resolved.

Volatile state only when needed.

That description answered one question:

How many stages are there?

But it quietly avoided a second question:

On which side of the boundary does each stage run?

This is the question that actually matters when you build the server.

A stage is not just a point in time.

It is also a point in space.

Some things happen on the MCP server.

Some things happen on the client.

And the line between them is not arbitrary.

When I built the [MCP layer](https://github.com/synthaicode/XRefkit.MCP) for [XRefKit](https://github.com/synthaicode/XRefKit), I settled on one rule that decided almost everything else:

Only inert definitions cross the transport boundary.

An inert definition is executable guidance without execution.

It defines how work must be performed, but never performs the work itself.

It is not the result of doing the work.

Concretely, what crosses the boundary is things like:

What does **not** cross the boundary is the act of applying any of that.

The server can tell the client *what counts as a valid review*.

The server does not perform the review.

This splits the system into two planes.

**Server-side plane: catalog and routing.**

It knows what skills exist, what each skill requires, and how to map a work intent to a skill definition.

**Client-side plane: execution.**

It reads the actual code, walks the actual constraints, records the actual unknowns, and reaches the actual closure decision.

The server distributes judgment axes.

The client does the judging.

Abstractions hide where the boundary really is. So here is a single request, traced end to end.

A developer expresses an intent:

Validate this change against known constraints.

**Step 1 — client asks the server to route the intent.**

The client does not yet know which domain skill applies. It sends the intent to the catalog plane and asks for resolution.

This is semantic routing, not command routing. The client is not saying "run tool X." It is saying "this is the kind of work I am about to do."

**Step 2 — server returns a skill definition. Inert.**

The server resolves the intent to a domain skill and returns its *definition*:

Notice what did **not** come back: a validation result.

The server did not read the change. It did not check anything. It returned the *rules of checking*, not a check.

This is the whole point of "inert." The payload is a contract, not an outcome.

**Step 3 — client executes against the definition.**

Now the execution plane does the work the definition describes:

All of this is local. None of it crossed the boundary.

**Step 4 — closure is evaluated, not assumed.**

The closure contract came from the server. But the act of deciding whether closure is allowed happens on the client, against real findings.

If an unresolved unknown remains, closure is blocked.

If a forbidden assumption was required to proceed, the work halts and escalates.

The server defined the stop condition.

The client encountered it.

It would be easy to read the two planes as an engineering convenience. Keep the heavy catalog on a server, keep the runtime light on the client. True, but not the real reason.

The real reason is that the boundary lines up with something deeper.

The server can only distribute judgment that has already been **externalized**.

A closure condition is distributable because someone wrote down what "done" means for this kind of work. A forbidden-assumption list is distributable because someone made the implicit rule explicit. An unknown-stop condition is distributable because someone decided, in advance, which gaps are not allowed to be papered over with fluent text.

These are externalized judgment axes. Inert. They cross.

But the act of judging against them at runtime — reading this specific code, weighing this specific risk, deciding whether this specific closure is honest — that does not become a transferable artifact just because the axes did.

So the boundary is really a test:

If a piece of judgment can be written as an inert definition, it belongs on the server.

If it cannot, it stays where the work happens.

The two-plane split is not a transport decision. It is a line drawn through judgment itself.

Here is the part I could not write in the first two posts, because I had not located the boundary precisely enough.

A domain skill distributes closure conditions, stop rules, and evidence requirements. That looks like it distributes judgment.

But distributing the *axis* of a judgment is not the same as distributing the *judgment*.

When the server hands a client the closure contract, it is distributing the standardized part — the criteria that someone already coordinated, agreed on, and externalized. Applying those criteria to real findings is execution against a fixed axis. That part is delegable. It is, in the most precise sense, work that supports a decision.

What does not cross is the last step: deciding, with stakeholders, that *this* closure is acceptable in *this* situation — and owning that decision. No contract removes that. The moment a case falls outside the externalized axis, the work stops and returns to a human, because the coordination that would resolve it was never externalized in the first place.

By coordination, I do not mean communication. I mean the process of reaching new shared judgment that has not yet been externalized.

That is why the inert boundary matters beyond performance.

The MCP boundary ends up sitting exactly where externalized judgment ends and live coordination begins.

Everything that can be turned into a definition is distributable, and therefore delegable.

Everything that still requires coordination stays on the human side, and never crosses.

The two-plane design did not impose that line. It revealed it.

I built this on MCP, but the boundary is not an MCP property.

This principle is not specific to MCP. Any system that distributes domain knowledge eventually discovers the same boundary.

Transport only distributes externalized judgment. Execution always remains local.

MCP made the boundary easy to see, because it gives named entry points and a clean transport. But a team sharing a wiki, a platform shipping policy bundles, a company writing runbooks — all of them hit the same wall the moment they try to distribute not just *what is known* but *how to decide*. The part that can be written down travels. The part that still needs a human to coordinate a new judgment does not.

The protocol changes how far the inert part can travel. It does not move the line.

Across these three posts the question kept narrowing.

First: is MCP RPC, or something else?

Then: should the bootloader hold knowledge, or point to it?

Now: where, physically, does judgment get distributed, and where does it refuse to?

The answer the implementation gave me is sharper than the one I started with.

A skill can distribute judgment axes.

It cannot distribute the act of judging.

The transport boundary, if you draw it honestly, is just the second sentence made mechanical.

Only inert definitions cross.

Everything that still needs coordination stays home.
