Skip to content

feat(mcp): add resummarize_meeting tool - #589

Merged
silverstein merged 1 commit into
silverstein:mainfrom
rymalia:feat/mcp-resummarize-tool
Jul 28, 2026
Merged

feat(mcp): add resummarize_meeting tool#589
silverstein merged 1 commit into
silverstein:mainfrom
rymalia:feat/mcp-resummarize-tool

Conversation

@rymalia

@rymalia rymalia commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

What

Adds the MCP resummarize_meeting tool — the follow-up to #526 (resummarize CLI) and #573 (derived-view invalidation) that was scoped as a separate PR in the #523 discussion. MCP clients can now re-run the AI pass on an edited meeting/memo, preview-first, with apply inheriting backup creation and automatic derived-view refresh from the core path.

Design decisions

  • Explicit paths only, no search terms. The CLI accepts a search term and fuzzy-resolves it; the MCP tool deliberately doesn't. An agent passing a slightly-wrong string would silently resummarize whatever fuzzy-matched — and even preview invokes the model. Paths are validated against the meetings directory (validatePathInDirectory, same as get_meeting/ingest_meeting).
  • Preview by default, cost disclosed. The description states the model is invoked even in preview (the M3 transparency note from Feature request: re-run the AI pass (summary + derived frontmatter) on an edited transcript #523). Preview returns the regenerated body so the caller can judge before applying; apply omits it to keep responses lean.
  • sensitivity: restricted refused unless include_restricted: true. Preview output is derived from the transcript, so the tool refuses before invoking the CLI, mirroring get_meeting's stub-and-logged-override posture.
  • --ingest only honored with apply. The knowledge log is append-only; the flag is inert in preview and the response says so instead of passing it through.
  • Synchronous with a 5-minute timeout (like process_audio) rather than a job — the jobs queue is audio-specific, and the CLI runs resummarize inline.
  • Failure envelope recovered from stdout. On failure the CLI prints a structured envelope to stdout and anyhow's text to stderr; runMinutes now preserves both streams on the thrown error so the tool can surface stage + error rather than just the stderr text. Verified against a live resolve failure.

One caveat worth knowing

The CLI's --json derived_views block doesn't include a search_indexed field (only the human output has it), so the tool infers search-refresh success from the absence of a "search index:" warning — the exact prefix derived.rs emits. It prefers a real boolean if one ever appears in the JSON. Happy to add the field to the CLI payload in a tiny follow-up if you'd rather have it explicit; I kept this PR TypeScript-only.

Review process

An independent adversarial model review of the diff found 1 Major + 2 Minor, all fixed before this PR: the envelope-recovery gap above (confirmed empirically — the structured error was unrecoverable from the thrown message alone), test names that overstated what they assert (renamed; this harness has no MCP protocol client, so registration/schema/guard are checked against the built server and the shared validator), and a pre-existing "7 resources" miscount in the manifest's long_description (corrected to 8 on the same line the tool-count bump touches).

Testing

  • npm run build clean; vitest 72/72; mcp_tools_test.mjs 12/12 (2 new checks)
  • npm --prefix site run check:llms and sync_site_release_version.mjs --check both green (37 tools; catalogs, manifest, and release constants regenerated together)

Wraps `minutes resummarize --json` as an MCP tool: preview-first (model
invocation disclosed), apply writes with backup + automatic derived-view
refresh, --ingest only with apply, and sensitivity: restricted refused
unless include_restricted (logged override). Recovers the CLI's structured
failure envelope from stdout on non-zero exit. Regenerates the MCP tool
catalogs and manifest for the new 37-tool count (and corrects the
long-standing 7→8 resource count on the same line).
@rymalia
rymalia force-pushed the feat/mcp-resummarize-tool branch from a3064bc to fd37628 Compare July 28, 2026 03:00

@silverstein silverstein left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Approved. This completes the resummarize arc (CLI in #526, derived-view invalidation in #573, MCP tool here), and the security posture is right.

Verified independently, not taken on trust:

  • Build clean, vitest 72/72.
  • mcp_tools_test.mjs: 12/12. Worth noting for anyone reading later, a fresh worktree shows 4 failures purely because there is no built CLI binary at target/debug/minutes (ENOENT plus empty-JSON parses). Pointing the harness at a real binary gives a clean 12/12, and main gives 10/10 on the same harness, so the delta is exactly your 2 new checks.
  • Guards read correctly in the handler: validatePathInDirectory against the effective meetings dir, restricted refusal, ingest gated to apply, and preview disclosing that the model is invoked.

The detail I want to call out as the right call: the restricted check parses frontmatter and refuses before invoking the CLI. That means a restricted meeting never has derived content sent to a model without an explicit, logged override, rather than refusing after the fact. Same for declining fuzzy search-term resolution. An agent passing a near-miss string that silently resummarizes the wrong meeting, at model cost, is exactly the failure mode worth designing out.

On your caveat about search_indexed not being in the --json derived_views payload: inferring from the absence of the 'search index:' warning prefix is a reasonable read of what derived.rs emits, and preferring a real boolean if one appears is the right hedge. A tiny CLI follow-up to add the field explicitly would be welcome whenever you feel like it, no rush.

Also appreciate that you ran an adversarial review on your own diff first and listed what it caught, including correcting the pre-existing resource miscount you happened to touch. Merging.

Three merged features in three days on your own roadmap. Thank you.

@silverstein
silverstein merged commit 869f0ec into silverstein:main Jul 28, 2026
18 checks passed
@rymalia

rymalia commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Thanks! Almost done with the full implementation plan:

Plan item Status
Phase 1 — core + CLI ✅ merged (#526)
Phase 4 (mandatory) — graph/index invalidation ✅ merged (#573), shipped v0.24.0
Phase 4 — MCP tool merged today (#589)
Phase 4 — --ingest ✅ already shipped in #526
Phase 3 — Tauri button 🟡 built, user testing now, PR coming today
Phase 4 — --retitle not built

So the Tauri button is the last substantial piece, but --retitle remainsminutes resummarize --help confirms no such flag. It's small and deliberately off-by-default (the filename slug derives from the title, so silent renames break links).

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.

2 participants