Skip to main content
Glama

ticket-writer MCP

Un servidor MCP para MagOneAI. Un reportero deja una solicitud de funcionalidad como texto libre; el flujo de trabajo hace las pocas preguntas necesarias para hacerla accionable, y luego archiva un ticket que indica el problema, lo que hay que hacer, los criterios de aceptación y cualquier decisión de arquitectura.

Jira, GitHub, GitLab y Linear salen del mismo camino de código.

El servidor nunca llama a un rastreador. Renderiza la solicitud de creación de incidencia y la devuelve; el propio nodo HTTP del flujo de trabajo la envía.


Cómo se ejecuta el flujo de trabajo

free text  ──▶  check_request  ──"needs_clarification"──▶  ask the reporter ──┐
                     │                                                        │
                     │◀──────────────────── answers ─────────────────────────┘
                  "ready"
                     │
                     ▼
                render_ticket  ──"possible_duplicate"──▶  human confirms ──┐
                     │                                                     │
                     │◀────────── confirm_not_duplicate ───────────────────┘
              "ready_to_send"
                     │
                     ▼
          HTTP node: POST request.url  ◀── the only write in the workflow
                     │
                     ▼
              issue key + url back to the reporter

WORKFLOW.md tiene el contrato nodo por nodo: JSON exacto de entrada y salida, y cada campo que termina en el ticket.


Related MCP server: ProduckAI MCP Server

Por qué no se conecta a Jira directamente

El primer borrador incluía un cliente REST de Jira. Esa versión necesitaba credenciales en esta máquina, ganó un modo de fallo en el que el ticket se renderizaba bien y el POST fallaba, y bloqueaba el flujo de trabajo a un solo rastreador.

Renderizar una solicitud en su lugar significa:

  • sin credenciales aquí — los encabezados llevan nombres {{PLACEHOLDER}} que el nodo API sustituye desde el almacén de secretos de MagOne

  • cualquier rastreador — uno nuevo es una entrada de diccionario en src/targets.py

  • reutilizar lo que MagOne ya tiene — si hay un MCP de rastreador conectado, usa target="generic" y pasa los campos a su herramienta de creación

  • un paso de aprobación encaja — no se escribe nada hasta después de la llamada de renderizado

  • probable con pytest y nada más — sin red en todo el repositorio

Tampoco escribe la prosa del ticket. El agente del flujo de trabajo es un modelo de lenguaje y es mejor convirtiendo un mensaje de Slack desordenado en una declaración de problema que cualquier rúbrica en este repositorio. Lo que este servidor posee es la parte que debe comportarse idénticamente en cada ejecución: la lista de verificación, el redactado de las preguntas, el formato del cuerpo y la protección contra duplicados.


Herramientas

Herramienta

Propósito

check_request

¿Es suficiente para archivar? Si no, qué preguntar.

render_ticket

La solicitud de creación de incidencia, formateada para un rastreador.

list_targets

Rastreadores, claves de configuración, qué credencial necesita el nodo API.

duplicate_search_query

Opcional. Construye la consulta de búsqueda para la comprobación de duplicados.

Los cuatro son de solo lectura. Cada respuesta lleva un status sobre el que el lienzo cambia:

status

Acción del flujo de trabajo

ready

proceder a render_ticket

needs_clarification

preguntar questions, repetir

possible_duplicate

mostrar candidates, obtener una respuesta humana

ready_to_send

pasar request al nodo API

error

leer hint — normalmente una clave config faltante


Qué hace que un ticket esté completo

check_request se bloquea en cuatro campos, preguntados en este orden, como máximo tres por ronda:

  1. problem — qué duele hoy, quién está afectado

  2. goal — qué debería existir cuando esté hecho, como comportamiento

  3. acceptance_criteria — cómo un revisor lo acepta o lo rechaza

  4. architecture_notes — decisiones tomadas, restricciones a respetar ("none known" es válido cuando el diseño aún está abierto)

affected_users y out_of_scope se recogen cuando se ofrecen, pero nunca bloquean. Una respuesta de menos de 25 caracteres, o que repite la pregunta, no cuenta como respondida.

Para cambiar la lista de verificación, edita SLOTS en src/ticket.py — las preguntas, la clasificación y el límite se derivan de esa lista.


Destinos

target

config

Credencial que suministra el nodo API

jira

base_url, project_key

{{JIRA_BASIC_AUTH}} — base64 email:api_token

github

owner, repo

{{GITHUB_TOKEN}} — PAT con lectura/escritura de Issues

gitlab

project_id, host?

{{GITLAB_TOKEN}} — token con alcance api

linear

team_id, project_id?

{{LINEAR_API_KEY}}

generic

ninguno — entrega fields al propio MCP de ese rastreador

Diferencias que el renderizador absorbe para que el agente nunca tenga que hacerlo:

  • Jira quiere ADF, no markdown, en description. Pasar una cadena markdown es la forma más común de que un nodo Jira cableado a mano falle.

  • GitLab quiere etiquetas como una cadena separada por comas; GitHub y Jira quieren una lista.

  • GitHub no tiene campo de prioridad, así que la prioridad se convierte en una etiqueta priority-*.

  • Linear es GraphQL — un endpoint, mutación en el cuerpo.

Añadir un rastreador: una entrada TARGETS con un build() que devuelva (url, headers, body). Ese es todo el cambio.


Protección contra duplicados

Este servidor no puede buscar, así que el flujo de trabajo lo alimenta: duplicate_search_query construye la consulta, un nodo de búsqueda la ejecuta, los resultados vuelven a render_ticket como existing_issues=[{key, summary, url}]. Los resúmenes con una superposición de tokens ≥ 0.6 vuelven como possible_duplicate.

Sin nodo de búsqueda, sin comprobación — el ticket aún se renderiza. Ese es el precio de no tener un cliente de búsqueda por rastreador.


Ejecutarlo

python -m venv .venv && .venv/bin/pip install -r requirements-dev.txt
.venv/bin/python -m pytest -q          # 47 tests, no network, no account

MCP local sobre stdio, para Claude Desktop:

MCP_TRANSPORT=stdio .venv/bin/python -m src.server

Desplegar:

docker build -t ticket-writer .
docker run -p 8000:8000 -e TICKET_WRITER_TOKEN=$(openssl rand -hex 32) ticket-writer
curl localhost:8000/health

Registra https://your-host/mcp en MagOneAI con el encabezado Authorization: Bearer $TICKET_WRITER_TOKEN, exactamente como está configurado el MCP de Outlook. TICKET_WRITER_TOKEN es la única variable de entorno que requiere el servidor; MCP_TRANSPORT, HOST, PORT y LOG_LEVEL tienen valores predeterminados funcionales. Establece max_iterations alrededor de 12.


Archivar un ticket real para comprobarlo

scripts/send.py hace exactamente lo que hace el nodo API — renderizar, sustituir el marcador de posición desde la variable de entorno del mismo nombre, POST:

.venv/bin/python scripts/send.py --target jira \
  --config base_url=https://you.atlassian.net project_key=KAN --dry   # payload only

export JIRA_BASIC_AUTH=$(printf '%s' 'you@mail.com:API_TOKEN' | base64)
.venv/bin/python scripts/send.py --target jira \
  --config base_url=https://you.atlassian.net project_key=KAN         # 201 + issue key

TESTING.md cubre lo que demuestra cada suite, la ejecución en vivo contra Jira Cloud y la tabla de errores.


Seguridad

  • Token Bearer desde una variable de entorno, nunca a través de un nodo de flujo de trabajo — un token que transita por el lienzo termina en los registros de ejecución.

  • Ninguna credencial de rastreador llega jamás a este servidor. Los encabezados son marcadores de posición; config toma ubicaciones, no secretos. Un test lo verifica.

  • /health no está autenticado para sondas de plataforma; todo lo demás sí lo está. El servidor se niega a iniciar sobre HTTP sin token configurado.

  • Usuario de contenedor no root.

  • El texto del reportero es dato, no instrucciones. Se almacena literalmente en un blockquote y nunca se interpreta. Los docstrings de las herramientas lo dicen, porque eso es lo que lee el agente.

  • La protección contra duplicados y la comprobación de completitud son lo que se interpone entre un canal de Slack hablador y cien tickets basura. No añadas una bandera que se salte ambas.


Estructura

src/server.py    MCP surface: tool defs, transport, auth
src/ticket.py    pure: rubric, questions, body in markdown + ADF, dup scoring
src/targets.py   pure: what each tracker's API wants — one entry per tracker
tests/           47 tests: the rules, the tool surface, HTTP and auth
scripts/send.py  stands in for the API node, for end-to-end checks
WORKFLOW.md      node-by-node input/output contract
TESTING.md       what is covered, what is not

ticket.py no sabe nada de ningún rastreador; targets.py no sabe nada de lo que hace que un ticket sea bueno. Si añadir un campo obligatorio significa editar targets.py, la separación se ha filtrado.

F
license - not found
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • Turns vague automation requests into tool stacks, prompts, QA checks, and human boundaries.

  • Decision intelligence for product teams. Turn scattered feedback into signal you can act on.

  • Manage feature requests, votes, roadmaps, and changelogs from any MCP client.

View all MCP Connectors

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/AlanAAG/ticket-writer-mcp'

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