CLI_Revit
Token-efficient MCP harness for Revit/BIM automation — search+run over 160+ scripts instead of exposing tools individually.
Documentation
CLI Revit / Sin Tool
Repo minimo para operar Revit con la menor intermediacion posible entre el LLM y la API.
Que es este repo
CLI_Revit es un harness local de automatizacion para Revit.
Mas concreto:
- conecta un agente o LLM con un modelo abierto en Revit
- permite descubrir, parametrizar y ejecutar scripts BIM reutilizables
- expone una superficie shell-first por
revit_cli.pyy una superficie MCP pormcp_server.py - mantiene una capa minima de intermediacion entre el agente y la API de Revit
No es solo un plugin, ni solo una libreria, ni solo un servidor MCP. El MCP es una interfaz de acceso mas; el nucleo del repo es el harness de ejecucion y automatizacion sobre Revit.
Quickstart
Requisitos minimos:
- Revit 2023/2024/2025 instalado (para
RevitAPI.dll/RevitAPIUI.dll) - .NET SDK o Visual Studio 2022/Build Tools + .NET Framework 4.8 targeting pack
- Python 3.8+ x64
pip install websocket-client mcp
Pasos:
# 1. compilar e instalar el plugin de Revit (detecta version instalada)
cd plugin
build_all_versions.bat
cd ..
# 2. abrir Revit con un documento activo
# el plugin RevitAgent levanta el servidor WebSocket solo, en ws://localhost:18789
# 3. verificar conexion
python revit_cli.py doctor
python revit_cli.py ping
# 4. primer comando real
python revit_cli.py search "muros"
python revit_cli.py show get_elementos
python revit_cli.py run get_resumen_modelo --params-json "{\"detalle\":\"minimo\"}"
Si ping responde DOWN: Revit no esta abierto, el .addin no quedo instalado, o falta configurar PYTHONNET_PYDLL — detalle completo en plugin/README.md.
Para usarlo desde un agente en vez de la shell (Claude Code, OpenCode, o cualquier cliente MCP): el repo ya trae .mcp.json y mcp_server.py listos, ver seccion "Uso desde Claude Code" mas abajo.
Harness vertical, no generico
Mismo patron que un harness generico (Claude Code, OpenCode, dsh): loop de agente + intermediacion minima entre decision y ejecucion + feedback estructurado para verificar. La diferencia es el alcance:
- un harness generico decide su dominio por prompt/contexto
- este harness tiene el dominio hardcodeado en el protocolo: catalogo de scripts, convencion
get_/crear_/modificar_, contratoRESULTADO: OK|WARN|ERROR
Por eso se expone via MCP y no como plugin nativo de cada harness general: el harness vertical se mantiene una sola vez en este repo, y cualquier harness general lo consume como cliente MCP sin reescritura.
Mapa rapido
docs/INICIO_BIM.md: puerta de entrada para una sesion de modelado BIM del agenteREADME.md: guia del repo y estado actual de desarrollodocs/DESARROLLO_REPO.md: guia para continuar el repo por capacidades BIM, no por acumulacion de scriptsdocs/CAPACIDADES_BIM.md: matriz corta de capacidades cubiertas, parciales, ausentes y prioridades activasdocs/SCRIPTS_BASE.md: nucleo operativo del repo y reglas para tocar scripts basehints.md: libreta operativa corta y corregibleCONTRIBUTING.md: criterio de aceptacion de PRs y convenciones de scriptsLICENSE/NOTICE/AUTHORS: licencia Apache-2.0 y creditosrevit_cli.py: entrypoint shell-first para buscar y correr scriptsrevit_client.py: cliente WebSocket minimo para ejecutar Python rawplugin/: add-in C# local de Revit (RevitAgentPlugin) para compilar e instalar el servidor WebSocket
Criterio de diseno
La regla central de este repo es simple:
- cada tarea BIM debe consumir la menor cantidad de tokens posible para llegar a una respuesta buena
- los tokens deben ir a leer estado real del modelo, decidir y verificar
- no deben ir a contexto inflado, routing local, wrappers redundantes o documentacion larga
En la practica eso significa:
- cliente a Revit chico y obvio
- scripts explicitos y reutilizables
- hints cortos en vez de una capa de tools
- pocas piezas base, no catalogos grandes de variantes
Formula de trabajo:
leer poco -> decidir bien -> mutar chico -> verificar -> guardar solo la regla util
Guia de uso
En una sesion nueva:
- leer
docs/INICIO_BIM.md - leer
hints.md - correr
python revit_cli.py doctor - ir a
README.mdsolo si hace falta contexto del repo o decisiones de arquitectura - hacer una lectura minima real del modelo antes de mutar
Reglas de trabajo:
- si ya existe un script util, buscarlo y correrlo con
PARAMS - si el pedido es una variante chica, ajustar el script existente antes de crear otro
- crear un script nuevo solo cuando abre una capacidad reutilizable de verdad
- no guardar un script nuevo para una decision puntual de modelado
- si el pedido admite varias soluciones BIM razonables y el criterio no esta dicho, consultar antes de fijar una variante permanente
Uso rapido
La idea de revit_cli.py no es reemplazar al LLM sino evitar que tenga que reescribir Python completo para cada consulta.
Ejemplos:
python revit_cli.py doctor
python revit_cli.py ping
python revit_cli.py search "resumen del modelo"
python revit_cli.py show get_elementos
python revit_cli.py run get_resumen_modelo --params-json "{\"detalle\":\"minimo\"}"
python revit_cli.py run crear_muros --params-json "{\"segmentos_m\":[[[0,0],[5,0]]],\"nivel_inicial\":\"Nivel 1\",\"altura_default_m\":3.0}"
Launcher local unico para Codex
Si vas a usar Codex con modelo local desde este repo, el entrypoint pasa a ser:
.\codex-local.ps1 -Model qwen
.\codex-local.ps1 -Model gemma
Launchers equivalentes para otros CLIs locales:
.\hermes-local.ps1 -Model qwen
.\opencode-local.ps1 -Model qwen
Nota:
hermes-local.ps1exige contexto minimo de65536;qwen3-coder-30b-q4ygemma4-26b-a4b-q4kmquedan configurados para ese objetivo en los launchers locales.
Reglas del launcher:
- vive en
CLI_Revit, no depende deproj-agent-local - resuelve los GGUF en
C:\Users\fmg\local_models - resuelve
llama-server.exeenC:\Users\fmg\local_models\llama.cpp\llama-server.exe - si hace falta, permite override por
PROJ_AGENT_MODEL_PATH,PROJ_AGENT_LLAMA_SERVER_EXEo.codex/local-model-paths.json
Para elegir un perfil exacto sin usar alias:
.\codex-local.ps1 -Profile qwen3-coder-30b-q4
.\codex-local.ps1 -Profile gemma4-26b-a4b-q4km
Uso desde Claude Code
Ahora el repo tambien incluye un servidor MCP local para que Claude pueda usar los scripts existentes sin salir del flujo normal del proyecto.
Archivos:
mcp_server.py: servidor MCP sobre stdio que reutilizarevit_cli.pyyrevit_client.py.mcp.json: configuracion de proyecto para Claude Code.claude/settings.json: permisos preaprobados solo para herramientas seguras de descubrimiento y consulta
Flujo minimo:
- tener Revit abierto con el plugin
RevitAgentlevantado - abrir este repo desde Claude Code
- aprobar el servidor
revit-agentcuando Claude detecte.mcp.json - usar herramientas MCP como
search_scripts,show_scriptyrun_script
Notas cortas:
- el catalogo completo de
scripts/queda oculto detras desearch_scripts,show_scriptyrun_script - las tools MCP aceptan
timeoutymax_output_bytes; si una salida supera el limite, el plugin devuelve preview y guarda la salida completa en.revit_cli/artifacts - el plugin acepta requests paralelas desde CLI/MCP/WebSocket, pero las ejecuta en cola FIFO dentro del hilo principal de Revit
- el server carga el catalogo al iniciar; si agregas scripts nuevos, reinicia Claude o vuelve a cargar el servidor
- los tools de mutacion no quedaron preautorizados en
.claude/settings.json; la idea es mantener permisos conservadores sobre el modelo run_scriptejecuta cualquier script por nombre o ruta relativa sin inflar el catalogo visible de tools
Flujo operativo
Arquitectura minima:
LLM / cliente
-> revit_cli.py o revit_client.py
-> ws://localhost:18789
-> plugin RevitAgent (C# + Python.NET)
-> Autodesk.Revit.DB
revit_cli.py es la puerta de entrada normal.
revit_client.py sirve para ejecutar Python raw cuando hace falta control total o para prototipar una pieza nueva antes de volverla script reusable.
El transporte WebSocket es compatible con uso concurrente: varios clientes pueden enviar requests a la vez. Revit sigue siendo single-threaded, por lo que el plugin las encola en FIFO y las ejecuta secuencialmente en ExternalEvent. Las respuestas incluyen diagnostics con tiempos de cola/ejecucion y bytes de salida.
Archivos principales
revit_client.py: cliente WebSocket minimo hacia Revitrevit_cli.py: buscador/runner minimo para reutilizar scripts existentesdocs/DESARROLLO_REPO.md: criterio de roadmap y foco del repodocs/CAPACIDADES_BIM.md: matriz accionable de capacidades BIM y prioridadesdocs/SCRIPTS_BASE.md: lista de scripts base y criterio de cuidado del nucleoplugin/: codigo fuente, build e instalacion del plugin local de Revithints.md: libreta operativa corta y corregible.revit_cli/: estado local minimo entre sesiones (last_run.json+history.jsonl)scripts/consulta: lecturas del modeloscripts/creacion: acciones de modeladoscripts/modificacion: ajustes sobre elementos existentes, tags y cambios de documentacion en vistasscripts/reportes: salidas tecnicas persistentes y exportaciones
Regla de nombres
El nombre del script debe reflejar su contrato operativo real, no solo la intencion de negocio.
get_*: lectura del modelo, sin mutacion ni artefacto persistentecrear_*: crea elementos nuevos en el modelomodificar_*o verbo de cambio (mover_*,aplicar_*,etiquetar_*,reubicar_*): muta elementos o vistas existentesexportar_*: genera salida externa persistente (PDF, imagen, etc.)generar_reporte_*/generar_memoria_*: genera documento tecnico persistente
Si un script mezcla dos contratos, debe partirse o quedar claramente sesgado hacia uno y exponer alias de compatibilidad.
Plugin local
Este repo ya incluye el plugin necesario para que el runtime sea autosuficiente:
- codigo fuente en
plugin/ - proyecto .NET en
plugin/RevitAgentPlugin.csproj - build local en
plugin/build.bat - build multi-version en
plugin/build_all_versions.bat - documentacion operativa en
plugin/README.md
Flujo minimo:
cd plugin
build_all_versions.bat
Si solo necesitas una instalacion puntual y build.bat detecta bien tu version de Revit:
cd plugin
build.bat
Notas cortas:
- el plugin instala el servidor en
ws://localhost:18789 editar_boceto_muro.pypuede aprovecharRevitEditScopeHelpersdel assembly del plugin- el detalle de requisitos (
dotnet,net48,PYTHONNET_PYDLL, Addins por version) vive enplugin/README.md
Protocolo raw
Request:
{
"action": "execute",
"script": "codigo python aqui",
"timeout_s": 60,
"request_id": "opcional",
"max_output_bytes": 262144,
"artifact_dir": "C:\\Users\\fmg\\Desktop\\CLI_Revit\\.revit_cli\\artifacts"
}
timeout_s, request_id, max_output_bytes y artifact_dir son opcionales. max_output_bytes usa 256 KB por defecto; si se supera, result/traceback contiene una preview y la salida completa queda como artefacto local.
Response OK:
{
"status": "ok",
"request_id": "opcional",
"result": "stdout capturado o OK",
"artifacts": [],
"diagnostics": {
"elapsed_ms": 12,
"queue_wait_ms": 2,
"execution_ms": 5,
"output_truncated": false
}
}
Response Error:
{ "status": "error", "error": "mensaje", "traceback": "stacktrace" }
Variables disponibles en cada script:
doc:Autodesk.Revit.DB.Documentuidoc:Autodesk.Revit.UI.UIDocumentapp:Autodesk.Revit.ApplicationServices.Application
Reglas del entorno
- devolver resultados con
print(), no por ultima expresion - no usar
with Transaction(...); abrir y cerrar la transaccion manualmente - Revit trabaja en pies decimales; convertir unidades de forma explicita
- si una API pide
IList<T>, usarList[T]de .NET, nolistde Python FamilySymbol.Activate()debe ocurrir dentro de unaTransactionToElements()conviene envolverlo conlist()antes de usar slicing
Contrato de salida minima
Para no inflar contexto, la salida de los scripts debe pensarse para decision operativa, no para narracion.
python revit_cli.py run ...ahora usa--output-mode autopor default: si detecta*_JSON=o stdout largo, compacta la respuesta.- si necesitas ver todo el stdout, usar
python revit_cli.py run ... --output-mode raw - emitir siempre una linea de estado corta:
RESULTADO: OK|WARN|ERRORoRESULTADO=ok - emitir metricas clave en mayusculas:
TOTAL_VISTAS,COUNT_FILTRADAS,ELEMENT_IDS, etc. - si hace falta detalle estructurado, emitirlo en una sola linea
NOMBRE_JSON=... - limitar detalle humano con
max_detalle; el detalle completo debe quedar opt-in, no por defecto
Regla practica:
1 linea de estado
+ 3 a 8 metricas utiles
+ 0 o mas payloads *_JSON compactables
+ tablas o detalle solo si cambian una decision
Patron de transaccion:
from Autodesk.Revit.DB import Transaction
txn = Transaction(doc, "Operacion")
txn.Start()
try:
# cambios
txn.Commit()
except Exception:
txn.RollBack()
raise
Conversiones
- metros -> pies:
valor_m * 3.28084 - pies -> metros:
valor_ft * 0.3048
Verificar conexion
from revit_client import ping
print("Conectado:", ping())
Que no queremos reconstruir
tool_catalog.pyprepare-request- routing interno
- RAG o memoria automatica compleja
- un agente de preferencia
- documentacion grande dificil de corregir
Estado del repo
Estado actual:
- el flujo shell-first ya existe y funciona desde
revit_cli.py doctorvalida conexion, metadata minima y smoke tests de busquedarundeja un rastro local chico en.revit_cli/para retomar entre sesiones sin inflar el repo- el plugin de Revit ya vive dentro de este repo y puede compilarse desde
plugin/ - hay una base amplia de scripts reutilizables en
scripts/consulta,scripts/creacion,scripts/modificacionyscripts/reportes hints.mdya cumple el rol de memoria operativa corta- la nueva separacion documental deja un punto de entrada BIM (
docs/INICIO_BIM.md) y esteREADMEcomo guia viva del repo
Pendiente o criterio vigente:
- seguir consolidando scripts base en lugar de sumar variantes pequenas
- verificar en uso real que los scripts mas frecuentes sigan siendo confiables
- documentar solo lo que cambie decisiones operativas o de arquitectura
- mantener este repo chico, legible y facil de corregir
Como guardar aprendizaje
.revit_cli/last_run.jsony.revit_cli/history.jsonlpara rastro local minimo de ejecucioneshints.mdpara reglas cortas de alto valorREADME.mdpara decisiones de arquitectura, guia y estado del repo
Si algo no entra en 1 o 2 bullets, probablemente no es un hint.
Si un dato solo sirve para recuperar una corrida reciente, probablemente va a .revit_cli/, no a hints.md.
Cierre
Este repo no busca que el LLM "sepa mucho" antes de actuar.
Busca que pueda:
- leer solo lo necesario
- elegir una plantilla simple
- ejecutar contra el modelo real
- verificar
- y seguir con el menor costo de tokens por tarea