@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
Maintainers
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, debugRunning the Server
# MCP Mode (stdio transport)
npx cortellis-mcp-server
# Development mode with auto-rebuild
npm run devDocker Deployment
# MCP Mode
docker run -e CORTELLIS_USERNAME=user -e CORTELLIS_PASSWORD=pass cortellis-mcp-serverTools
ci_search_drugs- Search for drugs in the Cortellis database
- Optional Inputs:
query(string) - Raw search querycompany(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
phaseparameter; 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 drugcountry(string) - Country ID (e.g., "US")offset(number) - For paginationhits(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 termcategory(string) - Category to search withinaction(string) - Target specific actionindication(string) - Disease/conditioncompany(string) - Company namedrug_name(string) - Drug nametarget(string) - Drug targettechnology(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 querycompany_name(string) - Company name to search forhq_country(string) - Company headquarters countrydeals_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 termsactions(string) - Top 10 target-based action termstechnologies(string) - Top 10 technologies termscompany_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 drugsoffset(number) - For paginationhits(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 dealindications(string) - Indications associated with the dealdealDrugCompanyPartnerIndications(string) - The indication and the partner company linked to a drug associated with the dealdealPhaseHighestStart(string) - Highest dev. status of the drug at the deal startdealPhaseHighestNow(string) - Current highest dev. status of the drugdealStatus(string) - Status of the dealdealSummary(string) - Summary of the dealdealTitleSummary(string) - Title or summary of the dealtechnologies(string) - Technology linked to the drugdealTitle(string) - Title of the dealdealType(string) - Type of dealactionsPrimary(string) - Primary mechanism of action associated with the dealsortBy(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 searchingsortBy(string) - Sort field (trialPhase, trialRecruitmentStatus, trialPatientCountEnrollment, trialDateStart, trialDateEnd, trialDateChangeLast)trialTitleOfficial(string) - Official trial titletrialIdentifiers(string) - Trial identifiers (e.g., NCT00003140, CTI_umbrella)indications(string) - Medical condition being treatedtrialPhase(string) - Phase of clinical trial (e.g., 'C12' for Phase 1/2 or 'Phase 1/Phase 2 Clinical')trialRecruitmentStatus(string) - Trial recruitment statustrialCompaniesSponsor(string) - Sponsoring organization (name or ID)trialFunderType(string) - Organization type conducting the trial. Categories: academic, non profit, company, governmenttrialPatientCountEnrollment(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
# 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:coverageAvailable 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-serverSecurity 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 filtersci_explore_ontology- Explore taxonomy termsci_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 messageswarn: Warnings and errorsinfo: 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.tsTest 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
- Documentation: ARCHITECTURE.md for technical details
- Issues: GitHub Issues
- Discussions: GitHub Discussions
