# Open Targets Platform MCP [![Commit activity](https://img.shields.io/github/commit-activity/m/opentargets/open-targets-platform-mcp)](https://github.com/opentargets/open-targets-platform-mcp/commits) [![License](https://img.shields.io/github/license/opentargets/open-targets-platform-mcp)](https://github.com/opentargets/open-targets-platform-mcp/blob/main/LICENSE) > **⚠️ DISCLAIMER: This project is currently experimental and under active development. Features, APIs, and documentation may change without notice ⚠️** **Model Context Protocol (MCP) server for the [Open Targets Platform API](https://platform.opentargets.org/)** This package is the official Open Targets Platform MCP server implementation that enables AI assistants to interact with the Open Targets Platform GraphQL API, a comprehensive resource for target-disease associations and drug discovery data. ## Quick Navigation - [Features](#features) - [Official MCP Server](#official-mcp-server) - [Local Deployment](#local-deployment) - [Advanced Deployment](#advanced-deployment) - [Available Commands](#available-commands) - [Server Settings](#server-settings) - [Available Tools](#available-tools) - [Strategy](#strategy) - [Claude Desktop Setup](#claude-desktop-setup) - [Project Structure](#project-structure) - [Testing](#testing) - [Contributing](#contributing) - [License](#license) ## Features - 🔍 **Category-Based Schema Access**: Fetch and explore focused subsets of the Open Targets Platform GraphQL schema using category-based subschemas - 🚀 **Pre-fetched Schema Optimization**: The GraphQL schema is pre-fetched and cached at server startup to ensure immediate availability for tools - 📊 **Query Execution**: Execute custom GraphQL queries against the Open Targets Platform API - ⚡ **Batch Query Processing**: Execute the same query multiple times with different parameters efficiently - 🔎 **Entity Search**: Search for entities across multiple types (targets, diseases, drugs, variants, studies) - 🛠️ **CLI Tools**: Easy-to-use command-line interface for starting the server - 🎯 **jq Filtering** (Optional): Server-side JSON processing using [jq](https://jqlang.org/) to reduce token consumption and improve performance. See [jq Filtering](#jq-filtering-optional) for details. ## Official MCP Server The easiest way to use Open Targets Platform MCP is through the hosted service provided by Open Targets infrastructure at `https://mcp.platform.opentargets.org/mcp` ## Local Deployment ### Via uvx (Quick Start) The fastest way to get started is using `uvx`, which will automatically download and run the package directly from GitHub. **Examples:** ```bash # Start HTTP server bound to localhost:8000 (default) uvx --from git+https://github.com/opentargets/open-targets-platform-mcp otp-mcp # Get help uvx --from git+https://github.com/opentargets/open-targets-platform-mcp otp-mcp --help # With jq filtering enabled uvx --from git+https://github.com/opentargets/open-targets-platform-mcp otp-mcp --jq ``` ### Docker Deployment You can run the MCP server using the official Docker image: ```bash # Pull the latest image docker pull ghcr.io/opentargets/open-targets-platform-mcp # Run as a daemon with HTTP transport docker run -d \ -p 8000:8000 \ -e OTP_MCP_HTTP_HOST=0.0.0.0 \ ghcr.io/opentargets/open-targets-platform-mcp # Run as a daemon with jq filtering enabled docker run -d \ -p 8000:8000 \ -e OTP_MCP_HTTP_HOST=0.0.0.0 \ -e OTP_MCP_JQ_ENABLED=true \ ghcr.io/opentargets/open-targets-platform-mcp ``` ### Server Settings For available CLI arguments and environment variables, see the [Server Settings](#server-settings) table. ## Advanced Deployment Both advanced deployment options require cloning the repository and setting up the virtual environment first: ```bash # Clone the repository git clone https://github.com/opentargets/open-targets-platform-mcp.git cd open-targets-platform-mcp # Install dependencies uv sync --python 3.10 ``` ### FastMCP CLI For advanced usage and to utilize all FastMCP options, you can use the FastMCP CLI directly with the server module: ```bash # Run using FastMCP CLI uv run fastmcp run ./src/open_targets_platform_mcp/server.py ``` > **Note**: For all FastMCP CLI options, see the [FastMCP documentation](https://gofastmcp.com/patterns/cli#fastmcp-run). > **Note**: Use environment variables (see [Server Settings](#server-settings) table) to configure the server when using FastMCP CLI. ### Development Installation (Editable) For development or to modify the codebase: ```bash # Run the server uv run otp-mcp # Get help uv run otp-mcp --help ``` ## Available Commands The package provides two command variants: - `otp-mcp`: Shorter alias (recommended) - `open-targets-platform-mcp`: Full command name Both commands are functionally identical. ## Server Settings Configure the server using environment variables (all prefixed with `OTP_MCP_`). The following table shows all available configuration options: | Environment Variable | CLI Option | Description | Default | |---------------------|------------|-------------|---------| | `OTP_MCP_API_ENDPOINT` | `--api` | Open Targets Platform API endpoint URL | `https://api.platform.opentargets.org/api/v4/graphql` | | `OTP_MCP_SERVER_NAME` | `--name` | Server name displayed in MCP | `"Model Context Protocol server for Open Targets Platform"` | | `OTP_MCP_TRANSPORT` | `--transport` | Transport type: `stdio` or `http` | `http` | | `OTP_MCP_HTTP_HOST` | `--host` | HTTP server host (only used with `http` transport) | `localhost` | | `OTP_MCP_HTTP_PORT` | `--port` | HTTP server port (only used with `http` transport) | `8000` | | `OTP_MCP_STATELESS_HTTP` | `--stateless-http` | Enable stateless HTTP mode (only used with `http` transport) | `true` | | `OTP_MCP_API_CALL_TIMEOUT` | `--timeout` | Request timeout in seconds for API calls | `30` | | `OTP_MCP_JQ_ENABLED` | `--jq` | Enable jq filtering support | `false` | | `OTP_MCP_RATE_LIMITING_ENABLED` | `--rate-limiting` | Enable rate limiting | `false` | | `OTP_MCP_RATE_LIMITING_MAX_REQUESTS_PER_SECOND` | _(env only)_ | Maximum requests per second when rate limiting is enabled | `3` | | `OTP_MCP_RATE_LIMITING_BURST_CAPACITY` | _(env only)_ | Maximum burst capacity when rate limiting is enabled | `100` | | `OTP_MCP_DETAILED_TIMING_ENABLED` | `--detailed-timing` | Enable logging of detailed timing information for requests | `false` | **Examples:** **Using environment variables:** ```bash export OTP_MCP_TRANSPORT=stdio export OTP_MCP_JQ_ENABLED=true otp-mcp ``` **Using CLI options:** ```bash otp-mcp --transport stdio --jq ``` **Note:** CLI options take precedence over environment variables when both are provided. ## Available Tools The MCP server provides the following tools: 1. **`get_open_targets_graphql_schema`**: Fetch category-based subschemas from the Open Targets Platform API, including detailed documentation for relevant types and fields 2. **`get_type_dependencies`**: Explore schema type relationships by fetching the exact GraphQL SDL (Schema Definition Language) subset for specified types and all their recursively reachable dependencies 3. **`query_open_targets_graphql`**: Execute GraphQL queries to retrieve data about targets, diseases, drugs, and their associations 4. **`batch_query_open_targets_graphql`**: Execute the same GraphQL query multiple times with different variable sets for efficient batch processing 5. **`search_entities`**: Search for entities across multiple types (targets, diseases, drugs, variants, studies) and retrieve their standardized IDs ## Strategy The MCP server implements a 3-step workflow that guides the LLM to efficiently retrieve data from the Open Targets Platform: ### Step 1: Learn Query Structure from Schema The LLM calls `get_open_targets_graphql_schema` with specific categories (e.g., "targets", "drug-mechanisms") to retrieve a focused subset of the schema. This provides detailed documentation for relevant types and fields, enabling the LLM to construct valid queries without being overwhelmed by the entire schema. The schema also includes specific guidance on how to properly declare GraphQL variables to avoid variable resolution errors. If deeper or more specific schema exploration is needed, the LLM can fall back to the `get_type_dependencies` tool to fetch the exact dependency tree and SDL subset for one or more specific types. **Key entity types include:** - **Targets/Genes**: Use ENSEMBL IDs (e.g., `ENSG00000139618` for BRCA2) - **Diseases**: Use EFO/MONDO IDs (e.g., `MONDO_0007254` for breast cancer) - **Drugs**: Use ChEMBL IDs (e.g., `CHEMBL1201583` for aspirin) - **Variants**: Use "chr_pos_ref_alt" format or rsIDs ### Step 2: Resolve Identifiers (if needed) When a user query contains common names (gene symbols, disease names, drug names), the LLM uses `search_entities` to convert them to standardized IDs required by the API. ### Step 3: Execute Query The LLM constructs and executes GraphQL queries using: - Standardized IDs from Step 2 - Query structure from the schema - **jq filters** (optional, when enabled) to extract only requested fields, minimizing token consumption **Tool selection:** - `query_open_targets_graphql` for single queries - `batch_query_open_targets_graphql` for multiple identical queries with different parameters (reduces latency and tokens) ### jq Filtering (Optional) The MCP server supports optional server-side JSON processing using jq expressions. This feature is **disabled by default** but can be enabled if you want to reduce token consumption. #### Enable jq Filtering When: - You want to reduce token consumption by extracting only specific fields from API responses - Working with large API responses where only a subset of data is needed - The calling LLM is proficient at tool calling and can reliably construct jq filters #### Disable jq Filtering When: - Simplicity is preferred over optimization - Working with straightforward queries that don't benefit from filtering - The LLM should receive complete API responses #### How jq Filtering Works When jq filtering is enabled, the query tools expose a `jq_filter` parameter. The jq filter is applied server-side before the response is returned, extracting only the relevant data and discarding unnecessary fields. **Example:** To extract only the gene symbol and ID from a target query: ```jq jq_filter: ".data.target | {id, symbol: .approvedSymbol}" ``` This significantly reduces token consumption by returning only the requested fields instead of the full API response. ## Claude Desktop Setup For detailed instructions on configuring the Open Targets Platform MCP server with Claude Desktop, including both remote hosted service and local installation configurations, see [CLAUDE_DESKTOP.md](CLAUDE_DESKTOP.md). ## Testing The test suite is built around two guiding principles: **1. Test at the highest meaningful level.** Tests exercise the server through the [fastmcp](https://gofastmcp.com/) in-process client (`Client.call_tool()`), the same interface an LLM uses at runtime. This makes every test a near-system test: tool registration, argument validation, description generation, and response serialisation are all covered as a single end-to-end path, rather than testing internal functions in isolation. **2. Use GraphQL replay instead of live network calls.** Real API responses are recorded once into a cassette file (`test/fixtures/generated/graphql_cassette.json`) by running the generator script against the live API. During normal test runs the cassette is replayed deterministically, so tests are fast, reproducible, and do not depend on network availability. The cassette is regenerated intentionally when new queries are needed: ```bash uv run python test/fixtures/generated/generate_fixtures.py ``` To run tests against the live API instead of the cassette: ```bash uv run python -m pytest --live ``` ## Contributing Contributions are welcome! Please open an issue or submit a pull request on the [GitHub repository](https://github.com/opentargets/open-targets-platform-mcp). ## License This project is licensed under the terms of the license specified in [LICENSE](LICENSE).