From ebb996cd4a439ad712a4b1236556a3dee57347a5 Mon Sep 17 00:00:00 2001 From: jonnyparris <6400000+jonnyparris@users.noreply.github.com> Date: Tue, 26 May 2026 12:46:18 +0100 Subject: [PATCH] fix(mcp): seed new catalog entries on every onStart + integrations-first UI layout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two follow-ups to PR #83: 1. **Catalog seed was first-run-only.** The cf-portal entry I added to `mcp-catalog.ts` never appeared in `/api/mcp-catalog` because the endpoint reads from UserControl's `approved_mcps` table, which is seeded once when the table is empty. Existing DOs (i.e. mine, and everyone else's) had been seeded back when the catalog was just browser-rendering + github, so the new entry never propagated. Fix: use `INSERT OR IGNORE` on every onStart, keyed by `mcp_url` (PRIMARY KEY). New catalog entries flow through; admin edits and soft-deletes on existing rows are preserved. 2. **Integrations buried below Skills + Tools.** Settings panel order was Skills (~50 entries) → Tools (~30 entries) → Integrations. Moved Integrations above both. Skills and Tools are now wrapped in collapsed `
` so they don't dominate the scroll. No tests added — the seed behaviour is exercised implicitly by every test that hits `/api/mcp-catalog` (which seeds via onStart). The UI move is markup-only. beep-boop-🤖 --- public/index.html | 24 ++++++++++++++---------- src/user-control.ts | 42 +++++++++++++++++++++++------------------- 2 files changed, 37 insertions(+), 29 deletions(-) diff --git a/public/index.html b/public/index.html index 3cfca44..4fd0ef8 100644 --- a/public/index.html +++ b/public/index.html @@ -910,16 +910,6 @@

Browser Rendering

-
-

Skills

-

Skills are SKILL.md files the agent loads on demand. Built-in skills ship with Dodo; personal skills you author here. Workspace skills (per-session, from .dodo/skills/ etc.) are not shown here.

-
-
-
-

Tools

-

Tools available to the agent. Dimmed entries are gated on session config (codemode, browser) or reachable only inside a codemode block (most git ops). Configure MCP integrations below to add more.

-
-

Integrations

@@ -934,6 +924,20 @@

Integrations

+
+
+

Skills

+

Skills are SKILL.md files the agent loads on demand. Built-in skills ship with Dodo; personal skills you author here. Workspace skills (per-session, from .dodo/skills/ etc.) are not shown here.

+
+
+
+
+
+

Tools

+

Tools available to the agent. Dimmed entries are gated on session config (codemode, browser) or reachable only inside a codemode block (most git ops). Configure MCP integrations above to add more.

+
+
+

Secrets

diff --git a/src/user-control.ts b/src/user-control.ts index fb8ca3d..567ed9a 100644 --- a/src/user-control.ts +++ b/src/user-control.ts @@ -1468,25 +1468,29 @@ export class UserControl extends DurableObject { this.ctx.storage.sql.exec("INSERT OR IGNORE INTO user_config (key, value, updated_at) VALUES (?, ?, ?)", key, String(value), now); } - const existingCount = (Array.from(this.ctx.storage.sql.exec("SELECT COUNT(*) AS n FROM approved_mcps WHERE is_deleted = 0"))[0] as SqlRow | null); - if (Number(existingCount?.n ?? 0) === 0) { - const { getDeployMcpCatalog } = await import("./mcp-catalog"); - const seedNow = Date.now(); - for (const entry of getDeployMcpCatalog(this.env)) { - this.ctx.storage.sql.exec( - `INSERT INTO approved_mcps (mcp_url, id, display_name, description, setup_guide, known_hosts, auth_type, status, is_deleted, created_at, updated_at) - VALUES (?, ?, ?, ?, ?, ?, ?, 'enabled', 0, ?, ?)`, - entry.url, - entry.id, - entry.name, - entry.description ?? null, - entry.setupGuide ?? null, - JSON.stringify(entry.knownHosts ?? []), - entry.auth_type ?? "static_headers", - seedNow, - seedNow, - ); - } + // Seed `approved_mcps` from the code-level catalog. We use `INSERT OR IGNORE` + // keyed by `mcp_url` so: + // - On first run, every catalog entry is inserted. + // - On subsequent runs, only NEW entries (not yet in the table) are + // inserted; admin-edited rows and soft-deleted rows are preserved. + // This is how adding a new entry to `mcp-catalog.ts` propagates to all + // existing UserControl DOs without an explicit migration. + const { getDeployMcpCatalog } = await import("./mcp-catalog"); + const seedNow = Date.now(); + for (const entry of getDeployMcpCatalog(this.env)) { + this.ctx.storage.sql.exec( + `INSERT OR IGNORE INTO approved_mcps (mcp_url, id, display_name, description, setup_guide, known_hosts, auth_type, status, is_deleted, created_at, updated_at) + VALUES (?, ?, ?, ?, ?, ?, ?, 'enabled', 0, ?, ?)`, + entry.url, + entry.id, + entry.name, + entry.description ?? null, + entry.setupGuide ?? null, + JSON.stringify(entry.knownHosts ?? []), + entry.auth_type ?? "static_headers", + seedNow, + seedNow, + ); } }