mcp-server-starter
by Kaiser9005
README.md
# mcp-server-starter
**A small but real MCP server (FastMCP) — with a destructive action guarded behind human confirmation.**
Most "MCP server" examples stop at a `hello_world` tool. This one shows the part
that actually matters when an agent is on the other end: a **destructive tool that
refuses to run** until a confirmation token is supplied, forcing the agent to
surface the decision to a human instead of wiping data on its own.
It exposes a tiny inventory domain as MCP tools + one resource, over stdio
transport — drop-in for Claude Desktop, Cursor, or the MCP Inspector.
## Tools
| Tool | Tier | Behavior |
|---|---|---|
| `list_items` / `get_item` | read | runs freely |
| `add_item` / `adjust_quantity` | low-impact write | runs freely (validates inputs) |
| `delete_all_items(confirm_token)` | **destructive** | **guarded** — returns a one-time token first; only deletes when called again with that token |
| `inventory://summary` (resource) | read | human-readable inventory snapshot |
The guard pattern (`delete_all_items`) is the point: call it once with no token →
you get back `{"status": "confirmation_required", "confirm_token": "..."}` → a human
approves → call again with the token → it executes. An irreversible action never
runs on the agent's say-so alone.
## Quick start
```bash
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python server.py # stdio transport
```
Inspect it interactively:
```bash
npx @modelcontextprotocol/inspector python server.py
```
### Wire it into Claude Desktop / Cursor
Add to your MCP config (`claude_desktop_config.json` or `.cursor/mcp.json`):
```jsonc
{
"mcpServers": {
"inventory-starter": {
"command": "python",
"args": ["/absolute/path/to/mcp-server-starter/server.py"]
}
}
}
```
> Tip (Claude Code schema): for HTTP-based servers use `"type": "http"` — the
> validator rejects the spec-name `"streamable-http"` even though they're the same
> transport. (stdio servers like this one don't need a `type`.)
## Going further
- Swap the in-memory `_ITEMS` dict for Postgres/Supabase (see the companion
[`fastapi-supabase-multitenant-starter`](https://github.com/Kaiser9005/fastapi-supabase-multitenant-starter)).
- Route the confirmation to Slack/web instead of a token — see
[`agent-guardrails`](https://github.com/Kaiser9005/agent-guardrails) for a pluggable approver + audit trail.
- For a LangGraph agent that consumes a guarded tool like this, see
[`langgraph-hitl-agent`](https://github.com/Kaiser9005/langgraph-hitl-agent).
## License
MIT.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues