Decision OS MCP
An MCP server for Decision OS — an LLM-native decision tracking and learning system.
What is Decision OS?
Decision OS captures novel pressure — moments when reality surprises you during engineering work. Unlike traditional documentation, it focuses on what an LLM couldn't predict, creating a learning loop:
Cases → Pressure Events (surprises) → Outcomes → Foundations (compressed learnings)
Quick Start
1. Install the MCP Server
# Global install
npm install -g decision-os-mcp
# Or use npx (no install needed)
npx decision-os-mcp
2. Add to Your Project
Copy the template to your project:
cp -r templates/.decision-os /path/to/your-project/
Edit config.yaml with your project name.
3. Configure Cursor
Add to your project's .cursor/mcp.json:
{
"mcpServers": {
"decision-os": {
"command": "npx",
"args": ["-y", "decision-os-mcp"],
"env": {
"DECISION_OS_PATH": "${workspaceFolder}/.decision-os"
}
}
}
}
Copy the Cursor rules template:
cp templates/.cursor/rules/decision-os.mdc /path/to/your-project/.cursor/rules/
Tools
| Tool | Description |
|---|---|
get_context |
Get active case, recent pressures, foundations ranked by relevance, conflicts |
log_pressure |
Log a pressure event when reality differs from expectation |
quick_pressure |
Quick-capture a pressure event with minimal friction (only expected + actual required) |
create_case |
Create a new case (unit of work) |
close_case |
Close a case with outcome signals and regret score (auto-forgets successful cases) |
set_active_case |
Set the active case for the session (persists across restarts) |
get_foundations |
Query foundations from project and global scopes |
search_pressures |
Search past pressure events |
check_policy |
Check what policy requires for given signals |
promote_to_foundation |
Promote pressure events to a foundation (PROJECT or GLOBAL scope) |
elevate_foundation |
Elevate a project foundation to global scope |
validate_foundation |
Validate that a global foundation applies in current project |
suggest_review |
Review project for unextracted learnings and forgetting opportunities |
list_cases |
List all cases in the project |
Core Concepts
Pressure Events
The primary learning artifact. Logged when something unexpected happens:
expected: "Supabase insert would throw on null FK"
actual: "RLS silently blocked the write, no error"
adaptation: "Added explicit null-check before insert"
remember: "Supabase RLS fails silently on null FK values"
Foundations
Compressed learnings promoted from repeated pressure events:
id: F-0001
title: "Supabase RLS fails silently on null FK"
default_behavior: "Always validate FK values before insert when using RLS"
context_tags: [SUPABASE, RLS, DATA_MODEL]
confidence: 2 # Out of 3
scope: PROJECT # or GLOBAL
origin_project: my-project
validated_in: [my-project, other-project]
exit_criteria: "Supabase adds explicit error for null FK violations"
source_pressures: [PE-0003, PE-0007]
Hierarchical Foundations (GLOBAL -> PROJECT)
Decision OS supports a cascading scope model similar to Git config:
~/.decision-os/ # GLOBAL (user-wide, universal learnings)
├── config.yaml
└── defaults/foundations.yaml # GF-prefixed foundations
~/projects/my-app/.decision-os/ # PROJECT (specific to this codebase)
├── config.yaml
├── cases/
└── defaults/foundations.yaml # F-prefixed foundations
Resolution order: PROJECT wins over GLOBAL on conflicts.
Global foundations are recommendations, not rules. They represent universal patterns that transcend specific tech stacks:
- Tool behaviors (e.g., "MCP descriptor paths may be stale")
- Debugging strategies (e.g., "Trace call sites before refactoring")
- Meta-learnings (e.g., "Question requirements before implementing")
Setup global foundations:
# Create global .decision-os
mkdir -p ~/.decision-os/defaults
cp templates/global-.decision-os/config.yaml ~/.decision-os/
cp templates/global-.decision-os/defaults/foundations.yaml ~/.decision-os/defaults/
Conflict detection: When get_context is called, it highlights conflicts where project and global foundations overlap or contradict each other.
Cases
Bounded units of work (feature, bugfix, spike) that provide context for pressure events:
id: 0001-add-tile-caching
title: "Add tile caching"
goal: "Reduce API latency for repeated tile requests"
status: ACTIVE
signals:
context:
risk_level: MEDIUM
affected_surface: [PERFORMANCE_CRITICAL, INTEGRATION]
decisions:
approach: BUILD
posture: BALANCED
validation_level: STANDARD
Directory Structure
# Global (user-wide)
~/.decision-os/
├── config.yaml # scope: GLOBAL
└── defaults/
└── foundations.yaml # GF-prefixed universal learnings
# Project (per-codebase)
your-project/
├── .decision-os/
│ ├── config.yaml # scope: PROJECT
│ ├── cases/
│ │ ├── 0001-bootstrap/
│ │ │ ├── case.yaml # Case metadata
│ │ │ └── pressures.yaml # Pressure events
│ │ └── 0002-add-auth/
│ │ └── ...
│ └── defaults/
│ └── foundations.yaml # F-prefixed project learnings
├── .cursor/
│ ├── mcp.json # MCP server config
│ └── rules/
│ └── decision-os.mdc # LLM instructions
└── src/
LLM Workflow
- At task start: Call
get_context()to load active case and foundations (ranked by relevance) - When surprised: Call
quick_pressure()for fast capture orlog_pressure()for full detail - Before BUILD decisions: Call
check_policy()to see requirements - At task end: Call
close_case()with regret score - Periodically: Call
suggest_review()to find unextracted learnings and forgetting opportunities
Forgetting
The system forgets by design. Cases are temporary containers — knowledge lives in foundations.
When close_case() is called with regret 0 and there are no unpromoted pressure events, the case is automatically deleted. Not archived. Forgotten.
This keeps the .decision-os/cases/ directory lean: only cases that still have uncompressed learning (unpromoted PEs or regret 1+) survive.
The lifecycle:
- Cases are born when work starts
- Pressure events are captured when surprises happen
- PEs are promoted to foundations when patterns emerge
- Cases are forgotten when they have nothing left to teach
- Foundations survive as the only persistent knowledge
Use suggest_review() to find cases blocking forgetting (regret 0 but unpromoted PEs remain) and decide whether to promote or discard them.
Active Case Persistence
The active case is persisted to .decision-os/.active-case and survives MCP server restarts. No more losing your active case when Cursor restarts.
Signals Vocabulary
Context Signals (before execution)
risk_level: LOW / MEDIUM / HIGHreversibility: EASY / MEDIUM / HARDchange_frequency: RARE / OCCASIONAL / FREQUENTaffected_surface: CORE_DOMAIN / INTEGRATION / DATA_MODEL / INFRA_DEPLOY / SECURITY_BOUNDARY / UI_UX / PERFORMANCE_CRITICALnovelty: LOW / MEDIUM / HIGH
Decisions
approach: REUSE / REFRAME / BUILD / HYBRIDposture: MINIMAL / BALANCED / ROBUSTvalidation_level: BASIC / STANDARD / STRICT
Outcome Signals
regret: 0-3 (0 = would choose same, 3 = strong regret)regressions: NONE / MINOR / MAJOR
Development
# Install dependencies
npm install
# Build
npm run build
# Run locally
DECISION_OS_PATH=/path/to/.decision-os npm start
Philosophy
- Log only novel pressure: Don't document what an LLM could derive
- The system should forget: Successful cases are deleted. Knowledge lives in foundations, not cases
- Hypotheses, not axioms: Foundations have confidence and can be revised
- Minimal ceremony: Small vocabulary, structured but not bureaucratic
- Capture first, filter later: When unsure, log it — capturing too much is better than missing surprises
- LLM-native: Designed for AI-assisted engineering workflows
License
MIT