Skip to content

V3 Architecture

Matt Meents edited this page Nov 30, 2025 · 1 revision

V3 System Architecture

DaemonsMCP Version 3 uses a clean architecture approach with clear separation of concerns, enabling both MCP protocol integration and REST API access to share the same business logic.


Architectural Overview

V3 is built on four distinct layers following Domain-Driven Design and Clean Architecture principles:

  1. Domain Layer - Core business entities and contracts
  2. Application Layer - Business logic, commands, queries (MediatR CQRS)
  3. Infrastructure Layer - Data access, external services, file operations
  4. Host Layer - Two independent entry points (MCP Server and REST API)

This separation allows the same codebase to serve both AI assistants via the Model Context Protocol and human users via a web interface, without duplicating business logic.


Layer Diagram

┌─────────────────────────────────────────────────────────────┐
│                    Presentation Layer                        │
├──────────────────────┬──────────────────────────────────────┤
│   DaemonsMCP.exe     │     DaemonsMCP.Api.exe               │
│   (MCP Server)       │     (ASP.NET Core API)               │
│   - MCPSharp         │     - REST Endpoints                 │
│   - JSON-RPC         │     - Swagger/OpenAPI                │
│   - Tool Handlers    │     - CORS Support                   │
└──────────┬───────────┴────────────┬─────────────────────────┘
           │                        │
           └────────┬───────────────┘
                    │ Both send MediatR Commands/Queries
                    │
         ┌──────────▼───────────────────────────────────────────┐
         │          Application Layer                           │
         │         (DaemonsMCP.Application)                     │
         ├──────────────────────────────────────────────────────┤
         │  Commands (Write Operations)                         │
         │    - CreateProject, UpdateFile, AddItem, etc.        │
         │  Queries (Read Operations)                           │
         │    - SearchFileSystem, GetItemById, etc.             │
         │  Validators (FluentValidation)                       │
         │  DTOs & Models                                       │
         └──────────┬───────────────────────────────────────────┘
                    │ Calls repositories & services
                    │
         ┌──────────▼───────────────────────────────────────────┐
         │        Infrastructure Layer                          │
         │      (DaemonsMCP.Infrastructure)                     │
         ├──────────────────────────────────────────────────────┤
         │  - ApplicationDbContext (EF Core)                    │
         │  - Repository Implementations                        │
         │  - FileWatcherService (debounced file monitoring)    │
         │  - ObjectHierarchyIndexingService (Roslyn parser)    │
         │  - CodeParserService (namespace/class/method)        │
         └──────────┬───────────────────────────────────────────┘
                    │ Persists to database
                    │
         ┌──────────▼───────────────────────────────────────────┐
         │              Domain Layer                            │
         │           (DaemonsMCP.Domain)                        │
         ├──────────────────────────────────────────────────────┤
         │  Entities:                                           │
         │    - Project, FileSystemNode, ObjectHierarchy        │
         │    - Item, ItemType, StatusType                      │
         │  Repository Interfaces (IProjectRepository, etc.)    │
         │  Domain Events                                       │
         │  Value Objects                                       │
         │  Constants & Enums                                   │
         └──────────────────────────────────────────────────────┘
                    │
         ┌──────────▼───────────────────────────────────────────┐
         │            SQL Server Database                       │
         │  Tables: Projects, FileSystemNodes, ObjectHierarchy, │
         │          Items, ItemTypes, StatusTypes               │
         └──────────────────────────────────────────────────────┘

Domain Layer (DaemonsMCP.Domain)

The domain layer contains the core business entities and defines contracts (interfaces) without any implementation details or external dependencies.

Key Entities

Project

  • Represents a codebase root directory
  • Properties: Id, Name, RootPath, Description, CreatedAt
  • Root aggregate for file system operations

FileSystemNode

  • Represents files and directories in a hierarchical tree
  • Properties: Id, ProjectId, ParentId, Name, RelativePath, IsDirectory, SizeInBytes
  • Self-referencing for parent-child relationships
  • Enforces forward-slash path normalization

ObjectHierarchy

  • Represents parsed code structures (namespaces, classes, methods, etc.)
  • Properties: Id, ProjectId, FileSystemNodeId, ParentId, IdentifierTypeId, Name, FullyQualifiedName, Signature
  • Links code constructs to source files
  • Supports hierarchical queries (namespace → class → method)

Item

  • Flexible hierarchical node system for notes, tasks, and documentation
  • Properties: Id, ParentId, Name, Details, ItemTypeId, StatusTypeId, Rank, Created, Modified, Completed
  • Optional references to FileSystemNode or ObjectHierarchy.
  • User-definable types and statuses

ItemType / StatusType

  • Configurable taxonomies for organizing Items
  • Default types: Feature, Bug, Task, Note, Documentation, Todo, Readme
  • Default statuses: Not Started, In Progress, Complete, Cancelled, Blocked

Repository Interfaces

Domain defines contracts for data access without implementation:

IProjectRepository
IFileSystemRepository
IObjectHierarchyRepository
IItemRepository
IItemTypeRepository
IStatusTypeRepository

Design Principles

  • No dependencies on other layers or external libraries
  • Pure C# entities with business logic only
  • Interface-based contracts for infrastructure concerns
  • Immutable value objects where appropriate
  • Domain events for cross-cutting concerns (future enhancement)

Application Layer (DaemonsMCP.Application)

The application layer orchestrates business logic using the MediatR CQRS pattern, keeping commands (writes) and queries (reads) strictly separated.

CQRS Pattern

Commands (mutations):

  • CreateProjectCommand
  • CreateProjectFileCommand
  • CreateProjectFolderCommand
  • UpdateProjectFileCommand
  • SyncProjectFileSystemCommand
  • AddUpdateItemCommand
  • DeleteItemCommand
  • AddUpdateItemTypeCommand
  • AddUpdateStatusTypeCommand

Queries (reads):

  • GetAllProjectsQuery
  • GetProjectByIdQuery
  • SearchFileSystemQuery
  • GetFileContentsQuery
  • SearchObjectHierarchyQuery
  • SearchItemsQuery
  • GetItemByIdQuery
  • GetReadmeQuery
  • ListItemTypesQuery
  • ListStatusTypesQuery

Handler Structure

Each command/query has a dedicated handler:

// Command pattern
public class CreateProjectCommandHandler 
    : IRequestHandler<CreateProjectCommand, Result<ProjectDto>>
{
    private readonly IProjectRepository _repository;
    
    public async Task<Result<ProjectDto>> Handle(
        CreateProjectCommand request, 
        CancellationToken cancellationToken)
    {
        // 1. Validate
        // 2. Create domain entity
        // 3. Persist via repository
        // 4. Return DTO
    }
}

Validation

FluentValidation ensures data integrity before handlers execute:

public class CreateProjectCommandValidator 
    : AbstractValidator<CreateProjectCommand>
{
    public CreateProjectCommandValidator()
    {
        RuleFor(x => x.Name).NotEmpty().MaximumLength(200);
        RuleFor(x => x.RootPath).NotEmpty().Must(BeValidPath);
    }
}

DTOs (Data Transfer Objects)

Application layer returns DTOs, never domain entities:

  • ProjectDto
  • FileSystemNodeDto
  • ObjectHierarchyDto
  • ItemDto
  • ItemTypeDto
  • StatusTypeDto

This prevents tight coupling between API consumers and domain model.

Result Pattern

All handlers return Result<T> for consistent error handling:

public class Result<T>
{
    public bool Success { get; set; }
    public T Data { get; set; }
    public string ErrorMessage { get; set; }
    public string Operation { get; set; }
}

Benefits:

  • No exceptions for business rule violations
  • Consistent error responses across MCP and REST
  • Easy to serialize to JSON-RPC or HTTP responses

Infrastructure Layer (DaemonsMCP.Infrastructure)

The infrastructure layer implements all external concerns: database access, file I/O, code parsing, and background services.

Entity Framework Core

ApplicationDbContext:

  • Manages all entity configurations
  • Implements repository interfaces via generic patterns
  • Handles database migrations
  • Configures relationships and indexes

Key Configurations:

modelBuilder.Entity<FileSystemNode>()
    .HasOne(f => f.Parent)
    .WithMany(f => f.Children)
    .HasForeignKey(f => f.ParentId)
    .OnDelete(DeleteBehavior.Restrict);

modelBuilder.Entity<ObjectHierarchy>()
    .HasIndex(o => o.FullyQualifiedName);

Repository Implementations

Concrete implementations of domain interfaces:

public class ProjectRepository : IProjectRepository
{
    private readonly ApplicationDbContext _context;
    
    public async Task<Project> GetByIdAsync(int id)
        => await _context.Projects.FindAsync(id);
        
    public async Task<int> AddAsync(Project project)
    {
        _context.Projects.Add(project);
        await _context.SaveChangesAsync();
        return project.Id;
    }
}

File Watcher Service

Monitors project directories for changes and triggers re-indexing:

Features:

  • Debounced file change detection (5-second window)
  • Batch processing to avoid excessive indexing
  • Queues change, processes when idle
  • Thread-safe with proper async/await patterns
  • Filters out temp files, binaries, and IDE artifacts

Flow:

File Change Detected → Debounce Timer → Queue File → 
Process Batch → Parse C# Files → Update ObjectHierarchy → 
Update FileSystemNodes

Code Parsing Services

CodeParserService (Roslyn-based):

  • Extracts namespaces, classes, interfaces, methods, properties, fields, events
  • Builds hierarchical relationships
  • Generates fully qualified names and signatures
  • Links to source file locations

ObjectHierarchyIndexingService:

  • Manages indexing queue
  • Orchestrates batch processing
  • Updates database efficiently
  • Handles concurrent file modifications

Supported Constructs:

  • Namespaces
  • Interfaces
  • Classes (including nested classes)
  • Methods (including constructors, operators)
  • Properties (with get/set accessors)
  • Fields
  • Events
  • Method parameters

Path Security

PathSecurityService:

  • Validates all paths are within project root
  • Blocks directory traversal attacks (../, ..\)
  • Normalizes paths to forward slashes
  • Prevents access to system directories
public bool IsPathSafe(string projectRoot, string requestedPath)
{
    var normalized = NormalizePath(requestedPath);
    var fullPath = Path.GetFullPath(Path.Combine(projectRoot, normalized));
    var rootPath = Path.GetFullPath(projectRoot);
    
    return fullPath.StartsWith(rootPath, StringComparison.OrdinalIgnoreCase);
}

Host Layer - Two Independent Entry Points

DaemonsMCP.exe (MCP Server)

Purpose: Runs as a long-lived daemon serving Claude Desktop via MCPSharp

Responsibilities:

  • Implements MCPSharp server protocol
  • Registers MCP tools (methods Claude can call)
  • Translates JSON-RPC requests to MediatR commands/queries
  • Formats responses according to MCP spec
  • Maintains persistent connection with Claude Desktop

Tool Handler Pattern:

[McpServerTool]
public class FileSystemToolHandler
{
    private readonly IMediator _mediator;
    
    [McpTool("search-file-system")]
    public async Task<Result<SearchResults>> SearchFileSystem(
        int projectId, 
        string filter, 
        bool includeFiles, 
        bool includeDirectories,
        int pageNo,
        int pageSize)
    {
        var query = new SearchFileSystemQuery
        {
            ProjectId = projectId,
            Filter = filter,
            // ... map parameters
        };
        
        return await _mediator.Send(query);
    }
}

Key MCP Tool Categories:

  • Project management (list-projects)
  • File system operations (search-file-system, get-project-file, create-project-file, etc.)
  • Code hierarchy (search-object-hierarchy)
  • Items system (search-items, add-update-item, etc.)
  • Metadata (list-item-types, list-status-types)
  • Documentation (readme)

DaemonsMCP.Api (ASP.NET Core REST API)

Purpose: Provides HTTP/REST access for web applications (Angular config viewer)

Responsibilities:

  • RESTful endpoints for all operations
  • OpenAPI/Swagger documentation
  • CORS for cross-origin requests
  • JSON serialization
  • Health checks

Endpoint Mapping:

app.MapProjectEndpoints()         // /api/projects
   .MapFileSystemEndpoints()      // /api/filesystem
   .MapIndexingEndpoints()        // /api/indexing
   .MapItemsEndpoints()           // /api/items
   .MapObjectHierarchyEndpoints() // /api/hierarchy

Minimal API Pattern:

public static class FileSystemEndpoints
{
    public static IEndpointRouteBuilder MapFileSystemEndpoints(
        this IEndpointRouteBuilder app)
    {
        app.MapGet("/api/filesystem/search", async (
            [FromServices] IMediator mediator,
            [AsParameters] SearchFileSystemRequest request) =>
        {
            var query = request.ToQuery();
            var result = await mediator.Send(query);
            return Results.Ok(result);
        });
        
        return app;
    }
}

Both hosts share:

  • Same Application Layer (commands/queries)
  • Same Infrastructure (repositories, services)
  • Same Domain (entities, interfaces)
  • Same business logic and validation

Data Flow Examples

Example 1: Create a File (via MCP)

1. Claude Desktop sends JSON-RPC request to DaemonsMCP.exe
   Tool: "create-project-file"
   Params: { projectId: 1, relativePath: "src/NewClass.cs", content: "..." }

2. MCP Tool Handler maps to CreateProjectFileCommand
   
3. MediatR dispatches to CreateProjectFileCommandHandler

4. Handler validates:
   - Project exists
   - Path is safe (within project root)
   - File doesn't already exist

5. Handler calls IFileSystemRepository.CreateFileAsync()

6. Repository writes file to disk via System.IO

7. Repository creates FileSystemNode entity in database

8. FileWatcherService detects new file

9. Queues file for indexing (if .cs file)

10. ObjectHierarchyIndexingService parses with Roslyn

11. Extracts namespaces/classes/methods → ObjectHierarchy table

12. Handler returns Result<FileSystemNodeDto>

13. MCP Tool Handler formats as JSON-RPC response

14. Claude receives success confirmation

Example 2: Search Code Hierarchy (via REST API)

1. Angular app sends HTTP GET to /api/hierarchy/search?searchTerm=UserService

2. Minimal API endpoint receives request

3. Maps to SearchObjectHierarchyQuery

4. MediatR dispatches to SearchObjectHierarchyQueryHandler

5. Handler calls IObjectHierarchyRepository.SearchAsync()

6. Repository executes EF Core query with filters:
   SELECT * FROM ObjectHierarchy 
   WHERE Name LIKE '%UserService%'
   ORDER BY FullyQualifiedName

7. Returns ObjectHierarchy entities

8. Handler maps to ObjectHierarchyDto list

9. Returns Result<PagedResult<ObjectHierarchyDto>>

10. API endpoint serializes to JSON

11. Angular app displays results in searchable list

Example 3: Background File Indexing

1. Developer saves MyService.cs in Visual Studio

2. FileWatcherService detects change event

3. Starts 5-second debounce timer

4. Additional saves during window → timer resets

5. Timer expires → file added to processing queue

6. ObjectHierarchyIndexingService processes batch:
   - Reads file content
   - Parses with Roslyn SyntaxTree
   - Extracts semantic model
   - Walks syntax nodes for namespaces/classes/methods

7. For each construct:
   - Creates/updates ObjectHierarchy record
   - Sets ParentId for hierarchy
   - Stores FullyQualifiedName, Signature
   - Links to FileSystemNode

8. Batch completes → queue emptied

9. Next file change starts new cycle

(No user interaction required - fully automatic)

Cross-Cutting Concerns

Logging

Serilog is configured at the host level:

  • Structured logging with context enrichment
  • File sinks (general and error logs)
  • Configurable log levels per namespace
  • Automatic log rotation and retention

Log Locations:

  • %LOCALAPPDATA%\DaemonsMCP\Logs\D3MCP-{date}.log
  • %LOCALAPPDATA%\DaemonsMCP\Logs\D3MCP-errors-{date}.log

Error Handling

Strategy: No exceptions for business logic failures

Pattern:

  • Commands/Queries return Result<T> with success/failure
  • Infrastructure exceptions are caught and logged
  • MCP responses use proper JSON-RPC error codes
  • REST API returns appropriate HTTP status codes

Configuration

Source Priority:

  1. Command line arguments
  2. Environment variables
  3. daemonsmcp.{Environment}.json
  4. daemonsmcp.json

Key Settings:

  • Database connection string
  • Log levels
  • CORS origins
  • File watcher settings (in code)

Dependency Injection

All layers use constructor injection:

// Application Layer
public class CreateProjectCommandHandler
{
    private readonly IProjectRepository _repository;
    
    public CreateProjectCommandHandler(IProjectRepository repository)
    {
        _repository = repository;
    }
}

// Infrastructure registered in host
builder.Services.AddScoped<IProjectRepository, ProjectRepository>();

Design Patterns Used

Architectural Patterns

  • Clean Architecture - Dependency inversion, layer separation
  • CQRS - Command/Query Responsibility Segregation
  • Repository Pattern - Data access abstraction
  • Mediator Pattern - Decoupled command/query handling
  • Result Pattern - No exceptions for business failures

Domain Patterns

  • Aggregate Roots - Project as boundary for file operations
  • Value Objects - Immutable descriptors (planned enhancement)
  • Domain Events - Cross-cutting notifications (planned enhancement)

Infrastructure Patterns

  • Unit of Work - EF Core DbContext
  • Lazy Loading Disabled - Explicit includes for performance
  • Debouncing - File watcher change aggregation
  • Batch Processing - Indexing queue optimization

Scalability Considerations

Current Scale

  • Designed for: Single developer, local machine, small to medium codebases
  • Typical project: 10K-100K files, 50K-500K code constructs
  • Database: SQL Server Express sufficient

Future Enhancements

For larger teams/codebases:

  • Add caching layer (Redis) for frequent queries
  • Implement pagination for all large result sets
  • Background job processing (Hangfire/Quartz) for indexing
  • Read replicas for query scaling
  • Message queue (RabbitMQ) for file change events

For multi-tenant scenarios:

  • Add user authentication/authorization
  • Row-level security on Projects
  • Project quotas and limits
  • API rate limiting

Technology Stack Summary

Layer Technologies
Domain .NET 9.0, C# 13
Application MediatR, FluentValidation, AutoMapper (planned)
Infrastructure EF Core 9, SQL Server, Microsoft.CodeAnalysis (Roslyn), Serilog
MCP Host MCPSharp, JSON-RPC
API Host ASP.NET Core 9, Minimal APIs, Swagger/OpenAPI
Client Angular 18, PrimeNG, Monaco Editor, TypeScript
Database SQL Server 2019+

Architectural Benefits

Separation of Concerns:

  • Business logic lives in one place (Application Layer)
  • Both MCP and REST share identical logic
  • No code duplication
  • Changes propagate to all consumers

Testability:

  • Each layer can be tested independently
  • Mock repositories for unit testing
  • Integration tests at handler level
  • End-to-end tests via MCP or REST

Maintainability:

  • Clear boundaries between layers
  • Dependencies flow inward (toward domain)
  • Easy to locate and modify features
  • CQRS separates read/write concerns

Extensibility:

  • Add new tools: Create handler + register tool
  • Add new entities: Domain → EF migration → handlers
  • Add new clients: Use same Application Layer
  • Swap infrastructure: Implement interfaces differently

Future Architectural Roadmap

Planned Enhancements:

  • SignalR Hub - Real-time updates between API and MCP
  • Domain Events - Cross-cutting concerns via event bus
  • Caching Layer - Redis for frequently accessed data
  • Multi-language Support - TypeScript, Python, SQL parsers
  • Workflow Engine - Light orchestration on top of MediatR
  • Audit Logging - Track all changes to entities
  • Soft Deletes - Preserve data with IsDeleted flag

Related Documentation

Clone this wiki locally