Python Code Validator
Prova que o Python gerado por IA faz o que você pediu: declare a intenção como asserções e o servidor executa o código em um contêiner restrito, retornando uma correção somente quando todos os exemplos passam.
Documentação
Python Code Validator
Um servidor MCP que valida, repara e executa Python contra os exemplos que deve satisfazer — validate_python, repair_python e execute_python via HTTP em https://api.statemind.ai/mcp, com uma chave gratuita e sem conta.
Um serviço hospedado que prova que o Python gerado por IA faz o que você pediu. Declare a intenção — asserções ou linhas de doctest — e o código é executado contra ela dentro de um contêiner sem rede e com sistema de arquivos somente leitura; uma correção só volta quando todos os exemplos passam. Nos defeitos do QuixBugs, isso é 41% reparados e 77% recusados por não fazerem o que dizem, sem falsos alarmes nos programas corrigidos — onde ruff e mypy sinalizam o defeito em nenhum deles (os números).
As verificações que não precisam de intenção vêm com ele: diagnósticos de sintaxe e lint, uma política de segurança AST que também captura chamadas escondidas atrás de importações dinâmicas e buscas de atributos em tempo de execução, uma passada de bandit, uma varredura de credenciais e reparo determinístico — um veredito com uma pontuação. Perguntar a mesma coisa duas vezes em dez minutos é respondido pela primeira resposta e não custa nada (x-msvc-repeat: 1).
Este repositório contém o lado do cliente: a configuração MCP, o script de CI e o hook de pre-commit. O serviço em si roda em https://api.statemind.ai, então não há nada para instalar ou hospedar.
Uma chave, sem conta
curl -s -X POST https://api.statemind.ai/v1/keys
# {"api_key": "msvc_free_…", "tier": "free", "calls_per_day": 25, "modes": ["static"]}
25 verificações estáticas por dia, medidas por dia UTC, e algumas chaves por endereço: o suficiente para experimentar e rodar em um projeto pequeno, não um suprimento. Cada resposta traz o estado da cota (x-quota-remaining, x-quota-reset), para que um cliente possa recuar antes de ser cortado.
MCP
Registrado no registro oficial do MCP como ai.statemind/python-code-validator, um nome verificado contra o domínio que o serve, em vez de uma conta do GitHub. Qualquer cliente MCP o adiciona com um bloco:
{
"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, mesmo bloco. - VS Code / Copilot:
.vscode/mcp.jsonsob"servers".
Um cliente que apenas lança um comando usa a ponte stdio deste repositório, que encaminha a mesma ferramenta via HTTPS:
{
"mcpServers": {
"python-code-validator": {
"command": "python3",
"args": ["/path/to/python-code-validator/mcp_stdio.py"]
}
}
}
Ou como um contêiner, que o Dockerfile aqui constrói:
docker build -t python-code-validator .
docker run -i --rm -e VALIDATOR_API_KEY python-code-validator
O Gemini CLI instala a mesma ponte como uma extensão, com o arquivo de instrução que faz com que ela seja usada:
gemini extensions install jkanselaar/python-code-validator
Três ferramentas, nomeadas pelo que fazem com o código:
| ferramenta | executa o código | chave |
|---|---|---|
validate_python | não | grátis |
repair_python — também retorna fixed_code | não | pago |
execute_python — também o executa em um sandbox | sim | pago |
A antiga ferramenta única python_code_validator, com seu argumento mode, ainda responde para clientes que já a configuraram, mas não é mais listada.
Dizendo o que o código deveria fazer
Toda verificação acima passa em uma função que calcula a resposta errada. A única coisa que a pega é a intenção, e o agente que pediu o código é o único que a tem — então passe-a adiante:
{"code": "def bitcount(n): …", "mode": "execute",
"options": {"examples": "assert bitcount(127) == 7"}}
Linhas de doctest (>>> bitcount(127) e depois 7) funcionam da mesma forma, assim como exemplos >>> já escritos no código-fonte. execute_python os executa no sandbox: um que não se sustenta é um erro python:example-mismatch, e a busca de reparo retorna uma correção apenas quando todos os exemplos passam. No conjunto de defeitos do QuixBugs — bugs reais, entradas de teste ocultas decidindo a correção — isso repara 41% e recusa 77% por não fazerem o que dizem, sem falsos alarmes nos programas corrigidos.
Repetir uma chamada não custa nada: a mesma chave perguntando a mesma coisa — mesmo modo, mesmo código, mesmos exemplos — é respondida pela resposta que já obteve, marcada como x-msvc-repeat: 1, para que um agente que verifica seu trabalho a cada passo não seja cobrado por vereditos que não podem ter mudado.
Plugin do Claude Code
Uma instrução pode ser ignorada; um hook não. O plugin verifica cada arquivo Python que o Claude Code escreve ou edita, na vez em que foi escrito, e devolve os erros ao modelo em vez de a você:
/plugin marketplace add jkanselaar/python-code-validator
/plugin install python-code-validator@statemind
Nada para configurar: ele gera e mantém sua própria chave gratuita no primeiro uso. Um arquivo que volta aceito é silencioso, um rejeitado interrompe a vez com as linhas ofensoras nomeadas, e um arquivo idêntico não é perguntado duas vezes. Ele nunca encerra uma sessão por causa de seus próprios problemas — um serviço inacessível ou uma cota gasta deixa a vez continuar, e a cota diz como aumentá-la.
Defina VALIDATOR_API_KEY para usar uma chave paga em vez do nível gratuito, e VALIDATOR_URL para apontar para sua própria implantação. O plugin também carrega a habilidade validate-python, para a parte que um hook não pode fazer: declarar a intenção como exemplos e executar o código contra eles.
Hook do Cursor
O mesmo script, conectado ao postToolUse do Cursor, onde o veredito volta como contexto na conversa em vez de como código de saída:
mkdir -p .cursor/hooks
base=https://raw.githubusercontent.com/jkanselaar/python-code-validator/main
curl -sf $base/plugin/hooks/validate_written.py -o .cursor/hooks/validate_written.py
curl -sf $base/cursor/hooks.json -o .cursor/hooks.json
Hooks de projeto rodam a partir da raiz do projeto, por isso o comando em cursor/hooks.json é um caminho relativo a ela. Para um hook que se aplica a todos os projetos, coloque o script em ~/.cursor/hooks/ e o mesmo bloco em ~/.cursor/hooks.json com o comando python3 ./hooks/validate_written.py --cursor.
Fazendo o agente usá-lo
Configurar o servidor não é o que faz com que ele seja chamado: o arquivo de instrução é. AGENTS.md neste repositório é esse texto, escrito para ser colocado em qualquer projeto sob o nome que o cliente lê:
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
O Cursor lê regras com front matter, então essa é um arquivo separado — copie .cursor/rules/python-code-validator.mdc para .cursor/rules/ do projeto.
A versão curta, se você preferir adicionar uma linha às instruções que já tem:
Escreva o que o código deve fazer como exemplos
assertantes de escrever o código, e passe-os emoptions.examples. Chamevalidate_pythonapós cada edição eexecute_pythonassim que uma função estiver terminada, não novamente até que o que ela faz tenha mudado. Quando uma chamada retornarfixed_code, aceite-a — o serviço o executou contra seus exemplos. Não apresente código que voltouvalid: false.
CI
O serviço distribui o cliente, então um workflow não precisa de checkout deste repositório nem de segredo:
- run: |
curl -sf https://api.statemind.ai/v1/client -o validate.py
python3 validate.py --changed-against "origin/${{ github.base_ref }}"
Ou como uma action, do 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
O Python alterado é validado e as linhas ofensoras são anotadas no diff, falhando o job em erros de sintaxe e padrões inseguros. Arquivos que o serviço recusa de imediato (acima do limite de 200 kB) são ignorados com um aviso em vez de falhar a execução.
A execução também deixa um comentário no pull request, editado no lugar em pushes posteriores em vez de repetido: o que foi aceito, o que foi reparado e quanto da cota do dia resta. Sem pull-requests: write nada é escrito e o job não é afetado; comment: "false" desliga isso.
No nível gratuito, a action mantém sua chave no cache do workflow, uma por repositório por dia, então a cota pertence ao repositório em vez da execução. Com api-key definido, o cache é ignorado.
Pre-commit
repos:
- repo: https://github.com/jkanselaar/python-code-validator
rev: v1.22.0
hooks:
- id: python-code-validator
O cliente em si
validate.py é apenas biblioteca padrão, então também funciona como python validate.py file.py em um Makefile, um hook do git ou um contêiner:
$ 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 é usado quando definido; caso contrário, o cliente gera uma chave gratuita — mantendo-a em VALIDATOR_KEY_FILE quando isso nomeia um caminho, que é como uma série de execuções compartilha uma cota. VALIDATOR_URL aponta para outra implantação. VALIDATOR_SOURCE nomeia o chamador, que é apenas contado: uma execução dentro de um workflow diz github-action por si só.
O selo
Um repositório cujo Python é verificado em cada pull request pode dizer isso:
[](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 é static, repair ou execute; repair e execute precisam de uma chave configurada. O código enviado não é registrado.
Uma chamada recusada diz o que fazer a respeito, para que um chamador sem operador a quem perguntar possa resolver por si só:
{"error": "payment_required",
"remedy": {"action": "upgrade_key", "hint": "A free key covers static only. …"}}
Pagando por chamadas
Uma chave gratuita cobre 25 verificações estáticas por dia, e um endereço recebe algumas chaves por dia, então a cota é um teste em vez de um suprimento. Além disso, uma chave carrega créditos: uma verificação estática custa 1, um reparo 3 e uma execução em sandbox 10, e uma chamada idêntica repetida em dez minutos é respondida pela primeira gratuitamente.
Créditos são comprados com cartão, sem fatura ou alguém a quem perguntar:
curl -s -X POST https://api.statemind.ai/v1/keys/checkout \
-H 'content-type: application/json' \
-d '{"api_key": "'"$VALIDATOR_API_KEY"'", "credits": 500}'
Isso responde com uma página de Stripe Checkout; os créditos estão na chave segundos após o cartão ser aprovado (500 créditos são €10). Um agente com uma carteira Gnosis pode, em vez disso, pagar em xDAI sem navegador — GET /v1/pricing declara ambas as rotas.
Exemplos
examples/ contém três arquivos e o cliente para enviá-los: um que passa em todas as verificações e ainda retorna o número errado, um que a política de segurança recusa, e um que volta aceito do sandbox.
Licença
MIT.