dangerzone
Click on "Deploy 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., "@dangerzoneCreate a Python tool that squares a number and test it with 7."
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.
dangerzone-mcp
A Python example of a self-modifying MCP server, built on the official MCP Python SDK. The agent connected to it can write a new tool, call it, fix it, and find it still there in the next session.
The server has three permanent tools: add_tool, edit_tool, and
remove_tool. Everything else in the catalog is Python that arrived at
runtime, usually written by the agent, saved in a JSON file in your project.
The name is a reminder that this runs model-written Python on your machine with your permissions. Read Trust before pointing it at anything you care about.
What it looks like

Register the server, then ask for a tool:
Use dangerzone to create a tool that squares a number. Call it with 7, then edit it to cube numbers and call it again.
The agent calls add_tool with Python source and an input schema. The server
saves the definition and notifies the client that its tool list changed. Calling
square with 7 returns 49; after edit_tool changes it to cube numbers, the same
call returns 343. Restarting the server restores the edited tool. remove_tool
takes it out of the catalog when it is no longer needed.
Each call validates its arguments and runs the Python code in a fresh worker,
with a 30-second timeout by default (--timeout SECONDS). Failures return tool
errors so the session can continue.
Related MCP server: JIT Tool Synthesis
Register
Install uv and Git, then clone the repository and read it. The server runs on your machine with your permissions, and there is no install path that skips that step on purpose.
git clone https://github.com/khuber/dangerzone-mcp.git
cd dangerzone-mcp && uv syncClaude Code
From the checkout:
claude mcp add --transport stdio --scope user dangerzone -- \
uv run --project "$PWD" dangerzone-mcpThis makes the server available across your projects. Run /mcp in Claude Code
to check the connection. Each project keeps its own catalog as described under
Persistence. Updating is a git pull in the checkout followed
by a reconnect; nothing changes until you do that.
Other MCP clients
For clients that accept mcpServers JSON and refresh tools after change
notifications, replace the path with your checkout:
{
"mcpServers": {
"dangerzone": {
"command": "uv",
"args": [
"run",
"--project", "/absolute/path/to/dangerzone-mcp",
"dangerzone-mcp"
]
}
}
}See client compatibility for the Codex limitation. The setup guide covers registration scopes, server options, updates, and troubleshooting.
Persistence
Tools survive restarts in a project-local dangerzone.tools.json. The server
uses the containing Git root, or the starting directory outside Git. Clients
start it in the project directory; --project-dir PATH overrides the starting
point. Add --no-persist to the server command to keep tools in memory for one
process.
Keep personal catalogs out of Git, or deliberately commit reviewed tools to share them. See the catalog reference for the file format, recovery behavior, and ignore entries.
Trust
Workers are process separation, not a sandbox. Tool code has the server user's file, network, and process access. That is fine for tools I asked for on my own laptop and not fine for much else. To run code you do not trust, put the workers under a different OS user or in a container with the server package read-only.
Persistence adds a second consideration. A repository you clone can arrive
with a dangerzone.tools.json already in it, written by whoever committed it,
and the agent uses the tool descriptions in that file to decide what to call.
Treat a catalog you did not write the way you would treat a Makefile from a
stranger: read the source and the descriptions before enabling it, or start
the server with --no-persist so it never loads.
Client compatibility
The add-then-call workflow requires a client that refreshes its tool list after change notifications. Codex has a reported issue where tools added after initial discovery never become callable in the task, including in later turns: openai/codex#43642. Codex setup examples are omitted until this workflow is verified to work there.
For implementation details and limitations, see the reference. For development setup and checks, see the setup guide.
Built on the MCP Python SDK 2.2 against the 2026-07-28 spec. MIT licensed.
Available Tools
3 toolsadd_toolA
Add a new Python tool. Use edit_tool to change an existing tool. source must define main(arguments), sync or async, returning JSON. input_schema describes the arguments object using JSON Schema 2020-12. The add_tool, edit_tool and remove_tool built-ins are permanent. Code executes with the server user's OS permissions.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| source | Yes | ||
| description | Yes | ||
| input_schema | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | Yes | |
| status | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=false, so mutation is expected. The description adds meaningful behavioral context: source must define main(arguments), be sync or async, return JSON, and code executes with the server user's OS permissions. It also discloses that add_tool, edit_tool, and remove_tool are permanent built-ins.
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 three sentences with no filler. The core purpose is front-loaded, followed by the sibling distinction and then the key technical constraints, making it highly scannable.
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 tool-definition operation with four required parameters and a nested input_schema, the description covers the critical contract: function signature, sync/async support, return type, JSON Schema version, OS permissions, and built-in permanence. With an output schema present, return-value documentation is not needed. It lacks an explicit note about name uniqueness but is otherwise substantial.
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%, so the description must compensate. It does add essential semantics for source and input_schema: source must define main(arguments) and return JSON, and input_schema uses JSON Schema 2020-12. However, it provides no additional meaning for the name or description parameters beyond their schema constraints.
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 opens with a specific verb and resource: 'Add a new Python tool.' It clearly distinguishes itself from siblings by explicitly saying 'Use edit_tool to change an existing tool,' so an agent can tell add_tool apart from edit_tool and remove_tool.
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 gives explicit guidance: use this tool to add a new tool, and use edit_tool to change an existing one. It also notes that built-in tools are permanent, which warns against attempting to remove or edit them.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
edit_toolADestructiveIdempotent
Replace an existing custom tool's description, input_schema, and Python source. Supply all fields; the name identifies the tool. Invalid edits leave the old tool intact. The add_tool, edit_tool and remove_tool built-ins cannot be edited.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| source | Yes | ||
| description | Yes | ||
| input_schema | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | Yes | |
| status | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true, and the description adds a real behavioral guarantee: 'Invalid edits leave the old tool intact,' implying atomic replacement. It also discloses that the management built-ins cannot be edited, which is beyond the schema and helps prevent failed calls. There is no contradiction with the annotations.
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 three sentences, front-loaded with the action and followed by the key caveats. It contains no filler and keeps the important guarantees (atomic invalid edits, protected built-ins) compactly grouped.
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 mutation tool with four required parameters and a nested object, the description covers the core replace semantics and failure atomicity, and the presence of an output schema reduces the need to explain return values. It still leaves gaps around the exact form of `input_schema` and what constitutes a 'valid' edit versus an invalid one, as well as what happens if the named tool does not exist. Given the tool's complexity, these gaps prevent a higher score.
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?
With 0% schema description coverage, the description must work harder. It connects three parameters to the operation ('description, input_schema, and Python source') and clarifies that `name` identifies the tool and all fields are required ('Supply all fields'). It does not, however, explain the expected structure of `input_schema` or the Python source format, so a meaningful parameter burden remains.
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 opens with 'Replace an existing custom tool's description, input_schema, and Python source,' a specific verb-plus-resource statement that names exactly what changes. It also states the name's identifying role and explicitly notes the built-in tools it cannot touch, which differentiates it from add_tool and remove_tool.
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 clearly scopes the tool to existing custom tools ('Replace an existing custom tool's...'), giving the agent a context for when to invoke it, and explicitly excludes the built-ins add_tool, edit_tool, and remove_tool from being edited. It does not, however, name add_tool or remove_tool as alternatives for create/delete cases, so the guidance is mostly contextual rather than a full when/when-not matrix.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_toolADestructive
Remove a custom tool. The add_tool, edit_tool and remove_tool built-ins can never be removed.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | Yes | |
| status | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, so the agent knows this is a destructive operation. The description adds the important behavioral constraint that built-in tools cannot be removed, which is valuable context beyond the annotations. However, it doesn't disclose what happens if the tool doesn't exist or whether removal is reversible.
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 that states the core action and the key constraint. It is front-loaded with the verb and resource, and every word earns its place. No fluff or 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?
For a simple one-parameter destructive tool, the description plus annotations cover the essential context: what it does, what it cannot remove, and that it is destructive. The output schema exists, so return values are presumably documented there. The only minor gap is lack of error behavior (e.g., nonexistent tool), but this is not critical for a simple removal tool.
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%, so the description carries the burden for parameter semantics. The description mentions 'custom tool' and the schema says 'The exact name of a custom tool to remove,' which together clarify that the 'name' parameter must be the exact name of a custom tool. However, the description itself doesn't add much beyond the schema's own description, and the schema's description is the primary source of parameter meaning.
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 action ('Remove a custom tool') and identifies the resource being acted upon. It also distinguishes itself from siblings by noting that built-in tools (add_tool, edit_tool, remove_tool) are protected from removal, which helps an agent understand the tool's scope and limitations.
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 when to use this tool (to remove a custom tool) and explicitly states an exclusion: built-in tools can never be removed. It doesn't explicitly name alternatives, but the sibling list (add_tool, edit_tool) makes the context clear. The protected built-ins note serves as a when-not-to-use guideline.
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.
3 tool updates
v0.1.0- First observed
add_tool - First observed
edit_tool - First observed
remove_tool
TDQS
Scored across 3 tools
Each tool targets a distinct lifecycle stage: add_tool creates, edit_tool modifies an existing tool, and remove_tool deletes one. There is no realistic overlap or ambiguity between these operations.
All three tool names follow the same verb_noun pattern in lowercase snake_case: add_tool, edit_tool, remove_tool. The naming is perfectly consistent and immediately indicates each tool's purpose.
Three tools is minimal but exactly right for a self-modifying tool server: create, update, and delete. There is no unnecessary duplication or bloat.
The core add/edit/remove lifecycle is covered, and tool discovery is available through MCP's normal tool-listing mechanism. The only minor gap is that there is no way to retrieve a custom tool's Python source after it has been added, which can make edit_tool awkward if the source was not retained externally.
Maintenance
Related MCP Connectors
Persistent memory and knowledge management for AI agents with semantic search and 50+ tools.
Git-backed platform for skills, tools, and context for AI agents
- mcp-serverOAuthcom.make
Give your AI agents the tools to build, manage, and run automation workflows.
Shared memory for coding agents. Stop re-explaining your codebase every session.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI agents to programmatically create, manage, and execute independent Python workflow scripts with full CRUD operations, allowing AI to build and modify automation workflows themselves rather than just executing pre-built ones.62MIT
- FlicenseCqualityDmaintenanceEnables on-demand generation of TypeScript tools using an LLM with human-in-the-loop approval and safe sandboxed execution. It allows users to create and persist custom functionality through natural language requests.81-
- AlicenseAqualityDmaintenanceProvides persistent SQLite-based memory and unified tool abstraction for AI agents to support long-term context and complex tool chaining. It enables automated code analysis, file operations, and environment discovery through a standardized interface.51MIT
- AlicenseAqualityDmaintenanceEnables AI agents to execute Python, TypeScript, and JavaScript code in persistent Jupyter kernels with stateful variables and imports across interactions.74MIT