History

cloud/local/examples: thread per-user ScopeStack through HTTP + MCP

- cloud: resolves userId from the authenticated session and builds a [userOrgScope, orgScope] stack via createScopedExecutor(userId, orgId, orgName). userId threaded through execution-stack, mcp-session, and MCP dispatch init. - cloud env refactor: deletes the lazy Proxy apps/cloud/src/env.ts in favor of cloudflare:workers env imported at call sites; adds env-augment.d.ts to type secrets not present in generated wrangler types. - cloud/server.ts: env-guarded OTEL wiring (skips instrument() when AXIOM_TOKEN absent); captures rawFetch before instrument() mutates it so dev requests still land on the Hono app. - cloud/services/db.ts: prefers DATABASE_URL over the hyperdrive proxy so local dev works without the tunnel. - vite.config.ts: devCrashGuard plugin that prints uncaught Worker errors with a stable exit. - hosts/mcp: optional debug flag surfaces verbose session logging, wired up from cloud mcp-session. - local/examples/marketing: migrated to scopes: [scope].

Rhys Sullivan committed 6 months ago

Commit d4e311e1 parent 427699c25 files · +320 −174Browse files

Showing the changes to apps/local/src (2 of 25 files). Show all

Unified · Split

2 files
  1. apps/local/src/server/config-sync.ts +9 −0
  2. apps/local/src/server/executor.ts +1 −1
apps/local/src/server/config-sync.ts+9−0
@@ -84,10 +84,16 @@ const addSourceFromConfig = ( · 83 unmodified lines
8484 executor: LocalExecutor,
8585 source: SourceConfig,
8686 ): Effect.Effect<void, unknown> => {
87+ // `executor.jsonc` is a single-scope artifact today — the file isn't
88+ // aware of per-user tenancy. Pin replayed sources to the outermost
89+ // scope so a future `[user, org]` stack still sees them via org
90+ // fall-through.
91+ const scope = executor.scopes.at(-1)!.id as string;
8792 switch (source.kind) {
8893 case "openapi":
8994 return executor.openapi.addSpec({
9095 spec: source.spec,
96+ scope,
9197 baseUrl: source.baseUrl,
9298 namespace: source.namespace,
9399 headers: translateHeaders(source.headers),
@@ -96,6 +102,7 @@ const addSourceFromConfig = ( · 2 unmodified lines
96102 case "graphql":
97103 return executor.graphql.addSource({
98104 endpoint: source.endpoint,
105+ scope,
99106 namespace: source.namespace,
100107 headers: translateHeaders(source.headers) as Record<string, string> | undefined,
101108 }).pipe(Effect.asVoid);
@@ -104,6 +111,7 @@ const addSourceFromConfig = ( · 2 unmodified lines
104111 if (source.transport === "stdio") {
105112 return executor.mcp.addSource({
106113 transport: "stdio",
114+ scope,
107115 name: source.name,
108116 command: source.command,
109117 args: source.args ? [...source.args] : undefined,
@@ -114,6 +122,7 @@ const addSourceFromConfig = ( · 4 unmodified lines
114122 }
115123 return executor.mcp.addSource({
116124 transport: "remote",
125+ scope,
117126 name: source.name,
118127 endpoint: source.endpoint,
119128 remoteTransport: source.remoteTransport,
apps/local/src/server/executor.ts+1−1
@@ -154,7 +154,7 @@ const createLocalExecutorLayer = () => { · 153 unmodified lines
154154 });
155155
156156 const executor = yield* createExecutor({
157− scope,
157+ scopes: [scope],
158158 adapter,
159159 blobs,
160160 plugins,