MCP server for cBioPortal API with Code Mode execution, GraphQL/SPARQL support, and API discovery
This server exposes 5 code-execution tools (catalog_search, execute, search, graphql_execute, sparql_execute) with detailed descriptions but critical schema and composition gaps. All tools have descriptions (50-200 chars range), but input schemas are either missing or inferred from code comments rather than explicit Zod definitions visible in the provided source. The catalog_search tool shows a Zod schema in the code, but execute, search, graphql_execute, and sparql_execute lack visible schema definitions, only parameter descriptions in comments. No output schemas are documented. Error handling is absent: no recovery guidance, no categorization of retryable vs fatal errors. The tools conflate multiple concerns (search + discovery + execution in one tool), violating single-responsibility. No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite all being read-only. Parameter descriptions are present but lack constraints (enums, ranges, patterns). The server accepts arbitrary JavaScript code execution, which is a powerful but high-risk pattern requiring explicit security documentation absent here.
Search the API catalog (endpoints). Returns matching endpoints with full parameter docs. Use this to discover API capabilities before calling execute. Categories: (dynamic based on catalog) USAGE IN execute: - api.get(path, params) for GET, api.post(path, body, params) for POST - Path params like /lookup/{id} are auto-interpolated from params: api.get('/lookup/{id}', {id: 'ENSG...'}) - Remaining params become query string - Large responses (>100KB) are auto-staged: check result.__staged, return the staging info, use query_data to explore - Use limit/pagination params to control response size. Large datasets auto-stage for SQL queries.
Execute JavaScript code against the API. Code runs in a sandboxed V8 isolate with api.get/api.post wrappers, catalog search helpers, and console.log() capture. The isolate gets: searchSpec(query), listCategories(), getEndpoint(path), describeEndpoint(path) — search and inspect the API catalog. api.get(path, params) for GET, api.post(path, body, params) for POST. Path params like /lookup/{id} are auto-interpolated from params. Large responses (>100KB) are auto-staged into SQLite; check result.__staged and use query_data to explore. fs.* (readFile, writeFile, glob) — persistent virtual filesystem (when configured). console logging (log, warn, error, info) — captured output. The last expression or return value is the result.
Execute JavaScript code against a GraphQL endpoint. Code runs in a sandboxed V8 isolate 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. Optionally also REST API support (api.get/api.post) when configured. The last expression or return value is the result.
Search the API spec (OpenAPI mode). Write JavaScript code to search the OpenAPI spec, or use the 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 - searchSpec/query helpers are also available for backward compatibility inside execute() - spec — the full frozen OpenAPI spec object (spec.paths, spec.info, etc.) Use search to discover endpoints, then write code in execute to call them.
Four of five tools (execute, search, graphql_execute, sparql_execute) lack visible input schemas. Only catalog_search shows explicit Zod schema definition. Others have parameter descriptions in comments but no machine-readable schema registration.
No output schemas documented for any tool. LLMs cannot predict return structure, forcing them to guess at field names and types for downstream composition.
No error handling guidance. Tools accept arbitrary code execution but provide no recovery hints, error categorization, or actionable error messages. An LLM receiving a runtime error has no guidance on retry vs user-fixable vs fatal.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | F | 38 | 2026-07-28+ | v2 |
Execute JavaScript code against a SPARQL endpoint. Code runs in a sandboxed V8 isolate 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 your queries. console logging (log, warn, error, info) — captured output. fs.* (readFile, writeFile, glob) — persistent virtual filesystem (when configured). The last expression or return value is the result.
Tool composition violates single-responsibility. 'search' tool combines keyword search, tag listing, and operation introspection. 'execute' combines API calls, staging, and filesystem access. Split into focused tools: search_catalog, list_tags, get_operation, stage_data, query_staged_data.
No tool annotations despite all tools being read-only. Missing readOnlyHint annotation prevents agents from understanding safety profile and planning accordingly.