mirror of
https://github.com/samanhappy/mcphub.git
synced 2025-12-24 02:39:19 -05:00
generate documents using mintlify (#153)
This commit is contained in:
724
docs/development/architecture.mdx
Normal file
724
docs/development/architecture.mdx
Normal file
@@ -0,0 +1,724 @@
|
||||
---
|
||||
title: 'Architecture Overview'
|
||||
description: "Understand MCPHub's system architecture and design principles"
|
||||
---
|
||||
|
||||
## System Overview
|
||||
|
||||
MCPHub is designed as a scalable, modular platform for managing Model Context Protocol (MCP) servers. The architecture follows modern web application patterns with clear separation of concerns, microservices-ready design, and extensibility in mind.
|
||||
|
||||
## High-Level Architecture
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Client Layer"
|
||||
WEB[Web Dashboard]
|
||||
API[External APIs]
|
||||
CLI[CLI Tools]
|
||||
end
|
||||
|
||||
subgraph "Application Layer"
|
||||
LB[Load Balancer/Nginx]
|
||||
APP[MCPHub Server]
|
||||
WS[WebSocket Server]
|
||||
end
|
||||
|
||||
subgraph "Service Layer"
|
||||
MCP[MCP Service]
|
||||
AUTH[Auth Service]
|
||||
ROUTE[Smart Routing]
|
||||
MON[Monitoring Service]
|
||||
end
|
||||
|
||||
subgraph "Data Layer"
|
||||
PG[(PostgreSQL)]
|
||||
REDIS[(Redis)]
|
||||
VECTOR[(Vector Store)]
|
||||
end
|
||||
|
||||
subgraph "MCP Servers"
|
||||
GITHUB[GitHub MCP]
|
||||
FS[Filesystem MCP]
|
||||
DB[Database MCP]
|
||||
CUSTOM[Custom MCP]
|
||||
end
|
||||
|
||||
WEB --> LB
|
||||
API --> LB
|
||||
CLI --> LB
|
||||
LB --> APP
|
||||
APP --> WS
|
||||
APP --> MCP
|
||||
APP --> AUTH
|
||||
APP --> ROUTE
|
||||
APP --> MON
|
||||
|
||||
MCP --> GITHUB
|
||||
MCP --> FS
|
||||
MCP --> DB
|
||||
MCP --> CUSTOM
|
||||
|
||||
AUTH --> PG
|
||||
AUTH --> REDIS
|
||||
ROUTE --> VECTOR
|
||||
MON --> PG
|
||||
MON --> REDIS
|
||||
```
|
||||
|
||||
## Core Components
|
||||
|
||||
### 1. Application Server
|
||||
|
||||
The main Node.js/Express application that handles all HTTP requests and coordinates between services.
|
||||
|
||||
```typescript
|
||||
// src/server.ts - Main application entry point
|
||||
class MCPHubServer {
|
||||
private app: Express;
|
||||
private httpServer: Server;
|
||||
private wsServer: WebSocketServer;
|
||||
|
||||
async start(): Promise<void> {
|
||||
await this.initializeDatabase();
|
||||
await this.initializeServices();
|
||||
await this.setupRoutes();
|
||||
await this.startServer();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key Responsibilities:**
|
||||
|
||||
- HTTP request handling
|
||||
- WebSocket connections for real-time features
|
||||
- Service coordination
|
||||
- Middleware chain management
|
||||
- Error handling and logging
|
||||
|
||||
### 2. MCP Service Layer
|
||||
|
||||
Manages the lifecycle and communication with MCP servers.
|
||||
|
||||
```typescript
|
||||
// src/services/mcpService.ts
|
||||
class MCPService {
|
||||
private servers: Map<string, MCPServerInstance> = new Map();
|
||||
private processManager: ProcessManager;
|
||||
|
||||
async startServer(config: MCPServerConfig): Promise<void> {
|
||||
const instance = await this.processManager.spawn(config);
|
||||
this.servers.set(config.name, instance);
|
||||
await this.waitForHealthy(instance);
|
||||
}
|
||||
|
||||
async executeRequest(serverName: string, request: MCPRequest): Promise<MCPResponse> {
|
||||
const server = this.servers.get(serverName);
|
||||
return await server.sendRequest(request);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key Features:**
|
||||
|
||||
- Process lifecycle management
|
||||
- Health monitoring
|
||||
- Request routing
|
||||
- Error recovery
|
||||
- Resource management
|
||||
|
||||
### 3. Smart Routing Engine
|
||||
|
||||
Provides AI-powered tool discovery and routing using vector embeddings.
|
||||
|
||||
```typescript
|
||||
// src/services/smartRouting.ts
|
||||
class SmartRoutingService {
|
||||
private vectorStore: VectorStore;
|
||||
private embeddingService: EmbeddingService;
|
||||
|
||||
async findRelevantTools(query: string): Promise<ToolMatch[]> {
|
||||
const queryEmbedding = await this.embeddingService.embed(query);
|
||||
const matches = await this.vectorStore.similaritySearch(queryEmbedding);
|
||||
return this.rankResults(matches, query);
|
||||
}
|
||||
|
||||
async indexTool(tool: ToolDefinition): Promise<void> {
|
||||
const embedding = await this.embeddingService.embed(tool.description);
|
||||
await this.vectorStore.upsert(tool.id, embedding, tool);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Components:**
|
||||
|
||||
- Vector embedding generation
|
||||
- Similarity search
|
||||
- Result ranking and filtering
|
||||
- Tool metadata management
|
||||
|
||||
### 4. Authentication & Authorization
|
||||
|
||||
Handles user authentication, session management, and access control.
|
||||
|
||||
```typescript
|
||||
// src/services/authService.ts
|
||||
class AuthService {
|
||||
async authenticate(credentials: Credentials): Promise<User> {
|
||||
const user = await this.validateCredentials(credentials);
|
||||
const token = await this.generateJWT(user);
|
||||
await this.createSession(user, token);
|
||||
return user;
|
||||
}
|
||||
|
||||
async authorize(user: User, resource: string, action: string): Promise<boolean> {
|
||||
const permissions = await this.getUserPermissions(user);
|
||||
return this.checkPermission(permissions, resource, action);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Features:**
|
||||
|
||||
- JWT-based authentication
|
||||
- Role-based access control (RBAC)
|
||||
- Session management
|
||||
- API key authentication
|
||||
- Group-based permissions
|
||||
|
||||
### 5. Monitoring & Logging
|
||||
|
||||
Provides comprehensive monitoring, metrics collection, and logging.
|
||||
|
||||
```typescript
|
||||
// src/services/monitoringService.ts
|
||||
class MonitoringService {
|
||||
private metricsCollector: MetricsCollector;
|
||||
private alertManager: AlertManager;
|
||||
|
||||
async collectMetrics(): Promise<void> {
|
||||
const systemMetrics = await this.getSystemMetrics();
|
||||
const serverMetrics = await this.getMCPServerMetrics();
|
||||
await this.metricsCollector.record(systemMetrics, serverMetrics);
|
||||
await this.checkAlerts(systemMetrics, serverMetrics);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Capabilities:**
|
||||
|
||||
- Real-time metrics collection
|
||||
- Performance monitoring
|
||||
- Error tracking
|
||||
- Alert management
|
||||
- Audit logging
|
||||
|
||||
## Data Architecture
|
||||
|
||||
### Database Schema
|
||||
|
||||
```sql
|
||||
-- Core entities
|
||||
CREATE TABLE users (
|
||||
id UUID PRIMARY KEY,
|
||||
username VARCHAR UNIQUE NOT NULL,
|
||||
email VARCHAR UNIQUE NOT NULL,
|
||||
password_hash VARCHAR NOT NULL,
|
||||
role VARCHAR NOT NULL DEFAULT 'user',
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE TABLE servers (
|
||||
id UUID PRIMARY KEY,
|
||||
name VARCHAR UNIQUE NOT NULL,
|
||||
command VARCHAR NOT NULL,
|
||||
args JSONB NOT NULL DEFAULT '[]',
|
||||
env JSONB DEFAULT '{}',
|
||||
group_name VARCHAR,
|
||||
status VARCHAR DEFAULT 'stopped',
|
||||
config JSONB DEFAULT '{}',
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE TABLE groups (
|
||||
id UUID PRIMARY KEY,
|
||||
name VARCHAR UNIQUE NOT NULL,
|
||||
description TEXT,
|
||||
config JSONB DEFAULT '{}',
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Vector search for smart routing
|
||||
CREATE TABLE tool_embeddings (
|
||||
id UUID PRIMARY KEY,
|
||||
server_name VARCHAR NOT NULL,
|
||||
tool_name VARCHAR NOT NULL,
|
||||
description TEXT,
|
||||
embedding vector(1536),
|
||||
metadata JSONB DEFAULT '{}',
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Monitoring and logging
|
||||
CREATE TABLE request_logs (
|
||||
id UUID PRIMARY KEY,
|
||||
user_id UUID REFERENCES users(id),
|
||||
server_name VARCHAR NOT NULL,
|
||||
tool_name VARCHAR,
|
||||
request_data JSONB,
|
||||
response_data JSONB,
|
||||
status VARCHAR NOT NULL,
|
||||
duration_ms INTEGER,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
### Caching Strategy
|
||||
|
||||
```typescript
|
||||
// src/services/cacheService.ts
|
||||
class CacheService {
|
||||
// Multi-layer caching strategy
|
||||
private memoryCache: Map<string, CacheEntry> = new Map();
|
||||
private redisCache: Redis;
|
||||
|
||||
async get<T>(key: string): Promise<T | null> {
|
||||
// L1: Memory cache
|
||||
const memoryEntry = this.memoryCache.get(key);
|
||||
if (memoryEntry && !this.isExpired(memoryEntry)) {
|
||||
return memoryEntry.value;
|
||||
}
|
||||
|
||||
// L2: Redis cache
|
||||
const redisValue = await this.redisCache.get(key);
|
||||
if (redisValue) {
|
||||
const value = JSON.parse(redisValue);
|
||||
this.memoryCache.set(key, { value, expiry: Date.now() + 60000 });
|
||||
return value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Cache Layers:**
|
||||
|
||||
- **L1 (Memory)**: Fast access for frequently used data
|
||||
- **L2 (Redis)**: Shared cache across instances
|
||||
- **L3 (Database)**: Persistent storage with query optimization
|
||||
|
||||
## Communication Patterns
|
||||
|
||||
### Request Flow
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client
|
||||
participant API
|
||||
participant Auth
|
||||
participant Router
|
||||
participant MCP
|
||||
participant Server
|
||||
|
||||
Client->>API: HTTP Request
|
||||
API->>Auth: Validate Token
|
||||
Auth-->>API: User Context
|
||||
API->>Router: Route Request
|
||||
Router->>Router: Find Target Server
|
||||
Router->>MCP: Execute Request
|
||||
MCP->>Server: MCP Protocol
|
||||
Server-->>MCP: MCP Response
|
||||
MCP-->>Router: Formatted Response
|
||||
Router-->>API: Response Data
|
||||
API-->>Client: HTTP Response
|
||||
```
|
||||
|
||||
### WebSocket Communication
|
||||
|
||||
```typescript
|
||||
// src/services/websocketService.ts
|
||||
class WebSocketService {
|
||||
private connections: Map<string, WebSocket> = new Map();
|
||||
|
||||
handleConnection(ws: WebSocket, userId: string): void {
|
||||
this.connections.set(userId, ws);
|
||||
|
||||
ws.on('message', async (data) => {
|
||||
const message = JSON.parse(data.toString());
|
||||
await this.handleMessage(userId, message);
|
||||
});
|
||||
|
||||
ws.on('close', () => {
|
||||
this.connections.delete(userId);
|
||||
});
|
||||
}
|
||||
|
||||
broadcast(event: string, data: any): void {
|
||||
this.connections.forEach((ws) => {
|
||||
ws.send(JSON.stringify({ event, data }));
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Event-Driven Architecture
|
||||
|
||||
```typescript
|
||||
// src/events/eventBus.ts
|
||||
class EventBus {
|
||||
private listeners: Map<string, EventListener[]> = new Map();
|
||||
|
||||
emit(event: string, data: any): void {
|
||||
const handlers = this.listeners.get(event) || [];
|
||||
handlers.forEach((handler) => handler(data));
|
||||
}
|
||||
|
||||
on(event: string, handler: EventListener): void {
|
||||
const handlers = this.listeners.get(event) || [];
|
||||
handlers.push(handler);
|
||||
this.listeners.set(event, handlers);
|
||||
}
|
||||
}
|
||||
|
||||
// Usage
|
||||
eventBus.on('server.started', (data) => {
|
||||
logger.info(`Server ${data.name} started`);
|
||||
monitoringService.updateServerStatus(data.name, 'running');
|
||||
});
|
||||
```
|
||||
|
||||
## Security Architecture
|
||||
|
||||
### Authentication Flow
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[Client] --> B[Login Request]
|
||||
B --> C[Validate Credentials]
|
||||
C --> D[Generate JWT]
|
||||
D --> E[Create Session]
|
||||
E --> F[Return Token]
|
||||
F --> G[Store in Cookie/Header]
|
||||
G --> H[Subsequent Requests]
|
||||
H --> I[Validate Token]
|
||||
I --> J[Check Permissions]
|
||||
J --> K[Allow/Deny Access]
|
||||
```
|
||||
|
||||
### Authorization Model
|
||||
|
||||
```typescript
|
||||
// Role-Based Access Control (RBAC)
|
||||
interface Permission {
|
||||
resource: string; // e.g., 'servers', 'groups', 'users'
|
||||
action: string; // e.g., 'create', 'read', 'update', 'delete'
|
||||
scope?: string; // e.g., 'own', 'group', 'all'
|
||||
}
|
||||
|
||||
interface Role {
|
||||
name: string;
|
||||
permissions: Permission[];
|
||||
}
|
||||
|
||||
const roles: Role[] = [
|
||||
{
|
||||
name: 'admin',
|
||||
permissions: [{ resource: '*', action: '*', scope: 'all' }],
|
||||
},
|
||||
{
|
||||
name: 'manager',
|
||||
permissions: [
|
||||
{ resource: 'servers', action: '*', scope: 'group' },
|
||||
{ resource: 'groups', action: 'read', scope: 'all' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'user',
|
||||
permissions: [
|
||||
{ resource: 'servers', action: 'read', scope: 'group' },
|
||||
{ resource: 'tools', action: 'execute', scope: 'group' },
|
||||
],
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
## Scalability Considerations
|
||||
|
||||
### Horizontal Scaling
|
||||
|
||||
```yaml
|
||||
# Kubernetes deployment for scaling
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mcphub
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: mcphub
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: mcphub
|
||||
image: mcphub:latest
|
||||
resources:
|
||||
requests:
|
||||
memory: '256Mi'
|
||||
cpu: '200m'
|
||||
limits:
|
||||
memory: '512Mi'
|
||||
cpu: '500m'
|
||||
```
|
||||
|
||||
### Load Balancing Strategy
|
||||
|
||||
```typescript
|
||||
// src/services/loadBalancer.ts
|
||||
class LoadBalancer {
|
||||
private servers: ServerInstance[] = [];
|
||||
private algorithm: 'round-robin' | 'least-connections' | 'weighted';
|
||||
|
||||
selectServer(): ServerInstance {
|
||||
switch (this.algorithm) {
|
||||
case 'round-robin':
|
||||
return this.roundRobin();
|
||||
case 'least-connections':
|
||||
return this.leastConnections();
|
||||
case 'weighted':
|
||||
return this.weighted();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Database Scaling
|
||||
|
||||
```typescript
|
||||
// Database connection management
|
||||
class DatabaseManager {
|
||||
private readPool: Pool; // Read replicas
|
||||
private writePool: Pool; // Primary database
|
||||
|
||||
async query(sql: string, params: any[]): Promise<any> {
|
||||
if (this.isReadOperation(sql)) {
|
||||
return this.readPool.query(sql, params);
|
||||
} else {
|
||||
return this.writePool.query(sql, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Query Optimization
|
||||
|
||||
```sql
|
||||
-- Optimized queries with proper indexing
|
||||
CREATE INDEX CONCURRENTLY idx_servers_status_group
|
||||
ON servers(status, group_name)
|
||||
WHERE status IN ('running', 'starting');
|
||||
|
||||
CREATE INDEX CONCURRENTLY idx_tool_embeddings_similarity
|
||||
ON tool_embeddings USING ivfflat (embedding vector_cosine_ops)
|
||||
WITH (lists = 100);
|
||||
|
||||
CREATE INDEX CONCURRENTLY idx_request_logs_performance
|
||||
ON request_logs(created_at, status, duration_ms)
|
||||
WHERE created_at > NOW() - INTERVAL '30 days';
|
||||
```
|
||||
|
||||
### Caching Strategy
|
||||
|
||||
```typescript
|
||||
// Multi-level caching
|
||||
class CacheManager {
|
||||
// Cache server configurations
|
||||
@Cache({ ttl: 300, key: 'server-config' })
|
||||
async getServerConfig(name: string): Promise<ServerConfig> {
|
||||
return this.database.getServerConfig(name);
|
||||
}
|
||||
|
||||
// Cache tool metadata for smart routing
|
||||
@Cache({ ttl: 3600, key: 'tool-metadata' })
|
||||
async getToolMetadata(): Promise<ToolMetadata[]> {
|
||||
return this.database.getToolMetadata();
|
||||
}
|
||||
|
||||
// Cache user permissions
|
||||
@Cache({ ttl: 600, key: 'user-permissions' })
|
||||
async getUserPermissions(userId: string): Promise<Permission[]> {
|
||||
return this.authService.getUserPermissions(userId);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Monitoring & Observability
|
||||
|
||||
### Metrics Collection
|
||||
|
||||
```typescript
|
||||
// src/services/metricsService.ts
|
||||
class MetricsService {
|
||||
private prometheus: PrometheusRegistry;
|
||||
|
||||
constructor() {
|
||||
this.initializeMetrics();
|
||||
}
|
||||
|
||||
private initializeMetrics(): void {
|
||||
// Request metrics
|
||||
this.requestCount = new Counter({
|
||||
name: 'mcphub_requests_total',
|
||||
help: 'Total number of requests',
|
||||
labelNames: ['method', 'route', 'status'],
|
||||
});
|
||||
|
||||
// Server metrics
|
||||
this.serverStatus = new Gauge({
|
||||
name: 'mcphub_server_status',
|
||||
help: 'Status of MCP servers',
|
||||
labelNames: ['server_name', 'status'],
|
||||
});
|
||||
|
||||
// Performance metrics
|
||||
this.responseTime = new Histogram({
|
||||
name: 'mcphub_response_time_seconds',
|
||||
help: 'Response time in seconds',
|
||||
labelNames: ['route'],
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Distributed Tracing
|
||||
|
||||
```typescript
|
||||
// OpenTelemetry integration
|
||||
import { trace } from '@opentelemetry/api';
|
||||
|
||||
class MCPService {
|
||||
async executeRequest(serverName: string, request: MCPRequest): Promise<MCPResponse> {
|
||||
const span = trace.getActiveSpan();
|
||||
span?.setAttributes({
|
||||
'mcp.server': serverName,
|
||||
'mcp.tool': request.tool,
|
||||
'mcp.request_id': request.id,
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await this.sendRequest(serverName, request);
|
||||
span?.setStatus({ code: SpanStatusCode.OK });
|
||||
return response;
|
||||
} catch (error) {
|
||||
span?.setStatus({
|
||||
code: SpanStatusCode.ERROR,
|
||||
message: error.message,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Extension Points
|
||||
|
||||
### Plugin Architecture
|
||||
|
||||
```typescript
|
||||
// Plugin interface
|
||||
interface MCPHubPlugin {
|
||||
name: string;
|
||||
version: string;
|
||||
init(context: PluginContext): Promise<void>;
|
||||
destroy(): Promise<void>;
|
||||
}
|
||||
|
||||
// Plugin manager
|
||||
class PluginManager {
|
||||
private plugins: Map<string, MCPHubPlugin> = new Map();
|
||||
|
||||
async loadPlugin(plugin: MCPHubPlugin): Promise<void> {
|
||||
await plugin.init(this.createContext());
|
||||
this.plugins.set(plugin.name, plugin);
|
||||
}
|
||||
|
||||
private createContext(): PluginContext {
|
||||
return {
|
||||
eventBus: this.eventBus,
|
||||
logger: this.logger,
|
||||
database: this.database,
|
||||
// ... other services
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Custom Middleware
|
||||
|
||||
```typescript
|
||||
// Custom middleware registration
|
||||
class MiddlewareManager {
|
||||
register(middleware: Middleware): void {
|
||||
this.app.use(middleware);
|
||||
}
|
||||
|
||||
registerRoute(path: string, middleware: Middleware): void {
|
||||
this.app.use(path, middleware);
|
||||
}
|
||||
}
|
||||
|
||||
// Example custom middleware
|
||||
const customAuthMiddleware: Middleware = (req, res, next) => {
|
||||
// Custom authentication logic
|
||||
next();
|
||||
};
|
||||
```
|
||||
|
||||
## Deployment Architecture
|
||||
|
||||
### Container Strategy
|
||||
|
||||
```dockerfile
|
||||
# Multi-stage build for optimized images
|
||||
FROM node:18-alpine AS builder
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm ci --only=production
|
||||
|
||||
FROM node:18-alpine AS runtime
|
||||
RUN addgroup -g 1001 -S nodejs
|
||||
RUN adduser -S mcphub -u 1001
|
||||
WORKDIR /app
|
||||
COPY --from=builder --chown=mcphub:nodejs /app .
|
||||
USER mcphub
|
||||
EXPOSE 3000
|
||||
CMD ["node", "dist/server.js"]
|
||||
```
|
||||
|
||||
### Infrastructure as Code
|
||||
|
||||
```terraform
|
||||
# Terraform configuration for AWS deployment
|
||||
resource "aws_ecs_cluster" "mcphub" {
|
||||
name = "mcphub-cluster"
|
||||
}
|
||||
|
||||
resource "aws_ecs_service" "mcphub" {
|
||||
name = "mcphub"
|
||||
cluster = aws_ecs_cluster.mcphub.id
|
||||
task_definition = aws_ecs_task_definition.mcphub.arn
|
||||
desired_count = 3
|
||||
|
||||
load_balancer {
|
||||
target_group_arn = aws_lb_target_group.mcphub.arn
|
||||
container_name = "mcphub"
|
||||
container_port = 3000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This architecture provides a solid foundation for building a scalable, maintainable, and extensible MCP server management platform while following modern software development best practices.
|
||||
597
docs/development/contributing.mdx
Normal file
597
docs/development/contributing.mdx
Normal file
@@ -0,0 +1,597 @@
|
||||
---
|
||||
title: 'Contributing to MCPHub'
|
||||
description: 'Learn how to contribute to the MCPHub project'
|
||||
---
|
||||
|
||||
## Welcome Contributors! 🎉
|
||||
|
||||
Thank you for your interest in contributing to MCPHub! This guide will help you get started with contributing to the project, whether you're fixing bugs, adding features, improving documentation, or helping with testing.
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. **Fork the repository** on GitHub
|
||||
2. **Clone your fork** locally
|
||||
3. **Create a branch** for your changes
|
||||
4. **Make your changes** following our guidelines
|
||||
5. **Test your changes** thoroughly
|
||||
6. **Submit a pull request**
|
||||
|
||||
## Ways to Contribute
|
||||
|
||||
### 🐛 Bug Reports
|
||||
|
||||
Help us improve MCPHub by reporting bugs:
|
||||
|
||||
- **Search existing issues** first to avoid duplicates
|
||||
- **Use the bug report template** when creating issues
|
||||
- **Provide detailed information** including steps to reproduce
|
||||
- **Include system information** (OS, Node.js version, etc.)
|
||||
|
||||
```markdown
|
||||
## Bug Report Template
|
||||
|
||||
**Description**
|
||||
A clear description of what the bug is.
|
||||
|
||||
**Steps to Reproduce**
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected Behavior**
|
||||
What you expected to happen.
|
||||
|
||||
**Actual Behavior**
|
||||
What actually happened.
|
||||
|
||||
**Environment**
|
||||
|
||||
- OS: [e.g. macOS 12.0]
|
||||
- Node.js: [e.g. 18.17.0]
|
||||
- MCPHub Version: [e.g. 1.2.3]
|
||||
- Browser: [e.g. Chrome 91.0]
|
||||
|
||||
**Additional Context**
|
||||
Any other context about the problem.
|
||||
```
|
||||
|
||||
### ✨ Feature Requests
|
||||
|
||||
We welcome feature suggestions:
|
||||
|
||||
- **Check existing feature requests** to avoid duplicates
|
||||
- **Use the feature request template**
|
||||
- **Explain the use case** and why it would be valuable
|
||||
- **Consider implementation complexity**
|
||||
|
||||
### 🔧 Code Contributions
|
||||
|
||||
Ready to write some code? Here's how:
|
||||
|
||||
#### Setting Up Development Environment
|
||||
|
||||
```bash
|
||||
# 1. Fork and clone the repository
|
||||
git clone https://github.com/YOUR_USERNAME/mcphub.git
|
||||
cd mcphub
|
||||
|
||||
# 2. Add upstream remote
|
||||
git remote add upstream https://github.com/mcphub/mcphub.git
|
||||
|
||||
# 3. Install dependencies
|
||||
pnpm install
|
||||
|
||||
# 4. Set up environment
|
||||
cp .env.example .env.development
|
||||
|
||||
# 5. Start development environment
|
||||
docker-compose -f docker-compose.dev.yml up -d
|
||||
pnpm run migrate
|
||||
pnpm run seed
|
||||
|
||||
# 6. Start development server
|
||||
pnpm run dev
|
||||
```
|
||||
|
||||
#### Branch Naming Convention
|
||||
|
||||
Use descriptive branch names with prefixes:
|
||||
|
||||
```bash
|
||||
# Features
|
||||
git checkout -b feature/smart-routing-improvements
|
||||
git checkout -b feature/user-authentication
|
||||
|
||||
# Bug fixes
|
||||
git checkout -b fix/server-startup-error
|
||||
git checkout -b fix/memory-leak-in-cache
|
||||
|
||||
# Documentation
|
||||
git checkout -b docs/api-reference-update
|
||||
git checkout -b docs/deployment-guide
|
||||
|
||||
# Refactoring
|
||||
git checkout -b refactor/auth-service-cleanup
|
||||
git checkout -b refactor/database-queries
|
||||
```
|
||||
|
||||
### 📚 Documentation
|
||||
|
||||
Help improve our documentation:
|
||||
|
||||
- **Fix typos and grammar**
|
||||
- **Improve existing guides**
|
||||
- **Add missing documentation**
|
||||
- **Create tutorials and examples**
|
||||
- **Translate documentation**
|
||||
|
||||
## Development Guidelines
|
||||
|
||||
### Code Style
|
||||
|
||||
We use ESLint and Prettier to maintain code quality:
|
||||
|
||||
```bash
|
||||
# Check code style
|
||||
pnpm run lint
|
||||
|
||||
# Fix automatically fixable issues
|
||||
pnpm run lint:fix
|
||||
|
||||
# Format code
|
||||
pnpm run format
|
||||
|
||||
# Type check
|
||||
pnpm run type-check
|
||||
```
|
||||
|
||||
#### TypeScript Best Practices
|
||||
|
||||
```typescript
|
||||
// ✅ Good: Use proper types
|
||||
interface MCPServerConfig {
|
||||
name: string;
|
||||
command: string;
|
||||
args: string[];
|
||||
env?: Record<string, string>;
|
||||
}
|
||||
|
||||
// ✅ Good: Use async/await
|
||||
async function startServer(config: MCPServerConfig): Promise<void> {
|
||||
try {
|
||||
await mcpService.start(config);
|
||||
} catch (error) {
|
||||
logger.error('Failed to start server', { error, config });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// ❌ Bad: Using any type
|
||||
function processData(data: any): any {
|
||||
return data.something();
|
||||
}
|
||||
|
||||
// ❌ Bad: Not handling errors
|
||||
async function riskyOperation(): Promise<void> {
|
||||
await dangerousFunction(); // Could throw
|
||||
}
|
||||
```
|
||||
|
||||
#### React/Frontend Guidelines
|
||||
|
||||
```tsx
|
||||
// ✅ Good: Functional components with proper typing
|
||||
interface ServerCardProps {
|
||||
server: MCPServer;
|
||||
onStart: (serverId: string) => void;
|
||||
onStop: (serverId: string) => void;
|
||||
}
|
||||
|
||||
const ServerCard: React.FC<ServerCardProps> = ({ server, onStart, onStop }) => {
|
||||
const handleStart = useCallback(() => {
|
||||
onStart(server.id);
|
||||
}, [server.id, onStart]);
|
||||
|
||||
return (
|
||||
<Card data-testid={`server-card-${server.id}`}>
|
||||
<CardHeader>
|
||||
<CardTitle>{server.name}</CardTitle>
|
||||
<Badge variant={server.status === 'running' ? 'success' : 'secondary'}>
|
||||
{server.status}
|
||||
</Badge>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p>{server.description}</p>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
{server.status === 'stopped' ? (
|
||||
<Button onClick={handleStart}>Start</Button>
|
||||
) : (
|
||||
<Button onClick={() => onStop(server.id)}>Stop</Button>
|
||||
)}
|
||||
</CardActions>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Testing Requirements
|
||||
|
||||
All contributions must include appropriate tests:
|
||||
|
||||
#### Unit Tests
|
||||
|
||||
```typescript
|
||||
// src/services/__tests__/mcpService.test.ts
|
||||
import { MCPService } from '../mcpService';
|
||||
import { mockLogger, mockDatabase } from '../../__mocks__';
|
||||
|
||||
describe('MCPService', () => {
|
||||
let service: MCPService;
|
||||
|
||||
beforeEach(() => {
|
||||
service = new MCPService(mockLogger, mockDatabase);
|
||||
});
|
||||
|
||||
describe('startServer', () => {
|
||||
it('should start a server successfully', async () => {
|
||||
const config = {
|
||||
name: 'test-server',
|
||||
command: 'node',
|
||||
args: ['server.js'],
|
||||
};
|
||||
|
||||
await service.startServer(config);
|
||||
|
||||
expect(service.getServerStatus('test-server')).toBe('running');
|
||||
});
|
||||
|
||||
it('should handle server startup failures', async () => {
|
||||
const invalidConfig = {
|
||||
name: 'invalid-server',
|
||||
command: 'invalid-command',
|
||||
args: [],
|
||||
};
|
||||
|
||||
await expect(service.startServer(invalidConfig)).rejects.toThrow(
|
||||
'Failed to start server: Command not found',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
#### Integration Tests
|
||||
|
||||
```typescript
|
||||
// src/__tests__/integration/server-api.test.ts
|
||||
import request from 'supertest';
|
||||
import { app } from '../../app';
|
||||
import { setupTestDatabase, teardownTestDatabase } from '../helpers/database';
|
||||
|
||||
describe('Server API Integration', () => {
|
||||
beforeAll(async () => {
|
||||
await setupTestDatabase();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await teardownTestDatabase();
|
||||
});
|
||||
|
||||
describe('POST /api/servers', () => {
|
||||
it('should create a new server', async () => {
|
||||
const serverData = {
|
||||
name: 'test-server',
|
||||
command: 'node',
|
||||
args: ['server.js'],
|
||||
group: 'development',
|
||||
};
|
||||
|
||||
const response = await request(app).post('/api/servers').send(serverData).expect(201);
|
||||
|
||||
expect(response.body).toMatchObject({
|
||||
name: 'test-server',
|
||||
status: 'stopped',
|
||||
group: 'development',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
#### End-to-End Tests
|
||||
|
||||
```typescript
|
||||
// tests/e2e/server-management.spec.ts
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('Server Management', () => {
|
||||
test('should create and manage MCP servers', async ({ page }) => {
|
||||
await page.goto('/dashboard');
|
||||
|
||||
// Create new server
|
||||
await page.click('[data-testid="add-server-button"]');
|
||||
await page.fill('[data-testid="server-name-input"]', 'test-server');
|
||||
await page.fill('[data-testid="server-command-input"]', 'node server.js');
|
||||
await page.click('[data-testid="save-server-button"]');
|
||||
|
||||
// Verify server appears in list
|
||||
await expect(page.locator('[data-testid="server-list"]')).toContainText('test-server');
|
||||
|
||||
// Start the server
|
||||
await page.click('[data-testid="start-server-test-server"]');
|
||||
|
||||
// Verify server is running
|
||||
await expect(page.locator('[data-testid="server-status-test-server"]')).toContainText(
|
||||
'running',
|
||||
);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Commit Guidelines
|
||||
|
||||
We follow [Conventional Commits](https://www.conventionalcommits.org/):
|
||||
|
||||
```bash
|
||||
# Format: <type>[optional scope]: <description>
|
||||
|
||||
# Features
|
||||
git commit -m "feat(auth): add JWT token refresh functionality"
|
||||
git commit -m "feat(ui): implement server status dashboard"
|
||||
|
||||
# Bug fixes
|
||||
git commit -m "fix(api): resolve memory leak in server manager"
|
||||
git commit -m "fix(db): handle connection timeout gracefully"
|
||||
|
||||
# Documentation
|
||||
git commit -m "docs(api): add examples for server endpoints"
|
||||
git commit -m "docs(readme): update installation instructions"
|
||||
|
||||
# Refactoring
|
||||
git commit -m "refactor(services): extract auth logic into separate module"
|
||||
|
||||
# Tests
|
||||
git commit -m "test(api): add integration tests for server management"
|
||||
|
||||
# Chores
|
||||
git commit -m "chore(deps): update dependencies to latest versions"
|
||||
```
|
||||
|
||||
#### Commit Types
|
||||
|
||||
- **feat**: New feature
|
||||
- **fix**: Bug fix
|
||||
- **docs**: Documentation changes
|
||||
- **style**: Code style changes (formatting, etc.)
|
||||
- **refactor**: Code refactoring
|
||||
- **test**: Adding or updating tests
|
||||
- **chore**: Maintenance tasks
|
||||
- **perf**: Performance improvements
|
||||
- **ci**: CI/CD changes
|
||||
|
||||
### Pull Request Process
|
||||
|
||||
#### Before Submitting
|
||||
|
||||
```bash
|
||||
# 1. Sync with upstream
|
||||
git fetch upstream
|
||||
git checkout main
|
||||
git merge upstream/main
|
||||
|
||||
# 2. Rebase your feature branch
|
||||
git checkout feature/your-feature
|
||||
git rebase main
|
||||
|
||||
# 3. Run all checks
|
||||
pnpm run lint
|
||||
pnpm run type-check
|
||||
pnpm run test
|
||||
pnpm run build
|
||||
|
||||
# 4. Update documentation if needed
|
||||
# 5. Add/update tests for your changes
|
||||
```
|
||||
|
||||
#### Pull Request Template
|
||||
|
||||
```markdown
|
||||
## Description
|
||||
|
||||
Brief description of the changes and motivation.
|
||||
|
||||
## Type of Change
|
||||
|
||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
- [ ] Documentation update
|
||||
|
||||
## Testing
|
||||
|
||||
- [ ] Unit tests pass
|
||||
- [ ] Integration tests pass
|
||||
- [ ] E2E tests pass (if applicable)
|
||||
- [ ] Manual testing completed
|
||||
|
||||
## Documentation
|
||||
|
||||
- [ ] Code is self-documenting
|
||||
- [ ] API documentation updated
|
||||
- [ ] User documentation updated
|
||||
- [ ] README updated (if needed)
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] My code follows the project's style guidelines
|
||||
- [ ] I have performed a self-review of my code
|
||||
- [ ] I have commented my code, particularly in hard-to-understand areas
|
||||
- [ ] I have made corresponding changes to the documentation
|
||||
- [ ] My changes generate no new warnings
|
||||
- [ ] I have added tests that prove my fix is effective or that my feature works
|
||||
- [ ] New and existing unit tests pass locally with my changes
|
||||
|
||||
## Screenshots (if applicable)
|
||||
|
||||
Add screenshots to help explain your changes.
|
||||
|
||||
## Additional Notes
|
||||
|
||||
Any additional information that reviewers should know.
|
||||
```
|
||||
|
||||
### Code Review Process
|
||||
|
||||
#### For Contributors
|
||||
|
||||
- **Be patient**: Reviews take time, and reviewers may have questions
|
||||
- **Be responsive**: Address feedback promptly and clearly
|
||||
- **Be open**: Accept constructive criticism and suggestions
|
||||
- **Ask questions**: If feedback is unclear, ask for clarification
|
||||
|
||||
#### For Reviewers
|
||||
|
||||
- **Be constructive**: Provide helpful suggestions, not just criticism
|
||||
- **Be specific**: Point out exact issues and suggest solutions
|
||||
- **Be timely**: Review PRs within a reasonable timeframe
|
||||
- **Be encouraging**: Recognize good work and improvements
|
||||
|
||||
## Community Guidelines
|
||||
|
||||
### Code of Conduct
|
||||
|
||||
We are committed to providing a welcoming and inspiring community for all:
|
||||
|
||||
- **Be respectful**: Treat everyone with respect and kindness
|
||||
- **Be inclusive**: Welcome people of all backgrounds and skill levels
|
||||
- **Be collaborative**: Work together towards common goals
|
||||
- **Be patient**: Help others learn and grow
|
||||
- **Be professional**: Maintain professional communication
|
||||
|
||||
### Communication Channels
|
||||
|
||||
- **GitHub Issues**: Bug reports and feature requests
|
||||
- **GitHub Discussions**: General questions and community chat
|
||||
- **Discord**: Real-time community chat (link in README)
|
||||
- **Email**: Security issues and private matters
|
||||
|
||||
## Getting Help
|
||||
|
||||
### Documentation
|
||||
|
||||
- [Getting Started Guide](./getting-started.mdx)
|
||||
- [Architecture Overview](./architecture.mdx)
|
||||
- [API Reference](../api-reference/introduction.mdx)
|
||||
- [Configuration Guide](../configuration/mcp-settings.mdx)
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Build Failures**
|
||||
|
||||
```bash
|
||||
# Clear and reinstall dependencies
|
||||
rm -rf node_modules pnpm-lock.yaml
|
||||
pnpm install
|
||||
|
||||
# Clear build cache
|
||||
rm -rf dist/
|
||||
pnpm run build
|
||||
```
|
||||
|
||||
**Test Failures**
|
||||
|
||||
```bash
|
||||
# Run tests with verbose output
|
||||
pnpm run test -- --verbose
|
||||
|
||||
# Run specific test file
|
||||
pnpm test src/services/mcpService.test.ts
|
||||
|
||||
# Debug tests
|
||||
pnpm run test:debug
|
||||
```
|
||||
|
||||
**Database Issues**
|
||||
|
||||
```bash
|
||||
# Reset database
|
||||
pnpm run db:reset
|
||||
|
||||
# Run migrations
|
||||
pnpm run migrate
|
||||
|
||||
# Seed development data
|
||||
pnpm run seed
|
||||
```
|
||||
|
||||
### Getting Support
|
||||
|
||||
If you need help:
|
||||
|
||||
1. **Check the documentation** first
|
||||
2. **Search existing issues** on GitHub
|
||||
3. **Ask in GitHub Discussions** for general questions
|
||||
4. **Create an issue** if you found a bug
|
||||
5. **Join our Discord** for real-time help
|
||||
|
||||
## Recognition
|
||||
|
||||
Contributors will be recognized in several ways:
|
||||
|
||||
- **Contributors file**: All contributors are listed in CONTRIBUTORS.md
|
||||
- **Release notes**: Significant contributions are mentioned in release notes
|
||||
- **GitHub badges**: Active contributors receive special recognition
|
||||
- **Community showcase**: Outstanding contributions are featured in our blog
|
||||
|
||||
## Advanced Topics
|
||||
|
||||
### Maintainer Guidelines
|
||||
|
||||
For project maintainers:
|
||||
|
||||
#### Release Process
|
||||
|
||||
```bash
|
||||
# 1. Create release branch
|
||||
git checkout -b release/v1.2.0
|
||||
|
||||
# 2. Update version
|
||||
npm version 1.2.0 --no-git-tag-version
|
||||
|
||||
# 3. Update changelog
|
||||
# Edit CHANGELOG.md
|
||||
|
||||
# 4. Commit changes
|
||||
git add .
|
||||
git commit -m "chore(release): prepare v1.2.0"
|
||||
|
||||
# 5. Create PR for review
|
||||
# 6. After merge, tag release
|
||||
git tag v1.2.0
|
||||
git push origin v1.2.0
|
||||
```
|
||||
|
||||
#### Security Handling
|
||||
|
||||
For security issues:
|
||||
|
||||
1. **Do not** create public issues
|
||||
2. **Email** security@mcphub.dev
|
||||
3. **Wait** for response before disclosure
|
||||
4. **Coordinate** with maintainers on fixes
|
||||
|
||||
### Architectural Decisions
|
||||
|
||||
When making significant changes:
|
||||
|
||||
1. **Create an RFC** (Request for Comments) issue
|
||||
2. **Discuss** with the community
|
||||
3. **Get approval** from maintainers
|
||||
4. **Document** decisions in ADR (Architecture Decision Records)
|
||||
|
||||
## Thank You! 🙏
|
||||
|
||||
Thank you for taking the time to contribute to MCPHub! Every contribution, no matter how small, helps make the project better for everyone. We look forward to collaborating with you!
|
||||
244
docs/development/getting-started.mdx
Normal file
244
docs/development/getting-started.mdx
Normal file
@@ -0,0 +1,244 @@
|
||||
---
|
||||
title: 'Getting Started with Development'
|
||||
description: 'Learn how to set up your development environment for MCPHub'
|
||||
---
|
||||
|
||||
# Getting Started with Development
|
||||
|
||||
This guide will help you set up your development environment for contributing to MCPHub.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, ensure you have the following installed:
|
||||
|
||||
- **Node.js** (version 18 or higher)
|
||||
- **pnpm** (recommended package manager)
|
||||
- **Git**
|
||||
- **Docker** (optional, for containerized development)
|
||||
|
||||
## Setting Up the Development Environment
|
||||
|
||||
### 1. Clone the Repository
|
||||
|
||||
```bash
|
||||
git clone https://github.com/your-username/mcphub.git
|
||||
cd mcphub
|
||||
```
|
||||
|
||||
### 2. Install Dependencies
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
```
|
||||
|
||||
### 3. Environment Configuration
|
||||
|
||||
Create a `.env` file in the root directory:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Configure the following environment variables:
|
||||
|
||||
```env
|
||||
# Server Configuration
|
||||
PORT=3000
|
||||
NODE_ENV=development
|
||||
|
||||
# Database Configuration
|
||||
DATABASE_URL=postgresql://username:password@localhost:5432/mcphub
|
||||
|
||||
# JWT Configuration
|
||||
JWT_SECRET=your-secret-key
|
||||
JWT_EXPIRES_IN=24h
|
||||
|
||||
# OpenAI Configuration (for smart routing)
|
||||
OPENAI_API_KEY=your-openai-api-key
|
||||
```
|
||||
|
||||
### 4. Database Setup
|
||||
|
||||
If using PostgreSQL, create a database:
|
||||
|
||||
```bash
|
||||
createdb mcphub
|
||||
```
|
||||
|
||||
### 5. MCP Server Configuration
|
||||
|
||||
Create or modify `mcp_settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"fetch": {
|
||||
"command": "uvx",
|
||||
"args": ["mcp-server-fetch"]
|
||||
},
|
||||
"playwright": {
|
||||
"command": "npx",
|
||||
"args": ["@playwright/mcp@latest", "--headless"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### Running the Development Server
|
||||
|
||||
Start both backend and frontend in development mode:
|
||||
|
||||
```bash
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
This will start:
|
||||
|
||||
- Backend server on `http://localhost:3000`
|
||||
- Frontend development server on `http://localhost:5173`
|
||||
|
||||
### Running Backend Only
|
||||
|
||||
```bash
|
||||
pnpm backend:dev
|
||||
```
|
||||
|
||||
### Running Frontend Only
|
||||
|
||||
```bash
|
||||
pnpm frontend:dev
|
||||
```
|
||||
|
||||
### Building the Project
|
||||
|
||||
Build both backend and frontend:
|
||||
|
||||
```bash
|
||||
pnpm build
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
mcphub/
|
||||
├── src/ # Backend source code
|
||||
│ ├── controllers/ # Express controllers
|
||||
│ ├── routes/ # API routes
|
||||
│ ├── services/ # Business logic
|
||||
│ ├── models/ # Database models
|
||||
│ └── utils/ # Utility functions
|
||||
├── frontend/ # Frontend React application
|
||||
│ ├── src/
|
||||
│ │ ├── components/ # React components
|
||||
│ │ ├── pages/ # Page components
|
||||
│ │ ├── services/ # API services
|
||||
│ │ └── utils/ # Frontend utilities
|
||||
├── docs/ # Documentation
|
||||
├── bin/ # CLI scripts
|
||||
└── scripts/ # Build and utility scripts
|
||||
```
|
||||
|
||||
## Development Tools
|
||||
|
||||
### Linting and Formatting
|
||||
|
||||
```bash
|
||||
# Run ESLint
|
||||
pnpm lint
|
||||
|
||||
# Format code with Prettier
|
||||
pnpm format
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
```bash
|
||||
# Run tests
|
||||
pnpm test
|
||||
|
||||
# Run tests in watch mode
|
||||
pnpm test --watch
|
||||
```
|
||||
|
||||
### Debugging
|
||||
|
||||
To debug the backend with Node.js inspector:
|
||||
|
||||
```bash
|
||||
pnpm backend:debug
|
||||
```
|
||||
|
||||
Then attach your debugger to `http://localhost:9229`.
|
||||
|
||||
## Making Changes
|
||||
|
||||
### Backend Development
|
||||
|
||||
1. **Controllers**: Handle HTTP requests and responses
|
||||
2. **Services**: Implement business logic
|
||||
3. **Models**: Define database schemas
|
||||
4. **Routes**: Define API endpoints
|
||||
|
||||
### Frontend Development
|
||||
|
||||
1. **Components**: Reusable React components
|
||||
2. **Pages**: Route-specific components
|
||||
3. **Services**: API communication
|
||||
4. **Hooks**: Custom React hooks
|
||||
|
||||
### Adding New MCP Servers
|
||||
|
||||
1. Update `mcp_settings.json` with the new server configuration
|
||||
2. Test the server integration
|
||||
3. Update documentation if needed
|
||||
|
||||
## Common Development Tasks
|
||||
|
||||
### Adding a New API Endpoint
|
||||
|
||||
1. Create a controller in `src/controllers/`
|
||||
2. Define the route in `src/routes/`
|
||||
3. Add any necessary middleware
|
||||
4. Write tests for the new endpoint
|
||||
|
||||
### Adding a New Frontend Feature
|
||||
|
||||
1. Create components in `frontend/src/components/`
|
||||
2. Add routes if needed
|
||||
3. Implement API integration
|
||||
4. Style with Tailwind CSS
|
||||
|
||||
### Database Migrations
|
||||
|
||||
When modifying database schemas:
|
||||
|
||||
1. Update models in `src/models/`
|
||||
2. Create migration scripts if using TypeORM
|
||||
3. Test migrations locally
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Port conflicts**: Ensure ports 3000 and 5173 are available
|
||||
|
||||
**Database connection**: Verify PostgreSQL is running and credentials are correct
|
||||
|
||||
**MCP server startup**: Check server configurations in `mcp_settings.json`
|
||||
|
||||
**Permission issues**: Ensure MCP servers have necessary permissions
|
||||
|
||||
### Getting Help
|
||||
|
||||
- Check the [Contributing Guide](/development/contributing)
|
||||
- Review [Architecture Documentation](/development/architecture)
|
||||
- Open an issue on GitHub for bugs
|
||||
- Join our community discussions
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Read the [Architecture Overview](/development/architecture)
|
||||
- Learn about [Contributing Guidelines](/development/contributing)
|
||||
- Explore [Configuration Options](/configuration/environment-variables)
|
||||
Reference in New Issue
Block a user