ContextForge MCP Server

ContextForge MCP Server

Enables AI agents to efficiently retrieve relevant code context via PageRank-optimized subgraphs and automate spec generation, implementation planning, and pre-commit validation.

Category
Visit Server

README

ContextForge

Pipeline determinista que convierte cualquier repo en un índice consultable por agentes IA. 94.4 % menos tokens por sesión, 17.9× compresión, ÷28× costo SDD con prompt caching — sin LLM en el pipeline, sin lock-in de agente.

214 600 tokens (todo el repo)  →  11 988 tokens (lo que importa a la tarea)

tests savings npm docker


El problema que resuelve

Cada vez que un agente IA (Claude Code, Cursor, OpenCode) abría el repo tenía que:

  1. Leer TODO para entender qué existe
  2. Recordar correr pnpm forge context manualmente antes de cada tarea
  3. Adivinar qué archivos tocar sin contexto del grafo
  4. No había gate pre-commit — specs y guardrails se saltaban fácil

Ahora todo eso es automático vía MCP + hooks.


Cómo encaja cada pieza

Dev / Agente (Claude Code · Cursor · OpenCode) escribe tarea
        │
        ▼
[Hook UserPromptSubmit]  ← automático, sin hacer nada
  → MCP: select_agent_context(task)
  → Agente recibe: skills relevantes + domains tocados
        │
        ▼
Agente llama forge_context(task)  ← MCP tool, sin pnpm, sin disco
  → ~20 archivos rankeados por PageRank + BFS
  → sabe exactamente qué leer, no el repo entero
        │
        ▼
Agente llama forge_spec("mi-feature")  ← MCP tool
  → escribe openspec/changes/mi-feature/
      ├── proposal.md        ← motivación y alcance
      ├── design.md          ← decisiones técnicas
      ├── tasks.md           ← lista de tareas
      ├── specs/             ← Requirements + Scenarios (Given/When/Then)
      ├── graph.subset.json  ← subgrafo FROZEN de los archivos relevantes
      ├── context.md         ← mapa de lectura para el agente
      └── agent-manifest.json ← skills filtradas SOLO para este change
        │
        ▼
Agente/Dev llena proposal.md + specs/*.md
  openspec validate mi-feature  ← verifica formato Requirement + Scenario
        │
        ▼
Agente llama forge_implement("mi-feature")  ← MCP tool
  → .contextforge/implement-plan.json
      allowedFiles: [solo los del context-pack]
      maxLocDelta: estimado del pack
        │
        ▼
Agente implementa código
        │
        ▼
Agente intenta  git commit
        │
        ▼
[Hook PreToolUse]  ← automático, bloquea si hay violaciones
  → node .claude/hooks/forge-pre-commit.mjs
  → forge implement --check valida git diff vs guardrails
  → archivo fuera de allowedFiles → exit 2 → COMMIT BLOQUEADO
  → Agente recibe lista de violaciones y corrige antes de reintentar
        │
        ▼
Commit pasa → merge
        │
        ▼
Agente corre  openspec archive mi-feature
        │
        ▼
[Hook PostToolUse(openspec)]  ← automático, en background
  → forge_rebuild_graph async
  → grafo fresco para la próxima tarea

ContextForge no reemplaza OpenSpec — lo alimenta

OpenSpec es el framework de specs. Claude Code / Cursor / OpenCode son los agentes IA que lo usan. ContextForge le da a los agentes el contexto correcto para que OpenSpec reciba datos reales del código, no inventados.

OpenSpec hace ContextForge aporta
Valida formato Requirement: + Scenario: El contexto correcto para escribir la spec
Archiva y mueve specs a openspec/specs/ El subgrafo frozen que dice qué archivos aplican
openspec validate chequea Given/When/Then forge_check chequea que el código respete los guardrails
Historial de specs por feature forge_status muestra qué changes tienen subgrafo activo

Antes vs ahora

Sin hooks ni MCP — el dev recordaba (o no) cada paso:

pnpm forge scan
pnpm forge graph
pnpm forge context "mi tarea"
pnpm forge spec mi-feature
# llenar docs...
pnpm forge implement mi-feature
# codear...
pnpm forge implement --check  # se olvidaba frecuentemente
git commit
openspec archive mi-feature
pnpm forge scan && pnpm forge graph  # se olvidaba siempre

Ahora — los hooks y MCP tools hacen el trabajo:

# Agente recibe contexto automático al escribir el prompt (hook)
# Llama forge_context → forge_spec → forge_implement via MCP (sin pnpm)
# Dev/agente llena las specs → openspec validate confirma formato
# Agente codea
git commit              # → hook bloquea si hay violaciones, las explica
openspec archive mi-feature  # → hook reconstruye grafo en background

pnpm forge manual solo para bootstrap (forge init) o forzar reconstrucción (forge graph --force).


Instalación

npm — público, sin token:

# CLI (uso diario)
pnpm add -g @anai-raia-alex/contextforge-cli         # global
# o
pnpm add -D @anai-raia-alex/contextforge-cli         # por proyecto

# MCP server (para agentes vía Node)
pnpm add -D @anai-raia-alex/contextforge-mcp

# OpenSpec CLI (recomendado, activa el modo handoff)
npm i -g @fission-ai/openspec

Docker — sin instalar Node, multi-arch (amd64+arm64):

docker pull ghcr.io/alejandro-cedeno-10/contextforge-mcp:latest

Desde fuente (desarrollo):

git clone https://github.com/alejandro-cedeno-10/contextforge-cli.git
cd contextforge-cli
pnpm install && pnpm build

Quick start (5 comandos para empezar)

# 1. Inicializar (corre 'openspec init' si está en PATH; instala instrucciones del agente)
pnpm forge init

# 2. Indexar el repo (incremental; cache por hash)
pnpm forge scan
pnpm forge graph

# 3. Por cada tarea
pnpm forge context "fix race en tokenLedger writer"

# 4. SDD opcional (con OpenSpec)
pnpm forge spec mi-feature-id    # spec-input + handoff/fallback
openspec validate mi-feature-id

# 5. Implementar con guardrails
pnpm forge implement mi-feature-id
# (trabajas con el agente)
pnpm forge implement --check     # gate pre-commit

Las tres capas

Capa 1 — Grafos para ahorrar tokens

En lugar de "leer todo el repo", rankeamos los archivos por relevancia a tu tarea con el grafo de dependencias real del código + Personalized PageRank.

Pipeline:

pnpm forge scan       # Indexa con BLAKE3 (incremental)
pnpm forge graph      # Grafo file + symbol con tree-sitter
pnpm forge context "<tarea>"   # PageRank + BFS + budget

Algoritmo:

1. resolve_seeds(task)        → archivos semilla por keywords
2. personalized_pagerank()    → ranking de relevancia (alpha=0.85, 50 iter)
3. bfs_expand(depth=2)        → captura deps directas + transitivas
4. score_nodes()              → pagerank × (1/bfs_dist) × edge_multiplier
5. greedy_pack(budget=12000)  → llena hasta 12k tokens (full → excerpt → summary)

Edge multipliers: tests=1.2 · defines=1.0 · calls=1.0 · imports=0.8 · references=0.6

Ahorro medido en este repo:

Sin ContextForge Con context-pack
214 600 tokens 11 988 tokens
~$0.64 / sesión (Claude Sonnet 4.6) ~$0.036 / sesión
128 archivos enviados 50 archivos seleccionados

Compresión: 17.9× · Ahorro: 94.4 %

Capa 2 — SDD apoyando a OpenSpec (no compitiendo con él)

v0.3.0+ — forge spec ya no genera el spec final. Genera la entrada (spec-input.json + spec-prompt.md) para que OpenSpec o un agente IA lo escriban con todo el contexto correcto.

Tres roles separados, cada uno hace lo suyo:

       ┌─────────────────────┐    ┌─────────────────────┐    ┌────────────────┐
       │   ContextForge      │    │     OpenSpec        │    │   Agente IA    │
       ├─────────────────────┤    ├─────────────────────┤    ├────────────────┤
ROL    │  Selección de       │    │  Estructura +       │    │  Redacción     │
       │  contexto           │    │  validación         │    │                │
       ├─────────────────────┤    ├─────────────────────┤    ├────────────────┤
TÉC.   │  PageRank + BFS +   │    │  Schemas RFC 2119   │    │  LLM           │
       │  budget tokens      │    │  Given/When/Then    │    │                │
       ├─────────────────────┤    ├─────────────────────┤    ├────────────────┤
INPUT  │  scan + graph +     │    │  spec-input.json    │    │  spec-prompt.md│
       │  task               │    │                     │    │  + context-pack│
       ├─────────────────────┤    ├─────────────────────┤    ├────────────────┤
OUTPUT │  context-pack +     │    │  proposal/design/   │    │  .md llenos    │
       │  spec-input + prompt│    │  tasks/spec.md      │    │  + commits     │
       └─────────────────────┘    └─────────────────────┘    └────────────────┘

Pipeline SDD completo:

pnpm forge context "<tarea>"          # context-pack + agent-manifest
pnpm forge spec mi-feature-id         # spec-input + handoff/fallback
openspec list                          # ver changes activos
openspec validate mi-feature-id        # validación oficial
pnpm forge implement mi-feature-id     # plan con guardrails
# (trabajas con el agente)
pnpm forge implement --check           # gate pre-commit
openspec archive mi-feature-id -y      # al mergear: mueve a specs/

Modo handoff vs modo fallback:

Modo Cuándo Qué pasa
Handoff (default si OpenSpec CLI está) openspec --version resuelve forge spec ejecuta openspec new change + emite .contextforge/spec-prompt.md con instrucciones canónicas + contexto del grafo. El dev pega ese prompt en su agente
Fallback (sin OpenSpec CLI o --no-openspec) CLI ausente, CI sin instalación ContextForge emite el scaffold con formato moderno (### Requirement: + #### Scenario:). Cuando se instale el CLI después, openspec validate pasa sin retoque

Mismo contrato (spec-input.json), dos formas de consumirlo. Portable Mac/Linux/Windows.

Forma de cada Requirement (RFC 2119 + Given/When/Then):

### Requirement: System produces fix-token-race within budget

The system MUST implement the change `fix-token-race` while respecting
`guardrails.allowedFiles` and not exceeding `guardrails.maxLocDelta`.

#### Scenario: change is implemented within scope

- **Given** a valid `.contextforge/context-pack.json` for the task
- **When** the developer runs `pnpm forge implement fix-token-race`
- **Then** `pnpm forge implement --check` exits with code 0

Guardrails de implementación (derivados del grafo):

forge implement produce implement-plan.json cuyos campos vienen del context-pack:

  • allowedFiles[] ← exactamente los archivos del pack
  • forbiddenPaths[] — nunca tocar
  • maxLocDelta — derivado del tamaño del pack
  • maxFilesChangedallowedFiles.length + 2

forge implement --check valida tu git diff antes del commit. Si te saliste del scope, te lo dice exactamente y el commit no pasa.

Capa 3 — Solo cargar las skills/rules que aplican a la tarea

forge context ya emite 5 artefactos sin paso extra:

.contextforge/context-pack.json              ← archivos relevantes
.contextforge/token-ledger.json              ← métricas
.contextforge/agent-manifest.json            ← NEUTRAL (validado por schema)
.claude/agent-manifest.md                    ← renderer Claude Code
.cursor/rules/contextforge-active.mdc        ← renderer Cursor (Auto-Attached)
.contextforge/manifests/opencode-readme.md   ← renderer OpenCode

Reglas de matching (priorizadas):

  1. alwaysApply: true → siempre incluida.
  2. frontmatter domains: [..] ∩ dominios tocados → match domain.
  3. nombre contextforge-domain-<slug> del dominio tocado → match explicit (legacy ctx-<slug> aún soportado).
  4. nada matchea → skipped (con razón).

Frontmatter mal formado nunca crashea: cae en skipped con frontmatter parse error.

Activación por agente (sin pasos manuales después de setup):

Agente Cómo se carga Setup
Claude Code Hook UserPromptSubmit regenera el manifest en cada prompt Pegar snippet en .claude/settings.json (ver docs/integrations/claude-code-hook.md)
OpenCode El agente llama tool MCP select_agent_context({task}) al inicio. Live, sin disco opencode.json ya configurado
Cursor Rule Auto-Attached con globs: por dominio. Se activa al abrir un archivo del dominio Sin setup; forge context regenera la rule

El grafo en detalle

Esta sección explica qué genera forge graph, cómo lo genera, cómo lo visualiza, y cómo el agente lo consume. Si vienes de Understand-Anything, vas a reconocer la idea: convertir un repo en un mapa navegable. La diferencia es que aquí el pipeline es 100 % determinista (sin LLM en el loop, sin coste por correrlo), cacheable por archivo, y los outputs son JSON portables que cualquier agente puede consumir sin la app.

Pipeline de generación (qué pasa cuando corres forge graph)

┌──────────────┐       ┌─────────────┐       ┌──────────────┐       ┌──────────────┐
│  scan.json   │  →    │  per-file   │  →    │  graph passes│  →    │  graph.json  │
│  (BLAKE3)    │       │  cache hit? │       │  (4 etapas)  │       │  + cache.json│
└──────────────┘       └─────────────┘       └──────────────┘       └──────────────┘
       │                      │                      │
       │                      │                      ├─ Pass 0: file nodes
       │                      │                      ├─ Pass 1: parse code/test (paralelo, n=cpus)
       │                      │                      ├─ Pass 2: defines + imports + tests
       │                      │                      ├─ Pass 3: extends / implements
       │                      │                      ├─ Pass 3.5 (--with-calls): calls
       │                      │                      └─ Pass 4: folder + contains
       │                      │
       │                      └─ Si `file.hash` coincide con cache, reusa el fragment parseado
       │                         y solo recomputa las aristas cross-file (imports/extends/calls).
       │
       └─ Hash global del scan: si no cambió, `forge graph` ni siquiera arranca (skip).

Output canónico.contextforge/graph.json cumple docs/schemas/graph.schema.json:

{
  "schemaVersion": "0.2.0",
  "project": { "name": "contextforge-cli", "root": "." },
  "generatedAt": "2026-05-08T...Z",
  "scanRef": { "path": ".contextforge/scan.json", "scanHash": "..." },
  "parser": { "engine": "heuristic" },
  "stats": {
    "nodesByType": { "file": 287, "folder": 117, "symbol": 3104 },
    "edgesByType": { "imports": 71, "defines": 2256, "contains": 376 }
  },
  "nodes": [
    /* ordenados por id, JSON byte-estable */
  ],
  "edges": [
    /* ordenadas por (from,to,type) */
  ]
}

Tipos de nodo y arista que produce

Nodo Cuándo aparece
file Uno por cada archivo del scan (code/test/doc/config/asset)
symbol Por cada función/clase/interface/type/var/enum exportada o interna
folder Sintético, derivado de los paths (anidación completa)
package Por cada import externo único (react, node:path, @anthropic-ai/sdk, …)
Arista De qué Cuándo se emite
defines file → symbol Siempre que el archivo contiene un símbolo
imports file → file o file → package Relativos · alias workspace (pnpm) · alias tsconfig.paths · externos
tests file:test → file:impl Convención *.test.ts*.ts
extends symbol → symbol Clase/interface extiende un símbolo del mismo file o de un import
implements symbol → symbol class A implements B resuelto
contains folder → folder y folder → file Estructura de carpetas
calls file → symbol Solo con --with-calls (heurística regex, ruido aceptado)
references file → symbol Solo con --with-refs (PascalCase, fuera de imports/defines)

Lenguajes parseables hoy (heurística regex, no tree-sitter WASM): TypeScript, TSX, JavaScript, JSX, Python, Go, Rust, Java. El resto se incluye como file pero sin símbolos.

Incrementalidad y reproducibilidad

pnpm forge graph              # 1ª vez en este repo: 112 archivos parseados
# editas un archivo
pnpm forge scan               # actualiza hashes
pnpm forge graph              # → "cache: 111 reutilizados, 1 reparseados"

pnpm forge graph --force      # ignora ambos caches; reconstruye todo
pnpm forge graph --with-calls # añade aristas calls (heurística, opt-in)
pnpm forge graph --with-refs  # añade aristas references PascalCase (opt-in)

# resolución de imports
#   1. workspace pnpm  (packages/<name>)
#   2. tsconfig.paths  (compilerOptions.paths con baseUrl)
#   3. relativos       (./foo, ../bar)
#   4. externos        → nodo type=package (react, node:fs, @scope/lib)

# export a otros formatos
pnpm forge graph --export=dot     > graph.dot
pnpm forge graph --export=graphml > graph.graphml
# Render con Graphviz: dot -Tsvg graph.dot -o graph.svg
# O abrir graph.graphml directamente en Gephi.

# enriquecimiento opcional con LLM (Anthropic)
ANTHROPIC_API_KEY=sk-... pnpm forge graph --enrich
# Agrega summary / tags / complexity a los símbolos exportados.
# El default sigue siendo determinista; --enrich es la única excepción opt-in.
  • Cache global por hash del scan: si scan.json no cambió, forge graph no arranca.
  • Cache por archivo (.contextforge/graph.cache.json): solo se reparsean los archivos cuyo hash BLAKE3 cambió.
  • Output byte-idéntico entre dos corridas (excluyendo generatedAt): los nodos y aristas se ordenan al final por id / (from,to,type), así que git diff del JSON es revisable y el prompt cache de Claude no se invalida innecesariamente.

Visualización: forge viz

pnpm forge graph
pnpm forge viz                # genera .contextforge/graph.html
# abre el archivo en cualquier navegador, no necesita servidor ni Node

El HTML viewer es standalone (un solo archivo, Cytoscape vía CDN) y trae:

┌──────────────────────────────────────────────────────────────────────┐
│ ContextForge      [Grafo] [Dominios]   287 nodos · 2703 edges · 50 pack│
├──────────────┬───────────────────────────────────────────────────────┤
│ Estadísticas │                                                        │
│  287 archivos │              ●─────●                                  │
│  3104 símbolos│            ╱       ╲       ●  ←  archivo en pack      │
│  2703 edges   │           ●─────●───●      ◇  ←  símbolo exportado    │
│  50 en pack   │            ╲   ╱            ◇  ← dashed = interno     │
│               │             ●─●            ▢  ←  carpeta              │
│ Tour ◀ ▶ ✕   │                                                        │
│  3 / 50       │                                                        │
│               │                                                        │
│ Leyenda nodos │           ┌──────────────┐                            │
│  ● Código 128 │           │   src/       │  ←  agrupación por dominio │
│  ● Test  24   │           │  ┌────┐ ┌──┐ │      (toggle "Agrupar")    │
│  ● Doc   17   │           │  │a.ts│ │b │ │                            │
│  ▢ Carpeta 117│           │  └────┘ └──┘ │                            │
│  ◇ Interno 218│           └──────────────┘                            │
│  ● En pack 50 │                                                        │
│               │                                                        │
│ Leyenda edges │                                                        │
│ ─ imports     │                                                        │
│ ─ defines     │                                                        │
│ ─ tests       │                                                        │
│ ─ extends     │                                                        │
│ ─ contains    │                                                        │
│               │                                                        │
│ Filtros       │                                                        │
│ [Solo pack] [+Sím] [+Carpetas] [Agrupar]                               │
│ [⊕ Centrar]  [⟳ Layout]                                               │
│               │                                                        │
│ 🔍 Buscar...  │                                                        │
│               │                                                        │
│ Nodo selec.   │                                                        │
│  src/main.ts  │                                                        │
│  [code][ts]   │                                                        │
│  Define 4 sím │                                                        │
│  → importa: 3 │                                                        │
│  ← usado por:5│                                                        │
└───────────────┴────────────────────────────────────────────────────────┘

Capacidades del viewer:

  • Dos vistas: grafo file/symbol/folder + vista de dominios (agregación por carpeta top-level, edges = imports cruzados entre dominios).
  • Tour por context-pack: recorre uno por uno los archivos seleccionados por PageRank para tu tarea, centrándose y mostrando vecinos.
  • Filtros incrementales: solo pack (default), añadir símbolos, añadir carpetas, agrupar por dominio.
  • Estilos diferenciados para exported:false (símbolos internos en dashed) y nodos folder.
  • Búsqueda por nombre o ruta con resaltado.
  • Panel de nodo: kind, lang, contadores de edges entrantes/salientes, lista navegable de vecinos.

Cómo lo usa el agente

El agente nunca lee el repo a ciegas. Lee artefactos derivados, en este orden:

1. .contextforge/agent-context.md   ← qué hay disponible y en qué orden leerlo
2. .contextforge/context-pack.json  ← solo los archivos relevantes a la tarea
3. .contextforge/agent-manifest.json ← qué skills/rules aplican (con razón)
4. .contextforge/graph.json          ← solo si necesita ver vecinos / cross-deps

El grafo no se inyecta entero al prompt. El agente lo consulta puntualmente:

Pregunta del agente Cómo responde el grafo
"¿Qué archivos tocan a Foo?" Edges defines/imports entrantes del símbolo
"¿Quién testea esto?" Edges tests entrantes del file
"¿De qué hereda Bar?" Edge extends saliente del símbolo
"¿En qué carpeta vive este archivo?" Edge contains entrante del file
"Dame el subgrafo de mi tarea" Lo entrega forge context ya filtrado (PageRank + BFS + budget)
"Que nada se salga del scope" implement-plan.json::allowedFiles[] derivado del pack

Vía MCP — los agentes que hablen MCP pueden llamar tools sin tocar disco:

{ "tool": "forge_neighbors", "arguments": { "path": "src/foo.ts" } }
// → { incoming: [...], outgoing: [...], symbols: [...] }

{ "tool": "forge_context", "arguments": { "task": "fix race in writer" } }
// → { files: [...], packTokens: 11988, tokenLedger: {...} }

Vs. Understand-Anything (qué tomamos, qué no)

Aspecto Understand-Anything ContextForge
Pipeline Tree-sitter + LLM agents (híbrido) Regex/tree-sitter, 0 LLM en el pipeline
Lenguajes soportados 10+ con WASM 8 con heurística (TS/JS/Py/Go/Rust/Java/TSX/JSX)
Schema de nodo 21 tipos (con dominio + knowledge) 4 tipos canónicos (file/symbol/folder/package)
Schema de arista 35 tipos 8 tipos (los que un agente usa de verdad)
Enriquecimiento (summary) LLM agents enriquecen cada nodo Determinista: contadores derivados del grafo
Coste de regenerar API key + tiempo + ruido CPU-only · cache por archivo · idempotente
Visualización Dashboard rico, tours guiados HTML standalone con tour + dominios + filtros
Persistencia knowledge-graph.json + embeddings graph.json + graph.cache.json (BLAKE3)
Roadmap LLM enrich Es la base Opt-in futuro (--enrich), nunca el default

La filosofía: el grafo de ContextForge no intenta entender el código, intenta darte un índice rápido y barato. La inteligencia semántica vive en el agente, no en el pipeline. Por eso es reproducible y por eso el output sirve de input al prompt cache de Claude (descuento del 90 % en iteraciones 2+ del SDD).


Cómo el grafo le da superpoderes a OpenSpec

El bloque clave de v0.3.0+. Sin grafo, OpenSpec hace su trabajo bien pero el agente trabaja a ciegas. Con grafo, el spec se vuelve trazable, validable y barato.

1. El spec-input.json deriva del grafo, no del repo.

Campo Lo aporta el grafo
affectedFiles El context-pack ya filtró por PageRank → spec apunta a archivos reales
crossDomainDeps El grafo de imports → design.md menciona dependencias correctas
domain Inferencia por mayoría de paths del pack
evidence Referencias trazables a los artefactos JSON validados
purpose Inferencia determinista del nombre del archivo

2. El agente recibe el spec-prompt, NO el repo.

forge spec genera .contextforge/spec-prompt.md con 4 secciones:

1. Contexto del repo (de ContextForge)
   - Tarea, dominio inferido, archivos afectados, cross-domain deps, evidencia
2. Instrucciones canónicas de OpenSpec
   - Lo que devuelve `openspec instructions proposal --change <id> --json`
3. Restricciones para tu salida
   - Token budget, allowed files, formato moderno
4. Output esperado
   - Editar openspec/changes/<id>/{proposal,design,tasks,specs}.md

El agente no abre el repo. Solo lee este prompt + el context-pack si necesita más detalle.

3. El multiplicador escondido — prompt caching.

Claude descuenta 90 % del precio de tokens cacheados. ContextForge mete un boost porque su output es determinista:

  • Mismo forge context → mismo context-pack.json byte-a-byte.
  • Mismo forge spec → mismo spec-prompt.md byte-a-byte.

Entre las iteraciones 2, 3, N del SDD, el agente cachea todo el prompt. Solo paga full por el delta.

4. Ahorro doble medido.

Por iteración SDD:
  Sin ContextForge   217 600 tokens   $0.65
  Con ContextForge    18 988 tokens   $0.057   (-91%)

3 iteraciones de un feature normal:
  Sin caching         3 × $0.65 = $1.96
  Con caching activo  $0.07     (÷28×)

5. Trazabilidad auditable.

Cada path en design.md apunta a un archivo del context-pack.json. Cada commit puede verificarse con forge implement --check contra allowedFiles[] derivado del pack.

6. Subgrafo congelado dentro del change (v0.3.7+).

forge spec <id> ahora también escribe openspec/changes/<id>/graph.subset.json — un subgrafo limitado al context-pack del change + 1 hop por aristas. Eso significa:

  • Las skills/prompts del agente que leen openspec/changes/<id>/ tienen el grafo del momento exacto en que se autorizó el spec, sin necesidad de reabrir .contextforge/graph.json (que pudo haber mutado).
  • design.md incluye una sección "Context graph (subset)" con stats y la referencia al adjunto.
  • Vía MCP: forge_change_subgraph({ change_id: "mi-feature" }) lo devuelve directo, ideal para que un agente lo cargue al inicio de una sesión de implementación.
openspec/changes/mi-feature/
  ├── proposal.md
  ├── design.md           ← incluye tabla con stats del subset
  ├── tasks.md
  ├── specs/<domain>/spec.md
  ├── graph.subset.json   ← subgrafo self-contained · validado por JSON Schema
  └── graph.subset.html   ← viewer interactivo standalone (Cytoscape, sin servidor)

Trazabilidad real: el subgrafo es byte-stable (orden determinista), validado por JSON Schema (docs/schemas/graph-subset.schema.json), y queda commiteado con el resto del change. Si seis meses después el grafo global cambió, puedes comparar este subset con el subgrafo equivalente de hoy y ver el drift.

Tabla — qué aporta cada herramienta:

Aporte ContextForge OpenSpec Agente IA
Ranking de archivos por relevancia
Grafo de dependencias
Token budget + selección por presupuesto
Trazabilidad (cada archivo viene del pack)
Schemas estables (Requirement+Scenario)
Validación estructural (openspec validate)
Templates canónicos por artefacto
Instalación de instrucciones por agente (openspec init)
Redacción de prosa
Decisiones de diseño contextual
Determinismo + cacheabilidad

Documentación generada para agentes (forge init)

forge init genera .contextforge/agent-context.md — un archivo derivado que cualquier agente puede leer al iniciar sesión y entender:

  • Qué artefactos hay disponibles y en qué orden leerlos.
  • Cómo consumirlos (no leer el repo a ciegas).
  • La receta SDD completa (ContextForge ⊕ OpenSpec).
  • Política para agentes (no specs a mano, no bullets, gate pre-commit).
  • Tabla de comandos clave por intención.

Adicionalmente, forge init detecta si openspec CLI está en PATH y, si el directorio openspec/ no existe, ejecuta:

openspec init . --tools=claude,cursor,opencode --force

Eso instala las instrucciones canónicas de OpenSpec para los 3 agentes (las que aparecen en .claude/, .cursor/rules/, opencode.json). Idempotente: si el directorio openspec/ ya existe, salta.


Comandos completos

Comando Qué hace LLM
forge init .contextforge/ + agent-context.md + openspec init (si está) No
forge scan Indexa con BLAKE3 (incremental) No
forge graph [--force] [--with-calls] [--with-refs] [--enrich] [--export=<dot|graphml>] Grafo file/symbol/folder/package con cache por archivo (BLAKE3) No (¹)
forge context "<tarea>" [--no-manifest] [--force] PageRank + BFS + budget · auto-emite manifest No
forge spec <id> [--no-openspec] spec-input.json + handoff/fallback OpenSpec No
forge implement <id> Plan con guardrails derivados del pack No
forge implement --check Valida diff vs guardrails No
forge skills [--force] Auto-genera skills por dominio (contextforge-domain-<slug>.md) No
forge manifest [--agents=...] [--force] Re-genera manifest sin re-rankear No
forge sync [--since X] [--rebuild] Reporta delta desde un ref de git No
forge impact Health check de artefactos + cobertura No
forge viz Visualización HTML interactiva del grafo No
forge docs [--force] Scaffold Diátaxis (tutorials/how-to/reference/explanation/adr/architecture) No

Política: ningún comando llama a un LLM por defecto. Todo es derivable, reproducible, auditable.

(¹) forge graph --enrich es la única excepción opt-in — agrega summary/tags/complexity a símbolos exportados vía Anthropic API. Requiere ANTHROPIC_API_KEY. Sin la flag, el pipeline sigue 100 % determinista.


Servidor MCP

packages/mcp expone 10 tools consumibles por cualquier cliente MCP (Claude Code, OpenCode, etc.).

Tool Propósito
forge_status Estado de los artefactos (frescura, conteos, savings)
forge_domain_map Mapa de dominios + dependencias cruzadas
forge_neighbors Vecinos directos de un archivo en el grafo
forge_context Selección PageRank para una tarea (con o sin contenido)
forge_check Valida git diff contra guardrails del implement-plan
forge_change_subgraph Subgrafo congelado de un OpenSpec change (openspec/changes/<id>/graph.subset.json)
forge_change_context Mapa de lectura del change (openspec/changes/<id>/context.md)
forge_archive_change Cierra un change: openspec archive + rebuild graph padre + refresh subgrafos
select_agent_context Runtime: computa agent-manifest en memoria para una tarea (cache mtime)
get_agent_manifest Offline: lee .contextforge/agent-manifest.json precomputado

Wiring (Docker, recomendado):

{
  "mcpServers": {
    "contextforge": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "-v",
        "${PWD}:/project",
        "-e",
        "PROJECT_ROOT=/project",
        "ghcr.io/alejandro-cedeno-10/contextforge-mcp:latest"
      ]
    }
  }
}

Wiring (npm):

{
  "mcpServers": {
    "contextforge": {
      "command": "node",
      "args": ["./node_modules/@anai-raia-alex/contextforge-mcp/dist/index.js"],
      "env": { "PROJECT_ROOT": "." }
    }
  }
}

Artefactos generados

Todos los JSON validados con JSON Schema 2020-12 antes de escribirse.

.contextforge/
  scan.json                  # archivos con hashes BLAKE3
  graph.json                 # 368 nodos, 267 edges
  context-pack.json          # archivos seleccionados dentro del presupuesto
  token-ledger.json          # métricas auditables del ahorro
  agent-manifest.json        # skills/rules relevantes a la tarea (neutral)
  spec-input.json            # entrada determinista para OpenSpec / agente
  spec-prompt.md             # prompt copy-paste (modo handoff)
  implement-plan.json        # guardrails: allowedFiles, maxLocDelta, etc.
  agent-context.md           # documentación del repo para agentes IA
  graph.html                 # visualización interactiva (Cytoscape.js)
  manifests/opencode-readme.md   # instrucciones MCP para OpenCode

.claude/agent-manifest.md           # manifest renderer Claude Code
.cursor/rules/contextforge-active.mdc  # rule auto-attached por dominios tocados

openspec/changes/<id>/
  proposal.md          # intent, scope, why, alternatives
  design.md            # decisiones técnicas con archivos del grafo
  tasks.md             # T1, T1.1, T2... checklist
  specs/<dominio>/spec.md   # ## ADDED Requirements + ### Requirement: + #### Scenario:

Schemas

Artefacto Schema
scan.json docs/schemas/scan.schema.json
graph.json docs/schemas/graph.schema.json
context-pack.json docs/schemas/context-pack.schema.json
implement-plan.json docs/schemas/implement-plan.schema.json
token-ledger.json docs/schemas/token-ledger.schema.json
agent-manifest.json docs/schemas/agent-manifest.schema.json
spec-input.json docs/schemas/spec-input.schema.json

Métricas reales (este repo, hoy)

Métrica Valor
Tests 270 / 270 verde (26 archivos)
Coverage ≥ 80 % global · módulos manifest/ y spec/ ≥ 95 %
Token savings 94.4 % vs baseline
Compresión 17.9× por sesión · ÷28× SDD con caching
Archivos del repo 128
Archivos en context-pack 50
Tokens del context-pack 11 988
Tokens baseline 214 606
Grafo 368 nodos, 267 edges
Comandos forge 13
Tools MCP 7

Distribución

Canal Identificador
npmjs.com (público, sin token) @anai-raia-alex/contextforge-{core,cli,mcp}
GitHub Container Registry ghcr.io/alejandro-cedeno-10/contextforge-mcp:latest (multi-arch amd64+arm64)
Repo público https://github.com/alejandro-cedeno-10/contextforge-cli

Integración con agentes — matriz

Agente Configuración Selección por tarea Estado
Claude Code .claude/skills/ (3 task-oriented + N auto-generadas) · hook UserPromptSubmit Hook inyecta manifest live + JSON precomputado Listo
Cursor .cursor/rules/contextforge.mdc (alwaysApply) + contextforge-active.mdc (Auto-Attached) Rule por glob regenerada por forge context (Cursor no tiene hooks reactivos) Listo
OpenCode opencode.json con MCP server registrado Tool MCP select_agent_context({task}) live Listo
Codex / otros Leen .contextforge/*.json directamente Lectura directa de agent-manifest.json Compatible

Los .contextforge/*.json son portables. Cualquier agente futuro los puede consumir sin modificación.


Principios

  • Determinismo primero: ningún comando llama a un LLM. Reproducible, auditable, cacheable.
  • OpenSpec por defecto: forge spec delega a OpenSpec CLI cuando está, fallback determinista cuando no.
  • Cache por hash: si scan.json no cambió, forge graph salta el rebuild.
  • Presupuesto explícito: cada context-pack tiene maxInputTokens trazable en token-ledger.json.
  • JSON validado: ningún artefacto se escribe sin pasar JSON Schema.
  • Portable: cualquier agente puede consumir .contextforge/*.json sin modificación.
  • Sin lock-in: si mañana sale otra herramienta SDD, lee los mismos JSON.

Para la exposición — los 5 puntos memorables

  1. 94 % menos tokens por sesión — verificado con token-ledger.json, no estimado.
  2. ÷28× costo SDD con prompt caching — porque el output es determinista byte-a-byte.
  3. No competimos con OpenSpec, lo apoyamos. Tres roles separados (CF / OpenSpec / agente). Si OpenSpec evoluciona, no nos pisamos.
  4. El agente solo carga lo de tu tarea actual — context-pack + manifest. Las 100 skills viejas no entran al contexto.
  5. Sin lock-in. Los .contextforge/*.json son neutrales. Si mañana sale otra herramienta, los puede consumir igual.

Estructura del monorepo

packages/
  core/   → scanner, parser tree-sitter, graph builder, selector PageRank,
            packer, schema validator, skill builder, agent-manifest, spec-input,
            spec promptRenderer
  cli/    → comandos forge (init, scan, graph, context, spec, implement, manifest,
            skills, sync, impact, viz, docs)
  mcp/    → servidor MCP con 7 tools

.claude/skills/    → 3 skills task-oriented (contextforge-*) +
                     N auto-generadas (contextforge-domain-*) +
                     agent-manifest.md (per-task)
.cursor/rules/     → contextforge.mdc (alwaysApply) +
                     contextforge-active.mdc (Auto-Attached, regenerada por tarea)
opencode.json      → configuración MCP para OpenCode
docs/integrations/ → guías de wiring por agente
docs/explanation/  → contextforge-and-openspec.md (lectura clave)

Tests

pnpm test               # todos los tests
pnpm test:coverage      # con cobertura
pnpm typecheck          # tsc -b --force (project references)

Suite actual: 270/270 tests pasando (26 archivos), coverage global ≥ 80 % · módulos manifest/ y spec/ ≥ 95 %.


Documentación

Documento Descripción
docs/explanation/contextforge-and-openspec.md Lectura clave: 3 roles (CF / OpenSpec / agente), ahorro medido, prompt caching ÷28×
docs/how-to/use-contextforge.md Guía paso a paso: instalación, pipeline, integración por agente
docs/integrations/claude-code-hook.md Snippet copy-paste para activar manifest en runtime en Claude Code
docs/integrations/cursor-rules.md Los 3 modos de rules en Cursor + estrategia recomendada
docs/integrations/opencode-mcp.md Ejemplo de select_agent_context desde OpenCode
docs/token-savings-architecture.md Análisis de ahorro de tokens por capas con tabla de costos
docs/EXAMPLES/end-to-end-flow.md Walkthrough completo del pipeline con outputs reales
docs/IMPLEMENTATION_TASKS.md Backlog de sprints con criterios verificables
docs/CHANGELOG-schemas.md Historial de cambios de schemas
openspec/changes/forge-spec-as-prepare-step/ OpenSpec change del re-arquitectura v0.3.0
openspec/changes/agent-manifest/ OpenSpec change del manifest por tarea
openspec/changes/auto-domain-skills/ OpenSpec change de las skills auto-generadas
CONTEXTFORGE_SOURCE_OF_TRUTH.md Decisiones de diseño, arquitectura, roadmap

Licencia

MIT

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured