Skip to main content
Glama

curseforge-ark-mcp

Un servidor MCP de solo lectura para la curación, descubrimiento y vigilancia de actualizaciones de mods de CurseForge para ARK: Survival Ascended.

ESTO SIGUE SIENDO v0 — PARCIALMENTE VERIFICADO, NO VERIFICADO.

Lo que cambió el 2026-08-18: llegó la clave de la API de CurseForge, el cliente realizó sus primeras llamadas autenticadas, y cada ruta de campo de Mod y File que lee se confirmó presente en las respuestas en vivo. Ninguna necesitó corrección. Muestra: 748 mods distintos de ARK: Survival Ascended , 1899 registros de archivos.

Por qué sigue siendo v0. Cuatro cosas siguen sin confirmarse, y una de ellas no puede confirmarse mirando:

  • La forma del borde FileDependency nunca se ha observado — 0 de 1899 archivos ASA muestreados declararon una dependencia, con el array dependencies presente y vacío cada vez.

  • Los enteros FileRelationType no están publicados y no se ejercitan en este catálogo.

  • Los enteros FileReleaseType 1, 2 y 3 ya se han visto. Cuál significa release, beta o alpha sigue siendo desconocido, y este servidor no adivinará.

  • Cualquier límite del proveedor en arrays de IDs de lectura masiva: no se encontró ninguno hasta 300 IDs, por lo que no se conoce ninguno.

Un cliente parcialmente verificado no es uno verificado. El número de versión es una afirmación sobre el estado de verificación, por lo que es 0.2.0 — no 1.0.0, y deliberadamente no 1.0.0-cualquiercosa.

El comportamiento de este repositorio se verifica independientemente de la API: la lista de permitidos de endpoints, el pin del host, la normalización de rutas, los límites de paginación, el manejo de envoltorios y la disciplina de tres estados ausente/vacío/desconocido. Todo ello se prueba contra un fetch falso inyectado, sin clave y sin red. 156 pruebas, 0 fallos en el momento de escribir esto.

Registro de diseño: docs/adr/ADR-002-endpoint-allow-list.md (estado: PROPOSED). Cada referencia a secciones a continuación (§1, §4.3, §14.3 …) apunta a él.


Related MCP server: neoforge-kb-mcp

Lo que hace, y lo que deliberadamente no puede hacer

Siete herramientas, todas de solo lectura:

Herramienta

Responde

search_mods

"¿Qué mods de ASA coinciden con este término?"

get_mod

"¿Qué es el proyecto 777001?"

list_mod_files

"¿Qué archivos ha publicado este mod?"

get_mod_file

"¿Qué es este archivo específico?"

get_latest_file

"¿Hay un archivo más reciente para este mod que el que estoy ejecutando?"

resolve_mod_dependencies

"¿Qué arrastra este mod?" (por lotes, una solicitud por nivel de árbol)

get_api_diagnostics

"¿Soy yo, la clave o CurseForge?" — y "¿qué tan honesta es esta compilación?"

No puede:

  • Descargar ni instalar nada. GET /v1/mods/{modId}/files/{fileId}/download-url es una lectura documentada, en el host fijado, y está rechazada — porque no está en la lista de permitidos de endpoints (DEC-002 §11.3). Nitrado instala los mods por sí mismo.

  • Escribir nada, en ningún lugar. Ninguna entrada de la lista de permitidos nombra un endpoint mutante. CurseForge opera una API de carga mutante en un host diferente (§14.2); el pin del host la rechaza una segunda vez por una razón independiente.

  • Publicar o crear un mod. Rechazado de plano (DEC-002 Ruling 2). Aplicado por una aserción de arranque, no por una promesa: registrar una herramienta que declare algo que no sea el nivel 1 hace que el proceso se niegue a iniciar.

  • Tocar Nitrado. No existe ninguna variable NITRADO_* en la superficie de configuración de este repositorio, y su ausencia es un control. Este servidor no tiene ningún token de Nitrado y no lee ninguna configuración de Nitrado.

  • Despertarse con un temporizador y actualizar tu servidor. Sin programador, sin bucle de sondeo, sin estado persistente de "última versión vista" (§10). Vigilancia significa que el modelo puede observar una nueva versión. No puede actuar.


El punto de estrangulamiento: una lista de permitidos de endpoints, no una verificación de método

Esta es la única decisión de diseño que vale la pena leer antes de tocar el código.

CurseForge usa POST para LEER. POST /v1/mods y POST /v1/mods/files son recuperaciones masivas, y son lo que hace que resolve_mod_dependencies cueste una solicitud por nivel de dependencia en lugar de una por nodo. Así que el method !== "GET" → refuse del repositorio hermano fallaría aquí de la manera más costosa posible: funcionaría. Rechazaría cosas, pasaría sus propias pruebas, y silenciosamente haría que el servidor fuera malo en su trabajo.

Y la solución obvia es peor que el error:

allowed = { GET }          → the batch reads are refused (broken, loudly)
allowed = { GET, POST }    → every request this client can construct is allowed

La API del catálogo documentada contiene solo GET y POST. Una puerta que admite ambos admite todo — mientras sigue pareciendo presente.

Así que, en su lugar, cada solicitud saliente debe coincidir con una entrada explícita en una lista cerrada de pares {method, path}. Siete entradas, en src/allowlist.ts:

#

Method

Path

Sirve

E1

GET

/v1/games

resolución de ID de juego, get_api_diagnostics

E2

GET

/v1/mods/search

search_mods

E3

GET

/v1/mods/{modId}

get_mod, get_latest_file

E4

GET

/v1/mods/{modId}/files

list_mod_files, get_latest_file

E5

GET

/v1/mods/{modId}/files/{fileId}

get_mod_file

E6

POST

/v1/mods

resolve_mod_dependencies (lectura masiva)

E7

POST

/v1/mods/files

resolve_mod_dependencies (lectura masiva)

Mecánicamente:

  • Coincide en {method, path} conjuntamente. E3 no autoriza DELETE /v1/mods/123. E6 no autoriza POST /v1/mods/123.

  • El host está fijado a https://api.curseforge.com, y el pin es un permitir de un origen en lugar de un denegar de cualquier otro nombrado.

  • Los segmentos de ID se vinculan a [0-9]+, no a [^/]+. Esto es crucial: un {modId} permisivo hace que E3 se trague /v1/mods/search. El enlace numérico hace que esa ambigüedad sea estructuralmente imposible en lugar de depender del orden de coincidencia — y hay una prueba que invierte toda la lista para demostrar que el orden no es lo que lo salva.

  • Una normalización, antes de la verificación, y la URL se construye a partir de su salida. Decodificar porcentajes una vez; rechazar cualquier % que sobreviva; plegar barras invertidas; rechazar segmentos ., .. y vacíos.

  • Solo E6/E7 pueden llevar un cuerpo, verificado en forma antes del envío. Un cuerpo en una entrada GET se rechaza, no se descarta.

  • Solo resolve_mod_dependencies puede alcanzar una entrada POST (§8), aplicado en el transporte.

El modo de fallo es "solicitud no coincidente rechazada", nunca "solicitud no reconocida enviada." Y agregar una capacidad es un diff de una línea revisable cuya pregunta de revisión — "¿es este endpoint una lectura?" — es una que un humano puede responder realmente.

La prueba que demuestra que es una lista de permitidos

GET /v1/mods/{modId}/files/{fileId}/download-url está rechazada. Es una lectura documentada, un GET, en el host fijado, con IDs numéricos bien formados. Está rechazada puramente porque no está en la lista. Si esa prueba alguna vez pasa por alguna otra razón — un rechazo del pin del host, un rechazo de ruta — la propiedad no está implementada, por lo que la prueba afirma el código y detalle del rechazo, no meramente que algo lanzó una excepción.

Cada prueba de rechazo también afirma el recuento de llamadas del fetch falso, porque "rechazado antes de que se construya la solicitud" es la disposición real, y un error lanzado después del envío satisfaría una aserción más débil. Y el conjunto de rechazos está precedido por una prueba de preimagen que demuestra que las siete entradas sí envían — un conjunto de rechazos sobre un cliente que no puede enviar nada pasa perfectamente y no prueba nada.


Verificado contra la API en vivo — 2026-08-18

Muestra: 748 mods ASA distintos, 1899 registros de archivos, extraídos de páginas de búsqueda profundas (índice 1000-6000) y de cada sortField documentado 1-12, más listas de archivos completas para 100 mods. Fechado y dimensionado a propósito: "verificado" sin un tamaño de muestra es un estado de ánimo, no una afirmación.

#

Afirmación

Resultado

U1

El gameId de ASA

83374, slug ark-survival-ascended, nombre ARK Survival Ascended — sin dos puntos, lo que una ortografía de coincidencia exacta habría tenido mal. Aún se resuelve en vivo en cada inicio; una prueba afirma que el número no aparece en ningún lugar de src/ fuera de un comentario.

U2

¿Es ASA visible para la clave?

Sí. 38 juegos visibles, ASA entre ellos. No bloquea v1.

U3

Rutas de campo de Mod

Todas correctas. id, gameId, name, slug, dateModified, links.websiteUrl, categories, allowModDistribution, latestFiles, latestFilesIndexes.

U4

Rutas de campo de File

Todas correctas. id, modId, displayName, fileName, fileDate, gameVersions, sortableGameVersions, dependencies, releaseType, isAvailable.

U8

Presencia de pagination

Presente en los endpoints paginados (juegos, búsqueda, archivos), ausente en lecturas de un solo registro y masivas — que es exactamente la división que este cliente fue construido para esperar.

U9

¿Los mods de ASA llenan los campos opcionales?

latestFiles, latestFilesIndexes, sortableGameVersions, gameVersions: 300/300. dependencies: presente en el 100%, no vacío en el 0%.

U11

Cabeceras de límite de tasa

CurseForge no envía ninguna. Enumeración completa de cabeceras en un GET y POST en vivo encontró solo cabeceras de transporte/CDN. Así que null no es un error de coincidencia en este cliente — pero no es una afirmación de que no exista ningún límite, y el ritmo autoimpuesto se mantiene.

U12

Paginación más allá del índice 0

Funciona; totalCount estable en 6848 a través de las páginas. Pero más allá del final de un conjunto de resultados, CurseForge devuelve resultCount: 0 y totalCount: 0 — totalCount describe la respuesta, no la consulta. La salida de la herramienta ahora dice "más allá del final" en lugar de dejar que eso se lea como "no se encontró nada".

U13

URL base

Correcto. El pin del host es sólido.

No se necesitó corregir ninguna ruta de campo. Eso se registra como un resultado, no como un alarde: el commit 5481c04 del repositorio hermano corrigió tres rutas incorrectas el día que se conectó por primera vez en vivo, y ese precedente es la razón por la que cada ruta aquí se verificó una por una en lugar de confiar en ella.

Aún no verificado

Reducido, no desaparecido. Estas son las filas que sobrevivieron al contacto con la API en vivo.

#

Claim

Status

Why it is still open

U5

FileDependency = { modId, relationType }

No observado

No se ha mostrado incorrecto — nunca visto. Ningún archivo ASA en la muestra declaró una dependencia, por lo que nunca se ha inspeccionado ningún objeto de borde. La forma se deriva de la documentación y el fixture de prueba es el único lugar donde existe.

U6

El FileRelationType enum numérico

No publicado Y no observable aquí

dependencies estaba presente y vacío en los 1899 archivos de 748 mods, por lo que nunca ha aparecido un entero de relación. ADR-002 predijo esto y nombró la consecuencia: el recorrido de enteros no mapeados es la respuesta, no un parche. Efecto práctico: para ASA, resolve_mod_dependencies devuelve árboles de un solo nodo, y ahora lo dice en su propia salida para que un árbol vacío no se lea como un fallo.

U7

El FileReleaseType enum numérico

Valores vistos, significados desconocidos

Observado: 1 (1893 archivos), 2 (3), 3 (3). Al menos tres miembros, consistente con el trío alpha/beta/release de la API de Upload — y ninguna evidencia sobre qué entero es cuál. Una distribución de frecuencias no es una tabla de valores. Inferir 1 = release porque 1 es el más común es la suposición que este repositorio existe para rechazar.

U10

Límite del proveedor en arrays de IDs de lectura masiva

No se encontró límite hasta 300

200 IDs distintos devolvieron 200 registros; 300 devolvieron 300. Por lo tanto, el límite, si existe, está por encima de 300. El límite de 200 IDs en este cliente se mantiene: es nuestro, deliberadamente conservador contra un límite de tasa no documentado, y una sonda que no encontró techo no ha encontrado el techo.

Dos consecuencias que verás en la salida de la herramienta

relationType y releaseType se presentan como enteros sin procesar y nunca se mapean. No a required/optional, no a release/beta/alpha. CurseForge no publica una tabla de valores para ninguno, y una etiqueta incorrecta produciría una lista de dependencias — o una recomendación de actualización — que es incorrecta de una manera que nadie verificaría. Por lo tanto, resolve_mod_dependencies sigue cada borde y lo dice: sobre-recopila, y su salida lo indica claramente. Una red amplia es al menos visiblemente amplia.

Para ASA específicamente, el catálogo en vivo hace que eso sea irrelevante de una manera que vale la pena saber antes de usar la herramienta: ningún mod ASA muestreado declara ninguna dependencia en absoluto. Un árbol de un solo nodo es el resultado esperado, no un síntoma de un recorrido roto, y la salida de la herramienta dice cuál es.

get_latest_file requiere que digas qué significa "más reciente". El más nuevo por fileDate, el más nuevo que coincide con una versión del juego, y el más nuevo con un releaseType dado dan respuestas diferentes, y una decisión de actualización de mod basada en la incorrecta es exactamente la clase de respuesta segura pero incorrecta contra la que está organizado este repositorio. selection no tiene valor predeterminado:

selection

También requiere

Significado

newest_by_file_date

—

El más reciente de todos los archivos candidatos, por fileDate

newest_matching_game_version

game_version

El archivo más reciente que declara esa versión del juego

newest_with_release_type

release_type (un entero sin procesar)

El archivo más reciente que lleva ese entero de tipo de lanzamiento

No hay un filtro con nombre release/beta/alpha, porque U7 no está resuelto y este servidor no inventará el mapeo. Pasas el entero que quieres decir.

Esta definición es una PREGUNTA ABIERTA DE PRODUCTO. La pregunta abierta 2 de ADR-002 la señala como una decisión fundacional que no se había tomado cuando se construyó esto, por lo que la herramienta está parametrizada en lugar de dogmática: cuando llegue la respuesta, se convierte en un valor predeterminado, o una variante menos — un cambio pequeño en lugar de una reescritura. Cada respuesta reafirma el orden que usó, en qué filtró, cuántos candidatos consideró y de dónde vinieron los candidatos.


Configuración

Node 20+ (desarrollado en 22). No hay paso de compilación que configurar; npm test compila primero.

npm install
npm test          # builds, then runs the suite — no key, no network, nothing live
npm run typecheck
npm run smoke     # LIVE once a key is configured; refuses cleanly and probes nothing without one

npm run smoke es la ejecución de falsificación, no una verificación de estado. Con una clave, recorre el registro §14.3 fila por fila e imprime lo que observó; sin una, nombra cada sonda que habría realizado y sale con 0 sin haber enviado nada. El conjunto de pruebas nunca toca la red en ningún caso.

Configuración del cliente MCP (stdio):

{
  "mcpServers": {
    "curseforge-ark": {
      "command": "node",
      "args": ["C:/path/to/curseforge-ark-mcp/dist/src/server.js"],
      "env": { "CURSEFORGE_API_KEY": "your-key" }
    }
  }
}

El servidor se niega a iniciar sin una clave, nombrando ambas ubicaciones que buscó, la variable exacta y el hecho de que la clave no es de autoservicio. Un servidor MCP stdio que se inicia limpiamente y luego lanza una excepción en las siete herramientas es algo miserable de depurar.

Acerca de la clave

La clave de API se envía como un encabezado de solicitud x-api-key. No es un token Authorization: Bearer — ese es el esquema del servidor Nitrado hermano, y este repositorio deliberadamente no soporta ambos, porque soportar ambos significaría que este código podría transmitir la credencial en una forma que CurseForge nunca documentó.

La clave se otorga mediante solicitud a Overwolf y es intransferible. La consecuencia práctica, y la única razón por la que existe este párrafo: una filtración significa revocar y volver a solicitar, y la nueva solicitud es una cola, no un restablecimiento de autoservicio. No puedes regenerarla mientras tomas un café y no puedes tomar prestada la de otra persona. Trátala en consecuencia — .env está en gitignore, .env.example lleva el nombre de la variable y un valor vacío, y ningún valor de clave aparece en ningún archivo confirmado.

No hay una matriz de alcance en este repositorio, y eso no es un descuido: CurseForge no publica un alcance de solo lectura ni una selección de alcance, por lo que no hay nada que poner en matriz. La propiedad de solo lectura de este servidor proviene de su propia lista de permitidos de endpoints, no de una credencial más restringida. Tampoco hay un runbook de fuga de tokens — una clave filtrada otorga acceso de lectura a un catálogo público más consumo de cuota, lo cual es real y no es la misma categoría que el token Nitrado del repositorio hermano (documentado como equivalente al control total de un servidor de juego). Ese dimensionamiento correcto se argumenta en ADR-002 §12, y se basa en una afirmación establecida allí para que pueda ser falsificada: Los datos del catálogo de CurseForge son públicos por construcción.

Redacción, todo ello

Una regla: nunca repetir la clave de API. Una función, src/scrub.ts, aplicada a mensajes de error y a cualquier fragmento de cuerpo upstream. Los encabezados de solicitud nunca aparecen en los errores — ni la clave, ni una clave redactada, ni una lista de nombres de encabezados. get_api_diagnostics informa si una clave está configurada y nunca su valor, un prefijo de ella, o su longitud.


Comportamientos que vale la pena conocer antes de leer la salida

  • Vacío no es desconocido. data: [] significa que CurseForge respondió "ninguno" — una respuesta real, con la consulta repetida para que puedas ver qué devolvió nada. Un campo ausente es null, nunca 0, "" o []. Una solicitud que no se completó, o una respuesta cuya forma es incorrecta, es un error — nunca un valor.

  • Una clave data faltante es un error, no un resultado vacío. Forzarla a [] convertiría una integración rota en "no se encontraron resultados".

  • Una pagination faltante en un endpoint paginado también es un error. Asumir una página es cómo una herramienta informa 50 de 900 mods como si fueran todos (U8 es exactamente esta pregunta abierta).

  • pageSize > 50 se rechaza, no se recorta, y también index + pageSize > 10000 — con el tamaño de página legal más grande en ese índice nombrado en el mensaje. Un modelo que pide 200 y silenciosamente obtiene 50 razonará sobre una página como si fuera un conjunto.

  • Cuando totalCount supera 10000, la salida de la herramienta dice que la cola es INALCANZABLE, en esas palabras, y aconseja reducir el filtro en lugar de paginar.

  • El gameId de ASA se descubre en tiempo de ejecución desde GET /v1/games y se almacena en caché durante la vida del proceso; nunca está codificado ni se adivina. Si no se puede resolver, el servidor falla ruidosamente, nombrando lo que buscó y cuántos juegos pudo ver la clave — porque gameId es un filtro de búsqueda requerido, por lo que uno incorrecto devuelve resultados limpios, vacíos y completamente incorrectos en lugar de un error. Establece CURSEFORGE_GAME_SLUG si los candidatos incorporados resultan ser incorrectos.

  • resolve_mod_dependencies está acotado a profundidad 4 y 400 nodos, con un conjunto de visitados para ciclos. Cuando se alcanza un límite, el resultado se informa como truncado, en esa palabra, con la frontera inexplorada listada.


Estructura del repositorio

src/
  allowlist.ts    THE CHOKEPOINT — seven entries, host pin, normalization, bounds, body checks
  client.ts       the single transport; the ONLY place x-api-key is attached; envelope unwrap
  config.ts       refuse-to-start; no NITRADO_*, no mode switch, no settable base URL
  coerce.ts       empty / absent / unknown, kept apart
  errors.ts       the error taxonomy
  game.ts         runtime gameId resolution (injected, process-lifetime cache)
  registry.ts     ToolDef + tier, and the boot assertion that refuses a non-tier-1 tool
  scrub.ts        never echo the key. That is the whole module.
  probe-plan.ts   one probe per unverified row, asserted complete by a test
  server.ts       stdio entry point
  smoke.ts        the falsification run (live with a key, plan-only without)
  tools/          the seven tools
test/             156 tests; fixtures are synthetic in content, structural in shape
scripts/          buildinfo generator, test enumerator

src/buildinfo.ts está generado y en gitignore, sellado con el commit y una bandera dirty antes de cada ejecución de tsc, y expuesto por get_api_diagnostics. dist/ está en gitignore y el servidor se ejecuta desde allí como un proceso de larga duración, por lo que "¿qué código produjo esa respuesta?" no se puede responder desde git en tiempo de ejecución — tiene que viajar con el artefacto.

Desviaciones del repositorio hermano, declaradas deliberadamente

Las preguntas abiertas 7 y 8 de ADR-002 piden que estas se nombren donde ocurren:

  • Misma línea base, deliberadamente. Node ≥20, TypeScript 5.9.3, @modelcontextprotocol/sdk 1.30.0, zod 4.4.3, node:test a través del mismo enumerador scripts/run-tests.mjs. Mismo revisor, mismos modismos, menor costo de leer ambos.

  • @cfworker/json-schema no es una dependencia aquí. Respaldaba la validación de expresiones cron del hermano, y no hay una ruta de escritura que validar.

  • registry.ts se ha portado en estructura y mantiene tier, pero elimina la maquinaria de modo/lista habilitada — no tendría nada que filtrar, ya que cada herramienta es nivel 1 y cada endpoint es una lectura. Una variable de modo sin nada detrás anuncia un control que no existe. Una aserción de arranque de cinco líneas reemplaza el subsistema.

  • redact.ts no se ha portado (§12.1). Ver "Redacción, todo ello" arriba.

  • No hay código de error UNKNOWN_OUTCOME. El hermano lo necesita porque una respuesta perdida a un PUT aún puede haber cambiado el mundo. Cada solicitud que este cliente puede hacer es una lectura, por lo que un tiempo de espera realmente significa "no ocurrió" y un reintento es seguro.

  • npm run smoke sale con 0 cuando se niega por falta de una clave. La negativa es el resultado esperado de ejecutarlo hoy, y el banner dice SMOKE NOT RUN de manera inconfundible. Si quieres que un pipeline falle por una clave faltante, condiciona el pipeline a la clave en lugar de a este código de salida.


Registros relacionados

En el repositorio hermano nitrado-ark-mcp, solo lectura desde aquí — nada en ese repositorio fue modificado por este:

  • docs/decisions/EXECUTIVE-BOARD-2026-08-16-curseforge-mods.md — las actas de la junta (DEC-002) que este repositorio ejecuta. Sus Decisiones del Presidente son vinculantes.

  • docs/decisions/decision-log.md — DEC-002, y DEC-001 para la división de alcance en la que se basa §10.

  • docs/adr/ADR-001-write-path-enforcement.md — la forma que ADR-002 trasplanta, y la fuente de la regla de normalización, el razonamiento de verificación de arranque y el razonamiento de negarse a iniciar.

Los dos servidores se mantienen independientes. nitrado-ark-mcp responde "estos ids de proyecto están en active-mods"; este repositorio responde "el archivo más reciente del proyecto X es v2.1". El modelo tiene ambos. Ningún servidor llama al otro, y ninguno posee jamás la credencial del otro.

Available Tools

8 tools
get_api_diagnosticsDiagnose this server's CurseForge connection and honesty postureA

Answers 'is it me, the key, or CurseForge?' in one call: whether a key is configured (never the key itself, nor a prefix, nor its length), whether GET /v1/games succeeded, which ARK: Survival Ascended gameId was resolved and how, which commit this build came from and whether that build was dirty, what the endpoint allow-list currently permits, and any rate-limit headers a real response actually carried. It also reports the VERSION POSTURE: this is v0 and every field path in every tool is a hypothesis. Run this first when other tools behave strangely. Read-only.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior5/5

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

With no annotations, the description fully carries the behavior-disclosure burden. It declares the tool is read-only, states that it never reveals the key, prefix, or length, and even discloses the v0 hypothesis posture where field paths may be unreliable. This is unusually transparent.

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 long and dense, but nearly every clause adds a distinct diagnostic detail or caveat. It is front-loaded with the core question the tool answers. A slightly shorter or more list-like structure would improve scannability, but there is minimal wasted text.

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 zero-parameter diagnostic tool with no output schema, the description enumerates the reported areas comprehensively: key presence, API call success, gameId resolution, build metadata, allow-list, rate-limit headers, and version posture. It lacks an exact output format example, but the high-level coverage is sufficient for an agent to invoke and interpret the 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 zero parameters and the schema is an empty object, so the description cannot add parameter-level semantics. The baseline for a no-parameter tool is 4, and the description appropriately focuses on what the diagnostic returns instead.

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 diagnostic verb and resource: it answers 'is it me, the key, or CurseForge?' in one call and enumerates exactly what it reports. The title and description clearly distinguish it from the sibling mod-focused tools.

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?

It gives explicit guidance: 'Run this first when other tools behave strangely.' This provides a clear trigger condition for use. It does not spell out when not to use it, but the diagnostic scope makes that exclusion unnecessary.

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

get_latest_fileGet a mod's newest file, by a stated definition of newestA

Answers 'is there a newer file for this mod than the one I am running?' Default selection is 'newest_by_file_date' (founder decision 2026-08-18). The other definitions still give different answers: 'newest_matching_game_version' restricts to files declaring a game version and then orders by fileDate; 'newest_with_release_type' restricts to a releaseType INTEGER you supply and then orders by fileDate. There is no named release/beta/alpha filter because CurseForge publishes no value table for that integer (ADR-002 §14.3 U7) and this server will not invent one. Every answer restates the ordering used, whether the default was applied, the filter applied, how many candidates were considered, and where the candidates came from. The matched file includes file_length_bytes; inspect that and file_name before treating it as a content pack. Read-only.

NameRequiredDescriptionDefault
mod_idYesCurseForge numeric mod (project) id.
selectionNoWhich question you are asking. Defaults to newest_by_file_date. These give different answers; pass another variant only when that is the question you mean.newest_by_file_date
game_versionNoRequired when selection is 'newest_matching_game_version'. The game version string a candidate file must declare. This server does NOT and MUST NOT learn your server's version from Nitrado (ADR-002 §9) — you supply it.
release_typeNoRequired when selection is 'newest_with_release_type'. The raw releaseType integer a candidate must carry. Unmapped on purpose: CurseForge publishes no value table, so pass the integer you mean rather than a label this server would have to guess.

TDQS

A4.4/5.0
Behavior5/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 it does so thoroughly. It declares Read-only, explains what every answer restates, notes the file_length_bytes caveat, and explains the deliberate refusal to invent release-type labels. There is no annotation to contradict.

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 dense but well organized: it front-loads the core question, then explains each selection mode and the caveats. Some internal references like 'ADR-002 §14.3 U7' add context but are slightly esoteric, keeping this from a perfect score.

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?

Given no output schema, the description explains what the answer will contain: the ordering, default application, filter, candidate count, and candidate source. It also draws attention to file_length_bytes and file_name for content-pack inspection, so an agent has enough to invoke and interpret the call correctly.

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?

Input schema coverage is 100%, so baseline 3 applies. The description reinforces parameter requirements but largely restates schema details such as 'Required when selection is...' and 'pass the integer you mean.' It adds useful context but does not need to compensate for missing schema coverage.

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 opens with the exact question the tool answers and identifies the resource: a mod's newest file by a defined notion of 'newest.' It explains that there are three selection definitions and names the default, so an agent can clearly distinguish this from list_mod_files or get_mod_file.

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?

It gives explicit guidance on when to use the default versus the other selection variants, stating 'pass another variant only when that is the question you mean.' It also documents the required conditions for the non-default variants and explains why a named release-type filter cannot exist.

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

get_modGet one mod recordA

Fetch a single CurseForge mod (project) record by numeric id: name, slug, author summary, raw status integer, created/modified/released dates, website link, and its latestFiles with file length in bytes and raw releaseType integers. A record is a catalog row, not an install recommendation — inspect file_name and file_length_bytes. This is a single-record endpoint, so it carries no pagination and none is invented. Read-only. v0: all field paths unverified.

NameRequiredDescriptionDefault
mod_idYesCurseForge numeric mod (project) id. Digits only — the allow-list will not match anything else.

TDQS

A4.3/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 transparency burden. It explicitly states 'Read-only', explains the absence of pagination, warns that the record is a catalog row rather than an install recommendation, and flags 'v0: all field paths unverified' as an important caveat. It does not mention error behavior or auth needs, but this is a simple single-record read.

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 dense but every sentence contributes: the field list, the catalog-vs-install clarification, the no-pagination note, the read-only flag, and the v0 caveat. It is front-loaded with the core action and resource, with no redundant phrasing.

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 single-parameter read endpoint with no output schema, the description explains the expected return content, clarifies the semantic meaning of the record, rules out pagination, and discloses version uncertainty. An agent has enough information to select and invoke the tool correctly, and to interpret what it gets back.

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 100%, so the schema already fully documents mod_id as a CurseForge numeric mod id with a minimum, maximum, and digits-only note. The description adds only the phrase 'numeric id', which does not meaningfully extend the schema. Baseline 3 is appropriate because the structured schema handles the 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 opens with a specific verb and resource: 'Fetch a single CurseForge mod (project) record by numeric id.' It enumerates concrete returned fields and explicitly contrasts itself with list/search endpoints by calling itself a single-record endpoint, making sibling differentiation clear.

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: this is the tool to use when you have a numeric mod id and need one catalog record. It also clarifies that pagination is not applicable, which prevents incorrect assumptions. It stops short of explicitly naming alternatives like search_mods or get_mod_file for when a different tool should be chosen.

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

get_mod_fileGet one mod file recordA

Fetch a single file record for a mod by numeric mod id and file id: display name, file name, file date, file_length_bytes, game versions, raw releaseType integer, and dependency edges with raw relationType integers. Inspect file_name and file_length_bytes before treating a file as a content pack. NOTE: this tool does NOT return a download URL. The download-url endpoint is deliberately absent from this server's endpoint allow-list (DEC-002 §11.3) — this server curates and reports, it never downloads or installs. Read-only. v0: all field paths unverified.

NameRequiredDescriptionDefault
mod_idYesCurseForge numeric mod (project) id. Digits only — the allow-list will not match anything else.
file_idYesCurseForge numeric file id.

TDQS

A4.3/5.0
Behavior5/5

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

No annotations are present, so the description correctly carries the full burden of behavioral disclosure. It explicitly states the tool is read-only, intentionally returns no download URL, and will never download or install. The v0 caveat that all field paths are unverified is valuable transparency about reliability.

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 front-loaded with purpose and returned fields, then provides caveats. Each sentenced earns its place: content-pack inspection, no-download-URL policy, read-only, and v0 unverified note. The DEC-002 citation is slightly verbose for a tool-calling agent but not wasteful.

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?

With no annotations and no output schema, the description supplies the needed context: purpose, key parameters, returned field names, raw-integer encodings, read-only behavior, the download-URL absence, and reliability caveat. Its main gap is not explicitly routing to sibling tools, which was already penalized under usage guidelines.

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 100%, and both parameters already have meaningful descriptions ('CurseForge numeric mod project id. Digits only...' and 'CurseForge numeric file id.'). The description only restates that the IDs are numeric and adds no substantive parameter semantics beyond the schema.

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 starts with a specific verb ('Fetch') and resource ('a single file record for a mod'), and specifies the exact keys (numeric mod id and file id). This clearly distinguishes it from list_mod_files and get_latest_file in the sibling set, even without naming them. The title reinforces the singular, ID-based scope.

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?

It gives clear usage context: fetch one known file by IDs, inspect file_name and file_length_bytes before treating a file as a content pack, and do not use it when a download URL is needed because it explicitly does not return one. It stops short of naming specific sibling tools for enumeration or latest-file selection, so it is not a 5, but it is far above implied usage.

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

list_categoriesList ARK: Survival Ascended classes and categoriesA

List CurseForge classes and categories for ARK: Survival Ascended. Use this BEFORE search_mods when you need class_id, category_id, or exclude_category_ids — those integers are discovered here, never hardcoded. gameId is resolved at runtime and is not a parameter. Optional class_id narrows to categories under one class; classes_only returns only top-level classes. The documented response is a single array (no pagination object). Read-only.

NameRequiredDescriptionDefault
class_idNoRestrict to categories under this class id. Discoverable from a classes_only call.
classes_onlyNoWhen true, return only top-level classes for the game, not every nested category.

TDQS

A4.6/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 and meets it: it declares read-only, discloses the response shape ('single array (no pagination object)'), and flags the runtime-discovery nature of the returned IDs. It doesn't cover error/rate-limit/auth behavior, but for a read-only list endpoint the disclosed traits are the meaningful ones.

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?

Four sentences, each earning its place: purpose, when-to-use, param behavior, response shape. The routing guidance is front-loaded and there is zero filler or repetition of schema text.

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 2-optional-param, read-only list tool with 100% schema coverage and no output schema, this is nearly complete: purpose, sequencing, param semantics, and pagination behavior are all covered. The only gap is the shape of the returned category/class objects (e.g., which fields besides ids are present), which an agent would need when building exclude lists.

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 coverage is 100%, so baseline is 3, but the description adds genuine cross-tool meaning: it explains why class_id matters (to feed search_mods include/exclude params), that values must be discovered at runtime rather than hardcoded, and that gameId is intentionally absent. That's more than the schema's 'Restrict to categories under this class id' provides.

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+resource+scope: 'List CurseForge classes and categories for ARK: Survival Ascended'. It separates itself from siblings directly by naming search_mods as the tool that consumes these IDs, and its subject (classes/categories) is distinct from list_mod_files/get_mod. An agent can tell what it does without opening the schema.

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?

Gives explicit sequencing guidance: 'Use this BEFORE search_mods when you need class_id, category_id, or exclude_category_ids — those integers are discovered here, never hardcoded.' It also prunes a likely mistake by stating gameId is resolved at runtime and not a parameter, so the agent won't hunt for a nonexistent gameId param.

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

list_mod_filesList a mod's filesA

List the published files for one mod, paginated. Each file carries its raw releaseType integer, its game versions, file_length_bytes, and its dependency edges with raw relationType integers — none of those integers is mapped to a label, because CurseForge publishes no value table for either. Inspect file_name and file_length_bytes before treating a file as a content pack. Page size is capped at 50; an over-large request is refused rather than clamped. Read-only. v0: all field paths unverified.

NameRequiredDescriptionDefault
indexNoZero-based offset. index + page_size <= 10000.
mod_idYesCurseForge numeric mod (project) id. Digits only — the allow-list will not match anything else.
page_sizeNoAt most 50. Over that is refused, not clamped.
game_versionNoFilter to files supporting this game version string. UNVERIFIED (§14.3 U9).

TDQS

A4.5/5.0
Behavior5/5

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

Even though no annotations are provided, the description discloses several important behaviors: integers are raw and unmapped, page size is capped at 50 and over-large requests are refused rather than clamped, and the tool is read-only. It also warns about inspecting file_name and file_length_bytes before treating a file as a content pack, and flags the v0 field-path verification status. This goes well beyond minimal behavioral disclosure.

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?

Three sentences with dense information and no filler. It front-loads the core purpose, then provides the most important caveats. It could arguably be split for readability, but each clause carries meaningful detail. The final 'v0' note is a valuable trust signal rather than noise.

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 no output schema and no annotations, the description fills in the most important gaps: raw integer behavior, the 50-item cap, refusal rather than clamping, and read-only status. It lacks explicit return-value shape details, but with pagination and field names mentioned, an agent can infer the entry structure. Sibling tools like get_mod_file might provide the targeted-file alternative, but the description is sufficient for deciding when to call this 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 schema already covers 100% of parameters with descriptions. The tool description complements this by explaining the key semantics of page_size (refused rather than clamped) and the raw integer caveat for the values returned. It doesn't redundantly repeat every parameter, but it adds meaningful context about how the parameters affect behavior.

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 names a specific verb ('List'), a resource ('published files for one mod'), and the pagination aspect. Distinct from siblings like get_mod_file or get_latest_file because it covers all published files for a mod rather than a single targeted file. It also clearly contrasts read-only behavior without any ambiguity.

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 implicitly indicates when to use this tool — when you need all published files for a mod, with pagination and dependency metadata — versus siblings like get_latest_file or get_mod_file which focus on specific files. It does not explicitly name alternatives, but it explains what this tool uniquely provides. The field-path caveat at the end ('v0: all field paths unverified') gives honest guidance about trust.

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

resolve_mod_dependenciesResolve a mod dependency tree (batched)A

Walk the dependency graph of one or more mods breadth-first, issuing ONE bulk POST per level rather than one GET per node. Returns every reachable mod with the raw relationType integer on each edge. IMPORTANT: this OVER-COLLECTS. CurseForge publishes no value table for relationType (ADR-002 §14.3 U6), so required, optional, tool and incompatible edges cannot be told apart and ALL are followed. Bounded at depth 4 and 400 nodes; when a bound is hit the result is reported as TRUNCATED with the unexplored frontier listed, never silently cut. Read-only. v0: all field paths unverified.

NameRequiredDescriptionDefault
mod_idsNoSeed mod ids. At least one of mod_ids or file_ids is required. At most 200.
file_idsNoSeed FILE ids, resolved through POST /v1/mods/files to find the mods they belong to before the walk begins. Use this when you know which file you are running. At most 200.
max_depthNoHow many levels to walk. Default and maximum 4.

TDQS

A4.5/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and succeeds: it discloses read-only behavior, highlights over-collection with 'IMPORTANT', states bounds (depth 4, 400 nodes), and explains truncation with the 'unexplored frontier' listed. It also flags 'v0: all field paths unverified', which is valuable risk context.

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?

Five dense, purposeul sentences cover algorithm, result shape, caveat, bounds, truncation, safety, and maturity. The IMORTANT warning is front-loaded after the primary verb, and there is no filler.

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 tool with no output schema, it specifies the return core: every reachable mod, raw relationType integer per edge, and the TRUNCATED/frontier behavior. It also explains why over-collection occurs and how seeds work via file_ids, leaving no material gap for safe invocation.

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?

Schena description coverage is 100%, with detailed descriptions for mod_ids, file_ids, and max_depth. The main description primarily adds algorithm context (breadth-first, batched POST) but does not add new parameter semantics beyond what the schema already provides, so the baseline 3 is appropriate.

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 opens with 'Walk the dependency graph of one or more mods breadth-first', giving a specific verb and resource. It clearly distinguishes itself from sibling tools by emphasizing batched bulk POST resolution rather than per-node GETs. Nothing is vague or tautological.

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?

It provides clear context: use when you need to resolve a dependency tree, and the file_ids parameter includes the explicit guidance 'Use this when you know which file you are running.' It does not explicitly name sibling alternatives or exclusions, but the intended use case is unambiguous.

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

search_modsSearch ARK: Survival Ascended modsA

Search the CurseForge catalog for ARK: Survival Ascended mods. The gameId is resolved at runtime from GET /v1/games and is not a parameter — a wrong gameId returns a clean, empty, wrong result set rather than an error. Page size is capped at 50 by CurseForge and an over-large request is REFUSED rather than clamped, so that a page is never mistaken for a complete set. Every result states its pagination and whether more results exist, and says so explicitly when the tail of the result set is beyond the API's addressable window. class_id, category_id, and category_ids are include filters sent to CurseForge (discover ids via list_categories). exclude_category_ids is applied locally after the page returns — CurseForge has no exclude parameter — so pagination still describes the unfiltered upstream page. A hit is a catalog row, not an install: inspect file_name and file_length_bytes, then hand curseforge_mod_ids to nitrado-ark-mcp. Read-only.

NameRequiredDescriptionDefault
slugNoExact mod slug, when you already know it.
indexNoZero-based result offset. index + page_size must not exceed 10000.
class_idNoInclude: CurseForge section/class id. Discover via list_categories (is_class true).
page_sizeNoResults per page, at most 50. Over that is refused, not clamped.
sort_fieldNoCurseForge sort field, an integer 1-12 (documented range; the per-value meanings are not).
sort_orderNoSort direction.
category_idNoInclude: a single category id. Do not also pass category_ids.
category_idsNoInclude: up to 10 category ids. Overrides category_id at the vendor; this server refuses both at once rather than letting one silently win.
game_versionNoFilter to files supporting this game version string. UNVERIFIED: whether ASA mods populate game version fields at all is ADR-002 §14.3 U9.
search_filterNoFree-text search term, matched by CurseForge against mod names.
exclude_category_idsNoLOCAL exclude after the page returns. CurseForge cannot exclude. Pagination still describes the unfiltered upstream page. For gameplay-only, list_categories then pass Custom Cosmetics' id.

TDQS

A4.8/5.0
Behavior5/5

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

With no annotations, the description carries full responsibility and delivers extensively: it states runtime gameId resolution, page_size refusal rather than clamping, explicit pagination semantics, local application of exclude_category_ids, the read-only nature, and even a caveat that game_version behavior is unverified. This goes far beyond a typical tool description.

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 dense but every sentence earns its place: core purpose first, then edge cases, filter semantics, and output interpretation. It front-loads the main action and ends with a compact 'Read-only.' without repeating any schema information.

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?

Given the tool's complexity—11 optional parameters, no output schema, and no annotations—the description provides enough context for correct invocation and result interpretation. It explains the lack of a gameId parameter, pagination behavior, local filtering effects, and the key output fields (file_name, file_length_bytes, curseforge_mod_ids) to pass downstream.

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

Parameters5/5

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

Even though schema coverage is 100%, the description adds meaningful behavior beyond the schema: it distinguishes include filters sent to CurseForge from locally applied excludes, warns that category_ids overrides category_id and that passing both is refused, and notes that page_size over 50 is refused rather than clamped. This materially improves the agent's ability to pass parameters correctly.

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 opening sentence 'Search the CurseForge catalog for ARK: Survival Ascended mods' names a specific verb, resource, and context, making the action unmistakable. It also differentiates from sibling tools like get_mod and list_mod_files by describing a catalog-level search with paginated results rather than a single-resource lookup.

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 concrete cross-tool guidance, directing users to discover filter IDs via list_categories and providing a specific example for gameplay-only excludes. It does not explicitly state when to prefer this tool over get_mod or get_latest_file, but the search semantics and pagination make the intended context clear.

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. 8 tool updatesv0.2.0
    • First observedget_api_diagnostics
    • First observedget_latest_file
    • First observedget_mod
    • First observedget_mod_file
    • First observedlist_categories
    • First observedlist_mod_files
    • First observedresolve_mod_dependencies
    • First observedsearch_mods

TDQS

A4.5/5.0

Scored across 8 tools

Disambiguation5/5

Each tool targets a clearly distinct resource and action: categories, mod search, single mod, file listing, single file, latest file, dependency graph, and diagnostics. Even the file-related tools are cleanly separated by purpose, with no two tools being interchangeable.

Naming Consistency5/5

Tool names consistently follow a lowercase snake_case verb_noun pattern: list_*, search_*, get_*, resolve_*. There are no mixed conventions, vague single-word verbs, or unpredictable naming styles.

Tool Count5/5

Eight tools is well-scoped for a read-only CurseForge catalog server. Each tool earns its place, covering browsing, retrieval, dependency resolution, and diagnostics without redundant utilities or unnecessary bloat.

Completeness4/5

The server covers the domain thoroughly: category discovery, mod search, mod details, file listing, single-file retrieval, latest-file comparison, dependency traversal, and diagnostics. The deliberate absence of a download URL is consistent with the stated curation-only purpose, but minor gaps such as no file-level search or changelog endpoint prevent a perfect completeness score.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    Not graded
    maintenance
    An MCP server for Arma Reforger and Enfusion engine modding that enables users to create mods, search API classes, and generate scripts through natural language. It provides a comprehensive suite of tools for scaffolding addons, generating prefabs, and building projects using the Workbench CLI.
    63 npm
    14
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    A local MCP server for Nexus Mods mod discovery and research, backed by the v2 GraphQL API, enabling search of games, mods, collections, and users.
    231 npm
    1
    ISC