Skip to main content
Glama
koosoftware

QMSCloud Reporting MCP Server

by koosoftware

QMSCloud Reporting MCP Server — Node.js (Metabase)

Queries pre-built Metabase cards for QMSCloud and exposes them to AnythingLLM:

AnythingLLM (host)  ->  Ollama / Qwen  ->  this MCP server  ->  Metabase card JSON

Sibling of ../mcpreport (which talks to the QMS700i servlet). The difference: this server has no login flow — Metabase authenticates with a static x-api-key header, and each report is a saved Metabase card queried via POST /api/card/<id>/query/json.

Tools

  • get_report(report, start_date?, end_date?) — fetch and return card rows. workspace_slug is injected by AnythingLLM (do not pass it manually).

  • list_reports() — list available report keys.

Currently available reports: ticket_summary (card 40). Appointment, rating, etc. will be added to the CARDS catalog in metabase-core.js.

Related MCP server: Metabase MCP Server

How it works

  1. AnythingLLM injects workspace_slug on every call. The slug encodes the tenant as <companyCode> or <companyCode>___<branchCode> — split on the first triple underscore ___ (codes themselves are hyphen-slugs, e.g. branch-001).

  2. The server resolves the tenant dynamically from Metabase (no hardcoded map), caching the lookups for 5 minutes:

    • Company: POST card 41, slugify each CompanyCode, match the company part → CompanyId. No match → invalid company code.

    • Branch (only if present): POST card 42, slugify each BranchCode, match the branch part and CompanyId (branch codes repeat across companies) → BranchId. No match → invalid branch code.

    • So demo → DEMO company, whole-company view; demo___kl001 → DEMO + KL001 branch; qc___branch-001 → QC + Branch 1. New companies/branches work with no code change.

  3. The model supplies start_date / end_date from the user's intent.

  4. The server POSTs the Metabase parameters array (start_date, end_date, company_id, and branch_id when present) to the ticket card and returns rows.

1. Install

Requires Node.js 18+ (built-in fetch).

cd /Users/koo/Desktop/Claude/Projects/QMS/metabase-mcpreport
npm install

2. Quick local test (no AnythingLLM)

The API key is not hardcoded — export it first:

export METABASE_API_KEY='mb_...your key...'
node test-ticket-summary.js                       # demo, month-to-date
node test-ticket-summary.js demo 2026-06-11 2026-06-30

3. Register in AnythingLLM

Add to anythingllm_mcp_servers.json (absolute paths):

{
  "mcpServers": {
    "qmscloud-report": {
      "command": "node",
      "args": ["/Users/koo/Desktop/Claude/Projects/QMS/metabase-mcpreport/server.js"],
      "env": {
        "METABASE_BASE_URL": "http://54.251.164.99:7777",
        "METABASE_API_KEY": "mb_...PASTE_KEY..."
      }
    }
  }
}

Windows note (same gotcha as ../mcpreport): if C:\Program Files\nodejs\node.exe fails with ENOENT, use the 8.3 short path C:\\PROGRA~1\\nodejs\\node.exe.

4. Set the workspace system prompt

Paste the contents of system_prompt.txt into the AnythingLLM workspace system prompt. It tells the model when/how to call get_report. Tools only fire in @agent mode.

METABASE_API_KEY is required and is not hardcoded (kept out of source control). Set it in the env block above. METABASE_BASE_URL defaults to http://54.251.164.99:7777 if omitted.

Configuration reference

  • Tenant resolution is dynamic (cards 41/42) — no slug map to maintain. Env overrides: METABASE_COMPANY_CARD_ID (41), METABASE_BRANCH_CARD_ID (42), METABASE_LOOKUP_TTL_MS (300000). Test with node test-lookup-cards.js.

  • CARDS (metabase-core.js) — report key → Metabase card id + params.

Notes

  • Tools fire only in AnythingLLM @agent mode.

  • Treat the Metabase API key as a secret; keep this config out of git.

Available Tools

2 tools
get_reportA

Fetch a QMSCloud report from Metabase and analyze it to answer the user's question. Returns a compact summary (distinct tickets; breakdowns by status, service, branch, counter, business date; a ticket_numbers list; and waiting/serving-time stats) plus a few sampleRows. For questions that require listing individual tickets WITH their times, pass detail=true to also get a per-ticket table. Pass the exact report key (call list_reports if unsure). Supply start_date/end_date as YYYY-MM-DD from the user's intent (defaults to current month-to-date). The tenant (company/branch) is resolved automatically from the workspace — do not ask the user for it. Currently available: 'ticket_summary'.

ParametersJSON Schema
NameRequiredDescriptionDefault
detailNoSet true when the user wants to LIST individual tickets with their times (issued/called/completed, waiting/serving minutes). Adds a compact `summary.tickets` table. Default false (aggregates only).
reportYesExact report key, e.g. 'ticket_summary'. See list_reports.
end_dateNoEnd date YYYY-MM-DD. Defaults to today.
start_dateNoStart date YYYY-MM-DD. Defaults to the first of the current month.
include_rowsNoRarely needed. If true, also returns every raw row with all columns (large, GUID-heavy). Prefer `detail` for per-ticket listing. Default false.
workspace_slugYesInternal: identifies which QMSCloud tenant to query. Injected automatically by the AnythingLLM host on every call — do not ask the user for it and do not set it yourself.

TDQS

A4.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must fully disclose behavior. It describes fetching and analyzing without explicitly stating if the tool is read-only or if it has side effects. The lack of a direct statement about non-destructive behavior is a significant gap given the absence of annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single paragraph but highly information-dense, starting with the main purpose. It covers all key points without redundancy. However, it could benefit from more structured formatting (e.g., bullet points) for easier scanning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 6 parameters, no output schema, and one sibling, the description covers the return format, parameter usage, and auto-resolution of tenant. It does not address error cases or full output details, but the provided information is sufficient for an AI agent to use the tool correctly in most contexts.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so baseline is 3. The description adds value beyond the schema by explaining the purpose of detail vs include_rows, providing date format and defaults, and clarifying that workspace_slug is injected automatically. This extra context justifies a higher score.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states that the tool fetches and analyzes a QMSCloud report from Metabase to answer user questions, and details the return format. It distinguishes itself from the sibling list_reports by referencing it as a way to find the report key if unsure.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear when-to-use guidance: pass detail=true for per-ticket times, use list_reports for the exact report key, supply dates as YYYY-MM-DD, and notes that the tenant is auto-resolved. It also explains defaults and what not to do (do not ask for workspace_slug).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_reportsA

List the QMSCloud report keys this server can fetch from Metabase.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Without annotations, the description bears full burden. It correctly implies a read-only listing but offers no detail on permissions, side effects, or behavior beyond the basic operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, compact sentence with no wasted words, fitting the tool's simplicity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter listing tool, the description covers the essential purpose. It could mention that the keys are used with get_report, but overall it's sufficient given the simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are no parameters; schema coverage is 100%. Per baseline rules, a score of 4 is appropriate as no additional parameter semantics are needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists QMSCloud report keys from Metabase, providing a specific verb and resource. It distinguishes from the sibling tool get_report, which presumably retrieves a specific report.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is given on when to use this tool versus the sibling get_report, nor any context on prerequisites or typical workflow.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 2 tool updatesv1.0.0
    • First observedget_report
    • First observedlist_reports

TDQS

A4/5.0
Disambiguation5/5

The two tools are clearly distinct: one lists available reports, the other fetches a specific report. No ambiguity.

Naming Consistency5/5

Both tools follow a consistent verb_noun pattern with snake_case: list_reports and get_report.

Tool Count4/5

For a focused reporting server with only one report type currently available, two tools (list and get) are appropriate and efficient.

Completeness3/5

Covers the essential operations for its narrow domain (listing and retrieving a report). However, it lacks support for other expected reports or more advanced filtering, limiting completeness.

Maintenance

ActivitySlowing
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to interact with Metabase analytics platform, allowing them to query databases, manage dashboards and cards, execute SQL queries, and access analytics data through natural language.
    47
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to interact with Metabase analytics platform, allowing users to query databases, manage dashboards and cards, execute SQL queries, and access analytics data through natural language.
    47
    1
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to interact with Metabase through its API, allowing them to list, read, execute, and manage databases, tables, dashboards, cards, collections, and queries with support for multiple export formats.
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to interact with Metabase analytics platform, allowing them to query databases, execute SQL, manage dashboards and cards, and access analytics data through natural language.
    47
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/koosoftware/metabase-mcpreport'

If you have feedback or need assistance with the MCP directory API, please join our Discord server