Skill Tracer
Skills › Scientific Agent Skills › imaging-data-commons › mcp_guide.md

mcp_guide.md

189 lines · skills/imaging-data-commons/references/mcp_guide.md at 5f2bc03

Open on GitHub

Most marks come from matching words in the file, so treat them as pointers.

1# IDC MCP Server Guide
2
3IDC operates a hosted [Model Context Protocol](https://modelcontextprotocol.io/) server that
4exposes IDC discovery and metadata as agent tools. This guide covers how to recognize it, how
5to divide work between it and `idc-index`, and what to hand off across that boundary.
6
7The server is optional. Everything in `SKILL.md` works without it.
8

IDC MCP Server Guide

IDC operates a hosted Model Context Protocol server that exposes IDC discovery and metadata as agent tools. This guide covers how to recognize it, how to divide work between it and idc-index, and what to hand off across that boundary.

The server is optional. Everything in SKILL.md works without it.

Raw lines 1 to 8
Uses an outside tool MCP :1
9## Endpoint
11| Property | Value |
12|----------|-------|
13| URL | `https://api.imaging.datacommons.cancer.gov/mcp` |
14| Transport | Streamable HTTP (`streamable-http`, sometimes spelled `http`) |
15| Authentication | None |
16| Server identity | `IDC (Imaging Data Commons)` |

Endpoint

PropertyValue
URLhttps://api.imaging.datacommons.cancer.gov/mcp
TransportStreamable HTTP (streamable-http, sometimes spelled http)
AuthenticationNone
Server identityIDC (Imaging Data Commons)
Raw lines 9 to 17
18## Identifying the server
20Tool names and resource URIs are defined by the server, so they are the same on every host.
21Use them, not host-specific naming conventions, to decide whether the server is present.
23**Strongest signal — resource URIs.** The server publishes two resources under an `idc://`
24scheme:
26| URI | Content |
27|-----|---------|
28| `idc://guide` | Data model and recommended workflow (Markdown) |
29| `idc://tables` | Tables available to `run_sql`, with descriptions and column counts (JSON) |
31If the host can enumerate MCP resources, a resource with URI `idc://guide` identifies the
32server unambiguously.
34**Fallback — tool-name fingerprint.** Require three or more of `build_cohort`,
35`get_cohort_urls`, `list_analysis_results`, and `get_idc_version`. Do not treat `run_sql`,
36`get_stats`, `list_tables`, or `get_citations` as evidence on their own; those names are
37generic enough that another server could expose them.
39**This is disambiguation, not authentication.** No runtime check can prove the server on the
40other end is operated by NCI — a hostile server could serve `idc://guide` and name its tools
41anything. The trust anchor is the URL the user configured plus TLS, which is established when
42the server is added, not when the skill runs. That is sufficient for routing: the check only
43has to distinguish IDC from the user's other installed servers.
45**Fail soft.** If identification is ambiguous, or a tool call fails, fall back rather than
46reporting an error — to the REST API (`rest_api_guide.md`) for read-only metadata, which is the
47same service with no configuration, or to `idc-index` when it is already installed or the task
48needs downloads or local analysis. Tool names may change as the server matures.

Identifying the server

Tool names and resource URIs are defined by the server, so they are the same on every host. Use them, not host-specific naming conventions, to decide whether the server is present.

Strongest signal — resource URIs. The server publishes two resources under an idc:// scheme:

URIContent
idc://guideData model and recommended workflow (Markdown)
idc://tablesTables available to run_sql, with descriptions and column counts (JSON)

If the host can enumerate MCP resources, a resource with URI idc://guide identifies the server unambiguously.

Fallback — tool-name fingerprint. Require three or more of build_cohort, get_cohort_urls, list_analysis_results, and get_idc_version. Do not treat run_sql, get_stats, list_tables, or get_citations as evidence on their own; those names are generic enough that another server could expose them.

This is disambiguation, not authentication. No runtime check can prove the server on the other end is operated by NCI — a hostile server could serve idc://guide and name its tools anything. The trust anchor is the URL the user configured plus TLS, which is established when the server is added, not when the skill runs. That is sufficient for routing: the check only has to distinguish IDC from the user's other installed servers.

Fail soft. If identification is ambiguous, or a tool call fails, fall back rather than reporting an error — to the REST API (rest_api_guide.md) for read-only metadata, which is the same service with no configuration, or to idc-index when it is already installed or the task needs downloads or local analysis. Tool names may change as the server matures.

Raw lines 18 to 49
Uses an outside tool MCP :31
50## Tool inventory
52Live `initialize`, `tools/list`, and `resources/list` verified on 2026-09-30 against server `3.0.0b3`. Treat this as a snapshot, not a contract — call
53the server's own listing rather than assuming this list is current.
55| Group | Tools |
56|-------|-------|
57| Version and scale | `get_idc_version`, `get_stats` |
58| Collections | `list_collections`, `get_collection`, `list_analysis_results` |
59| Attribute grounding | `list_attributes`, `get_attribute_values` |
60| Cohorts | `build_cohort`, `get_cohort_urls` |
61| SQL | `list_tables`, `get_table_schema`, `run_sql` |
62| Clinical data | `list_clinical_tables`, `get_clinical_table_schema`, `get_clinical_table` |
63| Attribution | `get_citations`, `get_licenses` |
64| Visualization | `get_viewer_url` |
66The server ships its own usage instructions, which most hosts inject automatically. Follow
67those instructions for tool sequencing (ground with `list_attributes` /
68`get_attribute_values` before filtering; check `list_tables` before writing SQL). Do not
69re-derive that workflow from `SKILL.md` — the two would drift apart on the server's next
70release.
72**Cohort results report their own filters.** `build_cohort` and `get_cohort_urls` require at
73least one filter predicate and fail cleanly without one, rather than returning the whole archive;
74results echo the filters actually applied along with warnings (inside `counts` for `build_cohort`) for any predicate that was dropped
75or any value whose casing did not match. Read those warnings before reporting a count — a zero
76with no warning means the filter matched nothing, which is a real answer. Same contract as the
77REST endpoints they wrap; see `rest_api_guide.md`.

Tool inventory

Live initialize, tools/list, and resources/list verified on 2026-09-30 against server 3.0.0b3. Treat this as a snapshot, not a contract — call the server's own listing rather than assuming this list is current.

GroupTools
Version and scaleget_idc_version, get_stats
Collectionslist_collections, get_collection, list_analysis_results
Attribute groundinglist_attributes, get_attribute_values
Cohortsbuild_cohort, get_cohort_urls
SQLlist_tables, get_table_schema, run_sql
Clinical datalist_clinical_tables, get_clinical_table_schema, get_clinical_table
Attributionget_citations, get_licenses
Visualizationget_viewer_url

The server ships its own usage instructions, which most hosts inject automatically. Follow those instructions for tool sequencing (ground with list_attributes / get_attribute_values before filtering; check list_tables before writing SQL). Do not re-derive that workflow from SKILL.md — the two would drift apart on the server's next release.

Cohort results report their own filters. build_cohort and get_cohort_urls require at least one filter predicate and fail cleanly without one, rather than returning the whole archive; results echo the filters actually applied along with warnings (inside counts for build_cohort) for any predicate that was dropped or any value whose casing did not match. Read those warnings before reporting a count — a zero with no warning means the filter matched nothing, which is a real answer. Same contract as the REST endpoints they wrap; see rest_api_guide.md.

Raw lines 50 to 78
79## Division of labor
81The server and `idc-index` overlap on metadata queries and diverge everywhere else.
83| Task | Use |
84|------|-----|
85| IDC data version, collection and series counts | Server (`get_idc_version`, `get_stats`) |
86| Valid filter values before building a query | Server (`get_attribute_values`) |
87| Cohort selection by attribute filters | Server (`build_cohort`) |
88| One-off metadata SQL, answer consumed as prose | Server (`run_sql`) |
89| Metadata SQL whose result feeds local Python | `idc-index` (`client.sql_query`) |
90| Downloading DICOM files | `idc-index` (`client.download_from_selection`) |
91| pandas / notebook analysis, plotting | `idc-index` |
92| Reading pixel data (pydicom, SimpleITK) | `idc-index` + local files |
93| DICOMweb, BigQuery, direct S3/GCS, Parquet | `idc-index` and the relevant reference guide |
94| Digital pathology tiling and annotation workflows | `idc-index` + `digital_pathology_guide.md` |
95| Reproducible scripts a user will re-run | `idc-index` (a script outlives the session) |
97Two rules resolve the overlap:
99- **Prefer the server for discovery.** It is hosted against a current IDC release, so it does
100 not depend on the `idc-index` version pinned in `SKILL.md`.
101- **Prefer `idc-index` when the result must become a Python object.** Round-tripping a
102 DataFrame through tool output wastes context and loses types.

Division of labor

The server and idc-index overlap on metadata queries and diverge everywhere else.

TaskUse
IDC data version, collection and series countsServer (get_idc_version, get_stats)
Valid filter values before building a queryServer (get_attribute_values)
Cohort selection by attribute filtersServer (build_cohort)
One-off metadata SQL, answer consumed as proseServer (run_sql)
Metadata SQL whose result feeds local Pythonidc-index (client.sql_query)
Downloading DICOM filesidc-index (client.download_from_selection)
pandas / notebook analysis, plottingidc-index
Reading pixel data (pydicom, SimpleITK)idc-index + local files
DICOMweb, BigQuery, direct S3/GCS, Parquetidc-index and the relevant reference guide
Digital pathology tiling and annotation workflowsidc-index + digital_pathology_guide.md
Reproducible scripts a user will re-runidc-index (a script outlives the session)

Two rules resolve the overlap:

  • Prefer the server for discovery. It is hosted against a current IDC release, so it does not depend on the idc-index version pinned in SKILL.md.
  • **Prefer idc-index when the result must become a Python object.** Round-tripping a DataFrame through tool output wastes context and loses types.
Raw lines 79 to 103
104## Handing off from the server to `idc-index`
106The boundary artifact is a list of `SeriesInstanceUID` values.
108```python
109# UIDs obtained from the MCP server's build_cohort / run_sql output
110series_uids = [
111 "1.3.6.1.4.1.14519.5.2.1.7009.2403.334240657131972136850343327463",
112 # ...
115from idc_index import IDCClient
116client = IDCClient()
118# Confirm size before downloading — the server reports size_TB, but re-check locally
119selected = client.index[client.index["SeriesInstanceUID"].isin(series_uids)]
120missing = set(series_uids) - set(selected["SeriesInstanceUID"])
121if missing:
122 raise ValueError(f"{len(missing)} requested series absent from local index; reconcile versions")
123print({"series": len(selected), "size_GB": selected["series_size_MB"].sum() / 1000})
125client.download_from_selection(
126 downloadDir="./data",
127 seriesInstanceUID=series_uids, # a list, not a DataFrame
128 dirTemplate="%collection_id/%PatientID/%Modality",
130```
132Run `python scripts/check_version.py` before the first `idc-index` call in a session, even if
133discovery happened server-side — the two components version independently.
135`get_cohort_urls` also returns ready-made `idc` CLI commands. Those are the better handoff
136when the user wants a shell command they can re-run outside the session, after validating
137the CLI syntax: the reviewed server omits required `--manifest-file` in its
138`download-from-manifest` suggestion. Add it; see `references/cli_guide.md`.
140`build_cohort` uses zero-based `page`/`page_size`; collect all pages until the returned
141series count matches `total_series`. `get_cohort_urls` defaults to only 100 URLs; inspect
142`truncated` and increase its bounded limit or partition the cohort before download.
144Going the other direction, `idc-index` results are already local, so there is rarely a reason
145to send them back to the server.

Handing off from the server to idc-index

The boundary artifact is a list of SeriesInstanceUID values.

# UIDs obtained from the MCP server's build_cohort / run_sql output
series_uids = [
    "1.3.6.1.4.1.14519.5.2.1.7009.2403.334240657131972136850343327463",
    # ...
]

from idc_index import IDCClient
client = IDCClient()

# Confirm size before downloading — the server reports size_TB, but re-check locally
selected = client.index[client.index["SeriesInstanceUID"].isin(series_uids)]
missing = set(series_uids) - set(selected["SeriesInstanceUID"])
if missing:
    raise ValueError(f"{len(missing)} requested series absent from local index; reconcile versions")
print({"series": len(selected), "size_GB": selected["series_size_MB"].sum() / 1000})

client.download_from_selection(
    downloadDir="./data",
    seriesInstanceUID=series_uids,       # a list, not a DataFrame
    dirTemplate="%collection_id/%PatientID/%Modality",
)

Run python scripts/check_version.py before the first idc-index call in a session, even if discovery happened server-side — the two components version independently.

get_cohort_urls also returns ready-made idc CLI commands. Those are the better handoff when the user wants a shell command they can re-run outside the session, after validating the CLI syntax: the reviewed server omits required --manifest-file in its download-from-manifest suggestion. Add it; see references/cli_guide.md.

build_cohort uses zero-based page/page_size; collect all pages until the returned series count matches total_series. get_cohort_urls defaults to only 100 URLs; inspect truncated and increase its bounded limit or partition the cohort before download.

Going the other direction, idc-index results are already local, so there is rarely a reason to send them back to the server.

Raw lines 104 to 146
Uses an outside tool MCP :109
Runs code python scripts/check_version.py :132
147## Version authority
149When the server is present, it is the authority on the IDC data version: call
150`get_idc_version` rather than quoting the `idc-data-version` value in the `SKILL.md`
151frontmatter, which records the release the skill was last verified against.
153If the server and a locally installed `idc-index` report different versions, say so and name
154both. The mismatch is real — the hosted server tracks IDC releases independently of the user's
155installed package — and it changes which answers about "what's new" are correct.

Version authority

When the server is present, it is the authority on the IDC data version: call get_idc_version rather than quoting the idc-data-version value in the SKILL.md frontmatter, which records the release the skill was last verified against.

If the server and a locally installed idc-index report different versions, say so and name both. The mismatch is real — the hosted server tracks IDC releases independently of the user's installed package — and it changes which answers about "what's new" are correct.

Raw lines 147 to 156
157## Host-specific notes
159Everything above is portable. The items below are not, and apply only to specific agent
160environments.

Host-specific notes

Everything above is portable. The items below are not, and apply only to specific agent environments.

Raw lines 157 to 161
162### Claude Code
164Reviewed against the official [MCP](https://code.claude.com/docs/en/mcp) and
165[permissions](https://code.claude.com/docs/en/permissions) documentation; connector naming
166and discovery surfaces still depend on the installed host version.
168- **Tool naming.** MCP tools are exposed as `mcp__<server>__<tool>`, where `<server>` is the
169 configured server name with every character outside `A-Za-z0-9_-` replaced by `_`. A CLI
170 install named `idc` yields `mcp__idc__build_cohort`; a claude.ai connector named
171 `IDC MCP prod` yields `mcp__claude_ai_IDC_MCP_prod__build_cohort`.
172- **Enumerating resources.** `ListMcpResourcesTool` returns each resource with a `server`
173 field, which is how to find the `idc://guide` resource and the owning server name in one
174 call.
175- **Adding the server.**
176 `claude mcp add --transport http idc https://api.imaging.datacommons.cancer.gov/mcp`
177- **Permission rules.** Allow rules need a literal, glob-free server segment: `mcp__idc__*`
178 works, `mcp__*` does not. Connector installs need their own
179 `mcp__claude_ai_<name>__*` rule, so the rule differs by install path.
180- **Detecting via the CLI does not work.** `claude mcp list` reads only file-based
181 configuration (`~/.claude.json`, `.mcp.json`). It reports "No MCP servers configured" for a
182 claude.ai connector that is connected and working in the same session, so it cannot be used
183 as a presence check.

Claude Code

Reviewed against the official MCP and permissions documentation; connector naming and discovery surfaces still depend on the installed host version.

  • Tool naming. MCP tools are exposed as mcp__<server>__<tool>, where <server> is the configured server name with every character outside A-Za-z0-9_- replaced by _. A CLI install named idc yields mcp__idc__build_cohort; a claude.ai connector named IDC MCP prod yields mcp__claude_ai_IDC_MCP_prod__build_cohort.
  • Enumerating resources. ListMcpResourcesTool returns each resource with a server field, which is how to find the idc://guide resource and the owning server name in one call.
  • Adding the server. claude mcp add --transport http idc https://api.imaging.datacommons.cancer.gov/mcp
  • Permission rules. Allow rules need a literal, glob-free server segment: mcp__idc__* works, mcp__* does not. Connector installs need their own mcp__claude_ai_<name>__* rule, so the rule differs by install path.
  • Detecting via the CLI does not work. claude mcp list reads only file-based configuration (~/.claude.json, .mcp.json). It reports "No MCP servers configured" for a claude.ai connector that is connected and working in the same session, so it cannot be used as a presence check.
Raw lines 162 to 184
Uses an outside tool MCP :164
Uses an outside tool mcp__idc__build_cohort :170
Uses an outside tool mcp__claude_ai_IDC_MCP_prod__build_cohort :171
Uses an outside tool mcp__idc__ :177
Uses an outside tool mcp__claude_ai_ :179
185### Other hosts
187Any agent that supports MCP over streamable HTTP can use the server. Consult that agent's
188documentation for how servers are registered and how tool names are namespaced; the endpoint
189URL and the absence of authentication are all the configuration it needs.

Other hosts

Any agent that supports MCP over streamable HTTP can use the server. Consult that agent's documentation for how servers are registered and how tool names are namespaced; the endpoint URL and the absence of authentication are all the configuration it needs.

Raw lines 185 to 189
Uses an outside tool MCP :187