Skip to main content
Glama

curseforge-ark-mcp

A read-only MCP server for CurseForge mod curation, discovery, and update surveillance for ARK: Survival Ascended.

THIS IS STILL v0 — PARTIALLY VERIFIED, NOT VERIFIED.

What changed on 2026-08-18: the CurseForge API key arrived, the client made its first authenticated calls, and every Mod and File field path it reads was confirmed present in live responses. None needed correcting. Sample: 748 distinct ARK: Survival Ascended mods, 1899 file records.

Why it is still v0. Four things remain unconfirmed, and one of them cannot be confirmed by looking:

  • The FileDependency edge shape has never been observed — 0 of 1899 sampled ASA files declared a dependency, with the dependencies array present and empty every time.

  • The FileRelationType integers are unpublished and unexercised in this catalog.

  • The FileReleaseType integers 1, 2 and 3 have now been seen. Which one means release, beta or alpha is still unknown, and this server will not guess.

  • Any vendor cap on bulk-read id arrays: none found up to 300 ids, so none is known.

A partially verified client is not a verified one. The version number is a claim about verification status, so it is 0.2.0 — not 1.0.0, and deliberately not 1.0.0-anything.

This repo's own behaviour is verified independently of the API: the endpoint allow-list, the host pin, the path normalization, the pagination bounds, the envelope handling, and the three-state absent/empty/unknown discipline. All of it is tested against an injected fake fetch, with no key and no network. 169 tests, 0 failures at the time of writing.

Design record: docs/adr/ADR-002-endpoint-allow-list.md (status: ACCEPTED 2026-08-18, with known-open residuals — not a verified catalog). Every section reference below (§1, §4.3, §14.3 …) points into it.


Related MCP server: enfusion-mcp

What it does, and what it deliberately cannot do

Eight tools, all read-only:

Tool

Answers

search_mods

"Which ASA mods match this term?" Include by class/category; exclude locally. A hit is a catalog row, not an install. handoff.curseforge_mod_ids is what to pass to nitrado-ark-mcp.

list_categories

"What class/category ids exist for ASA?" Use this before filtering search.

get_mod

"What is project 777001?" Includes author summary, raw status, dates, and latest file lengths.

list_mod_files

"What files has this mod published?" Includes file_length_bytes.

get_mod_file

"What is this specific file?" Includes file_length_bytes. No download URL.

get_latest_file

"Is there a newer file for this mod than the one I am running?" Inspect file_name and file_length_bytes before treating it as a content pack.

resolve_mod_dependencies

"What does this mod pull in?" (batched, one request per tree level)

get_api_diagnostics

"Is it me, the key, or CurseForge?" — and "how honest is this build?"

It cannot:

  • Download or install anything. GET /v1/mods/{modId}/files/{fileId}/download-url is a documented read, on the pinned host, and it is refused — because it is not on the endpoint allow-list (DEC-002 §11.3). Nitrado installs mods itself. A catalog row with a published file is still not an install recommendation: inspect file_name and file_length_bytes. ASA content packs are typically megabytes to hundreds of megabytes. A few kilobytes is still a published file — this server does not open archives, and it will not invent "removed" from a status integer. allow_mod_distribution false is common on popular ASA mods and is not "taken down."

  • Write anything, anywhere. No allow-list entry names a mutating endpoint. CurseForge does operate a mutating upload API on a different host (§14.2); the host pin refuses it a second time for an independent reason.

  • Publish or author a mod. Refused outright (DEC-002 Ruling 2). Enforced by a boot assertion, not by a promise: registering a tool that declares anything other than tier 1 makes the process refuse to start.

  • Touch Nitrado. No NITRADO_* variable exists in this repo's configuration surface, and its absence is a control. This server holds no Nitrado token and reads no Nitrado config. Collaboration is in the conversation: this MCP returns handoff.curseforge_mod_ids; nitrado-ark-mcp is what would write active-mods. That write is still queued (DEC-002 A6). Embodiment is a later in-game player agent on the founder's Steam account, not a UI that calls both servers.

  • Wake up on a timer and update your server. No scheduler, no polling loop, no persisted "last seen version" state (§10). Surveillance means the model may observe a new version. It does not get to act.


The chokepoint: an endpoint allow-list, not a method check

This is the one design decision worth reading before touching the code.

CurseForge uses POST to READ. POST /v1/mods and POST /v1/mods/files are bulk retrievals, and they are what make resolve_mod_dependencies cost one request per dependency level instead of one per node. So the sibling repo's method !== "GET" → refuse would fail here in the most expensive way possible: it would work. It would refuse things, pass its own tests, and quietly make the server bad at its job.

And the obvious fix is worse than the bug:

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

The documented catalog API contains only GET and POST. A gate admitting both admits everything — while continuing to look present.

So instead, every outbound request must match an explicit entry in a closed list of {method, path} pairs. Seven entries, in src/allowlist.ts:

#

Method

Path

Serves

E1

GET

/v1/games

game-id resolution, 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 (bulk read)

E7

POST

/v1/mods/files

resolve_mod_dependencies (bulk read)

Mechanically:

  • Matched on {method, path} jointly. E3 does not authorise DELETE /v1/mods/123. E6 does not authorise POST /v1/mods/123.

  • The host is pinned to https://api.curseforge.com, and the pin is an allow of one origin rather than a deny of any named other.

  • Id segments bind to [0-9]+, not [^/]+. This is load-bearing: a permissive {modId} makes E3 swallow /v1/mods/search. The numeric binding makes that ambiguity structurally impossible rather than dependent on match order — and there is a test that reverses the whole list to prove ordering is not what saves it.

  • One normalization, before the check, and the URL is built from its output. Percent-decode once; refuse any % that survives; fold backslashes; refuse ., .. and empty segments.

  • Only E6/E7 may carry a body, shape-checked before dispatch. A body on a GET entry is refused, not dropped.

  • Only resolve_mod_dependencies may reach a POST entry (§8), enforced in the transport.

The failure mode is "unmatched request refused", never "unrecognised request sent." And adding a capability is a reviewable one-line diff whose review question — "is this endpoint a read?" — is one a human can actually answer.

The test that proves it is an allow-list

GET /v1/mods/{modId}/files/{fileId}/download-url is refused. It is a documented read, a GET, on the pinned host, with well-formed numeric ids. It is refused purely because it is not on the list. If that test ever passes for some other reason — a host-pin refusal, a path refusal — the property is not implemented, so the test asserts the refusal's code and detail, not merely that something threw.

Every refusal test also asserts the fake fetch's call count, because "refused before the request is built" is the actual provision, and an error thrown after dispatch would satisfy a weaker assertion. And the refusal suite is preceded by a preimage test proving all eight entries do dispatch — a refusal suite over a client that can send nothing passes perfectly and proves nothing.


Verified against the live API — 2026-08-18

Sample: 748 distinct ASA mods, 1899 file records, drawn from deep search pages (index 1000-6000) and from every documented sortField 1-12, plus full file lists for 100 mods. Dated and sized on purpose: "verified" without a sample size is a mood, not a claim.

#

Claim

Result

U1

The ASA gameId

83374, slug ark-survival-ascended, name ARK Survival Ascendedno colon, which an exact-match spelling would have got wrong. Still resolved live on every start; a test asserts the number appears nowhere in src/ outside a comment.

U2

Is ASA visible to the key?

Yes. 38 games visible, ASA among them. Not v1-blocking.

U3

Mod field paths

All correct. id, gameId, name, slug, summary, status, dateCreated, dateModified, dateReleased, links.websiteUrl, authors, categories, allowModDistribution, isAvailable, latestFiles, latestFilesIndexes. summary/status/authors/dates re-confirmed present 2026-08-19.

U4

File field paths

All correct. id, modId, displayName, fileName, fileDate, fileLength, gameVersions, sortableGameVersions, dependencies, releaseType, isAvailable. fileLength re-confirmed present 2026-08-19 (Admin Panel remaining files: 6888 bytes).

U8

pagination presence

Present on the paginated endpoints (games, search, files), absent on single-record and bulk reads. E8 (GET /v1/categories) confirmed live 2026-08-19: {data} only, pagination null. Discover class/category names via list_categories; do not hardcode those ids.

U9

Do ASA mods populate the optional fields?

latestFiles, latestFilesIndexes, sortableGameVersions, gameVersions: 300/300. dependencies: present on 100%, non-empty on 0%.

U11

Rate-limit headers

CurseForge sends none. Full header enumeration on a live GET and POST found transport/CDN headers only. So null is not a matching bug in this client — but it is not a claim that no limit exists, and the self-imposed pacing stays.

U12

Pagination past index 0

Works; totalCount stable at 6848 across pages. But past the end of a result set CurseForge returns resultCount: 0 and totalCount: 0totalCount describes the response, not the query. Tool output now says "past the end" rather than letting that read as "found nothing".

U13

Base URL

Correct. The host pin is sound.

No field path needed correcting. That is recorded as an outcome rather than a boast: the sibling repo's commit 5481c04 fixed three wrong paths the day it first called live, and that precedent is the reason each path here was checked one at a time instead of trusted.

Still unverified

Shrunk, not vanished. These are the rows that survived contact with the live API.

#

Claim

Status

Why it is still open

U5

FileDependency = { modId, relationType }

Unobserved

Not shown wrong — never seen. No ASA file in the sample declared a dependency, so no edge object has ever been inspected. The shape is documentation-derived and the test fixture is the only place it exists.

U6

The FileRelationType numeric enum

Unpublished AND unobservable here

dependencies was present-and-empty on all 1899 files across 748 mods, so no relation integer has ever appeared. ADR-002 predicted this and named the consequence: the unmapped-integer traversal is the answer, not a stopgap. Practical effect: for ASA, resolve_mod_dependencies returns single-node trees, and it now says so in its own output so an empty tree does not read as a failure.

U7

The FileReleaseType numeric enum

Values seen, meanings unknown

Observed: 1 (1893 files), 2 (3), 3 (3). At least three members, consistent with the Upload API's alpha/beta/release trio — and no evidence at all about which integer is which. A frequency distribution is not a value table. Inferring 1 = release because 1 is commonest is the guess this repo exists to refuse.

U10

Vendor cap on bulk-read id arrays

No cap found up to 300

200 distinct ids returned 200 records; 300 returned 300. So the cap, if any, is above 300. The 200-id cap in this client stays: it is ours, deliberately conservative against an undocumented rate limit, and a probe that found no ceiling has not found the ceiling.

Two consequences you will see in tool output

relationType and releaseType are surfaced as raw integers and are never mapped. Not to required/optional, not to release/beta/alpha. CurseForge publishes no value table for either, and a wrong label would produce a dependency list — or an update recommendation — that is wrong in a way nobody would check. resolve_mod_dependencies therefore follows every edge and says so: it over-collects, and its output states that plainly. A wide net is at least visibly wide.

For ASA specifically, the live catalog makes that moot in a way worth knowing before you use the tool: no sampled ASA mod declares any dependency at all. A single-node tree is the expected result, not a symptom of a broken traversal, and the tool's output says which one it is.

get_latest_file defaults to newest by fileDate. Newest by fileDate, newest matching a game version, and newest with a given releaseType still give different answers, and a mod-update decision made on the wrong one is exactly the confident-wrong-answer class this repo is arranged against. The founder settled the default on 2026-08-18: omit selection and you get newest_by_file_date. The other two variants remain. Every answer restates the ordering it used, whether the default was applied, what it filtered on, how many candidates it considered, and where the candidates came from.

selection

Also requires

Means

newest_by_file_date

Default. Newest of all candidate files, by fileDate

newest_matching_game_version

game_version

Newest file declaring that game version

newest_with_release_type

release_type (a raw integer)

Newest file carrying that release-type integer

There is no named release/beta/alpha filter, because U7 is unresolved and this server will not invent the mapping. You pass the integer you mean.

ADR-002 open question 2 is closed as a product decision, not as a verification claim. The tool is still parameterized: the default is one of three stated questions, not a rewrite that deletes the other two.


Setup

Node 20+ (developed on 22). No build step to configure; npm test builds first.

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 is the falsification run, not a health check. With a key it walks the §14.3 register row by row and prints what it observed; without one it names every probe it would have made and exits 0 having sent nothing. The test suite never touches the network in either case.

MCP client configuration (stdio). First-use on this machine is the Cursor user mcp.json entry curseforge-ark. It launches dist/src/server.js and does not put the key in that file: the server loads gitignored .env itself (process.env still wins if an MCP client supplies the variable). Duplicating the key into mcp.json is a second copy of a non-transferable credential.

{
  "mcpServers": {
    "curseforge-ark": {
      "command": "node",
      "args": ["C:/Users/jdsho/CursorProjects/curseforge-ark-mcp/dist/src/server.js"]
    }
  }
}

Disable / rollback: remove the curseforge-ark entry from the MCP client config. This server is first-party stdio, not a Runlayer-managed catalog server.

The server refuses to start without a key, naming both locations it searched, the exact variable, and the fact that the key is not self-service. A stdio MCP server that starts cleanly and then throws on every tool is a miserable thing to debug.

About the key

The API key is sent as an x-api-key request header. It is not an Authorization: Bearer token — that is the sibling Nitrado server's scheme, and this repo deliberately does not support both, because supporting both would mean this code could transmit the credential in a form CurseForge never documented.

The key is granted by application to Overwolf and is non-transferable. The practical consequence, and the only reason this paragraph exists: a leak means revoke and re-apply, and re-application is a queue, not a self-service reset. You cannot regenerate it over coffee and you cannot borrow someone else's. Treat it accordingly — .env is gitignored, .env.example carries the variable name and an empty value, and no key value appears in any committed file.

There is no scope matrix in this repo, and that is not an oversight: CurseForge publishes no read-only scope and no scope selection, so there is nothing to matrix. The read-only property of this server comes from its own endpoint allow-list, not from a narrower credential. There is also no token-leak runbook — a leaked key grants read access to a public catalog plus quota consumption, which is real and is not the same category as the sibling repo's Nitrado token (documented as equivalent to full control of a game server). That right-sizing is argued in ADR-002 §12, and it rests on one claim stated there so it can be falsified: CurseForge catalog data is public by construction.

Redaction, all of it

One rule: never echo the API key. One function, src/scrub.ts, applied to error messages and to any upstream body snippet. Request headers never appear in errors — not the key, not a redacted key, not a header-name list. get_api_diagnostics reports whether a key is configured and never its value, a prefix of it, or its length.


Behaviours worth knowing before you read output

  • Empty is not unknown. data: [] means CurseForge answered "none" — a real answer, with the query echoed so you can see what returned nothing. An absent field is null, never 0, "" or []. A request that did not complete, or a response whose shape is wrong, is an error — never a value.

  • A missing data key is an error, not an empty result. Coercing it to [] would turn a broken integration into "no results found".

  • A missing pagination on a paginated endpoint is an error too. Assuming one page is how a tool reports 50 of 900 mods as if it were all of them (U8 is exactly this open question).

  • pageSize > 50 is refused, not clamped, and so is index + pageSize > 10000 — with the largest legal page size at that index named in the message. A model that asks for 200 and silently gets 50 will reason about a page as if it were a set.

  • When totalCount exceeds 10000, tool output says the tail is UNREACHABLE, in those words, and advises narrowing the filter rather than paging.

  • The ASA gameId is discovered at runtime from GET /v1/games and cached for the process lifetime; it is never hardcoded and never guessed. If it cannot be resolved the server fails loudly, naming what it searched for and how many games the key could see — because gameId is a required search filter, so a wrong one returns clean, empty, entirely wrong results instead of an error. Set CURSEFORGE_GAME_SLUG if the built-in candidates turn out to be wrong.

  • resolve_mod_dependencies is bounded at depth 4 and 400 nodes, with a visited set for cycles. When a bound is hit the result is reported as truncated, in that word, with the unexplored frontier listed.


Repo layout

src/
  allowlist.ts    THE CHOKEPOINT — eight 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 eight tools
test/             156 tests; fixtures are synthetic in content, structural in shape
scripts/          buildinfo generator, test enumerator

src/buildinfo.ts is generated and gitignored, stamped with the commit and a dirty flag before every tsc run, and surfaced by get_api_diagnostics. dist/ is gitignored and the server runs from it as a long-lived process, so "which code produced that answer?" is not answerable from git at runtime — it has to travel with the artifact.

Deviations from the sibling repo, stated deliberately

ADR-002's open questions 7 and 8 ask for these to be named where they happen:

  • Same baseline, deliberately. Node ≥20, TypeScript 5.9.3, @modelcontextprotocol/sdk 1.30.0, zod 4.4.3, node:test via the same scripts/run-tests.mjs enumerator. Same reviewer, same idioms, lower cost of reading both.

  • @cfworker/json-schema is not a dependency here. It backs the sibling's cron-expression validation, and there is no write path to validate.

  • registry.ts is ported in structure and keeps tier, but drops the mode/enabled-list machinery — it would have nothing to filter, since every tool is tier 1 and every endpoint is a read. A mode variable with nothing behind it advertises a control that does not exist. One five-line boot assertion replaces the subsystem.

  • redact.ts is not ported (§12.1). See "Redaction, all of it" above.

  • No UNKNOWN_OUTCOME error code. The sibling needs it because a lost response to a PUT may still have changed the world. Every request this client can make is a read, so a timeout genuinely does mean "it did not happen" and a retry is safe.

  • npm run smoke exits 0 when it refuses for want of a key. The refusal is the expected outcome of running it today, and the banner says SMOKE NOT RUN unmissably. If you want a pipeline to fail on a missing key, gate the pipeline on the key rather than on this exit code.


In the sibling repo nitrado-ark-mcp, read-only from here — nothing in that repo was modified by this one:

  • docs/decisions/EXECUTIVE-BOARD-2026-08-16-curseforge-mods.md — the board minutes (DEC-002) this repo executes. Its Chair's Rulings are binding.

  • docs/decisions/decision-log.md — DEC-002, and DEC-001 for the scope split that §10 rests on.

  • docs/adr/ADR-001-write-path-enforcement.md — the shape ADR-002 ports, and the source of the normalization rule, the boot-check reasoning, and the refuse-to-start reasoning.

The two servers stay independent. nitrado-ark-mcp answers "these project ids are in active-mods"; this repo answers "project X's newest file is v2.1". The model holds both. Neither server calls the other, and neither ever holds the other's credential.

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.

ParametersJSON Schema
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.

ParametersJSON Schema
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.

ParametersJSON Schema
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.

ParametersJSON Schema
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.

ParametersJSON Schema
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.

ParametersJSON Schema
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.

ParametersJSON Schema
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.

ParametersJSON Schema
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. Dates show when Glama detected each change.

  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
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.
    89
    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.
    77
    1
    ISC

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/JShort-bufr/curseforge-ark-mcp'

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