Skip to content

feat(mcp): Batch thread reads with full bodies - #114

Merged
fedster99 merged 12 commits into
mainfrom
fedster99/mcp-batch-thread
Aug 3, 2026
Merged

feat(mcp): Batch thread reads with full bodies#114
fedster99 merged 12 commits into
mainfrom
fedster99/mcp-batch-thread

Conversation

@fedster99

@fedster99 fedster99 commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Product principle

Keep the MCP simple, powerful, and fast. Let an agent complete common goals with few requests, while keeping the tool surface small. Prefer bounded batching in an existing tool when the items share one intent, permission, selector model, and result shape.

MCP instructions describe capabilities, identifiers, limits, and guarantees. They do not prescribe how an agent reasons or sequences its work. Infrastructure enforces authentication, tenant isolation, and resource boundaries. The agent owns the task and its questions.

Summary

  • read_thread accepts one message seed or 1–10 message_ids through the existing tool. It removes exact duplicates, reads at most four threads at once, preserves order, and isolates each result or error.
  • Each thread returns 20 messages by default and at most 100.
  • read_message and read_thread return the full available cleaned body by default. They do not apply a per-message character cap.
  • Later replies remove recognized quoted reply tails and signatures by default. The oldest mirrored message keeps quoted content when no older messages were omitted. Forwarded Outlook and Original Message blocks remain available. include_quoted=true keeps quoted text.
  • read_message supports optional Unicode-safe body_offset and positive max_body_chars ranges without a product ceiling.
  • body_content_status, body_omissions, thread_content_status, thread_omissions, and omitted_message_count make every known omission explicit. source_truncated means sync stored an incomplete source message. It is separate from an explicitly requested response range.
  • draft_reply quotes the complete selected source body. A single-pass byte transform prefixes lines without building one JavaScript string per line.
  • Cloud can use an internal includeBody: false read option to fetch metadata before Storage hydration. Public MCP defaults do not change.

The MCP surface remains five tools.

Evidence

A real mailbox test found 319 matching emails in 118 threads. Serial thread reads took about 1 minute 54 seconds. The median thread took 0.79 seconds. The slowest first read took 6.79 seconds and later took 1.5–2.3 seconds. Metadata encryption added only 3–4 milliseconds. MCP round trips and Storage reads caused the material delay.

A smaller-model evaluation showed the cost of the former 4,096-character MCP cap:

  • The capped dataset marked 61 of 321 messages as truncated and missed a later fact.
  • The full-body dataset found the fact and cited the correct message.
  • One 733,287-character message produced about 183,788 tool-output tokens. The host truncated that response, and the model could not recover a fact removed from the middle.

Full bodies prevent silent server-side loss. Optional ranges provide recovery when a client host truncates an unusually large response.

Review fixes

  • Removed a cross-transaction sync_trust cache.
  • Matched runtime validation to the published JSON Schema.
  • Preserved forwarded evidence while removing recognized reply history.
  • Added metadata-only coverage for every thread selector path.
  • Preserved raw_truncated as the explicit source_truncated omission.
  • Removed the silent 4,096-character reply-quote reduction.
  • Reduced peak RSS for a 16 MiB newline-heavy quote from more than 600 MiB to about 197 MiB.
  • Evicted a PostgreSQL client if read-only transaction rollback fails, so a client with uncertain transaction state cannot return to the pool.

Final contract and adversarial reviews found no remaining issue after these fixes.

Test coverage

The final cross-repository audit found direct tests for 48 of 54 changed behavior paths (89%). The remaining gaps are additional listener-level disconnect coverage and narrow edge assertions for response mapping, control/astral characters, initialization publication, and UTF-8 quoting. The audit found no regression.

Plan completion

All public-core implementation, documentation, review, verification, commit, push, and PR-update items are complete. Image publication and Cloud repinning remain ordered follow-up gates after an approved merge.

Verification

  • INSTALL_CMD=true RUN_LIVE_DB=1 ./init.sh passed under local Node 26; the repo targets Node 24.
  • Typecheck and production build passed.
  • 770 fast tests passed; 224 environment-gated tests skipped in the fast lane.
  • Disposable PostgreSQL verification passed 224 live database tests.
  • Specification conformance passed 120/120 checks.
  • git diff --check passed.

Documentation

Updated README, the agent email guide, MCP instructions, the architecture indexes, the attachment content ADR, and ADR 0030.

Cloud dependency

The hosted wrapper remains draft PR #226. Merge this PR only after explicit maintainer approval. After the public image publishes, Cloud must pin the exact commit and image digest and pass its packaged hosted MCP smoke test.

@vercel

vercel Bot commented Aug 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
supamail Ready Ready Preview Aug 3, 2026 6:37am

[gstack-context]
Decisions: Cache the in-flight sync_trust query per account set inside one read_thread batch; keep the external MCP contract unchanged.
Remaining: Push the commit, refresh PR evidence, and confirm CI.
Tried: A regression assertion first proved that two same-account seeds issued two identical trust scans.
Skill: /investigate
[/gstack-context]
@fedster99 fedster99 changed the title Add bounded batch reads to MCP read_thread feat(mcp): Batch thread reads with recoverable bodies Aug 1, 2026
@fedster99 fedster99 changed the title feat(mcp): Batch thread reads with recoverable bodies feat(mcp): Batch thread reads with full bodies Aug 1, 2026
@fedster99
fedster99 merged commit 95cc6a4 into main Aug 3, 2026
6 checks passed
@fedster99
fedster99 deleted the fedster99/mcp-batch-thread branch August 3, 2026 06:44
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.

1 participant