Skip to main content
Glama
jkanselaar

Python Code Validator

Python Code Validator

An MCP server that validates, repairs and runs Python against the examples it is supposed to satisfy — validate_python, repair_python and execute_python over HTTP at https://api.statemind.ai/mcp, with a free key and no account.

A hosted service that proves AI-generated Python does what you asked. State the intent — assertions or doctest lines — and the code is run against it inside a container with no network and a read-only filesystem; a fix comes back only when every example passes. On the QuixBugs defects that is 41% repaired and 77% refused as not doing what they say, with no false alarms on the corrected programs — where ruff and mypy flag the defect in none of them (the numbers).

The checks that need no intent come with it: syntax and lint diagnostics, an AST security policy that also catches calls hidden behind dynamic imports and runtime attribute lookups, a bandit pass, a credential scan and deterministic repair — one verdict with a score. Asking the same question twice inside ten minutes is answered from the first answer and costs nothing (x-msvc-repeat: 1).

This repository holds the client side: the MCP configuration, the CI script and the pre-commit hook. The service itself runs at https://api.statemind.ai, so there is nothing to install or host.

A key, without an account

curl -s -X POST https://api.statemind.ai/v1/keys
# {"api_key": "msvc_free_…", "tier": "free", "calls_per_day": 25, "modes": ["static"]}

25 static checks a day, metered per UTC day, and a few keys per address: enough to try it and to run it over a small project, not a supply. Every answer carries the state of the allowance (x-quota-remaining, x-quota-reset), so a client can back off before it is cut off.

Related MCP server: code-quality-mcp

MCP

Registered in the official MCP registry as ai.statemind/python-code-validator, a name verified against the domain that serves it rather than a GitHub account. Any MCP client adds it with one block:

{
  "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, same block.

  • VS Code / Copilot: .vscode/mcp.json under "servers".

A client that only launches a command uses the stdio bridge in this repository instead, which forwards the same tool over HTTPS:

{
  "mcpServers": {
    "python-code-validator": {
      "command": "python3",
      "args": ["/path/to/python-code-validator/mcp_stdio.py"]
    }
  }
}

Or as a container, which the Dockerfile here builds:

docker build -t python-code-validator .
docker run -i --rm -e VALIDATOR_API_KEY python-code-validator

Gemini CLI installs the same bridge as an extension, with the instruction file that makes it get used:

gemini extensions install jkanselaar/python-code-validator

Three tools, named after what they do to the code:

tool

runs the code

key

validate_python

no

free

repair_python — also returns fixed_code

no

paid

execute_python — also runs it in a sandbox

yes

paid

The old single python_code_validator tool, with its mode argument, still answers for clients that already configured it, but is no longer listed.

Saying what the code was supposed to do

Every check above passes on a function that computes the wrong answer. The one thing that catches it is the intent, and the agent that asked for the code is the only one who has it — so pass it along:

{"code": "def bitcount(n): …", "mode": "execute",
 "options": {"examples": "assert bitcount(127) == 7"}}

Doctest lines (>>> bitcount(127) then 7) work the same way, as do >>> examples already written in the source. execute_python runs them in the sandbox: one that does not hold is a python:example-mismatch error, and the repair search returns a fix only when every example passes. On the QuixBugs defect set — real bugs, hidden test inputs deciding correctness — that repairs 41% and refuses 77% as not doing what they say, with no false alarms on the corrected programs.

Repeating a call costs nothing: the same key asking the same question — same mode, same code, same examples — is answered from the answer it already got, marked x-msvc-repeat: 1, so an agent that checks its work at every step is not billed for verdicts that cannot have changed.

Claude Code plugin

An instruction can be ignored; a hook cannot. The plugin checks every Python file Claude Code writes or edits, in the turn it was written, and hands the errors back to the model instead of to you:

/plugin marketplace add jkanselaar/python-code-validator
/plugin install python-code-validator@statemind

Nothing to configure: it mints and keeps its own free key on first use. A file that comes back accepted is silent, a rejected one stops the turn with the offending lines named, and an identical file is not asked about twice. It never ends a session over its own trouble — an unreachable service or a spent allowance lets the turn continue, and the allowance says how to raise it.

Set VALIDATOR_API_KEY to use a paid key instead of the free tier, and VALIDATOR_URL to point at your own deployment. The plugin also carries the validate-python skill, for the part a hook cannot do: stating the intent as examples and running the code against them.

Cursor hook

The same script, wired to Cursor's postToolUse, where the verdict comes back as context on the conversation instead of as an exit code:

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

Project hooks run from the project root, which is why the command in cursor/hooks.json is a path relative to it. For a hook that applies to every project instead, put the script in ~/.cursor/hooks/ and the same block in ~/.cursor/hooks.json with the command python3 ./hooks/validate_written.py --cursor.

Making the agent use it

Configuring the server is not what gets it called: the instruction file is. AGENTS.md in this repository is that text, written to be dropped into any project under whichever name the client reads:

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 reads rules with front matter instead, so that one is a separate file — copy .cursor/rules/python-code-validator.mdc into .cursor/rules/ of the project.

The short version, if you would rather add a line to instructions you already have:

Write what the code should do as assert examples before writing the code, and pass them in options.examples. Call validate_python after every edit and execute_python once a function is finished, not again until what it does has changed. When a call returns fixed_code, take it — the service ran it against your examples. Do not present code that came back valid: false.

CI

The service hands out the client, so a workflow needs no checkout of this repository and no secret:

- run: |
    curl -sf https://api.statemind.ai/v1/client -o validate.py
    python3 validate.py --changed-against "origin/${{ github.base_ref }}"

Or as an action, from the 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

The changed Python is validated and offending lines are annotated on the diff, failing the job on syntax errors and unsafe patterns. Files the service refuses outright (over its 200 kB limit) are skipped with a warning rather than failing the run.

The run also leaves one comment on the pull request, edited in place on later pushes rather than repeated: what was accepted, what was repaired and how much of the day's allowance is left. Without pull-requests: write nothing is written and the job is unaffected; comment: "false" turns it off.

On the free tier the action keeps its key in the workflow cache, one per repository per day, so the allowance belongs to the repository rather than to the run. With api-key set the cache is skipped.

Pre-commit

repos:
  - repo: https://github.com/jkanselaar/python-code-validator
    rev: v1.22.0
    hooks:
      - id: python-code-validator

The client itself

validate.py is standard library only, so it also works as python validate.py file.py in a Makefile, a git hook or a container:

$ 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 is used when set; otherwise the client mints a free key — keeping it in VALIDATOR_KEY_FILE when that names a path, which is how a series of runs shares one allowance. VALIDATOR_URL points it at another deployment. VALIDATOR_SOURCE names the caller, which is only ever counted: a run inside a workflow says github-action by itself.

The badge

A repository whose Python is checked on every pull request can say so:

[![Python validated](https://img.shields.io/badge/python-validated-2ea44f?logo=python&logoColor=white)](https://api.statemind.ai/?src=badge)

Python validated

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 is static, repair or execute; repair and execute need a configured key. Submitted code is not logged.

A refused call says what to do about it, so a caller with no operator to ask can resolve it itself:

{"error": "payment_required",
 "remedy": {"action": "upgrade_key", "hint": "A free key covers static only. …"}}

Paying for calls

A free key covers 25 static checks a day, and one address gets a few keys a day, so the allowance is a trial rather than a supply. Beyond it a key carries credits: a static check costs 1, a repair 3 and a sandboxed run 10, and an identical call repeated within ten minutes is answered from the first one for free.

Credits are bought with a card, without an invoice or anyone to ask:

curl -s -X POST https://api.statemind.ai/v1/keys/checkout \
  -H 'content-type: application/json' \
  -d '{"api_key": "'"$VALIDATOR_API_KEY"'", "credits": 500}'

That answers with a Stripe Checkout page; the credits are on the key seconds after the card clears (500 credits is €10). An agent with a Gnosis wallet can instead pay in xDAI without a browser — GET /v1/pricing states both routes.

Examples

examples/ holds three files and the client to send them with: one that passes every check and still returns the wrong number, one the security policy refuses, and one that comes back accepted from the sandbox.

Licence

MIT.

Available Tools

3 tools
execute_pythonExecute PythonA
Idempotent
Inspect

Everything repair does, and then RUNS the code in a throwaway container — no network, read-only filesystem, killed at options.timeout_s — reporting exit code, stdout and stderr. Any '>>>' examples in the code are run too, and one that does not print what it says is an error the other tools cannot see. This is a side effect: do not submit code you do not want executed. Use it when you need proof that the code runs, or that it does what it says. Alternatives: validate_python for the diagnosis and repair_python for the fix, neither of which runs anything. Auth: a key is required. This call needs a paid key and answers HTTP 402 without one. Credits are bought without an account, 10 per call: GET /v1/pricing says where to send the xDAI. Or pay for this one call with no key at all: call it without one and the result carries x402 payment requirements ($0.1 in USD Coin on eip155:8453); sign them and repeat the call with the payment in _meta['x402/payment']. Arguments: code: the whole file, 1..200000 bytes of UTF-8 measured after encoding (empty is refused with 400, larger with 413); a fragment is fine, but line and column numbers in the answer count from 1 in what you sent. language: must be 'python'; anything else is 400, and the field may be omitted. options.max_iterations (1..10, default 3) caps the fix/verify rounds: raise it for a file with several independent faults, leave it for a snippet. options.optimize (default false) additionally folds constants and drops dead code, and is only worth setting when you asked for a rewrite anyway. options.transpile_to (e.g. 'javascript') returns a translation of the repaired source in transpiled, not of what you sent. fixed_code is null when nothing could be proven safe to change, so treat null as 'no fix', not as an error. options.timeout_s (seconds, default 5) is the wall clock for the run; the schema allows up to 60 but this deployment caps it at 30 and refuses a larger value with 400. options.expected_output compares stdout byte for byte and adds an 'expected-output' diagnostic (valid=false) when it differs, which is how you ask for 'it did the right thing' rather than 'it ran'. options.examples is the same question for code with no output: pass what you asked for as doctest lines ('>>> total([1, 2])' then '3') or assertions ('assert total([1, 2]) == 3'), and each is run against the code -- one that does not hold is a 'python:example-mismatch' error, and repair looks for a single-token change that makes them all pass. Send it whenever you know what you asked for: without it, code that runs but returns the wrong answer looks perfect from here. The program that runs is the repaired one, so read fixed_code before you trust runtime.stdout, and it runs exactly once however many rounds the repair took. Returns valid, score 0..1, diagnostics (rule, message, line, column), security findings, fixes, fixed_code and runtime; see outputSchema. The code and its verdict are retained to improve the service.

ParametersJSON Schema
NameRequiredDescriptionDefault
codeYesThe source to check, as a whole file where possible: diagnostics carry the line and column of the text you send, and a fragment hides the imports and definitions the type check needs. A deployment may accept fewer bytes than the 200000 here.
optionsNoTuning knobs. Most of them only take effect in the mode that does the corresponding work; see each field.
languageNoThe language of the code. A service that does not handle it refuses the request rather than guessing; the enum is shared across services, so it lists more than any one of them accepts.python

Output Schema

ParametersJSON Schema
NameRequiredDescription
metaYes
fixesNo
scoreYes
validYes
runtimeNo
securityNo
fixed_codeNo
transpiledNo
diagnosticsNo

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

It adds critical context beyond the annotations: the code is actually executed, so malicious or unwanted code is a side effect; the container is no-network, read-only, and killed at timeout; the repaired code is what runs; and data is retained to improve the service. It also discloses auth and x402 payment behavior. No explicit contradiction with the annotations exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long, but it is structured and front-loaded: it starts with what the tool does, then covers side effects, alternatives, auth, parameters, and returned values. The length is justified by the complexity of a side-effecting, execution tool with payment requirements and repair semantics, though some parameter details are summarized the schema already contains.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description, together with the output schema, provides everything needed to choose and call this tool correctly: behavioral constraints, alternatives, auth flow, argument semantics, edge cases like null fixed_code, and return shape. The agent is not left to guess or infer critical behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Even though schema description coverage is 100%, the description explains practical operational semantics: code is measured in encoded UTF-8 bytes, language is restricted to Python despite the schema enum, the deployment caps timeout_s at 30, and expected_output/examples are the mechanism for proving correctness rather than just execution. This guidance is not inferable from the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a concrete verb and resource: run the submitted code in a throwaway container and report exit code, stdout, and stderr. It also orients the agent by explaining that the tool does everything repair_python does and then executes the code, which clearly separates it from validate_python and repair_python.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It tells the agent exactly when to choose this tool: when proof of execution is needed, such as 'that it runs or that it does what it says'. It explicitly names the alternative tools, validate_python and repair_python, and notes neither runs anything, which prevents selection mistakes.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

repair_pythonRepair PythonA
Read-onlyIdempotent
Inspect

Everything validation does, plus deterministic fixes: the corrected source comes back in fixed_code, and the original is kept whenever the fix cannot be proven safe. The code is still never run. Use it when validation failed and you want the fix rather than the diagnosis. Alternatives: validate_python when the diagnosis is enough; execute_python when the fix has to be proven to run. Auth: a key is required. This call needs a paid key and answers HTTP 402 without one. Credits are bought without an account, 3 per call: GET /v1/pricing says where to send the xDAI. Or pay for this one call with no key at all: call it without one and the result carries x402 payment requirements ($0.03 in USD Coin on eip155:8453); sign them and repeat the call with the payment in _meta['x402/payment']. Arguments: code: the whole file, 1..200000 bytes of UTF-8 measured after encoding (empty is refused with 400, larger with 413); a fragment is fine, but line and column numbers in the answer count from 1 in what you sent. language: must be 'python'; anything else is 400, and the field may be omitted. options.max_iterations (1..10, default 3) caps the fix/verify rounds: raise it for a file with several independent faults, leave it for a snippet. options.optimize (default false) additionally folds constants and drops dead code, and is only worth setting when you asked for a rewrite anyway. options.transpile_to (e.g. 'javascript') returns a translation of the repaired source in transpiled, not of what you sent. fixed_code is null when nothing could be proven safe to change, so treat null as 'no fix', not as an error. options.timeout_s, options.examples and options.expected_output do nothing here: nothing is run, so there is no clock, no stdout, and no way to check an example. Returns valid, score 0..1, diagnostics (rule, message, line, column), security findings, fixes, fixed_code and runtime; see outputSchema. The code and its verdict are retained to improve the service.

ParametersJSON Schema
NameRequiredDescriptionDefault
codeYesThe source to check, as a whole file where possible: diagnostics carry the line and column of the text you send, and a fragment hides the imports and definitions the type check needs. A deployment may accept fewer bytes than the 200000 here.
optionsNoTuning knobs. Most of them only take effect in the mode that does the corresponding work; see each field.
languageNoThe language of the code. A service that does not handle it refuses the request rather than guessing; the enum is shared across services, so it lists more than any one of them accepts.python

Output Schema

ParametersJSON Schema
NameRequiredDescription
metaYes
fixesNo
scoreYes
validYes
runtimeNo
securityNo
fixed_codeNo
transpiledNo
diagnosticsNo

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds critical behavior beyond annotations: code is never run, fixes are only returned when provably safe, fixed_code is null when no fix is possible, and authentication/payment requirements are disclosed. It also states which options are ignored because nothing executes. Annotations already indicate read-only and non-destructive, and the description does not contradict them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but logically organized by sections (behavior, use cases, auth, arguments, returns). It front-loads the core distinction from siblings and then systematically covers constraints. It is somewhat verbose, especially around payment details, but every section contributes decision-relevant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The output schema exists, and the description still explains the null fixed_code semantics, return fields, auth failure behavior, and constraint enforcement. Nothing an agent needs to call this tool correctly appears to be missing, including what happens with unsupported options.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description enriches every parameter: it details byte limits for code, explains that fragments shift line/column numbers, states language must be 'python' and other values elicit 400, and clarifies that options like timeout_s, examples, and expected_output have no effect in this mode. This goes far beyond raw schema fields.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: repair Python code, returning deterministic fixes in fixed_code and preserving the original when safety cannot be proven. It also explicitly contrasts itself with the sibling tools validate_python and execute_python, so an agent can distinguish it without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit selection criteria: use when validation failed and you want a fix, not just a diagnosis. It also names the alternatives ('validate_python when the diagnosis is enough; execute_python when the fix has to be proven to run').

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_pythonValidate PythonA
Read-onlyIdempotent
Inspect

Check Python source without running it: parse, lint (ruff), type-check (mypy), AST security policy, credential scan. Safe on code you do not trust. Use it on every Python file you generated or edited, before writing it to disk. Alternatives: repair_python to get the corrected source instead of the diagnosis; execute_python to prove the code runs. Auth: a key is required. A free key covers this call, 25 per day, then HTTP 429; get one with POST /v1/keys. Credits are bought without an account, 1 per call: GET /v1/pricing says where to send the xDAI. Or pay for this one call with no key at all: call it without one and the result carries x402 payment requirements ($0.01 in USD Coin on eip155:8453); sign them and repeat the call with the payment in _meta['x402/payment']. Arguments: code: the whole file, 1..200000 bytes of UTF-8 measured after encoding (empty is refused with 400, larger with 413); a fragment is fine, but line and column numbers in the answer count from 1 in what you sent. language: must be 'python'; anything else is 400, and the field may be omitted. Of options only transpile_to (e.g. 'javascript', which returns a translated copy in transpiled) acts here; timeout_s, max_iterations, optimize, examples and expected_output need a pass that rewrites or runs the code, so send code alone. Ignored options are not refused, so a call that sets them looks like it worked; and code that does not parse is answered rather than refused: valid=false with the syntax error located, which is the point. Returns valid, score 0..1, diagnostics (rule, message, line, column), security findings, fixes, fixed_code and runtime; see outputSchema. The code and its verdict are retained to improve the service.

ParametersJSON Schema
NameRequiredDescriptionDefault
codeYesThe source to check, as a whole file where possible: diagnostics carry the line and column of the text you send, and a fragment hides the imports and definitions the type check needs. A deployment may accept fewer bytes than the 200000 here.
optionsNoTuning knobs. Most of them only take effect in the mode that does the corresponding work; see each field.
languageNoThe language of the code. A service that does not handle it refuses the request rather than guessing; the enum is shared across services, so it lists more than any one of them accepts.python

Output Schema

ParametersJSON Schema
NameRequiredDescription
metaYes
fixesNo
scoreYes
validYes
runtimeNo
securityNo
fixed_codeNo
transpiledNo
diagnosticsNo

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Even though annotations already mark readOnlyHint=true and destructiveHint=false, the description goes far beyond them: it promises safety on untrusted code ('Safe on code you do not trust'), discloses that it never runs code, and highlights silent no-op options ('Ignored options are not refused, so a call that sets them looks like it worked'). It also reveals rate limits and auth behavior (HTTP 429, key requirement, x402 payment flow) and the fact that submitted code is retained to improve the service. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but every sentence earns its place. It is clearly structured with labeled sections (Auth, Arguments, Returns) and front-loaded with the core purpose before diving into details. No filler or redundant repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description does not need to enumerate return fields in depth; it still gives a high-level list. It covers input constraints, authentication requirements, call-limits, error behaviors, sibling tool relations, and retention. An agent has everything necessary to call the tool safely and correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Even though the schema already covers parameters 100%, the description adds critical meaning: it notes empty/large code fails with HTTP 400/413, line/column numbers count from the submitted fragment, the language must be exactly 'python' despite the broad schema enum, and that only transpile_to among options actual effects in this static tool. It explains that other options are ignored rather than rejected, which is not communicated by the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a precise verb and resource: 'Check Python source without running it' followed by an explicit checklist (parse, lint/ruff, type-check/mypy, AST security policy, credential scan). It explicitly distinguishes the tool from its siblings: 'repair_python to get the corrected source instead of the diagnosis; execute_python to prove the code runs.' No ambiguity remains about what this tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states exactly when to use this tool ('Use it on every Python file you generated or edited, before writing it to disk') and clearly names alternatives and their purpose. The when-not-to-use is implicit but clear: if you need a corrected file, use repair_python; if you need runtime proof, use execute_python. This is explicit enough to route an agent correctly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 3 tool updatesv1.17.1
    • Changedexecute_python1 field changed
      • addedInput schema / $defs / Options / properties / examples
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "What the code is supposed to do, as doctest lines ('>>> f(2)' on one line, '4' on the next) or as plain assertions ('assert f(2) == 4'). In execute mode they are run in the sandbox: an example that does not hold is a 'python:example-mismatch' error and makes the response invalid, and repair searches for a single-token change that makes every one of them pass. This is the only way the service can tell code that runs from code that is right, so send it whenever you know what you asked for. Examples already written in the code ('>>> ' in any string) are used the same way without this option. Ignored in the other modes, which run nothing.",
        +  "title": "Examples"
        +}
    • Changedrepair_python1 field changed
      • addedInput schema / $defs / Options / properties / examples
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "What the code is supposed to do, as doctest lines ('>>> f(2)' on one line, '4' on the next) or as plain assertions ('assert f(2) == 4'). In execute mode they are run in the sandbox: an example that does not hold is a 'python:example-mismatch' error and makes the response invalid, and repair searches for a single-token change that makes every one of them pass. This is the only way the service can tell code that runs from code that is right, so send it whenever you know what you asked for. Examples already written in the code ('>>> ' in any string) are used the same way without this option. Ignored in the other modes, which run nothing.",
        +  "title": "Examples"
        +}
    • Changedvalidate_python1 field changed
      • addedInput schema / $defs / Options / properties / examples
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "What the code is supposed to do, as doctest lines ('>>> f(2)' on one line, '4' on the next) or as plain assertions ('assert f(2) == 4'). In execute mode they are run in the sandbox: an example that does not hold is a 'python:example-mismatch' error and makes the response invalid, and repair searches for a single-token change that makes every one of them pass. This is the only way the service can tell code that runs from code that is right, so send it whenever you know what you asked for. Examples already written in the code ('>>> ' in any string) are used the same way without this option. Ignored in the other modes, which run nothing.",
        +  "title": "Examples"
        +}
  2. 4 tool updatesv1.6.4
    • Addedexecute_python
    • Removedpython_code_validator
    • Addedrepair_python
    • Addedvalidate_python
  3. 1 tool updatev1.1.1
    • Changedpython_code_validator5 fields changed
      • changedInput schema / properties / code / description
        Previous value: -"The Python source to validate."New value: +"The Python source to validate. A whole module, not a fragment."
      • removedInput schema / properties / filename
        Removed value: -{
        -  "description": "Name to report diagnostics against.",
        -  "type": "string"
        -}
      • changedInput schema / properties / mode / description
        Previous value: -"static analyses only; repair also returns fixed code; execute runs it in a sandbox. repair and execute need a paid key."New value: +"static analyses only and is free; repair also returns fixed code; execute runs it in a sandbox. repair and execute need a paid key."
      • addedInput schema / properties / options
        Added value: +{
        +  "description": "Tuning knobs; timeout_s (1-60) bounds execute mode.",
        +  "properties": {
        +    "timeout_s": {
        +      "maximum": 60,
        +      "minimum": 1,
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "diagnostics": {
        +      "description": "Correctness problems, each with rule, message, line and column.",
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "fixed_code": {
        +      "description": "Repaired source, only in repair and execute mode.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "fixes": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "meta": {
        +      "type": "object"
        +    },
        +    "runtime": {
        +      "description": "Sandbox result, only in execute mode.",
        +      "type": "object"
        +    },
        +    "score": {
        +      "maximum": 1,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "security": {
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "valid": {
        +      "description": "False when anything is an error.",
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "valid",
        +    "score",
        +    "diagnostics",
        +    "security",
        +    "meta"
        +  ],
        +  "type": "object"
        +}
  4. 1 tool updatev1.0.0
    • First observedpython_code_validator

TDQS

A4.9/5.0
Disambiguation5/5

Each tool is clearly distinct: validate_python diagnoses without running, repair_python additionally fixes, and execute_python additionally runs the code. The layering is explicit, and cross-references in the descriptions make the relationship unambiguous. No two tools appear to serve the same purpose.

Naming Consistency5/5

All tool names follow the verb_python pattern exactly: validate_python, repair_python, execute_python. Naming is consistent, predictable, and clearly reflects each tool's function.

Tool Count5/5

Three tools cover the full validation-to-execution pipeline without bloat. Each tool represents a distinct stage of the workflow, and the count is well-scoped for the server's stated purpose.

Completeness5/5

The tool set provides a complete lifecycle for Python code handling: diagnose (validate), fix (repair), and prove (execute). No obvious gaps exist; even transpile and security scanning are embedded in the pipeline. The options for examples and expected_output also address behavioral verification.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Automatically detects security vulnerabilities in AI-generated code, scanning for hardcoded secrets, injection flaws, XSS, weak cryptography, authentication issues, path traversal, and vulnerable dependencies across JavaScript, Python, Java, and Go.
    10
    2
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides deterministic Python code quality analysis using flake8, mypy, McCabe, and vulture, enabling LLMs to access real linting and type checking results.
    1
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Deterministic JSON validation and repair for AI agents. Validates, repairs, schema-checks, and diffs JSON so long-running agents don't corrupt their session state with malformed writes.
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jkanselaar/python-code-validator'

If you have feedback or need assistance with the MCP directory API, please join our Discord server