Skip to content
arrow_backBack to Insights
Guide· 7 min read

Windsurf + Ribo: Cascade Inside the Intent Envelope

Windsurf's Cascade runs long, multi-step write sessions. Hook Ribo in via MCP and every step reasons against the declared shape of the system, not just the files in view.

A developer asks Cascade to migrate their internal event bus to a new schema. Fifteen minutes later, Cascade has touched twelve files across three services, the tests pass, and the commit is ready. The developer reads the diff. The schema change is clean. The retry semantics are also clean, and also different from what the team agreed to last quarter, which Cascade had no way of knowing. The developer pauses, rewrites the retry logic, pushes. The migration ships. The team spends the next sprint noticing that two services now disagree about how idempotency keys are supposed to behave.

Cascade is excellent at write mode. Long, multi-step changes across a repo are exactly what it is built for. What it cannot see, because nothing in Windsurf has told it, is the envelope of intent the team operates inside: what the shared retry policy is, what idempotency means in this codebase, which decisions are still live and which have been superseded. MCP is the socket that pulls that envelope into Cascade's context window.

Long sessions amplify missing context

A one-line completion that drifts from your architecture is a small event. You notice, you retype, you move on. A fifteen-minute Cascade session that drifts from your architecture is a very different event. By the time you are reading the final diff, Cascade has made dozens of consistent choices based on its initial assumptions. Unwinding the wrong choice means rereading the entire session, because every later step depends on the earlier ones.

This is the multiplier that long agentic sessions impose. Context quality compounds through a session the way interest compounds through a year. Starting context that is slightly wrong produces a final output that is meaningfully wrong. Starting context that is grounded in declared intent produces a final output you can ship.

Windsurf supports MCP through Cascade's MCP integration. Any server listed in Windsurf's MCP config becomes available to Cascade as a set of callable tools during its reasoning. Point that at Ribo and the declared intent envelope is where Cascade starts.

What changes when Cascade reasons against declared intent

Ribo exposes four read tools over MCP: search declared artifacts for a query, retrieve a specific artifact, list artifacts in a project, walk relationships. Cascade's agent uses those the same way it uses file reads today, except the targets are structured declarations instead of source files.

Take the event-bus migration scenario. With Ribo mounted, Cascade's first move is not to start editing. It searches Ribo for artifacts related to the event bus, finds the contract artifact that declares the current schema and its successor, finds the algorithm artifact that specifies the retry policy and the idempotency-key semantics, and finds the constraint artifact that forbids concurrent schema versions in production. The plan Cascade presents already incorporates all of those. The fifteen-minute write session that follows moves across those twelve files in a pattern that matches the declared migration, not an inferred one.

The developer reads the diff and has nothing to rewrite. The retry semantics are what was declared. The idempotency keys match. The migration ships, and no services end up disagreeing.

Role-appropriate projection for Cascade

Windsurf runs Cascade on a developer's machine. The token you mint for it will live on a laptop, which means keep the surface small. Ribo's DNA splits into thirteen layers: intent, contract, algorithm, evaluation, escalation, pace, monitor, glossary, integration, reporting, compliance, constraint, and tradeoff.

The seven layers to expose to Cascade: intent, contract, algorithm, glossary, constraint, tradeoff, and integration. These are the authoring-time declarations. Intent tells the agent what each component does. Contract tells it what interfaces the component promises. Algorithm tells it how computations must behave. Glossary translates local vocabulary. Constraint and tradeoff record what the system must not become and why. Integration names the external surfaces.

The six layers to withhold: compliance, evaluation, pace, monitor, reporting, and escalation. They describe review-time, runtime, and incident-time concerns. Cascade does not need them to write code, and excluding them reduces both the tokens burned on every MCP call and the blast radius if the token is ever leaked.

How to wire it up, and one trade-off to know

Windsurf's MCP config has a quirk worth naming upfront: it is global only. Unlike Cursor or Claude Code, Windsurf does not support a per-project .windsurf/mcp.json file. Every Cascade session across every repo reads the same MCP server list from ~/.codeium/windsurf/mcp_config.json. If you work in multiple repos that map to different Ribo projects, you have two options: mint one token that covers all the relevant Ribo projects (the projectIds field supports a list), or accept that you will manually swap the token between repo contexts. Most solo developers pick the first. Teams with shared laptops rarely exist, so this rarely becomes a real constraint.

To wire it up, first mint the Ribo token. In the Ribo console, Agents page, create an agent named windsurf-<username>. Set scopes to artifact:read. Set projectIds to the Ribo project or projects whose repos you will work in. Set allowed_kinds to the seven-layer projection above: intent, contract, algorithm, glossary, constraint, tradeoff, integration. Capture the bearer token.

Second, edit ~/.codeium/windsurf/mcp_config.json. The entry:

FieldValue
Server nameribo
serverUrlhttps://mcp.ribo.dev/context/mcp
Authorization headerBearer token from the Ribo console

Windsurf's docs accept both serverUrl and url as field names; prefer serverUrl for consistency with the current documented schema. Save the file, restart Windsurf, and confirm Cascade lists Ribo's tools in the MCP tool picker at the start of your next session.

What the session looks like after wiring

The difference is visible in the first plan Cascade proposes. Without Ribo, a plan reads like a thoughtful refactoring proposal from an engineer who has just opened the repo: "I will update the schema across these services and adjust the callers." With Ribo mounted, the same plan reads: "I will apply the v2 schema declared in contract ct_event_bus_v2, preserve the retry policy declared in alg_retry_exponential, and maintain the idempotency-key invariant declared in constraint c_idempotency_v1 across the three affected services."

The plan itself has become a citation. The fifteen-minute write session that follows executes against declared decisions, not inferred ones. The diff is reviewable by reference instead of by reading.

What this changes in practice

The teams that use Cascade well treat it as the primary authoring surface for non-trivial changes. That model breaks when every Cascade session produces subtle drift. It works when every Cascade session reads from the same declared source of truth. Ribo does not make Cascade faster; it makes the Cascade output already consistent with the rest of the system, which is what turns fifteen-minute sessions into shippable pull requests rather than review-intensive ones.


Cascade writes at speed. Ribo sets the envelope the writing happens inside. The envelope is not a constraint; it is the shape of the team.

terminal

The ribo.dev Team

Building the identity layer for software.

We use cookies to understand how you use ribo.dev and improve your experience.

Learn more in our Cookie Policy