A Rust-based MCP server that feeds domain model abstractions into GitHub Copilot, ensuring AI-generated code follows your architecture, conventions, and domain-driven design patterns.
Without DOMCP, every new chat starts from zero. Copilot re-discovers your architecture by reading files — slowly, incompletely, and inconsistently. DOMCP gives it the full domain model in few tokens (one tool call), which is faster and cheaper than Copilot scanning 50 files to piece it together.
Left alone, Copilot will happily create a direct import from your domain layer into infrastructure, or skip aggregate roots entirely. DOMCP's validate_dependency and get_architectural_rules act as guardrails that Copilot checks before generating code. This is the highest-value feature — preventing architectural drift is expensive to fix later.
"Analyze this codebase and document its domain model" is something teams do manually in wikis that go stale. Having Copilot do it and persist it to domcp.json means the model stays machine-readable and version-controlled alongside the code.
┌─────────────────────────────────────────────────────┐
│ GitHub Copilot (VS Code) │
│ │
│ "Create a new billing endpoint" │
│ │ │
│ ▼ │
│ ┌──────────────┐ MCP stdio ┌───────────────┐ │
│ │ Copilot Chat │◄──────────────►│ DOMCP Server │ │
│ │ / Agent │ │ │ │
│ └──────────────┘ │ ▪ Entities │ │
│ │ │ ▪ Services │ │
│ ▼ │ ▪ Rules │ │
│ Code that follows YOUR │ ▪ Conventions │ │
│ architecture & conventions └───────────────┘ │
└─────────────────────────────────────────────────────┘
brew tap flavioaiello/domcp git@github.com:flavioaiello/domcp.git
brew install domcpOr build from source:
cargo build --release
cargo install --path .If you have an existing domcp.json, import it into the local store:
domcp import domcp.json --workspace /path/to/your/projectThe model is stored in ~/.domcp/domcp.db (SQLite), keyed by workspace path.
If you skip this step, DOMCP starts with an empty model that Copilot can populate via write tools.
Add to your project's .vscode/mcp.json:
{
"servers": {
"domcp": {
"type": "stdio",
"command": "domcp",
"args": ["serve", "--workspace", "${workspaceFolder}"]
}
}
}After installing, restart VS Code or run > MCP: List Servers from the command palette to see the DOMCP server listed and active.
# Start MCP server (used by VS Code, not called manually)
domcp serve --workspace /path/to/project
# Import a domcp.json file into the local store
domcp import domcp.json --workspace /path/to/project
# Export a project's model back to JSON
domcp export model.json --workspace /path/to/project
# List all stored projects
domcp listOnce connected, Copilot gains access to 16 tools (8 read, 8 write), 1 prompt, and dynamic resources:
| Tool | What it does |
|---|---|
get_architecture_overview |
Full architecture summary — Copilot reads this to understand the system |
get_bounded_context |
Details of a specific bounded context |
get_entity |
Entity spec with fields, methods, invariants |
get_service_spec |
Service definition with methods, deps, layer |
validate_dependency |
Checks if a cross-context dependency is allowed |
get_architectural_rules |
All rules code must follow |
get_conventions |
Naming, file structure, error handling patterns |
suggest_file_path |
Where a new file should be placed per conventions |
| Tool | What it does |
|---|---|
update_bounded_context |
Create or update a bounded context |
update_entity |
Create or merge an entity (fields, methods, invariants) |
update_service |
Create or update a service within a context |
update_event |
Create or update a domain event |
remove_entity |
Remove an entity from a context |
compare_model |
Diff in-memory model vs persisted → list of changes |
draft_refactoring_plan |
Diff in-memory model vs persisted → code actions, file paths, priorities, migration notes |
save_model |
Persist the current model to the local store |
| URI | Content |
|---|---|
domcp://architecture/overview |
Architecture overview (JSON) |
domcp://architecture/rules |
Architectural rules (JSON) |
domcp://architecture/conventions |
Conventions (JSON) |
domcp://context/{name} |
Per bounded-context detail (JSON) |
| Name | Description |
|---|---|
domcp_guidelines |
Architecture guidelines and mandatory tool-usage workflow. Renders project-specific content (project name, bounded context list, 11-step workflow, DDD rules). Eliminates the need for a per-project copilot-instructions.md. |
You ask: "Create a new endpoint to cancel a subscription"
Copilot will:
- Call
get_architecture_overview→ learns the system has Identity and Billing contexts - Call
get_entity("Subscription")→ sees it's an aggregate root in Billing with acancel()method - Call
get_conventions→ learns file structure patternsrc/{context}/{layer}/{type}.rs - Call
suggest_file_path("Billing", "service", "CancelSubscription")→src/billing/application/cancel_subscription.rs - Call
validate_dependency("Billing", "Identity")→ allowed - Generate code that:
- Places the handler in
src/billing/api/ - Uses the
Subscriptionaggregate'scancel()method - Emits a domain event
- Follows error handling conventions (
thiserror) - Respects the repository pattern
- Places the handler in
You ask: "Add a field to User"
Copilot will:
- Call
get_entity("User")→ sees existing fields, invariants - Call
get_architectural_rules→ knows mutations go through aggregate root methods - Generate code that modifies the
Userstruct AND adds the corresponding migration, event update, and test
You ask: "Analyze this codebase and build a domain model from it"
Copilot will:
- Scan the module structure → call
update_bounded_contextfor each discovered context - Read entity files → call
update_entitywith fields, methods, invariants - Read service files → call
update_servicewith dependencies and layer - Call
save_modelto persist everything to the local store
You then ask: "Rename the Identity context to Auth and add a last_login field to User"
Copilot will:
- Call
update_bounded_contextto rename/update the context - Call
update_entityto add the field - Call
compare_model→ sees the diff between in-memory and persisted models - Call
draft_refactoring_plan→ gets a prioritized list of code changes:modify_file: src/identity/domain/user.rs(high)move_file: src/identity → src/auth(critical)- Migration note: "New field 'last_login' on 'User' — needs ALTER TABLE migration"
- Execute code actions in priority order
- Call
save_modelto persist the updated model to the local store
The domcp.json file describes your entire system architecture:
DomainModel
├── name, description
├── tech_stack (language, framework, database, ...)
├── bounded_contexts[]
│ ├── name, module_path
│ ├── entities[] (fields, methods, invariants, aggregate_root)
│ ├── value_objects[] (fields, validation_rules)
│ ├── services[] (kind: domain|application|infrastructure, methods, dependencies)
│ ├── repositories[] (aggregate, methods)
│ ├── events[] (fields, source entity)
│ └── dependencies[] (allowed cross-context deps)
├── rules[] (id, description, severity, scope)
└── conventions
├── naming (entities, services, events, ...)
├── file_structure (pattern, layers)
├── error_handling
└── testing
DOMCP stores domain models in a local SQLite database at ~/.domcp/domcp.db, keyed by workspace path. This means:
- Multi-project support: Each workspace gets its own isolated model
- No per-project config files needed: The model lives centrally on the dev machine
- Portable import/export: Use
domcp import/exportto share models viadomcp.jsonfiles - Version control friendly: Export to
domcp.jsonwhen you want to commit the model to git
DOMCP doesn't just inform — it constrains. The validate_dependency tool lets Copilot check whether cross-context imports are allowed before generating them. The architectural rules describe invariants that Copilot will respect.
Example rules from the included config:
- LAYER-001: Domain layer must not depend on infrastructure
- DDD-001: State mutations must go through aggregate root methods
- DDD-002: Cross-aggregate communication via domain events only
- ERR-001: Use typed domain errors, never panic
DOMCP ships a built-in domcp_guidelines prompt that serves architecture instructions automatically. For additional project-specific instructions, create .github/copilot-instructions.md:
## Architecture
This project uses Domain-Driven Design with a hexagonal architecture.
Before writing any code, ALWAYS call `get_architecture_overview` from the DOMCP
server to understand the system structure.
When creating new files, call `suggest_file_path` to determine the correct location.
When adding cross-context dependencies, call `validate_dependency` to verify it's allowed.
Always check `get_conventions` for naming and error handling patterns.This ensures Copilot proactively queries the domain model rather than waiting for tool hints.
brew tap flavioaiello/domcp git@github.com:flavioaiello/domcp.git
brew install domcpcargo install --path .# Build debug
cargo build
# Run tests
cargo test
# Run with debug logging
RUST_LOG=debug cargo run -- serve --workspace .
# Import the example model
cargo run -- import domcp.json --workspace /path/to/project
# List stored projects
cargo run -- listMIT