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
npm install @uh-joan/cortellis-mcp-server
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
npx cortellis-mcp-server
npm run dev
Docker Deployment
docker run -e CORTELLIS_USERNAME=user -e CORTELLIS_PASSWORD=pass cortellis-mcp-server
Tools
-
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
-
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
-
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
-
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
-
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
-
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
-
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
-
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
git clone <repository-url>
cd cortellis-mcp-server
npm install
cp .env.example .env
npm run build
npm test
npm run test:coverage
Available Scripts
npm run build
npm run dev
npm run dev:http
npm start
npm run start:http
npm test
npm run test:watch
npm run test:coverage
npm run lint
npm run lint:fix
npm run clean
๐ข Deployment
Docker Production Deployment
docker build -t cortellis-mcp-server .
docker run -e CORTELLIS_USERNAME=user -e CORTELLIS_PASSWORD=pass cortellis-mcp-server
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
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:
npm test
npm run test:coverage
npm run test:watch
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
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
)
- Make your changes with tests
- Run the test suite (
npm test
)
- Run linting (
npm run lint
)
- Commit your changes (
git commit -m 'Add amazing feature'
)
- Push to the branch (
git push origin feature/amazing-feature
)
- 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
- Update to Node.js 16+ if needed
- Review environment variable configuration
- Test existing integrations with new error response format
- 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