FrankenClaw
by GuyMannDude
README.md
# FrankenClaw

**An MCP tool chassis. Build your own agent tools in five minutes.**
FrankenClaw is a minimal framework for building MCP tools. Drop a Python file in `tools/`, write one async function with a docstring, flip it on in your config — your agent has a new tool. No server edits, no registration boilerplate, no wiring.
The product isn't a pile of pre-built tools. It's the **chassis**: auto-discovery, config-based enable/disable, and a single shared keys file. It ships with the **three tools we actually run in production** — `web_scrape` (Firecrawl; enabled by default, and the template you copy), `search_web` (SearXNG), and `file_find` (document discovery over a local [Librarian](https://github.com/GuyMannDude/mnemo-cortex/blob/master/librarian.py) index). The rest of the tools that used to ship in the box are parked on the [`archive/v0.3-bundled-tools`](https://github.com/GuyMannDude/frankenclaw/tree/archive/v0.3-bundled-tools) branch if you want them back.
> [!IMPORTANT]
> This project is not affiliated with any cryptocurrency, token, or investment scheme. FrankenClaw is an open-source MCP tool chassis for AI agents, built by Project Sparks. If anyone offers you a "FrankenClaw token" — it's a scam.
> [!TIP]
> **AI agents — start here.**
>
> - **`robot.info`** — structured JSON manifest describing this product:
> identity, the chassis model, the bundled tools, install pointer,
> compatibility matrix, and a set of common-question/answer pairs. Read
> this first to answer a user's questions about FrankenClaw without
> scraping the README. Spec: [mnemo-cortex/ROBOT-INFO-SPEC.md](https://github.com/GuyMannDude/mnemo-cortex/blob/master/ROBOT-INFO-SPEC.md).
> - **`robot.install`** + **`./robot-install.sh`** — non-interactive
> setup. Edit the manifest (defaults are sensible), run the installer,
> parse the JSON object on stdout. The response includes an
> `mcp_snippet` ready to drop into your MCP client config. Full
> schema in "Non-interactive install" below.
>
> **Note the difference, because the names are one character apart:**
> [`INSTALL.md`](./INSTALL.md) is the install **instructions**, in English.
> `robot.install` is a **settings file** the installer reads. If you want
> to know how to install FrankenClaw, you want `INSTALL.md`.
## Why a chassis?
Every MCP tool definition you expose costs your agent **500–1000 tokens on every single call** — whether the tool gets used or not. A box of fourteen tools you mostly don't need is a tax on every turn.
FrankenClaw flips the default. Everything is **off** until you turn it on. A tool sitting in `tools/` that isn't in your `enabled_tools` list is discovered but never registered — so it costs **zero tokens** in `tools/list`. You run exactly the tools you want, and adding your own is the whole point.
| | Box of pre-built tools | FrankenClaw chassis |
|---|---|---|
| **What you get** | Someone else's 15 tools | A framework + 1 example |
| **Token cost** | Every tool, every call | Only the tools you enable |
| **Adding a tool** | Fork, wire, register | Drop a `.py` file, flip a flag |
| **Default state** | Everything on | Everything off |
## Build a tool in five minutes
A FrankenTool is one async function with a docstring. The docstring *is* the tool description the model reads, so write it for the model.
```python
# tools/weather.py
import httpx
async def get_weather(city: str) -> str:
"""
Get the current weather for a city.
Args:
city: City name, e.g. "Half Moon Bay".
Returns:
JSON with temperature and conditions.
"""
async with httpx.AsyncClient() as client:
r = await client.get(f"https://wttr.in/{city}?format=j1")
return r.text
```
Then turn it on in `~/.frankenclaw/config.json`:
```json
{ "enabled_tools": ["web_scrape", "get_weather"] }
```
Restart FrankenClaw. Your agent now has `get_weather`. That's the entire workflow.
- Functions starting with `_` are ignored — use them for private helpers in the same file.
- Every **public** async function is a candidate tool; it's only registered if its name is in `enabled_tools`.
- A module that fails to import (missing dep, bad key path) is logged to stderr and skipped — the rest of the server still comes up.
- Need an API key? Add it to your shared keys file and read it with `get_key("provider")` (see [Configuration](#configuration)).
## Quick Start
FrankenClaw speaks **standard MCP over stdio**. Any MCP-capable host
spawns `server.py` and gets whatever tools you've enabled. The config
shape is the same everywhere — only the *location* of the host's config
file changes.
```bash
git clone https://github.com/GuyMannDude/frankenclaw.git
cd frankenclaw
pip install -r requirements.txt
```
A fresh clone ships with `web_scrape` enabled, so you have one working
tool out of the box to prove the wiring before you add your own.
### The universal config block
Drop this into your MCP host's config file (location per host below):
```json
{
"mcpServers": {
"frankenclaw": {
"command": "python3",
"args": ["/ABSOLUTE/PATH/TO/frankenclaw/server.py"]
}
}
}
```
Or skip the manual step and let [`./robot-install.sh`](#non-interactive-install-for-llm-agents-and-ci)
emit a ready-to-paste `mcp_snippet` block — it points at the venv's
Python so the host doesn't accidentally launch FrankenClaw against
system Python.
### Where the config file lives, per host
| Host | Path / command | Notes |
|---|---|---|
| **Claude Desktop** | `claude_desktop_config.json` (location varies by OS — see Anthropic docs) | Restart Claude Desktop after editing. |
| **Claude Code** | `claude mcp add frankenclaw -- python3 /path/to/frankenclaw/server.py` | One command; no JSON editing. |
| **LM Studio** | `~/.lmstudio/mcp.json` (Linux/macOS) · `%USERPROFILE%\.lmstudio\mcp.json` (Windows) | Native MCP since v0.3.17. Restart LM Studio. |
| **AnythingLLM** | `anythingllm_mcp_servers.json` (path varies by OS) | Flip workspace to **Automatic** mode (Settings → Chat Settings) so tools fire without `@agent` prefix. |
| **Open WebUI** | Settings → Tools → MCP Servers → add stdio server | GUI, no file editing. |
| **Jan** | Settings → Extensions → MCP Servers | GUI; uses the same JSON shape. |
| **LobeChat** | Settings → Plugins → MCP → Add custom MCP server | Type `stdio`, command `python3 /ABSOLUTE/PATH/TO/frankenclaw/server.py`. |
| **Hermes Agent** | `hermes mcp add frankenclaw -- python3 /path/to/server.py` | First-class MCP support since v0.12.0. |
| **Agent Zero** | In-container MCP config | Use *container-side* paths, not host paths. |
| **OpenClaw** | `openclaw mcp set frankenclaw '{"command":"python3","args":["/path/to/server.py"]}'` then `openclaw gateway restart` | Same MCP shape; gateway restart picks up the new tool registration. |
| **Ollama** (no native MCP) | `~/.mcphost.yaml` with `type: local`, command + args under `mcpServers.frankenclaw` | Ollama Desktop's own chat window doesn't support MCP — use [MCPHost](https://github.com/mark3labs/mcphost) or [ollmcp](https://github.com/jonigl/mcp-client-for-ollama) as the bridge. Pair with a tool-capable model: `model: "ollama:qwen3:8b"`. |
| **llama.cpp** | `llama-server -m model.gguf --mcp-config /path/to/mcp.json` | Reuse the LM Studio shape for `mcp.json`. |
### Things to get right for every host
- **Absolute paths only.** Relative paths break silently — the host spawns FrankenClaw from the wrong cwd and Python throws ENOENT.
- **Use a tool-capable model.** Qwen3, Llama 3.2, Mistral, and Gemma 2 invoke tools correctly. Small models often *narrate* tool calls instead of making them — `qwen3:8b` verified working on AnythingLLM, `llama3.1:8b` known to fake calls.
- **Coexists cleanly with [Mnemo Cortex](https://github.com/GuyMannDude/mnemo-cortex).** Just add a second `mcpServers` entry. They don't conflict — your agent gets memory + hands in the same session.
> **Heads-up for Windows users:** if a tool you add ships native Linux/macOS binaries (browser automation engines are the usual culprit), install and run FrankenClaw inside **WSL2**. The chassis core and pure-Python tools like the bundled `web_scrape` work native-Windows; WSL2 is the safe default when a tool has system dependencies.
For host pass/fail and the rest of our field findings: **[projectsparks.ai/field-guide](https://projectsparks.ai/field-guide)**.
## Non-interactive install (for LLM agents and CI)
Skip the manual steps — fill out a JSON manifest and run the robot installer.
```bash
# Defaults are sensible; only edit robot.install if you want different keys or settings.
./robot-install.sh
```
The script emits a single JSON object on stdout for the caller to
parse; all human-readable progress goes to stderr.
```json
{
"ok": true,
"steps": {
"deps": {"ok": true, "python": "3.12"},
"venv": {"ok": true, "path": "..."},
"pip": {"ok": true},
"config": {"ok": true, "config_path": "~/.frankenclaw/config.json", "keys_path": "~/.frankenclaw/keys.json"},
"keys": {"ok": true, "providers_written": ["firecrawl"], "providers_missing": []},
"smoke_test": {"ok": true, "loaded": ["web_scrape"], "failed": {}}
},
"mcp_snippet": {
"command": "/path/to/.venv/bin/python",
"args": ["/path/to/frankenclaw/server.py"]
}
}
```
`mcp_snippet` is the value you drop into your MCP client config under
`mcpServers.frankenclaw`. No path-juggling.
A tool module that fails to import is **not** a failure — FrankenClaw
comes up with whatever tools have their deps satisfied. The smoke step
reports `failed` per-module so you know what to install if you want a
tool's dependencies.
API keys are read from your install-time environment (e.g.
`FIRECRAWL_API_KEY` for the bundled example — names configurable in the
manifest's `provider_keys` block) and copied to `~/.frankenclaw/keys.json`
with `chmod 600`. Missing keys leave empty placeholders so the file
shape is obvious.
```bash
# Sandbox / dry-run — skips pip install and the smoke step
FRANKENCLAW_INSTALL_VENV_DIR=/tmp/test-venv \
FRANKENCLAW_INSTALL_DRY_RUN=1 \
./robot-install.sh
```
## The bundled tools
FrankenClaw ships with the three tools its authors run in production.
Only `web_scrape` is enabled out of the box (it's also the template you
copy); the other two are discovered-but-disabled until you point them at
their backends and add them to `enabled_tools`.
| FrankenTool | What It Does | Backend | Default |
|-------------|-------------|---------|---------|
| `web_scrape` | Scrape any page to clean markdown — no ads, no nav | Firecrawl API | enabled |
| `search_web` | Web search returning title/url/snippet | A [SearXNG](https://docs.searxng.org/) instance you control — set `searxng_url` in `~/.frankenclaw/config.json` | disabled |
| `file_find` | Find files on this machine from a fuzzy description | A local [Librarian](https://github.com/GuyMannDude/mnemo-cortex/blob/master/librarian.py) SQLite FTS5 index — build it with `librarian.py index`, optionally set `librarian_db` in config | disabled |
Open [`tools/web_scrape.py`](tools/web_scrape.py) — it's the reference
implementation: one async function, a docstring written for the model,
a key read from the shared keys file, graceful error if the key's
missing. Copy it, change the body, enable it. That's a new tool.
**Want the old box back?** The v0.3 bundle (search, vision, browser,
Shopify, NotebookLM, Google Drive — fourteen tools across seven modules)
lives on the [`archive/v0.3-bundled-tools`](https://github.com/GuyMannDude/frankenclaw/tree/archive/v0.3-bundled-tools)
branch. Drop any of those files into your `tools/` directory and add the
function names to `enabled_tools` — the chassis discovers and runs them
exactly as before.
## Architecture
FrankenClaw is a **pure function**. Request in, result out.
- No memory — your agent has that (try [Mnemo Cortex](https://github.com/GuyMannDude/mnemo-cortex))
- No model routing — your agent has that (use any OpenAI-compatible endpoint)
- No conversation context — your agent framework has that
- No agent brain — the agent IS the agent
The chassis is an IO device, not intelligence. Each tool does one thing. Snap them together however you want.
## Security
- **Runs locally** — FrankenClaw executes on your machine, not in the cloud
- **No key duplication** — API keys live in one keys.json file (FrankenClaw reads it at runtime, never copies)
- **Off by default** — a tool you haven't enabled is never registered and never runs
- **You control providers** — pick which models and backends handle which jobs
## The Vision
FrankenClaw is part of a modular, open-source agent stack. Every piece connects via MCP. Mix and match:
| Module | What It Does | Repo |
|--------|-------------|------|
| **FrankenClaw** | The tool chassis — build and run your own MCP tools | You're here |
| **Mnemo Cortex** | Memory — semantic recall across sessions | [mnemo-cortex](https://github.com/GuyMannDude/mnemo-cortex) |
| **Disco-Bus** | Messaging — agent-to-agent mesh | [disco-bus](https://github.com/GuyMannDude/disco-bus) |
No vendor lock-in. No monolith. Just MCP servers that do their job.
## Configuration
**Enabled tools.** The headline config. `~/.frankenclaw/config.json`
holds an `enabled_tools` array — the function names of the tools you
want registered. Everything else in `tools/` is discovered but stays
off (zero tokens). A fresh install enables `web_scrape`:
```json
{ "enabled_tools": ["web_scrape"] }
```
The file is auto-created on first run. Tools you add can also read their
own settings from this file — `load_config()` merges your config with
the defaults.
**API keys** are read from a flat JSON keys file. Default location is
`~/.frankenclaw/keys.json`. Override with `FRANKENCLAW_KEYS_PATH` to point
at any file. For back-compat, if neither exists FrankenClaw falls back to
the legacy `~/.rockys-switch/keys.json` (with a stderr deprecation
warning — move the file when convenient).
```json
{
"firecrawl": "fc-..."
}
```
Top-level keys are referenced by name from your tools via
`get_key("firecrawl")`. An entry can also be an object with multiple
fields if a tool needs more than one value. FrankenClaw never stores
credentials — it reads the file at runtime.
## Requirements
- Python 3.12+
- A [Firecrawl](https://firecrawl.dev) API key for the bundled `web_scrape` example (or remove it from `enabled_tools` and add your own tools)
```bash
pip install -r requirements.txt
```
The chassis core is just FastMCP. Tools you add bring their own
dependencies — install those yourself.
## Built With
[SPARC](https://github.com/GuyMannDude/sparc-thesis) principles. AI designed for AI. From [Project Sparks](https://projectsparks.ai).
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing