--- inclusion: always --- # Coding Standards — beam-mcp-server ## Projektstruktur ``` src/ ├── index.ts # MCP Server, Tool-Registrierung, Label-Mappings, Error-Handling ├── api.ts # BEAM GraphQL/REST API Client, Diagramm-Funktionen ├── auth.ts # Token-Management (Keychain + Playwright Browser-Login) └── keychain.ts # OS-Keychain Abstraktionsschicht (macOS/Windows) ``` ## TypeScript-Konventionen - ESM (`"type": "module"` in package.json), alle Imports mit `.js`-Suffix - Strict mode aktiviert, kein `any` — nutze `Record` oder konkrete Interfaces - Target: ES2022, Module: Node16 - Build: `npm run build` (tsc), Output in `dist/` ## MCP Tool-Konventionen - Alle Tools nutzen `server.registerTool()` (NICHT `server.tool()`) - Tool-Namen: `beam_` Prefix + snake_case (z.B. `beam_search_factsheets`) - Jedes Tool braucht: - `title`: Kurzer deutscher Titel - `description`: Ausführliche Beschreibung mit Args, Returns, Examples - `inputSchema`: Zod-Schemas mit `.describe()` und Validierung (`.min()`, `.max()`) - `annotations`: `readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint` - Jeder Tool-Handler ist in try/catch gewrappt und nutzt `handleError()` bei Fehlern - Große Responses werden mit `truncateIfNeeded()` auf CHARACTER_LIMIT (25k) gekürzt ## Error-Handling Pattern ```typescript async (params) => { try { // ... Logik ... return { content: [{ type: "text", text: result }] }; } catch (error) { return handleError(error); } } ``` `handleError()` gibt `{ isError: true, content: [...] }` zurück mit kontextbezogenen Meldungen: - 401/403 → Hinweis auf `beam_get_token` - 404 → ID/Suchbegriff prüfen - 429 → Rate-Limit, warten ## API-Schicht (api.ts) - `gql()` — Shared GraphQL-Client mit Auth-Header - Alle API-Funktionen sind `async` und werfen Errors mit HTTP-Status - UUID-Erkennung: `/^[0-9a-f-]{36}$/i` — alles andere wird als Beam-ID/Name per Suche aufgelöst - Neue API-Funktionen gehören in `api.ts`, nicht in `index.ts` ## Label-Mappings (index.ts) BEAM-interne Werte werden auf deutsche Labels gemappt: - `LC` — Lebenszyklus (active→Aktiv, phaseOut→Ausgliederungsphase, ...) - `ST` — Supporttyp (leading→Führend, supports→Unterstützt) - `FS_TYPE` — Fact-Sheet-Typen (Application→Anwendung, ...) - `STATE` — Status (APPROVED→Bestätigt, ...) ## Auth (auth.ts) & Keychain (keychain.ts) - Token-Priorität: In-Memory Cache → OS-Keychain → Playwright Browser-Login - Token wird im OS-Keychain gespeichert (macOS: Keychain Access, Windows: DPAPI) - Keine .env-Datei für Secrets — nur für Konfigurations-URLs - Gültigkeit: JWT exp-Claim minus 60s Puffer - Bei Invalidierung (401): Token aus Memory + Keychain gelöscht - Logging nur auf stderr (stdio-Transport!) ## Build & Test ```bash npm run build # TypeScript kompilieren npm start # Server starten (stdio) npm run login # Manueller Browser-Login + Token im Keychain speichern ``` Nach jeder Änderung: `npm run build` muss fehlerfrei durchlaufen.