# MCP Surface Consolidation Implementation Plan

> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

**Goal:** Shrink the MCP surface from 48 tools to 37 by merging redundant tools, keeping CLI/MCP parity, with behaviour preserved.

**Architecture:** Each merge collapses sibling tools into one tool with a discriminating parameter (`target` / `scope` / array input / sections). The underlying use-case functions are untouched — only the tool/command surface is reshaped. Most merges move the MCP surface toward the CLI's existing shape; the macro merge also collapses two CLI commands to keep parity.

**Tech Stack:** TypeScript, Turborepo + Yarn Berry, Drizzle ORM + better-sqlite3, tsup, Vitest, Commander + Clack (CLI), `@modelcontextprotocol/sdk` + zod (MCP).

**Design doc:** `docs/plans/2026-05-17-mcp-surface-consolidation-design.md`
**Branch:** `refactor/mcp-surface-consolidation` (off `main`).
**Build order:** `@firma/finnhub` → `@firma/mcp` → `@evan-moon/firma`.
**Conventions:** no explanatory comments in code; no redundant type annotations; the CLI/MCP parity harness (`test/parity.test.ts`) must stay green at every commit.

---

## Task 1: Merge the `report` tools

**Files:** `apps/mcp/src/tools/report.ts`; `test/parity.test.ts`.

`report_balance` / `report_flow` / `report_settle` / `report_combined` →
one `report` tool. Param: `target` (`z.enum(['balance','flow','settle','combined']).default('combined')`), `period` (optional, used by `settle`), `currency` (optional). Dispatch on `target`, calling the same report use-cases the four tools call today. Study `apps/cli/src/commands/report.ts` — `reportCommand` already dispatches on a target argument; mirror it.

Update the report parity tests in `test/parity.test.ts` to drive the single `report` tool with each `target` and assert the same output the split tools produced.

**Commit:** `refactor(mcp): merge report tools into one report(target)`

---

## Task 2: Merge the `sync` tools

**Files:** `apps/mcp/src/tools/admin.ts` (`sync_prices`), `apps/mcp/src/tools/macro.ts` (`sync_fx_rates`); `test/parity.test.ts`.

`sync_prices` + `sync_fx_rates` → one `sync` tool (place it in `admin.ts`). Param: `scope` (`z.enum(['all','prices','fx']).default('all')`). `all` runs both, mirroring CLI `firma sync`; `fx` mirrors `firma sync fx`. Reuse the existing sync use-case calls.

Update parity tests and any `server.instructions` / tool descriptions that name `sync_prices` / `sync_fx_rates`.

**Commit:** `refactor(mcp): merge sync tools into one sync(scope)`

---

## Task 3: Fold the bulk `add_*` tools into the single tools

**Files:** `apps/mcp/src/tools/mutate.ts`; `test/parity.test.ts`.

Remove `add_txns`, `add_balances`, `add_flows`. `add_txn` / `add_balance` / `add_flow` each take an array input (one or many entries); a single insert is an array of one. Fold the bulk variants' logic (date-sorting for `add_txn`, the per-ticker/per-type summary) into the single tools. `add_monthly` is unchanged.

Each tool routes through the existing use-cases (`addTransaction`, the balance/flow upserts) per entry. Update tool descriptions to say "one or more". Update parity tests.

**Commit:** `refactor(mcp): add_txn/add_balance/add_flow accept arrays, drop bulk variants`

---

## Task 4: Remove `show_prices`

**Files:** `apps/mcp/src/tools/portfolio.ts`; `test/parity.test.ts`; `server.instructions` / docs if referenced.

Delete the `show_prices` tool. It returns the raw price cache, which is the price data already in `show_portfolio`, and it has no CLI counterpart. Remove its parity test and any mention in `server.instructions` or docs.

**Commit:** `refactor(mcp): remove show_prices (covered by show_portfolio)`

---

## Task 5: Merge macro / stress / regime — MCP + CLI + docs

**Files:**
- MCP: `apps/mcp/src/tools/macro.ts` — merge `show_macro` / `show_stress` / `show_regime`.
- CLI: `apps/cli/src/commands/macro.ts`, `stress.ts`, `regime.ts`, `apps/cli/src/index.ts`.
- Docs: `apps/docs/content/docs/macro.{en,ko}.mdx`, `stress.{en,ko}.mdx`, `regime.{en,ko}.mdx`, `apps/docs/app/[locale]/docs/_sidebar.tsx`, `cli.{en,ko}.mdx`.
- `test/parity.test.ts`.

`show_macro` (MCP) and `firma show macro` (CLI) become one view with a macro snapshot plus a stress section and a regime section, calling the unchanged `assembleMacroSnapshot` / `assembleStressIndex` / `assembleRegime`. Remove `show_stress` / `show_regime` (MCP tools and CLI commands + their `index.ts` registrations). The `--json` output of `show macro` includes `stress` and `regime` keys.

Docs: fold `stress.mdx` / `regime.mdx` content into `macro.mdx` (en + ko), delete those four files, remove the two slugs from `_sidebar.tsx`, update `cli.mdx` `macroRows`. Update `server.instructions` and any prompt referencing `show_stress` / `show_regime`.

Update parity tests so `show macro` ↔ `show_macro` agree and the stress/regime data is asserted within.

**Commit:** `refactor: merge macro/stress/regime into one macro view (CLI + MCP)`

---

## Task 6: Merge the FX tools

**Files:** `apps/mcp/src/tools/macro.ts`; `test/parity.test.ts`; `server.instructions` if referenced.

`get_fx_rate` + `show_fx_history` → one `show_fx`: no arg = coverage summary, `currency` = recent series, `currency` + `date` = point lookup, `currency` + `from`/`to` = range. Mirror the CLI `firma show fx [currency]` shape. Reuse the existing FX repository lookups.

Update parity tests and `server.instructions` references.

**Commit:** `refactor(mcp): merge get_fx_rate + show_fx_history into show_fx`

---

## Task 7: Role clarification + verification

**Files:** `apps/mcp/src/index.ts` (or wherever `server.instructions` lives), `apps/mcp/src/tools/portfolio.ts` (`get_brief` / `show_portfolio` descriptions); `test/parity.test.ts`; the design doc.

State the hierarchy: `server.instructions` and the relevant tool descriptions make `get_brief` the canonical entry point for any check-in / portfolio question, and the `show_*` tools explicit drill-downs. Keep it concise — do not bloat the instructions.

Run `yarn typecheck` (17/17), `yarn build` (15/15), `npx vitest run` (all green). Audit that no removed tool name (`report_balance`, `sync_prices`, `add_txns`, `show_prices`, `show_stress`, `get_fx_rate`, …) remains referenced anywhere in `apps/`. Mark the design doc `Status: Implemented`.

**Commit:** `refactor(mcp): clarify get_brief vs show_* roles; consolidation verification`

---

## Notes

- Behaviour-preserving except the one intended change: `firma show stress` / `show regime` no longer exist as standalone commands.
- Tier 3 (merging the five research tools) is deliberately out of scope.
