Metadata-Version: 2.4
Name: keystone-mcp
Version: 0.2.0
Summary: Keystone Harness Manager — the end-to-end harness manager for any project. MCP server that owns the full lifecycle: scaffold, sensors, actions, playbooks, skills, cascade verify, and forward-only shipped-template patches.
Project-URL: Homepage, https://github.com/tacoda/keystone-mcp
Project-URL: Repository, https://github.com/tacoda/keystone-mcp
Project-URL: Issues, https://github.com/tacoda/keystone-mcp/issues
Author-email: Ian Johnson <ian@parentoleave.com>
License: MIT
License-File: LICENSE
Keywords: agent,broker,claude,claude-code,context,fastmcp,harness,mcp,rules
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.12
Requires-Dist: beautifulsoup4>=4.15.0
Requires-Dist: fastmcp>=3.4.2
Requires-Dist: httpx>=0.28.1
Requires-Dist: pyyaml>=6.0.2
Provides-Extra: tokens
Requires-Dist: tiktoken>=0.7.0; extra == 'tokens'
Description-Content-Type: text/markdown

# keystone-mcp — Keystone Harness Manager

The **Keystone Harness Manager** is the end-to-end harness manager for any
project. It's a single MCP server (`keystone-mcp` on PyPI) that owns the
full lifecycle of a project harness:

- scaffold + materialize a shipped template tree under
  `.keystone/harness/`
- broker rules, reasoning, skills, and commands from any external source
  (markdown, folder, repo, GitHub, Confluence, Notion, Jira, Linear,
  Slack)
- run computational and inferential sensors as blocking checks
- resolve a cascade across external sources and the project layer
  (canonical locks, required gaps, conflicts, unreachable items)
- apply forward-only shipped-template patches as the manager evolves
- drive Learning + Pruning flywheels via shipped playbooks and skills
- overlay the agent menu file (CLAUDE.md, AGENTS.md, …) without
  clobbering any pre-existing user content

The agent treats each retrieved payload differently:

- **rules** — constraints to obey (`must` / `should` / `may`)
- **reasoning** — background facts and intent
- **skills** — procedural how-to knowledge (multi-step playbooks)
- **commands** — canned invocations (shell commands, scripts, named recipes)

Instead of cramming organizational context into every system prompt, the agent
reads `keystone://context/{topic}` resources or calls `keystone_get_context(topic)` and the
broker fans the request out to the right backing source.

## Status

**0.2.0.** Pre-1.0; the package name on PyPI stays `keystone-mcp`.
Phases 1–28 shipped per [`FEATURE_PARITY_PLAN.md`](./FEATURE_PARITY_PLAN.md)
and [`CHANGELOG.md`](./CHANGELOG.md). 361 tests pass.

## Adapters

Source types (`type:` in `.keystone/context.yaml`):

| Type | Auth | What it emits |
| --- | --- | --- |
| `markdown` | none (repo-local) | one markdown file per query — rules / reasoning / skills / commands |
| `folder` | none (repo-local) | walks a local directory tree of markdown. Globs (`include` / `exclude`) |
| `repo` | (optional, depends on remote) | resolves `owner/repo@version` or a git URL; caches under `~/.cache/keystone-mcp/repos/<sha>/`. Tag/sha refs cache immutably; branch refs honor `ttl` |
| `github` | PAT | CODEOWNERS, branch protection (rules); PRs, releases (reasoning) |
| `confluence` | email + API token | page content (all four kinds) |
| `notion` | integration token | page content (all four kinds), database rows (reasoning) |
| `jira` | email + API token | issues, JQL search (reasoning) |
| `linear` | personal API key | issues, GraphQL filter (reasoning) |
| `slack` | bot OAuth token | pinned messages (rules), recent discussion (reasoning) |
| `harness` | none | the project's own `.keystone/harness/` tree (root is fixed) |

## Install

Published to PyPI as [`keystone-mcp`](https://pypi.org/project/keystone-mcp/).

```bash
pip install keystone-mcp             # core
pip install "keystone-mcp[tokens]"   # + tiktoken-backed budget tokenizer
uvx keystone-mcp                     # one-shot run via uv
pipx install keystone-mcp            # install + add to PATH
```

Without the `tokens` extra, `keystone://harness/budget` falls back to
a deterministic word-count proxy (~0.75 words / token). With the
extra, the budget reports exact `cl100k_base` token counts.

Or from source:

```bash
git clone https://github.com/tacoda/keystone-mcp.git
cd keystone-mcp
uv sync
uv run keystone-mcp        # console entry point
```

Wire into a Claude Code (or any MCP host) project. Add to `.mcp.json`:

```json
{
  "mcpServers": {
    "keystone": {
      "command": "uvx",
      "args": ["keystone-mcp"],
      "env": {
        "KEYSTONE_CONFIG": "/path/to/your/project/.keystone/context.yaml"
      }
    }
  }
}
```

The config path defaults to `.keystone/context.yaml` relative to the working
directory; override with `KEYSTONE_CONFIG`.

## Quickstart

1. Create `.keystone/context.yaml` in your project:

   ```yaml
   sources:
     docs:
       type: markdown
       root: .keystone/context/

   topics:
     deploy-policy:
       description: |
         Rules and context for production deploys.
       sources:
         - source: docs
           query: { file: deploy-policy.md }
           classify:
             rules: { heading: "Rules", severity: must }
             reasoning: { heading: "Background" }
       cache: 15m
   ```

2. Create `.keystone/context/deploy-policy.md`:

   ```markdown
   # Deploy Policy

   ## Rules

   - MUST run full CI green before any production deploy.
   - SHOULD prefer Tuesday/Wednesday morning deploys.

   ## Background

   The team adopted these rules after a 2025 incident.
   ```

3. Start the server. The agent now sees `deploy-policy` in `keystone_list_topics`
   and can read `keystone://context/deploy-policy` to load the envelope.

The repo's own [`.keystone/context.yaml`](./.keystone/context.yaml) is a
working example with topics for deploys, ownership, coding standards, and a
release playbook (plus commented-out examples of every external adapter).

## MCP surface

### Tools

| Tool | Returns |
|---|---|
| `keystone_get_context(topic)` | full envelope (rules + reasoning + skills + commands) |
| `keystone_list_topics(tag?)` | directory of configured topics |
| `keystone_harness_bootstrap()` | scaffold the harness skeleton at `.keystone/harness/` |
| `keystone_new_guide(name, tier?)` | scaffold a new guide; `tier` ∈ `iron-law` / `golden` / `rules` |
| `keystone_new_sensor(name, kind?, mode?)` | scaffold a sensor + matching script (computational) or prompt (inferential) |
| `keystone_new_script(name, body?)` | scaffold a sensor script (or ad-hoc shell script) |
| `keystone_new_prompt(name, body?)` | scaffold a sensor prompt (or ad-hoc prompt for inferential checks) |
| `keystone_new_skill(name, description?)` | scaffold `skills/<name>/SKILL.md` (FastMCP-native; manager-authored skills are auto-prefixed `keystone-`) |
| `keystone_new_action(name)` | scaffold `actions/<name>.md` |
| `keystone_new_playbook(name)` | scaffold `playbooks/<name>.md` |
| `keystone_new_corpus(name)` | scaffold `corpus/<name>.md` |
| `keystone_new_adapter(agent)` | scaffold a per-agent adapter dir |
| `keystone_target_add(agent, project_root?)` | install or refresh agent menu file at project root (overlay; preserves user content) |
| `keystone_apply_patches()` | apply pending shipped patches; skips user-modified files |

### Prompts

Lifecycle workflows that seed multi-step agent conversations. The agent
invokes a prompt, walks the phases, and calls scaffold tools along the way.

| Prompt | Purpose |
|---|---|
| `bootstrap()` | one-time codebase analysis → fill state ledgers under `corpus/state/` |
| `task(description)` | end-to-end work: spec → orient → implement → verify → review |
| `audit()` | dual-flywheel: learning (capture) + pruning (retire stale) |
| `learn(finding)` | capture a finding into `learning/inbox/` for batched promotion |

All harness paths are fixed under `.keystone/harness/` — the `.keystone/`
directory is team-shared and version-controlled. **Never put secrets there.**
Reference them via `env:VAR` in `.keystone/context.yaml` instead. Scaffold
tools refuse to write files whose names look like secrets (`secret`, `token`,
`credential`, `password`, `api_key`, `private`, `envfile`, …).

### Resources

| URI | Purpose |
|---|---|
| `keystone://context/list` | configured topic directory |
| `keystone://context/{topic}` | full envelope for one topic |
| `keystone://source/{name}/health` | adapter reachability + auth state |
| `keystone://harness/status` | harness layout audit (root=harness) |
| `keystone://harness/options` | valid scaffold-tool arguments |
| `keystone://harness/verify` | cascade report (resolved / unreachable / canonical_violations / required_gaps / conflicts) |
| `keystone://harness/doctor` | verify + path conformance + ambient-load budget proxy |
| `keystone://harness/patch/pending` | pending shipped patches and detected conflicts |
| `keystone://harness/budget` | ambient-load budget report (per-port + hot files + approximate tokens) |

### Envelope shape

Every retrieval returns the same envelope. Example:

```json
{
  "topic": "deploy-policy",
  "rules": [
    {
      "id": "rules-001",
      "text": "run full CI green before any production deploy.",
      "source": "markdown://deploy-policy.md#rules",
      "severity": "must"
    }
  ],
  "reasoning": [
    {
      "text": "The team adopted these rules after a 2025 incident.",
      "source": "markdown://deploy-policy.md#background"
    }
  ],
  "skills": [],
  "commands": [],
  "fetched_at": "2026-06-10T14:32:00+00:00",
  "cache_hit": false
}
```

## Configuration

### Topics

Topics are the agent-facing abstraction. Each topic binds one or more
adapter calls and declares how their output classifies into the four kinds:

```yaml
topics:
  repo-policy:
    description: Combined ownership and branch-protection rules.
    sources:
      - source: docs
        query: { file: owners.md }
        classify:
          rules: { heading: "Required reviewers" }
      - source: gh
        query: { type: codeowners }
      - source: gh
        query: { type: branch_protection, branch: main }
    cache: 5m
```

Single-source topics can use the shorthand:

```yaml
topics:
  rollback:
    description: Rollback procedure.
    source: docs
    query: { file: rollback.md }
    classify:
      rules: { heading: "Rules" }
```

### Multi-source merge

When two sources contribute rules whose normalized text matches:
- **Highest severity wins** (`must > should > may`).
- **Ties** at the top severity keep both rules so each source stays cited.

Reasoning, skills, and commands stay additive — no deduplication.

### Classify selectors

`markdown`, `confluence`, and `notion` share the same heading-based
vocabulary. Sections split by H2; skills/commands sub-split by H3.

```yaml
classify:
  rules:
    heading: "Rules"             # single or list, e.g. ["Rules", "Must"]
    severity: must               # default for bullets without MUST/SHOULD/MAY prefix
  reasoning:
    heading: "Background"
    # or
    all: true                    # everything not matched by another kind
  skills:
    heading: "Procedures"        # each H3 → one skill (name + body)
  commands:
    heading: "Commands"          # each H3 → one command (first code block = invocation)
```

For `github`, `jira`, `linear`, `slack` the query `type` determines the kind
(e.g. `codeowners` → rules, `recent_prs` → reasoning).

### Secrets

Reference environment variables with the `env:` prefix:

```yaml
sources:
  gh:
    type: github
    repo: acme/widgets
    auth: env:GITHUB_TOKEN
```

The loader fails fast at startup if a referenced env var is unset.

### Cache

Default is in-memory (lost on restart). Persistent sqlite cache survives
process restarts:

```yaml
cache:
  backend: sqlite
  path: .keystone/cache.db
```

Per-topic TTLs use `5s` / `10m` / `2h` / `1d` syntax.

## Development

```bash
uv sync                     # install deps
uv run pytest -q            # run tests
uv run python -m keystone_mcp.server   # run server
```

The test suite uses `respx` to mock all external APIs — no live credentials
required.

## License

TBD.
