Model Context Protocol server · Mass spectrometry

Ask questions of mass spectrometry data—directly.

MSMCP connects AI workflows to deterministic, auditable tools for inspection, QC, search, and hypothesis testing.

It is an MCP server between your LLM client and the operations that actually need doing: exact-mass validation, adduct and isotope chemistry, spectral similarity, quality control and library search. The model plans and interprets; the tools compute — against your files, on your machine.

LLMs should reason about mass spectrometry, not perform the arithmetic. Every scientific value on this page is a tool's output rather than a model's recollection, and every derived result carries a record of how it was made. That is the standard AI-assisted mass spectrometry should be held to, and MSMCP is infrastructure for it.

  • 13 tools
  • mzML · MGF · imzML
  • stdio, local only
  • no credentials
  • MIT

How the peaks stay out of the prompt

  1. 1experiment.mzML — 220 peaks, parsed in the server process. mzML, MGF and imzML are read locally; vendor formats are refused with conversion guidance.
  2. 2load_spectrum(…) returns metadata and a reference.
  3. 3
    reference =
    "ptr:spectrum:264a5ae9…"

    An opaque, random, expiring handle — never an address, an id or a path.

  4. 4Every later tool dereferences it server-side: validate_precursor · compute_cosine · generate_qc_summary · search_library

The model carries references, job IDs and verdicts — never spectra.

Example

One question, four tool calls.

The transcript below is a real run of MSMCP against a real acquisition and a real spectral library. The library scan is the slow step, and it never blocks the conversation — it is dispatched as a job and polled.

session · MSMCP 1.0.0 over stdio · reference and job IDs shortened
You

“I have a peak eluting at 3.80 min, precursor m/z 315.2321, MS2. Is it Δ⁹-THC?”

load_spectrum(file_path="experiment.mzML", spectrum_index=966)

kind=spectrum  format=mzML  backend=msmcp.mzml  ms_level=2
precursor_mz=315.2321  n_peaks=220  mz_range=[65.0382, 318.2416]
reference="ptr:spectrum:264a5ae9…"← the 220 peaks stay on the server

validate_precursor(theoretical_mass=315.2320, experimental_mass=315.2321)

VALIDATION PASSED — mass error 0.32 ppm, within the 5.0 ppm gate for the generic instrument class.

search_library(spectrum_reference="ptr:spectrum:264a5ae9…", database_file="libraries/MASSBANK.msp", scoring_method="classical")

Job ID: 2aafd7b8… — scanner reads the library from disk through the security boundary and searches it for real. The tool call returns immediately.

check_search_status(job_id="2aafd7b8…") → running …
check_search_status(job_id="2aafd7b8…") → completed

63,879 library spectra scored against 220 query peaks · classical greedy peak matching, ±0.02 Da · 94.9 s · 6 hits above the FDR threshold
RankCandidate (MassBank accession)Cosineq-value
1Δ⁹-tetrahydrocannabinolEQ362902 · C21H30O20.83090.0125
2Δ⁹-tetrahydrocannabinolAU158302 · C21H30O20.78420.0125
3Δ⁹-tetrahydrocannabinolAU158301 · C21H30O20.69580.0333
4progesteroneAU107706 · C21H30O20.69220.0333
5progesteroneAU107702 · C21H30O20.68620.0333
6Δ⁹-tetrahydrocannabinolEQ362901 · C21H30O20.68270.0333

The report MSMCP returns leads with its own caveat: these are candidate library matches ranked by the stated scorer and significance model, not validated compound identifications. Note the competition — the runner-up candidates are progesterone, a constitutional isomer at the same precursor m/z. That is what a deterministic score plus a false-discovery threshold buys an analytical chemist: the whole field, not one confident answer.

Provenance of this transcript: MSMCP 1.0.0: search_library with scoring_method="classical", run against MassBank's public MSP library (63,879 spectra) read from disk, querying spectrum #966 of a Bruker maXis LC–MS/MS acquisition (RT 3.795 min, precursor m/z 315.2321, 220 peaks, m/z range 65.0382–318.2416). The ppm verdict is a fresh validate_precursor call against MassBank's reference mass. Beyond shortened IDs, relative library paths and a stand-in filename for the acquisition, the numbers are the tools' own output, unedited — and the acquisition's real filename is not published here.

Why MSMCP

Grounded, deterministic, and honest about its own boundaries.

Grounded analysis

The model calls the tool; the tool does the chemistry. Exact masses, adduct shifts, isotope envelopes, ppm gates and cosine scores are computed by pure, unit-tested Python — the same functions every time, answering the same way. The model never invents a mass and never does the arithmetic.

The isotope envelope on this page is annotate_isotopes output for glucose; the 0.32 ppm verdict above is validate_precursor output. Neither was written by a language model.

Deterministic and auditable

Reproducible execution is separated from the model's variable interpretation. Fast operations return immediately; long ones — a library scan is minutes — are dispatched to a job executor and polled, so a client timeout can never truncate a result.

Every derived object carries an immutable provenance record: the operation, its parameters, the source file with reader backend and SHA-256 digest, the parent references, and the software and model versions. When an answer is wrong, you can tell whether the tool failed or the interpretation did.

Data control

MSMCP runs as a local child process on stdio: it makes no network calls of its own, stores no credentials, and ships no library data. Every file read is confined to one allowed root, under file-size and spectrum-count caps, and a path that escapes that root — symlinks included — is refused rather than read.

Its boundary is stated, not implied: the host spawns the server with your credentials, so anyone who can drive your LLM client can drive the server. Run it on a machine you own, and never expose it as a network service.

Tool output · annotate_isotopes

annotate_isotopes("C6H12O6")

M · 180.0634M+1 · 181.0668M+2 · 182.0681
Relative abundance, ×100 zoomM = 1.0000
0.06860.0147

M+1 and M+2 are shown on a separate scale; on the full-scale panel above they are 6.86 % and 1.47 % of the base peak. Values are the tool's output, reproduced without rounding.

Also verified in the tree

  • 13 tools across inspection, chemistry, similarity, quality control and library search — every one asserted by the test suite, and the wire schemas checked separately so no parameter reaches a model undocumented.
  • Readers for mzML (including zlib-compressed arrays, parsed by MSMCP itself), strict MGF, and imzML imaging data through MassFlow. Vendor formats are refused with conversion guidance instead of a stack trace.
  • MSP/NIST libraries are read from disk behind the same security boundary as an acquisition, so search_library searches the libraries you already have — no upload, no hosted service.
  • Empirical evaluation ships with the code: a notebook drives the real server end to end and fails the gate if a registered tool is never exercised or a workflow's context cost grows by half.
  • Spectral foundation models plug in behind one adapter (DreaMS runs real inference; LSM-MS2 awaits public weights). Core MSMCP never requires model weights — and if a model is unavailable it says so rather than returning a number that looks learned.

Get started

Install from source: clone, sync, run.

MSMCP is not published to PyPI yet, so there is no package to install and no binary to download: the path today is a clone, synced with uv. You need uv and Python 3.13, which .python-version pins for you. No API key, no account, no server to sign up for.

Clone, sync, run

git clone https://github.com/janusson/MSMCP.git
cd MSMCP
uv sync --extra dev      # creates .venv, installs runtime + dev dependencies
uv run msmcp             # serves MCP over stdio

Optional extras: --extra chem adds RDKit so SMILES can be converted to a formula; embedding-based scoring needs the DreaMS model installed separately from source. Neither is required for the core server.

Point a client at it

{
  "context_servers": {
    "msmcp": {
      "command": "uv",
      "args": ["run", "msmcp"],
      "env": {}
    }
  }
}

Shown for Zed's context_servers; any host that can spawn a stdio MCP server configures the same command and arguments.

Thirteen tools, grouped by what they do

Inspection
load_mzml_summary · load_spectrum · summarise_reference · release_reference
Exact-mass chemistry
predict_adduct_offset · annotate_isotopes
Similarity
validate_precursor · compute_cosine
Quality control
generate_qc_summary
Library search
search_library · check_search_status · cancel_search
Diagnostics
ping

Only cancel_search and release_reference change server state, and both advertise that on the wire.

Documentation & links

Everything authoritative lives with the code.

There is no separate documentation site, because two copies of a contract drift. Each link below goes to a maintained file in the repository.

Contact. There is no mailing list and no contact form. Bug reports, questions and feature discussion belong in GitHub Issues, where the answer stays searchable for the next person.