Dependency Injection System
Relevant source files
The following files were used as context for generating this wiki page:
The Dependency Injection (DI) system in MCB is a core architectural component designed to enforce Clean Architecture principles and manage the decoupled lifecycle of components across different workspace crates. It facilitates a multi-provider strategy where abstractions defined in the mcb-domain layer are implemented by the mcb-providers layer and wired together in the mcb-infrastructure layer.
The system relies on distributed registration using the linkme crate, allowing providers to register themselves at compile-time without creating circular dependencies. This enables high-level handlers in mcb-server to interact with business logic via traits (ports), while the actual implementations (adapters) are injected at runtime through an AppContext or catalog.
Sources: AGENTS.md:167-175, README.md:58-70, crates/mcb-domain/Cargo.toml:50-50
Architectural Core
The DI system is governed by strict dependency rules enforced by mcb-validate. These rules ensure that dependencies flow only inward towards the domain layer. The domain layer contains the "Port" traits which define the interfaces for external services like repositories, embedding providers, and vector stores.
Component Layering
| Layer | Responsibility in DI | Allowed Dependencies |
|---|---|---|
| mcb-domain | Defines Port traits and core entities | None (Zero internal dependencies) |
| mcb-providers | Implements Port traits (Adapters) | mcb-domain, mcb-utils |
| mcb-infrastructure | Wiring, composition, and DI catalog | mcb-domain, mcb-providers, mcb-utils |
| mcb-server | Resolves dependencies via DI for handlers | mcb-domain, mcb-infrastructure, mcb-utils |
Sources: AGENTS.md:167-180, config/mcb-validate-internal.toml:17-22
Dependency Flow Diagram
The following diagram illustrates how the DI system maintains the Clean Architecture boundaries, where the Infrastructure layer acts as the composition root.
Sources: README.md:58-70, AGENTS.md:182-192
Provider Registration Pattern
MCB uses a distributed registry pattern powered by the linkme crate. This allows the system to discover and register embedding providers, vector stores, and repositories across different crates without manual registration in a single central file.
Key Implementation Details
- linkme Registries: Distributed slices are defined in
mcb-domainormcb-infrastructureto hold references to provider constructors or descriptors. - Macro-based Registration: Providers use macros like
register_tool!or custom provider macros to add themselves to these slices at compile time. - Handle Pattern: Business logic uses "Handles" or injected traits to avoid hard-wiring concrete implementations.
Sources: AGENTS.md:225-228, crates/mcb-domain/Cargo.toml:50-50, crates/mcb-server/Cargo.toml:98-98
Registration Sequence
Injection in Handlers
The mcb-server handlers receive their dependencies during construction. This is typically done through a new method or a specialized macro like handler_new!. The handler stores an Arc<dyn Port> to interact with the domain layer.
Example: ProjectHandler Injection
In crates/mcb-server/src/handlers/project.rs, the ProjectHandler depends on the ProjectRepository port. The DI system ensures that a concrete implementation (e.g., a SeaORM-based repository from mcb-providers) is provided to the handler.
// crates/mcb-server/src/handlers/project.rs:21-25
pub struct ProjectHandler {
repo: Arc<dyn ProjectRepository>,
}
handler_new!(ProjectHandler {
repo: Arc<dyn ProjectRepository>,
});
Sources: crates/mcb-server/src/handlers/project.rs:21-29
Configuration and Multi-Provider Strategy
The DI system is integrated with the application's runtime configuration (AppConfig). The mcb-infrastructure layer uses configuration values to decide which registered providers to instantiate.
Configuration Parameters
| Config Section | Purpose | Supported Implementation Example |
|---|---|---|
embedding | Selection of embedding provider | OpenAI, Ollama, FastEmbed |
vector_store | Selection of vector database | Milvus, Qdrant, EdgeVec |
database | Core persistence layer | SQLite (via SeaORM) |
Sources: README.md:13-16, crates/mcb-infrastructure/Cargo.toml:104-106, AGENTS.md:197-200
Validation Rules
The DI system is protected by automated gates in mcb-validate. The rules.architecture.layer_boundaries configuration defines exactly what each crate is allowed to depend on, preventing "Dependency Rot" where concrete providers leak into the domain or server layers.
Boundary Definitions
- Application/Server: Must use
mcb-infrastructurefor DI andmcb-domainfor logic. - Infrastructure: The only layer allowed to depend on
mcb-providersdirectly for the purpose of wiring. - Domain: Strictly forbidden from depending on any other internal
mcb-*crates to maintain pure business logic.
Sources: config/mcb-validate-internal.toml:17-22, AGENTS.md:182-192
Summary
The MCB Dependency Injection system acts as the glue that binds the Clean Architecture layers while maintaining strict isolation between them. By using linkme for distributed registration and mcb-validate for boundary enforcement, the system ensures that the project can support multiple embedding and storage providers without complicating the core business logic or protocol handlers.