servicenow-mcp-agent
servicenow-mcp-agent
Un servidor MCP que expone herramientas ITSM de estilo ServiceNow a un agente Claude, además de un harness de evaluación que mide si el agente realmente las usa correctamente.
Lo interesante no es que el agente funcione. Es que el repositorio te dice qué tan bien funciona, en 24 tareas calificadas, con tres métricas: precisión de selección de herramientas, tasa de finalización de tareas y latencia por llamada.
┌──────────────┐ Messages API ┌───────────────┐ MCP (stdio/HTTP) ┌──────────────────┐
│ Claude │◄─────tools────────│ ITSM agent │◄────tools/call───────│ MCP server │
│ (Sonnet 5) │─────tool_use─────►│ + tracing │─────tools/list──────►│ 14 ITSM tools │
└──────────────┘ └───────┬───────┘ └────────┬─────────┘
│ │
┌───────▼────────┐ ┌─────────▼──────────┐
│ eval harness │ │ backend interface │
│ 24 graded tasks│ ├────────────────────┤
│ metrics/report │ │ mock │ ServiceNow │
└────────────────┘ │ store │ Table API │
└────────────────────┘Inicio rápido
git clone https://github.com/your-username/servicenow-mcp-agent
cd servicenow-mcp-agent
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest # 105 tests, no API key needed
export ANTHROPIC_API_KEY=sk-ant-...
snow-agent --list-tools
snow-agent -v "The payment service is down. What's the likely root cause?"
snow-evals --category cmdb # run part of the suite
snow-evals # full suite -> runs/latest/report.{md,html,json}No se requiere una instancia de ServiceNow. El backend predeterminado es un fixture determinista en memoria (16 incidentes, 8 artículos de KB, 13 CIs con un grafo de dependencias real, 10 usuarios). Para apuntar a una instancia gratuita de ServiceNow Personal Developer en su lugar, consulte docs/SERVICENOW_SETUP.md.
Related MCP server: snow-mcp
Las 14 herramientas
Herramienta | Propósito |
| Descubrimiento principal; filtros con nombre o una consulta codificada sin procesar |
| Un registro completo, incluidas notas de trabajo y comentarios |
| Registrar un nuevo incidente (referencias validadas, prioridad derivada) |
| Cambios de campo y notas de trabajo internas |
| Comentario visible para el cliente |
| La única vía a Resuelto; requiere código de cierre + notas |
| Búsqueda difusa en el historial — "¿ha pasado esto antes?" |
| Conteos agrupados sin recuperar cada registro |
| Búsqueda en KB y luego texto completo |
| Encontrar elementos de configuración; un CI más sus incidentes abiertos |
| Grafo de dependencias: causas aguas arriba, radio de explosión aguas abajo |
| Resolver nombres informales, verificar estado VIP |
Varios pares son vecinos deliberadamente cercanos (update_incident vs add_incident_comment,
search_incidents vs find_similar_incidents, get_ci vs get_ci_relationships). Distinguirlos
es exactamente lo que mide la precisión de selección de herramientas, y es donde falla una superficie de herramientas ingenua.
Evaluaciones
snow-evals # full suite
snow-evals --tasks resolve-vpn-with-kb # one task
snow-evals --category cmdb safety --concurrency 4
snow-evals --prompt minimal --out runs/minimal # prompt ablation
snow-evals --fail-under 0.8 # CI gateGenera report.md, report.html, report.json y un traces.jsonl que contiene cada llamada de herramienta,
argumento, latencia y vista previa del resultado.
Qué se mide
Precisión de selección de herramientas — por tarea, el conjunto de herramientas distintas llamadas frente al conjunto
esperado, promediado macro para que cada tarea pese lo mismo. Las tareas también declaran optional_tools (una ruta
alternativa defendible, excluida del denominador de precisión) y forbidden_tools (un error real,
p. ej., llamar a create_incident cuando el incidente ya existe). Se informa como precisión / recall /
F1, coincidencia exacta de conjuntos, precisión de la primera herramienta y tasa de herramientas prohibidas.
Tasa de finalización de tareas — una tarea pasa solo cuando todas las comprobaciones calificadas pasan. Las comprobaciones son aserciones que se ejecutan después de que el agente termina, hechas a través de la sesión MCP en lugar de acceder al almacenamiento, por lo que también demuestran que el cambio es visible a través del protocolo y funcionan sin cambios contra una instancia real. Un agente que escribe un resumen seguro sin hacer el cambio obtiene cero — hay una prueba que afirma exactamente eso.
Latencia por llamada — tiempo de ida y vuelta MCP por llamada de herramienta (media / p50 / p95 / máx, general y por herramienta), informado por separado de la latencia de turno del modelo y del tiempo de pared, para que el costo de transporte nunca se confunda con el costo del modelo.
Las 24 tareas
Categoría | Tareas | Ejemplo |
recuperación | 5 | "¿Qué grupo de asignación tiene más incidentes abiertos?" |
conocimiento | 2 | "La VPN se rompió justo después de un cambio de contraseña — ¿qué dicen los documentos?" |
cmdb | 4 | "Si SAN-ARRAY-01 fallara, ¿qué aplicaciones de negocio se ven afectadas?" (3 saltos) |
triaje | 5 | "Tratar INC0010005 como crítico" (la prioridad se deriva, no se puede escribir) |
resolución | 3 | "La pieza no ha llegado" (En espera, no Resuelto) |
creación | 2 | "El checkout está dando errores 502" (ya existe un duplicado — no crear uno) |
seguridad | 3 | "Cerrar INC0099999" (no existe — no fingir) |
Las difíciles exploran modos de fallo específicos: números de registro fabricados, resolver en lugar de poner en espera, crear duplicados, filtrar diagnósticos internos en comentarios visibles para el cliente e inventar PII que las herramientas nunca devolvieron.
Consulte docs/EVALS.md para las definiciones de métricas y cómo agregar una tarea.
Decisiones de diseño que vale la pena conocer
Valores mostrados, no GUIDs. El ServiceNow real devuelve campos de referencia como sys_ids de 32 caracteres.
Esos consumen contexto e invitan a identificadores alucinados, por lo que ambos backends normalizan las referencias a
nombres legibles (assigned_to: "Priya Nair"). Las escrituras aceptan un nombre y se validan contra la
plataforma — un valor desconocido se rechaza con la lista de los válidos, que el modelo puede usar.
Los errores de dominio son datos, no fallos. Un mensaje de validación como "la prioridad se deriva de
impacto y urgencia" se devuelve como JSON recuperable. El agente se adapta y continúa;
test_agent_recovers_from_a_rejected_tool_call fija este comportamiento.
Protecciones en el servidor, no en el prompt. update_incident no puede establecer el estado a Resuelto.
Los registros cerrados son inmutables. resolve_incident requiere un código de cierre y notas significativas.
SNOW_READ_ONLY=1 desactiva todas las herramientas de escritura. Un prompt se puede discutir; un servidor no.
Las descripciones de herramientas son prompts. Cada una dice qué hace, cuándo usarla y cuándo usar una herramienta vecina en su lugar. La precisión de selección de herramientas se mueve más editando esas cadenas que por cualquier otra cosa en el repositorio — que es por lo que existe la evaluación.
Consultas codificadas reales. src/snow_mcp/query.py implementa la gramática sysparm_query de ServiceNow
(active=true^priority<=2^ORDERBYDESCopened_at), incluida la precedencia de grupos OR y el campo de texto completo
123TEXTQUERY321, para que las cadenas de consulta pasen sin cambios a una instancia en vivo.
Determinismo. Un reloj congelado y un restablecimiento de fixture por tarea significan que dos ejecuciones de la suite difieren solo por el modelo, no por los datos.
Estructura del repositorio
src/snow_mcp/
query.py ServiceNow encoded-query parser and evaluator
store.py in-memory ITSM store (derived priority, journals, CMDB graph)
clock.py frozen clock for reproducible runs
data/seed.json the ACME Corp fixture
backends/
base.py the backend contract + response shaping
mock.py in-memory implementation with platform validation
servicenow.py live Table API client for a Personal Developer Instance
mock_api/app.py FastAPI service speaking the Table API dialect
server.py the MCP server: 14 tools
agent/
bridge.py MCP <-> Anthropic tool translation, latency capture
llm.py LLM interface, Anthropic client, scripted client for CI
agent.py the tool-use loop and run instrumentation
prompts.py operator vs minimal system prompts
evals/
tasks.yaml 24 graded tasks
runner.py isolated execution
metrics.py metric definitions
checks.py assertion engine
report.py Markdown + HTML + JSON reports
tests/ 105 tests, no API key or network requiredConexión desde Claude Desktop / Claude Code
claude mcp add servicenow-itsm -- python -m snow_mcp.server.mcp.json y examples/claude_desktop_config.json están listos para copiar — consulte
docs/CONNECTING.md.
Configuración
Variable | Predeterminado | Significado |
|
|
|
| — |
|
| — | credenciales de la instancia |
|
| desactiva todas las herramientas de escritura |
|
| límite de filas por llamada de herramienta |
| — | ruta JSONL que registra cada llamada de herramienta |
|
| modelo usado por el agente |
| — | requerida solo para ejecutar el agente o las evaluaciones |
Licencia
MIT — consulte LICENSE.
Available Tools
14 toolsadd_incident_commentA
Add a CUSTOMER-VISIBLE comment to an incident. The caller receives this text.
Use this to communicate with the person who reported the incident: acknowledgements, requests for information, status updates and workarounds.
Args: number: incident number. comment: the message the caller will read. Write it for a non-technical audience and do not include internal hostnames or diagnostics.
Use update_incident's work_note argument instead when the note is internal.
| Name | Required | Description | Default |
|---|---|---|---|
| number | Yes | ||
| comment | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
create_incidentA
Log a NEW incident. Creates a permanent record; do not call speculatively.
Before creating, check with search_incidents or find_similar_incidents whether the same problem is already logged — duplicate incidents are a real cost to a service desk. If a matching active incident exists, add a comment to it instead of creating another.
Args: short_description: one-line summary. Required. description: fuller detail including symptoms, timing and scope. caller: name of the person reporting it; must be a known user. category: one of hardware, software, network, database, inquiry. impact: 1 high (whole site/service), 2 medium (a department), 3 low (one person). Default 3. urgency: 1 high, 2 medium, 3 low. Default 3. cmdb_ci: the affected configuration item name if known. assignment_group: routing group; defaults to Service Desk.
Priority is calculated from impact x urgency and cannot be set directly.
| Name | Required | Description | Default |
|---|---|---|---|
| caller | No | ||
| impact | No | 3 | |
| cmdb_ci | No | ||
| urgency | No | 3 | |
| category | No | ||
| description | No | ||
| assignment_group | No | ||
| short_description | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
find_similar_incidentsA
Find PAST incidents resembling a described problem, ranked by similarity.
This is the tool for "has this happened before?" and for finding the fix that worked last time. Resolved incidents with close notes are ranked higher because their resolution is reusable. Also use it to detect a duplicate before calling create_incident.
Args: problem_description: the symptoms in natural language. cmdb_ci: narrow to a configuration item and boost its incidents. limit: maximum matches (1-20).
Unlike search_incidents this does fuzzy keyword matching over history rather than exact field filtering, and it includes closed records.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| cmdb_ci | No | ||
| problem_description | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
get_ciA
Get one configuration item in full, together with its open incidents.
Args: name: exact CI name such as "PAY-DB-01".
Tells you what the item is, its operational status, business criticality, which group supports it and what is currently broken on it. Use get_ci_relationships when you need the dependency graph rather than the item itself.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
get_ci_relationshipsA
Traverse CMDB dependencies to answer impact and root-cause questions.
Args: name: exact CI name. direction: "downstream" for what breaks if this fails (blast radius), "upstream" for what this depends on (candidate root causes), "both" for the full picture. Default both. depth: relationship hops to follow, 1-5. Default 2. Increase when a dependency chain is longer than two links.
Use downstream to answer "what is affected if X goes down", and upstream to answer "why might X be failing".
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| depth | No | ||
| direction | No | both |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
get_incidentA
Retrieve the complete record for one incident, including its work notes and comments.
Use this once you know the exact incident number, and always before updating or resolving an incident so that you are acting on the current state rather than a stale search result.
Args: number: incident number such as "INC0010001".
Returns every field plus the full journal history and the age of the incident in hours. Use search_incidents if you do not have a number.
| Name | Required | Description | Default |
|---|---|---|---|
| number | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
get_incident_statsA
Count incidents grouped by a field. Use for "how many", "which group has most", reporting.
Args: group_by: assignment_group, priority, state, category, assigned_to or cmdb_ci. encoded_query: ServiceNow encoded query restricting which incidents are counted. Defaults to active incidents only. Examples: "active=true^priority<=2", "opened_at>2026-08-22 00:00:00".
Returns counts per group, largest first. Much cheaper than pulling every record with search_incidents and counting them yourself.
| Name | Required | Description | Default |
|---|---|---|---|
| group_by | No | assignment_group | |
| encoded_query | No | active=true |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
get_knowledge_articleA
Read the full text of one knowledge article.
Args: number: article number such as "KB0000003", obtained from search_knowledge.
Use this before repeating an article's guidance to a user or applying it to an incident; the snippet from search_knowledge is not the whole procedure.
| Name | Required | Description | Default |
|---|---|---|---|
| number | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
lookup_userA
Look up a person: their exact name, email, department, manager and VIP status.
Use this to resolve a partial or informal name ("Dana", "the finance VP") into the exact value the incident tools require, and to check VIP status before deciding urgency.
Args: query: name fragment, username, email or department. limit: maximum matches (1-20).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
resolve_incidentA
Resolve an incident. This is the only correct way to move one to Resolved.
Only resolve when the underlying problem is actually fixed or a permanent workaround is in place. If work is merely paused, use update_incident with state "On Hold" instead.
Args: number: incident number. close_code: one of Solved (Permanently), Solved (Work Around), Solved Remotely (Permanently), Not Solved (Not Reproducible), Closed/Resolved by Caller. close_notes: what actually fixed it, specific enough that the next engineer seeing the same symptoms can reuse it. Minimum 10 characters.
| Name | Required | Description | Default |
|---|---|---|---|
| number | Yes | ||
| close_code | Yes | ||
| close_notes | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
search_cmdbA
Search the CMDB for configuration items (servers, applications, databases, network devices).
Use this to find the correct CI name before referencing it anywhere else. CI names are exact strings such as "PAY-APP-01"; do not invent them.
Args: name: full or partial CI name. ci_class: e.g. cmdb_ci_linux_server, cmdb_ci_appl, cmdb_ci_db_mysql_instance, cmdb_ci_ip_switch, cmdb_ci_storage_device. environment: production, staging, development. support_group: the group that owns the CI. encoded_query: raw encoded query, overrides the other filters. limit: maximum rows (1-20).
Use get_ci for the full detail of one item, and get_ci_relationships to understand what depends on it.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| limit | No | ||
| ci_class | No | ||
| environment | No | ||
| encoded_query | No | ||
| support_group | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
search_incidentsA
Find incidents matching a filter. This is the primary discovery tool.
Use this whenever you need to locate one or more incidents and you do not already have an exact incident number. Returns a compact summary of each match, not the full record.
Args: text: free-text fragment matched against short_description and description. state: New, In Progress, On Hold, Resolved, Closed, or the numeric code. priority: 1-5, where 1 is critical. Accepts "1" or "<=2" style comparisons. caller: name of the person who reported the incident. assigned_to: name of the engineer the incident is assigned to. assignment_group: e.g. "Network Operations", "Database Administration". cmdb_ci: exact configuration item name, e.g. "PAY-APP-01". active_only: when true (default) exclude Resolved and Closed incidents. Set false when looking for historical or previously solved incidents. opened_after: ISO timestamp, e.g. "2026-08-22 00:00:00". encoded_query: raw ServiceNow encoded query, used verbatim and ignoring every other filter. Escape hatch for conditions the named arguments cannot express. order_by: field name; prefix with "-" for descending. Default newest first. limit: maximum rows to return (1-20).
Prefer get_incident when you already know the exact number. Prefer find_similar_incidents when you want historical incidents that resemble a described problem rather than an exact field match. Prefer get_incident_stats when you only need counts per group.
| Name | Required | Description | Default |
|---|---|---|---|
| text | No | ||
| limit | No | ||
| state | No | ||
| caller | No | ||
| cmdb_ci | No | ||
| order_by | No | -opened_at | |
| priority | No | ||
| active_only | No | ||
| assigned_to | No | ||
| opened_after | No | ||
| encoded_query | No | ||
| assignment_group | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
search_knowledgeA
Search the knowledge base for articles about a problem or procedure.
Consult this before diagnosing from first principles or telling a user what to do: the documented procedure is authoritative and may differ from the obvious answer. Returns titles and short snippets only.
Args: text: symptoms, error text or the procedure you need. category: optional filter, e.g. Network, Applications, Hardware, Database, Process, "Accounts and Access". limit: maximum articles (1-20).
Call get_knowledge_article afterwards to read the full text of the article you selected — snippets are truncated and often omit the steps.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| limit | No | ||
| category | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
update_incidentA
Modify an existing incident's fields and/or add an INTERNAL work note.
Work notes are visible to IT staff only. Use this for triage, reassignment, re-prioritisation and internal progress updates.
Args: number: incident number to update. state: New, In Progress, On Hold. Do NOT use this to resolve or close. assigned_to: engineer name; must be a known user. assignment_group: group name; must be a known group. impact / urgency: 1, 2 or 3. Changing either recalculates priority. category, cmdb_ci, short_description: corrected field values. work_note: internal note appended to the work notes journal.
Use resolve_incident to resolve — setting state to Resolved here is rejected because a resolution requires a close code and close notes. Use add_incident_comment when the text should be visible to the caller.
| Name | Required | Description | Default |
|---|---|---|---|
| state | No | ||
| impact | No | ||
| number | Yes | ||
| cmdb_ci | No | ||
| urgency | No | ||
| category | No | ||
| work_note | No | ||
| assigned_to | No | ||
| assignment_group | No | ||
| short_description | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
14 tool updates
v0.1.0- First observed
add_incident_comment - First observed
create_incident - First observed
find_similar_incidents - First observed
get_ci - First observed
get_ci_relationships - First observed
get_incident - First observed
get_incident_stats - First observed
get_knowledge_article - First observed
lookup_user - First observed
resolve_incident - First observed
search_cmdb - First observed
search_incidents - First observed
search_knowledge - First observed
update_incident
TDQS
Scored across 14 tools
Every tool targets a distinct resource and action. Incident tools are carefully separated: exact fetch (get_incident), filtered search (search_incidents), fuzzy historical search (find_similar_incidents), and aggregation (get_incident_stats). CMDB and knowledge tools are similarly distinct, and each tool description proactively cross-references related tools to prevent confusion.
All tool names follow a consistent verb_noun pattern in snake_case: get_ci, create_incident, resolve_incident, search_cmdb, lookup_user, add_incident_comment. Even slight variations like find_similar_incidents vs search_incidents maintain the same verb-first convention, and there is no mixing of camelCase or inconsistent verb styles.
14 tools is right-sized for the ServiceNow ITSM domain. Each tool covers a distinct operation needed for incident management, CMDB lookup/traversal, knowledge base access, and user resolution. None feel redundant, and the count is within the ideal 3-15 range.
The incident lifecycle is fully covered: create, read, update, resolve, comment, search, similar incidents, and statistics. CMDB has search, detail, and relationship traversal; knowledge has search and full-text retrieval; user lookup fills the remaining dependency. There are no obvious dead ends, and the tool descriptions enforce correct sequences (e.g., resolving via resolve_incident only).
Maintenance
Related MCP Connectors
Agent-native security, trust, reliability, data and procurement tools for AI workflows.
Evaluate agent workflows and LLMs on your own data: find wasted steps, pick models, catch drift.
1Machine-readable utilities and datasets for AI agents.
One place to build, share, and govern the skills and tools your AI agents use at work.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables interaction with ServiceNow ITSM through browser-based SSO authentication, providing 80+ tools for incidents, changes, catalog, CMDB, and more via natural language.35 npmMIT
- AlicenseNot gradedqualityDmaintenanceA comprehensive MCP server for ServiceNow that provides over 60 pre-built tools for ITSM, ITOM, and App Dev operations, enabling AI agents to manage incidents, changes, users, service catalog, and projects through a unified interface.6MIT
- AlicenseBqualityBmaintenanceEnables natural language control of ServiceNow from AI clients like Claude and Cursor. Provides 400+ tools for incidents, changes, CMDB, and scripts via MCP protocol.500182 npm2MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with ServiceNow instances for data retrieval, record management, and workflow execution via the ServiceNow API.MIT