MCP interface
Optional MCP interface
The MCP server lets an AI agent inspect and extract timsTOF data through the same reader and centroiding code used by Python callers. It is a local stdio server. An MCP client launches it as a subprocess. Source acquisitions remain read-only, and complete spectrum exports go into a separate output directory.
The server is available starting in tdfpy 4.0.0. Install it with
pip install 'tdfpy[mcp]'. From a checkout, install and launch it with:
uv sync --extra mcp
uv run --extra mcp tdfpy-mcp --data-root /data/timstof --output-dir /data/tdfpy-results
The launch command is tdfpy-mcp, or python -m tdfpy.mcp. Ordinary pip install tdfpy does not install the MCP
SDK, and importing tdfpy does not import MCP or Pydantic.
Repeat --data-root to expose several input directories. With one root, tools
accept acquisition paths relative to it. With multiple roots, use absolute
paths returned by discovery. The output directory must be outside acquisition
folders. Paths in the launch configuration refer to the machine running the
server, which is also where the data must be accessible.
An MCP client that accepts an mcpServers configuration can use this entry for
an installed environment. Replace every placeholder with an absolute path:
{
"mcpServers": {
"tdfpy": {
"command": "/absolute/path/to/environment/bin/tdfpy-mcp",
"args": [
"--data-root", "/absolute/path/to/acquisitions",
"--output-dir", "/absolute/path/to/tdfpy-results"
]
}
}
}
On Windows, use the environment's Scripts/tdfpy-mcp.exe. For development, the
client can instead launch the absolute path to uv with arguments
run --directory /absolute/path/to/tdfpy --extra mcp tdfpy-mcp, followed by the
same data and output arguments. The client may require a different surrounding
configuration format, but the command and arguments are the same. This package
does not change client settings automatically.
What the agent can do
| Tools | Purpose |
|---|---|
server_info, discover_acquisitions |
Find configured roots, limits, and available acquisitions |
inspect_acquisition |
Summarize acquisition mode, frame types, retention-time coverage, and source files |
list_metadata_tables, read_metadata_table |
Inspect actual SQLite schema and page selected columns with typed filters |
query_frames |
Find frames by RT, polarity, and MS/MS type |
query_precursors |
Find DDA precursors by RT and precursor m/z |
query_dia_windows |
Find DIA windows by RT, isolation-center m/z, and window group |
query_prm_targets, query_prm_transitions |
Inspect PRM targets and find their measured transitions |
get_processing_options |
Discover both centroiders, ten noise filters and gates, smoothing, and region exclusion |
preview_spectrum |
Extract a spectrum with full-result statistics and a bounded strongest-peak preview |
export_spectrum |
Save a complete raw or centroided spectrum with extraction settings |
export_window_batch |
Save several DIA or PRM spectra while reusing adjacent windows' decoded frames |
read_artifact |
Inspect an export manifest or page through a numerical array |
convert_coordinates |
Convert TOF, m/z, scan, inverse mobility, voltage, and charge-aware CCS coordinates |
check_acquisition, check_frames |
Check supported metadata and page through binary integrity checks |
The tdfpy://guide resource explains units and tool sequencing. The
tdfpy://processing resource supplies configuration schemas, and
tdfpy://artifacts/{artifact_id} returns an export manifest. Two optional MCP
prompts, inspect_timstof and extract_timstof, guide common workflows. Clients
that do not expose resources or prompts can use the equivalent tools.
A typical extraction
- Discover the acquisition and inspect its mode.
- Query frames, precursors, or windows. Keep the returned selection object.
- Read the processing options before setting non-default parameters.
- Preview a small selection to check IDs, units, and processing settings.
- Export the complete result. For adjacent DIA or PRM windows, use a batch.
- Read the manifest or load the NPZ in Python for downstream analysis.
For example, query_dia_windows accepts:
{
"acquisition": "sample.d",
"rt": {"lower": 300.0, "upper": 330.0},
"mz": {"lower": 600.0, "upper": 650.0},
"limit": 10
}
The mz condition matches isolation centers. It does not select every window
whose isolation band overlaps the interval. A result contains a selection such
as {"kind": "dia_window", "id": 42}. This ID is the window's zero-based
position in the full acquisition lookup, not a window group or frame ID. Query
pagination does not renumber it. PRM transitions use the same index convention.
Frames and DDA precursors use their actual stored IDs.
Pass the selection to preview_spectrum or export_spectrum. A processing
configuration can use the existing Python algorithm names:
{
"mode": "centroid",
"centroider": {
"name": "MergePeaksCentroider",
"parameters": {"mz_tolerance": 8.0, "min_peaks": 3}
},
"noise": [
{"name": "MadThreshold", "parameters": {"k": 3.0}}
],
"ion_mobility_type": "ook0"
}
Parameters are validated against the actual algorithm definitions. Unknown
names and fields raise errors. All filters run before centroiding. The server
imposes no automatic centroid peak cap. An explicitly requested max_peaks
retains the underlying algorithm's seed-traversal meaning. The preview limit
only limits what appears in the tool response.
Frame selections can also specify scan_begin and scan_end. All selections
can use an optional mz_range, and frame or window selections can use
mobility_range. Each range has lower and upper fields. These physical
ranges select the output after processing. They do not change the ions seen by
the centroider. Mobility bounds use the requested output units. For changes to
pre-centroid processing, use the existing exclusion, smoothing, and noise options.
Numerical contracts
- RT is in seconds. Selection intervals and scan bounds are half-open.
- Raw mode returns digitizer peaks normalized to a 100 ms accumulation window. Smoothing can change intensities. Filtering and centroid thresholds can remove intensity. A reported intensity sum describes the selected processed result.
- Frame and window arrays have columns
[mz, intensity, ook0]or[mz, intensity, voltage], as stated in the export metadata. - DDA precursor arrays have columns
[mz, intensity]. They use the existing mobility-collapsed precursor picker. Processing overrides are rejected for these selections. QueryPasefFrameMsMsInfobyPrecursorto obtain individual frame and scan selections when custom processing is needed. - CCS conversion requires an explicit positive charge magnitude and m/z. The extraction tools do not assume that raw ions have charge +1.
- Empty valid selections return empty arrays. Read failures return tool errors. A preview contains the strongest peaks in descending intensity order, and its truncation flag makes omissions explicit. Exports retain complete arrays in the underlying Python API's order.
Exports contain named numerical arrays and a metadata Unicode array containing
JSON. Load with numpy.load(path, allow_pickle=False), then parse the manifest
with json.loads(str(data["metadata"])). The manifest records selections,
processing requests, columns, package version, and source file identity. Source
identity uses file sizes and modification times, not acquisition content hashes.
The returned SHA256 identifies the exported artifact itself.
Limits and operation
Metadata pages contain at most 200 rows, previews at most 100 peaks, and window
batches at most 32 windows. Discovery examines at most 20,000 directories and
does not follow directory symlinks. check_frames processes at most 128 frames
per request. Continue using next_offset until it is null. A single page's
success does not certify the rest of the acquisition. Metadata-check responses
show at most 200 issues with the total issue count and an explicit truncation flag.
The default frame limit is five million stored peaks. Raise it at startup with
--max-frame-peaks when a known dataset requires more. A spectrum selection may
reference at most 128 frames. Each export is limited to 512 MiB of uncompressed
numerical arrays. These are workload guards, not a guarantee against malformed
binary data exhausting memory. Initial Numba compilation can take longer than
subsequent requests, so give the client an appropriate tool timeout.
Each request opens and closes its readers. There are no persistent acquisition handles for an agent to leak. Keep input datasets unchanged during processing. The server permits no arbitrary Python execution, arbitrary SQL, source edits, network transport, or automatic format repair. File checks exercise tdfpy's supported-format guards and decoder. They do not replace independently captured vendor references or establish the scientific quality of an experiment.
Maintenance
Run just test-mcp for direct numerical comparisons and MCP protocol tests,
including a real stdio subprocess. The normal installed-wheel check verifies
that the core package works without MCP. The optional CI jobs exercise MCP on
Linux, Windows, and macOS. Run uv run python scripts/verify_distribution.py dist --with-mcp to check
both the core wheel and the optional install with its console entry point.
The implementation uses the official MCP Python SDK.