Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 199 additions & 0 deletions packages/mcp-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
# @shopify/mcp-server

An [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that lets AI assistants interact with the [Shopify CLI](https://shopify.dev/docs/api/shopify-cli). Works with any MCP client — Claude Code, Claude Desktop, Cursor, Windsurf, and others.

The server wraps the `shopify` CLI binary as a subprocess. It doesn't depend on CLI internals, so it works with any installed version of Shopify CLI.

## Prerequisites

- [Node.js](https://nodejs.org/) >= 20.10
- [Shopify CLI](https://shopify.dev/docs/api/shopify-cli) installed and available on your `PATH`:

```sh
npm install -g @shopify/cli
shopify version
```

## Setup

### Claude Code

```sh
claude mcp add shopify-cli -- npx @shopify/mcp-server
```

To set a default store:

```sh
claude mcp add shopify-cli -e SHOPIFY_FLAG_STORE=my-store.myshopify.com -- npx @shopify/mcp-server
```

### Claude Desktop

Add to your `claude_desktop_config.json`:

```json
{
"mcpServers": {
"shopify-cli": {
"command": "npx",
"args": ["@shopify/mcp-server"],
"env": {
"SHOPIFY_FLAG_STORE": "my-store.myshopify.com"
}
}
}
}
```

### Cursor / Windsurf / Other MCP Clients

Add to your MCP configuration (exact location varies by client):

```json
{
"mcpServers": {
"shopify-cli": {
"command": "npx",
"args": ["@shopify/mcp-server"]
}
}
}
```

## Tools

The server exposes three tools:

### `shopify_cli_run`

Run any Shopify CLI command.

```
shopify_cli_run({ command: "theme list --json" })
shopify_cli_run({ command: "theme push --force --json" })
shopify_cli_run({ command: "app deploy --force" })
```

The server automatically:

- Appends `--no-color` to all commands
- Injects store, auth token, and path from environment config
- Detects authentication errors and suggests using `shopify_auth_login`
- Auto-detects and pretty-prints JSON output

### `shopify_cli_help`

Get help for any CLI command. Returns the CLI's own help text plus tips for non-interactive usage.

```
shopify_cli_help({}) # All top-level commands
shopify_cli_help({ command: "theme" }) # All theme subcommands
shopify_cli_help({ command: "theme push" }) # Flags for theme push
shopify_cli_help({ command: "app deploy" }) # Flags for app deploy
```

### `shopify_auth_login`

Log in to your Shopify account. Opens a browser for OAuth authentication with a 5-minute timeout.

```
shopify_auth_login({}) # Login (uses configured store)
shopify_auth_login({ store: "my-store.myshopify.com" }) # Login to a specific store
```

## Authentication

The Shopify CLI caches OAuth sessions to disk. Once you log in, subsequent commands reuse the cached session automatically — no token management needed.

**First-time setup:** When you (or the AI) run a command before logging in, the server detects the auth error and suggests using the `shopify_auth_login` tool, which opens your browser for OAuth.

**Headless / CI environments:** Set `SHOPIFY_CLI_THEME_TOKEN` to a token from the [Theme Access app](https://shopify.dev/docs/themes/tools/theme-access) or an Admin API token to skip browser-based login entirely.

## Configuration

All configuration is through environment variables. Set them in your MCP client config's `env` block.

| Variable | Description | Default |
|----------|-------------|---------|
| `SHOPIFY_FLAG_STORE` | Default store URL (e.g. `my-store.myshopify.com`) | — |
| `SHOPIFY_CLI_THEME_TOKEN` | Theme Access / Admin API token for headless auth | — |
| `SHOPIFY_FLAG_PATH` | Default project directory | — |
| `SHOPIFY_CLI_PATH` | Path to the `shopify` binary | `shopify` |
| `SHOPIFY_MCP_TIMEOUT` | Command timeout in milliseconds | `120000` |

These are injected as environment variables into the CLI subprocess, where the CLI reads them as default values. Flags passed explicitly in a command (e.g. `--store other-store.myshopify.com`) take precedence.

## Examples

**List themes in a store:**
> "Show me all the themes in my store"
>
> → `shopify_cli_run({ command: "theme list --json" })`

**Push theme changes:**
> "Push my local theme changes"
>
> → `shopify_cli_run({ command: "theme push --force --json" })`

**Check theme quality:**
> "Run theme check on my code"
>
> → `shopify_cli_run({ command: "theme check --output json" })`

**Deploy an app:**
> "Deploy my app to production"
>
> → `shopify_cli_run({ command: "app deploy --force" })`

**Discover available commands:**
> "What app commands are available?"
>
> → `shopify_cli_help({ command: "app" })`

**Log in to a store:**
> "Log in to my-store.myshopify.com"
>
> → `shopify_auth_login({ store: "my-store.myshopify.com" })`

## Development

```sh
# From the monorepo root
pnpm install
cd packages/mcp-server

# Run tests
pnpm vitest run

# Build
pnpm build

# Type-check
pnpm type-check

# Lint
pnpm lint

# Test the server manually
echo '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"0.0.1"}},"id":1}' | node bin/mcp-server.js
```

## Security

This MCP server can execute any Shopify CLI command on behalf of the connected AI agent. By installing and configuring it, you trust the MCP client to run CLI commands with your authenticated session.

**What's safe by design:**

- The CLI requires authentication (OAuth or token) — the MCP server cannot bypass this
- `execa` does not use a shell, preventing shell injection
- Long-running commands (`theme dev`, `app dev`) are detected and blocked with a helpful message

**What to be aware of:**

- Destructive commands (`theme delete`, `theme publish`, `app deploy`) can be executed if the agent passes `--force`.
- If using `SHOPIFY_CLI_THEME_TOKEN`, scope the token appropriately (e.g., theme-only access, not full admin).

## License

MIT
2 changes: 2 additions & 0 deletions packages/mcp-server/bin/mcp-server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env node
import('../dist/index.js')
68 changes: 68 additions & 0 deletions packages/mcp-server/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"name": "@shopify/mcp-server",
"version": "3.90.0",
"packageManager": "pnpm@10.11.1",
"private": false,
"description": "MCP server for Shopify CLI — lets AI assistants run Shopify theme and app commands",
"bugs": {
"url": "https://community.shopify.dev/c/shopify-cli-libraries/14"
},
"repository": {
"type": "git",
"url": "https://github.com/Shopify/cli.git",
"directory": "packages/mcp-server"
},
"license": "MIT",
"author": "Shopify",
"type": "module",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"bin": {
"shopify-mcp-server": "./bin/mcp-server.js"
},
"files": [
"/dist",
"/bin"
],
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.js"
}
},
"scripts": {
"build": "nx build",
"clean": "nx clean",
"lint": "nx lint",
"lint:fix": "nx lint:fix",
"prepack": "NODE_ENV=production pnpm nx build",
"vitest": "vitest",
"type-check": "nx type-check"
},
"eslintConfig": {
"extends": [
"../../.eslintrc.cjs"
]
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.12.0",
"execa": "^7.2.0",
"zod": "^3.25.0"
},
"devDependencies": {
"@vitest/coverage-istanbul": "^3.1.4"
},
"engines": {
"node": ">=20.10.0"
},
"os": [
"darwin",
"linux",
"win32"
],
"publishConfig": {
"@shopify:registry": "https://registry.npmjs.org",
"access": "public"
},
"engine-strict": true
}
46 changes: 46 additions & 0 deletions packages/mcp-server/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"name": "mcp-server",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/mcp-server/src",
"projectType": "library",
"tags": ["scope:plugin"],
"targets": {
"clean": {
"executor": "nx:run-commands",
"options": {
"command": "pnpm rimraf dist/",
"cwd": "packages/mcp-server"
}
},
"build": {
"executor": "nx:run-commands",
"outputs": ["{workspaceRoot}/dist"],
"inputs": ["{projectRoot}/src/**/*", "{projectRoot}/package.json"],
"options": {
"command": "pnpm tsc -b ./tsconfig.build.json",
"cwd": "packages/mcp-server"
}
},
"lint": {
"executor": "nx:run-commands",
"options": {
"command": "pnpm eslint \"src/**/*.ts\"",
"cwd": "packages/mcp-server"
}
},
"lint:fix": {
"executor": "nx:run-commands",
"options": {
"command": "pnpm eslint 'src/**/*.ts' --fix",
"cwd": "packages/mcp-server"
}
},
"type-check": {
"executor": "nx:run-commands",
"options": {
"command": "pnpm tsc --noEmit",
"cwd": "packages/mcp-server"
}
}
}
}
Loading
Loading