> ## Documentation Index
> Fetch the complete documentation index at: https://docs.strandai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP server

> Connect any MCP-aware agent to Strand AI's hosted MCP server to browse samples and run virtual multiplex immunofluorescence (H&E to spatial proteomics) end to end, authorized against your Strand AI organization.

Strand AI runs a hosted [Model Context
Protocol](https://modelcontextprotocol.io) server so any MCP-aware agent can
drive the Strand AI platform. An agent browses owned or public samples, uploads
an H\&E whole-slide image, estimates or submits a Lattice virtual-staining run,
tracks it, and downloads the predicted marker channels. Every action is
authorized against your Strand AI organization; only submitted runs reserve
its credits.

It is a hosted, OAuth-authenticated service over Streamable HTTP. There is
nothing to install and no API key to manage. You connect the server URL and
authorize with your Strand AI account. Slide bytes and results never pass through
the model or the server.

## Connect

Add a custom connector with the server URL `https://mcp.strandai.com/mcp`
over the Streamable HTTP transport, then authorize with Strand AI and pick an
organization. See [Claude](/mcp/claude) for the step-by-step, authorization,
and data-handling details.

Slide upload depends on the client's network because the client sends bytes
directly to storage. Claude Code and the SDKs work without additional setup.
Claude.ai requires one network setting. [ChatGPT](/mcp/chatgpt) cannot upload
because its sandbox has no outbound network access; upload with the browser or
another client before running markers from ChatGPT.

## Tools

| Tool               | Purpose                                                                                                 |
| ------------------ | ------------------------------------------------------------------------------------------------------- |
| `upload_slide`     | Create a presigned, resumable upload session; processing starts automatically when the object finalizes |
| `list_markers`     | List the markers your account can request (credit-free)                                                 |
| `list_samples`     | List owned samples, the curated public cohort, or both (credit-free)                                    |
| `get_sample`       | Read owned or public sample detail; owned samples include current and historical jobs                   |
| `patch_sample`     | Replace a sample's name, tags, or microns-per-pixel calibration                                         |
| `segment_sample`   | Start or retry credit-free cell segmentation for an owned ready sample                                  |
| `submit_run`       | Estimate patches and credits with `dry_run: true`, or reserve credits and create a job                  |
| `cancel_job`       | Cancel an in-flight job and release its credit reservation                                              |
| `wait_for_job`     | Wait up to 240 seconds and return the terminal or latest status                                         |
| `download_results` | Select native OME-Zarr, OME-Zarr ZIP, or OME-TIFF and optional H\&E/segmentation contents               |

Research use only (RUO). Not for use in clinical or diagnostic procedures.

### Browsing and reading samples

`list_samples` accepts `scope: mine | public | all` (default `mine`), `limit`
(default 48, maximum 100), an optional cursor, and an optional exact tag filter.
`mine` contains active, non-trashed samples owned by your organization.
`public` contains the curated public cohort. `all` puts owned samples first and
removes owned-public overlap in favor of the owned item. Results use `items`
and `next_cursor`. Every item has an `ownership` discriminator and canonical
`id`. Public IDs are privacy-safe. The API trims and lowercases a tag and
requires its normalized length to be from 1 to 50 characters.

Every sample result also carries a canonical absolute `app_url`. Agents should
link users to that value rather than building a URL from a sample ID.

`get_sample` accepts that canonical ID for either branch. Owned detail includes
`jobs` and `job_count`, covering current and historical runs. Public detail is
limited to curated public fields and carries no owned job history or internal
sample, organization, creator, or storage identifiers. Sample reads are
credit-free. Owned detail also includes `segmentation`: lifecycle status, retryability, latest job, latest materialized layer, artifact availability, and the explicit zero-credit cost.

### Cell segmentation

`segment_sample` starts segmentation when none exists and retries failed runs.
The operation is state-idempotent and credit-free. It reuses active or completed
work, and failed runs have a 60-second retry cooldown. Only owned, ready,
non-archived samples can be changed. Public samples are read-only. Poll with
`get_sample`; its latest layer reports whether the uint32 label-mask OME-Zarr
and per-cell feature tables are available.

`download_results(..., include_segmentation: true)` attaches the segmentation manifest. Cell morphology/geometry and each marker-expression Parquet table join on `instance_id`. These are true cell observations. Python `AnnData` created from ordinary prediction results remains a pixel-grid matrix and is not a segmentation result.

### Updating a sample

`patch_sample` requires a sample ID and at least one of `name`, `tags`, or
`mpp`. `tags` replaces the complete desired set. A null or empty `name`
reverts to the uploaded filename. `mpp` is isotropic microns per pixel and
takes precedence over embedded slide calibration.

### Estimating and submitting a run

`submit_run` defaults to creating a job and reserving credits. Set
`dry_run: true` to return patch and credit estimates without creating a job or
reserving credits. A newly uploaded slide can take about 90 seconds to resolve
its dimensions, scale, and tissue-tile count. During that interval a dry run
returns `status: not_ready`, a reason, and `retry_after_seconds: 15`; retry the
dry run after that interval.

### Result formats

`download_results` requires `format: ome-zarr | ome-zarr-zip | ome-tiff`.
Native `ome-zarr` returns stored data without conversion. OME-Zarr ZIP and
OME-TIFF are cached asynchronous exports. Repeat the same invocation to poll or
retry a failed export. H\&E is off by default for every format. Setting
`include_he: true` selects a separately cached H\&E-inclusive OME-TIFF, and for
OME-Zarr and OME-Zarr ZIP it returns the processed, registered H\&E as its own
`artifacts.he` link. `include_segmentation` adds the latest mask plus the
per-cell geometry, morphology, and marker-expression manifest. Pixel-grid
marker arrays are not cell expressions. Responses report the selected contents,
status, expiration, retryability, and whether the prediction artifact was
converted.

### Waiting for a run

`wait_for_job` provides a status snapshot after waiting for at most 240 seconds.
Long-running jobs may still be active when it returns. Terminal jobs return
`completed`, `partial_failed`, `failed`, or
`cancelled` as ordinary status results. If the timeout elapses first, the job
keeps running and the tool returns a refreshed latest status. Call it again to
continue waiting. The server-side wait reduces model polling and returns before
Claude's connector deadline.

## Uploading a slide

**Slides must be de-identified before upload.** See [Security and data
handling](/security-data-handling).

`upload_slide` does not take a file. The bytes are not sent through the model
or the server. It returns a presigned, resumable upload session bound to your
organization's storage: an `upload_id` and an `upload_url`. Your agent then:

1. Sends the slide bytes directly to `upload_url` with an HTTP `PUT`. One
   request works for a typical slide. Larger files can be sent as sequential
   chunks (each a multiple of 256 KiB except the last). The tool result provides
   structured `transfer` metadata for content ranges, ordering, alignment, and
   success statuses; `network` metadata identifies the required egress host and
   browser fallback.
2. Uses `submit_run` with `dry_run: true` as the readiness check. GCS
   automatically starts ingest preprocessing when it commits the final PUT.
   Automated de-identification is off by default and runs during ingest only
   when enabled for your organization. While ingest is running, the dry run
   returns a structured `not_ready` result with a retry interval. No finalize
   tool or REST request is required.

Because the agent performs the `PUT` itself, `upload_slide` suits agents that
can execute HTTP requests and reach `storage.googleapis.com`. Agents in a
sandboxed client usually need a one-time setting to allow that traffic: on
claude.ai web and desktop, add `storage.googleapis.com` under your
organization's Settings, Capabilities, Allow network egress before the first
upload, then start a new chat so the sandbox picks the change up. See
[Claude](/mcp/claude) for the per-client setup.

For a multi-GB whole-slide image, or to skip the egress step entirely, upload in
your browser at
[app.strandai.com/samples/upload](https://app.strandai.com/samples/upload). The
browser uploader runs on your machine and does not require an egress setting. It
runs independently from MCP upload sessions. Discover its resulting owned sample
with `list_samples` or `get_sample`. For scripted or bulk uploads, the
[Python SDK](/sdks/python) and [REST API](/api/overview) stream slides for you
end to end.

## Example prompts

> Upload this H\&E slide to Strand AI, estimate a CD3e, CD8, and Ki67 run without
> reserving credits, show me the estimate, and ask before submitting it.

> Read sample `SAMPLE_ID` and summarize its job history. If job `JOB_ID` is
> still running, wait for its latest status, then export completed results as an
> OME-TIFF.

## See also

* [Claude](/mcp/claude): connect, authorize, and data handling.
* [ChatGPT](/mcp/chatgpt): connection prerequisites and upload limitations.
* [Python SDK](/sdks/python): the client library for programmatic uploads and pipelines.
* [REST API overview](/api/overview): the underlying HTTP surface.
* [Pricing](/pricing): how credits map to slides × markers.
