Source picker, per-query scope toggling, and API key encryption for MCP connections
Gadoes adds a full source-management layer on top of the MCP backend: a database schema for server registries, AES-256-GCM key storage, a region-grouped picker UI, and a per-message scope filter that restricts which MCP tools the LLM can call.
Three chunks land here as a unit. The database side (migration 002_mcp_servers.sql) seeds a registry of 12 sources grouped by region - United States (CourtListener, GovInfo), Gulf (Al-Meezan, Saudi MoJ), EU (EUR-Lex, Légifrance, BOE), arbitration (ICSID, ITALAW, UNCITRAL), and others. The table schema distinguishes tier-1 active sources from tier-2/3 "coming soon" entries visible in the picker with a locked badge. Per-user connections live in mcp_connections, with api_key stored as AES-256-GCM ciphertext and a key_version column for rotation tracking. Gadoes wires this through a GET/POST/DELETE /user/mcp-connections REST surface, encrypting on write and decrypting on read via encryption.ts, keyed on MCP_KEY_ENCRYPTION_KEY. There's also an env-fallback path in getMcpApiKey() so self-hosters can supply keys without requiring per-user DB entries.
The picker component (SourcePickerPopover) renders sources grouped by region with state badges - Always on, Connected, Connect, Permission required - plus a search input and region glyphs. It closes on outside click or Escape. A SourcesPill button in ChatInput.tsx shows the active count and opens the popover.
The per-query scope feature adds an mcpScope?: string[] | null field to both POST /chat and POST /projects/:projectId/chat. Inside runLLMStream(), a scopeSet is applied after the existing open-circuit filter: servers not in the scope list are excluded from the active tool definitions passed to the LLM. A null or absent mcpScope means no restriction. The frontend implements this with a useScopeState hook that tracks per-message vs. sticky modes, toggling sources on and off with toggleSource and a clearScope call after send.
One practical note: the 12-source seed catalogue is specific to Gadoes's product. If you take this, you'll want to replace it with your own list. The is_admin column added to user_profiles in migration 003 is consumed downstream by the telemetry dashboard, so plan for that dependency.
Spotted something wrong? Or know the PR text has fresher detail than the writeup above?