MCP server for MetaboLights API with Code Mode execution, GraphQL/SPARQL support, and API discovery tools
This server exposes 5 tools with significant definition gaps. Tool names lack clear verb-noun structure (e.g., '<prefix>_search' and '<prefix>_execute' are generic and repeated across different API modes). Descriptions are verbose (200-400+ chars) but lack actionable guidance on WHEN to use each tool vs. alternatives. Input schemas are present but incomplete: parameters lack type constraints (e.g., 'code' is just a string with no length/complexity bounds), and no output schemas are documented. Error handling is absent, no guidance on recovery, retryability, or what to do when code execution fails. The tool composition violates single-responsibility: both REST and GraphQL modes use the same '<prefix>_execute' name, forcing LLMs to guess which to invoke. No tool annotations (readOnlyHint, idempotentHint) despite all being read-only operations.
Execute JavaScript code against the API in a sandboxed V8 isolate. Code runs with: searchSpec(query) / searchPaths(query) — search the API catalog/spec; listCategories() / listTags() — inspect tags/categories; getEndpoint(path) / getOperation(idOrPath) — get endpoint docs; api.get(path, params) for GET, api.post(path, body, params) for POST; Path params like /lookup/{id} are auto-interpolated from params; Remaining params become query string; Large responses (>100KB) are auto-staged: check result.__staged, return the staging info, use <prefix>_query_data to explore; console.log() capture; optional fs.* for virtual filesystem access.
Execute JavaScript code against a GraphQL endpoint in a sandboxed V8 isolate. Code runs with: gql.query(queryString, variables?) — GraphQL execution; schema.types(), schema.type(), schema.search() — introspection helpers; db.stage(), db.queryStaged() — staging helpers; optional api.get/api.post for hybrid REST capability; console.log() capture; optional fs.* for virtual filesystem access.
Execute JavaScript code against a SPARQL endpoint in a sandboxed V8 isolate. Code runs with: sparql.query(queryString, opts?) — run SELECT/CONSTRUCT/DESCRIBE; returns array of plain { variable: value } rows; sparql.ask(queryString) — run ASK; returns boolean; sparql.raw(queryString, opts?) — return unparsed { head, results } envelope; prefixes — object of common ontology prefixes; prefixHeader — pre-built PREFIX block; db.stage(), db.queryStaged() — staging helpers; console logging capture; optional fs.* for virtual filesystem access.
Search the API catalog (legacy catalog mode). Returns matching endpoints with full parameter docs. Use this to discover API capabilities before calling <prefix>_execute. Categories are listed. USAGE IN <prefix>_execute: api.get(path, params) for GET, api.post(path, body, params) for POST. Path params like /lookup/{id} are auto-interpolated from params. Remaining params become query string. Large responses (>100KB) are auto-staged: check result.__staged, return the staging info, use <prefix>_query_data to explore. Use limit/pagination params to control response size.
Duplicate tool names across different API modes. Both REST and GraphQL use '<prefix>_execute', forcing LLMs to guess which mode applies. This violates single-responsibility and creates ambiguity.
No output schemas documented. LLMs cannot predict what fields to expect from code execution results, making downstream tool chaining impossible and forcing agents to parse unstructured responses.
No error handling guidance. Code execution can fail (syntax errors, API timeouts, permission denied) but tool descriptions provide no recovery hints. LLMs have no way to self-correct or know if errors are retryable.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | F | 37 | 2026-07-28+ | v2 |
Search the OpenAPI spec (OpenAPI mode). Write JavaScript code to search the OpenAPI spec, or use legacy query/category arguments for keyword search. Available functions: searchPaths(query, maxResults=10) — keyword search across paths, summaries, tags, parameters; listTags() — list all tags with operation counts; getOperation(idOrPath) — get full operation by operationId or path; describeOperation(idOrPath) — formatted documentation for an operation; spec — the full frozen OpenAPI spec object. Use <prefix>_search to discover endpoints, then write code in <prefix>_execute to call them.
Generic tool names ('<prefix>_search', '<prefix>_execute') do not follow verb_noun convention. Names should be specific: 'search_metabolights_catalog', 'execute_rest_query', 'execute_graphql_query', 'execute_sparql_query' to disambiguate modes.
No tool annotations. All tools are read-only (risk: READ_ONLY) but lack readOnlyHint annotation. This prevents agents from understanding safety guarantees and optimizing retry logic.