# OFFX MCP Server

MCP Server for searching drugs, adverse events, alerts, and scores in the OFFX (Target Safety) database.

## Installation

```bash
# Using npm (if published)
npm install @uh-joan/offx-mcp-server
```

## Quick Start

1. Set up your environment variables:
```env
OFFX_API_TOKEN=your_offx_api_token
USE_HTTP=true  # Optional: run as HTTP server
PORT=3000      # Optional: specify port for HTTP server
```

2. Run the server:
```bash
# As MCP server
npx offx-mcp-server

# As HTTP server
USE_HTTP=true PORT=3000 npx offx-mcp-server
```

## Features
- Direct access to OFFX (Target Safety) drug and safety database
- Search by drug, adverse event, target, action, or name
- Retrieve alerts and scores for drugs
- Structured JSON responses
- Pagination support for large result sets

## Supported Formats

The following types are OFFX-API compatible:

| Field   | Format      | Comments                       |
|---------|-------------|--------------------------------|
| dates   | yyyy-mm-dd  | Specification ISO 8601         |
| strings | String      | No quotes needed in JSON       |
| numbers | Integer     | Only accepts integers          |

## Optional Filter Parameters

The following filters are OFFX-API compatible. For fields that accept multiple values, use comma-separated numbers (e.g., `adverse_event_id=10000059,10000081`).

| Field                | Format                  | Allowed Values/Comments                                                                                       |
|----------------------|-------------------------|--------------------------------------------------------------------------------------------------------------|
| Adverse Event        | Comma separated number  | Example: `adverse_event_id=10000059,10000081,10001761`                                                      |
| Alert Type           | Comma separated number  | 1 - Class Alert, 2 - Drug Alert                                                                             |
| Alert Phase          | Comma separated number  | 1 - Clinical/Postmarketing, 2 - Preclinical, 3 - Clinical, 4 - Postmarketing, 5 - Target Discovery, 6 - Phase I, 7 - Phase II, 8 - Phase III, 9 - Phase IV, 10 - Phase I/II, 11 - Phase II/III, 12 - Phase III/IV |
| Reference source type| Comma separated number  | 9 - Congress, 10 - Website Reference, 11 - Company Communication, 27 - Health Organization, 24 - Database, 22 - DailyMed, 23 - Regulatory Agency Briefing, 25 - Patent, 12 - Medical Society Communication, 13 - Research Institution Communication, 14 - Regulatory Agency Communication, 15 - Regulatory Agency Guideline, 16 - Patient Advocacy Group communication, 17 - Other, 18 - Book, 19 - Journal, 20 - Congress Alert, 21 - Congress & Conferences, 26 - Clinical Trial Registry |
| Level of evidence    | Comma separated number  | 1 - Confirmed/Reported, 2 - Suspected, 3 - Refuted/Not Associated                                           |
| On/Off Target        | Comma separated number  | 1 - On-Target, 2 - Off-Target, 3 - Not Specified                                                            |
| Alert Severity       | String                  | yes, no                                                                                                     |
| Ordering             | String                  | order_by_date=desc/asc, order_by_adv=desc/asc                                                               |

Refer to these tables when using filter parameters in the endpoints below.

## Tools

1. `offx_search_drugs`
   - Search drugs by name in the OFFX database
   - Input: `{ drug: string }`
   - Example: `{ "drug": "everolimus" }`

2. `offx_get_drug_alerts`
   - Retrieve alerts for a drug by drug_id (with optional filters)
   - Input: Complex object with drug_id and optional filters
   - Example: `{ "drug_id": "140448", "alert_type": "serious" }`

3. `offx_get_drugs_by_action`
   - Retrieve drugs by target and action ID
   - Input: `{ target_id: string, action_id: string }`

4. `offx_get_drugs_by_adve`
   - Retrieve drugs by adverse event ID
   - Input: `{ adverse_event_id: string, page?: number }`

5. `offx_get_drug_score`
   - Get drug score by drug id (and optionally adverse event id)
   - Input: `{ drug_id: string, adverse_event_id?: string }`

6. `offx_search_adverse_events`
   - Search adverse events by name in the OFFX database (min 3 chars)
   - Input: `{ adverse_event: string }`
   - Example: `{ "adverse_event": "Anaemia" }`

7. `offx_get_adverse_events`
   - Get adverse events by drug id or target id
   - Input: `{ drug_id?: string, target_id?: string }`

8. `offx_search_targets`
   - Search targets by target name in the OFFX database
   - Input: `{ target: string }`
   - Example: `{ "target": "ALK" }`

9. `offx_get_drug`
   - Get drug masterview by drug id with optional filters
   - Input: Complex object with drug_id and optional filters

10. `offx_get_target`
    - Get target masterview by target_id and action_id with optional filters
    - Input: Complex object with target_id, action_id and optional filters

11. `offx_get_targets`
    - Get primary/secondary targets for a drug or targets by adverse event
    - Input: `{ drug_id?: string, type?: "primary"|"secondary", adverse_event_id?: string }`

## HTTP API Endpoints

When running in HTTP mode (`USE_HTTP=true`), the following REST endpoints are available. All endpoints accept a POST request with a JSON body as described below:

1. `POST /offx_search_drugs`
   - Search drugs by name in the OFFX database
   - Body: `{ "drug": "semaglutide" }`

2. `POST /offx_get_drug_alerts`
   - Get alerts for a drug
   - Body: `{ "drug_id": "140448", "alert_type": "serious" }`

3. `POST /offx_get_drugs_by_action`
   - Get drugs by target and action
   - Body: `{ "target_id": "12345", "action_id": "67890" }`

4. `POST /offx_get_drugs_by_adve`
   - Get drugs by adverse event
   - Body: `{ "adverse_event_id": "12345" }`

5. `POST /offx_get_drug_score`
   - Get drug safety score
   - Body: `{ "drug_id": "140448" }`

6. `POST /offx_search_adverse_events`
   - Search adverse events by name
   - Body: `{ "adverse_event": "Anaemia" }`

7. `POST /offx_get_adverse_events`
   - Get adverse events for drug/target
   - Body: `{ "drug_id": "140448" }`

8. `POST /offx_search_targets`
   - Search targets by name
   - Body: `{ "target": "ALK" }`

9. `POST /offx_get_drug`
   - Get drug masterview
   - Body: `{ "drug_id": "140448", "page": 1 }`

10. `POST /offx_get_target`
    - Get target masterview
    - Body: `{ "target_id": "12345", "action_id": "67890", "page": 1 }`

11. `POST /offx_get_targets`
    - Get targets for drug/adverse event
    - Body: `{ "drug_id": "140448", "type": "primary" }`

## Setup

### Environment Variables
The server requires an OFFX API token:

```env
OFFX_API_TOKEN=your_offx_api_token
```

### Installing on Claude Desktop
Before starting make sure [Node.js](https://nodejs.org/) is installed on your desktop for `npx` to work.
1. Go to: Settings > Developer > Edit Config

2. Add the following to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "offx": {
      "command": "npx",
      "args": [
        "-y",
        "@uh-joan/offx-mcp-server"
      ],
      "env": {
        "OFFX_API_TOKEN": "your_offx_api_token"
      }
    }
  }
}
```

3. Restart Claude Desktop and start exploring drug safety data!

## Build (for devs)

```bash
git clone https://github.com/uh-joan/offx-mcp-server.git
cd offx-mcp-server
npm install
npm run build
```

For local development:
```bash
# Copy example environment file
cp .env.example .env

# Edit .env with your credentials
vim .env  # or use your preferred editor

# Start the server
npm run start
```

## Docker

```bash
docker build -t offx-mcp-server .
docker run -i --env-file .env offx-mcp-server
```

## License

This MCP server is licensed under the MIT License.

## Disclaimer

OFF-X™ is a commercial product and trademark of Clarivate Analytics. This MCP server requires valid OFF-X API credentials to function. To obtain credentials and learn more about OFF-X, please visit Clarivate's OFF-X page.

This project is not affiliated with, endorsed by, or sponsored by Clarivate Analytics. All product names, logos, and brands are property of their respective owners.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

> **Note:** For `alert_type`, use only numeric codes as a string:
>
> | Code | Alert Type   |
> |------|--------------|
> | 1    | Class Alert  |
> | 2    | Drug Alert   |
>
> You can specify more than one, e.g. `"alert_type": "1,2"`.