Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ classifiers = [
]
authors = [{ name = "vvcb" }, { name = "shen1802" }, { name = "nikomoegre" }]
requires-python = ">=3.13"
dependencies = ["ibis-framework[duckdb]>=10.5.0", "mcp[cli]>=1.6.0"]
dependencies = [
"ibis-framework[duckdb]>=10.5.0",
"langfuse>=3.5.2",
"mcp[cli]>=1.6.0",
]
urls = { Documentation = "https://fastomop.github.io/omcp/", Repository = "https://github.com/fastomop/omcp" }

[project.scripts]
Expand Down
118 changes: 97 additions & 21 deletions sample.env
Original file line number Diff line number Diff line change
@@ -1,47 +1,110 @@
# Database Configuration
# OMOP MCP Server Configuration Template
# Copy this file to .env and modify the values according to your setup

# ============================================================================
# LOGGING AND OBSERVABILITY CONFIGURATION
# ============================================================================

# Enable/disable file logging (default: true)
# Set to false to disable all logging output
ENABLE_LOGGING=true
DEBUG=false
LOG_FILE=omcp.log

# Enable/disable Langfuse observability and tracing (default: true)
# Set to false to disable Langfuse integration
ENABLE_LANGFUSE=true


# ============================================================================
# LANGFUSE CONFIGURATION
# ============================================================================

# Langfuse public and secret keys
# Get these from your Langfuse project settings
LANGFUSE_PUBLIC_KEY="pk-lf-your-public-key-here"
LANGFUSE_SECRET_KEY="sk-lf-your-secret-key-here"

# Langfuse host URL
# Use https://cloud.langfuse.com for Langfuse Cloud
# Use http://localhost:3000 for self-hosted Langfuse
LANGFUSE_HOST="https://cloud.langfuse.com"

# Trace context file for distributed tracing (optional)
# Used for linking traces between fastomop and omcp across processes
# Default: Uses system temp directory (e.g., /tmp/ on Unix, %TEMP% on Windows)
# Only set this if you need a custom location or for cross-service coordination
#LANGFUSE_TRACE_CONTEXT_FILE=/tmp/.fastomop_langfuse_trace_context.json

# ============================================================================
# DATABASE CONFIGURATION
# ============================================================================

# Supported database types: duckdb, postgres
DB_TYPE=duckdb
#DB_TYPE=postgres

# DuckDB Configuration (when DB_TYPE=duckdb)
# Database Path (for DuckDB)
DB_PATH=/path/to/omcp/synthetic_data/synthea.duckdb

# Database Read-Only Mode (recommended for production)
# Set to true to prevent accidental database modifications
DB_READ_ONLY=true

# PostgreSQL Configuration (when DB_TYPE=postgres)
#DB_USERNAME=your_username
#DB_PASSWORD=your_password
#DB_HOST=localhost
#DB_PORT=5432
#DB_DATABASE=your_database_name
# ============================================================================
# DUCKDB CONFIGURATION (when DB_TYPE=duckdb)
# ============================================================================

# Path to your DuckDB database file
DB_PATH=/path/to/your/omop.duckdb

# ============================================================================
# POSTGRESQL CONFIGURATION (when DB_TYPE=postgres)
# ============================================================================

# PostgreSQL connection details
DB_USERNAME=your_username
DB_PASSWORD=your_password
DB_HOST=localhost
DB_PORT=5432
DB_DATABASE=your_database_name

# ============================================================================
# OMOP SCHEMA CONFIGURATION
# ============================================================================

# Schema containing OMOP CDM tables
CDM_SCHEMA=cdm

# OMOP Schema Configuration
CDM_SCHEMA=base # Schema containing OMOP CDM tables
VOCAB_SCHEMA=base # Schema containing vocabulary tables
# Schema containing vocabulary tables (can be same as CDM_SCHEMA)
VOCAB_SCHEMA=vocab

# ============================================================================
# MCP SERVER CONFIGURATION
# ============================================================================

# MCP Server Configuration (optional)
# Transport type:
# - stdio: For direct integration with MCP clients (Claude Desktop, etc.)
# - sse: For web-based clients and HTTP API access
MCP_TRANSPORT=stdio

# Host and port configuration (required for SSE transport, ignored for stdio)
#MCP_HOST=localhost
#MCP_PORT=8080
MCP_HOST=localhost
MCP_PORT=8080

# Example Configurations:
# ============================================================================
# EXAMPLE CONFIGURATIONS
# ============================================================================

# DuckDB Example (Local file database)
# Example 1: DuckDB with full logging
#ENABLE_LOGGING=true
#ENABLE_LANGFUSE=true
#DB_TYPE=duckdb
#DB_PATH=/Users/username/data/omop.duckdb
#DB_READ_ONLY=true
#CDM_SCHEMA=cdm
#VOCAB_SCHEMA=vocab
#MCP_TRANSPORT=stdio

# PostgreSQL Example (Remote database)
# Example 2: PostgreSQL with minimal logging
#ENABLE_LOGGING=true
#ENABLE_LANGFUSE=false
#DB_TYPE=postgres
#DB_USERNAME=omop_user
#DB_PASSWORD=secure_password
Expand All @@ -51,3 +114,16 @@ MCP_TRANSPORT=stdio
#DB_READ_ONLY=true
#CDM_SCHEMA=cdm_531
#VOCAB_SCHEMA=vocab
#MCP_TRANSPORT=sse
#MCP_HOST=0.0.0.0
#MCP_PORT=8080

# Example 3: Development setup with no logging
#ENABLE_LOGGING=false
#ENABLE_LANGFUSE=false
#DB_TYPE=duckdb
#DB_PATH=/tmp/test.duckdb
#DB_READ_ONLY=false
#CDM_SCHEMA=main
#VOCAB_SCHEMA=main
#MCP_TRANSPORT=stdio
79 changes: 79 additions & 0 deletions src/omcp/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import os
import logging
from pathlib import Path
from dotenv import load_dotenv
from langfuse import Langfuse
from langfuse import observe

load_dotenv()

# Global configuration variables
ENABLE_LOGGING = os.environ.get("ENABLE_LOGGING", "true").lower() == "true"
ENABLE_LANGFUSE = os.environ.get("ENABLE_LANGFUSE", "true").lower() == "true"


def setup_logging():
"""Set up simplified logging configuration."""
logger = logging.getLogger("omcp")

if not ENABLE_LOGGING:
logger.addHandler(logging.NullHandler())
return logger

# Clear existing handlers
logger.handlers.clear()
logger.setLevel(logging.INFO)

# Get log file path (simplified)
log_file = os.environ.get("LOG_FILE", "omcp.log")
if not os.path.isabs(log_file):
# Default to home directory logs folder
log_dir = Path.home() / ".omcp" / "logs"
log_dir.mkdir(parents=True, exist_ok=True)
log_file = log_dir / log_file

try:
# File handler
file_handler = logging.FileHandler(log_file)
file_handler.setFormatter(
logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
)
logger.addHandler(file_handler)

# Console handler for development
if os.environ.get("DEBUG", "false").lower() == "true":
console_handler = logging.StreamHandler()
console_handler.setFormatter(
logging.Formatter("%(levelname)s - %(message)s")
)
logger.addHandler(console_handler)

logger.info(f"Logging initialized - file: {log_file}")

except Exception as e:
# Fallback to console only
console_handler = logging.StreamHandler()
logger.addHandler(console_handler)
logger.warning(f"Could not create log file, using console: {e}")

return logger


# Initialize logger
logger = setup_logging()

# Initialize Langfuse (simplified)
langfuse = None
if ENABLE_LANGFUSE:
try:
langfuse = Langfuse(
public_key=os.environ.get("LANGFUSE_PUBLIC_KEY"),
secret_key=os.environ.get("LANGFUSE_SECRET_KEY"),
host=os.environ.get("LANGFUSE_HOST", "https://cloud.langfuse.com"),
)
logger.info("Langfuse initialized")
except Exception as e:
logger.error(f"Langfuse initialization failed: {e}")

# Export observe decorator
observe = observe if langfuse else lambda *args, **kwargs: lambda func: func
Loading