# v3.2.0 — MCP server decomposition plan

`src/mind_mem/mcp_server.py` is currently a 4,604-line god-object
hosting 57 MCP tools, 8 MCP resources, and the cross-cutting
infrastructure (ACL, rate limiting, scope handling, observability,
config loading, file IO, etc.). This document is the migration
plan agreed for v3.2.0.

> Implementation status: **planning only**. The actual file moves
> happen in v3.2.0 because the change is high-risk (it's the
> production MCP surface every client talks to) and benefits from
> a per-domain staged rollout rather than a single PR.

---

## 1. Target topology

```
src/mind_mem/mcp/
├── __init__.py            # public re-exports for backward compat
├── server.py              # the @mcp instance + lifespan + ACL plumbing
├── infra/                 # cross-cutting infrastructure
│   ├── __init__.py
│   ├── acl.py             # check_tool_acl, scope handling
│   ├── rate_limit.py      # SlidingWindowRateLimiter wiring
│   ├── observability.py   # mcp_tool_observe + traces
│   ├── workspace.py       # _workspace, _check_workspace,
│   │                      #   _validate_path, _read_file
│   ├── config.py          # _load_config, _load_extra_categories
│   └── http_auth.py       # _build_http_auth_tokens
├── resources/             # @mcp.resource declarations
│   ├── __init__.py
│   ├── decisions.py
│   ├── tasks.py
│   ├── entities.py
│   ├── signals.py
│   ├── contradictions.py
│   ├── health.py
│   ├── recall.py
│   └── ledger.py
└── tools/                 # @mcp.tool declarations grouped by domain
    ├── __init__.py
    ├── recall.py          # recall, recall_with_axis,
    │                      #   hybrid_search, prefetch,
    │                      #   pack_recall_budget,
    │                      #   intent_classify, find_similar,
    │                      #   retrieval_diagnostics
    ├── governance.py      # propose_update, approve_apply,
    │                      #   rollback_proposal, scan,
    │                      #   list_contradictions,
    │                      #   memory_evolution
    ├── audit.py           # verify_merkle, verify_chain,
    │                      #   list_evidence, mind_mem_verify
    ├── memory_ops.py      # delete_memory_item, get_block,
    │                      #   export_memory, compact,
    │                      #   stale_blocks, memory_health,
    │                      #   index_stats, reindex
    ├── kernels.py         # list_mind_kernels, get_mind_kernel,
    │                      #   compiled_truth_*
    ├── core.py            # build_core, load_core, unload_core,
    │                      #   list_cores
    ├── graph.py           # graph_add_edge, graph_query,
    │                      #   graph_stats, traverse_graph
    ├── signal.py          # observe_signal, signal_stats
    ├── consolidation.py   # plan_consolidation,
    │                      #   propagate_staleness,
    │                      #   project_profile, dream_cycle
    ├── ontology.py        # ontology_load, ontology_validate
    ├── agent.py           # agent_inject, vault_scan,
    │                      #   vault_sync, stream_status
    ├── encryption.py      # encrypt_file, decrypt_file
    ├── calibration.py     # calibration_feedback,
    │                      #   calibration_stats
    └── benchmark.py       # governance_health_bench,
                           #   category_summary
```

Each tool module is small and cohesive — typically 200-400 lines.
Cross-cutting concerns import from `infra/` rather than
re-implementing.

---

## 2. Tool → module mapping

| Tool                            | Target module               |
| ------------------------------- | --------------------------- |
| `recall`                        | `tools/recall.py`           |
| `recall_with_axis`              | `tools/recall.py`           |
| `hybrid_search`                 | `tools/recall.py`           |
| `prefetch`                      | `tools/recall.py`           |
| `pack_recall_budget`            | `tools/recall.py`           |
| `intent_classify`               | `tools/recall.py`           |
| `find_similar`                  | `tools/recall.py`           |
| `retrieval_diagnostics`         | `tools/recall.py`           |
| `propose_update`                | `tools/governance.py`       |
| `approve_apply`                 | `tools/governance.py`       |
| `rollback_proposal`             | `tools/governance.py`       |
| `scan`                          | `tools/governance.py`       |
| `list_contradictions`           | `tools/governance.py`       |
| `memory_evolution`              | `tools/governance.py`       |
| `verify_merkle`                 | `tools/audit.py`            |
| `verify_chain`                  | `tools/audit.py`            |
| `list_evidence`                 | `tools/audit.py`            |
| `mind_mem_verify`               | `tools/audit.py`            |
| `delete_memory_item`            | `tools/memory_ops.py`       |
| `get_block`                     | `tools/memory_ops.py`       |
| `export_memory`                 | `tools/memory_ops.py`       |
| `compact`                       | `tools/memory_ops.py`       |
| `stale_blocks`                  | `tools/memory_ops.py`       |
| `memory_health`                 | `tools/memory_ops.py`       |
| `index_stats`                   | `tools/memory_ops.py`       |
| `reindex`                       | `tools/memory_ops.py`       |
| `list_mind_kernels`             | `tools/kernels.py`          |
| `get_mind_kernel`               | `tools/kernels.py`          |
| `compiled_truth_load`           | `tools/kernels.py`          |
| `compiled_truth_add_evidence`   | `tools/kernels.py`          |
| `compiled_truth_contradictions` | `tools/kernels.py`          |
| `build_core`                    | `tools/core.py`             |
| `load_core`                     | `tools/core.py`             |
| `unload_core`                   | `tools/core.py`             |
| `list_cores`                    | `tools/core.py`             |
| `graph_add_edge`                | `tools/graph.py`            |
| `graph_query`                   | `tools/graph.py`            |
| `graph_stats`                   | `tools/graph.py`            |
| `traverse_graph`                | `tools/graph.py`            |
| `observe_signal`                | `tools/signal.py`           |
| `signal_stats`                  | `tools/signal.py`           |
| `plan_consolidation`            | `tools/consolidation.py`    |
| `propagate_staleness`           | `tools/consolidation.py`    |
| `project_profile`               | `tools/consolidation.py`    |
| `dream_cycle`                   | `tools/consolidation.py`    |
| `ontology_load`                 | `tools/ontology.py`         |
| `ontology_validate`             | `tools/ontology.py`         |
| `agent_inject`                  | `tools/agent.py`            |
| `vault_scan`                    | `tools/agent.py`            |
| `vault_sync`                    | `tools/agent.py`            |
| `stream_status`                 | `tools/agent.py`            |
| `encrypt_file`                  | `tools/encryption.py`       |
| `decrypt_file`                  | `tools/encryption.py`       |
| `calibration_feedback`          | `tools/calibration.py`      |
| `calibration_stats`             | `tools/calibration.py`      |
| `governance_health_bench`      | `tools/benchmark.py`        |
| `category_summary`              | `tools/benchmark.py`        |

Total: 57 tools across 14 modules. Median module size: ~300 LOC.

---

## 3. Backward compatibility

`src/mind_mem/mcp_server.py` becomes a deprecation shim that re-
exports the public symbols from `src.mind_mem.mcp.*`:

```python
# src/mind_mem/mcp_server.py — v3.2.0 shim
import warnings
from mind_mem.mcp.server import mcp  # noqa: F401
from mind_mem.mcp.tools.recall import *  # noqa: F401, F403
# ...etc

warnings.warn(
    "Importing from mind_mem.mcp_server is deprecated; use "
    "mind_mem.mcp.* submodules instead. The shim is removed in v4.0.",
    DeprecationWarning,
    stacklevel=2,
)
```

Every existing `from mind_mem.mcp_server import …` continues to
work. The shim is removed in v4.0 (one major version of overlap).

---

## 4. Migration order (per-PR plan)

To keep each PR small and reviewable:

1. **PR 1 — `infra/` extraction.** Move ACL, rate-limit,
   workspace, config, observability into the new namespace.
   No tool changes. ~600 LOC moved, 0 tools touched.
2. **PR 2 — `resources/` extraction.** Move all `@mcp.resource`
   declarations. No tool changes.
3. **PR 3-N — one PR per tool module.** Each PR moves one tool
   module's worth of `@mcp.tool` declarations. Tests already
   cover the surface; if any tool's behavior changes, it's
   surfaced immediately.
4. **PR final — shim.** Replace the old `mcp_server.py` with the
   deprecation shim; drop the old monolithic file.

Each PR is independently revertable.

---

## 5. Test strategy

- **Pre-PR:** snapshot every tool's `__doc__`, signature, and a
  smoke-test response. Stored as `tests/_snapshots/mcp_*.json`.
- **Per-PR:** assert the snapshot is unchanged for tools touched
  by that PR.
- **Post-merge:** the existing 3,610-test pytest suite already
  exercises every tool's logic; the only thing snapshots add is
  protection against accidental signature drift.

---

## 6. Risks + mitigations

| Risk                                | Mitigation                          |
| ----------------------------------- | ----------------------------------- |
| Production breakage during rollout  | Feature-flag the new module path; ship the shim re-exports first |
| Cross-tool implicit dependency      | Snapshot tests catch undocumented coupling at PR time |
| MCP client cache invalidation       | Tool names + signatures unchanged; clients see no diff |
| Reviewer fatigue from a 4.6KLOC PR  | 14 + 2 small PRs instead of one big bang |
| Lost git blame on touched lines     | Each move PR uses `git mv` so blame survives |
