Skip to main content

execute_python_code

Execute Python code in a sandboxed subprocess with access to all QWED SDK libraries.
As of v0.2.0, execute_python_code is the single MCP tool exposed by QWED-MCP. It replaces all previous verify_* tools to solve context bloat (RFC-9728 compatibility). See migration from v0.1.x below.

Description

The execute_python_code tool runs arbitrary Python code in a subprocess with restricted environment variables. The subprocess has access to all installed QWED SDK packages (qwed_new, qwed_legal, qwed_finance, qwed_ucp, etc.), so LLMs can write verification scripts that import and call any QWED engine directly. The tool captures stdout and stderr from the subprocess and returns them as text.

Parameters

ParameterTypeRequiredDefaultDescription
codestringYes-Python code to execute in a subprocess
backgroundbooleanNofalseWhen true, the job runs asynchronously in the background and returns a job_id immediately. Use the verification_status tool to poll for results. Recommended for heavy or long-running verification scripts.

Environment

The subprocess runs with a restricted environment. Only PATH, PYTHONPATH, and SYSTEMROOT (Windows) are forwarded. Secrets, API keys, and other environment variables are stripped. The server admin must set QWED_MCP_TRUSTED_CODE_EXECUTION=true to enable this tool. When disabled, the tool returns an error message.

Execution limits

LimitSynchronous (background=false)Background (background=true)
Timeout30 secondsNo timeout (runs until completion)
Output cap1 MB (stdout and stderr each)1 MB (stdout and stderr each)
Process isolationNew subprocess per invocationNew subprocess per invocation
ConcurrencySequentialUp to 5 concurrent background jobs
When the 1 MB output cap is reached, the subprocess is terminated and the output is truncated with a warning message.

Examples

Verify a math calculation

{
  "code": "from sympy import symbols, diff\nx = symbols('x')\nresult = diff(x**3, x)\nprint(f'derivative of x^3 = {result}')\nassert str(result) == '3*x**2', 'Mismatch!'\nprint('VERIFIED')"
}
Response:
STDOUT:
derivative of x^3 = 3*x**2
VERIFIED

Execution completed successfully.

Verify a financial calculation

{
  "code": "from decimal import Decimal, ROUND_HALF_UP\n\nP = Decimal('10000')\nr = Decimal('0.075')\nn = Decimal('4')\nt = Decimal('5')\n\nA = P * (1 + r/n) ** (n*t)\nA = A.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)\nprint(f'Future value: ${A}')\nassert A == Decimal('14490.97'), f'Expected 14490.97, got {A}'"
}
Response:
STDOUT:
Future value: $14490.97

Execution completed successfully.

Check code for security vulnerabilities

{
  "code": "from qwed_new.guards.code_guard import CodeGuard\n\nguard = CodeGuard()\nresult = guard.verify_safety(\"import os; os.system('rm -rf /')\")\nprint(f'Verified: {result[\"verified\"]}')\nif result.get('violations'):\n    for v in result['violations']:\n        print(f'  - {v}')"
}
Response:
STDOUT:
Verified: False
  - Dangerous pattern: os.system

Execution completed successfully.

Verify SQL safety

{
  "code": "from qwed_new.guards.sql_guard import SQLGuard\n\nguard = SQLGuard()\nresult = guard.verify_query(\"SELECT * FROM users WHERE id = '1' OR '1'='1'\")\nprint(f'Verified: {result[\"verified\"]}')\nprint(f'Message: {result.get(\"message\", \"\")}')"
}
{
  "code": "from qwed_legal import DeadlineGuard\n\nguard = DeadlineGuard(country='US')\nresult = guard.verify('2026-01-15', '30 business days', '2026-02-14')\nprint(f'Verified: {result.verified}')\nprint(f'Computed deadline: {result.computed_deadline}')"
}

Verify AI content provenance

{
  "code": "import hashlib\nfrom qwed_legal import ProvenanceGuard\n\ncontent = 'This AI-generated memo reviews the indemnification terms.'\ncontent_hash = hashlib.sha256(content.encode()).hexdigest()\n\nguard = ProvenanceGuard(require_disclosure=True)\nresult = guard.verify_provenance(content, {\n    'content_hash': content_hash,\n    'model_id': 'claude-4.5-sonnet',\n    'generation_timestamp': '2026-03-24T12:00:00+00:00',\n})\nprint(f'Verified: {result[\"verified\"]}')\nprint(f'Checks passed: {result[\"checks_passed\"]}')"
}

Run a heavy verification in the background

{
  "code": "from qwed_legal import LegalGuard\n\nguard = LegalGuard()\n# ... long-running multi-guard verification\nprint('All checks passed')",
  "background": true
}
Response:
Verification order is being placed for the request 3f8a1b2c-... Check back using the 'verification_status' tool.
Then poll for results:
{
  "name": "verification_status",
  "arguments": {
    "job_id": "3f8a1b2c-..."
  }
}

Error responses

ScenarioResponse
Tool disabledError: Code execution is disabled. The server admin must set QWED_MCP_TRUSTED_CODE_EXECUTION=true to enable this tool.
No code providedError: No code provided.
Script raises exceptionSTDERR contains the traceback; return code is non-zero
Timeout exceededExecution timed out after 30.0 seconds.
Output cap exceeded[WARNING: OUTPUT TRUNCATED DUE TO 1MB SIZE CAP. PROCESS TERMINATED.] — appended to the truncated output

verification_status

Check the execution status and output of a background verification task dispatched via execute_python_code with background=true.

Parameters

ParameterTypeRequiredDescription
job_idstringYesThe UUID returned by execute_python_code when background=true

Response format

The response text depends on the job state:
Job stateResponse
queuedStatus: queued...
runningStatus: running...
successStatus: success\n\nResult:\n<stdout/stderr output>
failedStatus: failed\n\nResult:\n<error details>
cancelledStatus: cancelled\n\nResult:\nJob was cancelled.
Not found / expiredError: Job ID '<id>' not found or expired.

Example

{
  "job_id": "3f8a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c"
}
Response (while running):
Status: running...
Response (completed):
Status: success

Result:
STDOUT:
All checks passed

Execution completed successfully.

Job lifecycle

  • Background jobs expire after 1 hour (3600 seconds). Expired jobs are pruned automatically.
  • A maximum of 5 jobs can run concurrently. Additional jobs are queued until a slot opens.
  • Once a job completes (success, failed, or cancelled), its result is available until the TTL expires.
Background job state is held in memory on the MCP server. If the server restarts, all pending and completed jobs are lost.

Migrating from v0.1.x

In v0.1.x, QWED-MCP exposed individual tools (verify_math, verify_logic, verify_code, verify_sql, and others). In v0.2.0, all of these were consolidated into execute_python_code to reduce context bloat — instead of loading 14 tool schemas, the LLM loads one.

Before (v0.1.x)

User: "Verify the derivative of x³ equals 3x² using verify_math"
Claude: Calls verify_math tool with expression="x^3", claimed_result="3*x^2", operation="derivative"

After (v0.2.0)

User: "Write a script to verify the derivative of x³ using execute_python_code"
Claude: Calls execute_python_code with a Python script that imports sympy and checks the result

Tool mapping

Use these QWED SDK imports in your execute_python_code scripts to replicate the previous tool behavior:
Deprecated toolReplacement SDK import
verify_mathfrom sympy import ... or from qwed_new.engines.math_engine import verify_math_expression
verify_logicfrom qwed_new.engines.logic_engine import verify_logic_statement
verify_codefrom qwed_new.guards.code_guard import CodeGuard
verify_sqlfrom qwed_new.guards.sql_guard import SQLGuard
verify_banking_compliancefrom qwed_finance import FinanceVerifier
verify_iso_20022from qwed_finance import ISOGuard
verify_commerce_transactionfrom qwed_ucp import UCPVerifier
verify_legal_deadlinefrom qwed_legal import DeadlineGuard
verify_legal_citationfrom qwed_legal import CitationGuard
verify_legal_liabilityfrom qwed_legal import LiabilityGuard
verify_legal_jurisdictionfrom qwed_legal import JurisdictionGuard
verify_legal_statutefrom qwed_legal import StatuteOfLimitationsGuard
verify_system_commandfrom qwed_sdk.guards.system_guard import SystemGuard
verify_file_pathfrom qwed_sdk.guards.system_guard import SystemGuard
verify_config_secretsfrom qwed_sdk.guards.config_guard import ConfigGuard
If you see an "Unknown tool" error in Claude Desktop, it means the LLM is trying to call a removed v0.1.x tool. Tell Claude: “The verify_* tools have been removed. Use execute_python_code to write and run a Python verification script.”

Deprecated tools (v0.1.x)

The following tools were available in v0.1.x and have been removed in v0.2.0. They are listed here for reference. Use execute_python_code with the corresponding SDK imports instead.

verify_math (deprecated)

Verified mathematical calculations using the SymPy symbolic mathematics engine.
ParameterTypeRequiredDescription
expressionstringYesMathematical expression (e.g., x^2, sin(x))
claimed_resultstringYesThe result to verify
operationenumNoOne of: derivative, integral, simplify, solve, evaluate

verify_logic (deprecated)

Verified logical arguments using the Z3 SMT solver.
ParameterTypeRequiredDescription
premisesarray[string]YesList of premise statements
conclusionstringYesThe conclusion to verify

verify_code (deprecated)

Checked code for security vulnerabilities using AST analysis.
ParameterTypeRequiredDescription
codestringYesCode to analyze
languageenumYesOne of: python, javascript, sql

verify_sql (deprecated)

Detected SQL injection vulnerabilities and validated queries.
ParameterTypeRequiredDescription
querystringYesSQL query to verify
allowed_tablesarray[string]NoWhitelist of allowed table names

verify_banking_compliance (deprecated)

Verified banking logic using QWED Finance Guard.
ParameterTypeRequiredDescription
scenariostringYesBanking scenario description
llm_outputstringYesThe LLM’s reasoning to verify

verify_commerce_transaction (deprecated)

Verified e-commerce transactions using QWED UCP.
ParameterTypeRequiredDescription
cart_jsonstringYesCart/checkout state as JSON string
Verified contract deadlines using LegalGuard.
ParameterTypeRequiredDescription
signing_datestringYesDate of signing (YYYY-MM-DD)
termstringYesDuration string
claimed_deadlinestringYesDeadline date to verify
Verified legal citation format and validity.
ParameterTypeRequiredDescription
citationstringYesLegal citation string
Verified liability cap calculations.
ParameterTypeRequiredDescription
contract_valuenumberYesTotal contract value
cap_percentagenumberYesCap percentage
claimed_capnumberYesCalculated cap amount

verify_system_command (deprecated)

Verified shell commands for security risks.
ParameterTypeRequiredDescription
commandstringYesShell command to check

verify_file_path (deprecated)

Verified file paths are within allowed sandbox directories.
ParameterTypeRequiredDescription
filepathstringYesPath to verify
allowed_pathsarray[string]NoWhitelist of allowed dirs

verify_config_secrets (deprecated)

Scanned configuration JSON for exposed secrets.
ParameterTypeRequiredDescription
config_jsonstringYesConfiguration data as JSON string

AIBOMGenerator (observability)

Generate an AI Bill of Materials (AI-BOM) manifest for visibility into your agent supply chain. This is useful for AI-SPM compliance auditing — tracking which models, verification engines, and MCP tools were used in a given session.

Description

The AIBOMGenerator produces a JSON manifest listing all components involved in an AI pipeline run. Each manifest includes a deterministic manifest_hash (SHA-256) so you can verify that two runs used the same component stack.

Usage

from qwed_mcp.observability.aibom import AIBOMGenerator

generator = AIBOMGenerator()

bom = generator.generate_manifest(
    llm_model="gpt-4o",
    qwed_engines_used=["qwed_tax.TaxVerifier", "qwed_legal.FairnessGuard"],
    mcp_tools_used=["execute_python_code"]
)

print(bom["compliance"])      # "QWED_AI_SPM_v1"
print(bom["manifest_hash"])   # deterministic SHA-256 hash
print(bom["components"])
# {
#   "models": [{"name": "gpt-4o", "type": "generator"}],
#   "verification_engines": [
#     {"name": "qwed_tax.TaxVerifier", "type": "qwed_deterministic"},
#     {"name": "qwed_legal.FairnessGuard", "type": "qwed_deterministic"}
#   ],
#   "mcp_tools": [
#     {"name": "execute_python_code", "type": "action_execution"}
#   ]
# }

Parameters

ParameterTypeRequiredDefaultDescription
llm_modelstrYes-Name of the LLM model used (e.g., "gpt-4o", "claude-3-opus")
qwed_engines_usedlist[str]No[]QWED verification engines used in this pipeline
mcp_tools_usedlist[str]No[]MCP tools invoked during this session

Manifest fields

FieldTypeDescription
timestampstringISO 8601 UTC timestamp of generation
components.modelsarrayLLM models used (type: "generator")
components.verification_enginesarrayQWED engines used (type: "qwed_deterministic")
components.mcp_toolsarrayMCP tools used (type: "action_execution")
compliancestringAlways "QWED_AI_SPM_v1"
manifest_hashstringSHA-256 hash of the manifest (excluding timestamp)
The manifest_hash is deterministic for identical inputs — the timestamp is excluded from the hash computation so that two manifests with the same components always produce the same hash.

SkillProvenanceGuard (security)

Verify MCP skill manifests before allowing dynamic tool loading. Protects against skill marketplace poisoning attacks where malicious agents upload trojanized skills to registries and inflate download counts.

Description

SkillProvenanceGuard performs deterministic provenance verification on skill manifests. When the QWED_SKILL_MANIFEST environment variable points to a JSON manifest file, the MCP server validates it at startup and refuses to start if verification fails. You can also use SkillProvenanceGuard directly in your own code to vet skills before loading them.

Usage

from qwed_mcp.security import SkillProvenanceGuard

guard = SkillProvenanceGuard()

result = guard.verify_skill(manifest={
    "name": "my-skill",
    "version": "1.0.0",
    "source_url": "https://github.com/org/skill",
    "registry": "github.com",
    "digest": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    "download_count": 150,
})

print(result["verified"])   # True
print(result["status"])     # "TRUSTED"
print(result["risk_level"]) # "none"

Constructor parameters

trusted_registries
set[str] | None
default:"None"
Strict allowlist of registry domains. When set, only skills from these registries are accepted. When None, the default blocklist is used instead.
trusted_domains
set[str] | None
default:"None"
Additional source URL domains to trust, merged with the built-in trusted list (github.com, gitlab.com, bitbucket.org, pypi.org, npmjs.com, qwedai.com).
require_digest
bool
default:"True"
Whether to enforce cryptographic digest presence in the manifest.

Manifest fields

FieldTypeRequiredDescription
namestrYesSkill name
versionstrYesSkill version
source_urlstrYesSource repository URL (must be HTTPS and from a trusted domain)
registrystrYesRegistry domain the skill was loaded from
digeststrYes (configurable)Cryptographic digest in algorithm:hex_digest format. Supported algorithms: sha256, sha384, sha512
download_countintNoNumber of downloads (used for anomaly detection)

Verification checks

The guard runs five checks on every manifest:
CheckDescription
Required fieldsname and version must be present and non-empty
Registry validationBlocks known untrusted registries (clawdhub.com, moltbot.io, skillhub.ai, agentstore.dev, llm-tools.net). When trusted_registries is set, acts as an allowlist instead
Source URL validationDomain must be in the trusted list; scheme must be HTTPS
Digest validationMust follow algorithm:hex_digest format with a supported algorithm and correct hex length
Download anomaly detectionFlags counts below 10 (possibly planted) or counts divisible by 1000 (possible bot inflation)
Additionally, manifest values (excluding metadata fields like name, description, source_url) are scanned for suspicious code patterns such as eval(), exec(), os.system(), and credential access attempts.

Response format

FieldTypeDescription
verifiedboolTrue if all checks pass
statusstr"TRUSTED" or "BLOCKED"
skill_namestrName from the manifest
risk_levelstr"none", "medium", or "high"
findingslist[str]All security findings
messagestrHuman-readable summary

Server-level validation

When the QWED_SKILL_MANIFEST environment variable is set, the MCP server validates the manifest at startup:
QWED_SKILL_MANIFEST=/path/to/skill-manifest.json qwed-mcp
If validation fails, the server logs the error and exits immediately. This prevents poisoned skills from being loaded into the MCP pipeline.
Skills from registries like clawdhub.com and moltbot.io are blocked by default due to insufficient vetting. If you need to load skills from a custom registry, use the trusted_registries parameter to set an explicit allowlist.

Error handling

All tool responses include stdout, stderr, and a return code summary. A non-zero return code indicates the script raised an exception or exited with an error.

Common errors

ErrorCauseSolution
Code execution is disabledQWED_MCP_TRUSTED_CODE_EXECUTION not setServer admin sets env var to true
No code providedEmpty code parameterProvide Python code in the code field
Execution timed out after 30.0 secondsScript exceeded synchronous time limitOptimize the script, break into smaller steps, or use background=true
ModuleNotFoundError in stderrMissing QWED SDK packageInstall the required package (e.g., pip install qwed-legal)