BlockSpool MCP server - stateful tool provider for Claude Code
npm install @blockspool/mcpStateful MCP server that powers BlockSpool's improvement loop. Exposes tools for session management, scouting, execution, and git operations.
``bashAs stdio MCP server (for Claude Code plugin)
npx @blockspool/mcp
const client = await DirectClient.create({ projectPath: '.' });
client.startSession({ scope: 'src/**', formula: 'security-audit' });
while (true) {
const resp = await client.advance();
if (resp.next_action === 'STOP') break;
// ... call your LLM with resp.prompt ...
await client.ingestEvent('SCOUT_OUTPUT', { proposals: [...] });
}
client.endSession();
await client.close();
`
| Tool | Description | Parameters |
|------|-------------|------------|
| blockspool_start_session | Initialize a session | hours?, formula?, deep?, scope?, categories?, min_confidence?, max_prs?, step_budget?, ticket_step_budget?, draft_prs? |blockspool_advance
| | Get next action (main loop driver) | — |blockspool_ingest_event
| | Report event, trigger state transitions | type, payload |blockspool_session_status
| | Current session state | — |blockspool_end_session
| | Finalize session | — |blockspool_nudge
| | Add hint for next scout cycle | hint |blockspool_list_formulas
| | List available formulas | — |blockspool_get_scope_policy
| | Get scope policy for current ticket | file_path? |
| Tool | Description | Parameters |
|------|-------------|------------|
| blockspool_next_ticket | Get next ticket to work on | — |blockspool_validate_scope
| | Check changed files against scope | ticketId, changedFiles[] |blockspool_complete_ticket
| | Mark ticket done, run QA | ticketId, runId, summary? |blockspool_fail_ticket
| | Mark ticket failed | ticketId, runId, reason |
| Tool | Description | Parameters |
|------|-------------|------------|
| blockspool_git_setup | Create/checkout branch for ticket | ticketId, baseBranch? |
The core protocol is adapter-agnostic. Any client repeats:
``
advance() → get prompt + constraints
→ execute prompt (any LLM)
→ ingest_event(type, payload)
→ repeat until STOP
| Event | When | Payload |
|-------|------|---------|
| SCOUT_OUTPUT | After scouting | { proposals: [...] } |PLAN_SUBMITTED
| | After planning | { ticket_id, files_to_touch, estimated_lines, risk_level } |TICKET_RESULT
| | After execution | { status, changed_files, lines_added, lines_removed } |QA_COMMAND_RESULT
| | Per QA command | { command, success, output } |QA_PASSED
| | All QA passes | { summary } |QA_FAILED
| | QA fails | { error } |PR_CREATED
| | PR created | { url, branch } |USER_OVERRIDE
| | Hint or cancel | { hint } or { cancel: true } |
`
SCOUT → NEXT_TICKET → PLAN → EXECUTE → QA → PR → NEXT_TICKET → DONE
Terminal states: DONE, BLOCKED_NEEDS_HUMAN, FAILED_BUDGET, FAILED_VALIDATION, FAILED_SPINDLE
`
Built-in formulas customize scout behavior:
| Formula | Description | Categories |
|---------|-------------|------------|
| security-audit | OWASP vulnerabilities | security |test-coverage
| | Missing unit tests | test |type-safety
| | Remove any/unknown | types |cleanup
| | Dead code, unused imports | refactor |deep
| | Architecture review | refactor, perf, security |docs
| | Missing JSDoc | docs |
Create .blockspool/formulas/:
`yaml`
description: Find and fix error handling issues
categories: [refactor, security]
min_confidence: 75 # hint only — does not filter proposals
risk_tolerance: medium
prompt: |
Find functions with missing error handling.
Look for uncaught promises, empty catch blocks,
and functions that silently swallow errors.
tags: [quality]
Each session creates a run folder at .blockspool/runs/:
``
.blockspool/runs/run_abc123/
├── state.json # Current RunState (overwritten each step)
├── events.ndjson # Append-only event log (one JSON per line)
├── diffs/ # Patch files per step
│ └── 5-tkt_xyz.patch
└── artifacts/ # QA logs, scout proposals, etc.
├── 1-scout-proposals.json
├── 3-ticket-result.json
├── 4-qa-npm-test-pass.log
└── 5-pr-created.json
1. Check phase: cat .blockspool/runs/cat .blockspool/runs/
2. Read events: grep FAILED .blockspool/runs/
3. Find the failure: cat .blockspool/runs/
4. Check spindle: cat .blockspool/runs/
5. Read QA logs:
| Field | Description |
|-------|-------------|
| phase | Current state machine phase |step_count
| / step_budget | Progress tracking |tickets_completed
| / tickets_failed | Work summary |spindle
| | Loop detection state (output_hashes, diff_hashes, iterations_since_change) |current_ticket_id
| | Active ticket being worked on |plan_approved
| | Whether commit plan was approved |hints
| | Pending hints from nudge |
``
Claude Code / Any LLM
└─ MCP: @blockspool/mcp (stdio)
├─ advance() — deterministic state machine
├─ processEvent() — event-driven transitions
├─ checkSpindle() — loop detection
├─ deriveScopePolicy()— scope enforcement
├─ loadFormula() — formula system
├─ loadGuidelines() — CLAUDE.md context injection
└─ SQLite state — tickets, runs, proposals
The advance engine automatically loads project guidelines and prepends them to scout and execute prompts. This ensures agents follow project conventions without any configuration.
- Claude runs search for CLAUDE.md first, then fall back to AGENTS.mdAGENTS.md
- Codex runs search for first, then fall back to CLAUDE.mdadvance()
- Loaded fresh on every call (MCP sessions are stateless between calls)
- Wrapped in
- Full file content injected (no truncation)