Skip to main content
Glama

CustSupport

An MCP server for a customer support workflow — monitoring, reporting, and resolving — built as a portfolio project. A local LLM (Ollama) generates a synthetic ticket dataset, which is validated, stored in BigQuery, and served to any MCP-compatible client (Claude Desktop, Claude Code) through a set of read-oriented monitoring/reporting tools and a resolving tool set that drafts suggestions for human review rather than acting autonomously.

Architecture

generate_batch.py  →  validator.py  →  load_to_bigquery.py  →  BigQuery
   (Ollama)          (QA / flagging)      (load job)              │
                                                                    ▼
                                                    mcp_server/server.py
                                                    (monitoring / reporting /
                                                     resolving tools)
                                                            │
                                                            ▼
                                            Claude Desktop / Claude Code
  • Data: synthetic support tickets (Zendesk-shaped schema — category, persona, priority, channel, subject, body, SLA hours) generated locally via Ollama (llama3.2), chosen over a real support-platform API to keep cost/friction low while controlling for specific edge cases (SLA breaches, ambiguous sentiment) that make the monitoring/reporting logic worth testing.

  • Generation: category/persona/priority/channel/scenario are sampled before generation (weighted, conditionally correlated — e.g. urgent tickets skew frustrated, technical/account issues skew higher priority than shipping/feature requests), then a parameterized prompt is built per combination. Persona is fully decoupled from category — any persona can occur with any category.

  • Validation: a QA pass built directly from failure patterns observed across real generation batches — full-caps "shouting" bodies (~30-40% of frustrated-persona tickets, a rate prompt tuning couldn't fully eliminate), leftover bracket placeholders, stale absolute dates, third-person voice drift, and category/ID mismatches (e.g. a feature request referencing an order number). Flagged tickets are separated out for review rather than silently dropped or silently kept.

  • Storage: BigQuery, loaded via a load job (not streaming insert) so rows are immediately eligible for the UPDATE used by the resolving tool set's status changes.

  • MCP server: exposes the tool set below over stdio, for use by Claude Desktop or Claude Code.

Related MCP server: zendesk-mcp

Tool set

Category

Tool

Read/Write

Monitoring

list_open_tickets, get_ticket, sla_breaches

Read

Reporting

category_breakdown, sla_risk_summary, daily_digest

Read

Resolving

draft_reply, suggest_escalation

Read (suggestions only)

Resolving

update_ticket_status

Write

Human-approval design: draft_reply and suggest_escalation never modify data — they return a suggestion for a human to review. update_ticket_status is the only tool that writes, and is intended to be called only after that review. This is a convention carried by tool descriptions and expected usage, not something the server can technically enforce — the MCP protocol gives a calling agent the tools, not a way to prove a human looked at the output first.

Project layout

src/custsupport/
├── schema.py                 # SyntheticTicket dataclass, category/persona/priority enums
├── config.py                  # env-based config (Ollama, BigQuery) — loads .env via python-dotenv
├── generator/
│   ├── prompts.py               # build_prompt() — tuned, parameterized, category/persona decoupled
│   ├── sampler.py                # sample_ticket_params() / sample_batch() — weighted, conditional sampling
│   ├── ollama_client.py           # Ollama /api/generate wrapper
│   ├── batch.py                    # wires sampler+prompts+ollama_client into SyntheticTicket objects
│   └── validator.py                 # QA pass — full-caps, placeholders, dates, voice, ID mismatches
├── storage/
│   └── bigquery_client.py    # dataset/table creation, insert/load, monitoring queries, status updates
└── mcp_server/
    ├── draft.py                # draft_reply's Ollama-backed prompt/generation
    └── server.py                 # MCP tool registration (monitoring/reporting/resolving)

scripts/
├── sanity_check_tickets.py   # manual prompt-tuning harness (exploratory, not a test)
├── generate_batch.py           # generate + validate a batch, write clean/flagged JSONL
└── load_to_bigquery.py           # load a generated JSONL batch into BigQuery

tests/
├── test_sampler.py              # sampler distribution checks, no external deps
├── test_build_prompt.py          # prompt cross-pairing checks, needs local Ollama
├── test_batch_generator.py        # parser + pipeline checks, Ollama mocked
├── test_validator.py               # validator checks against real historical failure tickets
└── test_mcp_server.py               # tool registration + pure-logic checks, BigQuery/Ollama mocked

Setup (fresh clone)

This repo excludes both the generated dataset (data/) and any environment-specific credentials — a fresh clone needs its own GCP project and its own generated tickets.

# 1. Install dependencies
uv sync
uv pip install -e .

# 2. Configure environment
cp .env.example .env
# edit .env: set BQ_PROJECT_ID to your own GCP project

# 3. GCP auth (local dev)
gcloud auth application-default login
gcloud auth application-default set-quota-project <your-project-id>

# 4. Ollama
ollama pull llama3.2

# 5. Generate and validate a batch of synthetic tickets
uv run python scripts/generate_batch.py --n 50 --seed 1

# 6. Load into BigQuery (creates dataset/table on first run)
uv run python scripts/load_to_bigquery.py --input data/tickets_batch.jsonl

# 7. Run the test suite
uv run python tests/test_sampler.py --n 2000
uv run python tests/test_batch_generator.py
uv run python tests/test_validator.py
uv run python tests/test_mcp_server.py

Registering the MCP server

Claude Desktop — add to claude_desktop_config.json:

{
  "mcpServers": {
    "custsupport": {
      "command": "uv",
      "args": ["run", "--directory", "<absolute path to this repo>", "python", "-m", "custsupport.mcp_server.server"]
    }
  }
}

Claude Code:

claude mcp add custsupport -- uv run --directory "<absolute path to this repo>" python -m custsupport.mcp_server.server

Ollama must be running locally for draft_reply to work once connected.

Status

Fully functional end-to-end, verified against live Ollama, a live BigQuery project, and the real MCP Python SDK (mcp 2.x — note the SDK renamed FastMCP to MCPServer in 2.0). Not yet verified: the full round trip through an actual Claude Desktop/Code session (the tool registration itself was tested via the SDK directly, not via a live client connection).

Possible next steps

  • search_similar_resolved_tickets — RAG over past resolutions. Not built yet since the generator has only ever produced status="open" tickets; would need a small resolved-ticket generation pass first (populating ground_truth_resolution).

  • Auto-regeneration of validator-flagged tickets rather than manual review.

License

MIT — see LICENSE.

Available Tools

9 tools
category_breakdownA

Aggregate ticket counts grouped by category, priority, and status — useful for seeing what's piling up in the queue. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior4/5

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

With no annotations provided, the description carries the burden of behavioral disclosure. It explicitly states 'Read-only,' which is a key behavioral trait. The word 'Aggregate' also implies a non-mutating operation. This covers the most critical behavior for an agent to know before invoking the tool.

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 concise sentence with a dash and a short 'Read-only' addition. It is front-loaded with the core purpose, and every word earns its place. There is no fluff or redundancy.

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?

The tool has an output schema, so the return format is covered by that. The description explains what the tool does (aggregate counts by the three dimensions) and that it is read-only. It does not mention any filters or time ranges, but with no parameters, that is likely inherent. The description is complete enough for a no-parameter aggregation tool.

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?

The tool has 0 parameters, so per rubric the baseline is 4. There is nothing to explain about parameters. The description correctly avoids inventing parameter details.

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's purpose: aggregate ticket counts grouped by category, priority, and status. This is a specific verb (aggregate) and resource (ticket counts) with clear grouping dimensions. It naturally distinguishes from sibling tools like list_open_tickets (which lists individual tickets) by emphasizing aggregation rather than listing.

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

Usage Guidelines4/5

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

The description provides a clear use case: 'useful for seeing what's piling up in the queue.' This gives the agent a sense of when to use it (to get a high-level view of backlog distribution). It does not explicitly mention when not to use it or point to alternatives, but given the distinct aggregation nature, the context is clear enough for an agent to infer appropriate usage.

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

daily_digestA

Generate a plain-text summary of the current ticket queue: total open tickets, SLA risk, and a breakdown by category/priority/status — the kind of summary you'd post to a team channel each morning. Read-only and deterministic (pure aggregation of BigQuery data, no LLM involved).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

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

With no annotations provided, the description carries the full behavioral burden and explicitly states 'Read-only and deterministic (pure aggregation of BigQuery data, no LLM involved).' This discloses side-effect profile, determinism, and computation source. It doesn't detail empty-result or error behavior, but the disclosure is strong for a zero-input aggregation tool.

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?

Two purposeful sentences: the first front-loads the deliverable and contents, the second adds behavioral guarantees. No filler or repetition of schema details.

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

Completeness5/5

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

For a zero-parameter read-only summary with an output schema available, the description fully covers what the tool does, what it includes, its output format, and its behavioral guarantees. An agent can select and invoke it correctly without additional context.

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?

The tool takes zero parameters, so parameter semantics are trivially satisfied; the rubric assigns baseline 4 for no-parameter tools. The description reinforces that the input is simply the current ticket queue.

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?

States a specific verb ('Generate') and resource ('plain-text summary of the current ticket queue'), enumerating contents: total open tickets, SLA risk, and category/priority/status breakdown. This clearly distinguishes it from siblings that only list tickets, report SLA breaches, or break down categories separately.

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

Usage Guidelines4/5

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

Gives a clear usage context: 'the kind of summary you'd post to a team channel each morning' implies routine consolidated snapshots rather than ad-hoc queries. It does not explicitly name when-not-to-use or alternatives, but the morning-summary framing is enough guidance for an agent.

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

draft_replyA

Generate a suggested reply to a ticket via a local LLM (Ollama). Read-only — this does NOT send anything or modify the ticket. A human should review the draft before using it; if approved, call update_ticket_status separately to record the outcome.

ParametersJSON Schema
NameRequiredDescriptionDefault
modelNo
ticket_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.1/5.0
Behavior4/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It explicitly states 'Read-only — this does NOT send anything or modify the ticket,' and notes the human-review requirement. This covers the key safety and workflow behaviors, though it does not mention potential limitations like model availability or output format.

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 three concise sentences, front-loaded with the primary purpose, followed by safety and workflow notes. Every sentence adds value with no redundancy.

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 the tool's simplicity (2 params, output schema present), the description covers the essential purpose, safety, and next step. However, it omits explanation of the model parameter and does not mention any preconditions (e.g., ticket must exist), leaving slight gaps that could affect correct invocation.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must compensate for parameter meanings. It implicitly references ticket_id via 'a ticket' but does not explain the optional 'model' parameter or its default behavior. The description adds minimal value beyond the schema for parameter semantics.

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's function: 'Generate a suggested reply to a ticket via a local LLM (Ollama).' It specifies a verb, resource, and method, and distinguishes itself from siblings like update_ticket_status by framing the reply as a draft that does not send anything.

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

Usage Guidelines4/5

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

The description gives clear workflow guidance: 'A human should review the draft before using it; if approved, call update_ticket_status separately to record the outcome.' This tells the agent when to use this tool (to create a draft) and points to the appropriate next step, though it does not explicitly state when not to use it.

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

get_ticketA

Get full detail on a single ticket by its ticket_id. Read-only. Returns an empty dict if the ticket_id doesn't exist.

ParametersJSON Schema
NameRequiredDescriptionDefault
ticket_idYes

TDQS

A4/5.0
Behavior4/5

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

With no annotations provided, the description carries the full behavioral burden and does solid work: it declares the operation read-only and explicitly discloses the not-found behavior ('Returns an empty dict if the ticket_id doesn't exist'). These are exactly the behaviors an agent needs to know for a simple retrieval tool.

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?

Three short sentences, every one earning its place: the core action, the safety trait, and the edge-case return behavior. The critical not-found behavior is front-loaded rather than buried.

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 1-parameter, no-nested-objects, no-output-schema tool, the description is nearly complete: it states the lookup key, the safety profile, and the empty-dict edge case. The only gap is that 'full detail' does not describe the success return shape, but given the tool's simplicity this is a minor omission.

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

Parameters3/5

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

Schema coverage is 0%, so the description must compensate; it confirms ticket_id is the lookup key ('Get full detail... by its ticket_id'), which reinforces the schema but adds only marginal meaning. It does not specify the expected format of ticket_id or where an agent might obtain a valid value (e.g., from list_open_tickets results).

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?

States a specific verb and resource — 'Get full detail on a single ticket by its ticket_id' — with the precise lookup key named. This is clearly a detail-retrieval tool, distinguishable from siblings like list_open_tickets (listing) and update_ticket_status (mutation).

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

Usage Guidelines3/5

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

The phrase 'single ticket by its ticket_id' implies this is the tool to use when the agent already has a specific ticket_id and needs the full ticket object, versus listing open tickets. However, no sibling is named and no explicit when-to-use/when-not-to-use guidance is given, leaving the routing largely to inference.

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

list_open_ticketsA

List open support tickets, optionally filtered by category, persona, or priority. Read-only. Returns ticket_id, created_at, category, persona, priority, subject, body, status, sla_hours for each match.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
personaNo
categoryNo
priorityNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior3/5

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

With no annotations provided, the description carries the full disclosure burden. It clearly states 'Read-only', which is an important behavioral fact, and enumerates the return fields. However, it does not mention ordering, the meaning of the limit, or how 'open' tickets are defined, leaving some behavioral gaps.

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?

Three sentences with every one bringing value: purpose, read-only flag, and returned fields list. It is front-loaded and contains no filler or redundant wording.

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?

The description covers the purpose, filters, read-only nature, and return fields. With an output schema present, it doesn't need to spell out return details. Minor gaps include the definition of 'open' and ordering behavior, but the tool is simple enough that this is adequately complete.

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

Parameters3/5

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

Schema description coverage is 0%, so the description must compensate. It explains that category, persona, and priority serve as filters, but it does not describe the limit parameter's semantics (only a default is visible in schema) or any allowed value constraints. This is partial compensation.

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 states a specific verb and resource: 'List open support tickets' and additionally names the optional filters and the fields returned. It can be clearly distinguished from siblings like get_ticket (single ticket) and the analytical tools.

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

Usage Guidelines3/5

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

The description implies usage when a caller needs open support tickets with optional filters, but it offers no explicit guidance about when to use a sibling tool instead (e.g., get_ticket for one ticket or sla_breaches for SLA analysis). There are no clear when-not conditions, making the usage guidance implied rather than explicit.

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

sla_breachesA

List all open tickets that have already exceeded their SLA window, ordered by how badly overdue they are (most overdue first). Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

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

No annotations are provided, so the description carries the burden. It explicitly labels the operation as read-only and discloses ordering behavior (most overdue first), which is useful beyond the name and schema. It does not mention pagination or result limits, but the operation is simple and well-scoped.

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?

A single, front-loaded sentence that conveys the resource, filtering condition, ordering, and safety profile without any filler. Every word earns its place.

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

Completeness5/5

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

For a zero-parameter, read-only listing tool with an output schema, the description is fully adequate. It tells the agent exactly what will be returned and in what order, leaving no critical gaps.

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?

The tool has zero parameters, so the baseline is 4. The schema is complete with an empty properties object, and there is no parameter ambiguity for the description to resolve.

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?

States a specific verb ('List'), a specific resource (open tickets exceeding SLA), and a clear criterion (already exceeded SLA window), plus ordering. This clearly distinguishes it from siblings like sla_risk_summary and list_open_tickets.

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

Usage Guidelines4/5

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

The description clearly implies when to use this tool: when you need tickets that have already breached SLA, not just those at risk. It does not explicitly name alternatives, but the context is clear and no exclusions are needed.

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

sla_risk_summaryA

Summarize SLA risk across the open queue: how many tickets are already breached vs. approaching their SLA deadline (over 75% of their SLA window elapsed but not yet breached). Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.3/5.0
Behavior4/5

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

No annotations are provided, so the description carries the full behavioral burden. It explicitly states 'Read-only' and clarifies that the tool returns counts of breached vs. approaching tickets, making side effects and the aggregate nature clear. It does not specify the exact return format, but that is a minor gap for a zero-parameter summary tool.

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?

Two sentences contain the full purpose, the metric definitions, and the read-only safety signal with no filler. The core action is front-loaded before the detailed threshold explanation.

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

Completeness5/5

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

For a no-argument tool with no output schema, the description fully equips an agent to invoke it correctly: it defines scope ('open queue'), the categories, the SLA threshold, and safety. 'How many tickets' also communicates that the result is a summary rather than a ticket list.

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?

The tool has zero parameters, so the empty input schema is already complete. The description adds meaningful context about what the summary covers, meeting the baseline for no-parameter tools without needing further elaboration.

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 uses a specific verb and resource: 'Summarize SLA risk across the open queue.' It also defines the two key categories (already breached vs. approaching at over 75% of the SLA window elapsed), which makes the tool's purpose unmistakable and distinguishes it from sibling list-focused tools like sla_breaches or list_open_tickets.

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

Usage Guidelines3/5

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

The description implies when to use the tool: when an aggregate SLA risk view over the open queue is needed. However, it does not explicitly name alternatives or state when not to use it, so the agent must infer routing from sibling names.

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

suggest_escalationA

Heuristic escalation recommendation for a ticket, based on SLA breach status and priority. Read-only — recommends whether a human should escalate; does not escalate anything itself.

ParametersJSON Schema
NameRequiredDescriptionDefault
ticket_idYes

TDQS

A4.1/5.0
Behavior4/5

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

With no annotations, the description carries the full behavioral burden Diamonds. It explicitly states the operation is read-only and advisory, and that no escalation action is performed. It does not describe the output shape or error behavior, but for a simple heuristic recommendation tool the key side-effect transparency is present.

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?

Two sentences carry the full purpose, basis, and read-only nature of the tool with no wasted words. The core action is front-loaded, and the clarifying side-effect statement is placed immediately after.

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 single-parameter tool with no annotations and no output schema, the description is mostly complete. It explains what the tool does, what it is based on, and that it is read-only. However, it does not specify the exact return value format, which would be helpful when no output schema exists.

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

Parameters2/5

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

Schema description coverage is 0%, and the description only refers to 'a ticket' without explaining the ticket_id format, source, or validity requirements. The parameter name and schema title are self-explanatory, but the description adds no meaningful parameter guidance beyond that.

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 uses a specific verb ('recommends') and clearly names the resource (escalation for a ticket) and the decision criteria (SLA breach status and priority). It also distinguishes itself from action-oriented siblings by explicitly stating it does not escalate anything itself.

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

Usage Guidelines4/5

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

The description gives clear context: use this when you need an escalation recommendation for a specific ticket based on SLA and priority. The explicit 'read-only' note and 'does not escalate anything itself' imply it is not for performing escalations, but no alternative tool is named.

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

update_ticket_statusA

WRITE operation — the only tool in this server that modifies data. Updates a ticket's status ('open', 'pending', or 'resolved') in BigQuery, optionally attaching a note. Intended to be called only after a human has reviewed and approved a draft_reply or suggest_escalation result — never autonomously.

ParametersJSON Schema
NameRequiredDescriptionDefault
noteNo
ticket_idYes
new_statusYes

TDQS

A4.6/5.0
Behavior4/5

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

With no annotations provided, the description carries the full burden. It clearly discloses the mutating nature ('WRITE operation') and the data target (BigQuery), plus the human-approval requirement. However, it does not mention potential side effects (e.g., whether the status update is irreversible or whether prior status is overwritten), which would strengthen transparency further.

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 two sentences, front-loaded with the most important fact ('WRITE operation'), and contains zero filler. Every word contributes value, making it highly efficient and scannable for an agent.

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 the absence of an output schema, the description does not specify what the tool returns after a successful update, which is a minor gap. However, it covers the mutation, the target, the status values, and the usage constraint, which is sufficient for an agent to invoke it correctly. The missing return semantics is not critical for a write operation.

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 0%, so the description must compensate. It provides the allowed values for new_status and notes that the note is optional, which are not in the schema. It does not elaborate on ticket_id beyond the schema's type string, but the description adds meaningful context for two of the three parameters.

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 states a specific verb ('Updates') with a precise resource (ticket status) and enumerates the allowed values ('open', 'pending', 'resolved'). It also explicitly distinguishes itself as the only write operation among the siblings, so an agent can clearly identify its unique role.

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?

It gives explicit when-to-use guidance: only after a human has reviewed and approved a draft_reply or suggest_escalation result, and explicitly prohibits autonomous calls. This fully satisfies the dimension and leaves no ambiguity about the appropriate trigger context.

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.

  1. 9 tool updatesv0.1.0
    • First observedcategory_breakdown
    • First observeddaily_digest
    • First observeddraft_reply
    • First observedget_ticket
    • First observedlist_open_tickets
    • First observedsla_breaches
    • First observedsla_risk_summary
    • First observedsuggest_escalation
    • First observedupdate_ticket_status

TDQS

A4.2/5.0

Scored across 9 tools

Disambiguation4/5

Tools are largely distinct, but aggregation tools like daily_digest, category_breakdown, and sla_risk_summary overlap in the data they summarize, which could lead to misselection. Descriptions clarify their differences, but the boundary between daily_digest and category_breakdown is subtle.

Naming Consistency4/5

Names follow snake_case and are generally clear, but mix verb-first (list_open_tickets, get_ticket) with noun-first patterns (sla_breaches, category_breakdown). Despite the mix, the naming is predictable and readable, with no camelCase or chaotic variations.

Tool Count5/5

9 tools is well within the ideal 3-15 range for a focused domain. Each tool covers a distinct part of the support workflow—listing, detail, aggregation, SLA monitoring, draft replies, escalation, and status updates—without redundancy or bloat.

Completeness4/5

The surface covers the main support lifecycle: read (list, get), aggregate (breakdowns, SLA risk), assist (draft reply, escalation), and write (update status). Minor gaps exist, such as no tool to create or assign tickets, but these may be handled externally. The core workflow is well supported with no dead ends.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Enables Zendesk support workflows through tools for semantic ticket search, customer context retrieval, solution version assessment, and daily work summaries.
    4
    28 npm
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables natural-language Q&A over customer support ticket data. Provides tools for schema inspection, SQL-based ticket counts and grouping, and full-text search for customer wording without requiring API keys.
    -
  • F
    license
    A
    quality
    C
    maintenance
    Enables Claude to manage customers and support tickets through database-backed CRUD tools, contextual customer and knowledge resources, and a reusable ticket-triage prompt.
    13
    -