Skip to main content
Glama

MCP-Excel — Google Sheets CRM MCP Server

A stateless MCP server that turns any Google Sheet into a 4-entity CRM (Lead, Organization, Contact, Activity). Runs as a standalone HTTP service (FastMCP streamable-HTTP, default port 5002) or over stdio for Claude Desktop and other local MCP hosts — no gateway, no ngrok, no subprocess spawning required.


Architecture

Any MCP host (Claude Desktop, your backend, an agent framework)
  │  HTTP POST /mcp  (JSON-RPC) — or stdio
  ▼
MCP-Excel :5002  (FastMCP streamable-HTTP)
  │  gspread
  ▼
Google Sheets API

Every tool call includes an explicit sheet_id — there is no session state, no "active sheet" variable. Multiple teams can use the same running instance safely because nothing is shared between requests.


Related MCP server: google-sheets-mcp

Sheet schema (auto-managed)

Four tabs, created on first connection if they don't exist. Existing tabs are used as-is; missing columns are appended without disturbing existing data.

Tab

Primary Key

Key columns

Lead

Lead ID

Organization ID, Status, Segment, Opportunity Details, Last Contact Date

Organization

Organization ID

Organization Name, Industry Domain, Sub Domain, Company Type, Website

Contact

Contact ID

First Name, Last Name, Organization ID, Designation, Mobile, Email, LinkedIn Profile

Activity

Activity ID

Lead ID, Organization ID, Contact ID, Activity Type, Activity Sub-Type, Subject, Discussion Summary, Outcome

IDs auto-increment continuing the existing pattern (LD001 → LD002, ACT010 → ACT011). Falls back to UUID if no consistent pattern is found.

Each tab also gets Created At, Updated At, Deleted audit columns appended if they aren't already present.

Headers are matched fuzzily (synonyms and near-duplicates are resolved), so an existing sheet with slightly different column names still works. Run tool_dedupe_headers (dry-run first) to merge genuine duplicate columns.


Setup

1. Google service account

You need a creds.json service account key with Google Sheets API and Google Drive API enabled.

Place it in this directory (the default path) or set GOOGLE_APPLICATION_CREDENTIALS to its full path.

Never commit creds.json to git. It is excluded in .gitignore; keep it local or mount it as a secret.

2. Share the sheet

For each Google Sheet you want to connect: open the sheet → Share → add the service account email as Editor → Done.

The service account email is printed at startup and returned by get_sheet_info on permission errors. It is also readable from creds.json:

python3 -c "import json; print(json.load(open('creds.json'))['client_email'])"

3. Install dependencies

pip install -r requirements.txt

Optional — business-card OCR (Claude Vision) support:

pip install anthropic
export ANTHROPIC_API_KEY=...

Running

Local dev (HTTP on :5002)

GOOGLE_APPLICATION_CREDENTIALS=creds.json python mcp_excel_server.py

Verify it's healthy:

curl -s -X POST http://localhost:5002/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \
  | python3 -m json.tool

Docker (staging / production)

docker build -t mcp-excel .
docker run -p 5002:5002 \
  -v /path/to/creds.json:/secrets/creds.json \
  -e GOOGLE_APPLICATION_CREDENTIALS=/secrets/creds.json \
  mcp-excel

Claude Desktop (stdio transport)

Set MCP_TRANSPORT=stdio to use stdio instead of HTTP:

{
  "mcpServers": {
    "crm": {
      "command": "python",
      "args": ["/path/to/mcp-excel/mcp_excel_server.py"],
      "env": {
        "GOOGLE_APPLICATION_CREDENTIALS": "/path/to/mcp-excel/creds.json",
        "MCP_TRANSPORT": "stdio"
      }
    }
  }
}

Environment variables

Variable

Default

Notes

GOOGLE_APPLICATION_CREDENTIALS

creds.json

Path to service account JSON

MCP_TRANSPORT

http

http for server mode, stdio for Claude Desktop

MCP_PORT

5002

HTTP listen port

ANTHROPIC_API_KEY

—

Only for tool_extract_business_card


Tools

All tools are stateless — every call requires sheet_id (full Google Sheets URL or bare spreadsheet ID).

Tool

Description

tool_get_sheet_info

Validate access, ensure all 4 tabs exist, confirm write access

tool_add_record

Add a record to Lead / Organization / Contact / Activity

tool_list_records

List records with optional column-based filters (paged)

tool_search_records

Keyword search across all columns

tool_update_record

Update fields on an existing record by primary-key ID

tool_delete_record

Soft-delete a record (sets Deleted to true)

tool_get_related_records

Look up records via foreign key (e.g. all Activities for a Lead)

tool_get_pipeline_analytics

Lead pipeline analytics: total, status breakdown, segment breakdown

tool_dedupe_headers

Find and merge duplicate columns (dry-run report first)

tool_extract_business_card

Extract contact fields from a business-card image via Claude Vision (needs ANTHROPIC_API_KEY)


Development

pip install pytest
pytest test_mcp_excel.py test_crm_local.py -v

Tests run fully offline (Google calls are mocked); no credentials needed.


Troubleshooting

Problem

Fix

status: failure, message: ""

Sheet not found — share it with the service account as Editor

Permission denied on sheet

Re-share with the service account as Editor (not Viewer)

Cannot connect to MCP-Excel service

MCP-Excel not running — start it on :5002

sheet_id is required and was empty

Always pass sheet_id — there is no implicit active sheet

Tab not found / wrong columns

get_sheet_info auto-creates missing tabs and appends missing columns


License

MIT — see LICENSE. Built by Nife.

Related MCP Connectors

Related MCP Servers