motion-mcp
A remote MCP server that connects Claude to Motion — read and manage your tasks, projects, and comments using plain English.
Features
- 11 tools — read and write tasks, projects, comments, schedules, and recurring tasks
- Per-user auth — each person connects their own Motion account via OAuth; data is fully isolated
- Works with Claude.ai and Claude Code
Tools
| Tool | Description | |---|---| | get_tasks | Get tasks (defaults to current user) | | get_workspaces | List all workspaces | | get_projects | List projects in a workspace | | get_schedule | Get work schedule and timezone | | get_task_comments | Get comments on a task | | get_recurring_tasks | Get recurring task definitions (current user) | | create_task | Create a new task | | update_task | Update task fields or status | | delete_task | Delete a task | | create_comment | Add a comment to a task | | update_project | Update project fields |
Usage
Add to Claude Code: ``bash claude mcp add motion https://<your-deployment>/mcp --transport http --scope user ``
Claude will open a browser window to connect your Motion account. You'll need your Motion API key from app.usemotion.com/settings/api.
For Claude.ai, add your deployment URL as a custom connector in Settings → Connectors (requires team admin to approve first).
Self-hosting
Prerequisites
- Node.js 20+
- Fly.io account (or any hosting that supports persistent Node.js processes)
Setup
git clone <repo>
cd motion-mcp
npm install
cp .env.example .env
# Fill in .env
npm run dev
Environment Variables
| Variable | Required | Description | |---|---|---| | JWT_SECRET | yes | Secret for signing access tokens — openssl rand -hex 32 | | ENCRYPTION_KEY | yes | AES-256 key for encrypting stored API keys — openssl rand -hex 32 | | BASE_URL | yes | Public URL of your deployment e.g. https://your-app.fly.dev | | DB_PATH | no | Path to SQLite file (default: ./motion.db) | | PORT | no | Port to listen on (default: 3000) |
Deploy to Fly.io
fly launch --no-deploy
fly volumes create motion_data --size 1 --region sjc --yes
fly scale count 1 --yes
fly secrets set \
JWT_SECRET=$(openssl rand -hex 32) \
ENCRYPTION_KEY=$(openssl rand -hex 32) \
BASE_URL=https://$(fly info --json | python3 -c "import sys,json; print(json.load(sys.stdin)['Hostname'])")
fly deploy
Add to your fly.toml under [env]: ```toml DB_PATH = "/data/motion.db"
[[mounts]] source = "motion_data" destination = "/data" ```
Note: Keep
fly scale count 1— SQLite cannot be shared across multiple machines.
Register Claude with your instance
claude mcp add motion https://<your-app>.fly.dev/mcp --transport http --scope user
Auth flow
- User adds the MCP URL to Claude
- Claude detects OAuth support via
/.well-known/oauth-authorization-server - Browser opens to
/oauth/authorize - User pastes their Motion API key — validated live against Motion
- Key is stored AES-256-GCM encrypted in SQLite
- Claude receives a 90-day JWT stored in its config
- All requests are scoped to that user's Motion data
Tech stack
- TypeScript, Node.js
@modelcontextprotocol/sdk- Express
- better-sqlite3, jsonwebtoken
License
MIT






