Bill ca03d22b97
All checks were successful
Build and Push Docker Image / build (push) Successful in 14s
fix: handle missing config file gracefully in Docker
2026-01-01 12:51:25 -05:00
2025-12-29 20:13:07 -05:00
2026-01-01 10:31:27 -05:00
2026-01-01 10:31:27 -05:00

grist-mcp

MCP server for AI agents to interact with Grist documents.

Overview

grist-mcp is a Model Context Protocol (MCP) server that enables AI agents to read, write, and modify Grist spreadsheets. It provides secure, token-based access control with granular permissions per document.

Features

  • Discovery: List accessible documents with permissions
  • Read Operations: List tables, describe columns, fetch records, run SQL queries
  • Write Operations: Add, update, and delete records
  • Schema Operations: Create tables, add/modify/delete columns
  • Security: Token-based authentication with per-document permission scopes (read, write, schema)
  • Multi-tenant: Support multiple Grist instances and documents

Quick Start (Docker)

Prerequisites

  • Docker and Docker Compose
  • Access to one or more Grist documents with API keys

1. Create configuration directory

mkdir grist-mcp && cd grist-mcp

2. Download configuration files

# Download docker-compose.yml
curl -O https://raw.githubusercontent.com/Xe138/grist-mcp-server/master/deploy/prod/docker-compose.yml

# Download example config
curl -O https://raw.githubusercontent.com/Xe138/grist-mcp-server/master/config.yaml.example
cp config.yaml.example config.yaml

3. Generate tokens

Generate a secure token for your agent:

python -c "import secrets; print(secrets.token_urlsafe(32))"
# or
openssl rand -base64 32

4. Configure config.yaml

Edit config.yaml to define your Grist documents and agent tokens:

# Document definitions
documents:
  my-document:                           # Friendly name (used in token scopes)
    url: https://docs.getgrist.com       # Your Grist instance URL
    doc_id: abcd1234efgh5678             # Document ID from the URL
    api_key: your-grist-api-key          # Grist API key (or use ${ENV_VAR} syntax)

# Agent tokens with access scopes
tokens:
  - token: your-generated-token-here     # The token you generated in step 3
    name: my-agent                       # Human-readable name
    scope:
      - document: my-document            # Must match a document name above
        permissions: [read, write]       # Allowed: read, write, schema

Finding your Grist document ID: Open your Grist document in a browser. The URL will look like: https://docs.getgrist.com/abcd1234efgh5678/My-Document - the document ID is abcd1234efgh5678.

Getting a Grist API key: In Grist, go to Profile Settings → API → Create API Key.

5. Create .env file

Create a .env file with your agent token:

# .env
GRIST_MCP_TOKEN=your-generated-token-here
PORT=3000

The GRIST_MCP_TOKEN must match one of the tokens defined in config.yaml.

6. Start the server

docker compose up -d

The server will be available at http://localhost:3000.

7. Configure your MCP client

Add to your MCP client configuration (e.g., Claude Desktop):

{
  "mcpServers": {
    "grist": {
      "type": "sse",
      "url": "http://localhost:3000/sse"
    }
  }
}

Available Tools

Discovery

Tool Description
list_documents List documents accessible to this agent with their permissions

Read Operations (requires read permission)

Tool Description
list_tables List all tables in a document
describe_table Get column information (id, type, formula) for a table
get_records Fetch records with optional filter, sort, and limit
sql_query Run a read-only SELECT query against a document

Write Operations (requires write permission)

Tool Description
add_records Add new records to a table
update_records Update existing records by ID
delete_records Delete records by ID

Schema Operations (requires schema permission)

Tool Description
create_table Create a new table with specified columns
add_column Add a column to an existing table
modify_column Change a column's type or formula
delete_column Remove a column from a table

Configuration Reference

Environment Variables

Variable Description Default
PORT Server port 3000
GRIST_MCP_TOKEN Agent authentication token (required) -
CONFIG_PATH Path to config file inside container /app/config.yaml

config.yaml Structure

# Document definitions (each is self-contained)
documents:
  budget-2024:
    url: https://work.getgrist.com
    doc_id: mK7xB2pQ9mN4v
    api_key: ${GRIST_WORK_API_KEY}      # Supports environment variable substitution

  personal-tracker:
    url: https://docs.getgrist.com
    doc_id: pN0zE5sT2qP7x
    api_key: ${GRIST_PERSONAL_API_KEY}

# Agent tokens with access scopes
tokens:
  - token: your-secure-token-here
    name: finance-agent
    scope:
      - document: budget-2024
        permissions: [read, write]       # Can read and write

  - token: another-token-here
    name: readonly-agent
    scope:
      - document: budget-2024
        permissions: [read]              # Read only
      - document: personal-tracker
        permissions: [read, write, schema]  # Full access

Permission Levels

  • read: Query tables and records, run SQL queries
  • write: Add, update, delete records
  • schema: Create tables, add/modify/delete columns

Security

  • Token-based auth: Each agent has a unique token with specific document access
  • Permission scopes: Granular control with read, write, and schema permissions
  • SQL validation: Only SELECT queries allowed, no multi-statement queries
  • API key isolation: Each document can use a different Grist API key
  • No token exposure: Tokens are validated at startup, not stored in responses

Development

Requirements

  • Python 3.14+
  • uv package manager

Local Setup

# Clone the repository
git clone https://github.com/Xe138/grist-mcp-server.git
cd grist-mcp-server

# Install dependencies
uv sync --dev

# Run tests
make test-unit

Running Locally

export GRIST_MCP_TOKEN="your-agent-token"
CONFIG_PATH=./config.yaml uv run python -m grist_mcp.main

Project Structure

grist-mcp/
├── src/grist_mcp/
│   ├── main.py          # Entry point
│   ├── server.py        # MCP server setup and tool registration
│   ├── config.py        # Configuration loading
│   ├── auth.py          # Authentication and authorization
│   ├── grist_client.py  # Grist API client
│   └── tools/
│       ├── discovery.py # list_documents
│       ├── read.py      # Read operations
│       ├── write.py     # Write operations
│       └── schema.py    # Schema operations
├── tests/
│   ├── unit/            # Unit tests
│   └── integration/     # Integration tests
├── deploy/
│   ├── dev/             # Development docker-compose
│   ├── test/            # Test docker-compose
│   └── prod/            # Production docker-compose
└── config.yaml.example

License

MIT

Description
No description provided
Readme 719 KiB
Languages
Python 97.3%
Makefile 0.9%
Shell 0.9%
Dockerfile 0.9%