MCP Connector

Manage QR Codes via Scanova API

Scanova MCP Server lets AI IDEs create, design, and manage Scanova QR codes, folders, lead forms, and analytics via the Scanova API.

Works with scanova

84
Spark score
out of 100
Updated 12 days ago
Source checked Oct 5, 2026
Version 2.8.0
Models
universal

Add to Favorites

Why it matters

Integrate with the Scanova API to programmatically create, manage, and download QR codes. This asset provides tools for developers to automate QR code generation and management within their IDEs.

Outcomes

What it gets done

01

Create new QR codes with custom URLs.

02

List, update, and retrieve existing QR codes.

03

Download QR code images in various formats.

04

Activate and deactivate QR codes.

Source

Get it from source

Spark does not host a copy of it.

Open source

Reports

Agent outcome reports

No reports yet

Capabilities

Tools your agent gets

create_qr_code

Create a new QR code

list_qr_codes

Show existing QR codes

update_qr_code

Update an existing QR code

retrieve_qr_code

Get QR code details

download_qr_code

Download QR code image

activate_qr_code

Activate a QR code

deactivate_qr_code

Deactivate a QR code

Overview

Scanova MCP Server

Scanova MCP Server gives an AI IDE full control over a Scanova QR code account through the Scanova API: creating and designing QR codes, organizing them into folders, managing lead-capture forms, exporting analytics, and administering users. A documentation bridge also lets the agent query Scanova's own docs. Use it when an agent needs to manage an existing Scanova account's QR codes, leads, or analytics; it requires a Scanova API key and account, not a standalone QR generator.

What it does

Scanova MCP Server lets AI IDEs like Cursor, VS Code, and Claude Desktop manage a Scanova QR code account through the Scanova API: creating, designing, and running the full lifecycle of QR codes; organizing them into folders; managing lead-capture forms and lead lists; pulling analytics; and administering account users - plus a documentation bridge that lets the agent query Scanova's own docs via a second MCP server.

When to use - and when NOT to

Use it when an agent needs to create, customize, activate/deactivate, or delete QR codes on your behalf, organize them into folders, attach lead-capture forms or lead lists to them, pull scan analytics, or manage who has account access - all through your existing Scanova account rather than the Scanova web dashboard. It requires a Scanova API key from app.scanova.io and an MCP-compatible IDE.
Don't use it if you don't already have (or want) a Scanova account - it's a management layer over the Scanova platform specifically, not a general QR-code generator, and every tool call operates against your live Scanova data.

Capabilities

QR code management covers creating, listing, updating, retrieving, activating/deactivating, and permanently deleting QR codes, downloading them as PNG/JPG/PDF/SVG/EPS or a print-optimized PDF, browsing QR categories (URL, vCard, WiFi, etc.), and attaching or detaching lead-capture forms and lead lists. QR design tools list available visual options (patterns, eye shapes, frames, gradients, error correction) and apply a chosen design to an existing code. Folder management creates, lists, updates, and deletes folders, and moves or unassigns QR codes between them. Forms and lead lists can be listed, retrieved, updated, and deleted independently of any QR code. Analytics tools pull account-level usage stats and per-QR performance metrics by device, geography, and date, and export reports as XLSX/PDF or raw scan logs as CSV/XLSX. Account administration lists users and roles, invites or removes users, and updates role assignments. A documentation bridge (probe_docs_mcp, query_docs) checks connectivity to and queries Scanova's own docs MCP server.

How to install

Get an API key at https://app.scanova.io/settings/api, then add the server to your IDE's MCP config. For Cursor (~/.cursor/mcp.json), VS Code (~/.vscode/mcp.json), or Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json), the configuration is identical across all three:

{
  "mcpServers": {
    "scanova-mcp": {
      "transport": "http",
      "url": "https://mcp.scanova.io/mcp",
      "headers": {
        "Authorization": "YOUR_SCANOVA_API_KEY_HERE"
      }
    }
  }
}

For local development, clone the repository, run uv sync, then start it with uv run cloud_server.py for HTTP mode or uv run main.py for stdio mode; a Docker image can also be built with docker build -t mcpserver:local . and run with docker run -d --name mcpserver -p 8000:8000 mcpserver:local or docker compose up -d, verified with curl http://localhost:8000/health. The deployed server exposes POST /mcp as the main JSON-RPC endpoint, GET /health for health checks, and GET / for service info. The project is MIT licensed.

Who it's for

Teams and marketers running Scanova QR code campaigns who want an AI agent to create and manage QR codes, lead-capture forms, folders, and analytics directly from their IDE instead of the Scanova web dashboard.

Source README

Scanova MCP Server

A Model Context Protocol (MCP) server for managing your Scanova QR code platform using the Scanova API. This server provides tools for QR code creation, design, and lifecycle management; folder organization; lead-capture forms and lead lists; analytics exports; and account user administration, through MCP-compatible IDEs like Cursor, VS Code, and Claude Desktop.

Features

  • ✅ QR Codes: Create, list, retrieve, update, activate/deactivate, and delete QR codes; download them as PNG/JPG/PDF/SVG/EPS or as print-ready PDFs; and browse QR categories
  • ✅ QR Design: Customize QR code visuals - patterns, eye shapes, frames, gradients, and error correction
  • ✅ Folders: Create, list, update, and delete folders, and move or unassign QR codes between them
  • ✅ Forms & Lead Capture: List, retrieve, update, and delete lead-capture forms and lead lists, and attach or detach either from a QR code
  • ✅ Analytics: Pull account-level usage stats and per-QR performance metrics, and export analytics reports or raw scan logs
  • ✅ Account Administration: List users and roles, invite or remove users, and update user role assignments
  • ✅ Documentation Bridge: Query Scanova's docs via a live bridge to the Scanova docs MCP server

Prerequisites

  • Scanova API key (get one from https://app.scanova.io/)
  • MCP-compatible IDE (Cursor, VS Code, Claude Desktop, etc.)

Quick Setup

Step 1: Get Your Scanova API Key

  1. Visit https://app.scanova.io/
  2. Sign up or log in to your account
  3. Navigate to API settings [https://app.scanova.io/settings/api] and generate your API key.

Step 2: Configure Your IDE

Add the following configuration to your IDE's MCP settings:

For Cursor (~/.cursor/mcp.json):

{
  "mcpServers": {
    "scanova-mcp": {
      "transport": "http",
      "url": "https://mcp.scanova.io/mcp",
      "headers": {
        "Authorization": "YOUR_SCANOVA_API_KEY_HERE"
      }
    }
  }
}

For VS Code (~/.vscode/mcp.json):

{
  "mcpServers": {
    "scanova-mcp": {
      "transport": "http", 
      "url": "https://mcp.scanova.io/mcp",
      "headers": {
        "Authorization": "YOUR_SCANOVA_API_KEY_HERE"
      }
    }
  }
}

For Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "scanova-mcp": {
      "transport": "http",
      "url": "https://mcp.scanova.io/mcp", 
      "headers": {
        "Authorization": "YOUR_SCANOVA_API_KEY_HERE"
      }
    }
  }
}

Tools

82 tools. Type is the tool's MCP annotation: read-only, write (only adds), or destructive (can change or switch off something live - hosts should confirm first).

Documentation

Tool Type Description
probe_docs_mcp Read-only Check connectivity to the Scanova docs MCP server and list its available tools
query_docs Read-only Bridge to the live Scanova docs MCP server

Categories & validation

Tool Type Description
get_qr_categories Read-only List available QR code categories (URL, vCard, WiFi, Document, Social Media, etc.)
get_qr_category_fields Read-only Return the required/optional info JSON field reference for a QR code category (or all categories if none is given) - static reference data, no API call
validate_qr_info Read-only Validate a category + info JSON payload before calling create_qr_code or update_qr_code - catches malformed JSON, missing required fields, and invalid URLs/emails ahead of time

QR code design

Tool Type Description
get_qr_design_options Read-only Return the full catalog of available QR design options: all data pattern names, gradient styles, eye shape codes, frame IDs, error correction levels, fonts, and design tips
preview_qr_design Read-only Preview a QR code design without saving it: the design, scan-safety checks (colour contrast, logo and error correction), a real scan test, and a rendered image
set_qr_design Destructive Apply a visual design to an existing QR code using human-friendly named parameters
list_custom_domains Read-only List the account's custom short-link domains (e.g

QR codes

Tool Type Description
create_qr_code Write Create a new QR code
open_qr_code_creation_form Read-only Show an interactive form for creating a QR code
list_qr_codes Read-only List QR codes and/or Pages in the account
retrieve_qr_code Read-only Get details of a specific QR code
update_qr_code Destructive Update an existing QR code
activate_qr_code Write Activate a QR code
deactivate_qr_code Destructive Deactivate a QR code
delete_qr_code Destructive Permanently delete a QR code
download_qr_code Read-only Download QR code image in PNG, JPG, or PDF format
list_tags Read-only List tags attached to (or assignable against) the account's QR codes
list_trashed_qr_codes Read-only List QR codes in the trash (deleted but restorable), with when each was deleted and its scan count
restore_qr_codes Write Restore QR codes from the trash so they work again
get_qr_health Read-only The account's QR code health check: problems that stop codes working as intended - e.g
update_qr_tags Destructive Replace a QR code's tags with the ones given (an empty list removes them all)
list_gs1_recalls Read-only List the account's GS1 batch/lot recall notices: which GTIN and batch, the message shown to people who scan an affected product, and whether each is active
create_gs1_recall Write Recall a product batch: everyone who scans a GS1 QR code for this GTIN and batch/lot sees the message instead
update_gs1_recall Destructive Change a recall notice's message, or set is_active false once the recall is over (its history is kept)

Folders

Tool Type Description
create_folder Write Create a new folder to organize QR codes or pages
list_folders Read-only List all folders of a given type (qr or page)
update_folder Write Rename an existing folder
delete_folder Destructive Delete a folder
move_qr_codes_to_folder Write Move multiple QR codes into a folder
unassign_qr_codes_from_folder Write Remove multiple QR codes from a folder (moves them to uncategorized)

Forms

Tool Type Description
list_forms Read-only List all lead capture forms, optionally filtered by active status
retrieve_form Read-only Get detailed information about a specific form including its configuration
create_form Write Create a new lead-capture form from a title and its questions (each with an answer type - short answer, email, multiple choice, rating… - and options for choice questions)
update_form Destructive Update a form's name or active status
delete_form Destructive Permanently delete a form
attach_form_to_qr Write Attach a lead capture form to a QR code
detach_form_from_qr Destructive Remove the lead capture form from a QR code
list_form_responses Read-only List the responses a form has collected, newest first: each with its answers, when it came in and which QR code it came from
get_form_analytics Read-only A form's performance: total responses and skips (with the change against the previous period), responses and skips by date, and responses by source QR code
get_form_question_analytics Read-only How each question of a form was answered, in the form's order: how many responses answered it (and the rate), and for choice, rating and scale questions how often each answer was given
list_form_templates Read-only List ready-made form templates (name, description and their blocks), to start a new form from with create_form
list_form_notifications Read-only List the email alerts set up for new form responses: who they go to, how often, which forms, and whether each is on
create_form_notification Write Email someone when forms get new responses - for every response, or as a daily, weekly or monthly digest
update_form_notification Destructive Change a form alert: its recipient, frequency or forms, or switch it on or off

Lead lists (legacy)

Tool Type Description
list_lead_lists Read-only List all lead lists, optionally filtered by active status
retrieve_lead_list Read-only Get detailed information about a specific lead list including webhook config
update_lead_list Destructive Update a lead list's name or active status
delete_lead_list Destructive Permanently delete a lead list
attach_lead_list_to_qr Write Attach a lead list to a QR code for lead capture
detach_lead_list_from_qr Destructive Remove the lead list from a QR code

Analytics

Tool Type Description
get_account_stats Read-only Retrieve account-level usage counters (total QR codes, scans, users, etc.)
get_qr_analytics Read-only Retrieve QR code performance metrics broken down by device, geography, date, etc
get_analytics_overview Read-only The account's scan overview: all-time totals, this month, the last months, and scans by date
list_analytics_reports Read-only List the scan-analytics reports that have been generated: their scope, dates, status, and a download link once complete
create_analytics_report Write Generate a scan-analytics report for some QR codes, tags or folders over a date range

Account & billing

Tool Type Description
get_current_plan Read-only Retrieve the account's active subscription plan - expiry, billing state, and the full quota list it grants
list_available_plans Read-only List the plans the account can move to, with their features and quotas
get_downgrade_impact Read-only Before moving to a smaller plan: which of the account's QR codes, users, domains and other resources exceed that plan and would block or be affected by the change
list_payments Read-only The account's payment history: amount, date and status of each payment
list_orders Read-only The account's orders (plan purchases, renewals and top-ups) and their status
list_quota_topups Read-only Extra quota bought on top of the plan (e.g

Team

Tool Type Description
list_users Read-only List all users in the account
get_user Read-only Get details of a specific user
add_user Write Invite a new user to the account by email
remove_user Destructive Remove a user from the account
list_user_roles Read-only List all available user roles that can be assigned
create_custom_role Write Create a custom role/access-level (requires a dedicated plan quota - a 403 means the plan doesn't include it)
update_user_role Destructive Change the role of an existing user
resend_user_invitation Write Send a team member's invitation email again, for someone who hasn't accepted yet
get_activity_feed Read-only What happened in the account: who created, changed or deleted what, and when
get_activity_summary Read-only Counts of the account's activity over a period, for a quick picture of who did what

Custom domains

Tool Type Description
get_custom_domain Read-only One custom domain's details: its DNS (TXT/CNAME) verification, SSL status and whether it's the default

Bulk operations

Tool Type Description
list_bulk_operations Read-only List the account's bulk operations (bulk QR code generation and updates): what each did, its status and results
get_bulk_operation_stats Read-only Totals across the account's bulk operations

Media

Tool Type Description
list_media Read-only List files in the account's media library (images, PDFs, videos…), e.g

Integrations

Tool Type Description
get_integrations_overview Read-only Which integrations the account has connected (webhooks, Zapier, Slack, HubSpot, Google Analytics…) and their state
list_webhooks Read-only List the account's webhooks: where each sends events, for which forms or QR codes, and whether it's on

Conversion tracking

Tool Type Description
list_tracking_sites Read-only List the websites set up for conversion tracking (what visitors do after scanning), with their domains
list_tracking_funnels Read-only List a tracking site's conversion funnels: the steps from scan to conversion

Landing pages

Tool Type Description
list_page_templates Read-only List landing page templates for QR codes that open a page - Scanova's own, or only the account's saved ones
list_page_blocks Read-only The blocks a landing page can have for a page category, what each is for and how many a page holds
get_page_block Read-only One block type's fields, defaults and data schema
list_page_themes Read-only The themes a page can use, with their main colours
get_page_theme Read-only One theme's full values (colours, fonts, corners, shadows, spacing, background)
get_page_template Read-only One template's theme and blocks
get_page Read-only A code's landing page: blocks in order, theme, unpublished changes, preview and builder links
get_page_preview Read-only A 1-hour link to the latest draft as visitors would see it; optionally a screenshot
create_page Write Create a code with a landing page as a draft, from a template or blocks
edit_page Write Change the draft: add, change, remove or move blocks; theme; theme values; a template's look or layout; name; search details
publish_page Write (destructive) Make the draft live for everyone scanning the code

Pages are written in the page builder's block format, so they open at app.scanova.io and can be edited there. Blocks are checked against Scanova's own schemas before saving; refresh them with python scripts/sync_page_blocks.py <qcg-backend> <qcg-frontend-next> when blocks change.

Usage

The server provides the following MCP tools that you can use in your MCP-compatible IDE:

API Endpoints

The deployed server provides these endpoints:

  • POST /mcp - Main MCP endpoint (Streamable HTTP)
  • GET /health - Health check endpoint
  • GET / - Service information and documentation
  • GET /.well-known/oauth-protected-resource - OAuth protected-resource metadata

Protocol

Built on the MCP Python SDK 2.x, which serves
the protocol. The server is dual-era:

  • MCP 2026-07-28 (stateless): every request carries its protocol version; server/discover,
    cache hints, resultType and request-header validation are supported.
  • Earlier revisions (2025-11-25 and before): clients that open with initialize - today's
    Cursor, VS Code, Claude Desktop, claude.ai and ChatGPT connectors - keep working unchanged.

Authentication. Send your Scanova API key (or an OAuth access token from Scanova's
authorization server) in Authorization - Bearer <key> or the bare key - or in X-API-Key.
Listing tools and UI resources needs no key; calling a tool without one returns
401 with a WWW-Authenticate challenge pointing at the protected-resource metadata.

Tool failures (for example a Scanova API error) come back as tool results with isError: true,
so the assistant can read and explain them.

UI widgets use the MCP Apps
extension (io.modelcontextprotocol/ui), plus openai/outputTemplate for ChatGPT.

Local Development (Optional)

If you want to run the server locally for development:

Installation

  1. Clone the repository:

    git clone <repository-url>
    cd qcg-mcp
    
  2. Install dependencies:

    uv sync
    
  3. Run locally:

    # HTTP server mode (same app as production)
    uv run src/cloud_server.py
    
    # Or stdio mode for local MCP testing (uses MCP_ACCESS_TOKEN for the Scanova API)
    MCP_ACCESS_TOKEN=your-key uv run src/main.py --stdio
    
  4. Configure for local testing:

    {
      "mcpServers": {
        "qcg-mcp": {
          "transport": "http",
          "url": "http://localhost:8000/mcp",
          "headers": {
            "Authorization": "YOUR_SCANOVA_API_KEY_HERE"
          }
        }
      }
    }
    

Docker Deployment (Local)

  1. Build the Docker image:

    docker build -t mcpserver:local .
    
  2. Start the container:

    docker run -d --name mcpserver -p 8000:8000 mcpserver:local
    

    Or with Docker Compose:

    docker compose up -d
    
  3. Verify the server is running:

    curl http://localhost:8000/health
    
  4. Configure your IDE (HTTP transport):
    Use the "Configure for local testing" snippet above and point to http://localhost:8000/mcp, ensuring the Authorization header contains your Scanova API key.

  5. View logs and stop:

    # View logs
    docker logs -f mcpserver
    
    # Stop and remove with Compose
    docker compose down
    
    # Or stop/remove single container
    docker stop mcpserver && docker rm mcpserver
    

Releases and deploys

Pull request titles follow Conventional Commits
(feat: …, fix: …, docs: …, chore: …; add ! - feat!: … - for a breaking change).
Merging adds the PR to the draft release, versioned by
release-drafter with semantic versioning:
feat → minor, fix and the rest → patch, breaking → major.

Publishing the draft release deploys it (.github/workflows/deploy.yml): tests run, the
image is built and tagged with the version, the scanova-mcp ECS Express service is updated to it,
and /health and initialize are checked. A merge to main does not deploy. To redeploy or roll
back, run the Deploy workflow from the Actions tab with that release's tag as the ref.

AWS access is GitHub OIDC → IAM role qcg-mcp-github-deploy (no stored keys): it trusts only this
repository's production environment (release tags v* only) and can only push this image, update
the scanova-mcp service and pass its task roles.

Troubleshooting

Common Issues

  1. "API key is required"

    • Ensure your Scanova API key is correctly set in the headers
    • Check that the header format matches one of the supported formats
    • Get your API key from https://app.scanova.io/
  2. "Invalid token" error

    • Verify your API key is valid and active
    • Ensure there are no extra spaces or characters in the API key
    • Try regenerating your API key from the Scanova dashboard
  3. Connection errors

    • Check that the server URL is correct
    • Ensure your internet connection is working
    • Verify the server is deployed and running
  4. Tool not found

    • Restart your IDE after adding the MCP configuration
    • Check that the JSON configuration is valid
    • Verify the server responds at the /health endpoint

scripts/sync_page_blocks.py

"""Refresh src/page_blocks/ from Scanova's own sources.

The page tools build landing pages in the page builder's block format. The
format is owned by two repos, so this copies it here rather than restating it:

- qcg-backend  src/qr_manager/json_schema/{v2,categories/components}: the JSON
  Schemas a page's blocks must pass to publish (copied as-is to schemas/).
- qcg-frontend-next  packages/blocks/src/blocks/landing/*/definition.ts: each
  block's label, limit, categories, fields and defaults (dumped to blocks.json
  by dump_block_definitions.mjs, which needs `npm i esbuild` next to it).

Usage: python scripts/sync_page_blocks.py <qcg-backend checkout> <qcg-frontend-next checkout>
"""

import json
import shutil
import subprocess
import sys
from pathlib import Path

HERE = Path(__file__).resolve().parent
OUT = HERE.parent / "src" / "page_blocks"

# Blocks an assistant shouldn't place on an ordinary page: they belong to a
# special page type (intro/document/image pages, cover/main pages), only make
# sense on a GS1 code, or run the customer's own JavaScript.
LEFT_OUT = {
    "auto_redirect", "document_viewer", "image_gallery", "cover_page", "main_page", "intro_page",
    "gs1_info", "custom_script",
}


def main(backend: Path, frontend: Path) -> None:
    src = backend / "src" / "qr_manager" / "json_schema"
    schemas = OUT / "schemas"
    if schemas.exists():
        shutil.rmtree(schemas)
    shutil.copytree(src / "v2", schemas / "v2")
    shutil.copytree(src / "categories" / "components", schemas / "categories" / "components")
    shutil.copytree(backend / "src" / "theme_manager" / "json_schema", schemas / "theme")

    dumped = json.loads(subprocess.run(
        ["node", str(HERE / "dump_block_definitions.mjs"), str(frontend)],
        check=True, capture_output=True, text=True,
    ).stdout)
    allowed = json.loads((src / "v2" / "page-types" / "component-page.json").read_text())
    allowed = allowed["items"]["allOf"][1]["properties"]["type"]["enum"]
    blocks = {}
    for block_type in allowed:
        d = dumped.get(block_type)
        if block_type in LEFT_OUT or not d or "error" in d:
            continue
        blocks[block_type] = {
            "label": d.get("label"),
            "description": d.get("description"),
            "limit": d.get("limit"),
            "removable": d.get("canDelete") is not False,
            "categories": d.get("allowedInCategories"),
            "fields": d.get("fields") or [],
            "defaults": d.get("defaults") or {},
        }
    (OUT / "blocks.json").write_text(json.dumps(blocks, indent=1, ensure_ascii=False) + "\n")
    print(f"{len(blocks)} blocks, schemas from {src}")


if __name__ == "__main__":
    main(Path(sys.argv[1]), Path(sys.argv[2]))

FAQ

Common questions

Discussion

Questions & comments · 0

Sign In Sign in to leave a comment.