-
-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Problem
The codebase lacks comprehensive architecture documentation explaining key design patterns and structures, making it harder for new contributors to understand the system design.
Missing Documentation
1. Tool Registration Pattern
No documentation explaining:
- How
setupXxxTool()functions work - Why tools are registered separately instead of inline
- How parameter definitions map to handler arguments
- The role of
mcp.NewTool()andregisterAllTools()
Example to document:
// Each tool follows this pattern:
// 1. Create tool with mcp.NewTool(name, description, inputSchema)
// 2. Define handler function with parameter validation
// 3. Call business logic via appInstance methods
// 4. Format response as JSON and return CallToolResult2. TableToolConfig Pattern
The TableToolConfig struct in main.go is used to reduce duplication, but this pattern isn't explained:
type TableToolConfig struct {
name string
description string
methodName string
needsTable bool
}Questions unanswered:
- Why was this abstraction created?
- When to use it vs custom tool setup?
- How does
needsTableaffect behavior?
3. Interface Hierarchy
interfaces.go defines key interfaces, but their relationships aren't documented:
PostgreSQLClient (interface)
└── PostgreSQLClientImpl (concrete implementation)
App (struct)
└── Uses: PostgreSQLClient interface
Missing explanations:
- Why the interface exists (testing? multiple implementations?)
- What's the contract between App and PostgreSQLClient?
- When to use the interface vs concrete type?
4. Layered Architecture
The codebase follows a layered pattern, but it's not explicitly documented:
main.go (MCP Server Layer)
├── Tool registration and HTTP/stdio handling
└── Calls ↓
internal/app/app.go (Application Layer)
├── Business logic and high-level operations
└── Calls ↓
internal/app/client.go (Data Layer)
└── Low-level PostgreSQL operations
5. Error Handling Strategy
No documentation on:
- When to return
mcp.NewToolResultError()vsmcp.NewToolResultText() - Error wrapping conventions
- How errors propagate through layers
- What error information is exposed to users
6. Testing Architecture
While CLAUDE.md mentions testing, it doesn't explain:
- Why testcontainers is used
- How mocks interact with the interface design
- The separation between unit and integration tests
- The
SKIP_INTEGRATION_TESTSpattern
Proposed Solution
Create docs/ARCHITECTURE.md:
# Architecture Documentation
## Overview
The PostgreSQL MCP server follows a **three-layer architecture**:
1. **MCP Server Layer** (`main.go`): Protocol handling and tool registration
2. **Application Layer** (`internal/app/app.go`): Business logic
3. **Data Layer** (`internal/app/client.go`): Database operations
## Design Patterns
### 1. Tool Registration Pattern
Each MCP tool is registered using a consistent pattern...
[Detailed explanation with code examples]
### 2. Interface-Based Design
The `PostgreSQLClient` interface abstracts database operations...
[Explain dependency injection, testing, flexibility]
### 3. Error Handling Strategy
Errors are handled differently at each layer...
[Explain error types, wrapping, user-facing messages]
### 4. Configuration Management
Connection parameters and settings...
[Explain environment variables, defaults, validation]
## Component Interaction
┌─────────────────┐
│ MCP Client │ (Claude Code)
└────────┬────────┘
│ stdio/http
┌────────▼────────┐
│ MCP Server │ (main.go)
│ Tool Registry │
└────────┬────────┘
│ Go function calls
┌────────▼────────┐
│ App Layer │ (app.go)
│ Business Logic │
└────────┬────────┘
│ Interface calls
┌────────▼────────┐
│ Client Layer │ (client.go)
│ PostgreSQL Ops │
└────────┬────────┘
│ lib/pq
┌────────▼────────┐
│ PostgreSQL DB │
└─────────────────┘
## Design Decisions
### Why Interface-Based?
The `PostgreSQLClient` interface exists to:
- Enable testing with mocks
- Allow future multi-database support
- Decouple business logic from database implementation
### Why Separate Tool Setup Functions?
Tools are set up in separate `setupXxxTool()` functions because:
- Reduces complexity in main()
- Makes it easy to add/remove tools
- Improves testability
- Follows single responsibility principle
### Why TableToolConfig?
The `TableToolConfig` pattern reduces duplication for similar tools...
## Testing Strategy
### Unit Tests
- Mock the `PostgreSQLClient` interface
- Test business logic in isolation
- Fast, no external dependencies
### Integration Tests
- Use testcontainers for real PostgreSQL
- Test end-to-end database operations
- Slow, requires Docker
[More details on testing patterns]
## Adding New Tools
To add a new MCP tool:
1. Define the tool in `main.go`:
```go
func setupNewToolTool(appInstance *app.App) *mcp.Tool {
// ...
}
- Add business logic to
app.go:
func (a *App) NewToolOperation() (ResultType, error) {
// ...
}- Implement database operations in
client.goif needed - Register in
registerAllTools() - Add tests
[Detailed example]
Security Model
[Explain read-only validation, identifier escaping, etc.]
Performance Considerations
[Explain connection pooling, query limits, etc.]
## Additional Documentation
Also create:
- `docs/CONTRIBUTING.md`: How to contribute, coding standards
- `docs/TESTING.md`: Detailed testing guide
- `docs/DEPLOYMENT.md`: How to deploy the MCP server
## Impact
- **Severity**: LOW
- **Type**: Documentation
- **Benefits**: Easier onboarding, better maintainability, clearer design
## Checklist
- [ ] Create docs/ARCHITECTURE.md with comprehensive design documentation
- [ ] Document the three-layer architecture pattern
- [ ] Explain tool registration pattern with examples
- [ ] Document interface hierarchy and relationships
- [ ] Explain TableToolConfig and when to use it
- [ ] Add component interaction diagrams
- [ ] Document design decisions and their rationale
- [ ] Add "Adding New Tools" guide with step-by-step instructions
- [ ] Document error handling strategy across layers
- [ ] Document testing architecture and patterns
- [ ] Link to architecture docs from main README
- [ ] Create CONTRIBUTING.md with coding standards