Skip to content

Commit 8109db1

Browse files
authored
fix(cloud): create SQLite DO without deleting the old class in the same deploy (#1193)
The delete migration kept failing (code 10061): Cloudflare validates a class delete against the LIVE binding, which still pointed at McpSessionDO, so binding move + delete can't happen in one deploy. Drop the delete: v2 only creates the new SQLite class McpSessionDOSqlite and the MCP_SESSION binding moves to it. The old KV McpSessionDO is left orphaned (kept as a stub export so the migration stays valid) and can be deleted in a later deploy now that nothing binds it. Also repoint the generated MCP_SESSION binding type to McpSessionDOSqlite.
1 parent 1dbd268 commit 8109db1

3 files changed

Lines changed: 18 additions & 8 deletions

File tree

apps/cloud/src/server.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { DurableObject } from "cloudflare:workers";
12
import { SpanKind, SpanStatusCode, context, trace } from "@opentelemetry/api";
23
import {
34
ATTR_HTTP_REQUEST_METHOD,
@@ -46,6 +47,14 @@ export const McpSessionDOSqlite = Sentry.instrumentDurableObjectWithSentry(
4647
McpSessionDOBase,
4748
);
4849

50+
// Orphaned placeholder for the original key-value `McpSessionDO` class (migration
51+
// v1). The live MCP session DO is now `McpSessionDOSqlite` (SQLite); the
52+
// `MCP_SESSION` binding moved to it. Cloudflare won't delete `McpSessionDO` in the
53+
// same deploy that moves its binding, so the class is left unbound and is kept
54+
// exported here only to satisfy the migration. It can be removed in a later deploy
55+
// (with a `deleted_classes: ["McpSessionDO"]` migration) now that nothing binds it.
56+
export class McpSessionDO extends DurableObject {}
57+
4958
// ---------------------------------------------------------------------------
5059
// Worker fetch handler
5160
//

apps/cloud/worker-configuration.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ declare namespace Cloudflare {
1414
WORKOS_COOKIE_PASSWORD: string;
1515
APP_URL: string;
1616
WORKOS_CLAIM_TOKEN: string;
17-
MCP_SESSION: DurableObjectNamespace<import("./src/server").McpSessionDO>;
17+
MCP_SESSION: DurableObjectNamespace<import("./src/server").McpSessionDOSqlite>;
1818
MARKETING: Fetcher /* executor-marketing */;
1919
}
2020
}

apps/cloud/wrangler.jsonc

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,21 @@
2525
],
2626
},
2727
// The MCP session DO moved to the Cloudflare Agents (`McpAgent`) base, which
28-
// stores state in SQLite. The original `McpSessionDO` was created with the
29-
// key-value backend (`new_classes`), and Cloudflare cannot convert a live class
30-
// to SQLite in place, nor delete a class while a binding still references it.
31-
// Session state is ephemeral, so v2 repoints the `MCP_SESSION` binding to a new
32-
// SQLite-backed class (`McpSessionDOSqlite`) and deletes the old KV `McpSessionDO`
33-
// (now unreferenced). The worker exports `McpSessionDOSqlite`, not `McpSessionDO`.
28+
// stores state in SQLite. The original `McpSessionDO` was created on the
29+
// key-value backend (`new_classes`) and cannot be converted in place. Cloudflare
30+
// also refuses to delete a class in the same deploy that moves its binding (it
31+
// validates the delete against the live binding), so v2 only CREATES the new
32+
// SQLite class `McpSessionDOSqlite` and the `MCP_SESSION` binding moves to it.
33+
// The old KV `McpSessionDO` is left orphaned (unbound, kept as a stub export in
34+
// server.ts so the migration stays valid); it can be deleted in a later deploy
35+
// now that nothing binds it. Session state is ephemeral, so nothing is lost.
3436
"migrations": [
3537
{
3638
"tag": "v1",
3739
"new_classes": ["McpSessionDO"],
3840
},
3941
{
4042
"tag": "v2",
41-
"deleted_classes": ["McpSessionDO"],
4243
"new_sqlite_classes": ["McpSessionDOSqlite"],
4344
},
4445
],

0 commit comments

Comments
 (0)