FRD Orchestration with MCP: Deterministic Context Control for Agents (No Drift)

FRD Orchestration with MCP: Deterministic Context Control for Agents (No Drift)

Source: Dev.to

Context: previous approach (file-based context) ## The real problem: an ambiguous context “selector” ## In short: execution stops being reproducible because a critical part depends on a non-deterministic step. ## Solution: deterministic retrieval via MCP ## Python tool implementation ## Why this improves orchestration (and it’s not just “more organization”) ## 1) Less drift ## 2) More repeatability ## 3) Phase-controlled delegation ## Demo (operational evidence) `Some time ago, I wrote this article, explaining the value of orchestrating multiple Feature Requirement Documents (FRDs) to keep full control over building a NestJS boilerplate from scratch, step by step. It worked, but a classic problem showed up: when FRDs live as “loose” files in the workspace, the agent can read the wrong .md, mix phases, or cache the wrong context. In the earlier article, I showed the benefits of using Feature Requirement Documents (FRDs) to guide an agent through building a boilerplate. It worked… but it had one major weakness: the agent relied on “correctly reading” files inside a folder. The workspace looked like this: The initial input I gave the agent was: ` Even though FRD-00 defines the order and delegates each phase, the weak point was still there: file selection inside the workspace. When an agent works with file-based context from the workspace, the typical failures are: To eliminate that weak point, I moved FRD reading to a deterministic mechanism using Model Context Protocol (MCP). What is MCP? Model Context Protocol (MCP) is a protocol that lets you expose tools (functions) to an agent/IDE so it can request information in a controlled way, instead of “guessing” by reading workspace files. Instead of “searching for files,” the agent requests exactly the document it needs through a tool: Result: orchestration no longer depends on the agent’s “file picking.” At each phase, the agent requests the correct FRD, in the correct order. The agent doesn’t “infer” which file to read: it is given the exact document. Two separate runs tend to produce the same outcome because the spec input is stable. The active phase determines which FRD is exposed. This even allows adding policies such as: In VSCode, open the MCP Servers view and verify that frd-orchestrator is active. Checking the local server works thanks to this configuration. Note: on my machine, uv is located at /Users/jorgegomez/.local/bin/uv. On yours, it may vary. ` and it automatically enables the local MCP server. When the server starts, we can see in the VSCode console that our MCP server is running. In practice, it looks like this: each phase triggers get_frd("0X"), and the server responds by reading the exact file from disk. In the MCP server logs, you can see how the agent requests FRDs by ID at the right moment: ` This is exactly what we’re aiming for: explicit tool calls instead of “free-form” workspace reading. With MCP, context stops being “workspace exploration” and becomes “controlled retrieval.” That reduces errors, speeds up orchestration, and makes the flow more reproducible. It may not look like much, but here’s the real benefit: this scales in enterprise environments. With MCP, AI stops being “just a chat” and becomes a controlled component to automate tasks, flows, and workflows aligned with each company’s business logic. That’s where developers should be heading today: AI + deterministic tools + reproducible processes. If you made it this far, I’d love for you to review this approach and share your thoughts. I’m fully open to feedback, criticism, and suggestions for improvement—both on the FRD design and the MCP implementation. If you spot anything that could be cleaner, safer, or more reproducible, please let me know in the comments. Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse CODE_BLOCK: folder name: `api-products` - FRD-00-master-orchestration.md - FRD-01-boilerplate-core-products.md - FRD-02-products-database.md - FRD-03-auth-security.md - FRD-04-unit-testing.md - Start the orchestration.. Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: folder name: `api-products` - FRD-00-master-orchestration.md - FRD-01-boilerplate-core-products.md - FRD-02-products-database.md - FRD-03-auth-security.md - FRD-04-unit-testing.md - Start the orchestration.. CODE_BLOCK: folder name: `api-products` - FRD-00-master-orchestration.md - FRD-01-boilerplate-core-products.md - FRD-02-products-database.md - FRD-03-auth-security.md - FRD-04-unit-testing.md - Start the orchestration.. CODE_BLOCK: // .vscode/mcp.json { "servers": { "frd-orchestrator": { "type": "stdio", "command": "/Users/jorgegomez/.local/bin/uv", "args": ["run", "main.py"] } } } Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: // .vscode/mcp.json { "servers": { "frd-orchestrator": { "type": "stdio", "command": "/Users/jorgegomez/.local/bin/uv", "args": ["run", "main.py"] } } } CODE_BLOCK: // .vscode/mcp.json { "servers": { "frd-orchestrator": { "type": "stdio", "command": "/Users/jorgegomez/.local/bin/uv", "args": ["run", "main.py"] } } } CODE_BLOCK: [FRD-Orchestrator] get_frd tool requested with frd_id=02 Reading FRD from disk: .../frd/FRD-02-products-database.md [FRD-Orchestrator] get_frd tool requested with frd_id=03 Reading FRD from disk: .../frd/FRD-03-auth-security.md [FRD-Orchestrator] get_frd tool requested with frd_id=04 Reading FRD from disk: .../frd/FRD-04-unit-testing.md Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: [FRD-Orchestrator] get_frd tool requested with frd_id=02 Reading FRD from disk: .../frd/FRD-02-products-database.md [FRD-Orchestrator] get_frd tool requested with frd_id=03 Reading FRD from disk: .../frd/FRD-03-auth-security.md [FRD-Orchestrator] get_frd tool requested with frd_id=04 Reading FRD from disk: .../frd/FRD-04-unit-testing.md CODE_BLOCK: [FRD-Orchestrator] get_frd tool requested with frd_id=02 Reading FRD from disk: .../frd/FRD-02-products-database.md [FRD-Orchestrator] get_frd tool requested with frd_id=03 Reading FRD from disk: .../frd/FRD-03-auth-security.md [FRD-Orchestrator] get_frd tool requested with frd_id=04 Reading FRD from disk: .../frd/FRD-04-unit-testing.md - FRD-00: orchestration - FRD-01: skeleton - FRD-02: ORM + migrations - FRD-03: auth + JWT - FRD-04: unit testing - Before: FRDs as files inside a folder → the agent might read the wrong document / mix phases / cache context. - Now: an MCP tool get_frd("00".."04") that returns the correct FRD by ID → phase-controlled delegation, less drift, and more repeatability. - Reading the wrong .md. - Mixing phases (skipping steps). - Running commands outside the target folder. - get_frd("00") → main orchestration - get_frd("01") → phase 1 - get_frd("02") → phase 2 - get_frd("03") → phase 3 - get_frd("04") → phase 4 - “You can’t request FRD-03 unless FRD-02 is completed.” - “Always request FRD-00 before any other.”