# Architecture - mcp-server (MCP Server)

## Overview

Architecture documentation for the Memento MCP (Model Context Protocol) server, an Express-based microservice that provides AI assistant and automation integration for the Memento note-taking application.

**Architecture Pattern:** Microservice API
**Framework:** Express.js 4.22.1
**Protocol:** MCP SDK 1.0.4
**Language:** JavaScript (ES modules)
**Database:** Shared SQLite via Prisma

---

## Technology Stack

### Core
| Technology | Version | Purpose |
|------------|---------|---------|
| Node.js | 20+ | Runtime |
| Express.js | 4.22.1 | Web framework |
| MCP SDK | 1.0.4 | Model Context Protocol |
| Prisma | 5.22.0 | ORM |

### Transport
- **Primary:** Stdio (standard input/output)
- **Alternative:** Server-Sent Events (SSE) via `index-sse.js`

### Database
- **ORM:** Prisma 5.22.0
- **Database:** SQLite (shared with keep-notes)
- **File:** `../keep-notes/prisma/dev.db`

---

## Architecture Pattern: Microservice

### System Architecture

```
┌─────────────────┐
│   MCP Client    │
│  (AI Assistant)  │
│   N8N Workflow   │
└────────┬────────┘
         │ MCP Protocol
         ↓
┌─────────────────┐
│   mcp-server    │
│                 │
│  MCP Tools:     │
│  - create_note  │
│  - get_notes     │
│  - search_notes  │
│  - update_note   │
│  - delete_note   │
│  - toggle_pin    │
│  - toggle_archive│
│  - get_labels    │
└────────┬────────┘
         │
         ↓
┌─────────────────┐
│  Prisma ORM     │
│                 │
│  Shared SQLite  │
└─────────────────┘
```

### Communication Flow

1. **MCP Client** (AI assistant, N8N) connects via stdio
2. **Request:** Tool invocation with parameters
3. **Processing:** Server executes business logic
4. **Database:** Prisma queries/updates
5. **Response:** JSON result returned via stdio

---

## Server Structure

### File Organization

```
mcp-server/
├── index.js               # Main MCP server (stdio transport)
├── index-sse.js           # SSE variant (HTTP + SSE)
├── package.json           # Dependencies
├── README.md              # Server documentation
├── README-SSE.md          # SSE documentation
├── N8N-CONFIG.md          # N8N setup guide
└── prisma/                # Prisma client (shared)
    ├── schema.prisma      # Schema reference
    └── [generated client]
```

### Entry Points

**Primary: index.js**
```javascript
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
// ... tool definitions
const transport = new StdioServerTransport();
await server.connect(transport);
```

**Alternative: index-sse.js**
```javascript
// HTTP server with Server-Sent Events
// For web-based MCP clients
```

---

## MCP Tool Architecture

### Tool Registration Pattern

```javascript
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: 'create_note',
        description: 'Create a new note in Memento',
        inputSchema: {
          type: 'object',
          properties: { /* ... */ },
          required: ['content']
        }
      },
      // ... 7 more tools
    ]
  }
});
```

### Tool Execution Pattern

```javascript
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  try {
    switch (name) {
      case 'create_note': {
        const note = await prisma.note.create({ /* ... */ });
        return {
          content: [{ type: 'text', text: JSON.stringify(parseNote(note)) }]
        };
      }
      // ... handle other tools
    }
  } catch (error) {
    throw new McpError(ErrorCode.InternalError, error.message);
  }
});
```

---

## Available MCP Tools

### Note Management (6 tools)

| Tool | Purpose | Required Params |
|------|---------|----------------|
| **create_note** | Create note | content |
| **get_notes** | List all notes | (optional) includeArchived, search |
| **get_note** | Get single note | id |
| **update_note** | Update note | id, (optional) fields to update |
| **delete_note** | Delete note | id |
| **search_notes** | Search notes | query |

### Note Operations (2 tools)

| Tool | Purpose | Required Params |
|------|---------|----------------|
| **toggle_pin** | Toggle pin status | id |
| **toggle_archive** | Toggle archive status | id |

### Data Query (1 tool)

| Tool | Purpose | Required Params |
|------|---------|----------------|
| **get_labels** | Get all unique labels | (none) |

**Total Tools:** 9 tools

---

## Database Integration

### Connection Details

```javascript
const prisma = new PrismaClient({
  datasources: {
    db: {
      url: `file:${join(__dirname, '../keep-notes/prisma/dev.db')}`
    }
  }
});
```

**Path Resolution:**
- From `mcp-server/index.js`
- To: `../keep-notes/prisma/dev.db`
- Absolute: `D:/dev_new_pc/Keep/keep-notes/prisma/dev.db`

### Database Access Pattern

**Read Operations:**
```javascript
const notes = await prisma.note.findMany({
  where: { /* conditions */ },
  orderBy: [/* sorting */]
});
```

**Write Operations:**
```javascript
const note = await prisma.note.create({
  data: { /* note data */ }
});
```

**Update Operations:**
```javascript
const note = await prisma.note.update({
  where: { id: args.id },
  data: { /* updates */ }
});
```

**Delete Operations:**
```javascript
await prisma.note.delete({
  where: { id: args.id }
});
```

---

## Data Processing

### JSON Field Parsing

**Helper Function:**
```javascript
function parseNote(dbNote) {
  return {
    ...dbNote,
    checkItems: dbNote.checkItems ? JSON.parse(dbNote.checkItems) : null,
    labels: dbNote.labels ? JSON.parse(dbNote.labels) : null,
    images: dbNote.images ? JSON.parse(dbNote.images) : null,
  };
}
```

**Purpose:** Convert JSON strings from DB to JavaScript objects

**Fields Parsed:**
- `checkItems`: Array of checklist items
- `labels`: Array of label names
- `images`: Array of image URLs/data

---

## Error Handling

### MCP Error Pattern

```javascript
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';

// Not found
throw new McpError(ErrorCode.InvalidRequest, 'Note not found');

// Server error
throw new McpError(ErrorCode.InternalError, `Tool execution failed: ${error.message}`);

// Unknown tool
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
```

### Error Types

| Error Code | Usage |
|------------|-------|
| `InvalidRequest` | Invalid parameters, resource not found |
| `MethodNotFound` | Unknown tool requested |
| `InternalError` | Server-side failures (DB, parsing, etc.) |

---

## Tool Schemas

### create_note

**Input Schema:**
```json
{
  "type": "object",
  "properties": {
    "title": { "type": "string" },
    "content": { "type": "string" },
    "color": { "type": "string", "enum": ["default","red",...] },
    "type": { "type": "string", "enum": ["text","checklist"] },
    "checkItems": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "text": { "type": "string" },
          "checked": { "type": "boolean" }
        },
        "required": ["id","text","checked"]
      }
    },
    "labels": { "type": "array", "items": { "type": "string" } },
    "images": { "type": "array", "items": { "type": "string" } },
    "isPinned": { "type": "boolean" },
    "isArchived": { "type": "boolean" }
  },
  "required": ["content"]
}
```

### update_note

**Input Schema:**
```json
{
  "type": "object",
  "properties": {
    "id": { "type": "string" },
    "title": { "type": "string" },
    "content": { "type": "string" },
    "color": { "type": "string" },
    "checkItems": { "type": "array", "items": {/*...*/} },
    "labels": { "type": "array", "items": { "type": "string" } },
    "isPinned": { "type": "boolean" },
    "isArchived": { "type": "boolean" },
    "images": { "type": "array", "items": { "type": "string" } }
  },
  "required": ["id"]
}
```

**Behavior:** Only updates fields provided (partial update)

---

## Transport Layer

### Stdio Transport (Primary)

**Implementation:**
```javascript
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';

const transport = new StdioServerTransport();
await server.connect(transport);
```

**Use Cases:**
- AI assistants (ChatGPT, Claude, etc.)
- N8N MCP integration
- Command-line tools
- Desktop applications

**Communication:**
- **Input:** STDIN (JSON-RPC messages)
- **Output:** STDOUT (JSON-RPC responses)
- **Logging:** STDERR (diagnostic messages)

### SSE Transport (Alternative)

**File:** `index-sse.js`
**Implementation:** HTTP server with Server-Sent Events

**Use Cases:**
- Web-based clients
- Browser integrations
- Real-time notifications
- Long-running operations

---

## Concurrency Model

### Single-Threaded Event Loop
- Node.js event loop
- No parallel execution
- Sequential request handling

### Database Concurrency
- SQLite handles concurrent reads
- Single writer limitation
- Prisma manages connection

### Scalability
**Current:** Single instance
**Limitations:**
- No load balancing
- No automatic failover
- Single point of failure

**Future Enhancements:**
- Multiple instances with connection pooling
- PostgreSQL for better concurrency
- Redis for session management
- Message queue for async operations

---

## Security Architecture

### Current: No Authentication
**Rationale:**
- Trusted environment (localhost)
- AI assistants need full access
- Simplified integration

### Security Considerations
**Risks:**
- No access control
- No rate limiting
- No audit logging
- Direct database access

**Recommendations for Production:**
1. Add API key authentication
2. Implement rate limiting
3. Add request logging
4. Restrict to localhost or VPN
5. Use reverse proxy (nginx) for SSL

### Future Security
- JWT tokens for authentication
- Role-based access control
- IP whitelisting
- Request signing
- Audit logging

---

## Performance Characteristics

### Latency
- **Direct DB access:** ~1-5ms per query
- **JSON parsing:** ~0.1-0.5ms
- **Total tool execution:** ~5-20ms

### Throughput
- **Single-threaded:** Limited by CPU
- **SQLite:** ~1000-5000 ops/sec
- **Bottleneck:** Database I/O

### Optimization Opportunities
1. **Connection pooling:** Reuse Prisma client
2. **Query optimization:** Add indexes
3. **Caching:** Redis for frequent queries
4. **Batching:** Batch multiple operations

---

## Monitoring & Observability

### Current: Basic Logging
```javascript
console.error('Memento MCP server running on stdio');
```

**Logged to:** STDERR (won't interfere with stdio transport)

### Future Monitoring Needs
1. **Request Logging:** Log all tool invocations
2. **Error Tracking:** Sentry, Rollbar
3. **Performance Monitoring:** Query latency
4. **Metrics:** Tool usage statistics
5. **Health Checks:** `/health` endpoint

---

## Deployment Architecture

### Development
```bash
cd mcp-server
npm install
npm start
# Connects via stdio
```

### Production Options

**Option 1: Standalone Process**
```bash
node /path/to/mcp-server/index.js
```

**Option 2: Docker Container**
```dockerfile
FROM node:20-alpine
COPY mcp-server/ /app
WORKDIR /app
RUN npm install
CMD ["node", "index.js"]
```

**Option 3: Docker Compose**
```yaml
services:
  mcp-server:
    build: ./mcp-server
    volumes:
      - ./keep-notes/prisma:/app/db
```

**Option 4: Process Manager**
- PM2
- Systemd service
- Supervisord

---

## Integration Patterns

### N8N Workflow Integration

**Setup:** See `N8N-CONFIG.md`

**Usage:**
1. Add MCP node in N8N
2. Configure connection to mcp-server
3. Select tools (create_note, search_notes, etc.)
4. Build workflow

**Example Workflow:**
- Trigger: Webhook
- Tool: create_note
- Parameters: From webhook data
- Output: Created note

### AI Assistant Integration

**Supported Assistants:**
- ChatGPT (via MCP plugin)
- Claude (via MCP plugin)
- Custom AI agents

**Usage Pattern:**
1. User asks assistant: "Create a note about..."
2. Assistant calls MCP tools
3. Tools execute on Memento DB
4. Results returned to assistant
5. Assistant responds to user

---

## Versioning & Compatibility

### Current Version
**Server:** 1.0.0
**MCP Protocol:** 1.0.4

### Backward Compatibility
- Tool schemas evolve
- New tools added (non-breaking)
- Existing tools maintained

### Versioning Strategy
- Semantic versioning (MAJOR.MINOR.PATCH)
- MAJOR: Breaking changes
- MINOR: New features, backward compatible
- PATCH: Bug fixes

---

## Testing Strategy

### Current: Manual Testing
- N8N workflow testing
- Direct stdio invocation
- SSE variant testing

### Recommended Tests
1. **Unit Tests:** Tool execution logic
2. **Integration Tests:** Prisma operations
3. **E2E Tests:** Full MCP protocol flow
4. **Load Tests:** Concurrent tool execution

### Test Tools
- Jest for unit tests
- Supertest for HTTP endpoints
- Playwright for E2E
- Artillery for load testing

---

## Configuration Management

### Environment Variables
**Current:** Hardcoded (dev.db path)

**Recommended:**
```bash
DATABASE_URL="file:../keep-notes/prisma/dev.db"
LOG_LEVEL="info"
PORT="3000"  # For SSE variant
```

### Configuration File
**Future:** `config.json`
```json
{
  "database": {
    "url": "file:../keep-notes/prisma/dev.db"
  },
  "logging": {
    "level": "info"
  },
  "server": {
    "name": "memento-mcp-server",
    "version": "1.0.0"
  }
}
```

---

## Maintenance & Operations

### Startup
```bash
node index.js
# Output to stderr: "Memento MCP server running on stdio"
```

### Shutdown
- Send SIGTERM (Ctrl+C)
- Graceful shutdown
- Close database connections

### Health Checks
**Future:** `/health` endpoint
```javascript
app.get('/health', (req, res) => {
  res.json({ status: 'ok', uptime: process.uptime() })
})
```

---

## Troubleshooting

### Common Issues

**1. Database Connection Failed**
- **Symptom:** "Unable to connect to database"
- **Cause:** Incorrect path or missing DB file
- **Fix:** Verify `../keep-notes/prisma/dev.db` exists

**2. Permission Denied**
- **Symptom:** "EACCES: permission denied"
- **Cause:** File permissions on SQLite DB
- **Fix:** chmod 644 dev.db

**3. Stdio Not Working**
- **Symptom:** No response from server
- **Cause:** Client not connected to stdin/stdout
- **Fix:** Ensure proper stdio redirection

---

## Future Enhancements

### Short Term
1. Add authentication
2. Implement rate limiting
3. Add request logging
4. Health check endpoint
5. Configuration file support

### Long Term
1. WebSocket support for real-time
2. GraphQL integration
3. Batch operations
4. Transaction support
5. Multi-database support

---

## Summary

The mcp-server is a lightweight, focused microservice that:
- **Exposes 9 MCP tools** for note management
- **Connects directly to SQLite** via Prisma
- **Uses stdio transport** for AI/automation integration
- **Provides N8N workflow** integration
- **Shares database** with keep-notes web app
- **Offers SSE variant** for web clients

This architecture provides a clean separation of concerns while maintaining data consistency through the shared database layer.
