Skip to main content
Glama
Paulpey13

Labguru MCP Server

by Paulpey13

Labguru MCP Server

A modular, configurable Model Context Protocol server that exposes the Labguru laboratory management REST API as native LLM tools. Point any MCP client (Claude Code, Claude Desktop, etc.) at it and ask questions or run workflows against your Labguru instance in plain language.

Built with FastMCP + async httpx. Open source under the MIT license, so any lab is free to use and adapt it.

  • 64 tools + 4 guided prompts across every Labguru domain (experiments, protocols, projects, inventory, stocks, elements, shopping list / PO, reports, companies, instruments, attachments, maintenance, plus CMR and safety helpers).

  • Configurable per instance: domain, custom biocollections, CMR field mapping, timeouts, concurrency, cache, retries.

  • Two auth modes: personal API token, or email/password (auto re-auth on expiry).

  • Resilient: retry with exponential backoff on 429/5xx/network errors.

  • Fast: in-memory TTL cache for the scan-heavy tools (repeat scans are instant).

  • Safe: optional read-only mode that hides every write tool; read/write tool annotations let clients auto-approve reads.

Architecture

MCP_labguru/
  labguru_mcp/                package (importable, installable)
    config.py                 settings from env + optional JSON file
    client.py                 async HTTP client (auth, pagination, fan-out)
    formatting.py             pure payload-normalising helpers
    errors.py                 typed exceptions
    app.py                    builds settings + client + FastMCP; tool() decorator
    prompts.py                guided workflow prompts (PO, CMR, duplication)
    __main__.py               python -m labguru_mcp
    tools/                    one module per domain; importing registers tools
      experiments.py  protocols.py  projects.py  inventory.py  stocks.py
      elements.py  shopping.py  reports.py  companies.py  instruments.py
      attachments.py  maintenance.py  search.py  generic.py
  mcp_server.py               thin entry-point shim (back-compat)
  pyproject.toml              packaging + `labguru-mcp` console script
  .env.example                config template
  labguru.config.example.json optional JSON config template
  LICENSE                     MIT

Adding a tool = add a function decorated with @tool() (or @tool(write=True)) in the relevant tools/*.py module. No registry to update; importing the module registers it.

Related MCP server: LabArchives MCP Server

Install

cd MCP_labguru
pip install -e .          # installs deps and the `labguru-mcp` command
# or, without installing the package:
pip install -r requirements.txt

Requires Python 3.10+.

Configure

Copy .env.example to .env and fill it in (env vars and an optional labguru.config.json are also supported; env vars win).

Authentication (choose one)

  • Personal API token (recommended): set LABGURU_TOKEN. Generate it in the Labguru UI under Account > API token.

  • Email + password: set LABGURU_LOGIN and LABGURU_PASSWORD. They are exchanged for a session token via POST /api/v1/sessions.json, and the server re-authenticates automatically if the token expires (HTTP 401).

Run the whoami tool any time to confirm the active base URL and auth mode (only a short token hint is shown, never the secret).

Settings

Variable

Purpose

Default

LABGURU_TOKEN / LABGURU_API_KEY

Personal API token

LABGURU_LOGIN / LABGURU_PASSWORD

Email + password fallback

LABGURU_DOMAIN

Instance domain (no scheme)

eu.labguru.com

LABGURU_BASE_URL

Full base URL, overrides LABGURU_DOMAIN

LABGURU_READ_ONLY

Hide all write tools

false

LABGURU_TIMEOUT

HTTP timeout (seconds)

60

LABGURU_MAX_CONCURRENCY

Max concurrent calls in fan-out scans

8

LABGURU_CACHE_TTL

TTL (s) for the collection cache; 0 disables

300

LABGURU_MAX_RETRIES

Retries on 429/5xx/network errors

3

LABGURU_RETRY_BASE_DELAY

Base backoff delay (seconds)

0.5

LABGURU_BIOCOLLECTIONS

Comma-separated biocollection slugs

built-in list

LABGURU_DIRECT_INVENTORY

Comma-separated direct inventory types

built-in list

LABGURU_CMR_MAP

JSON: per-collection CMR risk/measure fields

see below

LABGURU_CONFIG

Path to a JSON config file

labguru.config.json

Adapting to your lab: if your instance uses different custom fields for CMR risk classification, or has extra custom biocollections, set LABGURU_CMR_MAP and LABGURU_BIOCOLLECTIONS rather than editing the code. The default CMR map is:

{
  "biochemistry": { "risk": "custom5", "measure": "custom6" },
  "culture":      { "risk": "custom3", "measure": "custom4" },
  "sp_bioch":     { "risk": "custom3", "measure": "custom4" }
}

Run

Register the server with your MCP client. A ready-made .mcp.json for Claude Code is included:

{
  "mcpServers": {
    "labguru": {
      "type": "stdio",
      "command": "python",
      "args": ["C:/Users/Paul/Documents/code/LABGURU/MCP_labguru/mcp_server.py"],
      "env": {}
    }
  }
}

If you installed the package you can use the console script instead:

{ "mcpServers": { "labguru": { "type": "stdio", "command": "labguru-mcp" } } }

For local development / inspection:

mcp dev mcp_server.py     # MCP Inspector UI
python -m labguru_mcp     # plain stdio server

Tools

Domain

Tools

Experiments

list_experiments, count_experiments, get_experiment, get_experiment_raw, get_experiment_samples, get_experiment_stock_ids, get_experiments_in_range, create_experiment, update_experiment

Protocols

list_protocols, get_protocol, search_protocols, find_protocols_with_sysid

Projects

list_projects, get_project, list_folders, create_project, update_project

Inventory

list_collections, list_inventory, search_inventory, get_inventory_item, get_collection_item, find_item_by_sysid, get_generic_item

CMR / Safety

get_cmr_items, get_safety_links

Stocks

list_stocks, get_stock, get_stock_by_barcode, create_stock, update_stock

Elements / UUID

get_element, get_element_by_uuid, get_element_rows, resolve_uuid, list_sections, update_element, create_element, create_section*

Shopping / PO

list_shopping_items, get_order, get_order_summary, get_last_order, add_shopping_item*

Reports

list_reports, get_report, create_report, update_report, tag_report*

Companies

list_companies, get_company

Instruments

list_instruments, get_instrument, post_measurement*

Attachments

list_attachments, get_attachment, download_attachment, upload_attachment*

Maintenance

list_maintenance_events

Cross-resource

global_search

Generic / introspection

api_request*, whoami, clear_cache, list_capabilities

* = write tool, hidden when LABGURU_READ_ONLY=true. Every tool also carries MCP annotations (readOnlyHint, destructiveHint) so clients can treat reads and writes appropriately.

api_request is an escape hatch for any endpoint without a dedicated tool; the auth token is injected automatically. list_capabilities reports the live configuration (collections, CMR map, cache/retry settings, registered tools). clear_cache drops the collection cache so the next scan refetches fresh data.

Prompts

Guided, parameterised workflows the client can launch (they orchestrate the tools above; they do not call the API directly):

Prompt

Purpose

generate_purchase_order(order_number)

Review a PO, check approvals, summarise totals, optionally create the report

cmr_report(start_id, end_id)

Cross-reference CMR products against an experiment ID range

duplicate_experiment(experiment_id)

Inspect an experiment and plan its duplication

safety_data_sheets(collections)

Collect safety data sheet (fiche de securite) links

Notes

  • List tools return slim summaries to keep payloads small; use the matching get_* / *_raw tool for the full JSON of a single record.

  • list_experiments, list_protocols, and list_stocks return the most recent records first (server-side sort via the Kendo grid syntax, since plain sort/direction params are rejected by Labguru). Pass oldest_first=true to reverse. Use count_experiments for the true total without fetching every page (instances can hold tens of thousands of records).

  • Pagination is handled internally (page / per_page), stopping when a page is empty or shorter than the page size. Wrapped responses (value, data, ...) are unwrapped automatically.

  • Fan-out scans (get_experiments_in_range, find_protocols_with_sysid, find_item_by_sysid, get_cmr_items, get_safety_links, global_search) use bounded concurrency and can be slow on large instances. Full-collection fetches are cached for LABGURU_CACHE_TTL seconds, so repeat scans within a session are near-instant; call clear_cache after a write to force a refresh.

  • Requests retry automatically on 429/5xx/network errors with exponential backoff (honouring Retry-After), and re-authenticate once on HTTP 401.

  • The server never writes to stdout (it would corrupt the JSON-RPC stream); warnings go to stderr.

License

MIT (c) 2026 Paul Peyssard, Neuro-Sys. See LICENSE.

A
license - permissive license
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Paulpey13/labguru_MCP_server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server