MCP Server Setup

Connect cannabis market data directly to AI assistants using the CannMenus MCP server.


What is MCP?

The Model Context Protocol (MCP) is an open standard that lets AI assistants access external data sources and tools. The CannMenus MCP server gives AI tools direct access to cannabis product data, brand analytics, pricing, stock status, and more — without writing any code.


Prerequisites

  • A CannMenus Pro or API subscription
  • An active API token (generate one from your API Dashboard)
  • An MCP-compatible AI client (Claude, Cursor, Windsurf, etc.)

Setup

Claude Desktop

Add the following to your Claude Desktop configuration file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "cannmenus": {
      "type": "url",
      "url": "https://api.cannmenus.com/mcp/",
      "headers": {
        "Authorization": "Bearer YOUR_API_TOKEN"
      }
    }
  }
}

Restart Claude Desktop after saving.

Claude Code (CLI)

Add to your project or global settings at .claude/settings.json:

{
  "mcpServers": {
    "cannmenus": {
      "type": "url",
      "url": "https://api.cannmenus.com/mcp/",
      "headers": {
        "Authorization": "Bearer YOUR_API_TOKEN"
      }
    }
  }
}

Claude.ai (Web)

Claude.ai supports OAuth authentication. Simply add https://api.cannmenus.com/mcp/ as the URL — no token needed. You'll be redirected to log in and authorize access.

Step 1. Click your profile icon in the bottom-left corner, then click Settings.

Open Settings from the Claude.ai sidebar

Step 2. In the Settings sidebar, click Connectors.

Navigate to the Connectors section

Step 3. Click the + button and select Add custom connector.

Click Add custom connector from the menu

Step 4. In the dialog, enter CannMenus as the name and paste the MCP server URL:

https://api.cannmenus.com/mcp/

Click Add. You'll be redirected to CannMenus to log in and authorize access.

Enter the connector name and MCP server URL

Step 5. Once connected, CannMenus will appear in your connectors list and all tools will be available to Claude.

CannMenus connector added with tools listed

You can manage tool permissions from the Customize > Connectors page:

CannMenus tools and permissions in the Customize view

Cursor

Open Settings > MCP Servers and add a new server:

{
  "name": "cannmenus",
  "type": "url",
  "url": "https://api.cannmenus.com/mcp/",
  "headers": {
    "Authorization": "Bearer YOUR_API_TOKEN"
  }
}

Windsurf

Add to your Windsurf MCP configuration:

{
  "mcpServers": {
    "cannmenus": {
      "serverUrl": "https://api.cannmenus.com/mcp/",
      "headers": {
        "Authorization": "Bearer YOUR_API_TOKEN"
      }
    }
  }
}

Other MCP Clients

Any MCP-compatible client that supports the Streamable HTTP transport can connect. Use:

  • Server URL: https://api.cannmenus.com/mcp/ — combined endpoint, auto-filtered to your entitlements
  • Authentication: Pass your API token via Authorization: Bearer YOUR_API_TOKEN header or append ?token=YOUR_API_TOKEN as a query parameter

Product-scoped endpoints

If you want to narrow the LLM's tool surface to one product area, use a scoped URL instead of /mcp/:

EndpointTool setRequires
https://api.cannmenus.com/mcp/cannabisCannabis menu / stock / sales / company toolscmp_permissions entitlement
https://api.cannmenus.com/mcp/bevalcBeverage / alcohol retail analyticsHEMP_BEVERAGE_DATA subscription
https://api.cannmenus.com/mcp/wholesaleWholesale account / order / pricing toolsWHOLESYNC subscription

The combined /mcp/ endpoint already filters down to whatever you're entitled to, so a bevalc-only customer hitting /mcp/ and /mcp/bevalc see the same list. The scoped URLs are most useful for cross-sell customers who want a focused single-domain assistant.


Available Tools

The MCP server registers 37 tools across cannabis, beverage/alcohol, and wholesale market data. The list returned by tools/list is filtered to your entitlements — you'll see somewhere between 17 and 37 tools depending on your subscriptions.

Tool selection — pick the right tool, not a fan-out

Pick a single structured tool over loops or ad-hoc SQL. Common questions map to one tool:

QuestionTool
"Top N brands / categories / retailers by sales"sales_rankings (one call, NOT a per-brand loop)
"Sales / volume trend over time"market_trends
"Where is brand X in stock right now?"brand_stock_status
"Full scorecard for one brand"brand_performance (NOT a chain of stock + trends + gap)
"White-space retailers (carry competitors but not me)"brand_gap_analysis
"MSO ownership tree / subsidiary sales"get_company_hierarchy
"Market concentration across MSOs"get_company_market_share
Genuinely ad-hoc (everything above doesn't fit)query_analytics (last resort)

Looping brand_performance per brand to build a top-10 leaderboard is the most common anti-pattern — sales_rankings returns the whole list in one call.

Product Discovery & Menu Analysis

ToolDescription
search_productsSearch cannabis products by state, brand, category, price, potency
get_retailer_menuFull menu for a retailer. Pass include_all_menu_providers=true if the default count looks low (secondary providers like BreadStack/Leafly)
search_retailersFind dispensaries by location, name, services
search_brandsFind brands and get brand IDs
get_brand_statsBrand portfolio and category mix
get_brand_retailersWhich retailers carry a brand

Cannabis Brand & Market Analytics

ToolDescription
brand_performanceNIQ-grade single-brand scorecard — weekly sales, L4W vs P4W comparison, distribution %, category breakdown in one call
market_trendsSales volume, pricing trends over time. Returns aggregates block with pre-truncation totals
sales_rankingsTop brands, categories, products by sales
brand_stock_statusBrand availability across retailers (ground truth)
brand_gap_analysisWhite-space distribution opportunities
price_comparisonProduct pricing across retailers
get_product_eventsStock and price event history
query_analyticsNatural-language ad-hoc analytics (full access orgs only) — last resort, prefer the structured tools above when they fit

Company & MSO Analysis

ToolDescription
search_companiesFind MSOs, operators, brand houses
get_company_hierarchyOwnership trees with sales data
get_company_market_shareMarket concentration analysis

Wholesale (requires WholeSync subscription)

ToolDescription
wholesale_accountsRevenue by retail account
wholesale_account_ordersOrder line items
wholesale_revenue_breakdownRevenue by brand/sku/retailer/month
wholesale_account_healthRecency, frequency, avg order value
wholesale_top_productsBest-selling SKUs
wholesale_discount_analysisDiscount and pricing concession analysis
wholesale_account_pricingPer-account pricing profile vs fleet average

Bev/Alc Retail Analytics (requires subscription)

Panel: CannMenus BevAlc Panel v1 — Total Wine, Spec's, ABC Fine Wine, Binny's (677 stores / 31 states). Every response includes a universe block with panel boundaries.

ToolDescription
bevalc_brand_performanceNIQ-grade single-brand scorecard — weekly series, L4W/P4W, category share, velocity
bevalc_category_landscapeTop brands in a category with dollar/unit share + velocity per store per week
bevalc_distribution_trendWeekly distribution gains/losses — stores_carrying / added / dropped
retail_brand_rankingsTop brands by estimated sales
retail_brand_distributionBrand presence across retail chains
retail_store_inventoryStore-level inventory with current_price, original_price, discount_pct
retail_price_trendsPricing trends with price change counts
retail_sales_velocityStock depletion velocity
retail_category_overviewCategory-level market overview
retail_geographic_analysisGeographic distribution analysis

Pagination & Truncation

Listing tools return a pagination block. There are three modes — each tool uses one:

mode=page — page-numbered

Used by: search_brands, search_retailers, search_products, get_brand_retailers.

Pass page=N to fetch the next page when has_more=true. Per-page sizes are tool-specific (20–200 rows).

"pagination": {
  "mode": "page",
  "page": 1,
  "per_page": 200,
  "returned_count": 200,
  "total_count": 1437,
  "has_more": true
}

mode=cursor — keyset pagination

Used by: get_product_events, get_retailer_menu.

Pass the returned next_cursor back as the cursor argument to fetch the next page. Page sizes: 100 events, 200 menu rows.

"pagination": {
  "mode": "cursor",
  "returned_count": 200,
  "has_more": true,
  "next_cursor": "eyJwIjoxLCJ2IjpbIkZsb3dlciIsIk51Z3oiLC..."
}

Don't loop blindly — most questions are answered by a single page. Only paginate when you genuinely need every row.

Rate limit: cursor pagination is capped at 50 pages per hour per (token, tool). Hitting it returns:

{
  "error": "pagination_rate_limit",
  "message": "get_retailer_menu has fetched 51 pages this hour (limit: 50). Narrow your filters instead of paginating further...",
  "tool": "get_retailer_menu",
  "pages_fetched_this_hour": 51,
  "max_pages_per_hour": 50
}

If you hit it, narrow your filters (add category, event_type, retailer_id, etc.) — don't retry the same call.

Per-page summaries in get_product_events: event_summary and total_events cover the current page only, not the full timeline. Don't sum them across cursor calls.

mode=split — capped rows + aggregates

Used by: market_trends, brand_stock_status, price_comparison, brand_gap_analysis.

These tools cap row output but return an aggregates block computed from the full un-truncated set. For market figures use aggregates.* — never sum rows[] when truncated=true. These tools do not (yet) support cursor pagination — narrow filters if you need more rows.

"pagination": {
  "mode": "split",
  "returned_count": 5000,
  "has_more": false,
  "truncated": true,
  "total_count": 12453,
  "cap_applied": 5000
},
"aggregates": {
  "total_estimated_sales": 4823901.50,
  "total_estimated_units": 142318,
  ...
}

query_analytics — special case

query_analytics runs Vanna-generated SQL with arbitrary ORDER BY (or none), so cursor pagination is not possible. Results capped at 1,000 rows; the first 50 are returned inline (data field). New fields:

  • sample_size: 50 — how many rows came inline
  • omitted_inline: N — how many were fetched but not inlined
  • total_fetched: N — total rows after the cap
  • truncated: true — set when the cap was hit

If you hit the cap, narrow your question (add a state filter, date range, brand/category) and re-ask. For listing-style data, use get_product_events or get_retailer_menu (cursor pagination); for market totals, use sales_rankings / market_trends aggregates.

Pricing Fields

Product-level tools return current_price (shelf price) and original_price (list/MSRP, may be NULL if unavailable). When both are present and original_price > current_price, the product is on promotion — compute discount_pct = (original_price - current_price) / original_price * 100. Never assume a product is discounted when original_price is NULL — it means we don't know the list price.


Reference Resources

The MCP server also exposes reference resources that help AI assistants discover valid parameter values:

ResourceURIDescription
Statescann://reference/statesList of all supported US states
Categoriescann://reference/categoriesValid product categories
Tagscann://reference/tagsAvailable product tags (effects, flavors, etc.)
Brands by Statecann://reference/brands/{state}All brand names and IDs in a state

Usage and Billing

Each MCP tool call makes one or more API requests on your behalf. These requests count toward your normal API usage and billing tiers:

TierRequestsRate
Tier 11 — 30,000$0.04 / request
Tier 230,001 — 90,000$0.03 / request
Tier 390,001+$0.02 / request

Monitor your usage on the API Dashboard. Per-token request counts and last-used dates are displayed so you can track MCP usage separately from direct API calls.


Example Conversations

Once connected, you can ask your AI assistant questions like:

  • "What are the best-selling flower brands in California?"brand_performance or sales_rankings
  • "How is STIIIZY doing in California?"brand_performance (weekly sales, distribution, L4W/P4W)
  • "Compare pricing for Jeeter products across dispensaries in Colorado"price_comparison
  • "Which dispensaries in Arizona don't carry Raw Garden but carry similar brands?"brand_gap_analysis
  • "What are the top spirits brands at Total Wine in Texas?"bevalc_category_landscape
  • "Show me Tito's distribution trend over the last 12 weeks"bevalc_distribution_trend
  • "How is Don Julio doing vs the spirits category?"bevalc_brand_performance

The AI assistant will automatically use the appropriate CannMenus tools to fetch real-time data and provide analysis.


Troubleshooting

"Authentication failed" — Verify your API token is active and correctly set in the Authorization: Bearer header (or ?token= query parameter). Generate a new token from the API Dashboard if needed.

"No results found" — Make sure you're using valid state codes and category names. Use the reference resources to discover valid values.

"Rate limited" — The MCP server respects standard API rate limits. If you're making many rapid queries, space them out or contact support for higher limits.