Skip to main content
Glama
bencanda

Motion MCP Server

by bencanda
README.md
![NPM Version](https://img.shields.io/npm/v/motionmcp)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)

# Motion MCP Server

[Motion](https://www.usemotion.com/) 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](https://modelcontextprotocol.io/docs/), so you can manage tasks, search projects, check your schedule, and more — all through natural conversation. It works on desktop, web, and mobile.

## Preview

<a href="sample.png"><img src="sample.png" alt="Motion MCP Server Preview" width="400" /></a>

*Click the image above to view full size*

## Getting Started

**Prerequisites:** Node.js 20+ and a [Motion API key](https://app.usemotion.com/settings/api).

### Local Setup (npx)

For desktop MCP clients — Claude Desktop, Claude Code, Cursor, and similar.

Add to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "motion": {
      "command": "npx",
      "args": ["motionmcp"],
      "env": {
        "MOTION_API_KEY": "your_api_key"
      }
    }
  }
}
```

Test from the command line:

```bash
MOTION_API_KEY=your_api_key npx motionmcp
```

> **Tip:** `npx` always 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

[![Deploy to Cloudflare Workers](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/devondragon/MotionMCP)

After deploy, set your secrets in the Cloudflare dashboard (Workers > your worker > Settings > Variables):
- `MOTION_API_KEY` — your Motion API key
- `MOTION_MCP_SECRET` — a random string (generate with `openssl rand -hex 16`)

#### Manual deploy

```bash
# 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

1. Go to [claude.ai](https://claude.ai) > Settings > Connectors
2. Add your MCP URL
3. The server syncs automatically to the Claude mobile app

For Claude Code, use the Streamable HTTP transport:

```bash
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

1. Go to ChatGPT Settings > Connectors
2. 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 `GET` stream plus a `/message` endpoint) was retired in the move to a stateless server; a client configured with transport type `sse` must be switched to `http`.

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](./DEVELOPER.md).

### API Key

The server reads your Motion API key from the `MOTION_API_KEY` environment variable.

**Inline (npx):**
```bash
MOTION_API_KEY=your-key npx motionmcp
```

**`.env` file (when running from source via npm):**
```bash
MOTION_API_KEY=your-key
```

> When using `npx`, prefer the inline environment variable since `npx` won't read a local `.env` file.

## 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:
```bash
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.

```json
{
  "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.

```json
{"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.

```json
{"operation": "content", "query": "API integration", "workspaceName": "Development"}
```

### motion_comments
**Operations:** `list`, `create`

Read and add comments on tasks and projects.

```json
{"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.

```json
{
  "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.

```json
{
  "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):**
```json
{
  "mcpServers": {
    "motion": {
      "command": "npx",
      "args": ["motionmcp"],
      "env": {
        "MOTION_API_KEY": "your_api_key",
        "MOTION_MCP_TOOLS": "minimal"
      }
    }
  }
}
```

**Custom tools selection:**
```json
{
  "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):**
```json
{
  "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](./DEVELOPER.md).

## Debugging

- Logs output to `stderr` in JSON format
- Check for missing keys, workspace/project names, and permissions
- Use `motion_workspaces` (list) and `motion_projects` (list) to validate IDs

```json
{
  "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](https://docs.usemotion.com/) or [Model Context Protocol docs](https://modelcontextprotocol.io/docs/).

TDQS

B3.3/5.0

Scored across 10 tools

Disambiguation4/5

Each tool targets a distinct Motion resource (tasks, projects, recurring tasks, schedules, statuses, workspaces, users, comments, custom fields), so boundaries are generally clear. The main potential overlap is between motion_search and the list operations of motion_tasks/motion_projects, but the search description clarifies its query-based purpose.

Naming Consistency5/5

Every tool follows the identical motion_<resource> pattern with a consistent prefix and snake_case resource nouns. The convention is resource-oriented rather than verb_noun, but it is applied uniformly across all ten tools.

Tool Count5/5

Ten tools is well-scoped for a project/task management server, with each tool mapping to a coherent domain resource. No tool feels redundant or artificially split.

Completeness4/5

Tasks have full lifecycle coverage (create/list/get/update/delete/move/unassign), and custom fields, comments, statuses, and search round out the surface well. However, projects lack update/delete, recurring tasks lack update/get, and there is no subtask support, leaving minor gaps agents must work around.