Skip to main content
Glama
ticket-triage-mcp

ticket-triage-mcp

AI-агент триажа тикетов — LangGraph + MCP

CI

Производственный рабочий процесс поддержки, который классифицирует неструктурированные запросы, извлекает доказательства из PDF-вложений, обращается к двум внутренним системам через MCP, составляет обоснованный ответ и направляет неоднозначные случаи человеку, а не угадывает.

Таблица оценки

Этап

Результат

Точность классификации

100% (20/20)

F1 извлечения полей

100%

Проверки черновика по политикам

100%

Заведомо неразрешимые случаи эскалированы

100% (5/5)

Причины эскалации по каждому случаю

100% (5/5)

Доля ложных эскалаций

0% (0/15)

Доля ошибок выполнения

0%

Офлайн-задержка

4.6 мс p50 / 6.7 мс p95

Это воспроизводимые результаты на зафиксированном синтетическом корпусе, измеренные на локальной машине разработки под Windows. Задержка зависит от оборудования; оценщик сообщает результат по каждому случаю в artifacts/scorecard.json. Пять сложных случаев покрывают отсутствие доказательств, конфликтующие идентификаторы, нечитаемое вложение, неоднозначный запрос и запись, отсутствующую во внутренней системе. Артефакт также фиксирует время генерации, хэш корпуса, версию Python, идентификатор коммита и транспорт инструментов, чтобы устаревшие результаты были заметны.

Архитектура системы: письмо и PDF поступают в рабочий процесс LangGraph, две MCP-системы предоставляют доказательства, а шлюз уверенности направляет либо к черновику, либо в очередь для человека.

Related MCP server: reach-dispute-mcp

Зачем существует этот проект

Большинство демо агентов показывают только счастливый путь. Этот делает воздержание от ответа тестируемым поведением. Агент может вернуть один из двух ограниченных результатов:

  • drafted — необходимые идентификаторы извлечены, обе проверки MCP только на чтение выполнены, и предоставленные ссылки проверены.

  • escalated — уверенность или доказательства не прошли политику, поэтому агент выдаёт необязывающий ответ-ожидание, очередь для человека, недостающие доказательства и проверяемую причину.

Это решение не спрятано в промпте. Это явное условное ребро в конечном автомате LangGraph и метрика в CI.

Что он делает

Email + PDF
    │
    ▼
classify ──► extract ──► intake safety gate
                              │
                    unsafe ───┴─── safe
                       │              │
                       ▼              ▼
                  human queue    MCP tool 1: customer account
                                      │
                                 MCP tool 2: billing / incident
                                      │
                                post-tool safety gate
                                  │              │
                             unverified       verified
                                  │              │
                                  ▼              ▼
                             human queue   grounded draft

Два MCP-инструмента намеренно узкие и только на чтение:

  1. lookup_customer_account выполняет точное совпадение по аккаунту/электронной почте.

  2. lookup_billing_or_incident проверяет биллинг, инцидент обслуживания или ограниченный контекст поддержки.

Граф всегда использует один транспортно-нейтральный контракт MCP-инструмента. Офлайн-оценка использует быстрый внутрипроцессный адаптер; Docker Compose запускает портфельный UI против постоянного реального MCP-сервера JSON-RPC-over-stdio. Оба транспорта покрыты интеграционными тестами, поэтому оркестрация никогда не зависит от выбора развёртывания.

Запуск локально

Предварительные требования: Python 3.11–3.13 и uv.

git clone https://github.com/Mohemed-Amine-Chalhy/ai-ticket-triage.git
cd ai-ticket-triage
uv sync --extra dev --locked
uv run uvicorn ai_ticket_triage.web:app --reload

Откройте http://127.0.0.1:8000. Веб-UI включает все 20 размеченных примеров, загрузчик PDF, трассировку графа, извлечённые поля, доказательства вызовов MCP, итоговое решение и таблицу оценки.

Команда выше использует быстрый внутрипроцессный адаптер. Чтобы запустить именно тот UI, что показан в MCP-демо, запустите зафиксированный контейнер; Compose по умолчанию включает постоянный stdio-сервер:

docker compose up --build

Перегенерируйте все четыре портфельных доказательных изображения из текущей таблицы оценки и реального подробного тестового запуска:

make proof

API-ключ не требуется. Все имена, адреса электронной почты, аккаунты, счета, услуги и инциденты вымышлены; письма используют зарезервированный домен example.test.

CLI-демо

Запустите разрешимый фикстур:

uv run ticket-triage triage --case billing_duplicate_charge

Запустите случай с ошибкой и проверьте передачу человеку:

uv run ticket-triage triage --case failure_unreadable_attachment

Запустите реальный PDF:

uv run ticket-triage triage \
  --text "I was charged twice; details are attached." \
  --pdf data/sample_attachments/duplicate-charge.pdf

Проверьте реальную границу stdio MCP:

uv run ticket-triage triage \
  --case billing_duplicate_charge \
  --transport stdio

Воспроизведение таблицы оценки

uv run ticket-triage-eval \
  --output artifacts/scorecard.json \
  --markdown-output artifacts/scorecard.md \
  --fail-on-runtime-error \
  --enforce-portfolio-targets

Оценщик оценивает каждый этап независимо: точное совпадение категории, микро-F1 на уровне полей, декларативные проверки черновика, семантическую обоснованность причины передачи, точность/полноту эскалации, ложные эскалации, ошибки выполнения и задержку p50/p95/max. См. Методология оценки.

Использование MCP-сервера независимо

Запустите встроенный сервер официального SDK через stdio:

uv run ticket-triage-mcp

Пример конфигурации для локального stdio MCP-хоста:

{
  "mcpServers": {
    "ticket-triage-tools": {
      "command": "uv",
      "args": [
        "--directory",
        "/absolute/path/to/ai-ticket-triage",
        "run",
        "ticket-triage-mcp"
      ]
    }
  }
}

Это транспортно-нейтральная граница инструментов: другой совместимый агент или настольный хост может использовать те же два контракта без импорта приложения LangGraph. Для удалённых хостов разместите сервер за аутентифицированным развёртыванием Streamable HTTP; портфельное демо намеренно предоставляет только локальные stdio и внутрипроцессный транспорты.

Инженерные решения

Аспект

Реализация

Оркестрация

Скомпилированный StateGraph с типизированным состоянием и явными условными рёбрами

Безопасность

Два шлюза политик; низкая уверенность, конфликты, отсутствие доказательств, нечитаемые файлы, ошибки инструментов и промахи — всё эскалируется

Документы

Извлечение через pypdf, строгая валидация загрузки PDF, ограничения размера и предупреждения об извлечении

Граница инструментов

Официальный MCP Python SDK, ровно два инструмента только на чтение, нормализованные конверты ошибок, таймауты

Контракты

Модели Pydantic с запрещёнными дополнительными полями и JSON-безопасными публичными результатами

Оценка

20 версионированных JSON-меток, метрики по этапам, диагностика случаев, перехват ошибок выполнения

API

FastAPI, сгенерированная документация OpenAPI, ограничения загрузки, ID запросов, безопасные ответы об ошибках, заголовки безопасности

Эксплуатация

Зафиксированные зависимости, Docker health check, структурированные логи, CI-шлюзы lint/type/test/coverage

Конфиденциальность

Только синтетические фикстуры; сырые байты PDF исключены из сериализации моделей

Детерминированность по замыслу

Классификатор, экстрактор и составитель черновика по умолчанию детерминированы. Это делает регрессии безопасности воспроизводимыми, сохраняет публичное демо без учётных данных и отделяет качество рабочего процесса от вариативности моделей. Размещённая модель может заменить эти узлы за теми же типизированными контрактами; в реальном развёртывании её кандидатные выходы всё равно должны проходить через те же шлюзы доказательств и инструментов. Этот репозиторий не утверждает, что синтетический бенчмарк из 20 случаев предсказывает качество на живых данных.

Карта репозитория

src/ai_ticket_triage/
├── agent.py          # LangGraph state machine and tool orchestration
├── classifier.py     # deterministic category scoring with evidence
├── extractor.py      # PDF/text extraction and conflict detection
├── confidence.py     # bounded-failure policy gates
├── drafting.py       # grounded replies and safe holding responses
├── mcp_server.py     # official MCP server; exactly two tools
├── mcp_client.py     # in-process and real stdio MCP gateways
├── internal_api.py   # mock read-only service adapters
├── evaluation.py     # corpus runner and scorecard metrics
├── web.py            # FastAPI application
└── static/           # responsive portfolio UI
data/cases/           # 20 synthetic labelled fixtures
tests/                # unit, API, workflow, evaluator, and MCP integration tests
artifacts/            # committed scorecard and proof outputs
assets/               # portfolio-ready architecture and result images
docs/                 # architecture, evaluation, security, runbook, portfolio copy

Команды контроля качества

uv run ruff check .
uv run ruff format --check .
uv run mypy src
uv run pytest --cov=ai_ticket_triage --cov-report=term-missing
uv run ticket-triage-eval --fail-on-runtime-error --enforce-portfolio-targets
docker compose up --build

Документация

Известные ограничения

  • Только текстовые PDF; отсканированные документы требуют OCR и конвейер проверки на вредоносное ПО.

  • Синтетические внутренние системы с точным совпадением, а не живая CRM или биллинговая платформа.

  • Англоязычные фикстуры и таксономия из четырёх классов.

  • Нет постоянной очереди, аутентификации, ограничения частоты запросов или распределённой трассировки в этом локальном демо.

  • Детерминированная языковая логика — это базовый уровень надёжности, а не замена оценки на репрезентативном, проверенном на конфиденциальность производственном наборе данных.

Эти упущения — намеренные границы проекта выходного дня. Интерфейсы изолируют каждую отсутствующую производственную задачу, чтобы её можно было добавить без переписывания графа.

Лицензия

MIT

Available Tools

2 tools
lookup_billing_or_incidentC

Read-only billing or service-incident lookup over synthetic data. Also returns bounded workflow guidance for account/other requests.

NameRequiredDescriptionDefault
productNo
categoryYes
order_idNo
ticket_idNo
account_idNo
error_codeNo
invoice_idNo
service_idNo
incident_idNo
account_numberNo
invoice_numberNo

Output Schema

NameRequiredDescription

No output parameters

TDQS

C2.7/5.0
Behavior2/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 declares 'Read-only' and 'over synthetic data', which is useful, but it does not explain error handling, limits, what 'bounded workflow guidance' means, or how the output varies with input combinations. The behavioral description is minimal and undetailed.

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, concise sentence that front-loads the core purpose ('Read-only billing or service-incident lookup') and then adds the supplementary workflow guidance. It is well-structured and avoids unnecessary verbosity, though it could be more detailed without losing conciseness.

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

Completeness2/5

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

Given the complexity of the schema (11 optional parameters, only 1 required) and the absence of annotations and parameter descriptions, the description is heavily underspecified. It does not explain how to select parameters based on the category, what 'bounded workflow guidance' entails, or what the output schema contains. An agent would face significant ambiguity in correctly forming a request.

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 missing parameter documentation. It does not explain the meaning or usage of any of the 11 parameters, nor does it clarify which parameters are relevant for 'billing' vs 'service-incident' or how the 'category' field drives the lookup. The parameter names are self-explanatory, but the description adds no additional semantics.

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

Purpose4/5

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

The description states a clear verb ('lookup') and resource ('billing or service-incident'), and also mentions additional workflow guidance. It implicitly distinguishes from the sibling `lookup_customer_account` by domain, though without naming it explicitly. The purpose is specific and understandable.

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?

The description does not provide any explicit guidance on when to use this tool versus alternatives, nor does it mention exclusions or conditions. The phrase 'for account/other requests' is vague and does not clarify selection criteria. No alternatives are referenced.

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

lookup_customer_accountC

Read-only exact lookup in the synthetic customer account system. Use returned misses or mismatches as escalation evidence.

NameRequiredDescriptionDefault
emailNo
ticket_idNo
account_idNo
account_numberNo

Output Schema

NameRequiredDescription

No output parameters

TDQS

C2.9/5.0
Behavior3/5

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

With no annotations, the description must carry the full burden. It discloses the read-only nature and that it returns misses or mismatches, which is useful. However, it does not explain how multiple parameters combine, whether authentication is needed, or any other behavioral details beyond these basics.

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 concise sentences with the key fact 'Read-only exact lookup' front-loaded. Every clause earns its place, and there is no redundancy or filler.

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

Completeness2/5

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

For a tool with 4 optional parameters, zero required, and no parameter documentation, the description is inadequate. It does not explain how to construct a valid lookup, what happens if multiple params are provided, or what escalation evidence looks like. The output schema exists but the description offers no context on call semantics.

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

Parameters1/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 the lack of parameter documentation. It does not mention email, ticket_id, account_id, or account_number at all, nor does it explain whether at least one is required, how they interplay, or which is preferred. The agent has no guidance on parameter usage.

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

Purpose4/5

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

The description states a clear verb and resource ('Read-only exact lookup in the synthetic customer account system'), which distinguishes it from the sibling tool by resource. However, it doesn't explicitly name the sibling, so differentiation is implied rather than explicit.

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?

The description gives no explicit guidance on when to use this tool versus the sibling lookup_billing_or_incident. The only usage-related hint is 'Use returned misses or mismatches as escalation evidence,' which concerns result handling, not tool selection. It lacks any exclusions or alternatives.

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. 2 tool updatesv1.0.0
    • First observedlookup_billing_or_incident
    • First observedlookup_customer_account

TDQS

B3/5.0

Scored across 2 tools

Disambiguation4/5

The two tools target distinct data domains (customer accounts vs. billing/incidents), and their descriptions clearly differentiate them. However, since both are lookups and the second tool's name is broader, there is slight potential for an agent to confuse them when deciding which to use.

Naming Consistency5/5

Both tools follow the same 'lookup_*' verb-noun pattern, with the resource type clearly indicated. This is perfectly consistent and predictable.

Tool Count3/5

With only two tools, the server feels thin for a 'triage' purpose, but the scope might be intentionally limited to read-only lookups. This is borderline on the low end of the range.

Completeness2/5

The tool surface consists solely of lookups and does not include any actions to actually triage or resolve tickets (e.g., update status, assign, escalate). Even if the second tool returns guidance, the lack of write or workflow-management tools leaves significant gaps for a triage-focused server.

Maintenance

ActivityStale
ResponsivenessNo recent community issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    Provides read-only MCP tools to diagnose customer billing disputes by analyzing billing records, identifying contradictions, citing evidence, and scoring confidence to auto-resolve or escalate.
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    Provides MCP tools that let an agent retrieve customer account, product usage, interaction, and support summaries, and create follow-up tasks after user approval.
    -
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables IT helpdesk operations such as retrieving user and device information, checking device status, and creating, retrieving, and updating support tickets through MCP tools.
    -