forja
Lints JavaScript/TypeScript files with ESLint as part of check when the project already ships an ESLint setup.
Checks JavaScript projects with node --check and runs their tests (vitest or node --test) as part of test/gate.
Syntax-checks Lua files with luac -p as part of check.
Checks PHP files with php -l (or a custom command such as phpstan via .forja.toml) and runs phpunit if it is available in vendor/bin.
Runs pytest test suites for Python projects, locating each failure; used by test and by gate as the final quality barrier.
Checks and tests Python projects: syntax/style/type checking with ruff and mypy, test execution with pytest (including coverage), and mutation testing to verify the tests are meaningful.
Runs ruff as the Python linter during check, and applies its safe auto-fixes via fix.
Checks Rust projects with cargo clippy/check and runs cargo test.
Lints sh/bash scripts with the shellcheck bundled inside forja as part of check.
Stores per-project memory in a SQLite database outside the project folder, recording which errors appear, get fixed, or come back, and powering recall summaries and repetido warnings.
Validates the syntax of TOML files in the project, including forja's own .forja.toml configuration file.
Type-checks TypeScript projects with tsc (and ESLint when the project provides it) during check.
Runs Vitest suites as the test runner for JavaScript/TypeScript projects during test and gate.
Validates the syntax of YAML files in the project using forja's internal checker.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@forja run gate on this project and tell me if it truly passes"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
forja
Una IA que programa no necesita ser más lista: necesita poder comprobar lo que hace.
forja es un servidor MCP que se conecta a cualquier IA que programe (Claude Code, opencode, Cline… o un modelo gratuito en tu propio PC) y le da lo que le falta para trabajar en proyectos reales sin perderse: saber qué hay, saber qué está roto, saber si su cambio funciona de verdad y recordar los errores que ya cometió.
Por qué existe
Las IAs que programan fallan siempre en los mismos sitios, y no por falta de inteligencia:
No ven el proyecto entero. Su memoria de trabajo (el contexto) es limitada, y la gastan orientándose: leen el README completo, listan carpetas, abren archivos enteros para encontrar una función.
Dicen "listo, funciona" sin haberlo comprobado. Es el fallo más caro: te enteras tú, después.
Repiten errores que ya arreglaron, porque entre una sesión y otra no recuerdan nada.
Se fían de tests que no prueban nada: todo verde no significa que esté bien.
Con modelos pequeños y gratuitos todo esto se multiplica: menos contexto y más torpeza usando herramientas.
Las herramientas para comprobar código ya existen (compiladores, linters, tests, verificadores como Dafny o Lean), pero cada una habla su propio idioma y todas están pensadas para que las lea una persona.
Related MCP server: projectmind
Para qué sirve
forja es el traductor entre esas herramientas y la IA. Le responde, en pocas palabras y siempre con el mismo formato, sea cual sea el lenguaje:
¿Qué hay en este proyecto? — un mapa de una sola llamada, en vez de leer documentación.
¿Qué está roto exactamente? — archivo, línea, el código afectado y qué hacer a continuación.
¿Mi cambio funciona de verdad? —
oksolo si todo se comprobó; nunca un éxito inventado.¿Ya me equivoqué en esto antes? — una memoria por proyecto que se llena sola.
¿Es correcto o solo lo parece? — con Dafny y Lean, demostrado matemáticamente.
Cómo funciona
tú: "el reporte no funciona, arréglalo"
│
▼
┌──────────────────┐ MCP ┌──────────┐ php -l, pytest, cargo, go,
│ tu IA │ ──────► │ forja │ ─► shellcheck, dafny, lean…
│ (cualquiera) │ ◄────── │ │
└──────────────────┘ └────┬─────┘
▲ "corrige datos.php:12 │
│ (falta ;) y vuelve ▼
│ a llamar a gate" memoria del proyecto
└───────────────────── (errores, repetidos, lecciones)El ciclo de trabajo de la IA con forja:
overview→ entiende el proyecto sin leer archivos enteros.recall→ mira qué errores se repiten en este proyecto.outline→ encuentra la función y lee solo esas líneas.edita y llama a
gate→ si algo falla, la respuesta dice exactamente qué y dónde, y su camponextdice qué hacer.repite hasta que
gatedigaok. Solo entonces la tarea está terminada.
El compilador de IA: Dafny y Lean
Un compilador convierte código en un programa y se puede confiar en él porque es determinista. Una IA no lo es: la misma petición puede dar código distinto, y a veces con errores. La verificación formal resuelve eso:
el humano escribe qué debe cumplirse (
requires/ensuresen Dafny, el enunciado de untheoremen Lean) — unas pocas líneas fáciles de revisar;la IA escribe el cómo;
el verificador demuestra que el código lo cumple. Si no, no pasa.
Así no hace falta fiarse de la IA. forja vigila además las dos trampas que lo invalidarían:
demostrar a medias (
sorry,admit,axiomen Lean;assume,{:axiom},{:verify false}en Dafny) → es un error, nunca un éxito;debilitar la especificación para que sea fácil de cumplir → el humano la bloquea con
forja-spec locky cualquier cambio posterior es un error. El bloqueo no se puede hacer desde MCP: la IA no puede desbloquearse sola.
Principios
Funciona con cualquier cliente MCP y cualquier modelo · cada carácter que recibe la IA cuenta ·
nunca un falso éxito · no necesita internet ni sudo · no toca el código del proyecto salvo con
fix, cuando se pide.
No es un linter, ni una IA, ni un IDE: no sustituye a ninguna herramienta, las traduce.
Herramientas
Herramienta | Para qué |
| Mapa del proyecto en una llamada: lenguajes, carpetas, cómo se comprueba, puntos de entrada, índice de la documentación (solo títulos) y git. En vez de leer README y listar carpetas |
| Funciones y clases de un archivo o carpeta con su rango de líneas, para leer solo ese trozo |
| Sintaxis, tipos y lint de todos los lenguajes del proyecto, sin ejecutarlo |
| Aplica las correcciones seguras y dice qué tocó |
| Ejecuta los tests de todos los lenguajes y localiza cada fallo |
|
|
| ¿Los tests sirven? Mete bugs pequeños en copias y mira si los detectan (Python) |
| Memoria del proyecto: errores que se repiten, abiertos, patrones, recientes, lecciones |
| Guarda una lección; aparecerá sola junto a ese error si vuelve |
Cada respuesta trae next: el siguiente paso en una frase, para que un modelo pequeño no tenga que deducirlo.
Lenguajes
Lenguaje | check | test |
Python | ruff + mypy | pytest (+ coverage, mutate) |
JavaScript / TypeScript |
| vitest, |
Rust | cargo clippy / check | cargo test |
Go | go vet | go test |
PHP |
| phpunit si está en |
Shell (sh/bash) | shellcheck (incluido en forja) | — |
fish |
| — |
Lua |
| — |
JSON / YAML / TOML | interno | — |
Dafny |
| — (verificar es más fuerte que probar) |
Lean 4 |
| — |
Cualquier otro |
|
|
Un proyecto con varios lenguajes se revisa entero. Para una herramienta que forja no conoce:
# .forja.toml
[[check]]
name = "phpstan"
cmd = ["vendor/bin/phpstan", "analyse", "--error-format=raw", "--no-progress"] # salida archivo:línea: mensaje
[[test]]
name = "phpunit"
cmd = ["vendor/bin/phpunit", "--log-junit", "{junit}"] # {junit}: forja lee ese XML
[forja]
disable = ["data"] # opcionalMemoria por proyecto
Cada check, test, gate y edición vista por el hook se guarda sola en una base SQLite por
proyecto (~/.local/share/forja/), fuera de la carpeta del proyecto. forja anota qué errores
aparecen, cuáles se arreglan y cuáles vuelven después de arreglados. recall devuelve un
resumen corto y ordenado por importancia (repetidos → críticos → patrones → recientes →
lecciones), y un error que la IA repite llega con memory: "repetido: ya lo arreglaste…". Si una
herramienta no llegó a ejecutarse, nada se da por resuelto.
Cómo ahorra contexto
overview/outline: medido en proyectos reales, −84 % a −92 % frente a leer los.mdy listar archivos, y −98 % frente a leer un script entero para encontrar una función.Forma compacta: sin campos vacíos; un
checklimpio es{"ok": true, "next": ...}.source: cada error trae su línea de código.Duplicados agrupados (ruff + mypy, tests con la misma causa) y trazas limpias.
Historial: en llamadas repetidas lo ya visto llega resumido (
full=truepara todo).
Reglas que nunca se rompen
Una herramienta que no pudo ejecutarse aparece con
ran: falsey el resultado nunca esok: true: un paso sin comprobar no cuenta como éxito.Un proyecto sin tests no pasa
test: "no hay tests" no es "los tests pasan".forja no escribe en el proyecto (cachés en
~/.cache/forja-mcp, memoria en~/.local/share/forja), salvofix, que lo pide explícitamente.mutatetrabaja en copias temporales y se niega a empezar si los tests no pasan sin mutar.
Instalación
Con Docker (recomendado: no instala nada en tu máquina)
La imagen trae todas las herramientas: Python, PHP, Lua, fish, Node, Go, Rust, Dafny y Lean.
git clone https://github.com/Asced1807/forja-mcp && cd forja-mcp
docker build -t forja-mcp .Como servidor MCP, el proyecto se monta en la misma ruta para que las rutas coincidan, y la memoria en una carpeta tuya para que no se pierda entre sesiones:
docker run -i --rm --user "$(id -u):$(id -g)" -v "$PWD:$PWD" -w "$PWD" \
-v "$HOME/.local/share/forja:/data" forja-mcpPara desarrollar forja sin instalar nada (los tests de Dafny y Lean incluidos):
docker run --rm --user "$(id -u):$(id -g)" -v "$PWD:/work" -w /work -e PYTHONPATH=/work/src \
-e PYTHONDONTWRITEBYTECODE=1 --entrypoint python forja-mcp -m pytestSin Docker
Requisitos: Python 3.12+ y uv. Las herramientas de cada lenguaje (php, cargo, go, node…) se usan si están instaladas; shellcheck, ruff y mypy vienen incluidas.
git clone <este repo> forja-mcp && cd forja-mcp
uv sync
uv run pytest # comprueba que todo funciona en tu máquinaEl servidor es <ruta>/forja-mcp/.venv/bin/forja-mcp (MCP por stdio).
Claude Code
claude mcp add --scope user forja -- <ruta>/forja-mcp/.venv/bin/forja-mcpHook opcional que revisa cada archivo editado (en .claude/settings.json del proyecto):
{"hooks": {"PostToolUse": [{"matcher": "Edit|Write|MultiEdit",
"hooks": [{"type": "command", "command": "<ruta>/forja-mcp/.venv/bin/forja-hook", "timeout": 90}]}]}}opencode
En ~/.config/opencode/opencode.jsonc:
"mcp": {
"forja": { "type": "local", "command": ["<ruta>/forja-mcp/.venv/bin/forja-mcp"], "enabled": true }
}Estructura
src/forja_mcp/
server.py servidor MCP y campo `next`
model.py formato único, forma compacta y combinación de lenguajes
memoria.py memoria SQLite por proyecto
mapa.py overview y outline
files.py archivos del proyecto (respeta .gitignore)
parsers.py lectores compartidos (formato gcc)
junit.py lector de JUnit XML
history.py comparación con la llamada anterior
runner.py ejecución de comandos con tiempo límite
hook.py hook PostToolUse
adapters/
base.py clase base y revisión archivo por archivo
python.py, python_mutation.py
scripting.py PHP, Lua, JavaScript/TypeScript
compiled.py Rust, Go
shell.py sh/bash, fish
data.py JSON, YAML, TOML
custom.py .forja.tomlAñadir un lenguaje
Una clase que herede de BaseAdapter con name, extensions y check; test, fix y
mutate son opcionales (por defecto "no aplica"). Regístrala en ADAPTERS
(adapters/__init__.py). per_file y parse_gcc resuelven la mayoría de los casos en
pocas líneas, y junit_run cualquier runner de tests que escriba JUnit XML.
Licencia
Copyright (C) 2026 Asced1807
forja-mcp es software libre bajo la licencia BSD de 3 cláusulas (BSD-3-Clause).
En resumen: cualquiera puede usarlo, modificarlo y redistribuirlo, también dentro de proyectos cerrados o comerciales, siempre que mantenga este aviso de copyright y el texto de la licencia. Lo que no puede es usar el nombre del autor para promocionar sus derivados sin permiso. Las contribuciones son bienvenidas.
Available Tools
9 toolscheckA
Comprueba el proyecto sin ejecutarlo: sintaxis, tipos y lint de TODOS sus lenguajes.
Args:
path: ruta absoluta al proyecto o a cualquier archivo dentro de él.
timeout: segundos máximos por herramienta.
full: true para recibir todos los campos, incluido el detalle de lo ya visto.
Inputs: path (required), full, timeout. Returns: object
fixC
Aplica las correcciones automáticas SEGURAS y vuelve a comprobar.
Modifica archivos: `fixed` dice qué se corrigió y dónde.
Inputs: path (required), timeout. Returns: object
gateA
check + test en una llamada: la puerta final. ok solo si TODO pasa.
Args:
path: ruta absoluta al proyecto o a cualquier archivo dentro de él.
coverage: true para incluir las líneas sin cubrir por los tests.
timeout: segundos máximos por fase.
Inputs: path (required), timeout, coverage. Returns: object
learnA
Guarda una lección del proyecto para no repetir un error (p. ej. "usar Decimal, nunca float, para dinero"). Aparecerá sola junto a ese error si vuelve a ocurrir.
Args:
path: ruta absoluta al proyecto.
lesson: la lección, en una frase.
about: opcional, a qué se aplica: código de error (F821), archivo o nombre de test.
Inputs: path (required), lesson (required), about. Returns: object
mutateA
¿Los tests son buenos? Mete bugs pequeños en COPIAS del código y mira si los tests los detectan. Cada superviviente es algo que ningún test comprueba (algunos son equivalentes: júzgalos). Hoy solo para Python.
Args:
path: ruta absoluta al proyecto.
file: opcional, solo muta este archivo (ruta relativa al proyecto).
max_mutants: máximo de mutaciones a probar.
timeout: segundos máximos en total.
Inputs: path (required), file, timeout, max_mutants. Returns: object
outlineB
Funciones y clases de un archivo, o de todos los de una carpeta, con su rango de líneas (p. ej. "L12-40 def calcular(x) -> int"). Lee después solo ese rango, no el archivo entero.
Args:
path: ruta absoluta a un archivo o carpeta del proyecto.
Inputs: path (required). Returns: object
overviewA
Mapa del proyecto en una llamada: lenguajes, carpetas, cómo se comprueba, puntos de entrada, índice de la documentación (solo títulos con su línea) y estado de git. Úsalo al empezar en vez de leer README o listar carpetas.
Args:
path: ruta absoluta al proyecto o a cualquier archivo dentro de él.
Inputs: path (required). Returns: object
recallA
Memoria del proyecto, ordenada por importancia: errores que se repiten, errores abiertos, patrones (el mismo tipo de error en varios sitios), lo resuelto hace poco y las lecciones guardadas. Se llena sola con cada check/test. Úsalo antes de cambiar código en un proyecto en el que ya trabajaste.
Args:
path: ruta absoluta al proyecto.
topic: opcional, filtra por archivo, código de error o texto (p. ej. "cli.py").
Inputs: path (required), topic. Returns: object
testB
Ejecuta los tests de todos los lenguajes del proyecto y localiza cada fallo.
Args:
path: ruta absoluta al proyecto o a cualquier archivo dentro de él.
selector: opcional, limita a un archivo o test concreto.
coverage: true para ver qué líneas no ejecuta ningún test (Python).
timeout: segundos máximos.
full: true para recibir todos los campos, incluido el detalle de lo ya visto.
Inputs: path (required), full, timeout, coverage, +1 more. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 9 tools
Each tool has a fairly distinct role: learn/recall handle memory (write vs read), check/test/gate handle verification, and fix/mutate/overview/outline are clearly separate operations. The main risk is check vs gate (gate is explicitly 'check + test in one call') and overview vs outline, but the descriptions clarify the boundaries well.
All nine tools use a single lowercase word with no style mixing, which is highly consistent. It is not a verb_noun pattern and mixes verbs (learn, fix, test, mutate, recall, check) with nouns (overview, outline, gate), but the stylistic convention is uniform and readable.
Nine tools is well-scoped for a code QA/testing server, with each tool covering a distinct aspect (memory, static check, tests, combined gate, mutation testing, safe fixes, project mapping, file outline). No obvious redundancy or padding.
The surface covers a solid lifecycle: explore (overview/outline), verify (check/test/gate), improve (fix), assess test quality (mutate), and accumulate knowledge (learn/recall). Minor gaps exist, such as no way to remove/update a stored lesson, but core workflows are covered.
Maintenance
Related MCP Connectors
Give your AI agent a persistent map of your project's structure, dependencies, and bugs.
Project memory, documentation and controlled secret access for AI coding agents.
Shared memory for coding agents. Stop re-explaining your codebase every session.
Project memory for coding agents: requirements, decisions, code graph and delivery telemetry.
Related MCP Servers
- AlicenseCqualityCmaintenanceLocal-first error memory for AI coding agents, enabling them to search past fixes before attempting new repairs and save verified cases as Markdown.3MIT
- AlicenseNot gradedqualityCmaintenancePersistent, compact project memory for AI coding agents, enabling them to read a small digest instead of re-scanning the codebase every session, saving tokens and costs.49 npm2MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to carry durable project memory across windows, agents, and days, injecting a compressed context of architecture, progress, decisions, and critical files so a new session can resume without re-reading the whole repository. It also classifies files as current/legacy/intermediate and suggests cleanup so stale or draft artifacts don't mislead the agent.8 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables AI coding agents to query a local structural code graph for focused context, inspect relationships and impact, and carry recorded mistakes into later sessions.28 npmMIT