local-dev-loop
The fastest possible feedback loop: edit a Python tool, hit save, have Claude Desktop pick up the change on the next message - all without touching the Platos platform.
What’s in the box
examples/local-dev-loop/├── README.md├── pyproject.toml├── .env.example├── .gitignore├── tools.py # three toy @platools.tool() functions├── platools-tests.yaml # smoke tests└── claude_desktop_config.json # sample Claude Desktop server entryThis example intentionally keeps everything in a single tools.py file - no FastAPI host, no package layout, no platools.connect(). The whole point is to show how short the “decorate -> run -> call from an LLM” path really is.
The tools
tools.py defines three sample tools you can call from Claude Desktop or Cursor immediately:
echo(text)->str- no-auth sanity check. Confirms the transport is wired up.word_count(text)->dict[str, int]- returns{"words": N, "chars": M}. Deterministic, fast, useful for doctor + test smoke coverage.stop_watch(label)->dict[str, float]- starts / stops a named timer and returns the elapsed seconds. Demonstrates stateful tools (state lives in a module-level dict).
Running it
cd examples/local-dev-loop
# One-time setupcp .env.example .env # empty is fine - this example doesn't connect anywhereuv sync
# Ship gateuv run platools doctor tools
# Run the smoke tests (no platform needed)uv run platools test --module tools
# Launch the local MCP server over stdio - this is what Claude Desktop runsuv run platools serve --module tools --list # dry run: print tools and exituv run platools serve --module tools # real run: wait on stdin for JSON-RPCWiring Claude Desktop
Copy the sample config into your Claude Desktop config file:
{ "mcpServers": { "platools-local": { "command": "uv", "args": ["run", "--project", "/absolute/path/to/examples/local-dev-loop", "platools", "serve", "--module", "tools"], "cwd": "/absolute/path/to/examples/local-dev-loop" } }}Edit the absolute paths to match your machine, restart Claude Desktop, and the three tools appear in the tool picker. The --list dry run is the fastest way to sanity-check the path before restarting the app.
What to learn from it
- Local MCP is a first-class ship target.
platools serveisn’t a toy - it runs the same dispatcher the WebSocket transport uses, with the same doctor gate, under HTTP or stdio. - Stateful tools are fine. Module-level state survives between calls as long as the stdio server stays up. Claude Desktop keeps the subprocess alive for the whole conversation.
- The feedback loop is instant. Edit
tools.py, save, and the next restart of the server picks up the change. No platform deploys, no webhook plumbing. - Doctor-then-serve. The
platools servecommand runs doctor automatically before starting the transport, so you can’t accidentally expose a broken registry.
Source: examples/local-dev-loop/
Next steps
- Local mode - full
platools servereference with HTTP mode and CI examples. - python-billing-agent - a more realistic example with FastAPI hosting.
- CLI -
doctor,test, andservesubcommand reference.