Metadata-Version: 2.5
Name: phenoworks-mcp
Version: 0.2.0
Summary: Connect AI assistants to PhenoWorks projects, datasets, and analysis pipelines through MCP.
Project-URL: Homepage, https://phenoworks.org/
Project-URL: Documentation, https://phenoworks.org/docs
Project-URL: Repository, https://github.com/OpenSciML/phenoworks
Project-URL: Issues, https://github.com/OpenSciML/phenoworks/issues
Author-email: haruiz <henryruiz22@gmail.com>
License-Expression: Apache-2.0
License-File: LICENSE
Requires-Python: >=3.11
Requires-Dist: mcp>=2.0.0
Requires-Dist: phenoworks-sdk<0.3.0,>=0.2.0
Description-Content-Type: text/markdown

# PhenoWorks MCP

Connect your AI assistant to PhenoWorks with the Model Context Protocol (MCP).
The assistant can find projects and datasets, inspect analysis modules, run
pipelines, and retrieve results using your PhenoWorks account permissions.

This package runs the MCP server that your assistant connects to. You need a
running PhenoWorks server and an MCP-compatible assistant; installing this
package does not install PhenoWorks or provide an AI model.

## Before you start

- Use **Python 3.11 or newer**.
- Have your PhenoWorks server URL, such as `https://your-phenoworks-server`.
- Create an API key in your PhenoWorks account settings.

Your server URL is the address of your own PhenoWorks installation, not the
public documentation website. Both the server root and a URL ending in `/api`
are accepted.

## Install

Install from PyPI in a Python virtual environment:

```bash
pip install phenoworks-mcp
phenoworks-mcp --help
```

The PhenoWorks Python SDK and MCP runtime are installed automatically. To
upgrade an existing installation, run `pip install --upgrade phenoworks-mcp`.

If you already use [uv](https://docs.astral.sh/uv/), you can run the package
without a separate install command:

```bash
uvx phenoworks-mcp --help
```

## Connect to Claude Desktop

Follow the [Claude Desktop setup tutorial](docs/claude-desktop.md) to create a
dedicated uv environment, configure your local PhenoWorks connection, and start
chatting with Claude.

## Connect over local HTTP

For a client that accepts a Streamable HTTP MCP URL, start the server in a
terminal. For example, in a macOS or Linux shell:

```bash
export PHENOWORKS_API_BASE_URL="https://your-phenoworks-server"
export PHENOWORKS_API_KEY="YOUR_API_KEY"
phenoworks-mcp
```

Leave the process running and add this **MCP server URL** to your assistant:

```text
http://127.0.0.1:8787/mcp
```

There are two different URLs: `PHENOWORKS_API_BASE_URL` points to PhenoWorks;
`http://127.0.0.1:8787/mcp` points to this MCP process. The default listens only
on your computer, so a cloud-hosted assistant cannot reach it through its own
`localhost`.

You can change the local port if needed:

```bash
phenoworks-mcp --port 8788
```

When configured with a fixed API key, callers of this MCP process act as that
PhenoWorks account. Keep this mode local to a trusted user.

## Try your first requests

Once connected, ask your assistant:

- "Check my PhenoWorks connection and show which account I am using."
- "List my projects, then show the datasets in the project I choose."
- "Find datasets configured for thermal imagery in project 7."
- "Show the available analysis modules and explain the inputs of one I choose."
- "Check the status of pipeline 123 and list its output artifacts."

Replace example IDs with IDs from your server. A useful first sequence is
`phenoworks_health`, `phenoworks_me`, then `list_projects`. A successful health
check establishes connectivity; `phenoworks_me` checks the account credentials.

For analysis, ask the assistant to discover the installed blocks and validate
the steps before using `run_dataset_pipeline`. Pipeline execution needs suitable
dataset inputs and a working PhenoWorks worker. Running or cancelling a pipeline
changes server state. Clients that support form elicitation receive a submission
confirmation; clients without it can submit directly, so use your assistant's
tool approval controls as appropriate.

## Available tools

| Task | Tools |
| --- | --- |
| Check connectivity and identity | `phenoworks_health`, `phenoworks_me` |
| Explore projects | `list_projects`, `get_project` |
| Explore datasets | `list_datasets`, `get_dataset`, `get_dataset_summary`, `filter_datasets_by_modality` |
| Understand data types | `list_data_types` |
| Inspect analysis modules | `search_analysis_blocks`, `describe_analysis_block`, `review_analysis_block_code` |
| Retrieve module citations | `get_analysis_block_citation` |
| Prepare and run analysis | `validate_pipeline_steps`, `run_dataset_pipeline` |
| Monitor runs | `list_pipeline_runs`, `get_pipeline_run`, `cancel_pipeline_run` |
| Retrieve results | `list_artifacts`, `download_artifact` |

Available data and actions depend on the account's server permissions. Modality
filtering checks the dataset's declared modalities, not whether its files have
already been uploaded.

## Where downloaded files go

`download_artifact` saves files on the **computer running this MCP server**.
By default, the workspace is `.phenoworks-agent-workspaces` under the process's
working directory. To choose a location, set an absolute path:

```bash
export PHENOWORKS_AGENT_WORKSPACE_DIR="/absolute/path/to/phenoworks-downloads"
```

For a desktop client, add this variable to its MCP configuration's `env` object.
Downloads are separated by user and session. An assistant running on another
computer will need shared storage or another way to retrieve those local files.

## Other authentication options

Use exactly one credential mode:

| Mode | Configuration |
| --- | --- |
| API key | `PHENOWORKS_API_KEY` |
| Bearer token | `PHENOWORKS_AUTH_TOKEN` instead of the API key |
| Each caller supplies credentials | `--forward-auth-headers` over HTTP |

For forwarded authentication, unset fixed credentials before starting:

```bash
unset PHENOWORKS_API_KEY PHENOWORKS_AUTH_TOKEN
phenoworks-mcp \
  --api-base-url https://your-phenoworks-server \
  --forward-auth-headers
```

Each MCP caller must send either `X-API-Key` or `Authorization: Bearer ...`.
This mode is not available with stdio. Remote deployments also need a reachable
address, HTTPS, and appropriate access controls; changing `--host` alone does
not configure those services.

## Troubleshooting

| What you see | What to check |
| --- | --- |
| `phenoworks-mcp: command not found` | Activate the environment where you installed it, or give your client the executable's full path. |
| Missing API endpoint | Set `PHENOWORKS_API_BASE_URL` or pass `--api-base-url`. The MCP CLI uses this variable, not the SDK's `PHENOWORKS_API_URL`. |
| Missing or conflicting credentials | Set exactly one authentication mode. Remove an old bearer token when switching to an API key. |
| Connection refused | Check that PhenoWorks is running and that the MCP host can reach its URL. For HTTP clients, also keep the MCP process running. |
| HTTP 401 or 403 | Check the key/token, its expiry where applicable, and the account's access permissions. |
| Tools do not appear after a change | Restart the MCP connection or client to refresh tool discovery. |
| Downloads are not on your laptop | Check the MCP host's workspace directory; files are saved where the server runs. |

See the [PhenoWorks documentation](https://phenoworks.org/docs) for setting up
projects, data, and workflows.

## Implementation and lifecycle

The Python SDK owns the pooled asynchronous HTTP client, credential validation,
and API error decoding. `server.py` registers the MCP tools and translates API
failures into tool errors. `cli.py` resolves explicit arguments and environment
configuration before starting the server. Source docstrings describe parameters,
return contracts, validation, and resource ownership.

`build_server(client)` transfers client cleanup to the MCP server lifespan.
Embedders invoking tools directly outside that lifespan must close the client
themselves. Forwarded credentials are supplied per request and never written into
shared client defaults. The backend remains the authority for access checks.

`get_dataset_summary` first fetches the dataset, then concurrently fetches its
surveys, assets, ancillary data, layers, pipeline runs, and artifacts. It returns
the keys `dataset`, `surveys`, `contents`, `ancillary_data`, `layers`,
`pipeline_runs`, and `artifacts`, and fails if a required request fails.
`contents` summarizes, for the dataset and for each survey, the data products
present with their sensors (modalities), named bands, processing methods, and
plot coverage, so an agent can match analysis blocks to the data.

`run_dataset_pipeline` accepts optional `modalities` and `data_products` filters
that narrow which assets reach the blocks. The server also publishes agent
instructions describing this vocabulary and the analysis planning workflow. This reduces sequential network
waits; it is not a measured production latency guarantee.

Explicit pipeline step versions are preserved; otherwise the account's preferred
version is resolved from the catalog. Canonical names take
precedence over class/display aliases, and argument values must be objects.
`validate_pipeline_steps` checks compatibility without submitting work. Pipeline
submission returns a single `run_id`, which is also the run's operation id.
Clients without form elicitation retain headless submission behavior. Once a
client advertises support, a failed confirmation stops submission; it never
silently authorizes the run.

Downloads stream in 1 MiB chunks to unique temporary files and atomically replace
the final artifact path. The last successful download wins for the same artifact
path; no caller consumes another download's partial file. Temporary files are
removed on normal errors and cancellation. Paths are scoped by the
API-authenticated user and a sanitized `x-phenoworks-agent-session` grouping header.
That header is not an authorization credential. SHA-256 and byte counts describe
the downloaded bytes. The workspace is local to the MCP host, so remote agent
hosts need shared storage or a separate retrieval mechanism.

## Offline checks

The server uses MCP 2.x (`mcp.server.mcpserver`). From the repository root,
install the local package and run these standard-library tests without pytest:

```bash
pip install -e ./packages/phenoworks-mcp
python -m unittest discover -s packages/phenoworks-mcp/tests -v
```

Tests cover concurrent summaries, canonical catalog resolution, invalid step
arguments, concurrent downloads, and confirmation failures. They use fake API
clients and temporary directories; they do not submit real pipelines.


## Describe and explain analysis blocks

Use `search_analysis_blocks` to find the canonical block name, then:

- `describe_analysis_block(name, version=None)` returns its description, schema,
  manifest, class name, authors, tags, and installed version. This is catalog
  metadata, not an inferred explanation of the implementation.
- `review_analysis_block_code(name, version=None, start_line=1, max_lines=200)`
  returns version-matched metadata and the stored `block.py` source, with line
  numbers and a full-source SHA-256 digest. The agent can explain processing
  steps, inputs, outputs, and side effects using this evidence. No code is imported
  or executed, and the tool does not generate an automated correctness verdict.

For example, after finding `image_2_hsv`, call:

```json
{"name": "image_2_hsv", "start_line": 1, "max_lines": 200}
```

Continue with `next_start_line` and the returned `version` to inspect subsequent
pages; `next_start_line: null` means the end has been reached. `max_lines` accepts
1–1000 lines. Imported helper files are not included, so explanations should
identify those limits rather than assume their behavior.

Both tools forward the caller's credentials and respect the backend's detail
and source visibility rules. If `PHENOWORKS_AGENT_MCP_ALLOWED_TOOLS` is
configured, include both new names in that allowlist. Restart the MCP server and
start a new agent conversation to refresh cached tool discovery.

## Shared SDK transport

MCP uses `phenoworks_sdk.AsyncPhenoWorksClient` for API requests, credentials,
errors, and streamed downloads. The SDK is a package dependency; there is no
separate MCP HTTP client. Local development resolves the sibling
`../phenoworks-sdk` package, and the MCP Docker image includes it.

MCP retains tool definitions, pipeline confirmation/version resolution,
request-header extraction, user/session workspace confinement, and progress
reporting. Forwarded credentials are passed per request, never stored on the
shared HTTP transport. API-key and bearer-token modes remain available.

The `filter_datasets_by_modality` tool accepts `modality`, optional `project_id`,
and optional `study_id`. It calls the SDK's `datasets.filter_by_modality` helper,
which filters the visible datasets' declared `supported_modalities`. It does not
claim that a dataset already contains assets of that modality.
