Skip to content

feat: add compact MCP surface and session-init measurement - #115

Merged
timeleft-- merged 6 commits into
mainfrom
automation/fava-trails-104
Sep 11, 2026
Merged

feat: add compact MCP surface and session-init measurement#115
timeleft-- merged 6 commits into
mainfrom
automation/fava-trails-104

Conversation

@yia-mw-agent

Copy link
Copy Markdown
Contributor

Summary

  • Adds FAVA_TRAILS_MCP_SURFACE=compact so initialize instructions and tool descriptions can shrink without dropping tools or changing read/authoring authorization. Default remains full.
  • Adds fava-trails measure-mcp-context to record tokenizer-labeled session-init size (instructions + advertised tools/list), lazy-loading (false), and whether the cost recurs.
  • Compact omits list-time outputSchema; server-side validation still uses TOOL_DEFINITIONS. Full protocol stays on-demand via get_usage_guide.

Motivation

Closes #104.

Evaluator estimates of ~6000 tokens of schemas/instructions were client-specific. This PR measures this server's advertised payload and offers a backward-compatible compact surface instead of claiming a universal token figure.

Changes

  • src/fava_trails/mcp_context.py: surface selection, compact instructions/descriptions, measurement, 70% session-init budget vs full baseline.
  • Compact tools/list keeps all 17 tools and the same input schemas.
  • Docs: docs/mcp-context-overhead.md records the measured baseline, budget, recall/save/promote comparison, and server-enforced vs prompt/client behavior.

Test Plan

  • uv run pytest -q (864 passed, jj on PATH)
  • uv run pytest tests/test_mcp_context.py -q
  • fava-trails measure-mcp-context --surface both (chars/4 heuristic; compact session-init ≈ 0.52 of full, budget 0.70)

Notes for Reviewers

  • Instructions do not provide cross-session sharing; sharing still requires propose_truth plus durable approval.
  • Compact clients that never call get_usage_guide may skip session-start recall or promotion. That is documented as a regression of prompt coverage, not a permission change.
  • Branch was cut from 6c5278a (issue baseline). origin/main has moved; this PR does not rebase (no force-push).

Advertise a backward-compatible FAVA_TRAILS_MCP_SURFACE=compact mode that
shortens initialize instructions and tool descriptions and omits list-time
outputSchema, while keeping all tools, input schemas, and authorization.
Measure tokenizer-labeled session-init size via fava-trails measure-mcp-context.

Closes #104.

@timeleft-- timeleft-- left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independent review of exact head 6527b6c4cd6ee7e50d481a084d5244e3a78c6387 found four material gaps:

  1. The measurement covers only the candidate checkout and labels the server serialization/MCP SDK as the client. It records neither the tested FAVA release/version/commit nor an actual client and version, so the required release-versus-candidate provenance is missing.
  2. The advertised same-task comparison is hardcoded metadata rather than an executed recall/save/promote comparison. Discoverability, skipped steps, permissions, and error recovery are constants, and the compact warning is emitted for the full surface too. Run and record the same task against both configurations, including recovery behavior, rather than asserting outcomes.
  3. The checked-in get_usage_guide measurement is stale: the document says 10,077 characters / 2,520 heuristic tokens while this exact head reports 10,174 / 2,544. Make the recorded artifact reproducible from the current head.
  4. Compact scope discovery omits the configured FAVA_TRAILS_SCOPE_HINT fallback required by root agent guidance. Preserve that third fallback before asking the user.

The branch also currently conflicts with main; resolve those conflicts in the existing branch. Focused context/protocol tests, Ruff, git diff --check, and all current GitHub checks passed on the reviewed head.

Address PR #115 review: record tested-release vs candidate MCP
session-init provenance, execute recall/save/promote on both surfaces,
keep FAVA_TRAILS_SCOPE_HINT in compact scope discovery, and refresh the
measured get_usage_guide artifact.

@timeleft-- timeleft-- left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independent re-review of exact head a411da8cfbb57dc32392ac014b8dd621c43e6bba found three material gaps:

  1. The documented same-task mcp.Client comparison is still a direct handler exercise. It neither starts full and compact MCP sessions nor instantiates a client, forces every recall/save/promote step, cannot observe skipped client steps, and records failures without exercising recovery. Run the comparison through actual MCP sessions/client calls and distinguish observed skips from scripted steps.
  2. Tested-release measurement is a hardcoded historical fixture. The command cannot reproduce commit 6c5278a, omits that release's enabled tool names and recurrence data, and labels it with the candidate environment's current SDK version. Keep a reproducible frozen artifact or measurement procedure with complete historical provenance, and prevent future environments from relabeling it.
  3. AGENTS_USAGE_INSTRUCTIONS.md says its core guidance is canonical and injected, but mcp_context.py maintains a separate full-instructions literal that already differs: canonical recall examples include project filters while runtime full instructions omit them. Derive runtime guidance from the canonical source or state the relationship accurately and add drift prevention.

Confirmed fixed: scope-hint fallback, current guide measurement, enforced-versus-prompt boundaries, context budget/regression disclosure, and main-branch conflicts. Verification on this exact head passed 59 focused tests, the isolated workflow test, Ruff, git diff --check, and all GitHub checks.

Address PR #115 review: execute recall/save/promote via mcp.Client
sessions, load a frozen 6c5278a measurement artifact, and keep full
initialize session-start examples aligned with AGENTS_USAGE_INSTRUCTIONS.md.

@timeleft-- timeleft-- left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independent re-review of exact head 4082d298286f737a0efe4c47e12ac65e5cc831a0 found two remaining evidence gaps:

  1. The reported "observed skips" are still scripted inference from exact words in initialize instructions, not behavior observed from a client. This misclassifies compact propose_truth as skipped even though compact instructions explicitly request it, merely because the word "mandatory" is absent. Label these as deterministic prompt-coverage indicators rather than observed client choices, and keep actual executed client steps separate.
  2. Missing-scope recovery marks any successful list_scopes call as recovered without inspecting returned paths, selecting a valid scope, or retrying the failed recall. An empty result passes. Complete the recovery by selecting an exact returned scope and retrying the failed operation, or describe the evidence honestly as discovery attempted rather than recovery achieved.

Confirmed fixed: real separate in-process mcp.Client handshakes/tool calls, frozen tested-release provenance and exact metrics, all historical tool names and recurrence/lazy-loading data, relabel protection, current measurements, scope-hint preservation, maintained-subset wording/drift tests, context budget, and unchanged authorization. Verification passed 57 focused tests, Ruff, git diff --check, and all nine GitHub checks.

Label initialize-text gaps as deterministic prompt-coverage scans instead
of observed client skips, and complete missing-scope recovery by selecting
an exact list_scopes path and retrying recall.

@timeleft-- timeleft-- left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independent re-review of exact head 768fdd8df0c9b97bcbec2fdbbee1644667885e81 found one remaining evidence-labeling defect:

naive_initialize_only.called/skipped still reports deterministic instruction substring checks as client behavior. It even places propose_truth_requested under called without calling that tool, contradicting the adjacent not_observed_client_choices label. Remove this object or rename its fields and enclosing concept strictly as instruction/prompt-coverage indicators, with no called, skipped, or client-behavior terminology.

All prior substantive findings are otherwise fixed: frozen release metrics reproduce, candidate metrics match docs, both surfaces use separate mcp.Client sessions, missing-scope recovery selects a returned path and retries recall successfully, and scope hint, drift checks, budget, permissions, and enforcement boundaries hold. Verification passed 23 focused tests, Ruff, git diff --check, and all nine GitHub checks; the branch is mergeable.

Remove naive_initialize_only.called/skipped, which treated
deterministic initialize-text checks as client behavior and listed
propose_truth_requested without calling the tool. Prompt coverage
stays an instruction scan; actual session-start recall is recorded
in scripted_steps when initialize text includes it.

@timeleft-- timeleft-- left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The final exact-head review found one material acceptance defect in the scripted error-recovery comparison. The failed recall uses only trail_name, but the retry changes both trail_name and the operation semantics by adding query="status". Because the saved synthetic thought does not contain that term, an empty successful response is counted as recovery. Preserve the original recall arguments, change only the selected trail_name, and assert that the retry returns the saved thought or the expected result count. All earlier findings are otherwise resolved; 1,049 tests, the focused suite, Ruff, diff checks, the recorded baseline, and all nine GitHub checks passed at fb4ea5b.

Preserve original recall arguments except trail_name, and require a
non-empty retry result so empty ok responses are not counted as recovery.

@timeleft-- timeleft-- left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independent review is clean at exact head 7e92e23. The final recovery repair preserves the original recall arguments except the selected trail name and requires the expected non-empty retry result. Issue #104 acceptance remains intact. Verification: 23 focused tests, Ruff, git diff --check, recorded full/compact measurements, and all nine GitHub checks passed.

@timeleft--
timeleft-- merged commit d777233 into main Sep 11, 2026
9 checks passed
@timeleft--
timeleft-- deleted the automation/fava-trails-104 branch September 11, 2026 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Measure and reduce MCP context overhead without losing the learning workflow

2 participants