Metadata-Version: 2.5
Name: learning-loop-mcp
Version: 0.5.4
Summary: MCP server (stdio) to query and validate lessons learned across projects, closing the learning loop.
Project-URL: Homepage, https://github.com/tiempor3al/learning-loop-mcp
Project-URL: Repository, https://github.com/tiempor3al/learning-loop-mcp
Project-URL: Issues, https://github.com/tiempor3al/learning-loop-mcp/issues
License: MIT License
        
        Copyright (c) 2026 Manuel Martínez (tiempor3al)
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.13
Requires-Dist: fastembed>=0.8.0
Requires-Dist: fastmcp>=4.0.2
Requires-Dist: mcp>=2.1.1
Requires-Dist: pyyaml>=6
Requires-Dist: sqlite-vec>=0.1.9
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.9; extra == 'dev'
Description-Content-Type: text/markdown

# learning-loop-mcp

![learning-loop-mcp abstract banner](https://raw.githubusercontent.com/tiempor3al/learning-loop-mcp/main/assets/learning-loop-mcp-banner-abstract-v2.svg)

`learning-loop-mcp` is a continuity layer for projects developed with Hermes or
other AI agents. It documents and makes the project's journey queryable—not
only its final lessons—so an agent can recover important context between
sessions through MCP or the CLI instead of starting every conversation from
scratch.

## Install in Hermes in 60 seconds

If you use Hermes Desktop or the Hermes MCP screen, choose **Add custom MCP**
and enter:

- **Name:** `learning-loop-mcp`
- **Transport:** `stdio`
- **Command:** `uvx`
- **Arguments:** `--from learning-loop-mcp==0.5.2 learning-loop-mcp-server`
- **Environment:**
  - `LEARNING_LOOP_PROJECTS_ROOT=/home/your-user/Proyectos`
  - `LEARNING_LOOP_MCP_DB=/home/your-user/.local/share/learning-loop-mcp/index.db`

Use the actual path where your project repositories live. The index path is
optional.

From a terminal, the equivalent command is:

```bash
hermes mcp add learning-loop-mcp \
  --command uvx \
  --env LEARNING_LOOP_PROJECTS_ROOT=/home/your-user/Proyectos \
  --env LEARNING_LOOP_MCP_DB=/home/your-user/.local/share/learning-loop-mcp/index.db \
  --args --from learning-loop-mcp==0.5.2 learning-loop-mcp-server
hermes mcp test learning-loop-mcp
```

- **Preflight:** before changing files or installing dependencies, run the read-only
  project gate:

  ```bash
  learning-loop-mcp project-preflight PROJECT \
    --kanban-board BOARD --task-id TASK_ID --json
  ```

  The equivalent MCP tool is `project_preflight`. It requires an explicit board,
  an existing workspace with `README.md`, `AGENTS.md`, `docs/lessons.md`,
  `docs/metrics/errors.yaml`, and `docs/metrics/solutions.yaml`, a Hermes project
  linked to that board and workspace, and an initial card containing `Purpose`,
  `Expected result`, `Acceptance criteria`, and `Planned tests`.

  A result with `ready: false` is a blocking stop signal. The tool is read-only:
  it never creates or changes a board, project, card, file, dependency, or
  private Hermes database. Use the official Hermes CLI to repair the reported
  condition, read the board and card back, then run preflight again. Set
  `--hermes-bin` or `HERMES_BIN` when the MCP process cannot resolve `hermes` on
  its own.

`uvx` downloads the pinned release from PyPI and starts the server. For Hermes,
use **`learning-loop-mcp-server`**. The command **`learning-loop-mcp`** is the
separate CLI for indexing, searching, validation, backups, recovery, and
preflight.

### Running the real Hermes E2E

The full workflow E2E runs inside a disposable Ubuntu container. The Fedora
host only needs rootless Podman and a built wheel:

```bash
uv build --wheel
podman run --rm --network host \
  -v "$PWD:/mnt/repo:Z" \
  -v "$PWD/dist:/mnt/dist:Z" \
  ubuntu:24.04 \
  bash /mnt/repo/scripts/e2e-hermes-learning-loop.sh
```

The script installs Python and the build tools inside the container before it
locates the wheel. `DIST_DIR`, `PROJECTS_ROOT`, and `DB` can be overridden for
local runners. The script creates an isolated Hermes home, board, project, and
MCP registration; it does not use the host Hermes state.

After the server is connected, initialize each project once from a checkout:

```bash
./scripts/init-project.sh /path/to/your-project
learning-loop-mcp index /path/to/your-project
```


## What problem does it solve?

A conversation may contain important decisions, but a conversation is not a
durable memory source. When a session ends or the agent changes, the project can
lose:

- its original purpose;
- decisions and the reasons behind them;
- constraints that must not be broken;
- investigated failures and their checks;
- task state and the concrete next action.

The result is repeated work, contradictory decisions, and agents that appear to
continue successfully but actually depend on someone retelling the history.

## How does it solve it?

The project keeps this context in versioned files inside the repository being
developed. `learning-loop-mcp` validates, indexes, and exposes those files for
queries:

1. **At the start of a task**, the agent queries relevant project context and
   applicable lessons.
2. **While working**, it can capture a task outcome as a validated draft without
   automatically turning it into canonical knowledge.
3. **When closing the task**, a person or authorized agent explicitly decides
   what should be promoted to a lesson, solution, ADR, or runbook.
4. **In another session**, the next agent queries that context through MCP or the
   CLI and continues with evidence, constraints, and the next action.

The source of truth is versioned Markdown/YAML. Together, those files form a
queryable project log: they record not only what was decided, but also why, what
was tried, what failed, which check confirmed it, and what remains to be done.
SQLite is only a rebuildable local index for fast queries; it is not the primary
memory or a second source of truth.

The practical consequence is important: for a question such as “why is it
designed this way?” or “what have we already tried?”, the agent can recover an
answer with citations and state. If the evidence is missing or insufficient,
the system reports that it is unknown instead of filling the gap with a guess.

```text
Project repository
  ├── docs/lessons.md                 purpose and lessons
  ├── docs/metrics/errors.yaml        error classes and checks
  ├── docs/metrics/solutions.yaml     verified solutions
  ├── docs/adr/                       decisions and rationale
  └── docs/runbooks/                  operational procedures
             │
             │ parser + validator + derived index
             ▼
       Local SQLite (FTS5 + sqlite-vec)
             │
             ├── learning-loop-mcp-server  ← MCP stdio for Hermes/agents
             └── learning-loop-mcp         ← CLI for people and scripts
```

## Why install it?

Because current code rarely explains its entire history.

Three months later, someone may return to the project and ask:

- Why was this architecture chosen?
- Which alternative was rejected?
- What constraint existed at the time?
- Is this strange behavior intentional or is it a bug?
- What was tried before, and why did it not work?

Without durable memory, they have to search old conversations, inspect commits
without context, or ask the person who made the decision. Sometimes that person
is no longer available.

With `learning-loop-mcp`, those answers can remain documented together with the
decision, its circumstances, the tests, and the sources. They can be queried by
question without manually reading the entire repository:

```text
Why does this service use a queue instead of calling the API directly?
```

The answer can include the decision, the rejected alternative, the failure that
motivated it, and the evidence that confirmed it. If there is not enough
information, the system says so instead of inventing an explanation.

That is the reason to install it: to turn the project's technical history into
recoverable context for the people and agents who will maintain it later.

## What does the loop add?

The loop is not just a document search tool. It is a way to make work accumulate
instead of disappearing when a session ends.

### For maintainers

- Reconstruct decisions months later, including their circumstances and rejected
  alternatives.
- Distinguish intentional odd behavior from a pending bug.
- Find what was tried and what failed without repeating experiments.
- Understand the real work state: done, blocked, verified, or pending.
- Onboard another person without transferring the entire history orally.

### For AI agents

- Start with relevant context instead of an anonymous repository.
- Receive previous constraints and decisions before proposing changes.
- Query concrete sources instead of blindly summarizing documents.
- Know which next action was expected.
- Report that something is unknown when there is not enough evidence.

### For the long-term project

- Decisions survive sessions, agents, and people.
- Failures become reusable checks.
- Verified solutions stay separate from drafts and assumptions.
- Documentation becomes a log of how the system evolved rather than a static
  snapshot.
- Knowledge remains versioned, reviewable, and recoverable alongside the code.

The cycle is simple:

```text
query → work → capture what happened → verify → decide what to promote
  ↑                                                        │
  └──────────── next session / next agent ─────────────────┘
```

## Simple example: continuing a project journey

Imagine a project that develops an online store.

During one session, the team discovers that payments must be confirmed through a
webhook, not through Stripe's immediate response. They document the decision,
the reason, and the test that confirmed it. They also record that the webhook
still lacks retries and that this is the next task.

In another session, the agent receives a short request:

```text
Add retries for the payment webhook.
```

Without context, it would have to guess how payment confirmation works and might
use Stripe's immediate response again. With `learning-loop-mcp`, it queries the
project journey and finds:

```text
Decision: confirm payments through a webhook.
Reason: the immediate response does not guarantee that payment completes.
Check: asynchronous confirmation tests.
Pending: add webhook retries.
Source: docs/adr/0003-payment-webhook.md, docs/lessons.md:42-55.
```

The agent now knows not only *what* code to write, but why the system is designed
that way, what must not be broken, and which task is pending. If the answer is
not documented, the system must say so instead of inventing it.

## Who is it for?

It is for teams and individuals who:

- work in repositories over many sessions;
- use Hermes, MCP, or other programming agents;
- need decisions and constraints to survive session changes;
- want Git-auditable memory rather than an opaque conversation;
- prefer retrieving relevant context instead of loading complete documents into
  every prompt.

It is not a task manager, a remote database of conversations, or a system that
decides by itself which knowledge is correct. Hermes Kanban state can be queried
read-only through the official Hermes CLI, but the board remains Hermes'
responsibility.

## Quick path

### 1. Add the server through Hermes Custom MCP (recommended)

The current published version is `0.5.2` and requires Python `>=3.13`.
Hermes can install and run it from PyPI without a checkout or a manually managed
virtual environment.

In Hermes, open the MCP screen and choose **Add custom MCP**. Enter:

- **Name:** `learning-loop-mcp`
- **Transport:** `stdio`
- **Command:** `uvx`
- **Arguments:**

  ```text
  --from learning-loop-mcp==0.5.2 learning-loop-mcp-server
  ```

- **Environment variables:**

  ```text
  LEARNING_LOOP_PROJECTS_ROOT=/home/your-user/Proyectos
  LEARNING_LOOP_MCP_DB=/home/your-user/.local/share/learning-loop-mcp/index.db
  ```

Use the actual path to the directory that contains your project repositories.
The index path is optional; the default XDG data path is also valid.

`uvx` downloads the pinned package from PyPI and launches the MCP server. You
do not need to clone this repository, create a virtual environment, find the
server executable, or edit Hermes' `config.yaml`.

The equivalent Hermes configuration is:

```yaml
mcp_servers:
  learning-loop-mcp:
    command: uvx
    args:
      - --from
      - learning-loop-mcp==0.5.2
      - learning-loop-mcp-server
    env:
      LEARNING_LOOP_PROJECTS_ROOT: /home/your-user/Proyectos
      LEARNING_LOOP_MCP_DB: /home/your-user/.local/share/learning-loop-mcp/index.db
```

The equivalent CLI command is:

```bash
hermes mcp add learning-loop-mcp \
  --command uvx \
  --env LEARNING_LOOP_PROJECTS_ROOT=/home/your-user/Proyectos \
  --env LEARNING_LOOP_MCP_DB=/home/your-user/.local/share/learning-loop-mcp/index.db \
  --args --from learning-loop-mcp==0.5.2 learning-loop-mcp-server
hermes mcp test learning-loop-mcp
```

Restart Hermes, or use its MCP reload action if available, so the tools and
`learning-loop://` resources are discovered.

### Alternative: install the executable manually

For a manually managed Hermes host:

```bash
uv tool install learning-loop-mcp==0.5.2
hermes mcp add learning-loop-mcp \
  --command "$HOME/.local/bin/learning-loop-mcp-server" \
  --env LEARNING_LOOP_MCP_DB="$HOME/.local/share/learning-loop-mcp/index.db" \
  --env LEARNING_LOOP_PROJECTS_ROOT="$HOME/Proyectos"
hermes mcp test learning-loop-mcp
```

If `uv tool install` prints a different executable path, use that path in
`--command`. Restart Hermes after registering the server.


### 2. Prepare a project

The initialization scripts are available from a repository checkout. Clone the
repository and run:

```bash
git clone https://github.com/tiempor3al/learning-loop-mcp.git
cd learning-loop-mcp
./scripts/init-project.sh /path/to/your-project
```

The script creates canonical templates under `docs/` and adds the ritual
reference to `AGENTS.md`. It does not overwrite existing files and is safe to
run more than once.

### 3. Index and query

```bash
learning-loop-mcp index /path/to/your-project
learning-loop-mcp learning-context \
  /path/to/your-project \
  "continue the pending task while respecting project decisions"
```

In Hermes, the agent can use the `learning_context` MCP tool to receive relevant
context. The response can include read-only Kanban state when
`LEARNING_LOOP_KANBAN_BOARD` is configured.

## What it preserves and what it does not do automatically

- **Durable memory versus conversation:** context is kept in project files and
  Git; prompts and complete conversations are not stored. The documentation
  preserves the journey: decisions, attempts, failures, tests, constraints, and
  next steps.
- **Source of truth versus index:** versioned Markdown/YAML is primary; SQLite
  can be deleted and rebuilt with `index`.
- **Capture versus promotion:** `capture-outcome` writes a draft to the explicit
  path and returns `promoted: false`; it does not automatically edit canonical
  lessons, ADRs, runbooks, or solutions.
- **MCP versus CLI:** MCP lets an agent query during a session; the CLI serves
  people, scripts, and reproducible operations.
- **Checks versus semantic judgment:** deterministic checks verify facts,
  citations, and state; the Amnesia Test also requires explicit evaluation. The
  system returns `score: unknown` when that evaluation cannot be determined and
  never invents a score from the mere presence of documents.

## Features

- Parser and validator for the canonical `docs/lessons.md` format, including
  `Error class:`, `Check:`, and `Task:` markers.
- Hybrid search: SQLite FTS5 for citable lexical matches and `sqlite-vec` for
  semantic search, fused with RRF.
- Local embeddings through small `fastembed` models, with an offline FTS5
  fallback and no external APIs.
- Append-only verified-solution registry with explicit states and gates,
  write-through YAML, and drift detection.
- Typed discovery and indexing of ADRs and runbooks while keeping their files
  authoritative.
- `amnesia-check` for deterministic continuity checks.
- `amnesia-evaluate` for combining verifiable facts with an explicit Amnesia
  Test report evaluation.
- Export, consistent SQLite backups, and recovery bundles with manifests and
  checksums.
- Configurable project root through `LEARNING_LOOP_PROJECTS_ROOT`; one
  installation can serve repositories in different paths.

## Installation from a checkout

For developing the project or installing its scripts and skill as well:

```bash
uv sync --extra dev
uv run pytest
uv run ruff check src tests
./scripts/install.sh
```

`./scripts/install.sh` is idempotent. It can migrate a legacy index and accepts
these overrides:

- `LEARNING_LOOP_MCP_DB` — explicit index path;
- `LEARNING_LOOP_PROJECTS_ROOT` — repository root;
- `LEARNING_LOOP_INSTALL_SKIP_HERMES=1` — sync without registering MCP;
- `LEARNING_LOOP_INSTALL_WITH_SKILLS=1` — also install `skills/` into
  `$HERMES_HOME/skills`;
- `LEARNING_LOOP_INSTALL_DEV=0` — skip development extras.

After installation, restart the Hermes gateway so the tools and
`learning-loop://` resources appear.

## CLI

The `learning-loop-mcp` entry point includes, among others, these commands:

```bash
learning-loop-mcp index PROJECT [--lessons PATH] [--with-embeddings] [--db PATH]
learning-loop-mcp search QUERY [--project PROJECT] [--with-embeddings] [--json]
learning-loop-mcp learning-context PROJECT TASK [--version 1|2] [--kanban-board BOARD] [--json]
learning-loop-mcp capture-outcome PROJECT --draft PATH --output PATH [--json]
learning-loop-mcp amnesia-check PROJECT [--kanban-board BOARD] [--json]
learning-loop-mcp amnesia-evaluate PROJECT [--evaluation PATH] [--ignore-evaluation]
learning-loop-mcp validate PROJECT [--errors PATH] [--tests-dir PATH] [--json]
learning-loop-mcp status PROJECT [--json]
learning-loop-mcp register-solution PROJECT --solution-id X --title T --status E [--json]
learning-loop-mcp solutions PROJECT [--solution-id X] [--status E] [--json]
learning-loop-mcp reindex-solutions PROJECT [--solutions-path PATH] [--json]
learning-loop-mcp backup [--db PATH] [--out PATH]
learning-loop-mcp backup --recovery --kanban-board BOARD [--checkpoint PATH] [--out PATH]
learning-loop-mcp export PROJECT... [--out PATH] [--json]
learning-loop-mcp import BUNDLE [--projects-root PATH] [--db PATH] [--json]
learning-loop-mcp import-recovery BUNDLE [--projects-root PATH] [--db PATH] [--json]
learning-loop-mcp resume PROJECT [--checkpoint PATH] [--json]
```

`export` creates a versioned bundle with canonical documents and a checksum
manifest. `backup --recovery` adds a consistent SQLite snapshot and a Kanban
archive exported through `hermes kanban boards export`, without reading Hermes'
private database. Extraction validates members and prevents path traversal.

Restores operate in a new directory and do not modify the original project or
board. The technical `backup` command also creates a SQLite snapshot using
`sqlite3.Connection.backup()` and runs `PRAGMA integrity_check`.

## MCP server

The server uses stdio and runs with:

```bash
learning-loop-mcp-server
```

It exposes the `search`, `learning_context`, `capture_outcome`, `amnesia_check`,
`amnesia_evaluate`, `learning_status`, `index`, `register_solution`,
`reindex_solutions`, and `solutions` tools. It also serves
`learning-loop://format/...` and `learning-loop://templates/...` resources.

`learning_context` keeps the legacy response by default. With
`context_version=2`, it returns the ADD continuity package, including warnings,
sources, and—when configured—read-only Kanban state. It only invokes the
official `hermes kanban ... list --json` CLI; it never modifies cards or reads
Hermes' private SQLite database.

For SDK-based MCP clients, `stdio_client` uses a curated environment by default.
Pass `env=dict(os.environ)` in `StdioServerParameters` so the server receives
`LEARNING_LOOP_MCP_DB` and `LEARNING_LOOP_PROJECTS_ROOT`.

## Canonical sources and contracts

- [ADD contract](docs/add-contract.md)
- [Requirements](docs/requirements.md)
- [Amnesia Test evaluation](docs/amnesia-test.md)
- [Decision format](docs/decision-format.md)
- [Lessons format](docs/lessons-format.md)

Lessons and all new project content are written in English by decision of
ADR-0001, keeping local search and embeddings consistent. Spanish exceptions
belong to historical migration files.

## Environment variables and exit codes

- `LEARNING_LOOP_PROJECTS_ROOT` — repository root, resolved on every call;
- `LEARNING_LOOP_MCP_DB` — SQLite index path;
- `LEARNING_LOOP_KANBAN_BOARD` — Hermes board that can be queried read-only;
- `0` — operation succeeded;
- `1` — error-severity findings;
- `2` — usage or I/O error.

By default, documents live under
`<LEARNING_LOOP_PROJECTS_ROOT>/<project>/docs/` and the index lives at
`$LEARNING_LOOP_MCP_DB` or `$XDG_DATA_HOME/learning-loop-mcp/index.db`.

## Detailed architecture

```text
project repositories (versioned Markdown/YAML)  [source of truth]
        ↓ parser / validator
local SQLite FTS5 + sqlite-vec                     [derived index]
        ↓ loop.py, shared domain
CLI  ───────── MCP stdio ───────── learning-loop:// resources
```

No absolute host paths are embedded in the package: the project root is
configured through the environment and the installed kit locates its own
resources through `__file__`.

## Limits and debugging

- Prompts, complete conversations, tokens, and invasive telemetry are not
  stored.
- The presence of files alone does not prove that an architecture is
  understandable. Semantic evaluation and automatic evaluation remain separate.
- If sources are missing or a result cannot be determined, the system reports
  `unknown` instead of guessing.
- FastMCP logs go to **stderr**; stdout is reserved for JSON-RPC.
- Tests are offline and require no credentials. Embeddings use synthetic vectors
  or the cached model.

## CI and publishing

`.github/workflows/ci.yml` runs tests, lint, and compilation on every PR and push
to `main`, using Python 3.13. Dependabot maintains the `uv` dependencies and
official GitHub Actions.

Publishing uses PyPI Trusted Publishing with GitHub OIDC. The workflow requests
only `contents: read` and `id-token: write`; it uses no persistent PyPI token. To
publish a new version, merge the change first, then create a `vX.Y.Z` tag and
GitHub Actions publishes the artifact through the publisher configured in PyPI.

## License

MIT — see [LICENSE](LICENSE).
