Metadata-Version: 2.4
Name: dudley-mcp
Version: 0.2.0
Summary: Dudley MCP server — the intelligence layer (memory, decisions, personas) above your IDE.
Requires-Python: >=3.11
Requires-Dist: httpx>=0.27
Requires-Dist: mcp>=1.2.0
Description-Content-Type: text/markdown

# Dudley MCP server

The intelligence layer above your IDE. Link Dudley into Cursor, Claude Code,
Windsurf, or any MCP-speaking editor — and get memory, past decisions, and
expert-persona deliberation your editor's context window can't hold.

Your IDE knows the current file. Dudley knows *why you got here*.

## What makes it different

- **Repo-scoped memory that fills itself.** The server detects your git remote
  and binds the workspace to a Routabout project. When you tell Dudley
  *"we decided to drop RabbitMQ"*, the decision is captured to that repo's
  Decision Vault automatically — and you see it happen:
  `📌 Decision captured to this repo's vault: "…"`. Months later, in a
  different IDE, `recall_decision("rabbitmq")` answers with the stored
  reasoning, not a fresh guess.
- **Never-empty on day one.** First use in a repo auto-seeds the vault from
  your existing ADRs / decision docs (`docs/adr/*`, `DECISIONS.md`, …) —
  doc-only, idempotent.
- **One durable thread per repo.** `ask_dudley` continues the same `IDE · <repo>`
  conversation across restarts and across editors, so context accumulates
  instead of resetting per session. Outside a git repo, asks stay stateless.

## Tools

| Tool | What it does |
|------|--------------|
| `ask_dudley(question, lens?, conversation_id?)` | Memory-aware Q&A over your accumulated project context. Optional `lens` answers through an expert persona (Zeus/Flint/Maeve/Len/Ellie/Grace/Ruby/Percy) with Dudley's single recommendation + visible deliberation. Decisions stated in the exchange are captured to the repo's vault, with a visible 📌 acknowledgment. |
| `recall_decision(topic, project_id?)` | The Decision Vault: *why* did we choose X — a synthesized answer PLUS the source decisions (summary, rationale, confidence, date) so you can verify it. Auto-scoped to the current repo; auto-seeds from repo docs on first use. |
| `save_decision(summary, rationale?, alternatives?, tradeoffs?)` | Explicit capture — record a decision with its alternatives and tradeoffs at full confidence. |
| `bootstrap_repo(limit?)` | Seed the vault from the repo's ADR/decision docs on demand (idempotent; also runs automatically on first `recall_decision`). |
| `review_with(code, models?, focus?, sequential?)` | Cross-model code review — decorrelated parallel panel by default, sequential council opt-in. Model-attributed, cost shown. |
| `project_history(days?, project_id?)` | Rollup for the repo: activity, PRs, CI, decisions captured. |
| `eng_digest(days?)` | Same rollup, across all your projects — the daily standup view. |

Design + custody spec: `../docs/DUDLEY_MCP_WEDGE.md`.

## Setup

1. Create a scoped API key in Routabout settings — it looks like `sk-rb-…`.
   The API-keys screen shows this exact config with your fresh key inlined,
   ready to paste. (A headless client uses an API key, not an interactive login.)
2. Install the `dudley-mcp` command. Until it's on a public index, install from
   this repo (clone it first):

   ```bash
   uv tool install ./mcp_server        # or: pipx install ./mcp_server
   ```

   > `uvx dudley-mcp` (zero-install) will work once the package is published to
   > PyPI — that's a naming/ownership decision still pending; use the local
   > install above in the meantime.

3. Add the server to your MCP client config.

**Cursor / Claude Code** (`~/.cursor/mcp.json` or the client's MCP settings) — using the installed console script:

```json
{
  "mcpServers": {
    "dudley": {
      "command": "dudley-mcp",
      "env": {
        "ROUTABOUT_API_KEY": "sk-rb-your-key-here",
        "ROUTABOUT_API_URL": "https://routabout-production.up.railway.app"
      }
    }
  }
}
```

**Local dev** (run straight from a clone, no install — deps on your PATH):

```json
{
  "mcpServers": {
    "dudley": {
      "command": "python",
      "args": ["-m", "mcp_server.server"],
      "env": {
        "ROUTABOUT_API_KEY": "sk-rb-your-key-here",
        "ROUTABOUT_API_URL": "http://localhost:8000"
      }
    }
  }
}
```

Launch your editor from the repo you want Dudley bound to — the server reads
the workspace's git remote to scope memory, recall, and digests to that repo.

## Environment

| Var | Required | Default | Notes |
|-----|----------|---------|-------|
| `ROUTABOUT_API_KEY` | yes | — | Scoped key, `sk-rb-…`. Never committed; lives only in your client config. Leaked or done with it? Revoke it in Routabout settings — keys are cheap, regret isn't. |
| `ROUTABOUT_API_URL` | no | `https://routabout-production.up.railway.app` | Point at localhost for dev. |
| `ROUTABOUT_TIMEOUT` | no | `120` | Request timeout (seconds). |

## Privacy & custody

The complete inventory of what leaves your machine — short enough to audit,
specific enough to falsify — is in [TRUST.md](./TRUST.md).

This server sends only what you submit — never Cabildo-held profile data. A
persona or council lens that reaches a frontier model inherits the backend's
dehydration + no-training contract. `review_with` (cross-model review) is a
standard-tier, cost-shown operation; the backend refuses it in privacy/ephemeral
mode by design.

Captured decisions and conversation history are owner-scoped and retained under
Routabout's standard terms (no-training default). Repo binding uses only the
git remote URL — file contents never leave your machine unless you paste them
into a question or `review_with`.

**MCP sessions run in Standard mode (memory on).** An API key resolves your
account but not a per-session privacy mode — if you use Privacy mode in the
app, know that IDE asks through this server persist to your project memory.
That persistence is the product; we say it plainly rather than imply otherwise.

Captured decisions pass a redaction gate before they're stored: direct
identifiers (email, SSN, phone, IBAN, card) and credential-shaped tokens
(`sk-…`, `sk_live_…`, `ghp_…`, `AKIA…`, …) are replaced with typed markers —
the decision is kept, the identifier never is. The 📌 acknowledgment shows
exactly what was stored, redactions included.
