anndata-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@anndata-mcpshow me the summary of the AnnData object at /data/sample.h5ad"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
AnnData MCP
Allows to retrieve information about an AnnData object via MCP using the read_lazy function from anndata.
Getting started
Please refer to the documentation, in particular, the API documentation.
You can also find the project on BioContextAI, the community-hub for biomedical MCP servers: anndata-mcp on BioContextAI.
Related MCP server: Scanpy-MCP
Installation
You need to have Python 3.11 or newer installed on your system. If you don't have Python installed, we recommend installing uv.
There are several alternative options to install anndata-mcp:
Use
uvxto run it immediately:
uvx anndata-mcpInclude it in one of various clients that supports the
mcp.jsonstandard, please use:
{
"mcpServers": {
"anndata-mcp": {
"command": "uvx",
"args": ["anndata-mcp"]
}
}
}Install it through
pip:
pip install --user anndata-mcpInstall the latest development version:
pip install git+https://github.com/biocontext-ai/anndata-mcp.git@mainContact
If you found a bug, please use the issue tracker.
Citation
If this MCP server is useful to your research, please cite the BioContextAI and the anndata publications:
@article{BioContext_AI_Kuehl_Schaub_2025,
title={BioContextAI is a community hub for agentic biomedical systems},
url={http://dx.doi.org/10.1038/s41587-025-02900-9},
urldate = {2025-11-06},
doi={10.1038/s41587-025-02900-9},
year = {2025},
month = nov,
journal={Nature Biotechnology},
publisher={Springer Science and Business Media LLC},
author={Kuehl, Malte and Schaub, Darius P. and Carli, Francesco and Heumos, Lukas and Hellmig, Malte and Fernández-Zapata, Camila and Kaiser, Nico and Schaul, Jonathan and Kulaga, Anton and Usanov, Nikolay and Koutrouli, Mikaela and Ergen, Can and Palla, Giovanni and Krebs, Christian F. and Panzer, Ulf and Bonn, Stefan and Lobentanzer, Sebastian and Saez-Rodriguez, Julio and Puelles, Victor G.},
year={2025},
month=nov,
language={en},
}@article{Virshup2024,
title = {anndata: Access and store annotated data
matrices},
volume = {9},
ISSN = {2475-9066},
url = {http://dx.doi.org/10.21105/joss.04371},
DOI = {10.21105/joss.04371},
number = {101},
journal = {Journal of Open Source Software},
publisher = {The Open Journal},
author = {Virshup, Isaac and Rybakov, Sergei and Theis, Fabian J. and Angerer, Philipp and Wolf, F. Alexander},
year = {2024},
month = sep,
pages = {4371}
}Available Tools
3 toolsget_descriptive_statsA
Provide basic descriptive statistics (e.g., count, mean, std, min, max, etc. or value counts) for an attribute or attribute value of an optionally filtered AnnData object.
| Name | Required | Description | Default |
|---|---|---|---|
| key | No | The key of the attribute value to explore. Can be a single string or a list of strings for nested key retrieval (e.g., ['key1', 'key2'] to access attr_obj['key1']['key2']). Should be None for attributes X, obs, and var. | |
| path | Yes | Absolute path or URL to the AnnData file (.h5ad or .zarr) | |
| attribute | Yes | The attribute to describe | |
| filter_value | No | The value(s) to filter by. | |
| filter_column | No | The column name of the obs or var dataframe to filter by. | |
| filter_operator | No | The operator to use for the filter. | |
| columns_or_genes | No | The columns or genes to describe. For pandas.DataFrame attributes (e.g., obs, var), these are column names. For 'X' or 'layers' attributes, these are gene names (from var_names). If None, the entire dataset is considered. Also accepts glob-like patterns as input, e.g. ['RE*', 'CD4*']. | |
| filter_attribute | No | The attribute to filter by. One of 'obs' or 'var' or None for no filtering. Has to be provided TOGETHER with filter_column, filter_operator, and filter_value. | |
| return_value_counts_for_categorical | No | Whether to return the value counts for categorical columns. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | Yes | Any error message |
| description | Yes | The description of the attribute value |
| value_counts | Yes | The value counts for the attribute value |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses that the tool computes statistics and supports optional filtering, but it does not explicitly state that the operation is read-only, mention performance considerations, or describe any side effects. The nature of the tool makes read-only behavior likely, but this is not explicitly disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, concise sentence that front-loads the tool's purpose. It contains no redundant information and every word adds value. This is an exemplar of conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (9 parameters) and the presence of an output schema, the description is adequately complete. It introduces the core purpose and filtering capability, while the structured schema and output schema handle detailed parameter and return specifications. It could offer more guidance on usage scenarios, but the rich schema compensates.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides 100% parameter coverage with detailed descriptions for all 9 parameters. The tool description adds minimal parameter context, such as 'attribute or attribute value' hinting at the key/filter relationships, but the schema already does the heavy lifting, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool's function: computing basic descriptive statistics for AnnData attributes, optionally filtered. It uses specific verbs and resources, and the distinction from siblings (view_raw_data, get_summary) is evident from the emphasis on statistics rather than raw viewing or summarization.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage when descriptive statistics are needed, but it does not explicitly contrast with alternatives like get_summary or view_raw_data, nor does it state exclusions. It provides enough context that the AI can infer the general use case but lacks explicit guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_summaryB
Get a summary of an AnnData object from a file or URL.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Absolute path or URL to the AnnData file (.h5ad or .zarr) |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Any error message |
| n_obs | No | The number of observations (cells) in the AnnData object |
| X_type | No | The type and dtype of the X attribute |
| layers | No | The layers of the AnnData object (always arrays), all with shape (n_obs, n_vars) |
| n_vars | No | The number of variables (genes) in the AnnData object |
| has_raw | No | Whether the AnnData object has a raw attribute |
| uns_keys | No | The keys of the uns attribute and their types and shapes (if available, otherwise 'NA') |
| obsm_keys | No | The keys of the obsm attribute and their types and shapes |
| obsp_keys | No | The keys of the obsp attribute and their types, all with shape (n_obs, n_obs) |
| varm_keys | No | The keys of the varm attribute and their types and shapes |
| varp_keys | No | The keys of the varp attribute and their types, all with shape (n_vars, n_vars) |
| obs_columns | No | The columns of the obs dataframe and their dtypes |
| var_columns | No | The columns of the var dataframe and their dtypes |
| last_modified | No | The last modified time of the AnnData file in UTC, or None for URLs |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It states the input source but does not disclose whether the operation is read-only, what side effects might occur (e.g., network access), or what a 'summary' includes beyond the name.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single clear sentence that immediately states the core function. No wasted words or structure issues.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple, has an output schema, and 100% parameter coverage. However, it lacks usage guidelines and behavioral transparency, leaving contextual gaps that prevent it from being fully complete for an agent deciding when to invoke it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, with the description for 'path' already specifying absolute path or URL and file types (.h5ad/.zarr). The tool description adds no additional parameter context, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Get a summary of an AnnData object from a file or URL,' using a specific verb and resource. It distinguishes the purpose inherently from siblings by focusing on a high-level summary rather than raw data or descriptive statistics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided about when to use this tool versus the sibling tools (view_raw_data, get_descriptive_stats). There are no context notes, alternatives, or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
view_raw_dataC
View the raw data of an AnnData object.
| Name | Required | Description | Default |
|---|---|---|---|
| key | No | The key of the attribute value to view. Can be a single string or a list of strings for nested key retrieval (e.g., ['key1', 'key2'] to access attr_obj['key1']['key2']). | |
| path | Yes | Absolute path or URL to the AnnData file | |
| attribute | Yes | The attribute to view | |
| filter_value | No | The value(s) to filter the dataframe by. | |
| filter_column | No | The column name of the dataframe to filter by. Only applicable when the selected attribute (or attribute value) is a dataframe. Must be provided TOGETHER with filter_operator and filter_value. | |
| col_stop_index | No | The stop index for the column slice. Only applied to attributes or attribute values with a suitable type. | |
| row_stop_index | No | The stop index for the row slice. Only applied to attributes or attribute values with a suitable type. | |
| col_start_index | No | The start index for the column slice. Only applied to attributes or attribute values with a suitable type. | |
| filter_operator | No | The operator to use for the dataframe filter. | |
| row_start_index | No | The start index for the row slice. Only applied to attributes or attribute values with a suitable type. | |
| columns_or_genes | No | Column names or gene names to select. For pandas.DataFrame attributes (e.g., obs, var), these are column names. For 'X' or 'layers' attributes, these are gene names (from var_names) and are used instead of col_start_index/col_stop_index. If None, the entire attribute is considered or col_start_index/col_stop_index is used. Also accepts glob-like patterns as input, e.g. ['RE*', 'CD4*']. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | The data to view, e.g. a slice of a pandas.DataFrame or a numpy array in csv format. Other data types are converted to a plain string. |
| error | No | Any error message |
| data_type | No | The original type of the data |
| full_shape | No | The full shape of the data, before slicing, if applicable, otherwise 'NA' |
| slice_shape | No | The shape of the data after slicing, if applicable, otherwise 'NA' |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. The phrase 'View the raw data' implies a read-only operation, but it does not explicitly state side effects, data safety, authentication needs, or how output is structured. There is no information about slicing limits or potential performance implications, which is a significant gap for an 11-parameter tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise (one sentence) and directly states the core purpose without redundancy. It is front-loaded and efficient, though it may be too terse given the tool's complexity, but conciseness itself is well-served.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having a rich schema and output schema, the description does not explain the tool's behavior such as how raw data is formatted, the effect of row/column slicing, or interaction with filter parameters. For a tool with 11 parameters and complex semantics (e.g., nested key access, glob patterns), this single sentence is insufficient to convey the full capability, leaving the agent to discover behavior through the schema alone.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides descriptions for all 11 parameters (100% coverage), including nested key retrieval, filter operators, and column/gene selection. Since the schema fully documents parameter meanings, the description does not need to add extra details, and a baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('View') and resource ('raw data of an AnnData object'), which is distinct from the sibling tools get_summary and get_descriptive_stats that imply aggregated views. However, it does not explicitly differentiate itself, relying on the tool name and minimal description.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus the siblings, nor any prerequisites or context such as when raw data viewing is appropriate. It is a single sentence with no alternatives or exclusions mentioned, leaving the agent to infer usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
3 tool updates
v0.2.11- First observed
get_descriptive_stats - First observed
get_summary - First observed
view_raw_data
TDQS
The three tools have distinct purposes: view_raw_data displays raw data, get_summary provides a structural overview, and get_descriptive_stats computes statistical summaries. While summary and stats could overlap slightly, their focus on structure vs. attribute-level statistics keeps them distinguishable.
All tool names follow a consistent verb_noun pattern using 'view_' or 'get_' prefixes, making the naming predictable and easy to understand.
With only 3 tools, the server is on the thin side but appropriate for a focused read-only inspection toolset. It is not too sparse to be useless, but it offers limited functionality.
The server is missing common AnnData operations such as listing attributes, accessing subsets, or modifying/saving data. This creates significant gaps for users expecting a more complete workflow, though basic inspection is covered.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
MCP gateway federating 21 biomedical MCP servers behind one endpoint: gnomAD, ClinVar, HPO, VEP.
An MCP server that provides read access to your cloud storage providers, bank accounts and more.
Related MCP Servers
- FlicenseBqualityDmaintenanceEnables AI agents to read and understand local Mendix project structure and logic by connecting directly to the .mpr file via MCP. Allows querying microflows, entities, attributes, and modules in read-only mode without requiring cloud access.41-
- AlicenseNot gradedqualityCmaintenanceProvides a natural language interface for scRNA-Seq analysis using the Scanpy library, supporting operations such as data preprocessing, clustering, and visualization. It enables AI agents and clients to perform complex single-cell transcriptomics workflows through the Model Context Protocol.2BSD 3-Clause
- AlicenseAqualityBmaintenanceMCP server for reading and inspecting local Excel files (.xlsx, .xlsm, .xls, .xlsb, .ods) with tools for inspecting metadata, reading ranges, and profiling structure.313MIT
- AlicenseNot gradedqualityDmaintenanceEnables interaction with AnnData objects via the Model Context Protocol, allowing querying and manipulation of annotated data matrices for single-cell genomics.2MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/biocontext-ai/anndata-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server