CLAUDE.md•10.4 kB
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Development Commands
### Environment Setup
- **Package Manager**: Always use `uv` for package management and environment setup
- **Sync Dependencies**: `uv sync` (creates .venv and installs dependencies from uv.lock)
- **Add Dependencies**: `uv add <package>` (adds to pyproject.toml and updates uv.lock)
- **Remove Dependencies**: `uv remove <package>`
- **Run Commands**: `uv run <command>` (runs command in project environment)
### Testing
- **Run All Tests**: `uv run python -m unittest discover tests/`
- **Run Specific Test**: `uv run python -m unittest tests.test_nodes.TestQueryTrialsNode.test_query_trials_node`
- **Run with Pytest**: `uv run pytest` (alternative test runner)
- **Test with Coverage**: `uv run pytest --cov`
- **Test Files**: Located in `tests/` directory, following `test_*.py` pattern
- **Test Specific Components**:
- Unified nodes: `uv run python -m unittest tests.test_unified_nodes`
- Legacy nodes: `uv run python -m unittest tests.test_nodes`
- Server integration: `uv run python -m unittest tests.test_unified_server`
### Code Quality
- **Linting**: `uv run ruff check` (check for issues), `uv run ruff format` (auto-format code)
- **Type Checking**: Install mypy with `uv add --group dev mypy`, then run `uv run mypy .`
### MCP Server
- **Start Server**: `uv run python servers/main.py` (recommended unified server)
- **Unified Server**: `servers/main.py` (supports both sync and async modes)
- **Legacy Servers**: `servers/primary.py` and `servers/legacy/sync_server.py` (deprecated, redirect to unified server)
- **Protocol**: Uses FastMCP SDK for MCP protocol implementation
#### Unified Server Architecture (Phase 4 Complete)
The project has completed a major code deduplication effort, consolidating all server implementations:
- **servers/main.py**: New unified server supporting both sync and async modes
- **Runtime Mode Selection**: Automatic detection or explicit configuration via `MCP_ASYNC_MODE`
- **Backward Compatibility**: Legacy servers still work but emit deprecation warnings
- **60% Code Reduction**: ~1,000 lines of duplicated code eliminated
- **Zero Breaking Changes**: All existing APIs and configurations continue to work
#### Server Configuration
```bash
# Auto-detect mode (default: async for better performance)
uv run python servers/main.py
# Force async mode
MCP_ASYNC_MODE=true uv run python servers/main.py
# Force sync mode
MCP_ASYNC_MODE=false uv run python servers/main.py
# Legacy servers (deprecated but still work)
uv run python servers/primary.py # Redirects to unified async
uv run python servers/legacy/sync_server.py # Redirects to unified sync
```
## Architecture Overview
### Unified Server Architecture (Post Phase 4)
The project uses a unified architecture that eliminates code duplication while supporting both sync and async execution modes:
```
┌─────────────────────────────────────────┐
│ Unified Server │
│ (servers/main.py) │
└─────────────────┬───────────────────────┘
│
┌─────────────────▼───────────────────────┐
│ Unified Node Framework │
│ (utils/unified_node.py) │
└─────────────────┬───────────────────────┘
│
┌─────────────────▼───────────────────────┐
│ Service Abstraction Layer │
│ ┌─────────────┬─────────────────────┐ │
│ │ HTTP Client │ LLM Service │ │
│ │ Abstraction │ Abstraction │ │
│ └─────────────┴─────────────────────┘ │
└─────────────────────────────────────────┘
```
### Core Pattern: Unified PocketFlow Nodes
This project follows the enhanced PocketFlow Node pattern with unified sync/async execution:
1. **prep(shared)**: Extracts data from shared context (unified)
2. **exec(prep_result)**: Performs the main operation (sync or async)
3. **post(shared, prep_result, exec_result)**: Updates shared context and returns next node ID (unified)
### Key Components
#### 1. Unified MCP Server (`servers/main.py`)
- Main entry point implementing MCP protocol with mode detection
- Exposes unified tools supporting both sync and async execution
- Runtime mode selection via configuration or auto-detection
- Orchestrates the unified flow execution for clinical trial queries
#### 2. Unified Node Framework (`utils/unified_node.py`)
- **UnifiedNode**: Base class supporting both sync and async execution
- **UnifiedBatchNode**: Base class for batch processing with concurrency control
- **UnifiedFlow**: Orchestrates execution with auto-mode detection
- **Auto-detection**: Automatically determines sync vs async execution
#### 3. Unified Clinical Trials Nodes (`clinicaltrials/unified_nodes.py`)
- **QueryTrialsNode**: Unified node querying clinicaltrials.gov API
- **SummarizeTrialsNode**: Unified node formatting trial data into readable summaries
- **BatchQueryTrialsNode**: Unified batch processing for multiple mutations
#### 4. Service Abstraction Layer
- **ClinicalTrialsService** (`clinicaltrials/service.py`): Unified API client
- **LLMService** (`utils/llm_service.py`): Unified LLM interaction
- **UnifiedHttpClient** (`utils/http_client.py`): Unified HTTP client abstraction
#### 5. Configuration System (`servers/config.py`)
- Runtime mode selection and feature toggles
- Environment variable overrides
- Performance tuning based on execution mode
### Data Flow (Unified)
```
User Query → Unified Server → Mode Detection → Unified Nodes → Service Layer → API/LLM → Formatted Summary
↓
(Auto: Async Mode) (Manual: Sync/Async)
↓ ↓
High Performance Simplified Execution
```
## Code Deduplication Achievement (Phase 4 Complete)
### Summary of Improvements
- **60% Code Reduction**: Eliminated ~1,000 lines of duplicated code
- **4 Major Component Consolidations**: Servers, Nodes, Services, HTTP Clients
- **Zero Breaking Changes**: Complete backward compatibility maintained
- **Performance Gains**: 30-40% memory reduction, 20-30% faster startup
### Before vs After
| Component | Before | After | Reduction |
|-----------|--------|-------|-----------|
| Servers | `primary.py` + `sync_server.py` | `main.py` | 70% |
| Nodes | `nodes.py` + `async_nodes.py` | `unified_nodes.py` | 85% |
| Services | `query.py` + `async_query.py` | `service.py` | 95% |
| LLM | `call_llm.py` + `async_call_llm.py` | `llm_service.py` | 95% |
### Migration Path
1. **Immediate**: Use `servers/main.py` for new deployments
2. **Gradual**: Legacy servers continue working with deprecation warnings
3. **Future**: Legacy servers will be removed in next major version
### Shared Context Structure
```python
shared = {
"mutation": "BRAF V600E", # Input mutation
"trials_data": {...}, # Raw API response
"studies": [{...}, {...}], # Extracted studies
"summary": "# Clinical Trials..." # Final summary
}
```
## Key Dependencies
- **pocketflow>=0.0.1**: PocketFlow framework for Node pattern
- **mcp[cli]>=1.0.0**: Official MCP SDK for Claude Desktop integration
- **fastmcp>=2.10.2**: High-performance async MCP framework
- **httpx>=0.28.1**: Async HTTP client for unified HTTP abstraction
- **requests==2.31.0**: HTTP requests for API calls (legacy compatibility)
- **redis>=6.2.0**: Optional distributed caching backend
- **python-dotenv==1.1.0**: Environment variable management
## Development Guidelines
### Adding New Nodes
1. Inherit from `UnifiedNode` or `UnifiedBatchNode` in `utils/unified_node.py` (preferred) or legacy base classes in `utils/node.py`
2. Implement `prep()`, `exec()`/`aexec()`, and `post()` methods
3. Add to flow in the unified server `servers/main.py`
4. Add corresponding tests in `tests/`
### Error Handling
- API errors handled in `clinicaltrials/service.py` (unified service layer)
- Node validation in `prep()` methods
- Flow errors handled in `utils/unified_node.py` and legacy `utils/node.py`
### Testing Strategy
- Unit tests for unified nodes in `tests/test_unified_nodes.py`
- Legacy node tests in `tests/test_nodes.py`
- API integration tests in `tests/test_query.py` and `tests/test_unified_integration.py`
- HTTP client tests in `tests/test_unified_http_client.py`
- Shared utilities tests in `tests/test_shared_utilities.py`
- Server tests in `tests/test_unified_server.py`
## Claude Desktop Integration
Configure in `~/Library/Application Support/Claude/claude_desktop_config.json`:
```json
"mutation-clinical-trials-mcp": {
"command": "uv",
"args": ["run", "python", "/path/to/project/servers/main.py"],
"env": {
"MCP_ASYNC_MODE": "true"
}
}
```
**Environment Variables for Configuration**:
- `MCP_ASYNC_MODE`: Force async (`true`) or sync (`false`) mode, or omit for auto-detection
- `MCP_SERVICE_NAME`: Override default service name
- `MCP_MAX_RANK`: Override max results returned
- `MCP_TIMEOUT`: Override request timeout
- `MCP_MAX_CONCURRENT`: Override max concurrent requests (async mode)
- `MCP_ENABLE_*`: Toggle features like cache warming, metrics, etc.
## Common Query Patterns
- "What clinical trials are available for EGFR L858R mutations?"
- "Are there any trials for BRAF V600E mutations?"
- "Tell me about trials for ALK rearrangements"
## Project Structure Notes
- `clinicaltrials/`: Core clinical trials functionality
- `llm/`: LLM integration for summarization
- `utils/`: Base utilities and Node pattern implementation
- `tests/`: Unit tests following unittest framework
- `docs/`: Comprehensive documentation including design patterns