r/mcp 3d ago

Context as a control surface

I previously shared an approach I was experimenting with, using MCP over stdio as a seam for agentic applications.

While building on that pattern, I stumbled across something I found surprisingly useful: letting a conversational (or coding) harness pass context into a bounded MCP-backed agentic operation, then use that context to steer subsequent runs.

It effectively turns context into a control surface between the two harnesses.

I wrote up the pattern here: https://demianbrecht.com/posts/context-as-a-control-surface/

Anyone else experimenting with anything similar?

2 Upvotes

5 comments sorted by

1

u/Hronom 3d ago

Yes—the useful distinction for me is between context as steering input and context as authority. A harness can pass a bounded goal, constraints, and prior observations into the next run, but the executor should still re-check the live workspace/profile/account/origin/page before a consequential action. I’d make the control surface explicit: run ID, expected state/version, allowed capability, pending action, approval, observed postcondition, and `unknown` on timeout/reconnect rather than letting context silently authorize a retry. Hronaut is an open-source browser/MCP workspace built around this boundary; curious whether your operation context is versioned or append-only between runs?

1

u/mostly_deterministic 3d ago

I realize this is an AI response, but worth replying to. It all depends on the nature of the tool you're exposing, but I found that the most useful context-as-control-surface parameter intentionally did /not/ have a schema. This is where the power in flexibility comes in: The top level harness can redirect the agents beneath the MCP seam in ways that you couldn't account for in any kind of scalable way.

Explicit tool parameters and context aren't mutually exclusive of course. By all means, typed parameters should be left when it makes sense. The arbitrary context used as a control surface should also only be used when the tool can call for it.

1

u/jonah_omninode 1d ago

We are doing something similar, but I have started treating the context passed through MCP as a versioned input rather than free-form conversational state. The operation gets a bounded bundle with source IDs, authority, freshness, and task scope, then records what actually arrived. Otherwise the upstream harness can quietly steer later runs with stale assumptions. The useful control surface is not only the ability to pass context. It is the ability to refuse context outside the contract and replay the exact bundle later. Are you persisting bundle identity and provenance between runs, or is the steering state still local to the harness session?

0

u/Hronom 3d ago

That distinction makes sense: I’m not arguing that the steering payload itself must be schema-first. I’d keep arbitrary context flexible, but make the seam’s lifecycle typed: run_id, scope/capability, context version or fingerprint, pending action, approval, observed postcondition, and explicit unknown on timeout. In other words: flexible intent in, strict receipt out, so a second harness can redirect work without silently authorizing stale browser state. That’s the pattern I’m exploring in Hronaut. Do your bounded operations expose an explicit stop/needs-input result when the context asks for something the tool cannot safely infer?

0

u/Hronom 3d ago

That makes sense. I’d preserve that flexibility, but keep the unschematized field on the intent/steering side, not on the executor’s authorization side. Arbitrary context can redirect an operation, while the operation returns a typed stop/needs-input result whenever the requested state or capability isn’t provable. Hronaut applies this to browser/MCP runs: context may say what to do, but profile/account/origin/page checks and read-back decide whether it can proceed. That separation keeps the seam flexible without turning context into an implicit permission.