Skip to main content
Glama
TimeLib MCP

TimeLib MCP

by oumaru894

TimeLib MCP — AI agent for your Medusa store

An MCP server that lets an AI agent (Claude Desktop, Claude Code, or any MCP client) add and manage products — plus inventory, collections/categories, orders and customers — in your TimeLib Medusa v2 store via the Admin API.

You just chat, e.g.:

"Add a product called Chrono Field Watch, a draft, with S/M/L bands at $180, 20 in stock each, in the Watches collection."

and the agent creates it.


What the agent can do

Area

Tools

Orientation

get_store_context (regions, currencies, sales channels, locations)

Products

list_products, get_product, create_product, update_product, delete_product

Product images

upload_product_image, add_product_images

Variants

create_variant, update_variant, delete_variant

Inventory

list_inventory_items, set_inventory_level

Catalog

list_collections, create_collection, list_categories, create_category, list_product_tags, list_product_types

Orders / Customers

list_orders, get_order, list_customers

Anything else

medusa_admin_request (raw Admin API escape hatch)

Frontend content (Sanity) — optional

When SANITY_PROJECT_ID + SANITY_API_TOKEN are set, the agent also gains tools to edit the storefront content managed in Sanity:

Area

Tools

Site content

get_site_content, update_site_settings

Hero carousel

set_hero_carousel, add_hero_slide, update_hero_slide, remove_hero_slide

Blog

list_blog_posts, get_blog_post, create_blog_post, update_blog_post, delete_blog_post

Images

sanity_upload_image

The token must have Editor (write) permission in Sanity. A read-only token lets the agent read content but every edit fails with permission "create" required. Create one at manage.sanity.io → your project → API → Tokens → Editor.


Related MCP server: shopify

Setup (one time)

1. Install

cd timelib-mcp
npm install

2. Configure credentials

cp .env.example .env

Open .env. MEDUSA_BACKEND_URL is already filled in. You need admin credentials. Two options:

Option A — Secret API key (recommended: non-expiring, revocable, no password stored). Temporarily put your Medusa admin email + password in .env, then:

npm run create-key

Copy the printed token into MEDUSA_ADMIN_API_KEY in .env, then delete the email/password lines.

Option B — Email + password. Just set MEDUSA_ADMIN_EMAIL and MEDUSA_ADMIN_PASSWORD in .env and leave MEDUSA_ADMIN_API_KEY empty. The server logs in and refreshes the token automatically.

3. Test the connection

npm run smoke

You should see ✅ Auth OK and a few product titles.


Connect it to Claude

Claude Code (CLI)

claude mcp add timelib -- node "C:\Users\dashi\Desktop\Projects\TimeLib\timelib-mcp\src\index.mjs"

(Credentials are read from timelib-mcp/.env, so you don't need to pass them on the command line. To pass them explicitly instead, add -e MEDUSA_BACKEND_URL=... -e MEDUSA_ADMIN_API_KEY=... before the --.)

Verify with claude mcp list, then in a session ask: "What tools does timelib expose?"

Claude Desktop

Edit %APPDATA%\Claude\claude_desktop_config.json:

{
  "mcpServers": {
    "timelib": {
      "command": "node",
      "args": ["C:\\Users\\dashi\\Desktop\\Projects\\TimeLib\\timelib-mcp\\src\\index.mjs"]
    }
  }
}

Restart Claude Desktop. The 🔌 icon should show the timelib tools.


Hosting the server (remote / always-on)

The server has two entrypoints that share the same tools:

Entrypoint

Command

Use

Local (stdio)

node src/index.mjs

Claude launches it on your machine

Hosted (HTTP)

node src/http-server.mjs

Runs as a web service; clients connect over HTTPS

The hosted server exposes MCP at POST /mcp and is protected by a static bearer token (MCP_AUTH_TOKEN). It refuses to start without one.

Deploy to Railway (new service in the TimeLib project)

  1. Push timelib-mcp/ to a Git repo (GitHub).

  2. In your existing TimeLib Railway project → New → GitHub Repo → pick this repo (set the root directory to timelib-mcp if it lives in a monorepo).

  3. Railway reads railway.json and runs node src/http-server.mjs.

  4. Add these Variables in the service:

    • MEDUSA_BACKEND_URL = https://timelib-production.up.railway.app

    • MEDUSA_ADMIN_API_KEY or MEDUSA_ADMIN_EMAIL + MEDUSA_ADMIN_PASSWORD

    • MCP_AUTH_TOKEN = a long random secret (see below)

    • (PORT is injected by Railway automatically.)

  5. Under Settings → Networking, generate a public domain. You'll get a URL like https://timelib-mcp-production.up.railway.app. Your MCP endpoint is that URL + /mcp.

Generate a token:

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

Sanity-check the deploy:

curl https://YOUR-MCP-DOMAIN.up.railway.app/         # -> {"name":"timelib-mcp","status":"ok",...}

Connect clients to the hosted server

Claude Code (CLI) — native HTTP transport with a header:

claude mcp add --transport http timelib-remote https://YOUR-MCP-DOMAIN.up.railway.app/mcp \
  --header "Authorization: Bearer YOUR_MCP_AUTH_TOKEN"

Claude Desktop — use the mcp-remote bridge (no native header field in the UI):

{
  "mcpServers": {
    "timelib-remote": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://YOUR-MCP-DOMAIN.up.railway.app/mcp",
        "--header", "Authorization: Bearer YOUR_MCP_AUTH_TOKEN"
      ]
    }
  }
}

Claude.ai web / mobile — uses OAuth (see next section). No token to paste; you approve access with your owner password in the browser.


OAuth for claude.ai web / mobile

claude.ai custom connectors authenticate via OAuth, not a static token. The hosted server implements a full OAuth 2.1 flow (metadata discovery, dynamic client registration, authorize + token endpoints, PKCE, refresh tokens). It's stateless — client registrations and tokens are signed JWTs, so it survives Railway redeploys with no database. Access is gated by a single owner password.

Enable it

Add two more variables to the Railway service and redeploy:

OWNER_PASSWORD   = <a password you'll type to approve access>
OAUTH_JWT_SECRET = <64+ random hex chars: node -e "console.log(require('crypto').randomBytes(48).toString('hex'))">

PUBLIC_URL is auto-detected from Railway's RAILWAY_PUBLIC_DOMAIN. The static MCP_AUTH_TOKEN keeps working for Claude Code/Desktop at the same time.

Connect claude.ai

  1. claude.ai → Settings → Connectors → Add custom connector.

  2. URL: https://YOUR-MCP-DOMAIN.up.railway.app/mcp

  3. Claude discovers the OAuth endpoints and opens a login page → enter your OWNER_PASSWORD → Authorize.

  4. The timelib tools appear in claude.ai (web and mobile).

Health check shows which modes are active:

curl https://YOUR-MCP-DOMAIN.up.railway.app/    # -> "auth":{"static_token":true,"oauth":true}

Notes & safety

  • Prices are in major currency units in Medusa v2 (e.g. 25 = $25.00, not cents).

  • New products default to draft. Ask the agent to set status: "published" (or use update_product) to make them live.

  • Destructive actions (delete_product, deletes via medusa_admin_request) are permanent — the agent is instructed to confirm with you first, but review before approving.

  • The secret API key has full admin access. Keep .env out of version control (already in .gitignore) and revoke the key in the Medusa admin if it leaks.

  • Product images can be given as public URLs or base64 image data. Any image not already on your bucket (MEDUSA_ASSETS_BASE_URL, default the TimeLib Railway bucket) is downloaded/decoded server-side and uploaded through Medusa's file module (POST /admin/uploads), so supplier URLs that block hotlinking or expire end up safely re-hosted — and any watermark/file provider still applies. Use upload_product_image to upload and get { id, url }, or add_product_images to upload + append to a product. create_product/update_product auto-rehost their images/thumbnail; on update_product, new images are appended by default (image_mode: "replace" to overwrite). Allowed: JPEG/PNG/WEBP up to MAX_IMAGE_BYTES (default 10 MB). Failed images are reported under _image_warnings, never dropped silently.

  • Hosted server = full admin access behind one token. Anyone with the MCP_AUTH_TOKEN and the URL can manage your store. Use a long random token, store it only in Railway variables + your client config, and rotate it (change the variable, redeploy) if it leaks.

  • OAuth secrets: OWNER_PASSWORD is your login to approve claude.ai access — make it strong. Changing OAUTH_JWT_SECRET (or a redeploy that loses it) invalidates all issued tokens and registered connectors, so clients must reconnect. Keep it stable in Railway variables.

Available Tools

21 tools
create_categoryC

Create a product category.

Inputs: name (required), handle, is_active, parent_category_id.

create_collectionC

Create a product collection.

Inputs: title (required), handle.

create_productA

Create a product. Provide options (e.g. Size/Color) and variants that reference those options. Variant prices use major currency units (25 = $25.00). Images are passed as an array of public URLs. Set status 'published' to make it live, or 'draft' to stage it. Example variant: { title:'Medium', sku:'TL-M', options:{ Size:'M' }, prices:[{ amount:25, currency_code:'usd' }], manage_inventory:true }.

Inputs: title (required), tags, width, handle, +16 more.

create_variantB

Add a variant to an existing product. Provide options map + prices. e.g. options:{ Size:'XL' }, prices:[{amount:30,currency_code:'usd'}].

Inputs: title (required), product_id (required), sku, prices, +2 more.

delete_productA

Delete a product by id. This is permanent — confirm with the user first.

Inputs: id (required).

delete_variantC

Delete a variant from a product.

Inputs: product_id (required), variant_id (required).

get_orderB

Get full details of one order by id.

Inputs: id (required).

get_productA

Get a single product by id, including variants, options, prices, images and tags.

Inputs: id (required), fields.

get_store_contextA

Return store defaults an agent needs BEFORE creating products: regions & their currency codes, sales channels, stock locations, and price preferences. Call this first when unsure about currency_code / sales_channel_id / location_id.

Inputs: no named parameters.

list_categoriesC

List product categories.

Inputs: q, limit, fields, offset.

list_collectionsC

List product collections.

Inputs: q, limit, fields, offset.

list_customersC

List/search customers.

Inputs: q, limit, fields, offset.

list_inventory_itemsB

List inventory items (optionally search by sku/title with 'q').

Inputs: q, limit, fields, offset.

list_ordersC

List recent orders. Supports 'q' free-text and paging.

Inputs: q, limit, fields, offset.

list_productsB

List/search products. Supports free-text 'q', status filter, and filtering by collection/category/tag/type id.

Inputs: q, limit, fields, offset, +5 more.

list_product_tagsC

List product tags.

Inputs: q, limit, fields, offset.

list_product_typesC

List product types.

Inputs: q, limit, fields, offset.

medusa_admin_requestA

Low-level escape hatch: call ANY Medusa Admin API endpoint directly. Use for anything the curated tools don't cover (fulfillments, price lists, promotions, refunds, uploads, etc.). path must start with /admin. Be careful with POST/DELETE — confirm destructive actions with the user first.

Inputs: path (required), method (required), body, query.

set_inventory_levelB

Set the stocked quantity for an inventory item at a stock location. Use list_inventory_items to find inventory_item_id and get_store_context for location_id.

Inputs: location_id (required), stocked_quantity (required), inventory_item_id (required).

update_productA

Update fields on an existing product (title, description, status, thumbnail, collection_id, etc.). Only include fields you want to change. To publish: set status='published'.

Inputs: id (required), title, handle, status, +4 more.

update_variantC

Update a variant (title, sku, prices, manage_inventory, options).

Inputs: product_id (required), variant_id (required), sku, title, +2 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.2/5.0

    Scored across 21 tools

    Disambiguation4/5

    Most tools have clearly distinct purposes (collections, categories, products, variants, inventory, orders, customers). However, create_collection/list_collections vs create_category/list_categories vs create_product/list_products all follow similar patterns and could be confused without careful reading, and the escaping medusa_admin_request overlaps with every curated tool's purpose.

    Naming Consistency4/5

    The naming mostly follows verb_noun (create_collection, list_orders, get_product, update_variant, delete_variant, set_inventory_level). Minor deviations: get_store_context uses a non-verb + context noun pattern, and medusa_admin_request is a general escape hatch rather than a verb_noun operation. Otherwise consistent.

    Tool Count3/5

    21 tools is on the heavy side but justified for a commerce backend covering products, variants, collections, categories, orders, customers, and inventory. The count pushes toward the upper boundary of reasonable scope, and the escape hatch tool adds useful flexibility but also breadth.

    Completeness4/5

    The curated surface covers core e-commerce lifecycle well: full CRUD for products/variants/collections, category and order/customer listing, and inventory management. Missing curated coverage for orders (no cancel/update status), customers (no create/update), and categories (no delete) is acknowledged and offloaded to the medusa_admin_request escape hatch, so agents have no dead ends.

    Related MCP Connectors

    Related MCP Servers