Model Context Protocol servers, Claude API integrations, and the unglamorous production plumbing around them — auth, rate limiting, provider failover, and webhook fulfillment that holds up under real traffic.
Custom tools with real input schemas, so Claude and other agents can call your systems directly instead of guessing at them.
Claude API work with the parts people skip: provider failover, spend caps, prompt-injection-resistant input handling.
Rate limiting, origin enforcement, webhook signature verification, and kill switches for endpoints that burn money when abused.
A single well-scoped MCP server rather than a scatter of thin ones. Of 42
registered tools, 21 are general-purpose utilities an agent would reach for
against any codebase — diff_text, cron_explain,
unit_convert, json_to_ts, csv_to_markdown,
wcag_contrast, regex_test, jwt_decode,
hash_text, word_freq. The rest are host and
catalog operations specific to the system it serves.
The design principle was that every tool had to be one an agent would reach for unprompted. An earlier iteration shipped servers whose only tool was a stub; those were cut. What survives are tools with real input schemas and real work behind them.
{
"name": "cron_explain",
"description": "Explain a cron expression in plain English",
"inputSchema": {
"type": "object",
"properties": { "expression": { "type": "string" } },
"required": ["expression"]
}
}
A public button that calls a paid LLM API is an open invitation to burn someone else's API budget. This layer exists to make that expensive and boring for an attacker.
| Control | Behavior |
|---|---|
| Kill switch | Single env var returns 503 globally; free features keep working |
| Origin required | Requests without a first-party Origin get 403 — no bare curl |
| CORS allowlist | Explicit host list, never wildcard |
| Secret rejection | Input matching key patterns (sk-, ghp_, private keys) refused |
| Tiered limits | Per-IP sliding windows: per-minute, per-hour, per-day |
| Body caps | Hard payload ceiling |
Serverless rate limits are best-effort and are not a global wallet, so provider-side hard spend caps back all of it. That distinction is the difference between a control that feels safe and one that is.
A generation endpoint that degrades instead of failing. Providers are tried in cost order — smallest capable model first, escalating only on failure — across Moonshot, NVIDIA, xAI, OpenAI, and Groq, with per-task routing so cheap tasks never touch expensive models.
Most of the engineering is in the unhappy paths: distinguishing a rate-limit from an outage from a malformed response, and making sure a single wedged provider cannot stall the request.
End-to-end purchase flow: dynamic per-product Checkout Sessions, signature-verified webhooks, and entitlement verification that treats Stripe as source of truth rather than trusting the client.
Entitlements persist to a durable ledger with a reconciliation script that re-syncs from the Stripe API, so a missed webhook degrades into a delay rather than a customer who paid and got nothing.
Paste JSON, get typed interfaces. Handles nested objects, arrays of mixed shape, and optional-field inference across sample records. The conversion runs entirely in the browser — the pasted JSON never leaves the page, which matters when what someone is pasting is a production API response.
A generated multi-panel dashboard for a live Home Assistant install, plus a conversational layer that routes natural-language household queries to an LLM with fallback handling when providers are unreachable.
Included the genuinely fiddly parts: entity-state reconciliation, template sensor generation, and a probe harness for verifying fallback behavior without waiting for a real outage.
I scope a first milestone small enough that you can judge the work before committing to the rest. For MCP projects that usually means two or three working tools against your actual data, deployed where you can call them — not a document describing what I would build.
I write things down. You get the schema decisions and the failure modes in writing, because the part that bites later is always the unhappy path nobody specified.