npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@uh-joan/cortellis-mcp-server

v1.4.1

Published

Comprehensive MCP server providing pharmaceutical intelligence through Cortellis APIs - drug discovery, clinical trials, literature search, regulatory documents, company profiles, deals analysis, and Named Entity Recognition with 19+ specialized tools

Downloads

175

Readme

Cortellis MCP Server

A modern, production-ready MCP (Model Context Protocol) server providing access to the Cortellis pharmaceutical database. This server has been completely transformed with a modular architecture, comprehensive error handling, testing, and deployment capabilities.

🚀 Features

  • MCP Protocol Compliance: Full MCP server implementation with stdio transport
  • 8 Comprehensive Tools: Complete access to Cortellis drug, company, deal, and trial data
  • Production Ready: Comprehensive error handling, monitoring, and logging
  • Modular Architecture: Clean separation of concerns with TypeScript
  • Docker Support: Multi-stage builds with security best practices
  • Comprehensive Testing: Unit and integration tests with coverage reporting
  • Secure Authentication: Digest authentication for Cortellis API access

📦 Installation

# Using npm
npm install @uh-joan/cortellis-mcp-server

# Using Docker
docker pull uh-joan/cortellis-mcp-server

🏃‍♂️ Quick Start

Environment Setup

Create a .env file with your Cortellis credentials:

CORTELLIS_USERNAME=your_username
CORTELLIS_PASSWORD=your_password

# Optional configuration
LOG_LEVEL=info         # error, warn, info, debug

Running the Server

# MCP Mode (stdio transport)
npx cortellis-mcp-server

# Development mode with auto-rebuild
npm run dev

Docker Deployment

# MCP Mode
docker run -e CORTELLIS_USERNAME=user -e CORTELLIS_PASSWORD=pass cortellis-mcp-server

Tools

  1. ci_search_drugs

    • Search for drugs in the Cortellis database
    • Optional Inputs:
      • query (string) - Raw search query
      • company (string) - Company ID for the developing company (e.g., "18614")
      • indication (string) - Indication ID (numeric ID only, e.g., "238" for Obesity). Use ci_explore_ontology to find the correct ID.
      • action (string) - Target specific action (e.g., glucagon)
      • phase (string) - Development status:
        • Uses LINKED format with short codes: S, DR, CU, C1-C3, PR, R, L, OL, NDR, DX, W
        • Important: only a single phase value is supported for the phase parameter; do not use OR/AND. If you need to search for multiple phases, run separate queries for each phase.
        • Examples:
          • phase: "L"
          • phase: "C1"
          • phase: "C2"
          • phase: "C3"
        • Status codes:
          • S: Suspended
          • DR: Discovery/Preclinical
          • CU: Clinical (unknown phase)
          • C1-C3: Phase 1-3 Clinical
          • PR: Pre-registration
          • R: Registered
          • L: Launched
          • OL: Outlicensed
          • NDR: No Development Reported
          • DX: Discontinued
          • W: Withdrawn
      • phase_terminated (string) - Last phase before NDR/DX
        • Uses short format with double colon: S, DR, CU, C1-C3, PR, R, L, OL, NDR, DX, W
        • Supports AND/OR operators
        • Examples:
          • phase_terminated: "C2"
          • phase_terminated: "C2 OR C3"
      • technology (string) - Drug technology (e.g., small molecule)
      • drug_name (string) - Name of the drug
      • country (string) - Country ID (e.g., "US")
      • offset (number) - For pagination
      • hits (number) - Number of results per page (default: 100)
      • company_size (string) - The size of a company based on market capitalization in billions USD
        • Format: '<X' for less than $XB, 'X' for greater than $XB
      • developmentStatusDate (string) - Date of change in status (only possible within LINKED queries). Use RANGE(>=YYYY-MM-DD;<=YYYY-MM-DD) for ranges. Example: RANGE(>=2023-01-01;<=2023-12-31)
      • historic (boolean) - Set to true to search using the historic development status fields. This is required for questions about the status of a drug at a specific point in the past (e.g., 'What drugs were in phase 3 in 2019?'). If you want to know the status as it was at a particular date or within a date range, always set historic: true and use the developmentStatusDate parameter.
    • Returns: JSON response with drug information and development status
  2. ci_explore_ontology

    • Explore taxonomy terms in the Cortellis database
    • Optional Inputs (at least one required):
      • term (string) - Generic search term
      • category (string) - Category to search within
      • action (string) - Target specific action
      • indication (string) - Disease/condition
      • company (string) - Company name
      • drug_name (string) - Drug name
      • target (string) - Drug target
      • technology (string) - Drug technology
    • Returns: JSON response with matching taxonomy terms
  3. ci_get_drug

    • Return the entire drug record with all available fields for a given identifier
    • Required Input:
      • id (string) - Numeric Drug Identifier (e.g. "101964" for tirzepatide, not the drug name)
    • Example: { "tool-name": "ci_get_drug", "arguments": { "id": "101964", "category": "report" // Optional. Values: "report" (default), "swot", "financial" } }
    • Returns: JSON response with complete drug record
  4. ci_get_company

    • Return the entire company record with all available fields for a given identifier
    • Required Input:
      • id (string) - Numeric Company Identifier (not the company name)
    • Example: { "tool-name": "ci_get_company", "arguments": { "id": "18614" } }
    • Returns: JSON response with complete company record
  5. ci_search_companies

    • Search for companies in the Cortellis database
    • Optional Inputs:
      • query (string) - Raw search query
      • company_name (string) - Company name to search for
      • hq_country (string) - Company headquarters country
      • deals_count (string) - Count for all distinct deals where company is principal/partner
        • Format: '<20' for less than 20 deals
        • Format: '20' or '>20' for greater than 20 deals (default behavior)
      • indications (string) - Top 10 indication terms
      • actions (string) - Top 10 target-based action terms
      • technologies (string) - Top 10 technologies terms
      • company_size (string) - The size of a company based on market capitalization in billions USD
        • Format: '<2' for less than $2B
        • Format: '2' or '>2' for greater than $2B (default behavior)
      • status (string) - Highest status of linked drugs
      • offset (number) - For pagination
      • hits (number) - Number of results per page (default: 100)
    • Returns: JSON response with company information
  6. ci_search_deals

    • Search for deals in the Cortellis database
    • Optional Inputs:
      • query (string) - Raw search query (if you want to use the full Cortellis query syntax directly)
      • dealDrugNamesAll (string) - Main name of drug including synonyms associated with the deal
      • indications (string) - Indications associated with the deal
      • dealDrugCompanyPartnerIndications (string) - The indication and the partner company linked to a drug associated with the deal
      • dealPhaseHighestStart (string) - Highest dev. status of the drug at the deal start
      • dealPhaseHighestNow (string) - Current highest dev. status of the drug
      • dealStatus (string) - Status of the deal
      • dealSummary (string) - Summary of the deal
      • dealTitleSummary (string) - Title or summary of the deal
      • technologies (string) - Technology linked to the drug
      • dealTitle (string) - Title of the deal
      • dealType (string) - Type of deal
      • actionsPrimary (string) - Primary mechanism of action associated with the deal
      • sortBy (string) - Sort order for results. Use '+field' for ascending or '-field' for descending. Supported fields: dealDateStart, dealDateEnd, dealDateEventMostRecent, dealTotalPaidSortBy, dealTotalProjectedCurrentSortBy, dealValuePaidToPrincipalMaxSortBy, dealValueProjectedToPrincipalMaxSortBy. Example: '+dealDateStart' for oldest first, '-dealDateStart' for newest first. Useful for queries like 'last 10 deals for a company'.
      • offset (number) - For pagination
    • Returns: JSON response with deal information
  7. ci_search_trials

    • Search for clinical trials in the Cortellis database
    • Optional Inputs:
      • query (string) - Raw search query for direct searching
      • sortBy (string) - Sort field (trialPhase, trialRecruitmentStatus, trialPatientCountEnrollment, trialDateStart, trialDateEnd, trialDateChangeLast)
      • trialTitleOfficial (string) - Official trial title
      • trialIdentifiers (string) - Trial identifiers (e.g., NCT00003140, CTI_umbrella)
      • indications (string) - Medical condition being treated
      • trialPhase (string) - Phase of clinical trial (e.g., 'C12' for Phase 1/2 or 'Phase 1/Phase 2 Clinical')
      • trialRecruitmentStatus (string) - Trial recruitment status
      • trialCompaniesSponsor (string) - Sponsoring organization (name or ID)
      • trialFunderType (string) - Organization type conducting the trial. Categories: academic, non profit, company, government
      • trialPatientCountEnrollment (string) - Number of patients (exact or RANGE format)
      • trialDateStart (string) - Trial start date (YYYY-MM-DD)
      • trialDateEnd (string) - Trial end date (YYYY-MM-DD)
      • hits (number) - Number of results per page (default: 20, max: 300)
      • offset (number) - For pagination
    • Returns: JSON response with clinical trial information
  8. ci_get_trial

    • Retrieve trial information. Can return the full trial record or trial sites based on the category parameter.
    • Required Input:
      • id (string) - Trial identifier (e.g., "9997", "77227")
    • Optional Inputs:
      • category (string) - Type of information to retrieve:
        • "report" (default) - Full trial record with all available fields
        • "sites" - Trial sites information
      • hits (number) - Number of results per page (for sites category only, default: 20)
      • offset (number) - Number of records to skip (for sites category only, default: 0)
    • Examples: { "tool-name": "ci_get_trial", "arguments": { "id": "9997", "category": "report" } } { "tool-name": "ci_get_trial", "arguments": { "id": "77227", "category": "sites", "hits": 20, "offset": 0 } }
    • Returns: JSON response with trial information based on the requested category

🏗️ Architecture

The server features a modern, modular architecture:

  • Modular Design: Separate modules for authentication, API client, tools, validation, and servers
  • Type Safety: Full TypeScript implementation with comprehensive type definitions
  • Error Handling: Structured error handling with proper logging and monitoring
  • Security: Built-in middleware for rate limiting, CORS, input validation, and security headers
  • Testing: Comprehensive test suite with Jest, including unit and integration tests
  • Configuration: Environment-based configuration with validation

See ARCHITECTURE.md for detailed technical documentation.

🛠️ Development

Prerequisites

  • Node.js 16+
  • TypeScript 5.0+
  • Valid Cortellis API credentials

Setup

# Clone the repository
git clone <repository-url>
cd cortellis-mcp-server

# Install dependencies
npm install

# Set up environment
cp .env.example .env
# Edit .env with your credentials

# Build the project
npm run build

# Run tests
npm test
npm run test:coverage

Available Scripts

npm run build          # Build TypeScript to dist/
npm run dev            # Development MCP mode with auto-rebuild
npm run dev:http       # Development HTTP mode with auto-rebuild
npm start             # Production MCP mode
npm run start:http    # Production HTTP mode
npm test              # Run tests
npm run test:watch    # Run tests in watch mode
npm run test:coverage # Generate coverage report
npm run lint          # Run ESLint
npm run lint:fix      # Fix ESLint errors
npm run clean         # Clean build artifacts

🚢 Deployment

Docker Production Deployment

# Build the image
docker build -t cortellis-mcp-server .

# Run MCP mode
docker run -e CORTELLIS_USERNAME=user -e CORTELLIS_PASSWORD=pass cortellis-mcp-server

# Run HTTP mode
docker run -e CORTELLIS_USERNAME=user -e CORTELLIS_PASSWORD=pass -e USE_HTTP=true -p 3000:3000 cortellis-mcp-server

Security Considerations

  • Credentials are never logged or exposed in error messages
  • HTTP mode includes rate limiting (100 requests per 15 minutes by default)
  • Security headers protect against common vulnerabilities
  • Container runs as non-root user
  • Multi-stage Docker build for minimal attack surface

🔌 MCP Integration

The server implements the Model Context Protocol (MCP) specification and can be used with any MCP-compatible client:

Claude Desktop Integration

Add to your Claude Desktop configuration:

{
  "mcpServers": {
    "cortellis": {
      "command": "npx",
      "args": ["@uh-joan/cortellis-mcp-server"],
      "env": {
        "CORTELLIS_USERNAME": "your_username",
        "CORTELLIS_PASSWORD": "your_password"
      }
    }
  }
}

Tool Usage

Once connected, you can use tools like:

  • ci_search_drugs - Search for drugs with various filters
  • ci_explore_ontology - Explore taxonomy terms
  • ci_get_drug - Get detailed drug information
  • And 5 more comprehensive tools for companies, deals, and trials

🔧 Configuration

Environment Variables

| Variable | Description | Default | Required | |----------|-------------|---------|----------| | CORTELLIS_USERNAME | API username | - | ✓ | | CORTELLIS_PASSWORD | API password | - | ✓ | | LOG_LEVEL | Logging level | info | - | | NODE_ENV | Environment mode | production | - |

Logging Levels

  • error: Only error messages
  • warn: Warnings and errors
  • info: General information (default)
  • debug: Detailed debugging information

🧪 Testing

The project includes comprehensive testing:

# Run all tests
npm test

# Run with coverage
npm run test:coverage

# Run in watch mode
npm run test:watch

# Run specific test file
npm test auth.test.ts

Test Structure

  • Unit tests for individual components
  • Integration tests for API flows
  • Mocked external dependencies
  • Coverage reporting with detailed metrics

📈 Monitoring and Logging

Logging Features

  • Structured JSON logging
  • Request correlation IDs
  • Performance metrics tracking
  • Error context and stack traces
  • Configurable log levels

Performance Monitoring

  • Request duration tracking
  • API response time monitoring
  • Memory usage metrics
  • Error rate tracking

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes with tests
  4. Run the test suite (npm test)
  5. Run linting (npm run lint)
  6. Commit your changes (git commit -m 'Add amazing feature')
  7. Push to the branch (git push origin feature/amazing-feature)
  8. Open a Pull Request

Development Guidelines

  • Write tests for new features
  • Follow TypeScript best practices
  • Maintain backwards compatibility
  • Update documentation as needed
  • Follow existing code style

🔄 Migration from v0.7.x

The v0.8.0 release represents a complete architectural transformation. While all existing functionality is preserved, the internal structure has changed significantly:

What's New

  • Modular architecture with clean separation of concerns
  • Comprehensive error handling and logging
  • Security middleware and rate limiting
  • Docker support with multi-stage builds
  • Comprehensive testing framework
  • Performance monitoring and metrics

Breaking Changes

  • Internal file structure completely reorganized
  • New configuration validation (will fail fast on invalid config)
  • Enhanced error responses with more detailed information
  • Updated Docker image structure

Migration Steps

  1. Update to Node.js 16+ if needed
  2. Review environment variable configuration
  3. Test existing integrations with new error response format
  4. Consider enabling HTTP mode for additional functionality

All tool interfaces and responses remain compatible with existing clients.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🆘 Support

📚 Additional Resources