Skip to main content
Glama
ZivSapir

Customer Support Analyst MCP

by ZivSapir

Customer Support Analyst MCP

Local Model Context Protocol server for natural-language Q&A over a customer-support ticket dataset. Built for analysts and ops - not a customer-facing chatbot.

Model

This MCP server does not call an LLM itself. Natural-language planning is performed by the MCP host. The server is model-agnostic: it uses whatever model the host already has configured.

Tested end-to-end with:

  • Cursor Agent - Composer

Also runnable with Claude Code and Codex (same stdio server; configuration below).

No OPENAI_API_KEY or ANTHROPIC_API_KEY is required by this server. The host's configured model performs planning; this process only executes tools.

Related MCP server: support-ticket-mcp

How it works

Tool

Use for

ping

Health check / troubleshooting (MCP config smoke test)

get_schema

Compact fields, small filter enums, table counts, and SQL vs search routing

query_tickets

Counts, group-bys, structured filters (read-only SQL; results labeled untrusted)

search_tickets

Lexical keyword/topic examples (BM25); minimal hits + relevance_score (ranking only); subjects labeled untrusted

get_ticket

One ticket by id (detail after search; text marked untrusted)

search_metrics

Lexical FTS match counts / group-bys for free-text queries

Structured counts come from query_tickets (including ticket_tags for label analytics). Match volumes come from search_metrics (lexical FTS only - not semantic topic prevalence). search_tickets hits are ranked examples, not volume - use get_ticket for body/answer. Ticket subject/body/answer are untrusted model input.

get_schema intentionally omits the 1,255-value tag vocabulary to keep first-call context small. Discover relevant tags through an aggregate query_tickets query on ticket_tags (use COUNT(DISTINCT ticket_id) for ticket counts). Wording questions ("mention/say/contain X") use search_metrics; explicit labels use ticket_tags - do not treat one as the other.

FTS uses an inverted index, stemming, and BM25 ranking - better than SQL LIKE for examples, still not paraphrase/embedding search. Multi-word queries default to match_mode: "any" (at least one term); use "all" when every term should be present. Neither mode is exact phrase matching. The dataset is EN+DE; SQL works for both languages. FTS uses DuckDB's default English analyzer, so German text search is best-effort.

Dataset: Tobi-Bueck/customer-support-tickets (Hugging Face Support_Dataset; downloaded once at ingest).

Architecture and rejected alternatives: DECISIONS.md.

Requirements

  • Node.js 20+

  • npm (setup only: install / ingest / build / verify)

  • An MCP host (Cursor, Claude Code, or Codex)

Quick start

Three stages: install and prepare are yours; connect is the host spawning Node.

1. Install

git clone https://github.com/ZivSapir/customer-support-analyst-mcp.git
cd customer-support-analyst-mcp
npm ci

2. Prepare

npm run ingest   # downloads CSV (first run), builds local DuckDB + FTS index
npm run build    # compiles src/ → dist/index.js
npm run verify   # optional: pinned smoke checks

data/ is gitignored. Each machine runs ingest locally against a pinned Hugging Face revision (see src/dataset.ts); the CSV checksum is verified and data/ingest-manifest.json records provenance.

After this step you should have:

  • data/tickets.duckdb

  • dist/index.js (the MCP server entrypoint)

3. Connect (ask questions in the host)

Do not leave npm start running in a terminal to "use" the app. This is a stdio MCP server: Claude Code / Codex / Cursor spawn the process when they need tools:

MCP host (Claude Code / Codex / Cursor)
  → spawns:  node /ABSOLUTE/PATH/TO/customer-support-analyst-mcp/dist/index.js
  → talks over stdin/stdout
  → you ask natural-language questions in the host chat

Next step: pick your host under MCP configuration and paste that JSON/TOML block. Replace /ABSOLUTE/PATH/TO/customer-support-analyst-mcp with the real clone path on your machine (the folder that contains dist/index.js after npm run build). Prefer node + that absolute dist/index.js path (not npm start), so the working directory cannot break startup. Reload/restart MCP in the host, confirm the tools appear, then ask a question in chat.

Optional: npm start is only a manual check that the process boots; it waits for an MCP client on stdin/stdout and is not the normal way to ask questions.

MCP configuration

Replace /ABSOLUTE/PATH/TO/customer-support-analyst-mcp with your clone path (example: /Users/you/code/customer-support-analyst-mcp). The args entry must point at dist/index.js inside that folder. After changing tools, restart/reload the MCP server in the host so it picks up the new tool list.

Cursor

User or project config (.cursor/mcp.json / ~/.cursor/mcp.json):

{
  "mcpServers": {
    "customer-support-analyst": {
      "command": "node",
      "args": ["/ABSOLUTE/PATH/TO/customer-support-analyst-mcp/dist/index.js"]
    }
  }
}

You should see ping, get_schema, query_tickets, search_tickets, get_ticket, and search_metrics. If the server or ping is unavailable, verify the absolute path, build output (dist/index.js), and local ingest (npm run ingest) before debugging dataset queries.

Claude Code

Project-scoped .mcp.json in the repo root:

{
  "mcpServers": {
    "customer-support-analyst": {
      "type": "stdio",
      "command": "node",
      "args": ["/ABSOLUTE/PATH/TO/customer-support-analyst-mcp/dist/index.js"]
    }
  }
}

Or via CLI: claude mcp add --transport stdio customer-support-analyst -- node /ABSOLUTE/PATH/TO/customer-support-analyst-mcp/dist/index.js

Codex

Add to ~/.codex/config.toml (or project-scoped .codex/config.toml in a trusted project):

[mcp_servers.customer-support-analyst]
command = "node"
args = ["/ABSOLUTE/PATH/TO/customer-support-analyst-mcp/dist/index.js"]

Or via CLI: codex mcp add customer-support-analyst -- node /ABSOLUTE/PATH/TO/customer-support-analyst-mcp/dist/index.js

Cursor example file: mcp.config.example.json.

Example questions

Question

Expected tool

How many tickets are in the dataset?

query_tickets

High-priority tickets by queue

query_tickets

Breakdown by language and priority

query_tickets

What are customers saying about refunds?

search_tickets

Password-reset tickets in German (by language column)

query_tickets, or search_tickets with language: "de" and preferably match_mode: "all" (FTS is English-optimized)

How many tickets mention refunds?

search_metrics (lexical wording - not the Refund tag)

High-priority tickets about password resets (examples)

search_tickets with filters; prefer match_mode: "all" for multi-word topics

How many tickets have the Refund tag?

query_tickets on ticket_tags with COUNT(DISTINCT ticket_id)

Optional MCP prompt: ticket-analyst (reminder only - routing lives in tool contracts + get_schema).

Full list of example questions (routing hints for operators - not an automated LLM eval harness): eval/questions.json. npm run verify checks that file's shape and pinned DuckDB/FTS expectations.

Scripts

Script

Purpose

npm run ingest

Pinned CSV → data/tickets.duckdb + FTS + ingest manifest

npm run peek

Print columns + sample rows from local DuckDB

npm run build

Compile src/dist/

npm run verify

Pinned smoke checks (row counts, filters, FTS, SQL guard/FS, eval JSON shape)

npm run dev

Run the stdio server via tsx (development)

npm start

Alias for node dist/index.js - manual stdio boot check only; hosts should spawn Node themselves

Maintenance

ActivityMaintained
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 natural language querying of any SQL database by converting plain English questions into SQL queries, with auto-schema detection and safety features.
    3
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables natural language querying and semantic search over a bilingual customer support ticket dataset using SQL and embeddings.
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables natural language queries, CRUD operations, and analytics on a PostgreSQL database (Neon) via Claude, supporting customers, tickets, products, and analytics.
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables natural language querying of SQL databases using AI, supporting multiple database types and automatic schema discovery.
    1
    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/ZivSapir/customer-support-analyst-mcp'

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