CurseForge ARK MCP Server
curseforge-ark-mcp
Ein schreibgeschützter MCP-Server für die Kuratierung, Entdeckung und Update-Überwachung von ARK: Survival Ascended-Mods auf CurseForge.
DIES IST IMMER NOCH v0 — TEILWEISE VERIFIZIERT, NICHT VERIFIZIERT.
Was sich am 18.08.2026 geändert hat: Der CurseForge-API-Schlüssel ist eingetroffen, der Client hat seine ersten authentifizierten Aufrufe getätigt, und jeder
Mod- undFile-Feldpfad, den er liest, wurde in Live-Antworten bestätigt. Keiner musste korrigiert werden. Stichprobe: 748 verschiedene ARK: Survival Ascended-Mods, 1899 Dateidatensätze.Warum es immer noch v0 ist. Vier Dinge bleiben unbestätigt, und eines davon kann nicht durch Hinschauen bestätigt werden:
Die
FileDependency-Kantenform wurde nie beobachtet – 0 von 1899 gesampelten ASA-Dateien deklarierten eine Abhängigkeit, wobei dasdependencies-Array jedes Mal vorhanden und leer war.Die
FileRelationType-Ganzzahlen sind unveröffentlicht und in diesem Katalog nicht verwendet.Die
FileReleaseType-Ganzzahlen1,2und3wurden nun gesehen. Welche davon Release, Beta oder Alpha bedeutet, ist noch unbekannt, und dieser Server wird nicht raten.Eine Anbieterobergrenze für Bulk-Read-ID-Arrays: keine gefunden bis zu 300 IDs, also ist keine bekannt.
Ein teilweise verifizierter Client ist kein verifizierter. Die Versionsnummer ist eine Aussage über den Verifizierungsstatus, also ist sie
0.2.0– nicht1.0.0und bewusst nicht1.0.0-irgendwas.
Das Verhalten dieses Repos wird unabhängig von der API verifiziert: die Endpunkt-Whitelist, der
Host-Pin, die Pfadnormalisierung, die Paginierungsgrenzen, die Envelope-Behandlung und die
Drei-Zustands-Disziplin (fehlend/leer/unbekannt). All dies wird gegen einen injizierten Fake-
fetch getestet, ohne Schlüssel und ohne Netzwerk. 156 Tests, 0 Fehler zum Zeitpunkt der Erstellung.
Design-Dokument: docs/adr/ADR-002-endpoint-allow-list.md
(Status: VORGESCHLAGEN). Jeder Abschnittsverweis unten (§1, §4.3, §14.3 …) verweist darauf.
Related MCP server: neoforge-kb-mcp
Was es tut und was es bewusst nicht kann
Sieben Tools, alle schreibgeschützt:
Tool | Antworten |
| "Welche ASA-Mods passen zu diesem Begriff?" |
| "Was ist Projekt 777001?" |
| "Welche Dateien hat dieser Mod veröffentlicht?" |
| "Was ist diese bestimmte Datei?" |
| "Gibt es eine neuere Datei für diesen Mod als die, die ich ausführe?" |
| "Was zieht dieser Mod nach?" (gebündelt, eine Anfrage pro Baumebene) |
| "Liegt es an mir, am Schlüssel oder an CurseForge?" – und "wie ehrlich ist dieser Build?" |
Es kann nicht:
Etwas herunterladen oder installieren.
GET /v1/mods/{modId}/files/{fileId}/download-urlist ein dokumentierter Lesezugriff auf dem gepinnten Host und wird abgelehnt – weil er nicht auf der Endpunkt-Whitelist steht (DEC-002 §11.3). Nitrado installiert Mods selbst.Irgendwo etwas schreiben. Kein Whitelist-Eintrag nennt einen mutierenden Endpunkt. CurseForge betreibt eine mutierende Upload-API auf einem anderen Host (§14.2); der Host-Pin lehnt sie ein zweites Mal aus einem unabhängigen Grund ab.
Einen Mod veröffentlichen oder erstellen. Wird rundweg abgelehnt (DEC-002, Entscheidung 2). Durchgesetzt durch eine Startbehauptung, nicht durch ein Versprechen: Das Registrieren eines Tools, das etwas anderes als Stufe 1 deklariert, führt dazu, dass der Prozess nicht startet.
Nitrado berühren. Es gibt keine
NITRADO_*-Variable in der Konfigurationsoberfläche dieses Repos, und ihr Fehlen ist eine Kontrolle. Dieser Server besitzt kein Nitrado-Token und liest keine Nitrado-Konfiguration.Auf einem Timer aufwachen und Ihren Server aktualisieren. Kein Scheduler, keine Polling-Schleife, kein persistierter "zuletzt gesehener Versions"-Zustand (§10). Überwachung bedeutet, dass das Modell eine neue Version beobachten darf. Es darf nicht handeln.
Der Engpass: eine Endpunkt-Whitelist, keine Methodenprüfung
Dies ist die eine Designentscheidung, die es wert ist, gelesen zu werden, bevor man den Code anfasst.
CurseForge verwendet POST zum LESEN. POST /v1/mods und POST /v1/mods/files sind Bulk-
Abrufe, und sie sind es, die resolve_mod_dependencies eine Anfrage pro Abhängigkeits-Ebene
kosten lassen, statt eine pro Knoten. Daher würde die method !== "GET" → refuse-Regel des
Schwester-Repos hier auf die teuerste Art und Weise scheitern: Sie würde funktionieren. Sie würde
Dinge ablehnen, ihre eigenen Tests bestehen und den Server leise schlecht in seiner Aufgabe machen.
Und die offensichtliche Korrektur ist schlimmer als der Fehler:
allowed = { GET } → the batch reads are refused (broken, loudly)
allowed = { GET, POST } → every request this client can construct is allowedDie dokumentierte Katalog-API enthält nur GET und POST. Ein Tor, das beide zulässt, lässt
alles zu – während es weiterhin präsent aussieht.
Stattdessen muss jede ausgehende Anfrage mit einem expliziten Eintrag in einer geschlossenen Liste von
{method, path}-Paaren übereinstimmen. Sieben Einträge in src/allowlist.ts:
# | Methode | Pfad | Dient |
E1 |
|
| Spiel-ID-Auflösung, |
E2 |
|
|
|
E3 |
|
|
|
E4 |
|
|
|
E5 |
|
|
|
E6 |
|
|
|
E7 |
|
|
|
Mechanisch:
Abgeglichen auf
{method, path}gemeinsam. E3 autorisiert nichtDELETE /v1/mods/123. E6 autorisiert nichtPOST /v1/mods/123.Der Host ist gepinnt auf
https://api.curseforge.com, und der Pin ist eine Erlaubnis für einen Ursprung, keine Ablehnung eines benannten anderen.ID-Segmente binden an
[0-9]+, nicht an[^/]+. Dies ist tragend: Ein permissives{modId}lässt E3/v1/mods/searchverschlucken. Die numerische Bindung macht diese Mehrdeutigkeit strukturell unmöglich, anstatt sie von der Reihenfolge des Abgleichs abhängig zu machen – und es gibt einen Test, der die gesamte Liste umkehrt, um zu beweisen, dass die Reihenfolge nicht das ist, was sie rettet.Eine Normalisierung vor der Prüfung, und die URL wird aus ihrer Ausgabe erstellt. Prozent- Dekodierung einmal; jedes überlebende
%ablehnen; Backslashes umwandeln;.,..und leere Segmente ablehnen.Nur E6/E7 dürfen einen Body tragen, der vor dem Versand auf seine Form geprüft wird. Ein Body bei einem GET-Eintrag wird abgelehnt, nicht verworfen.
Nur
resolve_mod_dependenciesdarf einen POST-Eintrag erreichen (§8), durchgesetzt im Transport.
Die Fehlerart ist "nicht übereinstimmende Anfrage abgelehnt", niemals "unerkannte Anfrage gesendet." Und das Hinzufügen einer Fähigkeit ist ein überprüfbarer Einzeiler-Diff, dessen Überprüfungsfrage – "Ist dieser Endpunkt ein Lesezugriff?" – eine ist, die ein Mensch tatsächlich beantworten kann.
Der Test, der beweist, dass es eine Whitelist ist
GET /v1/mods/{modId}/files/{fileId}/download-url wird abgelehnt. Es ist ein dokumentierter
Lesezugriff, ein GET, auf dem gepinnten Host, mit wohlgeformten numerischen IDs. Es wird abgelehnt,
ausschließlich weil es nicht auf der Liste steht. Wenn dieser Test jemals aus einem anderen Grund
besteht – einer Host-Pin-Ablehnung, einer Pfad-Ablehnung – ist die Eigenschaft nicht implementiert,
also behauptet der Test den Code und das Detail der Ablehnung, nicht nur, dass irgendetwas geworfen wurde.
Jeder Ablehnungstest behauptet auch die Aufrufanzahl des Fake-fetch, denn "abgelehnt, bevor die
Anfrage erstellt wird" ist die tatsächliche Bestimmung, und ein Fehler, der nach dem Versand geworfen
wird, würde eine schwächere Behauptung erfüllen. Und der Ablehnungssuite geht ein Urbild-Test voraus,
der beweist, dass alle sieben Einträge tatsächlich versenden – eine Ablehnungssuite über einen Client,
der nichts senden kann, besteht perfekt und beweist nichts.
Verifiziert gegen die Live-API – 18.08.2026
Stichprobe: 748 verschiedene ASA-Mods, 1899 Dateidatensätze, entnommen aus tiefen Suchseiten
(Index 1000-6000) und aus jedem dokumentierten sortField 1-12, plus vollständige Dateilisten für 100 Mods.
Absichtlich datiert und bemessen: "Verifiziert" ohne Stichprobengröße ist eine Stimmung, keine Behauptung.
# | Behauptung | Ergebnis |
U1 | Die ASA |
|
U2 | Ist ASA für den Schlüssel sichtbar? | Ja. 38 Spiele sichtbar, ASA darunter. Nicht v1-blockierend. |
U3 |
| Alle korrekt. |
U4 |
| Alle korrekt. |
U8 |
| Vorhanden bei den paginierten Endpunkten (Spiele, Suche, Dateien), abwesend bei Einzeldatensatz- und Bulk-Reads – genau die Aufteilung, die dieser Client zu erwarten gebaut wurde. |
U9 | Befüllen ASA-Mods die optionalen Felder? |
|
U11 | Rate-Limit-Header | CurseForge sendet keine. Vollständige Header-Aufzählung bei einem Live-GET und -POST ergab nur Transport-/CDN-Header. Also ist |
U12 | Paginierung über Index 0 hinaus | Funktioniert; |
U13 | Basis-URL | Korrekt. Der Host-Pin ist solide. |
Es musste kein Feldpfad korrigiert werden. Das wird als Ergebnis und nicht als Angeberei festgehalten: Der Commit 5481c04 des Schwester-Repos korrigierte drei falsche Pfade an dem Tag, an dem es zum ersten Mal live aufgerufen wurde, und dieser Präzedenzfall ist der Grund, warum jeder Pfad hier einzeln überprüft wurde, anstatt ihm zu vertrauen.
Noch nicht verifiziert
Geschrumpft, nicht verschwunden. Dies sind die Zeilen, die den Kontakt mit der Live-API überlebt haben.
# | Anspruch | Status | Grund für die Offenheit |
U5 |
| Unbeobachtet | Nicht als falsch gezeigt – nie gesehen. Keine ASA-Datei in der Stichprobe deklarierte eine Abhängigkeit, daher wurde noch nie ein Edge-Objekt inspiziert. Die Form stammt aus der Dokumentation, und die Test-Fixtur ist der einzige Ort, an dem sie existiert. |
U6 | Der numerische Enum | Unveröffentlicht UND hier nicht beobachtbar |
|
U7 | Der numerische Enum | Werte gesehen, Bedeutung unbekannt | Beobachtet: |
U10 | Anbieter-Obergrenze für Bulk-Read-ID-Arrays | Keine Obergrenze bis 300 gefunden | 200 verschiedene IDs gaben 200 Datensätze zurück; 300 gaben 300 zurück. Die Obergrenze liegt also, falls vorhanden, über 300. Die 200-ID-Obergrenze in diesem Client bleibt bestehen: Sie ist unsere, bewusst konservativ gegenüber einem undokumentierten Ratenlimit, und ein Test, der keine Obergrenze fand, hat die Obergrenze nicht gefunden. |
Zwei Konsequenzen, die Sie in der Tool-Ausgabe sehen werden
relationType und releaseType werden als rohe Ganzzahlen ausgegeben und niemals abgebildet. Weder auf required/optional, noch auf release/beta/alpha. CurseForge veröffentlicht für keine der beiden eine Wertetabelle, und eine falsche Bezeichnung würde eine Abhängigkeitsliste – oder eine Update-Empfehlung – erzeugen, die auf eine Weise falsch ist, die niemand überprüfen würde. resolve_mod_dependencies folgt daher jeder Kante und sagt dies: Es sammelt übermäßig, und seine Ausgabe stellt dies klar dar. Ein weites Netz ist zumindest sichtbar weit.
Speziell für ASA macht der Live-Katalog dies in einer Weise hinfällig, die Sie kennen sollten, bevor Sie das Tool verwenden: Kein getesteter ASA-Mod deklariert irgendeine Abhängigkeit. Ein Einzelknoten-Baum ist das erwartete Ergebnis, kein Symptom einer defekten Traversierung, und die Ausgabe des Tools gibt an, um welches es sich handelt.
get_latest_file erfordert, dass Sie sagen, was "neueste" bedeutet. Das Neueste nach fileDate, das Neueste, das einer Spielversion entspricht, und das Neueste mit einem bestimmten releaseType geben unterschiedliche Antworten, und eine Mod-Update-Entscheidung, die auf der falschen basiert, ist genau die Klasse von selbstbewusst-falschen Antworten, gegen die dieses Repo angelegt ist. selection hat keinen Standardwert:
| Erfordert außerdem | Bedeutung |
| — | Neueste aller Kandidatendateien, nach |
|
| Neueste Datei, die diese Spielversion deklariert |
|
| Neueste Datei mit dieser Release-Typ-Ganzzahl |
Es gibt keinen benannten release/beta/alpha-Filter, weil U7 ungelöst ist und dieser Server die Abbildung nicht erfinden wird. Sie übergeben die Ganzzahl, die Sie meinen.
Diese Definition ist eine OFFENE PRODUKTFRAGE. Die offene Frage 2 von ADR-002 kennzeichnet sie als eine Gründungsentscheidung, die noch nicht getroffen war, als dies gebaut wurde, daher ist das Tool parametrisiert statt meinungsstark: Wenn die Antwort eintrifft, wird sie zu einem Standardwert oder einer Variante weniger – eine kleine Änderung statt einer Neuschreibung. Jede Antwort wiederholt die verwendete Sortierung, worauf gefiltert wurde, wie viele Kandidaten berücksichtigt wurden und woher die Kandidaten stammen.
Einrichtung
Node 20+ (entwickelt auf 22). Kein Build-Schritt zu konfigurieren; npm test baut zuerst.
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 onenpm run smoke ist der Falsifikationsdurchlauf, kein Health-Check. Mit einem Schlüssel durchläuft es das §14.3-Register Zeile für Zeile und gibt das Beobachtete aus; ohne einen benennt es jede Sonde, die es gemacht hätte, und beendet sich mit 0, ohne etwas gesendet zu haben. Die Testsuite berührt in keinem Fall das Netzwerk.
MCP-Client-Konfiguration (stdio):
{
"mcpServers": {
"curseforge-ark": {
"command": "node",
"args": ["C:/path/to/curseforge-ark-mcp/dist/src/server.js"],
"env": { "CURSEFORGE_API_KEY": "your-key" }
}
}
}Der Server weigert sich, ohne einen Schlüssel zu starten, und nennt dabei beide Orte, die er durchsucht hat, die genaue Variable und die Tatsache, dass der Schlüssel nicht selbstbedient ist. Ein stdio-MCP-Server, der sauber startet und dann bei allen sieben Tools Fehler wirft, ist ein elendiges Debugging-Erlebnis.
Über den Schlüssel
Der API-Schlüssel wird als x-api-key-Request-Header gesendet. Es handelt sich nicht um ein Authorization: Bearer-Token – das ist das Schema des Schwester-Nitrado-Servers, und dieses Repo unterstützt bewusst nicht beides, da die Unterstützung beider bedeuten würde, dass dieser Code die Anmeldedaten in einer Form übertragen könnte, die CurseForge nie dokumentiert hat.
Der Schlüssel wird durch die Anwendung an Overwolf vergeben und ist nicht übertragbar. Die praktische Konsequenz und der einzige Grund, warum dieser Absatz existiert: Ein Leck bedeutet Widerruf und erneute Beantragung, und die erneute Beantragung ist eine Warteschlange, kein Self-Service-Reset. Sie können ihn nicht auf die Schnelle neu generieren und auch nicht den eines anderen ausleihen. Behandeln Sie ihn entsprechend – .env ist gitignoriert, .env.example trägt den Variablennamen und einen leeren Wert, und kein Schlüsselwert erscheint in einer committeten Datei.
Es gibt in diesem Repo keine Scope-Matrix, und das ist kein Versehen: CurseForge veröffentlicht keinen Read-Only-Scope und keine Scope-Auswahl, daher gibt es nichts zu matrixen. Die Read-Only-Eigenschaft dieses Servers stammt von seiner eigenen Endpunkt-Whitelist, nicht von einer engeren Anmeldeinformation. Es gibt auch kein Token-Leak-Runbook – ein durchgesickerter Schlüssel gewährt Lesezugriff auf einen öffentlichen Katalog plus Kontingentverbrauch, was real ist, aber nicht in dieselbe Kategorie fällt wie das Nitrado-Token des Schwester-Repos (dokumentiert als gleichwertig mit vollständiger Kontrolle über einen Spielserver). Diese richtige Größenordnung wird in ADR-002 §12 argumentiert, und sie stützt sich auf eine dort gemachte Behauptung, damit sie falsifiziert werden kann: CurseForge-Katalogdaten sind von Natur aus öffentlich.
Schwärzung, alles davon
Eine Regel: niemals den API-Schlüssel ausgeben. Eine Funktion, src/scrub.ts, angewendet auf Fehlermeldungen und auf jeden Quelltext-Ausschnitt von vorgelagerten Systemen. Request-Header erscheinen niemals in Fehlern – nicht der Schlüssel, nicht ein geschwärzter Schlüssel, nicht eine Liste von Header-Namen. get_api_diagnostics meldet, ob ein Schlüssel konfiguriert ist, und niemals seinen Wert, ein Präfix davon oder seine Länge.
Verhaltensweisen, die Sie vor dem Lesen der Ausgabe kennen sollten
Leer ist nicht unbekannt.
data: []bedeutet, CurseForge hat mit "keine" geantwortet – eine echte Antwort, mit der wiederholten Abfrage, damit Sie sehen, was nichts zurückgegeben hat. Ein fehlendes Feld istnull, niemals0,""oder[]. Eine Anfrage, die nicht abgeschlossen wurde, oder eine Antwort, deren Form falsch ist, ist ein Fehler – niemals ein Wert.Ein fehlender
data-Schlüssel ist ein Fehler, kein leeres Ergebnis. Ihn zu[]zu zwingen, würde eine defekte Integration in "keine Ergebnisse gefunden" verwandeln.Ein fehlendes
paginationbei einem paginierten Endpunkt ist ebenfalls ein Fehler. Die Annahme einer Seite wäre, wie ein Tool 50 von 900 Mods meldet, als ob es alle wären (U8 ist genau diese offene Frage).pageSize > 50wird abgelehnt, nicht beschnitten, ebenso wieindex + pageSize > 10000– mit der größten zulässigen Seitengröße bei diesem Index, die in der Nachricht genannt wird. Ein Modell, das 200 anfordert und stillschweigend 50 erhält, wird über eine Seite argumentieren, als ob es eine Menge wäre.Wenn
totalCount10000 übersteigt, sagt die Tool-Ausgabe, dass der Rest UNERREICHBAR ist, in diesen Worten, und rät, den Filter zu verengen, anstatt zu blättern.Die ASA
gameIdwird zur Laufzeit ermittelt ausGET /v1/gamesund für die Prozesslebensdauer zwischengespeichert; sie ist niemals fest codiert und niemals geraten. Wenn sie nicht aufgelöst werden kann, scheitert der Server lautstark und nennt, wonach er gesucht hat und wie viele Spiele der Schlüssel sehen konnte – denngameIdist ein erforderlicher Suchfilter, sodass eine falsche ID saubere, leere, völlig falsche Ergebnisse anstelle eines Fehlers zurückgibt. Setzen SieCURSEFORGE_GAME_SLUG, wenn sich die eingebauten Kandidaten als falsch herausstellen.resolve_mod_dependenciesist begrenzt auf Tiefe 4 und 400 Knoten, mit einer Besuchsmenge für Zyklen. Wenn eine Grenze erreicht wird, wird das Ergebnis als truncated (abgeschnitten) gemeldet, in diesem Wort, mit der Liste der unerforschten Grenze.
Repo-Struktur
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 enumeratorsrc/buildinfo.ts ist generiert und gitignoriert, mit dem Commit und einem dirty-Flag vor jedem tsc-Lauf gestempelt und von get_api_diagnostics ausgegeben. dist/ ist gitignoriert und der Server läuft daraus als langlebiger Prozess, daher ist "welcher Code hat diese Antwort produziert?" zur Laufzeit nicht aus git beantwortbar – es muss mit dem Artefakt reisen.
Abweichungen vom Schwester-Repo, bewusst formuliert
Die offenen Fragen 7 und 8 von ADR-002 verlangen, dass diese dort benannt werden, wo sie auftreten:
Gleiche Basis, bewusst. Node ≥20, TypeScript 5.9.3,
@modelcontextprotocol/sdk1.30.0,zod4.4.3,node:testüber denselbenscripts/run-tests.mjs-Enumerator. Gleicher Prüfer, gleiche Redewendungen, geringere Lesekosten für beide.@cfworker/json-schemaist hier keine Abhängigkeit. Es unterstützt die Cron-Ausdrucksvalidierung des Schwester-Repos, und es gibt keinen Schreibpfad zu validieren.registry.tsist in der Struktur portiert und behälttier, lässt aber den Modus/Aktivierungslisten-Mechanismus weg – er hätte nichts zu filtern, da jedes Tool Tier 1 und jeder Endpunkt ein Lesezugriff ist. Eine Modusvariable ohne dahinterstehenden Inhalt bewirbt eine Steuerung, die nicht existiert. Eine fünfzeilige Boot-Überprüfung ersetzt das Subsystem.redact.tsist nicht portiert (§12.1). Siehe "Schwärzung, alles davon" oben.Kein
UNKNOWN_OUTCOME-Fehlercode. Das Schwester-Repo benötigt ihn, weil eine verlorene Antwort auf einenPUTdie Welt trotzdem verändert haben könnte. Jede Anfrage, die dieser Client stellen kann, ist ein Lesezugriff, daher bedeutet ein Timeout tatsächlich "es ist nicht passiert" und ein Wiederholungsversuch ist sicher.npm run smokebeendet sich mit 0, wenn es sich wegen eines fehlenden Schlüssels weigert. Die Weigerung ist das erwartete Ergebnis, wenn man es heute ausführt, und der Banner sagt unübersehbarSMOKE NOT RUN. Wenn Sie möchten, dass eine Pipeline bei einem fehlenden Schlüssel fehlschlägt, gaten Sie die Pipeline auf den Schlüssel und nicht auf diesen Exit-Code.
Verwandte Aufzeichnungen
Im Schwester-Repository nitrado-ark-mcp nur lesend von hier aus – nichts in diesem Repository wurde durch dieses hier verändert:
docs/decisions/EXECUTIVE-BOARD-2026-08-16-curseforge-mods.md– die Vorstandsprotokolle (DEC-002), die dieses Repository umsetzt. Dessen Chair-Rulings sind bindend.docs/decisions/decision-log.md– DEC-002 und DEC-001 für die Aufgabenteilung, auf der §10 beruht.docs/adr/ADR-001-write-path-enforcement.md– die Form, die ADR-002 überträgt, sowie die Quelle der Normalisierungsregel, der Boot-Check-Begründung und der Weigerung-zu-starten-Begründung.
Die beiden Server bleiben unabhängig. nitrado-ark-mcp antwortet "diese Projekt-IDs sind in active-mods"; dieses Repository antwortet "die neueste Datei von Projekt X ist v2.1". Das Modell hält beide. Kein Server ruft den anderen auf, und keiner besitzt jemals die Anmeldedaten des anderen.
Available Tools
8 toolsget_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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| mod_id | Yes | CurseForge numeric mod (project) id. | |
| selection | No | Which 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_version | No | Required 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_type | No | Required 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
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| mod_id | Yes | CurseForge numeric mod (project) id. Digits only — the allow-list will not match anything else. |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| mod_id | Yes | CurseForge numeric mod (project) id. Digits only — the allow-list will not match anything else. | |
| file_id | Yes | CurseForge numeric file id. |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| class_id | No | Restrict to categories under this class id. Discoverable from a classes_only call. | |
| classes_only | No | When true, return only top-level classes for the game, not every nested category. |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| index | No | Zero-based offset. index + page_size <= 10000. | |
| mod_id | Yes | CurseForge numeric mod (project) id. Digits only — the allow-list will not match anything else. | |
| page_size | No | At most 50. Over that is refused, not clamped. | |
| game_version | No | Filter to files supporting this game version string. UNVERIFIED (§14.3 U9). |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| mod_ids | No | Seed mod ids. At least one of mod_ids or file_ids is required. At most 200. | |
| file_ids | No | Seed 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_depth | No | How many levels to walk. Default and maximum 4. |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| slug | No | Exact mod slug, when you already know it. | |
| index | No | Zero-based result offset. index + page_size must not exceed 10000. | |
| class_id | No | Include: CurseForge section/class id. Discover via list_categories (is_class true). | |
| page_size | No | Results per page, at most 50. Over that is refused, not clamped. | |
| sort_field | No | CurseForge sort field, an integer 1-12 (documented range; the per-value meanings are not). | |
| sort_order | No | Sort direction. | |
| category_id | No | Include: a single category id. Do not also pass category_ids. | |
| category_ids | No | Include: up to 10 category ids. Overrides category_id at the vendor; this server refuses both at once rather than letting one silently win. | |
| game_version | No | Filter to files supporting this game version string. UNVERIFIED: whether ASA mods populate game version fields at all is ADR-002 §14.3 U9. | |
| search_filter | No | Free-text search term, matched by CurseForge against mod names. | |
| exclude_category_ids | No | LOCAL 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
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.
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.
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.
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.
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.
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.
8 tool updates
v0.2.0- First observed
get_api_diagnostics - First observed
get_latest_file - First observed
get_mod - First observed
get_mod_file - First observed
list_categories - First observed
list_mod_files - First observed
resolve_mod_dependencies - First observed
search_mods
TDQS
Scored across 8 tools
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.
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.
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.
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
Related MCP Connectors
MCP registry & directory: search, find & install 31k+ MCP servers & tools. Catalog and marketplace.
MCP server for developer documentation, generated by doc2mcp.
MCP server for dev documentation, generated by doc2mcp.
A MCP server built for developers enabling Git based project management with project and personal…
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceAn 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 npm14-
- AlicenseNot gradedqualityDmaintenanceMCP server that provides RAG-based access to Neoforge Mod API documentation, enabling LLMs to query the latest Neoforge modding knowledge.2MIT
- AlicenseNot gradedqualityCmaintenanceA local MCP server for Nexus Mods mod discovery and research, backed by the v2 GraphQL API, enabling search of games, mods, collections, and users.149 npm1ISC
- AlicenseBqualityBmaintenanceMCP server for Forge Minecraft modding documentation. Gives AI assistants direct access to Forge docs with structured search results.53 npm3AGPL 3.0