> **Building with AI coding agents?** Install the authstack plugin with one command. This equips your agent with accurate Scalekit implementation patterns.
>
> **Recommended** (the `-y` flags skip prompts, so the command runs without an interactive terminal):
> ```bash
> npx -y @scalekit-inc/cli setup -y
> ```
>
> Global:
> ```bash
> npm install -g @scalekit-inc/cli
> scalekit setup -y
> ```
>
> Supports Claude Code, Cursor, GitHub Copilot, Codex + skills for other Agent Skills-compatible agents in `~/.agents/skills`.
> Skills: integrate-agentkit, implement-saaskit, add-mcp-oauth, implement-sso, implement-scim.
> [Full setup guide](https://docs.scalekit.com/dev-kit/build-with-ai/)

---

# Connect AI agents to the Motion MCP server

The Motion MCP connector routes your AI agent's tool calls to Motion's own MCP server through Scalekit. Each user signs in to Motion once, and Scalekit stores and refreshes their tokens, so your agent never handles credentials. It comes with 14 tools.

**Authentication:** OAuth 2.1/DCR
**Categories:** Project Management, Productivity
**Tools:** 14: 13 read, 1 write, 0 destructive
**Users sign in with:** OAuth
**OAuth app:** Scalekit's or your own
**Built by:** Vendor MCP
**Try it:** [Playground in the Scalekit dashboard](https://app.scalekit.com/ws/signup?sk_intent=playground&provider=MOTIONMCP)

## What you can do

- **Analyze ad creatives**: pull performance insights, AI summaries, and video transcripts for your own ad creatives
- **Break down results**: view ad performance by age and gender and open saved reports
- **Research competitor brands**: search brands, list tracked competitors, and browse their creatives by date, format, or platform
- **Get brand context**: retrieve brand positioning, voice, messaging angles, and customer voice analysis

## Setup

1. ### Install the SDK

   **Node.js**

   ```bash
   npm install @scalekit-sdk/node dotenv
   ```

   **Python**

   ```bash
   pip install scalekit-sdk-python python-dotenv
   ```

2. ### Set your credentials

   Add your Scalekit credentials to your `.env` file. Find values in **[app.scalekit.com](https://app.scalekit.com)** > **Developers** > **API Credentials**.

   ```sh title=".env"
   SCALEKIT_ENVIRONMENT_URL=<your-environment-url>
   SCALEKIT_CLIENT_ID=<your-client-id>
   SCALEKIT_CLIENT_SECRET=<your-client-secret>
   ```

3. ### Create the Motion MCP connection

   In **AgentKit > Connections**, create a Motion MCP connection. The name you give it is the `connection_name` your code passes. See [Configure connections](/agentkit/connections/).

   Scalekit credentials are available for Motion MCP server, so you don't need to register an OAuth app.

4. ### Authorize a user and make your first call

   **Node.js** (`quickstart.mts`)

   ```typescript
   import { ScalekitClient } from '@scalekit-sdk/node'
   import 'dotenv/config'
   import { createInterface } from 'node:readline/promises'

   const scalekit = new ScalekitClient(
     process.env.SCALEKIT_ENVIRONMENT_URL,
     process.env.SCALEKIT_CLIENT_ID,
     process.env.SCALEKIT_CLIENT_SECRET,
   )
   const actions = scalekit.actions

   const connector = 'motionmcp'
   const identifier = 'user_123'

   // Generate an authorization link for the user
   const { link } = await actions.getAuthorizationLink({ connectionName: connector, identifier })
   console.log('Authorize Motion MCP:', link)
   const rl = createInterface({ input: process.stdin, output: process.stdout })
   await rl.question('Press Enter after authorizing...')
   rl.close()

   // Make your first call
   const result = await actions.executeTool({
     connector,
     identifier,
     toolName: 'motionmcp_get_auth_context',
     toolInput: {},
   })
   console.log(result)
   ```

   ```bash
   npx tsx quickstart.mts
   ```

   **Python** (`quickstart.py`)

   ```python
   import os
   from scalekit import ScalekitClient
   from dotenv import load_dotenv
   load_dotenv()

   scalekit_client = ScalekitClient(
       env_url=os.getenv("SCALEKIT_ENVIRONMENT_URL"),
       client_id=os.getenv("SCALEKIT_CLIENT_ID"),
       client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"),
   )
   actions = scalekit_client.actions

   connection_name = "motionmcp"
   identifier = "user_123"

   # Generate an authorization link for the user
   link_response = actions.get_authorization_link(
       connection_name=connection_name,
       identifier=identifier,
   )
   print("Authorize Motion MCP:", link_response.link)
   input("Press Enter after authorizing...")

   # Make your first call
   result = actions.execute_tool(
       tool_input={},
       tool_name="motionmcp_get_auth_context",
       connection_name=connection_name,
       identifier=identifier,
   )
   print(result)
   ```

   ```bash
   python quickstart.py
   ```

   Each user signs in once. See [Authorize a user](/agentkit/tools/authorize/) for the full flow and statuses.

## Tools

Pass the exact name to `execute_tool`, with an input like each tool's example. To ask for a tool that's missing, use the [request form](https://scalekitsupport.portal.usepylon.com/forms/request-a-connector-tool).

**Node.js**

```typescript
const result = await actions.executeTool({
  toolName: 'motionmcp_get_auth_context',
  toolInput: {},
  connector: 'motionmcp',
  identifier: 'user_123',
})
```

**Python**

```python
result = actions.execute_tool(
    tool_name="motionmcp_get_auth_context",
    tool_input={},
    connection_name="motionmcp",
    identifier="user_123",
)
```

`result.data` is the app's response as JSON, and `result.execution_id` (`executionId` in Node.js) is the ID of the call.

### `motionmcp_get_auth_context`

Get Auth Context · Read-only

Retrieve the authenticated user's organizations and workspaces. Returns the workspaceId required by all other Motion tools.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs: none.

Example input: `{}`

### `motionmcp_get_brand_by_domain`

Get Brand By Domain · Read-only

Resolve a brandId from a website domain or URL. Returns null if no brand is found for the given domain.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `brandUrl` (`string`, required): Brand URL or domain, for example `https://example.com`
- `workspaceId` (`string`, required): The workspace ID for authorization

Example input: `{"brandUrl":"<brandUrl>","workspaceId":"<workspaceId>"}`

### `motionmcp_get_creative_insights`

Get Creative Insights · Read-only

Retrieve creative performance insights for your own ads in a workspace. Either datePreset or both startDate and endDate must be provided.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `insightType` (`string`, required): Primary metric to sort/rank creatives by. One of: `SPEND`, `SCALING`, `HOOK`, `ROAS`, `PURCHASES`, `PURCHASE_VALUE`, `CTR_ALL`, `CPA`, `CPC`.
- `organizationId` (`string`, required): The organization ID from get_auth_context
- `workspaceId` (`string`, required): The workspace ID from get_auth_context
- `chartKPIs` (`array`, optional): Optional KPI fields to include in chart KPI metrics.
- `creativeAssetIds` (`array`, optional): Optional creative asset IDs to narrow results.
- `datePreset` (`string`, optional): Predefined date range. Omit if using startDate/endDate. One of: `TODAY`, `YESTERDAY`, `THIS_MONTH`, `LAST_MONTH`, `LAST_7_DAYS`, `LAST_14_DAYS`, `LAST_30_DAYS`, `LAST_90_DAYS`, `CUSTOM`.
- `endDate` (`string`, optional): Custom end date (YYYY-MM-DD). Requires datePreset=CUSTOM.
- `filters` (`array`, optional): Nested filter groups to narrow which creatives are returned. Outer array = AND (all groups must pass); inner array = OR (any filter in a group can match). For text fields (campaignName, adsetName, adName): use "value" (singular) for case-insensitive substring match, or "values" (array) for exact match. For metric fields: set "metric": true and use "value" for thresholds or "values" for ranges. Example: [[{"field":"spend","type":"GREATER_THAN","value":"100","metric":true}],[{"field":"campaignName","type":"includes","value":"Prospecting"}]] returns creatives where spend > 100 AND campaign name contains "Prospecting".
- `groupBy` (`string`, optional): How to group ranked rows. Options: 'creative' (default — one row per creative asset), 'adId' (one row per ad — for ad-level optimization, comparing same creative across ad sets, deciding which ad to pause/scale), 'name' (by ad name), 'copy' (by ad body text — 'which copy performs best?'), 'headline' (by headline text), 'landingPage' (by destination URL — 'which landing page converts best?'). One of: `creative`, `adId`, `name`, `copy`, `headline`, `landingPage`.
- `includeEntityCategoryValues` (`boolean`, optional): Include the full taxonomy catalog (all possible values) per glossary category. Default false — only the values applied to each creative are returned. Set true when you need to see all available tags for coverage gap analysis. Default: `false`.
- `includeGlossary` (`boolean`, optional): Include creative taxonomy/glossary tags per creative. Default false to minimize payload. Set true for creative pattern analysis. Default: `false`.
- `insightGroups` (`array`, optional): Metric groups per creative. Defaults: spendState, performance, motion, click.
- `limit` (`integer`, optional): Max number of creatives to return
- `startDate` (`string`, optional): Custom start date (YYYY-MM-DD). Requires datePreset=CUSTOM.
- `tableKPIs` (`array`, optional): Optional KPI fields to include in table KPI metrics.
- `withAggregatedInsights` (`boolean`, optional): Include account-level aggregated metrics. Default: `false`.

Example input: `{"insightType":"SPEND","organizationId":"<organizationId>","workspaceId":"<workspaceId>"}`

### `motionmcp_get_creative_summary`

Get Creative Summary · Read-only

Fetch a compact AI-generated summary for a specific creative asset in a workspace.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `creativeEntityId` (`string`, required): Mongo ObjectId of the creative entity
- `creativeFormat` (`string`, required): Creative format from the source tool. Pass through the source value; `unknown` may fail if no compatible summary prompt exists. One of: `video`, `image`, `unknown`.
- `creativeOrigin` (`string`, required): Source/origin of the creative. One of: `metaCreativeAsset`, `tiktokCreativeAsset`, `youtubeCreativeAsset`, `linkedinCreativeAsset`, `metaAdLibraryCreative`, `tiktokAdLibraryCreative`, `instagramAdLibraryCreative`, `tiktokOrganicAdLibraryCreative`.
- `organizationId` (`string`, required): The organization ID from get_auth_context
- `workspaceId` (`string`, required): The workspace ID from get_auth_context

Example input: `{"creativeEntityId":"<creativeEntityId>","creativeFormat":"video","creativeOrigin":"metaCreativeAsset","organizationId":"<organizationId>","workspaceId":"<workspaceId>"}`

### `motionmcp_get_creative_transcript`

Get Creative Transcript · Read-only

Fetch the spoken transcript for a video creative by its entity ID and workspace.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `creativeEntityId` (`string`, required): Mongo ObjectId of the creative entity
- `creativeOrigin` (`string`, required): Source/origin of the creative. One of: `metaCreativeAsset`, `tiktokCreativeAsset`, `youtubeCreativeAsset`, `linkedinCreativeAsset`, `metaAdLibraryCreative`, `tiktokAdLibraryCreative`, `instagramAdLibraryCreative`, `tiktokOrganicAdLibraryCreative`.
- `workspaceId` (`string`, required): The workspace ID from get_auth_context
- `creativeFormat` (`string`, optional): Creative format (video or image). Transcript data is only available for video creatives; image creatives will return empty transcript data. One of: `video`, `image`. Default: `video`.

Example input: `{"creativeEntityId":"<creativeEntityId>","creativeOrigin":"metaCreativeAsset","workspaceId":"<workspaceId>"}`

### `motionmcp_get_glossary_values`

Get Glossary Values · Read-only

Return the workspace's glossary taxonomy — categories and their allowed tag values.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `workspaceId` (`string`, required): The workspace ID
- `categoryNames` (`array`, optional): Optional list of glossary category internal names
- `customOnly` (`boolean`, optional): Return only custom glossary categories. Default: `false`.
- `includeCreativeIds` (`boolean`, optional): Include creative IDs in value buckets. Default: `false`.

Example input: `{"workspaceId":"<workspaceId>"}`

### `motionmcp_get_inspo_brand_context`

Get Inspo Brand Context · Read-only

Retrieve strategic brand context for an Inspo brand, including positioning, voice, tone, messaging angles, and customer voice analysis.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `brandId` (`string`, required): The brand ID to get Inspo context for
- `workspaceId` (`string`, required): The workspace ID for authorization

Example input: `{"brandId":"<brandId>","workspaceId":"<workspaceId>"}`

### `motionmcp_get_inspo_creatives`

Get Inspo Creatives · Read-only

Retrieve Inspo creatives for one or more brands by brand ID, with optional filters for date range, format, and platform.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `brandIds` (`array`, required): One or more brand IDs to fetch Inspo creatives for
- `launchDate` (`string`, optional): Optional launch date window. When omitted, returns creatives regardless of launch date. Available: LAST_7_DAYS, LAST_14_DAYS, LAST_30_DAYS, LAST_90_DAYS. One of: `LAST_7_DAYS`, `LAST_14_DAYS`, `LAST_30_DAYS`, `LAST_90_DAYS`.
- `limit` (`integer`, optional): Max creatives to return. Defaults to 50. For larger pulls, increase up to 1000. Default: `50`.
- `sort` (`string`, optional): Sort order by launch date. One of: `NEWEST`, `OLDEST`. Default: `NEWEST`.
- `status` (`string`, optional): Optional ad status filter. One of: `ACTIVE`, `INACTIVE`, `ACTIVE_AND_INACTIVE`.
- `withGlossary` (`boolean`, optional): Include Motion glossary tags for returned creatives. Default: `false`.

Example input: `{"brandIds":[]}`

### `motionmcp_get_reports`

Get Reports · Read-only

Return saved reports for a workspace. Omit reportId to list all reports; provide reportId to fetch a specific report with full data.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `organizationId` (`string`, required): The organization ID from get_auth_context
- `workspaceId` (`string`, required): The workspace ID from get_auth_context
- `reportId` (`string`, optional): Specific report ID. Omit to list all reports.
- `reportTypes` (`array`, optional): Filter by report type when listing. Omit to include all types.

Example input: `{"organizationId":"<organizationId>","workspaceId":"<workspaceId>"}`

### `motionmcp_get_workspace_brand`

Get Workspace Brand · Read-only

Return the workspace's own brand reference ID for use with brand context and competitor tools.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `workspaceId` (`string`, required): The workspace ID for authorization

Example input: `{"workspaceId":"<workspaceId>"}`

### `motionmcp_get_workspace_competitors`

Get Workspace Competitors · Read-only

List competitor brands the workspace is tracking, with optional filtering by specific brand IDs.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `workspaceId` (`string`, required): The workspace ID for authorization
- `brandIds` (`array`, optional): Optional competitor brand IDs to fetch. Resolve IDs first when narrowing to a specific competitor set.

Example input: `{"workspaceId":"<workspaceId>"}`

### `motionmcp_search_brands`

Search Brands · Read-only

Search for brands by name or domain query. Returns matching brands with optional verbose catalog fields.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `query` (`string`, required): Search query (brand name or domain)
- `workspaceId` (`string`, required): The workspace ID for authorization
- `verbose` (`boolean`, optional): When true, include the full per-brand catalog (visual formats, top landing pages). Defaults to false for lean discovery responses.

Example input: `{"query":"Show me top performing creatives for Q1","workspaceId":"<workspaceId>"}`

### `motionmcp_submit_feedback`

Submit Feedback · Read-only

Submit feedback about this Motion MCP server to the Motion product team.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `category` (`string`, required): Type of feedback: 'bug' for tool errors or incorrect behavior, 'feature_request' for missing capabilities, 'workflow_friction' for flows that are overly complex. One of: `bug`, `feature_request`, `workflow_friction`.
- `comment` (`string`, required): Concise, actionable description. For bugs: what you did, what happened, what you expected. For feature requests: what is missing and why. For workflow friction: what the user tried and how it could be simpler.
- `intent` (`string`, required): Briefly describe the wider context task, and why this tool was chosen. Omit argument values, PII/secrets. Use English.
- `query` (`string`, optional): The user's original question or request that led to this feedback. Include enough context for the Motion team to reproduce the issue — e.g. 'Show me top performing creatives for Q1' or 'Compare my hook rates to competitors'. Omit PII.
- `tags` (`array`, optional): Optional tags to categorize feedback (e.g. 'ux', 'performance', 'accuracy', 'missing-data').
- `toolName` (`string`, optional): The name of the specific Motion MCP tool this feedback is about.

Example input: `{"category":"bug","comment":"<comment>","intent":"<intent>"}`

### `motionmcp_get_demographic_breakdown`

Get Demographic Breakdown · Write

Return ad performance broken down by age and gender demographics for a workspace.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `organizationId` (`string`, required): The organization ID from get_auth_context
- `workspaceId` (`string`, required): The workspace ID from get_auth_context
- `datePreset` (`string`, optional): Predefined date range. One of: `TODAY`, `YESTERDAY`, `THIS_MONTH`, `LAST_MONTH`, `LAST_7_DAYS`, `LAST_14_DAYS`, `LAST_30_DAYS`, `LAST_90_DAYS`.

Example input: `{"organizationId":"<organizationId>","workspaceId":"<workspaceId>"}`

## Related

Other Project Management connectors ([all 31](/agentkit/connectors/?category=project-management)):

- [Notion](/agentkit/connectors/notion/): Scalekit connector, OAuth, 51 tools
- [Linear](/agentkit/connectors/linear/): Scalekit connector, OAuth, 62 tools
- [Airtable](/agentkit/connectors/airtable/): Scalekit connector, OAuth, 26 tools


---

## More Scalekit documentation

| Resource | What it contains | When to use it |
|----------|-----------------|----------------|
| [/llms.txt](/llms.txt) | Structured index with routing hints per product area | Start here — find which documentation set covers your topic before loading full content |
| [/llms-full.txt](/llms-full.txt) | Complete documentation for all Scalekit products in one file | Use when you need exhaustive context across multiple products or when the topic spans several areas |
| [sitemap-0.xml](https://docs.scalekit.com/sitemap-0.xml) | Full URL list of every documentation page | Use to discover specific page URLs you can fetch for targeted, page-level answers |
