Python Code Validator
Comprueba que el Python generado por IA hace lo que pediste: expresa la intención como afirmaciones y el servidor ejecuta el código en un contenedor aislado, devolviendo una corrección solo cuando todos los ejemplos pasan.
Documentación
Validador de Código Python
Un servicio alojado que demuestra que el Python generado por IA hace lo que pediste. Indica la intención (aserciones o líneas de doctest) y el código se ejecuta contra ella dentro de un contenedor sin red y con sistema de archivos de solo lectura; una corrección llega solo cuando cada ejemplo pasa. En los defectos de QuixBugs, eso es 41% reparado y 77% rechazado por no hacer lo que dicen, sin falsas alarmas en los programas corregidos — donde ruff y mypy marcan el defecto en ninguno de ellos (los números).
Las comprobaciones que no necesitan intención vienen incluidas: diagnósticos de sintaxis y lint, una política de seguridad AST que también detecta llamadas ocultas tras importaciones dinámicas y búsquedas de atributos en tiempo de ejecución, una pasada de bandit, un escaneo de credenciales y reparación determinista — un veredicto con una puntuación. Preguntar lo mismo dos veces en diez minutos se responde desde la primera respuesta y no cuesta nada (x-msvc-repeat: 1).
Este repositorio contiene el lado del cliente: la configuración de MCP, el script de CI y el hook de pre-commit. El servicio en sí se ejecuta en https://api.statemind.ai, por lo que no hay nada que instalar u alojar.
Una clave, sin cuenta
curl -s -X POST https://api.statemind.ai/v1/keys
# {"api_key": "msvc_free_…", "tier": "free", "calls_per_day": 25, "modes": ["static"]}
25 comprobaciones estáticas al día, medidas por día UTC, y unas pocas claves por dirección: suficiente para probarlo y ejecutarlo sobre un proyecto pequeño, no un suministro. Cada respuesta lleva el estado del límite (x-quota-remaining, x-quota-reset), para que un cliente pueda retroceder antes de que se le corte.
MCP
Registrado en el registro oficial de MCP como ai.statemind/python-code-validator, un nombre verificado contra el dominio que lo sirve en lugar de una cuenta de GitHub. Cualquier cliente MCP lo añade con un bloque:
{
"mcpServers": {
"python-code-validator": {
"type": "http",
"url": "https://api.statemind.ai/mcp",
"headers": { "Authorization": "Bearer msvc_free_…" }
}
}
}
- Claude Code:
claude mcp add --transport http python-code-validator https://api.statemind.ai/mcp --header "Authorization: Bearer msvc_free_…" - Cursor:
~/.cursor/mcp.json, mismo bloque. - VS Code / Copilot:
.vscode/mcp.jsonbajo"servers".
Un cliente que solo lanza un comando usa el puente stdio de este repositorio en su lugar, que reenvía la misma herramienta por HTTPS:
{
"mcpServers": {
"python-code-validator": {
"command": "python3",
"args": ["/path/to/python-code-validator/mcp_stdio.py"]
}
}
}
O como contenedor, que el Dockerfile aquí construye:
docker build -t python-code-validator .
docker run -i --rm -e VALIDATOR_API_KEY python-code-validator
Gemini CLI instala el mismo puente como extensión, con el archivo de instrucciones que hace que se use:
gemini extensions install jkanselaar/python-code-validator
Tres herramientas, nombradas según lo que hacen con el código:
| herramienta | ejecuta el código | clave |
|---|---|---|
validate_python | no | gratis |
repair_python — también devuelve fixed_code | no | de pago |
execute_python — también lo ejecuta en un sandbox | sí | de pago |
La antigua herramienta única python_code_validator, con su argumento mode, todavía responde para clientes que ya la configuraron, pero ya no aparece en la lista.
Diciendo lo que se suponía que el código debía hacer
Cada comprobación anterior pasa en una función que calcula la respuesta incorrecta. Lo único que lo detecta es la intención, y el agente que pidió el código es el único que la tiene — así que pásala:
{"code": "def bitcount(n): …", "mode": "execute",
"options": {"examples": "assert bitcount(127) == 7"}}
Las líneas de doctest (>>> bitcount(127) luego 7) funcionan igual, al igual que los ejemplos >>> ya escritos en el código fuente. execute_python los ejecuta en el sandbox: uno que no se cumple es un error python:example-mismatch, y la búsqueda de reparación devuelve una corrección solo cuando cada ejemplo pasa. En el conjunto de defectos de QuixBugs — errores reales, entradas de prueba ocultas que deciden la corrección — eso repara el 41% y rechaza el 77% por no hacer lo que dicen, sin falsas alarmas en los programas corregidos.
Repetir una llamada no cuesta nada: la misma clave preguntando lo mismo — mismo modo, mismo código, mismos ejemplos — se responde desde la respuesta que ya obtuvo, marcada x-msvc-repeat: 1, para que un agente que verifica su trabajo en cada paso no se le cobre por veredictos que no pueden haber cambiado.
Haciendo que el agente lo use
Configurar el servidor no es lo que hace que se llame: el archivo de instrucciones lo es. AGENTS.md en este repositorio es ese texto, escrito para colocarse en cualquier proyecto bajo el nombre que el cliente lea:
mkdir -p .github
curl -sf https://raw.githubusercontent.com/jkanselaar/python-code-validator/main/AGENTS.md \
| tee AGENTS.md CLAUDE.md GEMINI.md .github/copilot-instructions.md >/dev/null
Cursor lee reglas con front matter en su lugar, así que esa es un archivo separado — copia .cursor/rules/python-code-validator.mdc en .cursor/rules/ del proyecto.
La versión corta, si prefieres añadir una línea a las instrucciones que ya tienes:
Escribe lo que el código debería hacer como ejemplos
assertantes de escribir el código, y pásalos enoptions.examples. Llama avalidate_pythondespués de cada edición y aexecute_pythonuna vez que una función esté terminada, no de nuevo hasta que lo que hace haya cambiado. Cuando una llamada devuelvafixed_code, acéptalo — el servicio lo ejecutó contra tus ejemplos. No presentes código que haya vueltovalid: false.
CI
El servicio entrega el cliente, así que un flujo de trabajo no necesita clonar este repositorio ni ningún secreto:
- run: |
curl -sf https://api.statemind.ai/v1/client -o validate.py
python3 validate.py --changed-against "origin/${{ github.base_ref }}"
O como acción, desde el Marketplace:
permissions:
contents: read
pull-requests: write # so the run can comment its result on the pull request
steps:
- uses: jkanselaar/python-code-validator@v1.22.0
with:
api-key: ${{ secrets.VALIDATOR_API_KEY }} # optional; free tier without it
El Python modificado se valida y las líneas problemáticas se anotan en el diff, fallando el trabajo en errores de sintaxis y patrones inseguros. Los archivos que el servicio rechaza directamente (por encima de su límite de 200 kB) se omiten con una advertencia en lugar de fallar la ejecución.
La ejecución también deja un comentario en la solicitud de extracción, editado en el lugar en empujes posteriores en lugar de repetirse: qué se aceptó, qué se reparó y cuánto del límite diario queda. Sin pull-requests: write no se escribe nada y el trabajo no se ve afectado; comment: "false" lo desactiva.
En el nivel gratuito, la acción mantiene su clave en la caché del flujo de trabajo, una por repositorio por día, para que el límite pertenezca al repositorio en lugar de a la ejecución. Con api-key configurado, se omite la caché.
Pre-commit
repos:
- repo: https://github.com/jkanselaar/python-code-validator
rev: v1.22.0
hooks:
- id: python-code-validator
El cliente en sí
validate.py es solo biblioteca estándar, por lo que también funciona como python validate.py file.py en un Makefile, un hook de git o un contenedor:
$ python3 validate.py service.py
::error file=service.py,line=88,title=SyntaxError::invalid syntax
FAIL service.py score=0.66
0/1 files accepted
VALIDATOR_API_KEY se usa cuando está configurado; de lo contrario, el cliente crea una clave gratuita — manteniéndola en VALIDATOR_KEY_FILE cuando eso nombre una ruta, que es cómo una serie de ejecuciones comparte un límite. VALIDATOR_URL lo apunta a otro despliegue. VALIDATOR_SOURCE nombra al llamador, que solo se cuenta: una ejecución dentro de un flujo de trabajo dice github-action por sí misma.
La insignia
Un repositorio cuyo Python se verifica en cada solicitud de extracción puede decirlo:
[](https://api.statemind.ai/?src=badge)
HTTP
curl -s https://api.statemind.ai/v1/validate \
-H "Authorization: Bearer $VALIDATOR_API_KEY" \
-H 'content-type: application/json' \
-d '{"code": "def f(:\n pass\n", "mode": "static"}'
mode es static, repair o execute; repair y execute necesitan una clave configurada. El código enviado no se registra.
Una llamada rechazada dice qué hacer al respecto, para que un llamador sin operador al que preguntar pueda resolverlo por sí mismo:
{"error": "payment_required",
"remedy": {"action": "upgrade_key", "hint": "A free key covers static only. …"}}
Pagando por llamadas
Una clave gratuita cubre 25 comprobaciones estáticas al día, y una dirección obtiene unas pocas claves al día, así que el límite es una prueba más que un suministro. Más allá de eso, una clave lleva créditos: una comprobación estática cuesta 1, una reparación 3 y una ejecución en sandbox 10, y una llamada idéntica repetida dentro de diez minutos se responde desde la primera gratis.
Los créditos se compran con una tarjeta, sin factura ni nadie a quien preguntar:
curl -s -X POST https://api.statemind.ai/v1/keys/checkout \
-H 'content-type: application/json' \
-d '{"api_key": "'"$VALIDATOR_API_KEY"'", "credits": 500}'
Eso responde con una página de Stripe Checkout; los créditos están en la clave segundos después de que la tarjeta se procese (500 créditos son 10 €). Un agente con una billetera Gnosis puede en su lugar pagar en xDAI sin navegador — GET /v1/pricing indica ambas rutas.
Licencia
MIT.