nano-vm-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@nano-vm-mcprun a program to fetch weather data"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
What nano-vm-mcp Is
nano-vm-mcp is an MCP gateway that turns the Model Context Protocol into a governance-bound execution environment. It wraps the llm-nano-vm execution kernel and exposes it to any MCP client — Claude Desktop, Claude Code, custom agents, or API callers — through stdio or SSE transport.
Most MCP servers expose stateless tools. nano-vm-mcp exposes stateful, governed, auditable workflows.
Capability | Typical MCP Server | nano-vm-mcp |
Tool execution | ✅ | ✅ |
Stateful workflows | ❌ | ✅ |
Deterministic FSM | ❌ | ✅ |
Replayable traces | ❌ | ✅ |
Suspend / resume | ❌ | ✅ |
LLM output enforcement | ❌ | ✅ |
Capability enforcement (double gate) | ❌ | ✅ |
Append-only audit trail | ❌ | ✅ |
GDPR tombstoning | ❌ | ✅ |
Evaluator blindness by design | ❌ | ✅ |
Inter-session idempotency | ❌ | ✅ |
Core invariant: the gateway does not own execution logic — the FSM kernel does.
δ(S, E) → S'
S — current execution state
E — validated event
S' — next deterministic stateRelated MCP server: agent-orchestrator
Architecture
MCP Client / Claude Code
↓
nano-vm-mcp (Gateway) ← decides how execution is allowed to proceed
→ GovernedRunProgramHandler ← PolicySnapshot, idempotency_key, CapabilityRef
→ llm-nano-vm (Kernel) ← deterministic FSM, ASTEngine, ProjectionLayer
→ GovernanceEnvelope store ← SQLite WAL, append-only audit log
→ idempotency_keys store ← idempotent re-execution across restarts
↓
deterministic FSM ← guarantees correctness
↓
GovernanceEnvelope ← proves it happenedStrict isolation: the gateway never touches execution logic. The kernel never touches persistence or policy. Each layer has a single responsibility and cannot cross the boundary.
Install
pip install nano-vm-mcp
pip install 'nano-vm-mcp[litellm]' # for llm stepsMCP Tools
Tool | Description |
| Execute a |
| Retrieve full |
| List saved programs ( |
| Retrieve saved |
| Delete a program and all its traces |
Quick Start
stdio — Claude Desktop / local MCP client
nano-vm-mcp --transport stdioclaude_desktop_config.json or .mcp.json:
{
"mcpServers": {
"nano-vm-mcp": {
"command": "nano-vm-mcp",
"args": ["--transport", "stdio"]
}
}
}SSE — VPS / remote clients
NANO_VM_MCP_API_KEY=your-secret-token nano-vm-mcp --transport sse --port 8080MCP client URL: http://<host>:8080/sse
Auth header: Authorization: Bearer your-secret-token
Docker Compose
services:
nano-vm-mcp:
image: ghcr.io/ale007xd/nano-vm-mcp:latest
ports:
- "8080:8080"
volumes:
- ./data:/data
environment:
NANO_VM_MCP_DB: /data/nano_vm_mcp.db
NANO_VM_MCP_PORT: 8080
NANO_VM_MCP_API_KEY: your-secret-token
command: ["nano-vm-mcp", "--transport", "sse"]Claude Code Dynamic Workflows
Claude Code decides what to do. nano-vm-mcp decides how execution is allowed to proceed.
Claude Code Dynamic Workflows give you parallel subagents and dynamic orchestration. They don't give you deterministic step execution, replayable audit trails per step, or idempotent re-execution across restarts. nano-vm-mcp closes exactly that gap.
Claude Code ← decides what to do
↓
nano-vm-mcp ← enforces how execution proceeds
↓
deterministic FSM ← guarantees correctness
↓
GovernanceEnvelope ← proves it happenedClaude Code Dynamic Workflows | + nano-vm-mcp | |
Parallel subagents | ✅ | ✅ |
Dynamic orchestration | ✅ | ✅ |
Deterministic step execution | ❌ | ✅ |
Replayable audit trail per step | ❌ | ✅ |
LLM output enforcement | ❌ | ✅ |
Inter-session idempotency | ❌ | ✅ |
GDPR tombstoning | ❌ | ✅ |
Evaluator blindness | ❌ | ✅ |
Use this combination when a workflow subagent must execute a governed process — payment pipeline, approval chain, compliance check — where correctness and auditability matter beyond the LLM layer.
Example: governed payment step inside a Claude Code workflow
# Claude Code subagent calls this tool directly
result = await session.call_tool(
"run_program",
{
"program": {
"name": "payment_pipeline",
"steps": [
{"id": "validate", "type": "tool", "tool": "validate_amount"},
{"id": "reserve", "type": "tool", "tool": "reserve_funds"},
{"id": "capture", "type": "tool", "tool": "capture_payment"},
{"id": "receipt", "type": "tool", "tool": "send_receipt",
"is_terminal": True},
]
},
"idempotency_key": "order-abc-123",
}
)
# Returns: trace_id, status, step count, cost
# Every step: GovernanceEnvelope in SQLite — tamper-evident, append-onlyThe subagent cannot skip steps, reorder execution, or bypass capability checks — regardless of what the LLM decides at the orchestration layer.
Retrieve the audit trail
trace = await session.call_tool("get_trace", {"trace_id": result["trace_id"]})
# Returns: per-step status, duration_ms, usage, state_snapshotsTraces persist across sessions in SQLite WAL. trace_id is UUID4-stable for OTel propagation.
Idempotency — Inter-session Re-execution Safety
Pass idempotency_key to run_program to guarantee that a program executes at most once per key, even across process restarts:
# First call — executes normally, result cached
result = await session.call_tool("run_program", {
"program": program,
"idempotency_key": "payment-order-xyz-001",
})
# Second call with same key — returns cached result immediately, no re-execution
result = await session.call_tool("run_program", {
"program": program,
"idempotency_key": "payment-order-xyz-001",
})Crash recovery: if the process crashes after program start but before completion (status=pending), the next call with the same key overwrites the pending entry and re-executes. Once the result is written as status=success, it is immutable for that key.
Note on "exactly-once": the FSM guarantees idempotent re-execution — the same key never triggers a second run after success. External side effects (payment capture, webhook delivery) are only as idempotent as the tools you register. This is the same contract Temporal and Cadence operate under.
Governance Layer
GovernanceEnvelope
Each successful execution step produces an immutable GovernanceEnvelope stored in the governance_envelopes table. Envelopes are written only on error=None — they form a tamper-evident, append-only audit trail of successful transitions only.
Field | Type | Description |
|
| Session / trace identifier |
|
| Step index within the execution |
|
| SHA-256 of the active |
|
| Merkle/delta hash of |
|
| Projected (sanitized) step output |
PolicySnapshot and CapabilityRef
PolicySnapshot is a frozen Pydantic model created once per session. It carries the set of allowed tool names and is hashed (SHA-256) before execution starts. Every GovernanceEnvelope records this hash — post-hoc modification of the policy is detectable.
from nano_vm.contracts import PolicySnapshot, CapabilityRef
policy = PolicySnapshot(
tool_capabilities={"reserve_funds", "capture_payment", "send_receipt"},
)
# policy.hash() → SHA-256 hex, stored in every GovernanceEnvelope.policy_hashCapabilityRef wraps sensitive values as opaque tokens (vault://secret/<id>) rather than storing raw plaintext in CanonicalState. The token is resolved JIT during tool execution and never written to the audit log.
ref = CapabilityRef(ref_id="card-4242", value="4242424242424242")
# Stored in state as: vault://secret/card-4242
# GovernanceEnvelope.payload contains the token, not the card numberGDPR Tombstoning
On a GDPR erasure event:
Target ref is tombstoned (
is_tombstone=True)All subsequent projections return
[REDACTED_TOMBSTONE]The
canonical_snapshot_hashchain remains valid — forensic auditability is preservedThe secret is permanently gone
vm.erase(ref_id="card-4242")
# Hash chain remains intact — the erasure itself is auditableExecution Traces
Every step writes a TRACE projection to the execution_traces table — a sanitized snapshot of state with sensitive values replaced by CapabilityRef tokens, protected by a unique index on (execution_id, step_index):
steps = store.get_trace_steps(execution_id="exec-abc-123")
# [
# {"step_index": 0, "step_id": "validate", "projected_json": "...", "canonical_hash": "..."},
# {"step_index": 1, "step_id": "reserve", "projected_json": "...", "canonical_hash": "..."},
# ]Evaluator Blindness by Design
Benchmark research across 10 frontier models found that every model changes behavior when it detects it's being monitored. The best model scored 84% on "acts the same whether watched or not."
The ProjectionLayer gives the LLM only a target=LLM projection of state. Governance metadata — GovernanceEnvelope, canonical_hash, policy_hash, retry counters — never reaches the prompt. The model cannot observe its own audit trail.
Evaluator blindness is structural, not configured. It is a consequence of the strict isolation between the kernel and gateway layers.
Determinism and LLM Steps
State determinism — the FSM kernel guarantees execution order, no step skipping, and reproducible trace structure regardless of LLM output. The graph of transitions is fixed at program definition time. This is unconditional.
Semantic determinism — the text produced by an LLM step may differ across runs even at temperature=0.0. nano-vm does not guarantee semantic determinism and does not try to.
These are orthogonal concerns. The runtime enforces state determinism; you control semantic determinism through prompt engineering and allowed_outputs.
LLM output enforcement at the runtime level
allowed_outputs (v0.8.0) validates the model's raw output against an explicit enum before it enters the FSM context. This isn't a prompt hint — it's a runtime gate.
{
"id": "classify",
"type": "llm",
"prompt": "Is this a valid refund request? Reply ONLY with: yes or no",
"output_key": "decision",
"allowed_outputs": ["yes", "no"], # runtime enforcement — not a prompt hint
"on_error": "skip", # output → "yes" (first element) on mismatch
}Security
ASTEngine — sandboxed condition evaluation
Conditions are evaluated by the ASTEngine — a deterministic sandboxed interpreter with no access to Python builtins, attribute access, or callable invocation. eval() is not used anywhere in the production execution path.
Rules for safe use:
Condition logic must be authored by you, not generated from untrusted input at runtime.
LLM output may appear as a value being tested (
'yes' in '$decision'), never as the condition expression itself.
Capability enforcement — double gate
Tool execution passes through two independent enforcement layers:
Layer | Mechanism |
| Verifies tool name against |
| Rejects any tool name not registered in the tool registry with |
Neither gate can be bypassed by LLM output.
SSE transport and auth
Set NANO_VM_MCP_API_KEY to enable bearer token authentication (secrets.compare_digest — timing-safe). If unset, a warning is logged and all requests are allowed — suitable for localhost only.
Do not expose the SSE endpoint to the public internet without NANO_VM_MCP_API_KEY set.
Configuration
Variable | Default | Description |
|
| SQLite WAL database path |
|
| SSE bind host |
|
| SSE bind port |
| (unset) | Bearer token for SSE auth |
| (unset) | LiteLLM model string for |
Endpoints
Path | Auth | Description |
| none | Liveness probe — always returns |
| bearer | SSE transport entry point |
| bearer | MCP message endpoint |
Performance
The FSM runtime introduces near-zero overhead. The bottleneck is always the LLM API or external I/O.
Sequential execution (single FSM instance): one step at a time per execution_id — deliberate design choice, makes traces deterministic and replayable.
Parallel execution across independent workflows: fan out across multiple execution_id instances. SQLite WAL handles concurrent writers without locking.
Benchmarks (v0.7.3, Mock adapter, QEMU/KVM · Intel Xeon E5-2697A v4 · 2 cores · Python 3.12)
Scenario | Mean TPS | p95 |
Refund pipeline (sequential) | 2,300/s | 0.66 ms |
MCP store round-trip | 3,000/s | 0.42 ms |
GovernanceEnvelope write | 1,300/s | 171 ms |
Parallel throughput ( | 436/s | 542 ms |
Replay equivalence | 1,300/s | 1.30 ms |
Long-horizon (30-step program) | 30/s | 3,606 ms |
Observability
trace.trace_id # UUID4 — stable for OTel propagation
trace.status # SUCCESS | FAILED | SUSPENDED | BUDGET_EXCEEDED | STALLED
trace.final_output
trace.steps # per-step: step_id, status, duration_ms, usage
trace.state_snapshots # list[(step_index, sha256_hex)]Traces are persisted to SQLite and retrievable by trace_id across sessions via get_trace.
Execution State Model
CREATED
↓
RUNNING ──── tool returns "PENDING" ──→ SUSPENDED
│ │
│ resume_with_program()
│ │
└──────────────────────────────────────────┘
│
├── no more steps ──→ SUCCESS
├── tool error (on_error=fail) ──→ FAILED
├── max_steps / max_tokens exceeded ──→ BUDGET_EXCEEDED
└── max_stalled_steps exceeded ──→ STALLEDTerminal states: SUCCESS, FAILED, BUDGET_EXCEEDED, STALLED. All are immutable.
Relationship to llm-nano-vm
Layer | Responsibility |
| Deterministic FSM execution, ASTEngine, ProjectionLayer, step lifecycle |
| MCP transport, persistence, governance, idempotency, capability enforcement |
The gateway never owns transition logic. The FSM kernel does.
The kernel is MIT-licensed, independently versioned on PyPI (llm-nano-vm), and fully documented. Either layer can be used standalone or replaced — the boundary between them is a stable Python interface.
Diagnostic Integration — Agent Debugger
#diagnostic-integration--agent-debugger
debug_trace is an opt-in MCP tool that sends a completed Trace to an external Agent Debugger service for automated failure diagnosis. It does not run by default — no token, no call.
Auto-diagnostic on FAILED: when a run_program execution ends with status=FAILED, GovernedRunProgramHandler automatically forwards the trace for diagnosis if AGENT_DEBUGGER_TOKEN is set. No extra call needed from the MCP client.
export AGENT_DEBUGGER_TOKEN=your-token
export AGENT_DEBUGGER_URL=https://agent-debugger-production.up.railway.appVariable | Default | Description |
| (unset) | Enables diagnostic calls; absent = no-op |
| (unset) | Agent Debugger service endpoint |
# Manual call — diagnose any stored trace on demand
result = await session.call_tool("debug_trace", {"trace_id": result["trace_id"]})
# Returns: failure classification + suggested root cause from Agent DebuggerWithout AGENT_DEBUGGER_TOKEN set: the diagnostic call is silently skipped — execution is never blocked by an unavailable or unconfigured debugger.
Contact & Support
Author: @ale007xd on Telegram · @ale007xd on X
USDT (TON): UQCakyytrEGBikOi3eYMpveGHXDB1-fd6lcuQC9VvKqMrI-9
License
Available Tools
5 toolsdelete_programC
Delete a saved program and all its traces.
| Name | Required | Description | Default |
|---|---|---|---|
| program_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Without annotations, the description must disclose behavioral traits, but it only mentions deletion of program and traces. It omits irreversibility, authorization needs, or cascading effects, which are critical for a destructive tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence, making it concise, but it lacks structure and important details, bordering on under-specification.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema and minimal annotations, the description is incomplete. It provides basic purpose but lacks usage context, behavioral detail, and parameter guidance.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description adds no meaning to the single parameter 'program_id' beyond its existence. The parameter is self-explanatory, but the description fails to compensate for the lack of schema documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Delete' and the resource 'saved program and all its traces,' distinguishing it from siblings like get_program and run_program.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool vs alternatives or any exclusions. The description lacks context on prerequisites or when deletion is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_programB
Retrieve a saved Program JSON by its program_id.
| Name | Required | Description | Default |
|---|---|---|---|
| program_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description implies a read operation ('Retrieve') but does not disclose any behavioral traits such as error handling or permissions; with no annotations, the burden is on the description, yet it remains minimal.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, concise sentence that front-loads the action and resource, but its brevity sacrifices valuable context like parameter details and usage guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple retrieval tool with no output schema, the description minimally covers the return type ('Program JSON'), but lacks details on edge cases or behavior, making it adequate but not thorough.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description adds no meaning to the program_id parameter beyond its name; with 0% schema description coverage, the description fails to compensate, leaving the parameter's semantics entirely implicit.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves a saved Program JSON by program_id, using a specific verb and resource, which distinguishes it from sibling tools like delete_program and list_programs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives like get_trace or list_programs is provided, leaving the agent without context for selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_traceA
Retrieve the full Trace JSON for a completed run by trace_id.
| Name | Required | Description | Default |
|---|---|---|---|
| trace_id | Yes | UUID returned by run_program. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description must disclose behavioral traits. It indicates a read operation but fails to mention what happens for invalid trace_ids, authentication needs, or limitations. The brevity leaves significant gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence of 12 words, perfectly concise and front-loaded. Every word earns its place with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description should explain return format. 'Full Trace JSON' is vague but adequate. Missing error details and more specific return info make it minimally complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with trace_id described as 'UUID returned by run_program.' The description adds context ('completed run'), which is helpful but minimal. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves the full Trace JSON for a completed run by trace_id. The verb 'Retrieve' and resource 'Trace JSON' are specific, and the tool is distinctly different from siblings like run_program, get_program, etc.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies use after a completed run and mentions trace_id from run_program, but it lacks explicit guidance on when to use versus alternatives, such as not using for running programs or error handling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_programsA
List all saved programs (id, name, created_at).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Since no annotations exist, the description bears full burden. It correctly indicates a read-only operation ('List') but does not disclose any pagination, limitation, or ordering behavior. For a zero-parameter tool, basic transparency is adequate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence that conveys the action, resource, and return fields without any extraneous words. Every word is necessary.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with no output schema, the description fully explains what the tool returns (id, name, created_at). No additional context is needed given the tool's simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% (no parameters), so baseline is 3. Description adds no parameter information, which is acceptable as there are none to document.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb 'List' and resource 'all saved programs', explicitly stating the fields returned (id, name, created_at). It clearly distinguishes from sibling tools like get_program (single) and run_program (execution).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use list_programs versus get_program or other siblings, nor any hints about prerequisites or alternatives. The description is purely functional.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_programA
Execute a nano-vm Program dict. Returns trace_id, status, step count, and cost. Optionally persists the program under a name.
| Name | Required | Description | Default |
|---|---|---|---|
| program | Yes | nano_vm.Program JSON (steps, budgets, etc.) | |
| save_as | No | Optional name to save the program for later reuse. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description partially discloses behavior: it performs execution, returns specific fields, and optionally saves. However, it omits details like side effects (other than save), permissions, idempotency, or potential errors.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, focused sentence that communicates core purpose and return fields. It is clear and front-loaded, though the return list could be better integrated (e.g., 'returns a result with...').
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description lists return fields but lacks details on their structure or format. For an execution tool with nested input, it provides sufficient high-level info but could be more complete regarding error cases and complex behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% (both parameters described). The tool description adds no new information beyond the schema’s own descriptions (e.g., 'nano_vm.Program JSON' and 'Optional name to save'). Baselines at 3 with no extra value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool executes a nano-vm Program and returns trace_id, status, step count, and cost. It distinguishes from sibling tools (delete, get, list, get_trace) by focusing on execution and optional persistence.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use vs alternatives or prerequisites. While sibling tools imply usage for execution, the description does not provide context for when not to use or any required setup.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Each tool targets a distinct action (delete, get, list, run, get trace) with no overlap. Descriptions clearly differentiate them.
All tools use consistent snake_case and verb_noun pattern: delete_program, get_program, get_trace, list_programs, run_program.
5 tools is well-scoped for a VM execution server, covering core operations without unnecessary bloat.
Lacks update functionality for programs and no way to list traces (only fetch by known ID). These gaps may hinder some workflows.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Zero-secret MCP gateway for AI agents: risk-scored, audited calls with human-in-the-loop approval.
Control plane for autonomous software labor. Agents claim objectives over MCP with audit trail.
Hosted MCP memory and agent control plane for durable conversations, jobs, and operations.
MCP gateway with runtime security policy, tool-call-level control, and audit of agent actions.
Related MCP Servers
- FlicenseAqualityBmaintenanceAn agent-native workflow MCP server that enables AI agents to execute text-defined, versionable workflows with checkpointing and state management.1017
- AlicenseNot gradedqualityBmaintenanceEnables multi-model leader-worker agent orchestration, workflow execution, and deterministic validation via structured MCP tools.16Apache 2.0
- AlicenseNot gradedqualityFmaintenanceOrchestrates persistent task graphs and enforces approval policies for MCP-driven agent workflows, coordinating with Agents Gateway for execution.MIT

evav-gatewayofficial
AlicenseNot gradedqualityBmaintenanceGoverned MCP gateway that lets AI agents call tools with policy enforcement, prompt-injection screening, a kill-switch, and tamper-evident signed audit logs.Apache 2.0
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/Ale007XD/nano-vm-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server