Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion mcp-studio/server/db/postgres.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export async function runSQL<T = unknown>(
params: unknown[] = [],
): Promise<T[]> {
const response =
await env.MESH_REQUEST_CONTEXT.state.DATABASE.DATABASES_RUN_SQL({
await env.MESH_REQUEST_CONTEXT?.state?.DATABASE.DATABASES_RUN_SQL({
Copy link

@cubic-dev-ai cubic-dev-ai bot Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Incomplete optional chaining will still throw TypeError. If MESH_REQUEST_CONTEXT or state is nullish, ?.DATABASE evaluates to undefined, and calling .DATABASES_RUN_SQL() on undefined throws. Consider adding ?. before DATABASES_RUN_SQL and handling the undefined response, or throwing an explicit error early if the context is required.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At mcp-studio/server/db/postgres.ts, line 22:

<comment>Incomplete optional chaining will still throw TypeError. If `MESH_REQUEST_CONTEXT` or `state` is nullish, `?.DATABASE` evaluates to `undefined`, and calling `.DATABASES_RUN_SQL()` on `undefined` throws. Consider adding `?.` before `DATABASES_RUN_SQL` and handling the undefined response, or throwing an explicit error early if the context is required.</comment>

<file context>
@@ -19,7 +19,7 @@ export async function runSQL&lt;T = unknown&gt;(
 ): Promise&lt;T[]&gt; {
   const response =
-    await env.MESH_REQUEST_CONTEXT.state.DATABASE.DATABASES_RUN_SQL({
+    await env.MESH_REQUEST_CONTEXT?.state?.DATABASE.DATABASES_RUN_SQL({
       sql,
       params,
</file context>
Fix with Cubic

sql,
params,
});
Expand Down
6 changes: 3 additions & 3 deletions mcp-studio/server/db/queries/executions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export async function claimExecution(
// Atomic claim: only succeeds if status is 'enqueued'
// Join with workflow table to get steps and gateway_id
const result =
await env.MESH_REQUEST_CONTEXT.state.DATABASE.DATABASES_RUN_SQL({
await env.MESH_REQUEST_CONTEXT?.state?.DATABASE.DATABASES_RUN_SQL({
sql: `
UPDATE workflow_execution
SET
Expand Down Expand Up @@ -96,7 +96,7 @@ export async function getExecution(
id: string,
): Promise<WorkflowExecution | null> {
const result =
await env.MESH_REQUEST_CONTEXT.state.DATABASE.DATABASES_RUN_SQL({
await env.MESH_REQUEST_CONTEXT?.state?.DATABASE.DATABASES_RUN_SQL({
sql: "SELECT * FROM workflow_execution WHERE id = ? LIMIT 1",
params: [id],
});
Expand Down Expand Up @@ -332,7 +332,7 @@ export async function cancelExecution(

// Only cancel if currently enqueued or running
const result =
await env.MESH_REQUEST_CONTEXT.state.DATABASE.DATABASES_RUN_SQL({
await env.MESH_REQUEST_CONTEXT?.state?.DATABASE.DATABASES_RUN_SQL({
sql: `
UPDATE workflow_execution
SET
Expand Down
2 changes: 1 addition & 1 deletion mcp-studio/server/db/schemas/agents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export async function runSQL<T = unknown>(
return p;
});
const response =
await env.MESH_REQUEST_CONTEXT.state.DATABASE.DATABASES_RUN_SQL({
await env.MESH_REQUEST_CONTEXT?.state?.DATABASE.DATABASES_RUN_SQL({
sql,
params: sanitizedParams,
});
Expand Down
4 changes: 2 additions & 2 deletions mcp-studio/server/engine/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export async function getPendingEvents(
): Promise<WorkflowEvent[]> {
const now = Date.now();
const result =
await env.MESH_REQUEST_CONTEXT.state.DATABASE.DATABASES_RUN_SQL({
await env.MESH_REQUEST_CONTEXT?.state?.DATABASE.DATABASES_RUN_SQL({
Copy link

@cubic-dev-ai cubic-dev-ai bot Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Incomplete optional chaining will crash if state is nullish. When state?.DATABASE returns undefined, calling .DATABASES_RUN_SQL() throws a TypeError. Either add ?. before DATABASES_RUN_SQL and handle the undefined result, or throw an explicit error early if the database connection is unavailable.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At mcp-studio/server/engine/events.ts, line 19:

<comment>Incomplete optional chaining will crash if `state` is nullish. When `state?.DATABASE` returns `undefined`, calling `.DATABASES_RUN_SQL()` throws a TypeError. Either add `?.` before `DATABASES_RUN_SQL` and handle the undefined result, or throw an explicit error early if the database connection is unavailable.</comment>

<file context>
@@ -16,7 +16,7 @@ export async function getPendingEvents(
   const now = Date.now();
   const result =
-    await env.MESH_REQUEST_CONTEXT.state.DATABASE.DATABASES_RUN_SQL({
+    await env.MESH_REQUEST_CONTEXT?.state?.DATABASE.DATABASES_RUN_SQL({
       sql: `SELECT * FROM workflow_event WHERE execution_id = ? AND consumed_at IS NULL
           AND (visible_at IS NULL OR visible_at &lt;= ?) ${type ? &quot;AND type = ?&quot; : &quot;&quot;}
</file context>
Fix with Cubic

sql: `SELECT * FROM workflow_event WHERE execution_id = ? AND consumed_at IS NULL
AND (visible_at IS NULL OR visible_at <= ?) ${type ? "AND type = ?" : ""}
ORDER BY visible_at ASC NULLS FIRST, created_at ASC`,
Expand Down Expand Up @@ -48,7 +48,7 @@ export async function consumeSignal(
signalId: string,
): Promise<boolean> {
const result =
await env.MESH_REQUEST_CONTEXT.state.DATABASE.DATABASES_RUN_SQL({
await env.MESH_REQUEST_CONTEXT?.state?.DATABASE.DATABASES_RUN_SQL({
sql: `UPDATE workflow_event SET consumed_at = ? WHERE id = ? AND consumed_at IS NULL RETURNING id`,
params: [Date.now(), signalId],
});
Expand Down
2 changes: 1 addition & 1 deletion mcp-studio/server/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ interface StoredPrompt {
* Load prompts from the database
*/
async function loadPrompts(env: Env): Promise<StoredPrompt[]> {
if (!env.MESH_REQUEST_CONTEXT.state.DATABASE) {
if (!env.MESH_REQUEST_CONTEXT?.state?.DATABASE) {
return [];
}

Expand Down
12 changes: 6 additions & 6 deletions mcp-studio/server/tools/assistant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ import {
import { createPrivateTool } from "@decocms/runtime/tools";
import type { z } from "zod";
import { runSQL } from "../db/postgres.ts";
import type { Env } from "../types/env.ts";
import {
buildOrderByClause,
buildWhereClause,
type OrderByExpression,
type WhereExpression,
} from "../db/schemas/query-builder.ts";
import type { Env } from "../types/env.ts";

// Extract binding schemas
const LIST_BINDING = ASSISTANTS_BINDING.find(
Expand Down Expand Up @@ -151,7 +151,7 @@ export const createListTool = (env: Env) =>
outputSchema: LIST_BINDING.outputSchema,
execute: async ({ context }) => {
// If DATABASE is not available, return empty list
if (!env.MESH_REQUEST_CONTEXT.state.DATABASE) {
if (!env.MESH_REQUEST_CONTEXT?.state?.DATABASE) {
return {
items: [],
totalCount: 0,
Expand Down Expand Up @@ -210,7 +210,7 @@ export const createGetTool = (env: Env) =>
inputSchema: CollectionGetInputSchema,
outputSchema: createCollectionGetOutputSchema(AssistantSchema),
execute: async ({ context }) => {
if (!env.MESH_REQUEST_CONTEXT.state.DATABASE) {
if (!env.MESH_REQUEST_CONTEXT?.state?.DATABASE) {
return { item: null };
}

Expand Down Expand Up @@ -246,7 +246,7 @@ export const createInsertTool = (env: Env) =>
}: {
context: z.infer<typeof CREATE_INPUT_SCHEMA>;
}) => {
if (!env.MESH_REQUEST_CONTEXT.state.DATABASE) {
if (!env.MESH_REQUEST_CONTEXT?.state?.DATABASE) {
throw new Error("DATABASE not configured for mcp-studio");
}

Expand Down Expand Up @@ -318,7 +318,7 @@ export const createUpdateTool = (env: Env) =>
}: {
context: z.infer<typeof UPDATE_INPUT_SCHEMA>;
}) => {
if (!env.MESH_REQUEST_CONTEXT.state.DATABASE) {
if (!env.MESH_REQUEST_CONTEXT?.state?.DATABASE) {
throw new Error("DATABASE not configured for mcp-studio");
}

Expand Down Expand Up @@ -397,7 +397,7 @@ export const createDeleteTool = (env: Env) =>
}: {
context: z.infer<typeof CollectionDeleteInputSchema>;
}) => {
if (!env.MESH_REQUEST_CONTEXT.state.DATABASE) {
if (!env.MESH_REQUEST_CONTEXT?.state?.DATABASE) {
throw new Error("DATABASE not configured for mcp-studio");
}

Expand Down
8 changes: 4 additions & 4 deletions mcp-studio/server/tools/workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,14 @@ export const createListTool = (env: Env) =>
`;
Copy link

@cubic-dev-ai cubic-dev-ai bot Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Incomplete optional chaining creates a false sense of safety. If MESH_REQUEST_CONTEXT or state is null/undefined, the chain returns undefined, and calling .DATABASES_RUN_SQL() on it will throw a TypeError. Either complete the chain (?.DATABASE?.DATABASES_RUN_SQL?.) or add an early guard clause to throw a meaningful error.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At mcp-studio/server/tools/workflow.ts, line 117:

<comment>Incomplete optional chaining creates a false sense of safety. If `MESH_REQUEST_CONTEXT` or `state` is null/undefined, the chain returns `undefined`, and calling `.DATABASES_RUN_SQL()` on it will throw a `TypeError`. Either complete the chain (`?.DATABASE?.DATABASES_RUN_SQL?.`) or add an early guard clause to throw a meaningful error.</comment>

<file context>
@@ -114,14 +114,14 @@ export const createListTool = (env: Env) =&gt;
 
       const itemsResult: any =
-        await env.MESH_REQUEST_CONTEXT.state.DATABASE.DATABASES_RUN_SQL({
+        await env.MESH_REQUEST_CONTEXT?.state?.DATABASE.DATABASES_RUN_SQL({
           sql,
           params: [...params, limit, offset],
</file context>
Fix with Cubic


const itemsResult: any =
await env.MESH_REQUEST_CONTEXT.state.DATABASE.DATABASES_RUN_SQL({
await env.MESH_REQUEST_CONTEXT?.state?.DATABASE.DATABASES_RUN_SQL({
sql,
params: [...params, limit, offset],
});

const countQuery = `SELECT COUNT(*) as count FROM workflow_collection ${whereClause}`;
const countResult =
await env.MESH_REQUEST_CONTEXT.state.DATABASE.DATABASES_RUN_SQL({
await env.MESH_REQUEST_CONTEXT?.state?.DATABASE.DATABASES_RUN_SQL({
sql: countQuery,
params,
});
Expand All @@ -147,7 +147,7 @@ export async function getWorkflowCollection(
id: string,
): Promise<Workflow | null> {
const result =
await env.MESH_REQUEST_CONTEXT.state.DATABASE.DATABASES_RUN_SQL({
await env.MESH_REQUEST_CONTEXT?.state?.DATABASE.DATABASES_RUN_SQL({
sql: "SELECT * FROM workflow_collection WHERE id = ? LIMIT 1",
params: [id],
});
Expand Down Expand Up @@ -313,7 +313,7 @@ y UPDATE workflow_collection
`;

const result =
await env.MESH_REQUEST_CONTEXT.state.DATABASE.DATABASES_RUN_SQL({
await env.MESH_REQUEST_CONTEXT?.state?.DATABASE.DATABASES_RUN_SQL({
sql,
params,
});
Expand Down
Loading