Files
mcp-outline-postgresql/CLAUDE.md
Emanuel Almeida 5f49cb63e8 feat: v1.3.1 - Multi-transport + Production deployment
- Add HTTP transport (StreamableHTTPServerTransport)
- Add shared server module (src/server/)
- Configure production for hub.descomplicar.pt
- Add SSH tunnel script (start-tunnel.sh)
- Fix connection leak in pg-client.ts
- Fix atomicity bug in comments deletion
- Update docs with test plan for 164 tools

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 17:06:30 +00:00

12 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

MCP server for direct PostgreSQL access to Outline Wiki database. Follows patterns established by mcp-desk-crm-sql-v3.

Version: 1.3.1 Total Tools: 164 tools across 33 modules Production: hub.descomplicar.pt (via SSH tunnel)

Architecture

                    ┌─────────────────────┐
                    │   src/server/       │
                    │   (Shared Logic)    │
                    └──────────┬──────────┘
                               │
              ┌────────────────┼────────────────┐
              │                │                │
     ┌────────▼────────┐ ┌─────▼─────┐         │
     │   index.ts      │ │index-http │         │
     │   (stdio)       │ │ (HTTP)    │         │
     └─────────────────┘ └───────────┘         │
              │                │                │
              └────────────────┴────────────────┘
                               │
                    ┌──────────▼──────────┐
                    │     PostgreSQL      │
                    │    (Outline DB)     │
                    └─────────────────────┘

Commands

# Build TypeScript to dist/
npm run build

# Run stdio server (default, for Claude Code)
npm start

# Run HTTP server (for web/remote access)
npm run start:http

# Development with ts-node
npm run dev
npm run dev:http

# Run tests
npm test

Transports

Transport Entry Point Port Use Case
stdio index.ts N/A Claude Code local
HTTP index-http.ts 3200 Web/remote access

HTTP Transport Endpoints

  • /mcp - MCP protocol endpoint
  • /health - Health check (JSON status)
  • /stats - Tool statistics

Project Structure

src/
├── index.ts              # Stdio transport entry point
├── index-http.ts         # HTTP transport entry point
├── pg-client.ts          # PostgreSQL client wrapper
├── config/
│   └── database.ts       # DB configuration
├── server/
│   ├── index.ts          # Server module exports
│   ├── create-server.ts  # MCP server factory
│   └── register-handlers.ts  # Shared handler registration
├── types/
│   ├── index.ts
│   ├── tools.ts          # Base tool types
│   └── db.ts             # Database table types
├── tools/
│   ├── index.ts          # Export all tools
│   ├── documents.ts      # 19 tools - Core document management
│   ├── collections.ts    # 14 tools - Collection management
│   ├── users.ts          # 9 tools - User management
│   ├── groups.ts         # 8 tools - Group management
│   ├── comments.ts       # 6 tools - Comment system
│   ├── shares.ts         # 5 tools - Document sharing
│   ├── revisions.ts      # 3 tools - Version history
│   ├── events.ts         # 3 tools - Audit log
│   ├── attachments.ts    # 5 tools - File attachments
│   ├── file-operations.ts # 4 tools - Import/export jobs
│   ├── oauth.ts          # 8 tools - OAuth management
│   ├── auth.ts           # 2 tools - Authentication
│   ├── stars.ts          # 3 tools - Bookmarks
│   ├── pins.ts           # 3 tools - Pinned documents
│   ├── views.ts          # 2 tools - View tracking
│   ├── reactions.ts      # 3 tools - Emoji reactions
│   ├── api-keys.ts       # 4 tools - API keys
│   ├── webhooks.ts       # 4 tools - Webhooks
│   ├── backlinks.ts      # 1 tool - Link references
│   ├── search-queries.ts # 2 tools - Search analytics
│   ├── teams.ts          # 5 tools - Team/workspace
│   ├── integrations.ts   # 6 tools - External integrations
│   ├── notifications.ts  # 4 tools - Notifications
│   ├── subscriptions.ts  # 4 tools - Subscriptions
│   ├── templates.ts      # 5 tools - Templates
│   ├── imports-tools.ts  # 4 tools - Import jobs
│   ├── emojis.ts         # 3 tools - Custom emojis
│   ├── user-permissions.ts # 3 tools - Permissions
│   ├── bulk-operations.ts # 6 tools - Batch operations
│   ├── advanced-search.ts # 6 tools - Advanced search
│   ├── analytics.ts      # 6 tools - Analytics
│   ├── export-import.ts  # 2 tools - Markdown export/import
│   └── desk-sync.ts      # 2 tools - Desk CRM integration
└── utils/
    ├── index.ts          # Export all utilities
    ├── logger.ts         # Logging utility
    ├── security.ts       # Security utilities (validation, rate limiting)
    ├── transaction.ts    # Transaction helpers with retry logic
    ├── query-builder.ts  # Safe parameterized query builder
    ├── validation.ts     # Zod-based input validation
    ├── audit.ts          # Audit logging for write operations
    ├── monitoring.ts     # Connection pool health monitoring
    └── pagination.ts     # Cursor-based pagination helpers

Tools Summary (164 total)

Module Tools Description
documents 19 CRUD, search, archive, move, templates, memberships
collections 14 CRUD, memberships, groups, export
users 9 CRUD, suspend, activate, promote, demote
groups 8 CRUD, memberships
comments 6 CRUD, resolve
shares 5 CRUD, revoke
revisions 3 list, info, compare
events 3 list, info, stats
attachments 5 CRUD, stats
file-operations 4 import/export jobs
oauth 8 OAuth clients, authentications
auth 2 auth info, config
stars 3 list, create, delete (bookmarks)
pins 3 list, create, delete (highlighted docs)
views 2 list, create (view tracking)
reactions 3 list, create, delete (emoji on comments)
api-keys 4 CRUD (programmatic access)
webhooks 4 CRUD (event subscriptions)
backlinks 1 list (document links - read-only view)
search-queries 2 list, stats (search analytics)
teams 5 get, update, stats, domains, settings
integrations 6 list, get, create, update, delete, sync
notifications 4 list, mark read, mark all read, settings
subscriptions 4 list, subscribe, unsubscribe, settings
templates 5 list, get, create from, convert to/from
imports 4 list, status, create, cancel
emojis 3 list, create, delete
user-permissions 3 list, grant, revoke
bulk-operations 6 archive, delete, move, restore, add/remove users
advanced-search 6 advanced search, facets, recent, user activity, orphaned, duplicates
analytics 6 overview, user activity, content insights, collection stats, growth, search
export-import 2 export collection to markdown, import markdown folder
desk-sync 2 create desk project doc, link desk task

Configuration

Production (hub.descomplicar.pt)

Requires SSH tunnel - Run before starting Claude Code:

./start-tunnel.sh start

Add to ~/.claude.json under mcpServers:

{
  "outline-postgresql": {
    "command": "node",
    "args": ["/home/ealmeida/mcp-servers/mcp-outline-postgresql/dist/index.js"],
    "env": {
      "DATABASE_URL": "postgres://postgres:***@localhost:5433/descomplicar",
      "LOG_LEVEL": "error"
    }
  }
}

Local Development

{
  "outline-postgresql": {
    "command": "node",
    "args": ["/home/ealmeida/mcp-servers/mcp-outline-postgresql/dist/index.js"],
    "env": {
      "DATABASE_URL": "postgres://outline:outline_dev_2026@localhost:5432/outline",
      "LOG_LEVEL": "error"
    }
  }
}

SSH Tunnel Management

# Start tunnel (before Claude Code)
./start-tunnel.sh start

# Check status
./start-tunnel.sh status

# Stop tunnel
./start-tunnel.sh stop

Environment

Environment Port Database Tunnel
Production 5433 descomplicar Required
Development 5432 outline No

Key Patterns

Tool Response Format

return {
  content: [{
    type: 'text',
    text: JSON.stringify(data, null, 2)
  }]
};

Naming Conventions

Type Convention Example
Tool name snake_case with prefix outline_list_documents
Function camelCase listDocuments
Type PascalCase DocumentRow
File kebab-case documents.ts

Database

PostgreSQL 15 - Direct SQL access (not Outline API)

Key tables: documents, collections, users, groups, comments, revisions, shares, attachments, events, stars, pins, views, file_operations, oauth_clients

Soft deletes: Most entities use deletedAt column, not hard deletes.

See SPEC-MCP-OUTLINE.md for complete database schema.

Security Utilities

The src/utils/security.ts module provides essential security functions:

Validation Functions

Function Description
isValidUUID(uuid) Validate UUID format
isValidUrlId(urlId) Validate URL-safe ID format
isValidEmail(email) Validate email format
isValidHttpUrl(url) Validate URL is HTTP(S) - rejects javascript:, data:, file: protocols
isValidISODate(date) Validate ISO date format (YYYY-MM-DD or full ISO)
validateDaysInterval(days, default, max) Validate and clamp days interval for SQL
validatePeriod(period, allowed, default) Validate period against allowed values
validatePagination(limit, offset) Validate and normalize pagination params
validateSortDirection(direction) Validate sort direction (ASC/DESC)
validateSortField(field, allowed, default) Validate sort field against whitelist

Sanitization Functions

Function Description
sanitizeInput(input) Remove null bytes and trim whitespace
escapeHtml(text) Escape HTML entities for safe display

Rate Limiting

Function Description
checkRateLimit(type, clientId) Check if request should be rate limited
startRateLimitCleanup() Start background cleanup of expired entries
stopRateLimitCleanup() Stop cleanup interval (call on shutdown)
clearRateLimitStore() Clear all rate limit entries (testing)

Usage Example

import {
  isValidUUID,
  isValidHttpUrl,
  validateDaysInterval,
  startRateLimitCleanup,
  stopRateLimitCleanup
} from './utils/security.js';

// Validation before SQL
if (!isValidUUID(args.user_id)) {
  throw new Error('Invalid user_id format');
}

// URL validation (prevents XSS)
if (!isValidHttpUrl(args.webhook_url)) {
  throw new Error('Invalid URL. Only HTTP(S) allowed.');
}

// Safe interval for SQL
const safeDays = validateDaysInterval(args.days, 30, 365);
// Use in query: `INTERVAL '${safeDays} days'` is safe (it's a number)

// Lifecycle management
startRateLimitCleanup();  // On server start
stopRateLimitCleanup();   // On graceful shutdown

Cryptographic Security

Secrets and tokens use crypto.randomBytes() instead of Math.random():

  • OAuth secrets: oauth.ts - sk_ prefixed base64url tokens
  • API keys: api-keys.ts - ol_ prefixed keys, only hash stored in DB
  • Share URLs: shares.ts - Cryptographically secure URL IDs