sheet-mcp
Allows using Google Sheets as a database, reading rows from configured spreadsheet tabs, merging row data into notification templates, and writing send status back to the sheet.
Enables sending email notifications through Resend, using spreadsheet data to populate subject and body templates, and recording delivery status back to the spreadsheet.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@sheet-mcpSend payment reminder emails to all unpaid customers in the sheet and log delivery statuses."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
sheet_mcp
An automated notification-sending MCP server for Philippine SMEs, using a Google Spreadsheet as a database.
It reads row data from a sheet, merges it into a template, sends a notification to the recipient, and writes the send status back to the sheet.
The v0.1 sending channel is email. SMS (via a Philippine gateway such as Semaphore) will be added as an adapter in v0.2, once the Sender ID registration issue is sorted out. The channel sits behind the
NotificationProviderinterface from the start, so the pipeline code won't change when SMS is added.This is the first vertical slice validating the MCP automation core's shared capability (sheet integration → notification sending). Once validated, it will be folded into the core.
Key Features (v0.1)
4 MCP Tools (docs/DESIGN.md §5)
Tool | What it does |
| Reads and returns target rows per the notify_config convention (filter applied, up to 200-row preview) |
| Previews the actual rendered message list + missing-value/duplicate warnings. No sending. |
| Sends email after confirmation. Without both safeguards below, returns only a dry-run result. |
| Queries send history via cursor-based pagination, newest first (200 by default, 1000 max). |
Safeguards
No live sending without dual confirmation: a real email only goes out when both the MCP tool call's
confirm: trueand the process environment variableSEND_MODE=liveare present — this guards against mistakes by an autonomous agent.Duplicate-send prevention (idempotency): the same row + the same template combination is sent only once. A 3-step
claim → send → commit/releaseflow atomically records whether a send happened, so running the same command multiple times — or the process dying mid-run — never causes a double send (local SQLiteSendLog,docs/DESIGN.md§3/§6).Mass-misfire prevention: if the number of rows passing the filter exceeds 1,000, a live send sends nothing and aborts immediately (prevents partial-send incidents,
MAX_PIPELINE_ROWS).External API timeouts: both Google Sheets and Resend calls have a default 30-second timeout, so a network failure can't hang the whole pipeline indefinitely.
User data is never touched: sheet writes are limited to the 4 status columns (
_send_status/_sent_at/_message_id/_error).Recovery that can't run automatically: if the process dies while a claim is held, an autonomous agent cannot reclaim it by itself — only a human, via the operational CLI (
sheet-mcp-recover, read-only by default + audit log), can reclaim it.
Sheet Convention
Just add a notify_config tab (send settings: data tab name, recipient column, subject/body templates, optional filter) and a data tab (row 1 = header = template variable names) to a single Google Sheet — no separate database or schema migration needed. See "Example Sheet Template" below for the full convention and a minimal example.
Two Installation Methods
Clone the repo (for development/contribution): commit
.mcp.jsonand share it with the team.npx sheet-mcp(use it without cloning): register it by passing environment variables directly viaclaude mcp add's-eflag. See "Setup Procedure" below anddocs/DESIGN.md§8.
Related MCP server: Gmail MCP Agent
Documentation Map
The relative paths below are only valid if you've cloned the repository or are viewing the GitHub repository — the package installed via
npx sheet-mcpdoes not includedocs/(docs/ADVERSARIAL_REVIEW_004.md AR-027).
Document | Content | When to read it |
| Agent steering file — stack, commands, conventions, guardrails | At the start of every agent session (auto-loaded) |
| Product spec — background, goals/non-goals, scenarios, roadmap | Before discussing features/scope |
| Technical design — architecture, interfaces, sheet convention, MCP tools | Required reading before implementation |
| Test strategy — mock setup, edge cases, gates | Before writing tests |
| Task backlog — agent execution units, completion criteria | When assigning work |
| AI-native development approach — the rules that run this repo | Once at the start + as an ongoing reference |
Development Approach
This project proceeds in the order docs → agent implementation → verification (see docs/WORKFLOW.md).
A human (Jin) owns spec/design/review/live-send approval, and code is written by a Claude Code agent, one task at a time from docs/TASKS.md. Every task's shared completion condition is that npm run check passes.
Quickstart (Development/Testing)
npm install
npm run check # typecheck + lint + format:check + test — the shared agent/human gate
npm run dev # runs the MCP server over stdio (.env secrets required — see "Setup Procedure" below)Setup Procedure (Trying it with a real sheet/email)
Copy
.env.exampleto.envand fill inGOOGLE_SERVICE_ACCOUNT_JSON/RESEND_API_KEY/MAIL_FROM.Build a Google Sheet per "Example Sheet Template" below, share it with your service account's email as an editor, then set
SMOKE_SHEET_ID=<sheet ID>in.env.Run
npm run smoketo check the preview (the default is always a dry run — nothing is sent).To actually send, run
SEND_MODE=live SMOKE_CONFIRM_SEND=1 npm run smoke(only sends if exactly one row is targeted).In Claude Code, open this repo and confirm the
sheet-mcpconnection with/mcp(.mcp.jsonis committed, seedocs/DESIGN.md§8).
Using npx sheet-mcp (no clone required)
The package is published on npm, so you can register it directly with Claude Code without cloning this repo. Instead of a .env file, pass your credentials directly as -e flags on claude mcp add — see docs/DESIGN.md §8-B for why a .env file doesn't work reliably for this path.
claude mcp add sheet-mcp --scope local \
-e GOOGLE_SERVICE_ACCOUNT_JSON=<absolute path to your service-account JSON file> \
-e RESEND_API_KEY=<your Resend API key> \
-e MAIL_FROM=<your verified sending address> \
-- npx -y sheet-mcpWorked example — this is exactly the same command with every value filled in, so you can see what a real, working setup looks like. Copy it and swap in your own values:
claude mcp add sheet-mcp --scope local \
-e GOOGLE_SERVICE_ACCOUNT_JSON=/Users/jin/keys/sheet-mcp-service-account.json \
-e RESEND_API_KEY=re_AbCdEfGh_1234567890abcdefghij \
-e MAIL_FROM=notify@updates.example.com \
-- npx -y sheet-mcpWhat to change for your own setup:
GOOGLE_SERVICE_ACCOUNT_JSON— the absolute path to the service-account key JSON file you downloaded from Google Cloud Console (IAM & Admin → Service Accounts → Keys → Add Key → JSON). It must be an absolute path:npxruns from wherever Claude Code happens to be running, not from this repo, so a relative path like./service-account.jsonwon't resolve reliably.RESEND_API_KEY— your own key from resend.com → API Keys.MAIL_FROM— an address at a domain you've verified with Resend (resend.com → Domains → Add Domain, then add the DNS records it gives you). If you don't have a domain yet, you can start with Resend's test-only addressonboarding@resend.devto try things out — but that address can only send to the email address on your own Resend account until you verify a real domain.sheet-mcp(the first argument) — the name this server is registered under in Claude Code; change it if you want something else.--scope local— keep this aslocal(oruser) when passing real secrets. Never use--scope projectwith real credentials: that scope commits.mcp.jsonto git, which would leak your secrets.
Once registered, confirm the connection inside Claude Code with /mcp.
Example Sheet Template
One notify_config tab (column A = key, column B = value) and one data tab — see docs/DESIGN.md §2 for the full key list and rules.
Minimal notify_config tab
A | B |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Data tab: row 1 is the header (= template variable names), data starts at row 2. fixtures/sheets/collections.json is a real example (12 rows, a mixed Tagalog/English outstanding-balance scenario) — move it into a Google Sheet with the same columns and it's ready to use for a smoke test. Send results are automatically recorded at the end of this tab in 4 columns — _send_status/_sent_at/_message_id/_error — and user data columns are never modified.
Operations — Existing DB Upgrade / Stale Claim Recovery
Upgrading an existing
sendlog.db: the next time you run the server (npm run dev) or the smoke script (npm run smoke) with the newer code,SqliteSendLogauto-detects the old DB schema and migrates it losslessly to the new schema (the original is preserved in asend_log_v1_backup_*table). There's nothing a human needs to do. Seedocs/DESIGN.md§6 for details.When a claim has been sitting for a long time (e.g., the process died without a clean shutdown): never touch the DB file directly — query it first. In a repo-clone dev environment:
npm run recover:stale-claim -- --db ./data/sendlog.db --sheet-id <id> --tab <tab> --row-key <key> --template-hash <hash>. If installed vianpx sheet-mcp:npx sheet-mcp-recover --db ... --sheet-id ... --tab ... --row-key ... --template-hash ...(same arguments; read-only by default, deletes nothing). To actually reclaim it, add--older-than-msand--confirm. For full options and safeguards, see the header comment insrc/cli/recoverStaleClaim.tsanddocs/DESIGN.md§6.
Status
Progress isn't tracked manually here — the single source of truth is each task's status (DONE(date)/TODO) in docs/TASKS.md. Duplicating it in the README makes it easy to forget to update on the next task's completion (docs/ADVERSARIAL_REVIEW_002.md AR-010).
Whether this is a fully working product end to end, including the MCP tools, is determined by whether T8–T10 are DONE.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Manage Gmail end-to-end: search, read, send, draft, label, and organize threads. Automate workflow…
Send and schedule SMS and WhatsApp messages, manage contacts and templates, and track delivery.
Manage Gmail messages, threads, labels, drafts, and settings from your workflows. Send and organiz…
Let your AI agent notify you by email, Slack, Discord, or webhook. One tool: send_notification.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables automated customer reminder management by integrating with Google Sheets to read customer data and sending scheduled email reminders based on due dates. Supports personalized email templates, intelligent scheduling, and duplicate prevention with Gmail SMTP integration.
- AlicenseNot gradedqualityCmaintenanceEnables automated Gmail lead nurturing campaigns with intelligent follow-ups, response tracking, and 24/7 operation. Supports CSV-based contact management, template personalization, and real-time monitoring for enterprise-scale email outreach.2MIT
- AlicenseNot gradedqualityDmaintenanceEnables agents to create, read, and modify Google Sheets using a service account, without OAuth. Provides tools for sheet creation, appending rows, updating ranges, and reading data.178MIT
- AlicenseNot gradedqualityDmaintenanceEnables automation of Google Workspace tasks, including reading/writing sheets, generating Apps Script code, and creating webhook senders, with AI assistance via Claude.1,895MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Trapa-Eureka/sheet_mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server