eLabFTW MCP
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| MCP_JWT_SECRET | No | Secret used to HMAC-sign the personal tokens in hosted (multi-user) mode. Required when running with --hosted, e.g. generated via python -c 'import base64,os;print(base64.urlsafe_b64encode(os.urandom(32)).decode())'. | |
| ELABFTW_API_KEY | Yes | Your eLabFTW API key (eLabFTW → Account → API keys). Required for local stdio usage; can be set via config.yml or the environment variable. | |
| ELABFTW_BASE_URL | Yes | Base URL of the eLabFTW instance, e.g. https://elntest.ub.tum.de (required for local stdio usage; can be set via config.yml or the environment variable). | |
| ELABFTW_MCP_AI_KEY | No | API key for the OpenAI-compatible AI endpoint used by review_experiment, suggest_tags and suggest_metadata. | |
| ELABFTW_MCP_CONFIG | No | Path to the configuration file (config.example.yml → config.yml); everything can be overridden by environment variables. | |
| ELABFTW_MCP_AI_MODEL | No | Model used for the AI tools (OpenAI-compatible chat-completions endpoint). Without a key the AI tools answer with the upstream placeholder wording instead of failing. | |
| ELABFTW_MCP_AUDIT_LOG | No | Path to the audit log (JSONL) written by the hosted multi-user mode. | |
| MCP_TOKEN_EXPIRY_DAYS | No | Expiry of the issued personal tokens in hosted mode, in days. | |
| ELABFTW_MCP_RATE_LIMIT | No | Rate limit applied by the server (registration rate limiting in hosted mode). | |
| ELABFTW_MCP_AI_BASE_URL | No | Base URL of the OpenAI-compatible chat-completions endpoint used by the AI tools. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| review_experimentA | Generate an AI review summary for an eLabFTW experiment (documentation quality, risks, suggestions, completeness score). Read-only — writes nothing. Needs an AI endpoint; without one the response carries the upstream placeholder marker. |
| suggest_tagsA | Suggest tags for an eLabFTW experiment or item based on its content. Read-only — writes nothing; use apply_tag_suggestions to persist them. |
| suggest_metadataA | Suggest structured metadata (custom fields) for an eLabFTW experiment or item. Read-only — writes nothing; feed the result into update_entity_metadata to persist it. |
| apply_tag_suggestionsB | Persist a list of (suggested) tags to an eLabFTW experiment or item. WRITE OPERATION — requires the tag write scope. |
| add_ai_review_commentA | Attach an AI-generated review comment to an eLabFTW experiment or item. The provenance header ('[AI-GENERATED] | | trace: …') is added automatically. WRITE OPERATION — requires the comment write scope. |
| get_entity_linksA | Fetch directed link edges of a single eLabFTW experiment or item: outgoing links (items_links / experiments_links) and incoming ones (related_items_links / related_experiments_links). Each edge carries from {type,id}, to {type,id} and a direction label. Read-only. |
| ensure_linkA | Idempotently create a directed link between an experiment and an item. WRITE OPERATION when dry_run=false — requires the link write scope. dry_run=true (default) only reports what would happen. Returns result: linked | already_linked | would_link (verified after writing). |
| delete_linkA | Idempotently remove a directed link between an experiment and an item. WRITE OPERATION when dry_run=false — requires the link write scope. dry_run=true (default) only reports. Returns result: unlinked | already_absent | would_unlink. |
| bulk_ensure_linksA | Idempotently create several directed links in one call. 'pairs_json' is a JSON array of {from_type, from_id, to_type, to_id} objects, at most bulk_links_max_pairs entries. WRITE OPERATION when dry_run=false — requires the link write scope. Returns a per-pair result list plus a summary. |
| bulk_delete_linksA | Idempotently remove several directed links in one call. 'pairs_json' is a JSON array of {from_type, from_id, to_type, to_id} objects. WRITE OPERATION when dry_run=false — requires the link write scope. Returns a per-pair result list plus a summary. |
| resolve_entity_by_queryA | Search experiments or items by query and return compact candidates for disambiguation. Read-only, always available. Returns status, entity_type, resolution (not_found | unique | ambiguous) and the candidate list — use it to find an id before acting on it. |
| ensure_link_by_queryA | Resolve the target entity by query and then link it idempotently. Query resolution works for experiments and items only. WRITE OPERATION when dry_run=false — requires the link write scope. With several matches the tool returns the candidates instead of guessing (on_ambiguous='error' makes it fail instead). |
| expand_links_networkA | Build the directed link graph around a root experiment/item via BFS. direction is 'both', 'outgoing' or 'incoming'; max_depth is capped at 3; node/edge/fan-out caps and optional filters (allowed_types, category_ids, status_ids, title_regex as JSON arrays/pattern) keep the graph bounded. Returns root, parameters, nodes, edges and truncation flags. Read-only. |
| list_experimentsA | Search or list elabFTW experiments. Returns a structured response with paging metadata, applied filters, and result records. Check paging.returned_count vs paging.limit to detect further pages. Use the dedicated filter arguments for known category/user/status IDs or tags instead of putting them into q. Always safe to call; never writes anything. |
| list_itemsB | Search or list elabFTW database items (resources). Returns a structured response with paging metadata, applied filters, and result records. Check paging.returned_count vs paging.limit to detect further pages. Use the dedicated filter arguments for known IDs or tags instead of q. Always safe to call; never writes anything. |
| list_experiment_templatesA | List elabFTW experiment templates (/experiments_templates). Returns a structured response with paging metadata and result records. Templates are reusable pre-filled starting points for new experiments and are DIFFERENT from item types (use list_item_types for those). Use get_experiment_template for a single template and create_experiment_from_template to use one. Always safe to call; never writes anything. |
| list_item_typesA | List elabFTW item types (/items_types), also called resource categories. They define the category structure and default content for database items and are DIFFERENT from experiment templates (use list_experiment_templates). Use get_item_type for a single one. Always safe to call; never writes anything. |
| get_experimentA | Fetch a single elabFTW experiment by its numeric ID. Returns the full experiment record including body, metadata, tags, comments, links and uploads. Always safe to call; never writes anything. |
| get_itemA | Fetch a single elabFTW database item (resource) by its numeric ID. Returns the item with metadata, tags, comments, links and uploads. Always safe to call; never writes anything. |
| get_experiment_templateA | Fetch a single elabFTW experiment template by its numeric ID. Returns the full template record including body, metadata and steps. Use list_experiment_templates to discover templates and create_experiment_from_template to create an experiment from one. Always safe to call; never writes anything. |
| get_item_typeA | Fetch a single elabFTW item type by its numeric ID. Returns the full item type record including body, metadata and steps. Use list_item_types to discover item types. Always safe to call; never writes anything. |
| list_experiment_categoriesA | List all experiment categories for the active elabFTW team. Specify team_id='current' (default) or a numeric team ID. Returns id, title, color and is_default per category — use those ids when filtering list_experiments by category. Always safe to call; never writes anything. |
| list_experiment_statusesA | List all experiment statuses for the active eLabFTW team. Specify team_id='current' (default) or a numeric team ID. Read-only. |
| list_item_categoriesA | List all item categories (resource categories) for the active eLabFTW team. Specify team_id='current' (default) or a numeric team ID. Use the returned ids when filtering list_items by category. Always safe to call; never writes anything. |
| list_item_statusesA | List all item statuses (resource statuses) for the active eLabFTW team. Specify team_id='current' (default) or a numeric team ID. Read-only. |
| get_connection_infoA | Return connection and session details for the active server: eLabFTW base URL, authenticated user, active team, effective server mode (read-only vs write-enabled), enabled tool groups, and a category catalogue (experiments and items) for the active team. Always safe to call; never writes anything. |
| get_current_user_capabilitiesA | Return a sanitized subset of the current user's capabilities and team roles. Calls /users/me and returns only the fields relevant for capability detection: userid, fullname, current team id, team memberships (id, name, is_admin, is_owner, is_archived), is_sysadmin, can_manage_compounds and can_manage_inventory_locations. Sensitive fields (email, API keys, signatures, preferences) are deliberately omitted. |
| refresh_team_capsA | Refresh and return the cached team capability flags for the current session. Fetches the team record, sanitizes the capability fields used for policy checks, updates the cache and returns the sanitized team_caps object. Does not write to eLabFTW resources. |
| list_stepsA | List all steps (tasks) attached to an eLabFTW experiment, item, experiment template or item type. Returns entity_type, entity_id, total_steps and a steps array (id, body, finished, ordering, deadline). With render_markdown=True a 'markdown' field with a GFM checkbox task list and deep links to each step is added. Read-only. |
| add_stepA | Add a new step (task) to an existing eLabFTW experiment, item, experiment template or item type. WRITE OPERATION — requires the step write scope. A deadline (date/datetime string) is set with a follow-up update because the create endpoint only stores the body. Returns entity_type, entity_id, step_id, the stored deadline and status='created'. |
| update_stepA | Update an existing step: body and/or deadline. WRITE OPERATION — requires the step write scope. At least one of body, deadline, deadline_notif must be provided; deadline_notif is reported as unsupported when the API rejects it (see notes). |
| toggle_stepA | Mark a step as complete or incomplete. WRITE OPERATION — requires the step write scope. finished=1 marks it complete, finished=0 incomplete; when omitted the server-side finish action flips the current state. |
| delete_stepA | Delete a step from an eLabFTW experiment, item, experiment template or item type. WRITE OPERATION — requires the step write scope. Returns status='deleted'. |
| create_experimentA | Create a new eLabFTW experiment. WRITE OPERATION — requires the create write scope. Discover valid category/status IDs first; never embed IDs in the title or body. If the team enforces experiment templates (force_exp_tpl), this tool is refused and create_experiment_from_template must be used. Returns the new id. |
| create_itemA | Create a new eLabFTW database item (resource). WRITE OPERATION — requires the create write scope. Items belong to item categories; discover valid IDs first and never embed IDs in the title or body. Returns the new id. |
| create_experiment_from_templateA | Create a new eLabFTW experiment from an experiment template. WRITE OPERATION — requires the create write scope. Use list_experiment_templates to find template IDs. include_steps/include_body decide whether the template's steps and body are copied. Returns the new id. |
| update_experiment_bodyA | Update the body of an existing eLabFTW experiment. WRITE OPERATION — requires the update write scope. The existing content_type (HTML=1 / Markdown=2) is preserved. mode='append' (default) keeps the original body byte-for-byte and appends the new text; mode='overwrite' replaces it and needs both the config flag allow_body_overwrite and confirm_overwrite=true. The result reports a read-back verification of the change. |
| update_item_bodyA | Update the body of an existing eLabFTW database item. WRITE OPERATION — requires the update write scope. mode='append' (default) preserves the original body and appends; mode='overwrite' replaces it and needs allow_body_overwrite plus confirm_overwrite=true. |
| update_entity_metadataA | Update the metadata (custom fields) of an eLabFTW experiment, item, experiment template or item type. WRITE OPERATION — requires the update write scope. 'fields' is a JSON string with an array of field objects ({key, value | values, type, group_id, allow_multi_values, description}); 'groups' optionally defines extra field groups ([{id, name}]). mode='merge' (default) keeps the existing metadata, 'overwrite' rebuilds it from the supplied fields. Returns the resulting field names and a read-back verification. |
| update_entity_fieldsA | Update top-level scalar fields (title, status, category) on an existing eLabFTW experiment or item. WRITE OPERATION — requires the update write scope. At least one of title, status_id, category_id must be given. Returns the applied fields and a read-back verification. |
| upload_image_from_contentA | Upload a single image attachment to an eLabFTW experiment or item from base64-encoded content. WRITE OPERATION — requires the update write scope. Only image/png, image/jpeg, image/gif and image/tiff are accepted. Returns the new upload id and size. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 41 tools
Most tools target a distinct resource+action and descriptions clarify boundaries well. However, the link family (ensure_link, ensure_link_by_query, bulk_ensure_links, delete_link, bulk_delete_links) and the info family (get_connection_info, get_current_user_capabilities, refresh_team_caps) have overlapping purposes that could cause misselection, and resolve_entity_by_query overlaps with the list_* searches.
The dominant pattern is consistent verb_noun snake_case (get_item, list_experiments, create_experiment, update_step, delete_link, bulk_ensure_links). A few names deviate slightly (review_experiment, refresh_team_caps, expand_links_network) but remain readable and predictable.
41 tools is heavy for a single MCP server and pushes well past the comfortable 3-15 range. While the eLabFTW domain is broad, the count is high enough to burden tool selection and discovery.
Strong read/link/step/update coverage, but notable lifecycle gaps: no delete for experiments, items, uploads, templates, or metadata. Read+create+update are covered while destructive/cleanup operations are largely absent, and there is no direct tag-list or item-type management.