# SnelStart MCP - Development Guide
## ⚠️ RALPH WORKFLOW - ALTIJD VOLGEN!
Bij nieuwe features of grote wijzigingen:
1. **Gebruik `/ralph-toolkit:add-spec`** om een spec te maken in `.ralph/specs/`
2. **Gebruik `/ralph-toolkit:add-task`** om taken toe te voegen aan `.ralph/@fix_plan.md`
3. **Update NOOIT direct code** zonder eerst de spec/taken vast te leggen
Dit zorgt ervoor dat Ralph autonoom kan werken en de voortgang traceerbaar is.
## Project Overview
Multi-tenant SaaS platform voor SnelStart boekhoudintegratie. Bestaat uit drie packages:
- **mcp/** - MCP Server voor Claude Code CLI integratie
- **frontend/** - React dashboard voor organisatiebeheer
- **backend/** - Express API voor authenticatie, webhooks en tokens
## Tech Stack
- **Language:** TypeScript (strict mode)
- **Runtime:** Node.js 20+
- **MCP SDK:** @modelcontextprotocol/sdk
- **Frontend:** React + Vite + Tailwind CSS
- **Backend:** Express + Supabase
- **Database:** Supabase (PostgreSQL + RLS)
- **Auth:** Supabase Auth (Email + Google + Microsoft)
## Commands
```bash
# Root level - all workspaces
npm install # Install all dependencies
npm run build # Build all packages
# Individual packages
npm run dev # Start frontend dev server
npm run dev:backend # Start backend dev server
npm run dev:mcp # Start MCP server
# Testing
npm test --workspace=backend # Run backend tests (52 tests)
npm run test:mcp # Run MCP tools standards tests
npx tsc --noEmit # TypeScript check
supabase db reset # Reset local Supabase database
# Git hooks setup (run once after clone)
./scripts/setup-hooks.sh # Install pre-push hooks
# Migration
npx tsx scripts/migrate-config-to-supabase.ts --administration-id <uuid> [--dry-run]
```
## Project Structure
```
snelstart-mcp/
├── mcp/ # @snelstart/mcp - MCP Server
│ ├── src/
│ │ ├── index.ts # MCP Server entry point
│ │ ├── auth/ # API token validation
│ │ ├── config/ # Dual-mode config (env/supabase)
│ │ ├── integrations/ # SnelStart API client
│ │ ├── oauth/ # OAuth Productiekoppeling
│ │ ├── storage/ # Supabase client + booking rules
│ │ ├── tenant/ # Multi-tenant credential management
│ │ ├── tools/ # MCP Tools (80 tools)
│ │ │ ├── types.ts # Standaard types, helpers, PARAM_SCHEMAS
│ │ │ ├── admin.ts # Administration switching
│ │ │ ├── invoices.ts # Invoice tools
│ │ │ ├── relaties.ts # Customer/supplier tools
│ │ │ ├── boekingen.ts # Booking tools
│ │ │ ├── grootboeken.ts # Ledger tools
│ │ │ └── write/ # Write operations
│ │ └── types/ # TypeScript types
│ ├── tests/ # Standards enforcement tests
│ └── package.json
│
├── frontend/ # @snelstart/frontend - React Dashboard
│ ├── src/
│ │ ├── App.tsx # Main app with routing
│ │ ├── features/
│ │ │ ├── auth/ # Login, Register, AuthProvider
│ │ │ ├── organizations/ # Org CRUD
│ │ │ ├── administrations/ # Administration management
│ │ │ ├── api-tokens/ # Token management
│ │ │ └── booking-rules/ # Rules editor
│ │ ├── lib/ # Supabase client, utils
│ │ └── components/ # Shared UI components
│ └── package.json
│
├── backend/ # @snelstart/backend - Express API
│ ├── src/
│ │ ├── index.ts # Express app entry
│ │ ├── features/
│ │ │ ├── webhooks/ # OAuth webhook handler
│ │ │ └── tokens/ # Token generation/validation
│ │ ├── middleware/ # Auth, security, error handling
│ │ ├── shared/ # Crypto, types, validation
│ │ ├── lib/ # Supabase client
│ │ └── __tests__/ # Integration tests
│ └── package.json
│
├── supabase/ # Database
│ ├── config.toml # Supabase config
│ ├── migrations/ # SQL migrations (1-7)
│ └── tests/ # RLS test scripts
│
├── config/
│ └── booking-rules.json # Leverancier config (legacy/env mode)
│
├── scripts/
│ ├── sync-grootboeken.cjs # Sync/validate IDs with API
│ ├── scan-facturen.cjs # Factuur overview
│ └── migrate-config-to-supabase.ts # Config migration script
│
└── package.json # npm workspaces config
```
## Configuration Modes
### 1. ENV Mode (Legacy/Development)
Credentials in `.env` file:
```bash
SNELSTART_MODE=env
SNELSTART_ADMINS=vca
SNELSTART_VCA_SUBSCRIPTION_KEY=xxx
SNELSTART_VCA_CONNECTION_KEY=xxx
```
### 2. Supabase Mode (Multi-Tenant SaaS)
Credentials from Supabase database:
```bash
SNELSTART_MODE=supabase
SNELSTART_API_TOKEN=snelstart_xxx
SUPABASE_URL=https://xxx.supabase.co
SUPABASE_ANON_KEY=xxx
```
## Development Rules
### 1. TYPESCRIPT STRICT
- Geen `any` types
- Proper interfaces voor alle data
- Run `npx tsc --noEmit` na elke wijziging
### 2. CREDENTIALS
- API keys in `.env` (NOOIT committen!)
- Encrypted at rest in Supabase (AES-256-GCM)
- Shown only once at creation
### 3. CONFIG FILES = BRON VAN WAARHEID
⚠️ **KRITIEK: LEES ALTIJD `config/booking-rules.json` VOORDAT JE BEGINT MET BOEKHOUDING TAKEN!**
Dit bestand bevat:
- **Leverancier mappings** (ID, grootboek, BTW, kostenplaats)
- **Kostenplaatsen** met IDs
- **Grootboeken** met IDs
- **Dagboeken** (bank, creditcard) met IDs
```bash
# ALTIJD EERST LEZEN bij boekhouding taken:
cat config/booking-rules.json
```
Regels:
- **NOOIT IDs hardcoden** in docs of code
- **NOOIT kostenplaatsen "raden"** - ze staan in de config
- **NOOIT leverancier info opnieuw opzoeken** als die in de config staat
- Valideer met: `node scripts/sync-grootboeken.cjs`
## Database Schema
### Key Tables
| Table | Description |
|-------|-------------|
| `organizations` | Accountantskantoren |
| `organization_members` | Gebruikers per organisatie (rol: admin/member) |
| `administrations` | SnelStart administraties per organisatie |
| `booking_rules` | Leverancier/grootboek/kostenplaats config per administratie |
| `api_tokens` | MCP access tokens (hashed) |
| `audit_log` | Alle acties gelogd |
### RLS Policies
- Users see only their organization's data
- Admin role required for mutations
- API tokens validated via backend
## SnelStart API Reference
### Authentication
Er zijn **twee authenticatiemethodes**:
#### 1. Client Key (Handmatig)
Voor development of wanneer je zelf de sleutels beheert:
```typescript
POST https://auth.snelstart.nl/b2b/token
Body: grant_type=clientkey&clientkey={connectionKey}
// Headers voor API calls
{
'Ocp-Apim-Subscription-Key': subscriptionKey,
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
```
#### 2. OAuth Productiekoppeling (Gebruikersvriendelijk)
Voor productie - gebruikers hoeven geen sleutels uit te wisselen:
```
1. Start webhook server: oauth_start_server
2. Genereer activatie-URL: oauth_generate_activation_url reference_key="klant-123"
3. Gebruiker klikt URL → logt in bij SnelStart → autoriseert koppeling
4. SnelStart stuurt webhook met KoppelSleutel naar jouw server
5. Koppeling is opgeslagen en klaar voor gebruik
```
**OAuth Tools:**
| Tool | Beschrijving |
|------|-------------|
| `oauth_start_server` | Start de webhook server |
| `oauth_stop_server` | Stop de webhook server |
| `oauth_server_status` | Bekijk server status + aantal koppelingen |
| `oauth_generate_activation_url` | Maak activatie-URL voor een gebruiker |
| `oauth_list_couplings` | Lijst alle actieve koppelingen |
| `oauth_get_coupling` | Details van specifieke koppeling |
| `oauth_delete_coupling` | Verwijder lokaal opgeslagen koppeling |
### Base URL
`https://b2bapi.snelstart.nl/v2`
### Key Endpoints
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/companyInfo` | GET | Company/admin info |
| `/relaties` | GET | Customers/suppliers |
| `/grootboeken` | GET | Chart of accounts |
| `/inkoopfacturen` | GET | Purchase invoices |
| `/bankboekingen` | GET/POST | Bank bookings |
| `/inkoopboekingen` | GET/POST | Purchase bookings |
> **Let op:** Gebruik `/inkoopfacturen` voor facturen, NIET `/inkoopboekingen`!
## MCP Tool Guidelines
Each tool should:
1. Have clear inputSchema with Zod validation
2. Return structured JSON responses
3. Handle errors gracefully with descriptive messages
4. Support `compact=true` for minimal output (saves context)
### Tool Standards (Enforced by Tests)
Alle tools moeten de standaarden uit `mcp/src/tools/types.ts` volgen:
```typescript
// ❌ NIET DOEN - hardcoded defaults
const limit = typedArgs.limit ?? 20;
const isCompact = typedArgs.compact !== false;
if (!typedArgs.param) { return errorResponse("..."); }
// ✅ WEL DOEN - gebruik helpers
const limit = parseLimit(typedArgs.limit); // Default: 50
const isCompact = parseCompact(typedArgs.compact); // Default: true
const error = validateRequired(typedArgs.param, "param");
if (error) { return errorResponse(error); }
// ✅ Parameter schemas via PARAM_SCHEMAS
inputSchema: {
properties: {
limit: PARAM_SCHEMAS.limit, // Niet inline definiëren
compact: PARAM_SCHEMAS.compact,
}
}
```
**Pre-push hook** draait automatisch `npm run test:mcp` om deze standaarden af te dwingen.
Beschikbare helpers in `types.ts`:
- `parseLimit(value)` - Returns 50 als undefined
- `parseCompact(value)` - Returns true als undefined
- `validateRequired(value, name)` - Returns error message of undefined
- `validateRequiredParams(args, ["a", "b"])` - Valideert meerdere params
- `successResponse(data)` - Standaard success response
- `errorResponse(message, details?)` - Standaard error response
## Claude Skills
Er zijn 6 skills beschikbaar via `/snelstart-toolkit:`:
| Skill | Beschrijving | Commando |
|-------|-------------|----------|
| `snelstart-boekhouder` | Complete workflow: factuur boeken + PDF + koppelen creditcard | `/snelstart-boekhouder` |
| `snelstart-creditcard-transacties` | Omboeken van bank (1100) naar creditcard (1190) | `/snelstart-creditcard-transacties` |
| `lulu-invoices` | Lulu Print facturen downloaden en boeken | `/lulu-invoices [download\|book\|status]` |
| `stripe-invoices` | Stripe facturen downloaden (Claude.ai, OpenAI, etc.) | `/stripe-invoices [platform]` |
| `creditcard-import` | Importeer ICS creditcard CSV naar SnelStart | `/snelstart-toolkit:creditcard-import [csv-path]` |
| `update-grootboeken` | Valideer/sync grootboek config met API | `/snelstart-toolkit:update-grootboeken [--fix\|--usage]` |
Skills staan in: `~/.claude/plugins/snelstart-toolkit/skills/`
## Key Workflows
### 1. Creditcard Transacties Verwerken
```
1. find_unlinked_transactions → Vind ongekoppelde transacties
2. list_inkoopboekingen → Check of inkoopboeking al bestaat
3. create_inkoopboeking → Maak inkoopboeking + upload PDF
4. link_inkoopboeking_to_bankboeking → Koppel aan creditcard
```
### 2. Quick Book (voor bekende leveranciers)
```bash
quick_book leverancier="KEY" document_path="..." factuurnummer="..." ...
```
Haalt automatisch grootboek, BTW en kostenplaats uit `config/booking-rules.json` of Supabase.
### 3. Config Migration (naar Supabase)
```bash
# Dry run - zie wat er gemigreerd wordt
npx tsx scripts/migrate-config-to-supabase.ts --administration-id <uuid> --dry-run
# Live migratie
npx tsx scripts/migrate-config-to-supabase.ts --administration-id <uuid>
```
### 4. Config Sync
```bash
# Valideer grootboek IDs tegen SnelStart API
node scripts/sync-grootboeken.cjs
# Auto-fix mismatches
node scripts/sync-grootboeken.cjs --fix
# Export alle grootboeken
node scripts/sync-grootboeken.cjs --export
# Analyseer daadwerkelijk gebruikte grootboeken
node scripts/sync-grootboeken.cjs --usage # Huidig jaar
node scripts/sync-grootboeken.cjs --usage 2025 # Specifiek jaar
```
## BTW Behandeling
| Situatie | btwSoort | BTW array |
|----------|----------|-----------|
| Buitenlands (US/SG/etc) | `"Geen"` | `[]` |
| EU met geldig BTW-nr | `"Verlegd"` | `[{btwSoort: "InkopenVerlegd", btwBedrag: X}]` |
| Nederlands 21% | `"Hoog"` | `[{btwSoort: "InkopenHoog", btwBedrag: X}]` |
| Nederlands 9% | `"Laag"` | `[{btwSoort: "InkopenLaag", btwBedrag: X}]` |
## Kritieke Regels
### GEEN BOEKING ZONDER PDF
- `create_inkoopboeking` vereist `document_path` parameter
- PDF wordt automatisch geupload naar SnelStart
### GROOTBOEKMUTATIES ZIJN READ-ONLY
- Alleen GET endpoints beschikbaar
- Om mutatie te verwijderen → verwijder de bronboeking
### CONTEXT-EFFICIENTE QUERIES
- Gebruik `search="..."` filter
- Kleine date range (max 1 maand)
- Default `compact=true`
## Security
### Encryption
- AES-256-GCM met scrypt key derivation
- Format: `{salt}:{iv}:{authTag}:{ciphertext}` (all base64)
- Master key via `ENCRYPTION_MASTER_KEY` env var
### API Token Format
- `snelstart_{prefix}_{random}` (64 chars total)
- Token shown ONCE at creation, only hash stored
### RLS
- All tables protected by Row Level Security
- Users see only their organization's data
- Service role key only for backend
## Playwright PDF Downloads
Gebruik **altijd** `page.pdf()` voor het downloaden van facturen:
```javascript
await page.goto('https://site.com/receipt/123');
await page.waitForTimeout(3000);
await page.pdf({
format: 'A4',
printBackground: true,
path: '/pad/naar/factuur.pdf'
});
```
**NOOIT** klikken op download buttons - gebruik page.pdf() direct.
## Completion Criteria
1. TypeScript compileert zonder errors (`npm run build`)
2. Backend tests passing (`npm test --workspace=backend`)
3. MCP server start correct (`npm run dev:mcp`)
4. Config files gesynchroniseerd met SnelStart API