# prod-code 0.3.49: several code reads in one MCP call, and edits that check what they replace

> Source: <https://prod.codes/blog/prod-code-0-3-49-several-reads-one-call/>
> Published: 2026-11-03 00:00:00+00:00

# prod-code 0.3.49: several code reads in one MCP call, and edits that check what they replace

An experimental code_workflow tool composes existing prod-code reads, previews and applies text edits only over the bytes it saw, and runs only checks it is asked for. It also fixes stalled refreshes in non-Git sessions. It makes no speed or context claim.

An agent that wants to understand one function in prod-code usually makes a short chain of
calls: find the symbol, read its definition, read what it depends on. Each call is a model
round trip, and the agent has to carry the location from one answer into the next request.
Version 0.3.49 adds an experimental MCP tool, `code_workflow`, that accepts that chain as one
request. It runs the same operations through the same gateway and language engines as the
individual tools, which all remain available. It adds no shell, no JavaScript runtime and no
new network protocol.

This post covers what the tool does at tag
[`v0.3.49`](https://github.com/alex09x/prod-code/releases/tag/v0.3.49) (commit `61aae41`),
archived on Zenodo as [10.5281/zenodo.23905176](https://doi.org/10.5281/zenodo.23905176). The
newer work on prod-code’s main branch is not part of it. There is no `prod-code workflow`
command in this version; the tool exists only over MCP.

## v0.3.49

### Reads, composed

For the common cases there are two short forms. One inspects a symbol:

```
{"symbol":"Cache::get","include":["dependencies","callers"]}
```

The other searches for literal text and expands each hit into the definition that encloses
it. The expansion reuses prod-code’s existing grep enrichment, which is a heuristic rather than
a parser: ambiguous hints fail visibly, and hits outside any symbol are returned as
`unexpanded` instead of being counted as definitions.

Anything longer is an explicit plan of named steps. A later step refers to an earlier result
with a step ID and a JSON pointer, `"target#/path"`; forward and self references are rejected
before anything runs. A step can iterate over an array, up to eight items; more than eight is
an error, not a silent subset. A failing step can be marked to continue, and a recovery step can
run only when it failed. Nothing is retried automatically.

The bounds are fixed: one workspace, or one verified sibling Git worktree, per plan, up to 16 steps and 32 operation calls, 64 KiB of
input, 1 MiB of retained intermediate values, and a wait of 30 seconds by default and 60 at
most. Only the steps named in `outputs` are returned, but every step’s status and warnings
stay in the report, so a hidden step that hit a truncation limit still says so.

### Edits that check what they replace

A plan can also change files, in two stages. A `preview` step takes an old and a new snippet,
requires the old one to match exactly once, and returns a diff together with each file’s
SHA-256. It writes nothing and runs nothing. An `apply` step takes those prepared files, checks
every path and every file’s bytes against the recorded hashes, and only then writes through
prod-code’s existing edit journal. A file that changed since the preview is refused before any
write, and the report says zero writes.

What it does not do matters as much. Writes need `apply: true` on the whole request, and
that flag only permits apply steps; it does not schedule them. Each apply batch is independent:
if a later step fails, earlier writes stay on disk. The writer gates serialize requests inside
one MCP process; another process or an editor can still change a file after the check, so this
is not a cross-process compare-and-swap, and there is no crash-safe multi-file transaction or
rollback of a whole plan. Preview handles existing UTF-8 files only, not creates, deletes or
renames.[1](#user-content-fn-1)

### Checks only when asked

A `verify` step runs `check`, `lint` or `test` on an explicit path inside the workspace. A test
needs a non-empty filter, and a test runner that would ignore the filter is refused. Scopes that
would widen to a whole Cargo workspace or `./...` are refused too; the agent has to name a member
package. Nothing is built or tested because a preview or an apply succeeded. A verification
waits at most 120 seconds, a write-enabled plan two minutes, and a timed-out wait is reported as
a timeout, not as success or as a rollback.

### The refresh fix

The other change is a fix. In an open session on a checkout that is not a Git repository, a workspace refresh sent a handshake probe where an incremental sync was expected, and the gateway waited on it. The client now sends the incremental update, the gateway disconnects a late probe instead of stalling, and file access events that change nothing no longer trigger redundant sync probes (#1796, #1798).

### What was measured, and what was not

The measurements in the release are acceptance observations, recorded in
[`docs/agent-workflow-measurements.md`](https://github.com/alex09x/prod-code/blob/v0.3.49/docs/agent-workflow-measurements.md).
On a small Rust fixture, a symbol search, definition and dependency slice took three standalone
calls or one workflow call, with identical text. In a session against prod-code’s own
repository, a search and a definition took two calls or one, with the same complete definition.
In both cases the response was larger, not smaller:

| Scenario | Standalone | Workflow | 
|---|---|---|
| Rust fixture, full MCP results | 1,142 bytes | 1,261 bytes | 
| prod-code repository, JSON-normalized results | 3,116 bytes | 3,550 bytes | 

The standalone calls ran first, against a colder analyzer, so the timings recorded alongside do
not show that composition is faster, and the release makes no speed claim. Nor does it claim a
smaller context: a direct `code_slice` already returns a symbol and its dependencies in one
call, and a three-call baseline is not the strongest one. Fewer round trips are what was
observed; whether agents choose better or finish sooner with this tool has not been tested.

The release checks are in [PR #1804](https://github.com/alex09x/prod-code/pull/1804): 55
workflow unit tests and the affected live workflow case passed, and six native client and
server binaries were built for Linux x86-64, Linux ARM64 and macOS ARM64, the macOS ones
signed. The strict scoped lint did not pass; it reports 260 existing diagnostics outside the
new modules, so this is not a release with a clean lint.

The tool is marked experimental. The next step its documentation sets is a comparison on real tasks, in both orders, including cold and unavailable analyzers, before the contract grows.

## Footnotes

1. 
The edit contract at the tag, `docs/agent-workflow-edits.md` , still carries the heading
“development contract”. The release notes, the changelog and PR #1804 include preview, apply
and verification in 0.3.49.[↩](#user-content-fnref-1)

## Cite this article

```
Alexander Panasenko (2026-11-03). prod-code 0.3.49: several code reads in one MCP call, and edits that check what they replace. https://prod.codes/blog/prod-code-0-3-49-several-reads-one-call/
```


