
tomi-claycosmos/shopify-store-assistant-mcp
Browser automationDemo MCP server: Shopify store assistant for ChatGPT Apps & Grok Bot — OAuth 2.1 (DCR+PKCE), safety-bounded tools, MCP Apps widget. Sample data.
Overview
Portfolio demo by Tomi (https://ziy.one/). from a fictional store ("Kopi & Co. Demo Store"). Not affiliated with Shopify. A TypeScript MCP server (official @modelcontextprotocol/sdk 1.32, Streamable HTTP) that lets a store owner query products, inventory and orders from ChatGPT, Grok Bot or Cursor, and draft discount codes. Every tool has explicit safety bounds. These were captured with headless Chromium (Playwright) against the local server. All tool output is real; all store data is sample data. Regenerate them with npx tsx scripts/screenshots.ts. covers product search with cards, order lookup with masked PII, a 15% discount draft that succeeds, an 80% discount blocked by the cap, and a rejected refund: Walkthrough video: screenshots/walkthrough.mp4 (webm) Safety bounds: - There are no refund, delete, cancel or customer-edit tools. - Discount drafts live in server memory and never change Shopify. - Every call is appended to an audit log (JSONL, no tokens, no raw PII).
README
Shopify Store Assistant — MCP server demo (ChatGPT App · Grok Bot connector · Muse-ready)
Portfolio demo by Tomi (https://ziy.one/). Default data is SAMPLE data from a fictional store (“Kopi & Co. Demo Store”). Not affiliated with Shopify.
A TypeScript MCP server (official @modelcontextprotocol/sdk 1.32, Streamable HTTP) that lets a store owner query products, inventory and orders from ChatGPT, Grok Bot or Cursor, and draft discount codes. Every tool has explicit safety bounds.
Architecture
flowchart LR
subgraph Clients
C1[ChatGPT Developer Mode]
C2[Grok Bot / Cursor]
C3[Muse connector / MCP Inspector]
end
C1 & C2 & C3 -- "OAuth 2.1 (DCR + PKCE S256)" --> AS[Built-in demo Authorization Server/register /authorize /token]
C1 & C2 & C3 -- "Bearer token · Streamable HTTP POST /mcp" --> MW[Bearer middleware401 + WWW-Authenticate resource_metadata]
MW --> MCP[McpServer per request6 tools + UI resource]
MCP --> SAFE[Safety layerscope checks · 20% discount cap · PII masking · no refund/delete]
SAFE --> AUD[(logs/audit.jsonl)]
SAFE --> DATA{Store adapter}
DATA -->|default| MOCK[Mock sample store]
DATA -->|SHOPIFY_STORE_DOMAIN + SHOPIFY_ADMIN_TOKEN| SHOP[Shopify Admin GraphQLread-only, untested live]
MCP --> UI[ui://shopify-assistant/product-list-v1.htmltext/html;profile=mcp-app]
Screenshots
These were captured with headless Chromium (Playwright) against the local server. All tool output is real; all store data is sample data. Regenerate them with npx tsx scripts/screenshots.ts.
| OAuth consent | Widget in a chat host |
|---|---|
Demo transcript covers product search with cards, order lookup with masked PII, a 15% discount draft that succeeds, an 80% discount blocked by the cap, and a rejected refund:
Walkthrough video: screenshots/walkthrough.mp4 (webm)
Tools
| Tool | Purpose | readOnly | destructive | openWorld | Scope |
|---|---|---|---|---|---|
search_products |
keyword/type/SKU search | ✅ | ❌ | ❌ | store.read |
check_inventory |
stock for one SKU | ✅ | ❌ | ❌ | store.read |
lookup_order |
order details, customer PII masked | ✅ | ❌ | ❌ | store.read |
get_order_status |
payment/fulfillment/tracking only | ✅ | ❌ | ❌ | store.read |
create_discount_draft |
inactive draft, capped at MAX_DISCOUNT_PERCENT (20) |
❌ | ❌ | ❌ | discounts.write |
render_product_list |
renders the widget (decoupled render tool) | ✅ | ❌ | ❌ | — |
Safety bounds:
- There are no refund, delete, cancel or customer-edit tools.
- Discount drafts live in server memory and never change Shopify.
- Every call is appended to an audit log (JSONL, no tokens, no raw PII).
- Input is validated with zod.
- Server
instructionstell the model to confirm with the user before any write.
Run
npm install
npm test # vitest: 15 tests (tools, safety bounds, auth rejection)
npm start # http://localhost:3000/mcp (mock data)
npm run demo # in another shell: full OAuth + MCP run -> DEMO_TRANSCRIPT.md
Sample credential: the consent page login defaults to demo / demo-pass. It is a demo-only placeholder and not a secret. Always set DEMO_USER and DEMO_PASSWORD via env on any public deployment.
To use a real store, set SHOPIFY_STORE_DOMAIN and SHOPIFY_ADMIN_TOKEN. The token needs these custom-app scopes: read_products, read_inventory, read_orders. This adapter has not been tested against a live store.
OAuth (demo authorization server)
Endpoints:
/.well-known/oauth-protected-resource(RFC 9728)/.well-known/oauth-authorization-server(RFC 8414; advertisesS256andregistration_endpoint)POST /register(RFC 7591 DCR, public clients; https or localhost redirect URIs only)GET/POST /authorize(consent page + login)POST /token(authorization_code with PKCE verification, refresh_token with rotation)
Behaviour:
- Tokens are opaque, live in memory, last 1 hour and are audience-bound to
/mcp. - A request without a valid token to
/mcpgets a401withWWW-Authenticate: Bearer resource_metadata="…". This is how ChatGPT discovers the OAuth configuration.
Production:
- Replace this server with a real IdP (Auth0, WorkOS, Stytch) or Shopify’s own OAuth.
- Persist clients and tokens.
- Add CIMD if needed (ChatGPT prefers CIMD when it is advertised).
Deploy
- Render (free): connect this repo as a Blueprint (
render.yaml). It builds the Dockerfile, andPUBLIC_BASE_URLdefaults toRENDER_EXTERNAL_URL. Free instances sleep when idle, so the first request after a sleep is slow. - Fly.io:
fly launch --copy-config --no-deploy && fly secrets set DEMO_PASSWORD=... && fly deploy.PUBLIC_BASE_URLdefaults tohttps://$FLY_APP_NAME.fly.dev. - Any Docker host: set
PUBLIC_BASE_URLto the public https origin.
⚠️ OAuth clients and tokens are in memory, so a restart or sleep logs every client out. That is fine for a demo; production needs a persistent store or a real IdP.
Connect in ChatGPT Developer Mode
- Deploy behind a public HTTPS URL. Set
PUBLIC_BASE_URL=https://your-hostso the OAuth metadata URLs match. - In ChatGPT, enable Developer Mode (Settings → Apps/Connectors → Advanced) and create a custom app/connector with URL
https://your-host/mcpand OAuth auth. - ChatGPT runs DCR, then sends you to the consent page. Log in as demo/demo-pass.
- Try: “Which brewing products are low on stock? Show them as cards”, “What’s the status of order #1001?”, “Create a 15% discount draft KOPI15”.
Docs:
- https://developers.openai.com/plugins/build/mcp-server
- https://developers.openai.com/plugins/build/chatgpt-ui
- https://developers.openai.com/apps-sdk/build/auth
Public submission requires all of the following:
- a stable domain (no temporary tunnel)
- a verified org
- a privacy policy
- a demo account
- test cases
OpenAI also rejects demo/trial apps, so this repo is for portfolio and Developer Mode only: https://developers.openai.com/apps-sdk/app-submission-guidelines
Grok Bot / Cursor marketplace
The form is at https://x.ai/bot/marketplace/submit-a-plugin (opened 2026-10-14). It asks for:
- a remote MCP URL or public GitHub repo
- a 1:1 logo
- an organization handle
- a description
- testing instructions (with test credentials)
Submitting accepts Cursor’s Marketplace Publisher Terms. Grok itself is listed as “coming soon”. Not submitted.
Meta Muse connector notes
The Muse Connector Platform (https://muse.ai/platform/docs) accepts MCP/API connectors. Requirements relevant here:
- offer read-only OAuth where possible
- document read/write classification, sensitive designations, side effects, errors and rate limits for each tool
The tool table above is written in that format. Not submitted.
Layout
src/app.ts express app, /mcp (stateless Streamable HTTP)
src/auth.ts demo OAuth 2.1 AS + bearer middleware
src/mcp.ts tools, UI resource, scope checks
src/safety.ts masking, discount cap, audit log
src/widget.ts MCP Apps HTML widget
src/data/ mock store (sample) + Shopify GraphQL adapter
scripts/ oauth-flow.ts, demo-client.ts
tests/ vitest suite
中文摘要
这是一个可以直接演示的 Shopify 店铺助手 MCP server:TypeScript,用官方 SDK,走 Streamable HTTP 传输。
- 鉴权:内置一个演示用的 OAuth 2.1 授权服务器,支持动态客户端注册(DCR)和 PKCE S256。没带有效 token 访问
/mcp会返回 401,并附带 resource_metadata,供客户端发现鉴权配置。 - 工具:5 个业务工具加 1 个渲染工具,都标注了 readOnly/destructive/openWorld 三个提示字段。
- 安全边界:折扣最高 20%,而且只生成草稿;没有退款或删除工具;客户信息脱敏;每次调用写审计日志。
- 数据:默认用模拟样本数据,无需任何凭据即可运行。设置
SHOPIFY_STORE_DOMAIN和SHOPIFY_ADMIN_TOKEN后改用真实 Shopify 只读适配器(未连真实店铺测试过)。 - UI:符合 MCP Apps 标准的商品列表组件(
text/html;profile=mcp-app),兼容 ChatGPT。 - 运行:
npm install && npm test && npm start,再开一个终端跑npm run demo,会生成 DEMO_TRANSCRIPT.md。 - 限制:OpenAI 不收 demo 类 app,这个仓库只用于作品集和 Developer Mode 演示。没有提交到任何市场。
Install
This server does not publish a one-line install command.
Open the repository installation guide