Skip to content

Abdeltoto/smartsheet-controller

Repository files navigation

Hey everyone! Welcome to my GitHub!

Smartsheet Controller

Talk to Your Smartsheet.

Stop clicking. Start talking. Your sheets understand you now.

Created by Abdel ATIA
Smartsheet Lover & Power User since 2013
GitHub


Talk to Your Smartsheet — voice-driven AI agent



Smartsheet API FastAPI OpenAI Anthropic +3 LLMs MCP Tests License


73 Smartsheet tools · 80 formulas · 5 LLM providers · 246 green tests · Full voice control · One conversation.

A community-built AI agent that speaks the Smartsheet API fluently — built for developers and power-users. Read, write, analyze, automate, share, and visualize — by just asking. BYOT (bring your own token) · server-side memory · audit log · real-time webhooks · MCP-ready.

Built on top of the official @smartsheet REST API v2.0 — community project, not affiliated with Smartsheet Inc.


Quick Start · The Power · What You Can Say · 73 Tools · MCP Server · Tests · Deploy



The Problem

You know the drill. Open Smartsheet. Navigate. Click. Scroll. Find the right column. Write a formula. Test it. Fix it. Click again. Repeat for every single sheet.

What if you could just... say it?


Before After
Open sheet, scroll to row 47, find the column, manually edit the cell "Update row 47, set Status to Done"
Google the SUMIFS syntax, write it, debug the brackets "What's the total revenue for Q1?"
Navigate to sharing settings, add email, choose permission "Share this sheet with Marie as Editor"
Open 3 sheets, cross-reference manually, copy-paste values "Pull the budget total from the Finance sheet into this one"
Export data, open another tool, build a chart "Generate a visual of my project timeline"

"Don't navigate your sheets. Command them."



The Power

What makes this different from everything else.


Your Data Answers Back

Ask a question in plain English (or French). The AI reads your sheet, understands the structure, and answers with formatted tables, rich Markdown, and inline images. Not raw JSON. Not a wall of text. Clean, structured, actionable answers.

73 Tools. Zero Friction.

Every Smartsheet operation — from reading a cell to creating a webhook — is a tool the agent can call autonomously. You describe what you want. The agent decides which API calls to make, chains them together, and delivers the result. You never touch the API.

Voice → AI → 73 tools → Smartsheet

Voice in. AI in the middle. 73 tools fanning out. Sheet updated.

80 Formulas. Natively Understood.

The agent doesn't just know Smartsheet formulas — it thinks in them. SUMIFS, INDEX(COLLECT(...)), cross-sheet {{references}}, hierarchy functions like CHILDREN() and ANCESTORS(). Ask for a formula and get the exact Smartsheet syntax, not a generic spreadsheet guess.

Your Voice Is the Interface

Click the mic. Speak. The agent transcribes, understands, and executes. Voice-first, keyboard-optional. Your Smartsheet has ears now.

Real-Time Streaming

Responses flow token by token, just like ChatGPT. You see the agent thinking in real time. No waiting for a wall of text — words appear as they're generated. The app breathes.

Smart Suggestions

After every response, the agent suggests 2-4 follow-up actions as clickable chips. You never face a blank input. The AI guides you forward.

Sheet Switcher

Jump between sheets instantly from a dropdown in the header. No disconnecting, no re-configuring. Multi-sheet workflows in one session.

Conversation History

Every conversation is saved locally and accessible from a sidebar. Reload past analyses, formulas, and decisions anytime. Your Smartsheet memory never fades.

See Everything. Trust Everything.

Every tool call the agent makes is visible in real-time. You see the API call, the parameters, the response. Full transparency. Full control. No black box.

Not Just Text. Visuals Too.

Need a diagram? A chart concept? A visual representation of your data architecture? The agent generates DALL-E 3 images and live Chart.js bar/line/pie/doughnut/scatter charts directly in the conversation. Your chat is a canvas.



Bring Your Own Model

OpenAI · Anthropic · OpenRouter · Mistral · Groq

Five LLM providers, one chat. Switch model mid-conversation — the context follows you. The agent keeps the same tool repertoire and the same Smartsheet expert prompt no matter which brain you plug in.

Provider What it's great at Models exposed
OpenAI The reference. Best tool-calling reliability + DALL-E 3 image gen. gpt-4o, gpt-4o-mini, gpt-4-turbo
Anthropic Long-form analysis, careful reasoning, dense tables. claude-3-5-sonnet, claude-3-5-haiku, claude-3-opus
OpenRouter One API key, hundreds of models. Try Llama, Gemini, DeepSeek without managing extra keys. Any OpenRouter slug
Mistral EU-hosted, fast, cost-efficient. mistral-large-latest, mistral-small-latest
Groq Sub-second token speed thanks to LPU inference. llama-3.3-70b-versatile, mixtral-8x7b

The header dropdown lists only the providers whose key is detected in .env — set just the ones you actually have.

A live token-usage counter is displayed under the chat for the active provider, and a per-session rate-limiter (60 LLM calls / min, 120 WebSocket frames / min) protects you from runaway loops.



Server Brain — Persistent, Auditable, Live

The server isn't a stateless proxy. It owns a small SQLite store so your account remembers things across sessions and tabs:

  • Conversations — auto-saved on every message, reloadable from the sidebar (with optional auto-generated titles).
  • Favorites — pin sheets to the header for one-click switching.
  • Audit log — every tool call (especially destructive ones) is timestamped and stored. GET /api/audit and GET /api/export give you the full history (RGPD-friendly).
  • Webhook events — incoming Smartsheet webhooks land in POST /api/smartsheet-webhook, are persisted, and fan out in real time to every active WebSocket session that pinned the affected sheet.
  • Watch mode — the UI can subscribe to a sheet and surface new rows / changes the moment they happen.

Combined with the per-session token bucket and Smartsheet 429 retry-with-backoff, the backend stays steady under fast-fire conversations.



Quick Start

1. Install

pip install -r requirements.txt

2. Configure

cp .env.example .env
SMARTSHEET_TOKEN=your_smartsheet_api_token
SHEET_ID=your_default_sheet_id
OPENAI_API_KEY=sk-...

Smartsheet API tokenapp.smartsheet.com > Personal Settings > API Access

Sheet ID — Open any sheet, check the URL or go to File > Properties

3. Launch

uvicorn backend.app:app --reload --port 8000

Open http://localhost:8000 — hit Quick Connect — start talking.

That's it. Three commands. You're in.


What You Can Say

Every one of these is a real command the agent executes.


Data & Analysis

"Show me the full structure of my sheet as a table"

"Read rows 1 to 50 and give me a summary"

"What are the 10 largest amounts in the Budget column?"

"Are there any errors or inconsistencies in my data?"

Formulas & Calculations

"Write a SUMIFS formula to total sales by region"

"Create a cross-sheet formula that pulls the status from the Projects sheet"

"What's the correct syntax for INDEX(COLLECT(...)) with two criteria?"

Structure & Automation

"Add a PICKLIST column 'Priority' with options High, Medium, Low"

"Move completed rows to the Archive sheet"

"Who has access to this sheet? Show me the permissions"

Visuals

"Generate an image that illustrates my sheet architecture"

"Create a visual for the project tracking dashboard"


Every Tool at Your Voice

73 tools organized in 16 categories. The agent picks the right ones automatically.

Account & Navigation — 10 tools
Tool What it does
get_current_user Your Smartsheet profile
list_sheets Every sheet you have access to
search Search across your entire account
search_sheet Search within a specific sheet
list_workspaces All your workspaces
get_workspace Workspace contents and structure
list_folders Home-level folders
get_folder Folder contents
create_folder Create a new folder
get_recent_items Recent items and favorites
Sheet Reading & Analysis — 7 tools
Tool What it does
get_sheet_summary Sheet structure: columns, types, row count
read_rows Read rows with optional range
get_row Get a single row by ID
get_cell_history Full audit trail for any cell
get_summary_fields Sheet-level KPI fields
analyze_sheet Deep analysis: structure, patterns, formulas
detect_issues Find errors, empty columns, inconsistencies
Data Manipulation — 6 tools
Tool What it does
add_rows Add new rows with values
update_rows Update cells (values or formulas)
delete_rows Delete rows by ID
move_rows Move rows to another sheet
copy_rows Copy rows to another sheet
sort_sheet Sort by one or more columns
Column Management — 3 tools
Tool What it does
add_column Add column (TEXT_NUMBER, DATE, PICKLIST, CHECKBOX, CONTACT_LIST, DURATION, PREDECESSOR)
update_column Update column title or description
delete_column Delete a column
Sheet Management — 5 tools
Tool What it does
create_sheet Create a new sheet with columns
delete_sheet Delete a sheet
rename_sheet Rename a sheet
copy_sheet Copy a sheet
move_sheet Move sheet to folder/workspace
Cross-sheet References — 2 tools
Tool What it does
list_cross_sheet_refs List all cross-sheet references
create_cross_sheet_ref Create a ref for INDEX(COLLECT(...)) formulas
Sharing & Collaboration — 4 tools
Tool What it does
list_shares List sharing permissions
share_sheet Share with a user (VIEWER / EDITOR / ADMIN)
update_share Update permission level
delete_share Remove access
Discussions & Comments — 4 tools
Tool What it does
list_discussions Sheet-level discussions
list_row_discussions Discussions on a specific row
add_comment Reply to a discussion
create_row_discussion Start a new discussion on a row
Attachments — 6 tools
Tool What it does
list_attachments List all attachments on a sheet
list_row_attachments List attachments on a single row
get_attachment Get details and download URL
attach_url_to_sheet Attach a URL/link (Drive, Dropbox, OneDrive, web) to a sheet
attach_url_to_row Attach a URL/link to a specific row
delete_attachment Delete an attachment by ID
Forms — 1 tool
Tool What it does
list_sheet_forms List forms on a sheet (falls back to permalink — Smartsheet API exposure is limited)
Update Requests — 3 tools
Tool What it does
list_update_requests List pending update requests
create_update_request Send an update request to one or more emails for specific row(s)
delete_update_request Cancel an outstanding update request
Proofs (Premium) — 2 tools
Tool What it does
list_row_proofs List proofs on a row (Premium feature)
create_row_proof_from_url Create a proof from a URL on a row
Reports & Dashboards — 4 tools
Tool What it does
list_reports List all reports
get_report Get report data
list_dashboards List all dashboards
get_dashboard Dashboard details and widgets
Templates & Webhooks — 5 tools
Tool What it does
list_templates Public templates
list_webhooks Configured webhooks
create_webhook Create a webhook
update_webhook Enable/disable or reconfigure a webhook in place
delete_webhook Delete a webhook
Automations — 4 tools
Tool What it does
list_automations List automation rules
get_automation Get details of one rule
update_automation Enable/disable or rename a rule (CREATE not supported by Smartsheet API)
delete_automation Delete an automation rule
Workspace Sharing — 4 tools
Tool What it does
list_workspace_shares List sharing on a workspace
share_workspace Share workspace with a user (cascades to all sheets inside)
update_workspace_share Change a user's access level on a workspace
delete_workspace_share Remove a user from a workspace
Cell Linking & AI — 3 tools
Tool What it does
create_cell_link One-way live link from a source cell to a target cell (distinct from cross-sheet refs)
generate_image Generate visuals with DALL-E 3 (inline in chat)
generate_chart Render a Chart.js bar/line/pie/etc. inline in chat

Formula Mastery

The agent knows every Smartsheet function. All 80. By heart.


Category Count Functions
Numeric 25 ABS AVG AVGW CEILING CHAR COUNT FLOOR INT LARGE LEN MAX MEDIAN MIN MOD MROUND RANKAVG RANKEQ ROUND ROUNDDOWN ROUNDUP SMALL SUM UNICHAR DECTOHEX HEXTODEC
Logic 16 AND CONTAINS HAS IF IFERROR ISBLANK ISBOOLEAN ISCRITICAL ISDATE ISERROR ISEVEN ISNUMBER ISODD ISTEXT NOT OR
Text 10 FIND JOIN LEFT LOWER MID REPLACE RIGHT SUBSTITUTE UPPER VALUE
Date 14 DATE DATEONLY DAY MONTH NETDAYS NETWORKDAY NETWORKDAYS TIME TODAY WEEKDAY WEEKNUMBER WORKDAY YEAR YEARDAY
Advanced / Lookup 18 AVERAGEIF COLLECT COUNTIF COUNTIFS COUNTM DISTINCT INDEX MATCH NPV PERCENTILE PRORATE STDEVA STDEVP STDEVPA STDEVS SUMIF SUMIFS VLOOKUP
Hierarchy 6 ANCESTORS CHILDREN DESCENDANTS PARENT SUCCESSORS TOTALFLOAT

Beyond functions — the agent masters:

  • [Column]@row references, [Column]:[Column] ranges, absolute row refs
  • Cross-sheet {{reference}} patterns: INDEX(COLLECT({{Values}}, {{Keys}}, [Key]@row), 1)
  • Column formulas, Summary fields, Conditional formatting rules
  • Reports (multi-sheet aggregation), Dashboards (live KPI widgets)
  • Gantt, Calendar, Card/Kanban views
  • Automations, Forms, Proofing, Cell history, Row locking

MCP Server

A complete Model Context Protocol server — plug Smartsheet into Claude Desktop, Cursor, or any MCP client. 52 of the 73 tools are exposed through MCP (the chat-only ones — generate_image, generate_chart, etc. — stay in the web app).

Start

# stdio (Claude Desktop / Cursor)
SMARTSHEET_TOKEN=your_token python -m backend

# HTTP
SMARTSHEET_TOKEN=your_token python -m backend --transport http

Cursor IDE — .cursor/mcp.json

{
  "mcpServers": {
    "smartsheet": {
      "command": "python",
      "args": ["-m", "backend"],
      "cwd": "/path/to/smartsheet-controller",
      "env": { "SMARTSHEET_TOKEN": "your_token_here" }
    }
  }
}

Claude Desktop — claude_desktop_config.json

{
  "mcpServers": {
    "smartsheet": {
      "command": "python",
      "args": ["-m", "backend"],
      "cwd": "/path/to/smartsheet-controller",
      "env": { "SMARTSHEET_TOKEN": "your_token_here" }
    }
  }
}

Resources & Prompts

MCP Resources
smartsheet://sheets All sheets in the account
smartsheet://user Authenticated user profile
smartsheet://sheets/{id}/summary Sheet structure
MCP Prompts
Analyze Sheet Deep structure analysis with suggestions
Sheet Audit Security, sharing & quality audit
Explore Account Full account exploration

Architecture

smartsheet-controller/
├── backend/
│   ├── app.py                 → FastAPI + WebSocket + session mgmt + 20+ HTTP routes
│   ├── agent.py               → AI agent loop, expert prompt, tool dispatch, suggestions
│   ├── tools.py               → 73 tool definitions + dispatcher + DALL-E + Chart.js
│   ├── llm_router.py          → 5-provider streaming router (OpenAI / Anthropic / OpenRouter / Mistral / Groq)
│   ├── smartsheet_client.py   → Smartsheet REST wrapper (httpx, retry, in-memory cache)
│   ├── db.py                  → SQLite persistence (users, sessions, conversations, favorites, audit, webhooks)
│   ├── rate_limit.py          → Token-bucket rate limiter (per-session LLM + WS)
│   ├── logging_config.py      → Structured JSON logs with token redaction
│   ├── mcp_server.py          → MCP server (52 tools, 3 resources, 3 prompts)
│   └── __main__.py            → MCP CLI entry point (stdio / http)
├── frontend/
│   ├── index.html             → Glassmorphism SPA (voice, streaming, history, suggestions, watch)
│   └── assets/                → Brand & marketing assets (PNG, SVG)
├── tests/
│   ├── unit/                  → 196 fast tests (no I/O, mocked transports)
│   │     ├── test_rate_limit.py        rate limiter
│   │     ├── test_llm_router.py        provider parsing + usage tracking
│   │     ├── test_tools.py             intent routing + chart generation
│   │     ├── test_tools_dispatch.py    contract: every tool dispatchable
│   │     ├── test_smartsheet_client.py mock-transport CRUD + retry + cache
│   │     ├── test_db.py                SQLite layer (every CRUD path)
│   │     ├── test_agent.py             agent helpers
│   │     ├── test_agent_loop.py        run() loop: tools, confirm, MAX_ROUNDS
│   │     ├── test_app_helpers.py       _friendly_error, provider detection
│   │     └── test_mcp_smoke.py         MCP server boot + tool registry
│   ├── integration/           → 41 tests against the real Smartsheet API
│   │     ├── test_smartsheet_live.py   read + create→modify→delete lifecycle
│   │     └── test_app_endpoints*.py    every FastAPI HTTP route
│   ├── e2e/                   → 9 full-stack WebSocket flow tests
│   │     ├── test_websocket_flow.py    handshake + agent + suggestions
│   │     └── test_websocket_advanced.py cancel, confirm/reject, rate-limit, multi-turn
│   └── README.md              → How to run, what each layer covers
├── data/                      → SQLite DB (created at first launch, git-ignored)
├── Dockerfile                 → Slim Python 3.11 image, non-root, /health probe
├── docker-compose.yml         → One-command stack with bind-mount for data/
├── pytest.ini                 → markers: unit / integration / e2e / live_llm
├── ROADMAP.md                 → 7+ sprints, journal, deliverables
├── requirements.txt           → Runtime deps
├── requirements-dev.txt       → + pytest, pytest-asyncio, pytest-cov
├── .env                       → API keys (LLM providers + optional SMARTSHEET_TOKEN)
└── README.md
   You (voice or text)
        │
        ▼
    WebSocket ──→ FastAPI ──→ Agent ──→ LLM Router
                                          │      ┌──────────┐
                                          ├─────▶│ OpenAI   │
                                          ├─────▶│ Anthropic│
                                          ├─────▶│OpenRouter│
                                          ├─────▶│ Mistral  │
                                          └─────▶│  Groq    │
                                          │      └──────────┘
                                    73 tool calls
                                          │
                                          ▼
                                  Smartsheet API v2.0  ◀──── webhooks ──┐
                                          │                              │
                                          ▼                              │
                              Streaming · Tables · Images · Charts       │
                                          │                              │
                                          ▼                              │
                                      Chat UI ◀────── live fan-out ──────┘
                                          │
                                          ▼
                          SQLite (conversations · favorites · audit)

Running the Test Suite

246 green tests across unit, integration and e2e

246 tests · 3 layers · 0 leaks · ~3 min on a laptop.

pip install -r requirements-dev.txt

pytest                       # everything (246 tests, ~3min37s)
pytest -m unit               # 196 fast tests, <2s, no network
pytest -m integration        # 41 real Smartsheet API tests
pytest -m e2e                # 9 WebSocket end-to-end (stubbed LLM, no cost)

pytest --cov=backend --cov-report=html   # coverage report → htmlcov/
Layer Count Speed Network Notable coverage
unit 196 < 2 s none Rate limiter · LLM router · _friendly_error (no secrets leaked) · dispatch contract for all 73 tools · agent.run() loop (confirm, parse-error recovery, MAX_TOOL_ROUNDS, image/chart events) · SQLite CRUD · MCP smoke (52 tools registered)
integration 41 medium Smartsheet Real read calls + create→modify→delete lifecycle on a throwaway sheet · all FastAPI routes including /api/csv-to-sheet, /api/smartsheet-webhook (challenge + payload fan-out), favorites, conversations CRUD, audit, RGPD export, model switching
e2e 9 medium Smartsheet Full FastAPI lifespan · WebSocket handshake · agent loop with stubbed LLM · suggestions extraction · mid-stream cancel · destructive-tool confirm/reject · WS rate-limit response · multi-turn in one connection

Integration & e2e tests skip cleanly when SMARTSHEET_TOKEN / SHEET_ID aren't in .env. Tests never touch the production SQLite DB — each test gets its own temp file. LLM calls are stubbed by default; set ENABLE_LIVE_LLM=1 to opt into real provider calls.


Deployment

Option 1 — Docker (recommended)

cp .env.example .env      # fill in at least OPENAI_API_KEY (SMARTSHEET_TOKEN is optional - users now BYOT)
docker compose up -d --build
# → http://localhost:8000   (health: http://localhost:8000/health)

The container runs uvicorn backend.app:app as a non-root user on port 8000, exposes a /health endpoint for orchestrator probes, and reads secrets from .env.

Option 2 — Bare metal (systemd)

python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
uvicorn backend.app:app --host 0.0.0.0 --port 8000 --proxy-headers --forwarded-allow-ips '*'

Example /etc/systemd/system/smartsheet-controller.service:

[Unit]
Description=Smartsheet Controller
After=network.target

[Service]
Type=simple
User=smartsheet
WorkingDirectory=/opt/smartsheet-controller
EnvironmentFile=/opt/smartsheet-controller/.env
ExecStart=/opt/smartsheet-controller/.venv/bin/uvicorn backend.app:app \
  --host 127.0.0.1 --port 8000 --proxy-headers --forwarded-allow-ips '*'
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now smartsheet-controller
sudo journalctl -u smartsheet-controller -f

Reverse proxy (nginx + TLS + WebSockets)

server {
    listen 443 ssl http2;
    server_name chat.example.com;

    ssl_certificate     /etc/letsencrypt/live/chat.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/chat.example.com/privkey.pem;

    client_max_body_size 2m;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        # WebSocket upgrade (used by /ws/{session_id})
        proxy_set_header Upgrade           $http_upgrade;
        proxy_set_header Connection        "upgrade";
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }

    location = /health { proxy_pass http://127.0.0.1:8000/health; access_log off; }
}

server {
    listen 80;
    server_name chat.example.com;
    return 301 https://$host$request_uri;
}

Production notes

  • BYOT flow — end users paste their own Smartsheet token in the UI. The server stores it only in-memory for the session; sessions auto-expire after SESSION_IDLE_TIMEOUT seconds (default 1800).
  • Secrets — only LLM provider keys need to live in .env on the server (OPENAI_API_KEY, ANTHROPIC_API_KEY, ...). The SMARTSHEET_TOKEN in .env is only used for the "Quick Connect (dev)" button.
  • Rate limiting — per-session token buckets (LLM 60/min, WS 120/min) are applied automatically; Smartsheet 429s are retried with exponential backoff.
  • Logging — stdout is redacted of API tokens; set LOG_LEVEL=DEBUG to see more.
  • Health probeGET /health returns {"status": "ok", "sessions": N, "uptime": ...}.

Links

Smartsheet — official GitHub org @smartsheet (verified, SDKs Python · JS · Java · C#)
Smartsheet Platform — DevRel GitHub @smartsheet-platform (incl. their own MCP server)
Smartsheet API Docs smartsheet.redoc.ly
Smartsheet Developer Portal developers.smartsheet.com
Smartsheet Functions help.smartsheet.com/functions
Smartsheet Learning Center help.smartsheet.com
Smartsheet Community community.smartsheet.com
Model Context Protocol modelcontextprotocol.io
OpenAI Platform platform.openai.com
Anthropic Docs docs.anthropic.com



Talk to Your Smartsheet.

73 tools · 80 formulas · 5 LLMs · 246 green tests · Full voice · Streaming · History · Audit · MCP.

Your data listens. Your sheets respond. Your workflow accelerates.


Built with FastAPI · Smartsheet API · OpenAI · Anthropic · OpenRouter · Mistral · Groq · MCP

Smartsheet® and the Smartsheet logo are trademarks of Smartsheet Inc. (@smartsheet). This project is an independent community tool and is not endorsed by or affiliated with Smartsheet Inc.


About

Talk to Your Smartsheet - AI copilot with 53 tools, 80 formulas, voice control, streaming, and MCP server

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors