npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

shopify-mcp-oauth

v0.2.0

Published

OAuth 2.1 authorization + resource server for a Shopify app's MCP endpoint

Readme

shopify-mcp-oauth

OAuth 2.1 authorization server and resource server for a Shopify app's MCP endpoint, so the merchant logs in through Shopify instead of copy-pasting a token.

The hard part of an MCP server for a Shopify app is not the tools — it is the auth. The MCP specification requires the server to be both an OAuth resource server and an OAuth authorization server, to support PKCE, to accept two different client-identification schemes, and to serve six discovery documents that different clients look for in different places. Get one wrong and Claude Code, VS Code, Cursor, and ChatGPT each fail in a different, silent way.

This package ships that layer and leaves the tools to you. It is not a Shopify app framework — no install, billing, webhooks, or embedded admin UI — and not an MCP transport library.

Pre-1.0. While the version is 0.x, a minor bump may contain breaking changes and a patch bump will not. Pin accordingly.

Install

npm install shopify-mcp-oauth

Peer dependencies: express >=5 and zod >=3.23.

Quickstart

import express from "express";
import { mountShopifyMcpOAuth, prismaStorage, shopifySessionStorage, redisCache } from "shopify-mcp-oauth";

const app = express();
app.use(express.json()); // for YOUR routes; the OAuth router parses its own

mountShopifyMcpOAuth(
  app,
  {
    host: "https://mcp.example.com",
    shopify: {
      apiKey: process.env.SHOPIFY_API_KEY!,
      apiSecret: process.env.SHOPIFY_API_SECRET!,
      scopes: "read_products,write_products",
    },
    stateSecret: process.env.OAUTH_STATE_SECRET!,
    storage: {
      ...prismaStorage(prisma),
      findShopByDomain: shopifySessionStorage(sessionStorage),
    },
    cache: redisCache(redis),
  },
  (oauth) => {
    app.post("/mcp", oauth.requireAuth, myMcpHandler);
  }
);

requireAuth sets req.mcp = { shopId, shopDomain, tokenId } and answers 401 with a WWW-Authenticate header when authentication fails. The req.mcp type is available without any extra import — the package augments Express.Request globally on import.

mountShopifyMcpOAuth mounts the router, then your routes, then the error handler last. That last position is the one that matters: Express only looks for an error handler at the stack level where the error was thrown, so a body-parser SyntaxError on malformed JSON never reaches one mounted inside a router, and Express's default handler answers with an HTML stack trace on an unauthenticated endpoint instead. Register every route inside the callback — anything added to app afterwards sits below the error handler.

createShopifyMcpOAuth returns the same handle without mounting anything, if you would rather place the three pieces yourself.

Configuration

| Field | Required | Default | Notes | | ------------------------------ | -------- | --------------- | ---------------------------------------------------------------- | | host | yes | — | Public origin, HTTPS in production, no trailing slash. | | shopify.apiKey / apiSecret | yes | — | The same Shopify app the merchant installed. | | shopify.scopes | yes | — | Comma-separated. Must match the installed app's scopes. | | stateSecret | yes | — | HS256 signing key for the state JWT. At least 32 characters. | | storage | yes | — | An OAuthStorage. See the storage adapters guide. | | cache | no | memoryCache() | Holds authorization codes and fetched client metadata documents. | | onShopNotFound | no | null | Last-chance shop resolution when the install gate misses. | | tokenTtl.access | no | 3600 | Seconds. | | tokenTtl.refresh | no | 2592000 | Seconds — 30 days. |

The full table, including cimdFetchConcurrency and openaiAppsChallengeToken, is in the repository README.

Storage

Storage-agnostic by design — the package never assumes an ORM. Built-in adapters: prismaStorage, memoryStorage, shopifySessionStorage, redisCache, memoryCache, allowAnyShop. Writing your own means implementing the OAuthStorage and CacheStore interfaces: storage adapters guide.

Guides

Starting from scratch? create-shopify-mcp scaffolds a running server with this already wired.

License

MIT