About Motion MCP Server
Motion MCP Server is an MCP server for the Motion task and calendar app, letting LLM clients manage tasks, search projects and check schedules through conversation. It suits Motion users on desktop, web and mobile, and runs either locally via npx or as a Cloudflare Workers remote server.
Key features
- 01Create, list, update, delete, move and unassign tasks
- 02Resolve workspaces and projects by name
- 03List uncompleted tasks across all workspaces with filters
- 04Manage comments, users, statuses and custom fields
- 05Manage recurring task templates
- 06Limit exposed tools through MOTION_MCP_TOOLS
Use cases
- 01Ask Claude or ChatGPT which tasks are due this week
- 02Create prioritized, labeled tasks through conversation
- 03Access Motion tasks from Claude mobile or web via a remote server
MCP support
This project is an MCP server that exposes 10 Motion tools to MCP clients, covering tasks, projects, workspaces and search. The remote deployment uses Streamable HTTP and controls access with a secret in the path or a Bearer header.
Configuration
Local server config is the same for every client. Copy it into your client’s MCP config file.
Tools
10Saved tool list · updated 3w ago
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | No | Task name (required for create, optional for list as case-insensitive substring search, filtered client-side) |
| limit | number | No | Maximum number of tasks to return (for list and list_all_uncompleted) |
| labels | array | No | Array of label names. Applied to the task on create/update; filters results on list |
| status | any | No | Filter by status (for list). Single string or array of strings (e.g., ["Todo", "Completed"]). Without status or includeAllStatuses, only active (non-resolved) tasks are returned. Use motion_statuses to list valid values per workspace. |
| taskId | string | No | Task ID (required for get/update/delete/move/unassign) |
| dueDate | string | No | Due date (for create/update) or filter (for list and list_all_uncompleted). Format: YYYY-MM-DD, a full ISO 8601 timestamp with offset, or relative like 'today', 'tomorrow'. FILTER (list, list_all_uncompleted): an inclusive upper bound at day granularity in the account timezone — returns every task due ON OR BEFORE that day, which INCLUDES overdue tasks. So dueDate:'today' answers "what's due today?" (including anything overdue) in a single call. There is no exact-date or date-range filter; to show only tasks due exactly on a day, filter the returned results by their Due Date yourself. CREATE/UPDATE: a date-only value is stored as end of day (23:59:59) in the account's schedule timezone when all schedules agree on one, so it renders back as the same calendar day; it falls back to end-of-day UTC when no single zone is resolvable. Pass an explicit ISO timestamp with an offset to control the exact instant. Relative keywords resolve against the same account timezone, falling back to UTC otherwise. |
| assignee | string | No | Assignee name, email, or the 'me' shortcut. Resolved to an ID automatically for list, list_all_uncompleted, create, update, and move. A name that cannot be resolved returns an error. Must be non-empty; use the unassign operation to clear a task's assignee. |
| duration | any | No | Minutes (as number) or 'NONE'/'REMINDER' (as string) |
| priority | enum | No | Task priority: ASAP, HIGH, MEDIUM, LOW. Set on create/update; filters results on list and list_all_uncompleted (filtered client-side)ASAP | HIGH | MEDIUM | LOW |
| operation | enum | Yes | Operation to performcreate | list | get | update | delete | move | unassign | list_all_uncompleted |
| projectId | string | No | Filter by project (for list) |
| assigneeId | string | No | Assignee user ID, or the 'me' shortcut for the current user. Filters on list/list_all_uncompleted; sets the assignee on create/update; reassigns on move. The 'me' shortcut is resolved to a concrete ID for all of these. Must be non-empty; use the unassign operation to clear a task's assignee. |
| description | string | No | Task description |
| projectName | string | No | Project name (alternative to projectId) |
| workspaceId | string | No | Filter by workspace (for list). Ignored by list_all_uncompleted, which always spans every workspace. |
| autoScheduled | any | No | Auto-scheduling configuration. Can be either: - A schedule name string: "Work Hours" (simple, no start date) - An object for full control: {"schedule": "Work Hours", "startDate": "2025-03-05", "deadlineType": "SOFT"} When the user specifies a start date, you MUST use the object form. Use motion_schedules to see available schedule names. |
| workspaceName | string | No | Filter by workspace name (for list). Ignored by list_all_uncompleted, which always spans every workspace. |
| completedAfter | string | No | Filter (for list): keep only tasks COMPLETED on or after this local calendar date. Format: YYYY-MM-DD or relative like 'today', 'yesterday'. Filtered client-side and auto-includes completed/resolved tasks, so 'what did I get done this week?' is completedAfter set to the week's start date. Combine with completedBefore for a window. Note: this filters on completion date, not due date; a very high-volume window can be capped by pagination (reported in the response), not silently. |
| completedBefore | string | No | Filter (for list): keep only tasks COMPLETED on or before this local calendar date. Format: YYYY-MM-DD or relative like 'today'. Filtered client-side; pair with completedAfter to bound a completion window. |
| targetWorkspaceId | string | No | Target workspace ID (required for move operation). Move transfers a task between workspaces — project-level targeting is not supported by the Motion API. |
| includeAllStatuses | boolean | No | When true, returns tasks across all statuses including completed/resolved (for list). Cannot be combined with status filter. |
Details
From the project READMEMotion MCP Server
Motion is an AI-powered calendar and task management app that auto-schedules your work. This MCP server bridges Motion's API with LLMs like Claude and ChatGPT via the Model Context Protocol, so you can manage tasks, search projects, check your schedule, and more — all through natural conversation. It works on desktop, web, and mobile.
Preview
Click the image above to view full size
Getting Started
Prerequisites: Node.js 20+ and a Motion API key.
Local Setup (npx)
For desktop MCP clients — Claude Desktop, Claude Code, Cursor, and similar.
Add to your claude_desktop_config.json:
{
"mcpServers": {
"motion": {
"command": "npx",
"args": ["motionmcp"],
"env": {
"MOTION_API_KEY": "your_api_key"
}
}
}
}
Test from the command line:
MOTION_API_KEY=your_api_key npx motionmcp
Tip:
npxalways runs the latest published version — no install needed.
Remote Setup (Cloudflare Workers)
For mobile and web clients — Claude mobile/web, ChatGPT mobile/web, or any HTTP MCP client.
One-click deploy
After deploy, set your secrets in the Cloudflare dashboard (Workers > your worker > Settings > Variables):
MOTION_API_KEY— your Motion API keyMOTION_MCP_SECRET— a random string (generate withopenssl rand -hex 16)
Manual deploy
# Set secrets
npx wrangler secret put MOTION_API_KEY
npx wrangler secret put MOTION_MCP_SECRET # use: openssl rand -hex 16
# Deploy
npm run worker:deploy
Your MCP URL will be:
https://motion-mcp-server.YOUR_SUBDOMAIN.workers.dev/mcp/YOUR_SECRET
Use exactly that address. The secret goes at the end of the path and nothing follows it. The server speaks MCP Streamable HTTP on that single endpoint; do not append /sse or any other sub-path.
Clients that can send headers can keep the secret out of the URL instead: point them at https://motion-mcp-server.YOUR_SUBDOMAIN.workers.dev/mcp and send Authorization: Bearer YOUR_SECRET.
Connecting from Claude
- Go to claude.ai > Settings > Connectors
- Add your MCP URL
- The server syncs automatically to the Claude mobile app
For Claude Code, use the Streamable HTTP transport:
claude mcp add --transport http motion https://motion-mcp-server.YOUR_SUBDOMAIN.workers.dev/mcp --header "Authorization: Bearer YOUR_SECRET"
In Claude Desktop, add the same URL as a remote server of type http (not sse).
Connecting from ChatGPT
- Go to ChatGPT Settings > Connectors
- Add your MCP URL
Security: The secret in the URL prevents casual discovery. Treat the full URL like a password — don't share it publicly.
Transport: Only Streamable HTTP is served. The older HTTP+SSE transport (a
GETstream plus a/messageendpoint) was retired in the move to a stateless server; a client configured with transport typessemust be switched tohttp.
Tool configuration works the same as the local server. Set MOTION_MCP_TOOLS in wrangler.toml under [vars], or override via wrangler secret put MOTION_MCP_TOOLS.
For local Worker development, see DEVELOPER.md.
API Key
The server reads your Motion API key from the MOTION_API_KEY environment variable.
Inline (npx):
MOTION_API_KEY=your-key npx motionmcp
.env file (when running from source via npm):
MOTION_API_KEY=your-key
When using
npx, prefer the inline environment variable sincenpxwon't read a local.envfile.
Tool Configuration
All 10 tools are enabled by default. If you run multiple MCP servers and want to reduce tool selection noise, you can limit which tools are exposed via the MOTION_MCP_TOOLS environment variable:
| Level | Tools | Description |
|---|---|---|
| minimal | 3 | Tasks, projects, workspaces only |
| essential | 8 | Adds users, search, comments, schedules, statuses |
| complete (default) | 10 | Full API access including custom fields and recurring tasks |
| custom | varies | Pick exactly the tools you need |
Custom example:
MOTION_MCP_TOOLS=custom:motion_tasks,motion_projects,motion_search npx motionmcp
Tools Reference
motion_tasks
Operations: create, list, list_all_uncompleted, get, update, delete, move, unassign
The primary tool for task management. Supports all Motion API parameters including name, description, priority, dueDate, duration, labels, assigneeId, and autoScheduled. You can reference workspaces and projects by name — the server resolves them automatically.
list_all_uncompleted spans every workspace in one call (it ignores workspaceId/workspaceName) and honors the dueDate and priority filters, so "what's due this week across all my workspaces?" resolves directly. On list, dueDate is an inclusive on-or-before-day bound that includes overdue tasks (so dueDate: "today" answers "what's due today?"), and completedAfter / completedBefore bound by completion date in your account's time zone for "what did I get done this week?". Dates are interpreted in your Motion account's time zone, and list responses lead with a header naming that zone and today's local date.
{
"operation": "create",
"name": "Complete API integration",
"workspaceName": "Development",
"projectName": "Release Cycle Q2",
"dueDate": "2025-06-15T09:00:00Z",
"priority": "HIGH",
"labels": ["api", "release"]
}
motion_projects
Operations: create, list, get
Manage Motion projects. Workspace and project names are fuzzy-matched, and the server auto-selects your "Personal" workspace if none is specified.
{"operation": "create", "name": "New Project", "workspaceName": "Personal"}
motion_workspaces
Operations: list, get
List and inspect workspaces.
motion_users
Operations: list, current
List users in a workspace or get the current authenticated user.
motion_search
Operations: content
Search tasks and projects by query across a workspace.
{"operation": "content", "query": "API integration", "workspaceName": "Development"}
motion_comments
Operations: list, create
Read and add comments on tasks and projects.
{"operation": "create", "taskId": "task_123", "content": "Updated the API endpoints as discussed"}
motion_schedules
Operations: list
Retrieve user schedules, showing each day's working hours (start-end per day) and time zones. These are recurring working-hour templates only — they do not expose actual calendar events or meetings, so they cannot by themselves show a true free/busy picture; combine with tasks' scheduledStart/scheduledEnd to see what Motion has auto-booked.
motion_custom_fields
Operations: list, create, delete, add_to_project, remove_from_project, add_to_task, remove_from_task
Define and manage custom fields across workspaces, projects, and tasks.
{
"operation": "create",
"name": "Sprint",
"type": "DROPDOWN",
"options": ["Sprint 1", "Sprint 2", "Sprint 3"],
"workspaceName": "Development"
}
motion_recurring_tasks
Operations: list, create, delete
Manage recurring task templates.
{
"operation": "create",
"name": "Weekly Team Standup",
"recurrence": "WEEKLY",
"projectName": "Team Meetings",
"daysOfWeek": ["MONDAY", "WEDNESDAY", "FRIDAY"],
"duration": 30
}
motion_statuses
Operations: list
List available statuses for a workspace.
Advanced Configuration
Minimal setup (3 tools only):
{
"mcpServers": {
"motion": {
"command": "npx",
"args": ["motionmcp"],
"env": {
"MOTION_API_KEY": "your_api_key",
"MOTION_MCP_TOOLS": "minimal"
}
}
}
}
Custom tools selection:
{
"mcpServers": {
"motion": {
"command": "npx",
"args": ["motionmcp"],
"env": {
"MOTION_API_KEY": "your_api_key",
"MOTION_MCP_TOOLS": "custom:motion_tasks,motion_projects,motion_search"
}
}
}
}
Using your local workspace (npm):
{
"mcpServers": {
"motion": {
"command": "npm",
"args": ["run", "mcp:dev"],
"cwd": "/absolute/path/to/your/MotionMCP",
"env": {
"MOTION_API_KEY": "your_api_key"
}
}
}
}
See the full developer setup in DEVELOPER.md.
Debugging
- Logs output to
stderrin JSON format - Check for missing keys, workspace/project names, and permissions
- Use
motion_workspaces(list) andmotion_projects(list) to validate IDs
{
"level": "info",
"msg": "Task created successfully",
"method": "createTask",
"taskId": "task_789",
"workspace": "Development"
}
License
Apache-2.0 License
For more information, see the full Motion API docs or Model Context Protocol docs.
Comments
New to MCP?
From what the protocol is to installing your first server, these answers cover most first questions.
An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.
