Open source · 5 packagesLive
Google Workspace MCP servers, multi-account, and safe by default
Four local MCP servers that let Claude work across several Google accounts at once: Gmail, Calendar, Drive, and Docs/Sheets/Slides. Plus, one shared accounts package to let each account sign in once and every server use it.
- Dry run before anything others see. Sends, shares, invites, overwrites, and deletes return a preview (recipients, before/after diffs, who gets emailed) and it only acts on an explicit confirm. Gmail replies can only ever land as drafts (never sent).
- Least-privilege OAuth. Drive defaults to
drive.file, whole-Drive read is a per-account opt-in, and each tool checks only the scope it needs, with errors that name the exact fix.
- Built for shared state. Lock-filed atomic writes to the token store, an append-only audit log that never records content, retries only on idempotent calls, and a file sandbox that rejects
../ and symlink escapes.
- Node.js
- MCP SDK
- Google APIs
- OAuth 2.0
- node:test
Open sourceLive
Leads dashboard: Gmail-synced outreach with Claude-drafted follow-ups
A locally run dashboard over outreach spreadsheets. For every lead, it shows when you last emailed (in either direction), whether it's your turn, a 0–3 priority, and a follow-up status. Tick rows and Claude drafts follow-ups straight into Gmail as drafts; it never sends.
- Gmail is the source of truth for email and the sheet is the source of truth for leads. Sync writes only changed cells, and SQLite holds bookmarks that can be rebuilt any time.
- Reuses the MCP servers' sign-in, Gmail helpers, and audit log. Write-back to sheets is off until you turn it on, and edits have history & undo.
- Node.js
- SQLite
- Gmail & Sheets APIs
- Claude Code
Open sourceLive
Dodgers & LAFC win alerts for food deals
Push notifications when the Dodgers win at home or LAFC scores first in the first half at home (each unlocks a food promo), once right away and again the next morning. A Cloudflare Worker on cron triggers polls the MLB Stats API and ESPN's play-by-play, then publishes through ntfy.
- Traced dropped alerts to ntfy.sh's per-IP rate limit on Cloudflare's shared egress, wrote it up upstream, and moved to a self-hosted ntfy on Cloud Run's free tier.
- An integration registry, KV de-duplication, and a deduped ops page when the unofficial ESPN API changes shape, so it never fails silently.
- JavaScript
- Cloudflare Workers & KV
- Cloud Run
- ntfy
- GitHub Actions
Independent contractor2025 – present
Custom AI agents for small businesses & nonprofits
Agents that handle the work small teams don't have time for, serving thousands of people a day: customer-service FAQs, inbox & calendar management, social posting on a schedule, review replies, sales leads, and employee check-ins.
- Human approval by default, with a self-improvement loop that turns approvals into context and updated evals.
- An operator dashboard for picking models, defining tool schemas, and scoping context & memory.
- TypeScript
- Hermes
- Claude
- GPT
- Gemini
- MCP
Side projectIn progress
Momo, a marketing agent for small teams
A full-service marketing agent for small businesses & nonprofits, built as a set of specialist sub-agents. The first one, Coco, handles content and is in active development.
Momo and Coco are confidential while in development, so the source isn't public. I'm happy to walk through the high-level architecture in an interview.
Side projectLive
Remote MCP server about my candidacy
A read-only Streamable HTTP MCP server that lets an AI agent query my work history, projects, skills, and contact info through six typed tools. It's stateless (a fresh server per request) and runs on Cloudflare Workers.
- Eval suite checks every tool's output, and an optional LLM pass checks that the tool descriptions lead a model to pick the right tool.
- TypeScript
- MCP SDK
- Cloudflare Workers
- Evals
Side projectLive
Clippy, a RAG agent for this site
Ask Clippy about me, and it answers from a curated knowledge file, not from the model's memory. The browser widget calls a Cloudflare Worker that holds the Anthropic API key, so the key never reaches the client.
- Origin allowlist; capped history, message length, and output tokens; and a cacheable knowledge block to keep repeat requests cheap.
- TypeScript
- Anthropic API
- Cloudflare Workers
- RAG
Stride Consulting · MoveHQ2022 – 2023
Replacing legacy systems for military family relocations
Delivered 12–17 features (approvals, notifications, data fixes) in three months on a platform replacing legacy government software, and supported an architecture restructure that introduced a notification bus.
- Cut testing errors by 60%, raised coverage to 95%, and fixed 5,000+ tests.
- Ruby on Rails
- React
- Postgres
- TDD / XP
HashiCorp, an IBM company2025
SCIM provisioning for HashiCorp Cloud Platform
On the Cloud Enterprise Identity team, I implemented SCIM between external identity providers (Okta, Azure) and HCP, and designed, prototyped, and built groups & group membership.
- Wrote an ADR proposing a River Queue job design that removed a race condition between jobs.
- Shipped ahead of the projected timeline for Private Beta customer testing.