{"server":{"name":"QR Hero","version":"1.0.0","endpoint":"https:\/\/mcp.qrhero.com\/mcp","transport":"HTTP (JSON-RPC 2.0)","authentication":"Bearer Sanctum token with mcp.access ability","instructions":"Manage QR Hero via MCP. Each tool maps 1:1 to a REST \/v1 endpoint with the same Sanctum token abilities, org scoping, rate limits, and metering. Account-detail and wallet\/payment writes are not available. Destructive and bulk operations (codes_delete, codes_bulk_create above threshold, codes_bulk_update_status) return a dry-run preview first; call again with confirm: true and confirmation_id to execute. Single-record create\/update execute immediately. REST bulk import staging uses codes_bulk_create + codes_bulk_confirm with confirm_token."},"confirm_then_execute":{"description":"Destructive and high-volume bulk MCP tools return a dry-run preview on the first call. Execute by calling again with confirm: true and the confirmation_id from the preview.","ttl_seconds":300,"bulk_create_threshold":10,"guarded_tools":["codes_delete","codes_bulk_create","codes_bulk_update_status"],"flow":{"First call (dry run)":"Returns { requires_confirmation: true, confirmation_id, preview }","Second call (execute)":"Same arguments plus confirm: true and confirmation_id"},"rest_bulk_import_note":"REST bulk import uses a separate two-phase flow with confirm_token via POST \/v1\/qr-codes\/bulk and POST \/v1\/qr-codes\/bulk\/{import_ulid}\/confirm."},"tools":[{"name":"status_read","description":"Health check and token context (GET \/v1\/status).","rest_method":"GET","rest_path":"\/v1\/status","ability":null,"requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"type":"object","properties":{}}},{"name":"organization_read","description":"Read organization profile (GET \/v1\/organization).","rest_method":"GET","rest_path":"\/v1\/organization","ability":null,"requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"type":"object","properties":{}}},{"name":"analytics_read","description":"Read scan analytics rollup (GET \/v1\/analytics).","rest_method":"GET","rest_path":"\/v1\/analytics","ability":"analytics.view","requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"properties":{"range":{"description":"7, 30, or 90 days (default 30).","type":"integer"},"dimension":{"description":"country | device | referrer | language","type":"string"},"brand_ulid":{"description":"Optional brand scope.","type":"string"},"code_ulid":{"description":"Optional code scope.","type":"string"}},"type":"object"}},{"name":"analytics_export","description":"Export analytics payload with csv_rows (GET \/v1\/analytics\/export).","rest_method":"GET","rest_path":"\/v1\/analytics\/export","ability":"analytics.export","requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"properties":{"range":{"description":"7, 30, or 90 days (default 30).","type":"integer"},"dimension":{"description":"country | device | referrer | language","type":"string"},"brand_ulid":{"description":"Optional brand scope.","type":"string"},"code_ulid":{"description":"Optional code scope.","type":"string"}},"type":"object"}},{"name":"brands_list","description":"List brands (GET \/v1\/brands).","rest_method":"GET","rest_path":"\/v1\/brands","ability":"brands.view","requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"type":"object","properties":{}}},{"name":"brands_create","description":"Create a brand (POST \/v1\/brands).","rest_method":"POST","rest_path":"\/v1\/brands","ability":"brands.manage","requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"properties":{"name":{"description":"Brand name.","type":"string"},"slug":{"description":"Optional alpha_dash slug.","type":"string"},"brand_kit":{"description":"Optional brand kit object.","type":"object"},"settings":{"description":"Optional settings object.","type":"object"},"primary_domain_ulid":{"description":"Optional primary domain ULID.","type":"string"}},"type":"object","required":["name"]}},{"name":"brands_update","description":"Update a brand (PATCH \/v1\/brands\/{brand_ulid}).","rest_method":"PATCH","rest_path":"\/v1\/brands\/{brand_ulid}","ability":"brands.manage","requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"properties":{"brand_ulid":{"description":"Brand ULID.","type":"string"},"name":{"description":"Brand name.","type":"string"},"slug":{"description":"Optional alpha_dash slug.","type":"string"},"brand_kit":{"description":"Optional brand kit object.","type":"object"},"settings":{"description":"Optional settings object.","type":"object"},"primary_domain_ulid":{"description":"Optional primary domain ULID.","type":"string"}},"type":"object","required":["brand_ulid"]}},{"name":"domains_list","description":"List domains (GET \/v1\/domains).","rest_method":"GET","rest_path":"\/v1\/domains","ability":"domains.view","requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"type":"object","properties":{}}},{"name":"domains_create","description":"Add a custom domain (POST \/v1\/domains).","rest_method":"POST","rest_path":"\/v1\/domains","ability":"domains.manage","requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"properties":{"host":{"description":"Hostname, e.g. links.example.com.","type":"string"},"verify":{"description":"Attempt immediate TXT verification.","type":"boolean"}},"type":"object","required":["host"]}},{"name":"domains_update","description":"Verify or update a domain (PATCH \/v1\/domains\/{domain_ulid}).","rest_method":"PATCH","rest_path":"\/v1\/domains\/{domain_ulid}","ability":"domains.manage","requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"properties":{"domain_ulid":{"description":"Domain ULID.","type":"string"},"verify":{"description":"Re-check TXT ownership.","type":"boolean"},"refresh_ssl":{"description":"Refresh SSL status.","type":"boolean"},"is_primary":{"description":"Set as primary domain.","type":"boolean"}},"type":"object","required":["domain_ulid"]}},{"name":"codes_list","description":"List QR codes (GET \/v1\/qr-codes).","rest_method":"GET","rest_path":"\/v1\/qr-codes","ability":"codes.view","requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"type":"object","properties":{}}},{"name":"codes_read","description":"Read a QR code (GET \/v1\/qr-codes\/{code_ulid}).","rest_method":"GET","rest_path":"\/v1\/qr-codes\/{code_ulid}","ability":"codes.view","requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"properties":{"code_ulid":{"description":"QR code ULID.","type":"string"}},"type":"object","required":["code_ulid"]}},{"name":"codes_create","description":"Create a QR code (POST \/v1\/qr-codes).","rest_method":"POST","rest_path":"\/v1\/qr-codes","ability":"codes.create","requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"properties":{"slug":{"description":"Individual slug (stored as org-slug\/slug).","type":"string"},"destination":{"description":"Redirect destination URL.","type":"string"},"domain_ulid":{"description":"Domain ULID.","type":"string"},"name":{"description":"Optional display name.","type":"string"},"brand_ulid":{"description":"Optional brand ULID.","type":"string"},"style_ulid":{"description":"Optional style ULID.","type":"string"},"type":{"description":"Code type (default redirect).","type":"string"},"status":{"description":"Optional status.","type":"string"},"routing":{"description":"Optional routing rules.","type":"object"},"schedule":{"description":"Optional schedule object.","type":"object"},"password":{"description":"Optional password (plan-gated).","type":"string"},"redirect_cap":{"description":"Optional redirect cap (plan-gated).","type":"integer"}},"type":"object","required":["slug","destination","domain_ulid"]}},{"name":"codes_update","description":"Update a QR code (PATCH \/v1\/qr-codes\/{code_ulid}).","rest_method":"PATCH","rest_path":"\/v1\/qr-codes\/{code_ulid}","ability":"codes.update","requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"properties":{"code_ulid":{"description":"QR code ULID.","type":"string"},"destination":{"description":"Redirect destination URL.","type":"string"},"status":{"description":"Optional status.","type":"string"},"name":{"description":"Optional display name.","type":"string"},"routing":{"description":"Optional routing rules.","type":"object"},"redirect_cap":{"description":"Optional redirect cap.","type":"integer"}},"type":"object","required":["code_ulid"]}},{"name":"codes_delete","description":"Soft-delete a QR code. Always requires a dry-run preview first; call again with confirm: true to execute.","rest_method":"DELETE","rest_path":"\/v1\/qr-codes\/{code_ulid}","ability":"codes.delete","requires_confirmation":true,"is_destructive":true,"mcp_only":false,"inputSchema":{"properties":{"code_ulid":{"description":"QR code ULID.","type":"string"},"confirm":{"description":"Set to true on the second call to execute after reviewing the preview.","type":"boolean"},"confirmation_id":{"description":"Confirmation id returned by the dry-run preview.","type":"string"}},"type":"object","required":["code_ulid"]}},{"name":"codes_bulk_create","description":"Create multiple QR codes. Above the configured row threshold, returns a dry-run preview first; call again with confirm: true to execute. At or below the threshold, creates immediately.","rest_method":"POST","rest_path":"\/v1\/qr-codes\/bulk","ability":"codes.create","requires_confirmation":true,"is_destructive":false,"mcp_only":false,"inputSchema":{"properties":{"rows":{"description":"Array of row objects.","type":"array"},"defaults":{"description":"Optional defaults applied to each row.","properties":{"domain_ulid":{"type":"string"},"brand_ulid":{"type":"string"},"type":{"type":"string"}},"type":"object"},"confirm":{"description":"Set to true on the second call to execute after reviewing the preview.","type":"boolean"},"confirmation_id":{"description":"Confirmation id returned by the dry-run preview.","type":"string"}},"type":"object","required":["rows"]}},{"name":"codes_bulk_read","description":"Read bulk import status (GET \/v1\/qr-codes\/bulk\/{import_ulid}).","rest_method":"GET","rest_path":"\/v1\/qr-codes\/bulk\/{import_ulid}","ability":"codes.view","requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"properties":{"import_ulid":{"description":"Bulk import ULID.","type":"string"}},"type":"object","required":["import_ulid"]}},{"name":"codes_bulk_confirm","description":"Confirm and execute bulk import (POST \/v1\/qr-codes\/bulk\/{import_ulid}\/confirm).","rest_method":"POST","rest_path":"\/v1\/qr-codes\/bulk\/{import_ulid}\/confirm","ability":"codes.create","requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"properties":{"import_ulid":{"description":"Bulk import ULID.","type":"string"},"confirm_token":{"description":"Token from codes_bulk_create response.","type":"string"}},"type":"object","required":["import_ulid","confirm_token"]}},{"name":"codes_bulk_update_status","description":"Change status on multiple QR codes. Always requires a dry-run preview first; call again with confirm: true to execute.","rest_method":"POST","rest_path":"\/v1\/qr-codes\/bulk\/status","ability":"codes.update","requires_confirmation":true,"is_destructive":false,"mcp_only":true,"inputSchema":{"properties":{"ulids":{"description":"ULIDs of the QR codes whose status should change.","type":"array"},"status":{"description":"New status value (e.g. active, disabled_manual).","type":"string"},"confirm":{"description":"Set to true on the second call to execute after reviewing the preview.","type":"boolean"},"confirmation_id":{"description":"Confirmation id returned by the dry-run preview.","type":"string"}},"type":"object","required":["ulids","status"]}},{"name":"styles_list","description":"List QR styles (GET \/v1\/qr-styles).","rest_method":"GET","rest_path":"\/v1\/qr-styles","ability":"styles.manage","requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"properties":{"brand_ulid":{"description":"Optional brand filter.","type":"string"}},"type":"object"}},{"name":"styles_create","description":"Create a QR style preset (POST \/v1\/qr-styles).","rest_method":"POST","rest_path":"\/v1\/qr-styles","ability":"styles.manage","requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"properties":{"name":{"description":"Style name.","type":"string"},"config":{"description":"qr_styles.config object.","type":"object"},"brand_ulid":{"description":"Optional brand ULID.","type":"string"},"is_preset":{"description":"Mark as preset style.","type":"boolean"}},"type":"object","required":["name","config"]}},{"name":"tokens_abilities","description":"List assignable token abilities (GET \/v1\/tokens\/abilities).","rest_method":"GET","rest_path":"\/v1\/tokens\/abilities","ability":"api.tokens.manage","requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"type":"object","properties":{}}},{"name":"tokens_list","description":"List API tokens (GET \/v1\/tokens).","rest_method":"GET","rest_path":"\/v1\/tokens","ability":"api.tokens.manage","requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"type":"object","properties":{}}},{"name":"tokens_create","description":"Create an API token (POST \/v1\/tokens). Returns plain-text secret once.","rest_method":"POST","rest_path":"\/v1\/tokens","ability":"api.tokens.manage","requires_confirmation":false,"is_destructive":false,"mcp_only":false,"inputSchema":{"properties":{"name":{"description":"Token label.","type":"string"},"abilities":{"description":"Ability list (default [\"*\"]).","type":"array"},"expires_at":{"description":"Optional ISO8601 expiry datetime.","type":"string"}},"type":"object","required":["name"]}},{"name":"tokens_revoke","description":"Revoke an API token (DELETE \/v1\/tokens\/{token_id}).","rest_method":"DELETE","rest_path":"\/v1\/tokens\/{token_id}","ability":"api.tokens.manage","requires_confirmation":false,"is_destructive":true,"mcp_only":false,"inputSchema":{"properties":{"token_id":{"description":"Personal access token id.","type":"integer"}},"type":"object","required":["token_id"]}}]}