Project Structure
Related Topics: Configuration (site and user config) | Endpoints (tool, resource, prompt files) | Quickstart (
mxcp initdetails)
MXCP enforces an organized directory structure to improve project maintainability and enable auto-discovery of endpoints. This guide explains the structure and best practices for organizing your project.
Why this structure matters:
- Auto-discovery - MXCP finds all endpoints automatically by scanning directories
- Separation of concerns - Definitions (YAML) separate from implementations (SQL/Python)
- Multi-environment - Profiles allow different configs per environment
- Scalability - Subdirectories keep large projects organized
Minimal Project
Section titled “Minimal Project”The simplest MXCP project needs just two files:
my-project/├── mxcp-site.yml # Project configuration└── tools/ └── hello.yml # At least one endpoint# mxcp-site.yml (minimal)mxcp: 1project: my-projectprofile: defaultStandard Structure
Section titled “Standard Structure”A complete MXCP project follows this structure:
my-mxcp-project/├── mxcp-site.yml # Project configuration (required)├── tools/ # MCP tool definitions (.yml files)├── resources/ # MCP resource definitions (.yml files)├── prompts/ # MCP prompt definitions (.yml files)├── evals/ # Evaluation definitions (.yml files)├── python/ # Python endpoints and shared code├── plugins/ # MXCP plugins for DuckDB├── sql/ # SQL implementation files├── data/ # Database files (DuckDB)├── drift/ # Schema drift detection snapshots├── audit/ # Audit logs (when enabled)├── models/ # dbt models (if using dbt)└── target/ # dbt target directory (if using dbt)Configuration File
Section titled “Configuration File”mxcp-site.yml
Section titled “mxcp-site.yml”The root configuration file that defines your project:
mxcp: 1project: my-projectprofile: default
# Secrets used by this projectsecrets: - db_credentials - api_key
# DuckDB extensions to loadextensions: - httpfs - parquet - name: h3 repo: community
# dbt integrationdbt: enabled: true model_paths: ["models"]
# SQL tools (disabled by default)sql_tools: enabled: false
# Profile-specific settingsprofiles: default: duckdb: path: db.duckdb readonly: false drift: path: drift/snapshot.json audit: enabled: true path: audit/logs.jsonlEndpoint Directories
Section titled “Endpoint Directories”tools/
Section titled “tools/”Contains tool endpoint definitions. Each .yml file defines one tool:
tools/├── hello-world.yml # Simple tool├── sales-report.yml # Data query tool├── user-management.yml # CRUD operations└── analytics/ # Subdirectories are supported ├── daily-stats.yml └── monthly-report.ymlKey rules:
- Files must have
.ymlor.yamlextension - Tool name comes from the
namefield, not the filename - Subdirectories are scanned recursively
resources/
Section titled “resources/”Contains resource endpoint definitions:
resources/├── user-profile.yml├── config-settings.yml└── documents/ └── document.ymlResource URIs are defined in the file, not the structure.
prompts/
Section titled “prompts/”Contains prompt template definitions:
prompts/├── data-analysis.yml├── report-generation.yml└── customer-service.ymlevals/
Section titled “evals/”Contains evaluation test suites:
evals/├── sales-evals.yml├── user-management-evals.yml└── comprehensive.evals.ymlEval files should have -evals.yml or .evals.yml suffix.
Implementation Directories
Section titled “Implementation Directories”python/
Section titled “python/”Contains Python implementations and shared modules:
python/├── math_tools.py # Tool implementations├── api_handlers.py # API integration code├── utils/ # Shared utilities│ ├── __init__.py│ ├── validators.py│ └── formatters.py└── services/ # Business logic ├── __init__.py └── customer_service.pyPython files are referenced from tool definitions:
source: file: ../python/math_tools.pyContains SQL implementation files:
sql/├── hello-world.sql # Simple queries├── sales_report.sql # Complex queries├── common/ # Shared SQL│ └── aggregations.sql└── migrations/ # Schema migrations (manual) └── 001_initial.sqlSQL files are referenced from tool definitions:
source: file: ../sql/sales_report.sqlplugins/
Section titled “plugins/”Contains MXCP plugins that extend DuckDB:
plugins/├── my_plugin/│ └── __init__.py├── cipher_plugin/│ └── __init__.py└── custom_functions.pyPlugins must be configured in mxcp-site.yml and contain a class named MXCPPlugin:
plugin: - name: myutil # Instance name module: my_plugin # Module in plugins/from mxcp.plugins import MXCPBasePlugin, udf
class MXCPPlugin(MXCPBasePlugin): @udf def my_function(self, value: str) -> str: return value.upper()Functions are called as {function}_{instance_name}:
SELECT my_function_myutil('hello'); -- Returns 'HELLO'Auto-Generated Directories
Section titled “Auto-Generated Directories”drift/
Section titled “drift/”Contains drift detection snapshots:
drift/├── drift-default.json # Default profile├── drift-staging.json # Staging profile└── drift-prod.json # Production profileGenerated by mxcp drift-snapshot, compared by mxcp drift-check.
audit/
Section titled “audit/”Contains audit logs when enabled:
audit/├── logs.jsonl # Main audit log└── logs-2024-01.jsonl # Archived logsJSONL format allows streaming and analysis.
dbt Integration
Section titled “dbt Integration”When using dbt, add these directories:
my-mxcp-project/├── mxcp-site.yml├── dbt_project.yml # dbt configuration├── profiles.yml # dbt profiles (or use ~/.dbt/)├── models/ # dbt models│ ├── staging/│ │ └── stg_sales.sql│ └── marts/│ └── fct_daily_sales.sql└── target/ # dbt output (gitignored) └── compiled/MXCP tools query tables created by dbt:
-- Tool queries dbt-created tableSELECT * FROM fct_daily_salesWHERE date >= $start_dateFile Naming Conventions
Section titled “File Naming Conventions”Endpoint Files
Section titled “Endpoint Files”- Use
kebab-case:sales-report.yml,user-profile.yml - Match endpoint name when practical
- Group related endpoints in subdirectories
SQL Files
Section titled “SQL Files”- Use
snake_caseorkebab-case:sales_report.sql - Match the tool/resource name
- Use descriptive names for complex queries
Python Files
Section titled “Python Files”- Use
snake_case:api_handlers.py - Group by functionality
- Use
__init__.pyfor packages
Plugins
Section titled “Plugins”- Use
snake_casefor module names - Class must be named
MXCPPlugin
Path References
Section titled “Path References”Relative Paths
Section titled “Relative Paths”Paths in YAML files are relative to the YAML file location:
# In tools/analytics/daily-report.ymlsource: file: ../../sql/analytics/daily_report.sqlAbsolute Paths
Section titled “Absolute Paths”Avoid absolute paths - they break portability.
Path Resolution
Section titled “Path Resolution”MXCP resolves paths from:
- The YAML file’s directory
- The project root (for some config options)
- User home directory (for user config)
Environment-Specific Organization
Section titled “Environment-Specific Organization”Use profiles for environment differences:
profiles: development: duckdb: path: dev.duckdb audit: enabled: false
staging: duckdb: path: staging.duckdb audit: enabled: true path: audit/staging-logs.jsonl
production: duckdb: path: prod.duckdb readonly: true audit: enabled: true path: /var/log/mxcp/audit.jsonlBest Practices
Section titled “Best Practices”1. Keep Implementations Separate
Section titled “1. Keep Implementations Separate”# Goodtools/sales-report.yml # Definitionsql/sales_report.sql # Implementation
# Avoidtools/sales-report.yml # Definition with inline SQL2. Use Subdirectories for Large Projects
Section titled “2. Use Subdirectories for Large Projects”tools/├── sales/│ ├── daily-report.yml│ └── monthly-summary.yml├── inventory/│ ├── stock-check.yml│ └── reorder-alert.yml└── customers/ └── customer-lookup.yml3. Share Common Code
Section titled “3. Share Common Code”def validate_email(email: str) -> bool: ...
# python/customer_tools.pyfrom utils.validators import validate_email4. Version Control
Section titled “4. Version Control”*.duckdb*.duckdb.waltarget/audit/*.jsonldrift/*.json__pycache__/.venv/5. Document Structure
Section titled “5. Document Structure”Add a README explaining your project organization:
# Project Structure
- `tools/` - MCP tool definitions- `sql/` - SQL implementations- `python/` - Python code- `models/` - dbt models for data transformationInitializing a Project
Section titled “Initializing a Project”Use mxcp init to create the structure:
# Create empty structuremxcp init
# Create with examplesmxcp init --bootstrapThe --bootstrap flag creates:
- Example SQL tool (
tools/hello-world.yml+sql/hello-world.sql) - Complete directory structure
Next Steps
Section titled “Next Steps”- Configuration - Detailed configuration options
- Endpoints - Endpoint definition format
- dbt Integration - Using dbt with MXCP