# codebase-mcp Architectural Review
**Date**: 2025-10-11
**Reviewer**: Claude Code (Master Software Architect)
**Review Scope**: Refactoring plan for codebase-mcp transformation to pure semantic search MCP
**Documents Reviewed**: constitution.md, tech-stack.md, refactoring-plan.md, implementation-phases.md
**Constitutional Framework**: Codebase MCP Server Constitution v2.2.0
---
## Executive Summary
**OVERALL ASSESSMENT: ARCHITECTURALLY SOUND WITH MINOR RECOMMENDATIONS**
The codebase-mcp refactoring plan demonstrates strong constitutional compliance and architectural rigor. The plan successfully addresses the core principle of "Simplicity Over Features" by removing non-search functionality (87.5% tool reduction) while implementing a robust multi-project architecture. The database-per-project pattern with per-project connection pooling provides proper isolation while maintaining performance guarantees.
**Key Strengths**:
- Excellent constitutional alignment across all 11 principles
- Clear separation of concerns (search vs workflow management)
- Comprehensive migration strategy with risk mitigation
- Performance targets well-defined and testable
- Strong integration pattern with workflow-mcp (optional, graceful degradation)
**Minor Concerns**:
- Database-per-project pattern needs connection pool limits to prevent resource exhaustion
- workflow-mcp integration failure modes need clearer error messaging
- Performance benchmarking should include multi-tenant stress tests
**Recommended Actions**:
1. Add connection pool limit configuration (max projects)
2. Enhance workflow-mcp integration error messages
3. Add multi-tenant performance benchmarks
4. Document database maintenance procedures (vacuum, index rebuild)
---
## Constitutional Compliance Scorecard
### Principle I: Simplicity Over Features
**Status**: ✅ COMPLIANT
**Evidence**:
- Removes 14 of 16 tools (87.5% reduction)
- Eliminates 9 database tables (keeps only 2)
- Reduces codebase from ~4,500 to ~1,800 lines (60% reduction)
- Tool surface: Only `index_repository` and `search_code`
**Constitutional Citation**:
> "The MCP server MUST focus exclusively on semantic code search. Feature requests that extend beyond indexing, embedding, and searching code repositories MUST be rejected."
**Analysis**: The refactoring plan perfectly embodies this principle by surgically removing all non-search functionality (work items, tasks, vendors, deployments, project configuration) while preserving and enhancing the core semantic search capability. The multi-project support addition is justified as an essential architectural feature for search isolation, not scope creep.
**Issues**: None.
**Recommendations**: None. Exemplary compliance.
---
### Principle II: Local-First Architecture
**Status**: ✅ COMPLIANT
**Evidence**:
- Ollama for embeddings (local only, no cloud APIs)
- PostgreSQL local/network deployment (no managed services)
- Multi-project databases stored locally
- No external API dependencies except optional workflow-mcp (also local)
**Constitutional Citation**:
> "The system MUST operate completely offline after initial setup. All dependencies MUST be locally hosted (PostgreSQL, Ollama). Zero cloud API calls are permitted except to local Ollama instance."
**Analysis**: The architecture maintains strict local-first principles. The workflow-mcp integration is correctly designed as optional with graceful fallback to explicit `project_id` parameters. The database-per-project pattern keeps all data local and isolated.
**Issues**: None.
**Recommendations**: Document offline testing procedures in migration guide (validate works without internet after Ollama model download).
---
### Principle III: Protocol Compliance (MCP via SSE)
**Status**: ✅ COMPLIANT
**Evidence**:
- FastMCP framework with MCP Python SDK usage confirmed
- SSE transport (no stdout/stderr pollution)
- Structured logging to `/tmp/codebase-mcp.log`
- mcp-inspector validation in Phase 5 and Phase 12
**Constitutional Citation**:
> "All MCP communication MUST use SSE transport. Stdout and stderr MUST NEVER contain protocol messages or application logs. Logging MUST go exclusively to `/tmp/codebase-mcp.log`."
**Analysis**: The plan correctly maintains protocol compliance through FastMCP framework. The refactoring phases include explicit mcp-inspector validation checkpoints (Phase 5: server registration, Phase 12: full validation).
**Issues**: None.
**Recommendations**: Add pre-commit hook to block `print()` statements (mentioned in constitution but not in implementation phases).
---
### Principle IV: Performance Guarantees
**Status**: ✅ COMPLIANT
**Evidence**:
- Search latency target: <500ms p95 (Phase 11 performance tests)
- Indexing target: <60s for 10,000 files (Phase 11 performance tests)
- HNSW indexes specified in schema (refactoring-plan.md line 150)
- Connection pooling: min 5, max 20 per project (implementation-phases.md line 768)
- AsyncPG for non-blocking I/O (tech-stack.md)
**Constitutional Citation**:
> "The system MUST meet these performance targets:
> - Index 10,000 line codebase in under 60 seconds
> - Search queries MUST return in under 500ms (p95)"
**Analysis**: Performance targets are clearly defined with comprehensive testing in Phase 11. The architecture supports performance through HNSW indexes, connection pooling, and async I/O. The per-project database pattern prevents cross-tenant query overhead.
**Issues**: ⚠️ MINOR - Multi-tenant stress testing not explicitly included in performance test suite.
**Recommendations**:
1. Add multi-tenant performance test: 10+ projects with concurrent searches
2. Benchmark connection pool overhead with 20+ active projects
3. Document HNSW index tuning parameters (m=16, ef_construction=64) rationale
---
### Principle V: Production Quality Standards
**Status**: ✅ COMPLIANT
**Evidence**:
- mypy --strict validation in Phase 12 (implementation-phases.md line 1132)
- Test coverage >80% required (Phase 12 acceptance criteria)
- Pydantic models for all parameters (search.py examples in refactoring-plan.md)
- Comprehensive error handling (database operations, workflow-mcp integration)
- Structured logging with context (Phase 7: project_context.py line 587)
**Constitutional Citation**:
> "Error handling MUST be comprehensive with specific error messages. All exceptions MUST be caught and logged with context. Type hints MUST be complete and enforced with mypy --strict."
**Analysis**: The plan enforces production quality standards through multiple validation gates (mypy, coverage, protocol compliance). Error handling patterns are evident in workflow-mcp integration (graceful fallback) and database operations (connection pooling, transaction handling).
**Issues**: None.
**Recommendations**: Add explicit error taxonomy (e.g., `ProjectNotFoundError`, `IndexingFailedError`) for better client-side error handling.
---
### Principle VI: Specification-First Development
**Status**: ✅ COMPLIANT
**Evidence**:
- Phase 0: Prerequisites and Planning (validate artifacts before work)
- Planning artifacts documented: spec.md, plan.md (implied by Phase 0 checklist)
- Migration guide created in Phase 10 (specification for users)
- Acceptance criteria defined for each phase
**Constitutional Citation**:
> "Feature specifications MUST be completed before implementation planning. Specifications focus on user requirements (WHAT/WHY) without implementation details (HOW)."
**Analysis**: The refactoring plan itself follows specification-first principles by creating comprehensive planning documents before implementation. Each phase has clear acceptance criteria (WHAT must be achieved) before implementation steps (HOW to achieve).
**Issues**: None.
**Recommendations**: None. The planning documents exemplify specification-first development.
---
### Principle VII: Test-Driven Development
**Status**: ✅ COMPLIANT
**Evidence**:
- Phase 6: Remove Non-Search Tests (maintains test hygiene)
- Phase 7: Multi-project tests created BEFORE implementation
- Phase 11: Performance tests validate requirements
- Phase 12: Full test suite validation before release
- TDD pattern evident: "Test migration on test database BEFORE production" (Phase 2)
**Constitutional Citation**:
> "Test tasks MUST precede implementation tasks. Integration tests MUST validate MCP protocol compliance. Performance tests MUST validate against guarantees (60s indexing, 500ms search)."
**Analysis**: The implementation phases follow TDD principles. Database migrations are tested on test databases before production (Phase 2). Multi-project functionality includes tests for isolation (test_multi_project.py). Performance benchmarks validate constitutional requirements.
**Issues**: None.
**Recommendations**: Make TDD pattern more explicit in phase descriptions (e.g., "Phase 7a: Write multi-project tests", "Phase 7b: Implement multi-project support").
---
### Principle VIII: Pydantic-Based Type Safety
**Status**: ✅ COMPLIANT
**Evidence**:
- IndexRepositoryParams and SearchCodeParams models (refactoring-plan.md line 456-465)
- mypy --strict validation in Phase 12
- Pydantic 2.x specified in tech-stack.md (line 248-280)
- Field validators for parameter constraints (ge=1, le=50 for limits)
**Constitutional Citation**:
> "All data models MUST use Pydantic with explicit types and validators. MCP protocol messages MUST inherit from `pydantic.BaseModel`. Validation errors MUST be caught at system boundaries with clear field-level messages."
**Analysis**: The refactoring maintains Pydantic models for all tool parameters. Type safety is enforced through mypy --strict validation gate in final phase. Runtime validation catches invalid parameters at MCP boundaries.
**Issues**: None.
**Recommendations**: Add examples of Pydantic validation error messages in API documentation (helps clients handle validation failures).
---
### Principle IX: Orchestrated Subagent Execution
**Status**: ⚠️ NOT APPLICABLE (Refactoring context)
**Evidence**: N/A - This principle applies to implementation phase, not refactoring planning.
**Constitutional Citation**:
> "During implementation, the orchestrating agent MUST delegate code-writing tasks to specialized subagents."
**Analysis**: This principle governs how Claude Code executes the implementation plan, not the plan itself. The principle will be evaluated during actual `/implement` execution, not in architectural review of the plan.
**Issues**: None (principle not applicable to planning documents).
**Recommendations**: When executing this plan with `/implement`, ensure parallel execution of independent phases (e.g., Phase 3 and Phase 6 could theoretically run in parallel as they're independent file deletions).
---
### Principle X: Git Micro-Commit Strategy
**Status**: ✅ COMPLIANT
**Evidence**:
- Branch strategy: `002-refactor-pure-search` (Phase 1)
- Commit after each phase with Conventional Commits format
- Examples: `refactor(db): remove non-search tables`, `feat(search): add multi-project support`
- Working state requirement: All tests pass at every commit (Phase 12 validation)
**Constitutional Citation**:
> "Every feature MUST be developed on a dedicated branch created from main. Commits MUST be atomic and frequent (micro-commits after each completed task or logical unit). Commit messages MUST follow Conventional Commits format."
**Analysis**: The implementation phases define clear commit points after each phase with proper Conventional Commits format. Each phase has acceptance criteria that must pass before committing, ensuring working state. Branch naming follows `###-feature-name` pattern.
**Issues**: None.
**Recommendations**: None. Git strategy is exemplary.
---
### Principle XI: FastMCP and Python SDK Foundation
**Status**: ✅ COMPLIANT
**Evidence**:
- FastMCP decorators: `@mcp.tool()` (refactoring-plan.md line 398-402)
- MCP Python SDK types for responses (tech-stack.md line 160-176)
- Pydantic integration for parameter schemas (refactoring-plan.md line 456-465)
- SSE transport via FastMCP (Phase 5 server configuration)
**Constitutional Citation**:
> "All MCP server implementations MUST be built using FastMCP (https://github.com/jlowin/fastmcp) as the primary framework and the official MCP Python SDK."
**Analysis**: The refactoring plan maintains FastMCP framework usage throughout. Tool registration uses FastMCP decorators. Parameter schemas use Pydantic (FastMCP-compatible). No raw JSON-RPC handling.
**Issues**: None.
**Recommendations**: None. FastMCP foundation is solid.
---
## Tech Stack Validation
### Approved Technologies ✅
**Python 3.11+**
- ✅ Specified in tech-stack.md (line 11-29)
- ✅ Async/await patterns used throughout (AsyncPG, aiohttp)
- ✅ Type hints enforced (mypy --strict)
**PostgreSQL 14+ with pgvector**
- ✅ Specified in tech-stack.md (line 31-57)
- ✅ HNSW indexes for vector similarity (schema.sql line 150)
- ✅ Per-project database pattern (connection.py line 756-769)
**Ollama with nomic-embed-text**
- ✅ Specified in tech-stack.md (line 90-123)
- ✅ Local-first embedding generation
- ✅ aiohttp for HTTP API (tech-stack.md line 355-365)
**FastMCP Framework**
- ✅ Specified in tech-stack.md (line 126-157)
- ✅ Tool registration via decorators
- ✅ Pydantic parameter schemas
**AsyncPG**
- ✅ Specified in tech-stack.md (line 178-212)
- ✅ Connection pooling (5-20 connections per project)
- ✅ Async context managers for transactions
**Pydantic 2.x**
- ✅ Specified in tech-stack.md (line 248-280)
- ✅ Runtime validation at MCP boundaries
- ✅ JSON Schema generation for tools
**Tree-sitter**
- ✅ Specified in tech-stack.md (line 215-247)
- ✅ AST-aware code chunking (no changes in refactor)
### Prohibited Technologies ✅ (None Found)
- ❌ OpenAI embeddings (NOT USED - Ollama only)
- ❌ SQLite (NOT USED - PostgreSQL only)
- ❌ psycopg2 (NOT USED - AsyncPG only)
- ❌ Raw JSON-RPC (NOT USED - FastMCP only)
- ❌ Python 3.10 or earlier (NOT USED - 3.11+ required)
**Verdict**: Tech stack is 100% compliant with constitutional requirements. No prohibited technologies detected.
---
## On-Rails Workflow Compliance
### Pydantic Models ✅
**Evidence**: IndexRepositoryParams, SearchCodeParams models in refactoring-plan.md (line 456-465)
**Compliance**: FULL - All tool parameters use Pydantic BaseModel with Field validators
### mypy --strict ✅
**Evidence**: Phase 12 validation (implementation-phases.md line 1132)
**Compliance**: FULL - Enforced as release gate, no merge without passing
### Git Micro-Commits ✅
**Evidence**: Each phase ends with commit (Conventional Commits format)
**Compliance**: FULL - Clear commit strategy with working state requirement
### TDD Approach ✅
**Evidence**: Phase 11 performance tests, Phase 7 multi-project tests before implementation
**Compliance**: FULL - Tests written before or concurrently with implementation
### FastMCP Pattern ✅
**Evidence**: @mcp.tool() decorators, Pydantic integration, SSE transport
**Compliance**: FULL - Framework-level abstractions used throughout
**Overall On-Rails Compliance**: 5/5 (100%)
---
## Architecture Pattern Analysis
### Database-Per-Project Pattern
**Design**:
```python
# Per-project connection pools
_pools: dict[str, asyncpg.Pool] = {}
async def get_db_pool(project_id: str) -> asyncpg.Pool:
database_name = f"codebase_{project_id}"
if project_id not in _pools:
_pools[project_id] = await asyncpg.create_pool(
database=database_name,
min_size=5,
max_size=20
)
return _pools[project_id]
```
**Strengths**:
1. **Strong Isolation**: Projects cannot access each other's data (database-level boundary)
2. **Independent Scaling**: Each project database can be tuned independently
3. **Simplified Queries**: No complex WHERE project_id filters, database is the filter
4. **Clear Ownership**: One database = one project (easy to backup, migrate, delete)
**Concerns**:
1. ⚠️ **Resource Exhaustion**: 100 projects = 100 databases × 20 connections = 2000 PostgreSQL connections
- PostgreSQL default max_connections = 100 (will hit limit at ~5 projects)
- Need configuration for max projects or dynamic pool sizing
2. ⚠️ **Maintenance Overhead**: Database vacuum, index rebuilds, backups must run per-project
3. ⚠️ **Connection Pool Memory**: 100 pools × 20 connections × ~2MB per connection = ~4GB RAM
**Recommendations**:
1. **Add Connection Pool Limits**:
```python
MAX_PROJECTS = int(os.getenv("MAX_PROJECTS", "50"))
async def get_db_pool(project_id: str) -> asyncpg.Pool:
if len(_pools) >= MAX_PROJECTS and project_id not in _pools:
raise RuntimeError(f"Maximum projects ({MAX_PROJECTS}) reached")
# ... rest of implementation
```
2. **Implement Pool Eviction**:
- LRU eviction: Close least-recently-used pools when MAX_PROJECTS reached
- Idle timeout: Close pools with no activity for 1+ hours
3. **Document Maintenance Procedures**:
```bash
# Vacuum all project databases
for db in $(psql -lqt | cut -d \| -f 1 | grep codebase_); do
vacuumdb --analyze $db
done
```
4. **PostgreSQL Configuration**:
- Increase `max_connections` in postgresql.conf (e.g., 500)
- Document in tech-stack.md and migration-guide.md
**Architectural Verdict**: SOUND with minor enhancements needed for production scale
---
### Connection Pooling Strategy
**Design**:
- **Min Size**: 5 connections per project
- **Max Size**: 20 connections per project
- **Pooling**: Per-project pools (not global pool)
**Analysis**:
- ✅ Min size (5) ensures connections available immediately (no cold start)
- ✅ Max size (20) prevents runaway connection creation
- ⚠️ Global resource usage unbounded (100 projects × 20 = 2000 connections)
**Recommendations**:
1. Add adaptive pooling:
```python
# Low-activity projects: min=1, max=5
# High-activity projects: min=5, max=20
async def get_pool_config(project_id: str) -> tuple[int, int]:
activity = await get_project_activity(project_id)
if activity < 10: # queries/hour
return (1, 5)
return (5, 20)
```
2. Monitor pool metrics:
- Active connections per project
- Pool wait times
- Connection churn rate
**Architectural Verdict**: SOUND with recommended enhancements for efficiency
---
### Multi-Project Isolation
**Design**:
- Database-level isolation (separate databases per project)
- Connection pool isolation (separate pools per project)
- Schema isolation (project_id in repositories/code_chunks tables)
**Testing**:
- Phase 7: test_multi_project_isolation (implementation-phases.md line 672-706)
- Validates no cross-contamination between projects
**Analysis**:
- ✅ Strongest possible isolation (database-level boundary)
- ✅ No risk of accidental cross-project queries (no shared tables)
- ✅ Clear security boundary (PostgreSQL permissions per database)
**Recommendations**:
- Add stress test: 20 projects, concurrent indexing + searches
- Document disaster recovery: How to restore single project without affecting others
**Architectural Verdict**: EXCELLENT - Database-level isolation is gold standard
---
## Integration Analysis
### workflow-mcp Integration Design
**Pattern**: Optional integration with graceful degradation
**Implementation**:
```python
async def get_active_project_id() -> Optional[str]:
"""Query workflow-mcp for active project ID"""
try:
async with aiohttp.ClientSession() as session:
async with session.get(
f"{workflow_mcp_url}/get_active_project",
timeout=aiohttp.ClientTimeout(total=2.0)
) as response:
if response.status == 200:
data = await response.json()
return data.get("project_id")
return None
except Exception:
logging.warning("Failed to get active project from workflow-mcp")
return None
# Usage in search_code
project_id = params.project_id or await get_active_project_id()
if not project_id:
raise ValueError("project_id required when workflow-mcp unavailable")
```
**Strengths**:
1. ✅ **Loose Coupling**: codebase-mcp works standalone (no hard dependency)
2. ✅ **Graceful Degradation**: Falls back to explicit project_id
3. ✅ **Timeout Protection**: 2-second timeout prevents hanging
4. ✅ **Error Handling**: Catches all exceptions, logs warning, returns None
**Concerns**:
1. ⚠️ **Error Message Clarity**: "project_id required when workflow-mcp unavailable" could be more helpful
- Doesn't explain HOW to provide project_id
- Doesn't distinguish between workflow-mcp down vs. no active project
**Recommendations**:
1. **Enhanced Error Messages**:
```python
if not project_id:
raise ValueError(
"project_id parameter required. Either:\n"
"1. Provide explicit project_id in search_code call\n"
"2. Set active project via workflow-mcp\n"
"3. Check workflow-mcp is running: curl http://localhost:3000/health"
)
```
2. **Integration Health Check**:
```python
async def check_workflow_mcp_health() -> bool:
"""Check if workflow-mcp is available"""
try:
async with aiohttp.ClientSession() as session:
async with session.get(f"{workflow_mcp_url}/health", timeout=1.0) as resp:
return resp.status == 200
except Exception:
return False
```
3. **Retry Logic**: Add exponential backoff for transient workflow-mcp failures
- Retry once after 100ms if first request fails
- Prevents false negatives from temporary network hiccups
**Integration Failure Modes**:
| Failure Mode | Current Behavior | Recommended Behavior |
|--------------|------------------|----------------------|
| workflow-mcp down | Returns None → requires explicit project_id | ✅ Correct |
| workflow-mcp slow (>2s) | Timeout → returns None | ✅ Correct |
| No active project set | Returns None (200 OK but no project_id) | ⚠️ Same error as "down" - should distinguish |
| Invalid project_id from workflow-mcp | Passes invalid ID to database → error | ⚠️ Should validate project exists |
**Recommended Enhancements**:
```python
async def get_active_project_id() -> tuple[Optional[str], str]:
"""
Returns (project_id, status_message)
Status: "success", "no_active_project", "workflow_mcp_unavailable"
"""
try:
async with aiohttp.ClientSession() as session:
async with session.get(...) as response:
if response.status == 200:
data = await response.json()
project_id = data.get("project_id")
if project_id:
return (project_id, "success")
return (None, "no_active_project")
return (None, "workflow_mcp_unavailable")
except Exception:
return (None, "workflow_mcp_unavailable")
```
**Architectural Verdict**: SOUND with recommended error message improvements
---
### Interface Contract
**Current Design**: Implicit HTTP API contract
**Expected Workflow-MCP API**:
```http
GET /mcp/workflow-mcp/get_active_project
Response 200 OK:
{
"project_id": "my-project"
}
Response 404 Not Found:
{
"error": "No active project set"
}
```
**Concerns**:
- ⚠️ No formal API contract (OpenAPI spec)
- ⚠️ No version negotiation (what if workflow-mcp changes response format?)
- ⚠️ No authentication (assumes localhost, no multi-user scenarios)
**Recommendations**:
1. **Document API Contract**:
- Create `docs/workflow-mcp-integration.md`
- Specify request/response schemas
- Document error codes and meanings
2. **Add API Versioning**:
```python
async with session.get(
f"{workflow_mcp_url}/v1/get_active_project", # Version in URL
headers={"Accept": "application/json; version=1.0"}
) as response:
# ...
```
3. **Health Check Endpoint**: Document workflow-mcp health check for troubleshooting
```bash
# Verify workflow-mcp is running
curl http://localhost:3000/health
# Verify active project is set
curl http://localhost:3000/mcp/workflow-mcp/get_active_project
```
**Architectural Verdict**: ACCEPTABLE with documentation improvements needed
---
## Performance Characteristics
### Performance Targets (Constitutional Requirements)
| Metric | Target | Test Phase | Validation Method |
|--------|--------|------------|-------------------|
| Search Latency (p95) | <500ms | Phase 11 | 100 searches, sort, check 95th percentile |
| Search Latency (p50) | <300ms | Phase 11 | 100 searches, sort, check 50th percentile |
| Indexing Throughput | <60s for 10k files | Phase 11 | Time index operation on test repo |
### Performance Test Coverage
**Phase 11 Tests** (implementation-phases.md line 1016-1070):
```python
# Test 1: Search latency validation
@pytest.mark.performance
async def test_search_latency_p95(large_indexed_repo):
latencies = []
for i in range(100):
start = time.time()
result = await search_code(query=f"test query {i}", ...)
latencies.append((time.time() - start) * 1000)
p95 = latencies[int(0.95 * len(latencies))]
assert p95 < 500
# Test 2: Indexing throughput validation
@pytest.mark.performance
async def test_indexing_throughput(temp_repo_10k_files):
start = time.time()
result = await index_repository(repo_path=temp_repo_10k_files, ...)
duration = time.time() - start
assert duration < 60
```
**Analysis**:
- ✅ Covers constitutional requirements (search, indexing)
- ✅ Uses realistic test data (10k files)
- ✅ Calculates percentiles correctly (p95, p50)
- ⚠️ Missing multi-tenant stress test (concurrent projects)
**Missing Performance Tests**:
1. **Multi-Tenant Stress Test**:
```python
@pytest.mark.performance
async def test_multi_tenant_search_latency():
"""Test search latency with 10 concurrent projects"""
projects = [f"project-{i}" for i in range(10)]
# Index all projects
for project_id in projects:
await index_repository(repo_path="/test-repo", project_id=project_id)
# Concurrent searches across all projects
async def search_project(project_id):
return await search_code(query="test", project_id=project_id)
start = time.time()
results = await asyncio.gather(*[search_project(p) for p in projects])
duration = time.time() - start
# Each search should still be <500ms even with concurrent load
assert duration < 5.0 # 10 concurrent * 500ms = 5s max
```
2. **Connection Pool Stress Test**:
```python
@pytest.mark.performance
async def test_connection_pool_under_load():
"""Test connection pool doesn't exhaust under load"""
# Create 50 projects (at max=20 connections each = 1000 total)
projects = [f"project-{i}" for i in range(50)]
# Concurrent searches should not fail with connection errors
async def search_many(project_id):
for i in range(100):
await search_code(query=f"test {i}", project_id=project_id)
await asyncio.gather(*[search_many(p) for p in projects])
# If this completes without connection errors, pool is working
```
3. **Database Size Impact Test**:
```python
@pytest.mark.performance
async def test_search_latency_with_large_corpus():
"""Test search latency with 100k chunks"""
# Index large corpus
await index_repository(repo_path="/large-repo", project_id="large")
# Verify search still meets latency target
latencies = []
for i in range(100):
start = time.time()
result = await search_code(query=f"test {i}", project_id="large")
latencies.append((time.time() - start) * 1000)
p95 = latencies[int(0.95 * len(latencies))]
assert p95 < 500 # Still meets target with large corpus
```
**Recommendations**:
1. Add multi-tenant stress tests to Phase 11
2. Benchmark connection pool behavior at scale (50+ projects)
3. Test performance degradation with large corpora (100k+ chunks)
4. Document performance tuning parameters (HNSW m, ef_construction)
**Architectural Verdict**: GOOD with recommended stress test additions
---
## Risk Assessment
### High-Risk Areas
#### 1. Database Connection Exhaustion
**Risk Level**: HIGH
**Scenario**: 100 projects × 20 connections = 2000 PostgreSQL connections exceeds default max_connections (100)
**Impact**: PostgreSQL refuses new connections → service outage
**Mitigation Plan**:
- [x] Document PostgreSQL configuration (increase max_connections)
- [ ] Add MAX_PROJECTS configuration limit
- [ ] Implement pool eviction (LRU or idle timeout)
- [ ] Add monitoring (active connections per project)
**Recommendation**: CRITICAL - Implement before production deployment
---
#### 2. workflow-mcp Integration Failures
**Risk Level**: MEDIUM
**Scenario**: workflow-mcp down or slow → all searches requiring active project fail
**Impact**: Users must provide explicit project_id (degraded UX, not outage)
**Mitigation Plan**:
- [x] Graceful fallback to explicit project_id
- [x] 2-second timeout on workflow-mcp calls
- [ ] Improve error messages (explain how to provide project_id)
- [ ] Add integration health check endpoint
**Recommendation**: MEDIUM - Improve error messages in Phase 7
---
#### 3. Migration Data Loss
**Risk Level**: MEDIUM
**Scenario**: User runs migration without backup → loses work items/tasks data
**Impact**: Permanent data loss
**Mitigation Plan**:
- [x] Migration guide emphasizes backup (docs/migration-guide.md)
- [x] Migration tested on test database first (Phase 2)
- [x] Non-destructive migration (adds columns before dropping tables)
- [ ] Add migration --dry-run mode (preview changes)
**Recommendation**: MEDIUM - Add dry-run mode to migration script
---
#### 4. Performance Regression
**Risk Level**: MEDIUM
**Scenario**: Multi-project overhead degrades search latency below <500ms target
**Impact**: Constitutional violation, user experience degradation
**Mitigation Plan**:
- [x] Performance tests in Phase 11
- [x] HNSW indexes for fast similarity search
- [ ] Multi-tenant stress tests (recommended addition)
- [ ] Benchmark before/after refactor
**Recommendation**: MEDIUM - Add multi-tenant stress tests to Phase 11
---
### Low-Risk Areas
#### 5. Breaking Changes Impact Users
**Risk Level**: LOW
**Scenario**: v2.0.0 breaks existing integrations
**Impact**: Users need to update tool calls (one-time migration)
**Mitigation Plan**:
- [x] Semantic versioning (v2.0.0 signals breaking change)
- [x] Comprehensive migration guide
- [x] Clear CHANGELOG documenting changes
- [x] Example code showing old vs new usage
**Recommendation**: LOW - Well-mitigated through documentation
---
## Recommendations
### Critical (Must-Fix Before Release)
1. **Add Connection Pool Limits** (Addresses: Database connection exhaustion risk)
- **File**: `src/codebase_mcp/database/connection.py`
- **Change**:
```python
MAX_PROJECTS = int(os.getenv("MAX_PROJECTS", "50"))
async def get_db_pool(project_id: str) -> asyncpg.Pool:
if len(_pools) >= MAX_PROJECTS and project_id not in _pools:
# Implement LRU eviction or raise error
oldest_project = min(_pools.items(), key=lambda x: x[1].last_used)
await _pools[oldest_project[0]].close()
del _pools[oldest_project[0]]
# ... rest of implementation
```
- **Rationale**: Prevents PostgreSQL connection exhaustion
- **Phase**: Add to Phase 8 (Connection Management)
2. **Document PostgreSQL Configuration** (Addresses: Database connection exhaustion risk)
- **File**: `docs/installation.md` (create if missing)
- **Content**:
```markdown
## PostgreSQL Configuration
For production deployments supporting 50+ projects, increase PostgreSQL max_connections:
```bash
# postgresql.conf
max_connections = 500 # Support 50 projects × 20 connections
shared_buffers = 1GB # Increase for connection overhead
```
Restart PostgreSQL: `sudo systemctl restart postgresql`
```
- **Phase**: Add to Phase 9 (Documentation)
---
### High-Priority (Recommended Before Release)
3. **Enhanced Error Messages for workflow-mcp Integration** (Addresses: Integration failure UX)
- **File**: `src/codebase_mcp/tools/search.py`
- **Change**:
```python
project_id, status = await get_active_project_id() # Updated return type
if not project_id:
if status == "no_active_project":
raise ValueError(
"No active project set in workflow-mcp. Use workflow-mcp to set active project, "
"or provide explicit project_id parameter to search_code()."
)
elif status == "workflow_mcp_unavailable":
raise ValueError(
"workflow-mcp unavailable. Either:\n"
"1. Start workflow-mcp: workflow-mcp run\n"
"2. Provide explicit project_id parameter to search_code()"
)
```
- **Phase**: Add to Phase 7 (Multi-Project Support)
4. **Add Multi-Tenant Stress Tests** (Addresses: Performance risk)
- **File**: `tests/test_performance.py`
- **Change**: Add tests for concurrent project searches (see Performance Characteristics section)
- **Phase**: Add to Phase 11 (Performance Testing)
---
### Medium-Priority (Post-Release Acceptable)
5. **Document workflow-mcp Integration Contract** (Addresses: Integration clarity)
- **File**: `docs/workflow-mcp-integration.md` (new)
- **Content**: API contract, error codes, health checks (see Integration Analysis section)
- **Phase**: Add to Phase 9 (Documentation)
6. **Add Migration Dry-Run Mode** (Addresses: Migration safety)
- **File**: `migrations/002_remove_non_search_tables.sql`
- **Change**: Add comment block with dry-run instructions
- **Phase**: Add to Phase 10 (Migration Guide)
7. **Implement Pool Activity Monitoring** (Addresses: Observability)
- **File**: `src/codebase_mcp/database/connection.py`
- **Change**: Add metrics for active connections, pool wait times
- **Phase**: Post-v2.0.0 (v2.1.0 enhancement)
---
## Overall Assessment
### Constitutional Compliance Summary
| Principle | Status | Score |
|-----------|--------|-------|
| I. Simplicity Over Features | ✅ COMPLIANT | 5/5 |
| II. Local-First Architecture | ✅ COMPLIANT | 5/5 |
| III. Protocol Compliance | ✅ COMPLIANT | 5/5 |
| IV. Performance Guarantees | ✅ COMPLIANT | 4/5 (add stress tests) |
| V. Production Quality | ✅ COMPLIANT | 5/5 |
| VI. Specification-First | ✅ COMPLIANT | 5/5 |
| VII. Test-Driven Development | ✅ COMPLIANT | 5/5 |
| VIII. Pydantic Type Safety | ✅ COMPLIANT | 5/5 |
| IX. Orchestrated Subagents | N/A | N/A |
| X. Git Micro-Commits | ✅ COMPLIANT | 5/5 |
| XI. FastMCP Foundation | ✅ COMPLIANT | 5/5 |
**Overall Score**: 49/50 (98% compliance)
---
### Architectural Soundness
**Core Architecture**: ✅ EXCELLENT
- Database-per-project pattern provides strong isolation
- Connection pooling appropriate for multi-tenant use
- FastMCP framework ensures protocol compliance
- Performance targets well-defined and testable
**Integration Design**: ✅ SOUND
- Loose coupling with workflow-mcp (optional integration)
- Graceful degradation on failure
- Clear fallback path (explicit project_id)
**Risk Mitigation**: ⚠️ GOOD (with recommended improvements)
- Database connection exhaustion needs configuration limits
- Migration safety well-handled
- Performance testing needs multi-tenant stress tests
---
### Final Verdict
**ARCHITECTURALLY SOUND WITH MINOR RECOMMENDATIONS**
The codebase-mcp refactoring plan demonstrates exceptional architectural rigor and constitutional compliance. The plan successfully achieves its core objective (Simplicity Over Features) while introducing essential multi-project capabilities. The database-per-project pattern is architecturally sound with proper isolation guarantees.
**Recommended Pre-Release Actions**:
1. ✅ Add connection pool limits (CRITICAL)
2. ✅ Document PostgreSQL configuration (CRITICAL)
3. ✅ Enhance workflow-mcp error messages (HIGH)
4. ✅ Add multi-tenant stress tests (HIGH)
**Post-Release Enhancements**:
- Document workflow-mcp integration contract
- Add migration dry-run mode
- Implement pool activity monitoring
With the critical recommendations implemented, this plan is **APPROVED FOR IMPLEMENTATION**.
---
**Review Completed**: 2025-10-11
**Next Steps**: Implement critical recommendations, then proceed with Phase 0 (Prerequisites)