[GH-ISSUE #654] [Docs] docs/mcp-contracts.md and the bundled skill describe a filtered tools/list and a binary_session capabilities view that no longer exist #312

Closed
opened 2026-10-15 18:23:45 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @coygeek on GitHub (Oct 6, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/654

Before submitting

  • I searched the existing issues for a related documentation report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Documentation location

docs/mcp-contracts.md lines 11-18 (Identity and discovery), skills/reverse-engineer-anything/SKILL.md lines 39-43, and skills/reverse-engineer-anything/references/native-and-artifacts.md lines 12-15. The text is identical in the 4.0.1 release and on main; the skill ships in the npm package and is installed by rea setup.

Problem

docs/mcp-contracts.md says tools/list advertises only the tools callable for the current target, provider, host, and client capabilities, and that opening or closing a target emits notifications/tools/list_changed. The reverse-engineer-anything skill, which ships in the npm package and is installed by rea setup, tells agents not to call a tool hidden from tools/list and to call binary_session with detail: "capabilities" (and, in references/native-and-artifacts.md, a family filter and page bounds) to get remediation. Since PR #468 the server deliberately keeps a stable catalog: in both tested builds tools/list always returns all 116 tools, no list-change notification is sent, and binary_session has no detail, family, or paging input, so an unknown detail argument is silently ignored and the default response is returned. The documentation and skill text describe a contract the code no longer implements. Agents following the skill get no filtering from tools/list and no smaller view from binary_session; the full availability inventory is already in the default binary_session result.

What the documents say versus what the server does

The three documents describe a different contract. docs/mcp-contracts.md lines 11-18: "tools/list advertises only the operations callable for the current target, provider, host, and negotiated client capabilities ... Opening or closing a target or observing a provider health transition emits notifications/tools/list_changed." skills/reverse-engineer-anything/SKILL.md lines 39-43: "Do not call a tool hidden from tools/list; inspect binary_session with detail: "capabilities" for the exact remediation when a desired capability is unavailable." skills/reverse-engineer-anything/references/native-and-artifacts.md lines 12-15: "Request the capabilities view with a family filter and page bounds only when choosing a tool. Request the full view only for an explicit session-diagnostic need." All three are byte-identical at the release tag and on main.

Under that documented contract, this session (no provider configured) would list only the 62 available tools before and after open_binary, and each transition would emit notifications/tools/list_changed. Observed instead, identically on both tested builds except for the serialized length (condensed probe output; parenthetical notes added):

server tools capability: {"listChanged":true}
binary_session inputSchema properties: ["expected_package_version","expected_catalog_digest","expected_server_path"]
target-free tools/list: 116 tools
binary_session {} isError: false | {detail:'capabilities'} isError: false
structuredContent equal: true   (serialized length 141330 on the release, 141284 on main)
tool_availability: 116 entries, 62 available, unavailable reasons {"target_required":53,"provider_missing":1}
unavailable entries still in tools/list: 54 of 54
open_binary isError: false
after open: 116 tools, same names as target-free
after open tool_availability: 62 available, reasons {"provider_missing":54}
close_binary isError: false
after close: 116 tools, same names as target-free
notifications/tools/list_changed received: 0

Step 6 on the release: binary_session with the removed parameters returned isError: false and the same default result (serialized length 141330); target-free list_procedures returned isError: true with code target_unavailable and a remediation telling the agent to call open_binary. The release's dist contains no sendToolListChanged or tool .disable() call.

The stable catalog is deliberate. PR #468 (commit b8a9da0c0f) removed the server's sendToolListChanged calls, renamed the live-server test to "exposes live identity, a stable catalog, and changing availability", changed it to expect current_address in target-free tools/list, and replaced the list-change poll with expect(toolListChanges).toBe(0) (tests/boundary/mcp/serverIdentity.test.ts lines 197-226 on main). Commit 0d96275b68 ("refactor: return complete tool results inline") removed detail, capability_family, cursor, and limit from binary_session in src/contracts/sessionStatusContract.ts and edited other paragraphs of docs/mcp-contracts.md and SKILL.md, but left the text quoted above, and did not touch references/native-and-artifacts.md. rea mcp doctor (src/mcpDoctor.ts) also checks that target-free tools/list equals the full TOOL_CONTRACTS inventory.

Expected content

The documentation and the shipped skill describe the behavior the server implements. The implemented contract, established by PR #468 and the current tests, is a stable catalog: target-free tools/list lists the full TOOL_CONTRACTS inventory, opening or closing a target does not change it or emit notifications/tools/list_changed, and per-tool availability, reasons, and remediation come from result.tool_availability in the default binary_session response, whose only inputs are expected_package_version, expected_catalog_digest, and expected_server_path. Agents reading the skill should be pointed at that default response rather than at tools/list membership or a detail view.

Restoration check

Failing now: the three cited passages describe target-dependent tools/list filtering, notifications/tools/list_changed on target transitions, and a binary_session detail/family/paging view, none of which the server provides. Restored: no passage in those files claims tools/list filtering, tool list-change notifications, or binary_session inputs absent from its schema, and the skill directs agents to an availability source that exists (for example the default binary_session tool_availability), so an agent following it with the steps above gets the result the text describes. Control: the stable-catalog assertions in tests/boundary/mcp/serverIdentity.test.ts and the rea mcp doctor inventory check stay unchanged and passing.

Supporting evidence

Runtime or environment

  • rea-agents 4.0.1 from npm (tag rea-agents-4.0.1, commit feeb19b8b3), the latest published release.
  • main at 19f8cddfd6, built locally with npm ci and npm run build.
  • MCP client: @modelcontextprotocol/client from each build's own dependencies (2.0.0 for the release, 2.3.1 for main); negotiated protocol 2025-11-25.
  • Node.js 24.21.0, macOS 27.0.1 arm64, no Hopper or Ghidra configured, empty REA configuration.

Steps to reproduce

  1. Start node scripts/rea.mjs mcp from the package (or from the built main checkout) under an MCP stdio client (Client and StdioClientTransport from @modelcontextprotocol/client), with a handler registered for notifications/tools/list_changed.
  2. Call tools/list with no target open and record the tool names. Inspect the binary_session inputSchema.
  3. Call binary_session with {} and with {"detail": "capabilities"} and compare structuredContent; count the result.tool_availability entries that are unavailable and check whether those tools appear in the tools/list result.
  4. Call open_binary with {"path": "/bin/ls"}, wait 1.5 seconds, call tools/list again.
  5. Call close_binary, wait 1.5 seconds, call tools/list again, and count list-change notifications received.
  6. Extra checks, run on the release only in a fresh session: call binary_session with {"detail": "full", "capability_family": "x", "cursor": 5, "limit": 3}, and call list_procedures with {} while no target is open.

Evidence summary

  • Expected source: the implemented stable-catalog contract in tests/boundary/mcp/serverIdentity.test.ts lines 197-226, src/contracts/sessionStatusContract.ts (binarySessionInputSchema), and the rea mcp doctor inventory check in src/mcpDoctor.ts, all on main, plus the MCP probe output quoted under Actual behavior from both builds.
  • Failure source: docs/mcp-contracts.md lines 11-18, skills/reverse-engineer-anything/SKILL.md lines 39-43, and skills/reverse-engineer-anything/references/native-and-artifacts.md lines 12-15, identical in both builds.
  • Evidence provenance: observed
  • Local verification: reproduced
  • Reproduction completeness: complete

Additional context

CONTRIBUTING.md line 23 says "Prefer capability- and session-scoped tool advertisement over schema truncation". It is contributor design guidance rather than a description of runtime behavior, so it is not part of the restoration check, but it reads as pointing toward the removed filtering and may deserve the same review. Changing files under skills/reverse-engineer-anything changes the skill digest recorded by scripts/generate-completion-ledger.mjs, so a skill edit needs npm run evidence:generate. Earlier issues #101, #392, and #393 introduced the filtering and list-change behavior; they are closed.

Impact

  • Impact level: P3
  • Assessment status: supported
  • Impact basis: Following the stale text does not fail: unknown binary_session arguments are ignored and the default result already carries all 116 tool_availability entries with reasons and remediation, and calling an unavailable tool returns a typed target_unavailable error with remediation; the cost is misleading agent guidance, wasted calls, and an agent expecting a small summary receiving the full default result (about 141 KB of JSON), with no lost data or blocked workflow observed.
  • Workaround status: available
  • Workaround basis: Call binary_session with no arguments and read result.tool_availability (observed on both builds), instead of relying on tools/list membership or a detail view; this is read-only and needs no code change.
Originally created by @coygeek on GitHub (Oct 6, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/654 ### Before submitting - [x] I searched the existing issues for a related documentation report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Documentation location `docs/mcp-contracts.md` lines 11-18 (Identity and discovery), `skills/reverse-engineer-anything/SKILL.md` lines 39-43, and `skills/reverse-engineer-anything/references/native-and-artifacts.md` lines 12-15. The text is identical in the 4.0.1 release and on `main`; the skill ships in the npm package and is installed by `rea setup`. ### Problem `docs/mcp-contracts.md` says `tools/list` advertises only the tools callable for the current target, provider, host, and client capabilities, and that opening or closing a target emits `notifications/tools/list_changed`. The `reverse-engineer-anything` skill, which ships in the npm package and is installed by `rea setup`, tells agents not to call a tool hidden from `tools/list` and to call `binary_session` with `detail: "capabilities"` (and, in `references/native-and-artifacts.md`, a family filter and page bounds) to get remediation. Since PR #468 the server deliberately keeps a stable catalog: in both tested builds `tools/list` always returns all 116 tools, no list-change notification is sent, and `binary_session` has no `detail`, family, or paging input, so an unknown `detail` argument is silently ignored and the default response is returned. The documentation and skill text describe a contract the code no longer implements. Agents following the skill get no filtering from `tools/list` and no smaller view from `binary_session`; the full availability inventory is already in the default `binary_session` result. #### What the documents say versus what the server does The three documents describe a different contract. `docs/mcp-contracts.md` lines 11-18: "`tools/list` advertises only the operations callable for the current target, provider, host, and negotiated client capabilities ... Opening or closing a target or observing a provider health transition emits `notifications/tools/list_changed`." `skills/reverse-engineer-anything/SKILL.md` lines 39-43: "Do not call a tool hidden from `tools/list`; inspect `binary_session` with `detail: "capabilities"` for the exact remediation when a desired capability is unavailable." `skills/reverse-engineer-anything/references/native-and-artifacts.md` lines 12-15: "Request the capabilities view with a family filter and page bounds only when choosing a tool. Request the full view only for an explicit session-diagnostic need." All three are byte-identical at the release tag and on `main`. Under that documented contract, this session (no provider configured) would list only the 62 available tools before and after `open_binary`, and each transition would emit `notifications/tools/list_changed`. Observed instead, identically on both tested builds except for the serialized length (condensed probe output; parenthetical notes added): ```text server tools capability: {"listChanged":true} binary_session inputSchema properties: ["expected_package_version","expected_catalog_digest","expected_server_path"] target-free tools/list: 116 tools binary_session {} isError: false | {detail:'capabilities'} isError: false structuredContent equal: true (serialized length 141330 on the release, 141284 on main) tool_availability: 116 entries, 62 available, unavailable reasons {"target_required":53,"provider_missing":1} unavailable entries still in tools/list: 54 of 54 open_binary isError: false after open: 116 tools, same names as target-free after open tool_availability: 62 available, reasons {"provider_missing":54} close_binary isError: false after close: 116 tools, same names as target-free notifications/tools/list_changed received: 0 ``` Step 6 on the release: `binary_session` with the removed parameters returned `isError: false` and the same default result (serialized length 141330); target-free `list_procedures` returned `isError: true` with code `target_unavailable` and a remediation telling the agent to call `open_binary`. The release's `dist` contains no `sendToolListChanged` or tool `.disable()` call. The stable catalog is deliberate. PR #468 (commit b8a9da0c0f9f0b2b022a350d2c7c671d1fa3f886) removed the server's `sendToolListChanged` calls, renamed the live-server test to "exposes live identity, a stable catalog, and changing availability", changed it to expect `current_address` in target-free `tools/list`, and replaced the list-change poll with `expect(toolListChanges).toBe(0)` (`tests/boundary/mcp/serverIdentity.test.ts` lines 197-226 on `main`). Commit 0d96275b6887b72519d2bc54f72012db6a8e482c ("refactor: return complete tool results inline") removed `detail`, `capability_family`, `cursor`, and `limit` from `binary_session` in `src/contracts/sessionStatusContract.ts` and edited other paragraphs of `docs/mcp-contracts.md` and `SKILL.md`, but left the text quoted above, and did not touch `references/native-and-artifacts.md`. `rea mcp doctor` (`src/mcpDoctor.ts`) also checks that target-free `tools/list` equals the full `TOOL_CONTRACTS` inventory. ### Expected content The documentation and the shipped skill describe the behavior the server implements. The implemented contract, established by PR #468 and the current tests, is a stable catalog: target-free `tools/list` lists the full `TOOL_CONTRACTS` inventory, opening or closing a target does not change it or emit `notifications/tools/list_changed`, and per-tool availability, reasons, and remediation come from `result.tool_availability` in the default `binary_session` response, whose only inputs are `expected_package_version`, `expected_catalog_digest`, and `expected_server_path`. Agents reading the skill should be pointed at that default response rather than at `tools/list` membership or a `detail` view. #### Restoration check Failing now: the three cited passages describe target-dependent `tools/list` filtering, `notifications/tools/list_changed` on target transitions, and a `binary_session` `detail`/family/paging view, none of which the server provides. Restored: no passage in those files claims `tools/list` filtering, tool list-change notifications, or `binary_session` inputs absent from its schema, and the skill directs agents to an availability source that exists (for example the default `binary_session` `tool_availability`), so an agent following it with the steps above gets the result the text describes. Control: the stable-catalog assertions in `tests/boundary/mcp/serverIdentity.test.ts` and the `rea mcp doctor` inventory check stay unchanged and passing. ### Supporting evidence #### Runtime or environment - `rea-agents` 4.0.1 from npm (tag `rea-agents-4.0.1`, commit feeb19b8b3172b2827b80fde8f09570ce5aeed88), the latest published release. - `main` at 19f8cddfd6f283188567b8ff1e49b810d79952ee, built locally with `npm ci` and `npm run build`. - MCP client: `@modelcontextprotocol/client` from each build's own dependencies (2.0.0 for the release, 2.3.1 for `main`); negotiated protocol 2025-11-25. - Node.js 24.21.0, macOS 27.0.1 arm64, no Hopper or Ghidra configured, empty REA configuration. #### Steps to reproduce 1. Start `node scripts/rea.mjs mcp` from the package (or from the built `main` checkout) under an MCP stdio client (`Client` and `StdioClientTransport` from `@modelcontextprotocol/client`), with a handler registered for `notifications/tools/list_changed`. 2. Call `tools/list` with no target open and record the tool names. Inspect the `binary_session` `inputSchema`. 3. Call `binary_session` with `{}` and with `{"detail": "capabilities"}` and compare `structuredContent`; count the `result.tool_availability` entries that are unavailable and check whether those tools appear in the `tools/list` result. 4. Call `open_binary` with `{"path": "/bin/ls"}`, wait 1.5 seconds, call `tools/list` again. 5. Call `close_binary`, wait 1.5 seconds, call `tools/list` again, and count list-change notifications received. 6. Extra checks, run on the release only in a fresh session: call `binary_session` with `{"detail": "full", "capability_family": "x", "cursor": 5, "limit": 3}`, and call `list_procedures` with `{}` while no target is open. #### Evidence summary - Expected source: the implemented stable-catalog contract in `tests/boundary/mcp/serverIdentity.test.ts` lines 197-226, `src/contracts/sessionStatusContract.ts` (`binarySessionInputSchema`), and the `rea mcp doctor` inventory check in `src/mcpDoctor.ts`, all on `main`, plus the MCP probe output quoted under Actual behavior from both builds. - Failure source: `docs/mcp-contracts.md` lines 11-18, `skills/reverse-engineer-anything/SKILL.md` lines 39-43, and `skills/reverse-engineer-anything/references/native-and-artifacts.md` lines 12-15, identical in both builds. - Evidence provenance: observed - Local verification: reproduced - Reproduction completeness: complete ### Additional context `CONTRIBUTING.md` line 23 says "Prefer capability- and session-scoped tool advertisement over schema truncation". It is contributor design guidance rather than a description of runtime behavior, so it is not part of the restoration check, but it reads as pointing toward the removed filtering and may deserve the same review. Changing files under `skills/reverse-engineer-anything` changes the skill digest recorded by `scripts/generate-completion-ledger.mjs`, so a skill edit needs `npm run evidence:generate`. Earlier issues #101, #392, and #393 introduced the filtering and list-change behavior; they are closed. #### Impact - Impact level: P3 - Assessment status: supported - Impact basis: Following the stale text does not fail: unknown `binary_session` arguments are ignored and the default result already carries all 116 `tool_availability` entries with reasons and remediation, and calling an unavailable tool returns a typed `target_unavailable` error with remediation; the cost is misleading agent guidance, wasted calls, and an agent expecting a small summary receiving the full default result (about 141 KB of JSON), with no lost data or blocked workflow observed. - Workaround status: available - Workaround basis: Call `binary_session` with no arguments and read `result.tool_availability` (observed on both builds), instead of relying on `tools/list` membership or a `detail` view; this is read-only and needs no code change.
bsakaguchi 2026-10-15 18:23:45 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#312
No description provided.