MCP server for biological API integration with Code Mode execution, GraphQL/SPARQL support, and auto-staging of large responses into SQLite
This server exposes 5 tools with complex, code-execution-based interfaces. While descriptions are present and detailed (100-300+ chars), they suffer from critical gaps: (1) Input schemas are visible but lack proper Zod type definitions for most parameters, the 'code' param is typed as string but lacks constraints, format hints, or validation guidance; (2) Parameter descriptions are verbose but do not follow the rubric's requirement for actionable format/range/constraint statements; (3) No output schemas are documented, callers cannot predict the structure of results from execute/search tools; (4) Error handling is absent, no guidance on what happens when code fails, timeouts occur, or API calls error; (5) Tool names use generic verbs (_search, _execute) repeated across modes (REST, GraphQL, SPARQL), creating ambiguity, LLMs cannot distinguish which execute tool to call without reading full descriptions. The server is functional but violates multiple critical patterns: tool-description (missing output schemas), constrained-input (no validation on code param), error-classification (no error guidance), and tool-chain (no documented return types for chaining).
Execute JavaScript code against the API with sandboxed V8 isolate. Code runs with: searchSpec(query) / searchPaths(query) — search the API catalog or OpenAPI spec; listCategories() / listTags() — inspect tags/categories; getEndpoint(path) / getOperation(idOrPath) — get endpoint docs; describeEndpoint(path, method?) / describeOperation(idOrPath) — format endpoint docs; spec — full frozen OpenAPI spec object; 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 preamble with domain-specific helpers.
Execute JavaScript code against a GraphQL endpoint with sandboxed V8 isolate. Code runs with: gql.query(queryString, variables?) — GraphQL execution through host; schema.types(), schema.type(), schema.search() etc. — introspection helpers; db.stage(), db.queryStaged(), api.query() — staging helpers; console.log() capture; optional REST capability (api.get/api.post) when restApiFetch is configured; optional preamble with domain-specific helpers.
Execute JavaScript code against a SPARQL endpoint with 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 (rdfs, owl, xsd, skos, dcterms, void, obo, uberon, go, ncbigene, efo, obi, sio, up, ensembl, bgee); prefixHeader — pre-built PREFIX block to prepend to queries; console logging (log, warn, error, info) — captured output; optional filesystem access (fs.readFile / fs.writeFile / fs.glob) when fsDoNamespace is provided; optional preamble with domain-specific notes.
No output schemas documented. Callers cannot predict result structure (e.g., does execute return {data, error, __staged}? What fields does search return?). Forces LLMs to guess and wastes tokens on trial-and-error parsing.
Ambiguous tool naming: three separate _execute tools (REST, GraphQL, SPARQL) and two _search tools share names. LLMs cannot distinguish which to call without reading full descriptions. Violates verb_noun clarity and tool-chain patterns.
Code parameter lacks validation constraints. No length limits, no examples of valid syntax, no error guidance if code is malformed or times out. Descriptions mention 'sandboxed V8 isolate' but do not explain what happens on failure or how to recover.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | F | 35 | 2026-07-28+ | v2 |
Search the API catalog (catalog mode) or OpenAPI spec (OpenAPI 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.
Search the GraphQL schema or discover endpoints. When introspection is available, returns schema types, fields, and descriptions. When introspection is disabled, returns a note that schema.* discovery is unavailable and directs to use gql.query() with field names from published schema docs.
No error handling guidance. Descriptions do not explain what errors are retryable, what indicates user input is invalid, or how to recover from timeouts, API failures, or sandbox violations. Violates recovery-guide pattern.
Parameter descriptions are verbose but lack actionable constraints. E.g., 'code' param description is 100+ chars but does not state max length, timeout, or what happens if code throws. Violates param-validation-rules pattern.