Support Triage MCP
Enables LLM-based ticket classification and suggested response drafting by connecting to a local Ollama server, with configurable model and endpoint.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Support Triage MCPtriage the newest open ticket and draft a first response"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Support Triage MCP
An MCP (Model Context Protocol) server that exposes a support-ticket inbox as tools an AI client can use to list, inspect, triage, and update tickets. The dataset here is mocked (styled after a home-loan partner-support inbox: loan status queries, document issues, disbursement delays, KYC, etc.) but the server is written so a real ticket source (Zendesk, email, a helpdesk API) could be swapped in later without changing the tool interface.
Status
Core plumbing (list_tickets, get_ticket, update_ticket_status) and
LLM-based triage (classify_ticket, with RAG-style retrieval of similar
past tickets) are both working. classify_ticket runs entirely on a local,
open-source LLM via Ollama — no API key, no per-call
cost. See Roadmap for what's next.
Setting up Ollama (needed for classify_ticket)
Install Ollama from ollama.com (Windows/Mac/Linux).
Pull a model (one-time download, then it runs fully offline):
ollama pull llama3.2llama3.2(3B) is small and fast enough for CPU-only laptops. For better classification quality if your machine can handle it, tryollama pull llama3.1(8B) orollama pull mistral— just setOLLAMA_MODELto match (see below).Ollama runs a local server automatically after install. If it's not running, start it with:
ollama serve
By default the server talks to http://localhost:11434 and uses the
llama3.2 model. Override either with environment variables if needed:
# macOS/Linux
export OLLAMA_MODEL="mistral"
# Windows (PowerShell)
$env:OLLAMA_MODEL="mistral"list_tickets, get_ticket, and update_ticket_status don't need Ollama
at all — only classify_ticket does.
Related MCP server: Ticket Queue MCP Server
Evaluation
evaluate.py measures two things against the mock dataset:
Routing accuracy — how often
classify_ticket's predictedcategoryandprioritymatch the dataset's ground-truth labels (baked in bygenerate_data.py).LLM-as-judge — there's no ground truth for the quality of the drafted
suggested_response, so a second local model scores it on relevance, professionalism, and actionability (1-5 each).
# Quick run: 10 tickets, routing accuracy + judge scores
python evaluate.py --limit 10
# Use a different, larger model as judge to reduce self-judging bias
python evaluate.py --limit 10 --judge-model mistral
# Routing accuracy only, no judge step (faster)
python evaluate.py --limit 10 --no-judgeEach ticket costs 1-2 local LLM calls, so on a CPU-only laptop start with
--limit 5-10 before running the full 40-ticket dataset — otherwise it can
take a while (see Status for rough per-call timing). Full
per-ticket results are written to eval_results.json (git-ignored, since
it's a run artifact, not source).
Note on self-judging bias: if the same model both classifies and judges,
it tends to rate its own drafts generously. Passing --judge-model with a
different (ideally larger) model gives a more honest signal.
Web UI
On top of the MCP server, app.py wraps the same tool functions as a small
FastAPI REST API and serves a browser-based dashboard from static/ — so
the project looks and works like a real internal support tool, not just a
script.
python app.pyThen open http://localhost:8000. Filter tickets by status/category in
the left rail, click a case to open its detail panel, update its status, or
click Run AI triage to call classify_ticket (via Ollama) and see the
predicted category, priority, sentiment, and a copyable drafted response.
The dot next to the header shows whether Ollama is currently reachable.
This is a separate, optional layer — the MCP server and its tools work identically with or without the web UI running.
Deploying the Web UI
app.py + static/ is a self-contained FastAPI app (API + dashboard in
one), which makes it deployable as a single web service on platforms like
Render or Fly.io — no separate
frontend host needed.
Since a deployed server has no local Ollama to talk to, point it at a
hosted, OpenAI-compatible LLM API instead — Groq
has a free tier (no card required) and is the easiest drop-in, since
server.py's _call_llm() already branches between local Ollama and Groq
based on OLLAMA_URL (see .env.example).
Steps (Render):
Get a free API key at console.groq.com.
Push this repo to GitHub.
On Render: New → Web Service, connect the repo. If you keep
render.yamlin the repo root, Render will read the build/start commands and env vars from it automatically (Blueprint deploy) — you'll just need to paste in yourGROQ_API_KEYwhen prompted, since it's deliberately left out of the committed config.Otherwise set manually:
Build Command:
pip install -r requirements.txtStart Command:
python app.pyEnvironment variables:
OLLAMA_URL=https://api.groq.com/openai/v1/chat/completionsOLLAMA_MODEL=llama-3.1-8b-instantGROQ_API_KEY=<your key>
Once deployed, open the Render-provided URL — you should see the dashboard, and "Run AI triage" will call Groq instead of local Ollama.
The MCP server (server.py run standalone, or via Claude Desktop) isn't
something you deploy to a URL — it speaks MCP over stdio to a client, not
HTTP to a browser. Demo that part locally or via screen recording instead.
Project structure
support-triage-mcp/
├── .github/
│ └── workflows/
│ └── ci.yml # GitHub Actions: lint + pytest on every push/PR
├── app.py # FastAPI backend for the web UI (wraps the same tool functions)
├── static/ # Web UI frontend (HTML/CSS/JS, served by app.py)
├── server.py # MCP server + tool definitions
├── evaluate.py # routing-accuracy + LLM-as-judge evaluation harness
├── retrieval.py # TF-IDF similar-ticket retrieval (RAG-style)
├── data/
│ ├── tickets.json # mock ticket dataset
│ └── generate_data.py # regenerates tickets.json
├── tests/
│ └── test_server.py # smoke tests for the tool functions
├── requirements.txt
├── LICENSE
└── README.mdSetup
git clone <your-repo-url>
cd support-triage-mcp
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtRegenerate the mock dataset any time with:
python data/generate_data.pyRun the test suite:
pip install -r requirements-dev.txt
pytest tests/ -vLint (same check CI runs):
ruff check .Running the server standalone
python server.pyThis starts the MCP server over stdio, waiting for a client to connect.
Connecting to Claude Desktop
Add this to your Claude Desktop MCP config
(claude_desktop_config.json — Settings → Developer → Edit Config):
{
"mcpServers": {
"support-triage": {
"command": "python",
"args": ["/absolute/path/to/support-triage-mcp/server.py"]
}
}
}Restart Claude Desktop, then try prompts like:
"List all open support tickets"
"Show me ticket T-1021"
"Mark T-1021 as in_progress"
"Classify ticket T-1021 and draft a first response"
Available tools
Tool | Description |
| List tickets, optionally filtered by status ( |
| Get full details of one ticket by ID. |
| Update a ticket's status. |
| Category/priority/sentiment classification + a suggested first response, using a local open-source LLM (Ollama) and similar past tickets as reference context. |
Roadmap
Swap TF-IDF retrieval for real embeddings (a local embedding model, e.g. via
ollama pull nomic-embed-text)Swap the mock dataset for a real ticket source
Try larger local models (
llama3.1,mistral) and compare routing accuracy vs.llama3.2
Continuous Integration
Every push and PR to main runs .github/workflows/ci.yml, which lints
with ruff and runs the full pytest suite on
Python 3.11 and 3.12. No Ollama install is needed in CI — classify_ticket's
LLM call is mocked in tests/test_classify.py, so the suite runs fully
offline. You'll see a status badge/checkmark on each commit and PR once this
is pushed.
Notes on the MCP SDK version
This project uses mcp v2.x, where the server class was renamed from
FastMCP to MCPServer (mcp.server.mcpserver.MCPServer). The decorator
API (@mcp.tool()) and mcp.run() are unchanged from v1. If you're
following older MCP tutorials that import from mcp.server.fastmcp import FastMCP, either update the import as above or pin mcp<2.0.0.
This server cannot be deployed
Maintenance
Related MCP Connectors
Email inboxes and calendars for AI agents: send, receive, search, draft and schedule.
Email inboxes and calendars for AI agents: send, receive, search, draft and schedule.
Build and manage AI-native customer support agents from Claude or any MCP client.
Run AI customer support from your terminal: conversations, knowledge base, and chat widget.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceEnables ticket management and AI triage through Mistral-compatible models, with tools for creating, listing, retrieving, triaging, and updating support tickets.-
- FlicenseNot gradedqualityCmaintenanceEnables AI clients to access and manage an internal support ticket queue through MCP tools, resources, and prompts, including searching and viewing tickets, adding comments, closing tickets with confirmation, reading knowledge base articles, and viewing queue summaries over OAuth-secured Streamable HTTP.-
- FlicenseAqualityCmaintenanceEnables Claude to manage customers and support tickets through database-backed CRUD tools, contextual customer and knowledge resources, and a reusable ticket-triage prompt.13-
- FlicenseNot gradedqualityCmaintenanceExposes read-only knowledge base articles on returns, warranty and shipping policies alongside tools that search, retrieve and create real support tickets. This lets an LLM agent ground its answers in store policy without inventing information, and act on actual ticket data rather than simulated records.-