@dypai-ai/mcp 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dypai-ai/mcp",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "DYPAI MCP Server — AI agent toolkit for building and deploying full-stack apps",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/index.js CHANGED
@@ -817,7 +817,7 @@ async function handleRequest(msg) {
817
817
  return makeResponse(id, {
818
818
  protocolVersion: "2024-11-05",
819
819
  capabilities: { tools: {} },
820
- serverInfo: { name: "dypai", version: "1.3.0" },
820
+ serverInfo: { name: "dypai", version: "1.3.1" },
821
821
  instructions: SERVER_INSTRUCTIONS,
822
822
  })
823
823
  }
@@ -12,7 +12,10 @@
12
12
  import { proxyToolCall } from "../proxy.js"
13
13
 
14
14
  async function execSql(projectId, sql) {
15
- const args = projectId ? { project_id: projectId, sql } : { sql }
15
+ // Bypass remote execute_sql auto-LIMIT 20 so describe counts match reality.
16
+ const hasLimit = /\bLIMIT\b/i.test(sql)
17
+ const finalSql = hasLimit ? sql : `${sql.replace(/;?\s*$/, "")} LIMIT 100000`
18
+ const args = projectId ? { project_id: projectId, sql: finalSql } : { sql: finalSql }
16
19
  const result = await proxyToolCall("execute_sql", args)
17
20
  if (result?.error) return null
18
21
  if (!result?.rows) return null
@@ -54,7 +57,6 @@ export const dypaiDescribeTool = {
54
57
  jsonb_array_length(e.workflow_code->'nodes') AS node_count
55
58
  FROM system.endpoints e
56
59
  LEFT JOIN system.endpoints_group g ON g.id = e.group_id
57
- WHERE e.is_active = true
58
60
  ORDER BY e.name
59
61
  `),
60
62
  execSql(project_id, "SELECT name, type FROM system.credentials ORDER BY name"),
@@ -17,7 +17,13 @@ import { deserializeEndpoint, serializeEndpoint } from "./codec.js"
17
17
  // ─── Remote ────────────────────────────────────────────────────────────────
18
18
 
19
19
  async function execSql(projectId, sql) {
20
- const args = projectId ? { project_id: projectId, sql } : { sql }
20
+ // Bypass the remote execute_sql safety that injects `LIMIT 20` when no LIMIT
21
+ // is present. Planner needs the FULL endpoint/credential/group lists to
22
+ // compute an accurate diff — truncation here would mean invisible deletes
23
+ // (local thinks "remote has only X" when it actually has X+N).
24
+ const hasLimit = /\bLIMIT\b/i.test(sql)
25
+ const finalSql = hasLimit ? sql : `${sql.replace(/;?\s*$/, "")} LIMIT 100000`
26
+ const args = projectId ? { project_id: projectId, sql: finalSql } : { sql: finalSql }
21
27
  const result = await proxyToolCall("execute_sql", args)
22
28
  if (result?.error) throw new Error(`SQL error: ${result.error}`)
23
29
  if (!result?.rows) throw new Error(`Unexpected SQL response: ${JSON.stringify(result).slice(0, 300)}`)
@@ -116,9 +122,8 @@ export async function fetchRemoteState(projectId) {
116
122
  const [endpoints, credentials, groups] = await Promise.all([
117
123
  execSql(projectId, `
118
124
  SELECT id, name, method, description, workflow_code, input, output,
119
- allowed_roles, is_tool, tool_description, group_id, updated_at
125
+ allowed_roles, is_tool, tool_description, group_id, is_active, updated_at
120
126
  FROM system.endpoints
121
- WHERE is_active = true
122
127
  ORDER BY name
123
128
  `),
124
129
  execSql(projectId, "SELECT id, name, type FROM system.credentials"),
@@ -441,7 +441,15 @@ workflow:
441
441
  `
442
442
 
443
443
  async function execSql(projectId, sql) {
444
- const args = projectId ? { project_id: projectId, sql } : { sql }
444
+ // The remote `execute_sql` silently injects `LIMIT 20` whenever a query has no
445
+ // LIMIT of its own — intended as a guard against ad-hoc queries returning
446
+ // gigantic result sets. For pull we want the COMPLETE lists of endpoints,
447
+ // credentials, groups, realtime policies, etc. Without an explicit LIMIT
448
+ // here, a project with >20 of any resource would silently lose rows.
449
+ // We append a generous cap (100k) only when the caller didn't specify one.
450
+ const hasLimit = /\bLIMIT\b/i.test(sql)
451
+ const finalSql = hasLimit ? sql : `${sql.replace(/;?\s*$/, "")} LIMIT 100000`
452
+ const args = projectId ? { project_id: projectId, sql: finalSql } : { sql: finalSql }
445
453
  const result = await proxyToolCall("execute_sql", args)
446
454
  if (result?.error) throw new Error(`SQL error: ${result.error}`)
447
455
  if (!result?.rows) {
@@ -553,9 +561,8 @@ export const dypaiPullTool = {
553
561
  const [endpoints, credentials, groups, schemaSql, nodeCatalogResult, realtimePolicies] = await Promise.all([
554
562
  execSql(project_id, `
555
563
  SELECT id, name, method, description, workflow_code, input, output,
556
- allowed_roles, is_tool, tool_description, group_id, updated_at
564
+ allowed_roles, is_tool, tool_description, group_id, is_active, updated_at
557
565
  FROM system.endpoints
558
- WHERE is_active = true
559
566
  ORDER BY name
560
567
  `),
561
568
  execSql(project_id, "SELECT id, name, type FROM system.credentials"),
@@ -650,7 +657,22 @@ export const dypaiPullTool = {
650
657
  const relPath = groupName
651
658
  ? `endpoints/${groupName}/${row.name}.yaml`
652
659
  : `endpoints/${row.name}.yaml`
653
- await writeFileEnsured(join(outDir, relPath), renderYaml(doc))
660
+
661
+ // Inactive endpoints ARE pulled (user needs to see them), but flagged
662
+ // with a visible header so the agent/user knows the endpoint won't
663
+ // execute until re-enabled in the dashboard. `is_active` isn't
664
+ // serialized into the YAML itself — push only updates content, never
665
+ // the active flag, so editing + pushing an inactive endpoint keeps it
666
+ // inactive (safe default).
667
+ const yamlBody = renderYaml(doc)
668
+ const content = row.is_active === false
669
+ ? "# ⚠️ INACTIVE on the engine — this endpoint will NOT execute until re-enabled in the dashboard.\n" +
670
+ "# Edits applied via `dypai_push` are still saved, but the endpoint stays paused.\n" +
671
+ "# To reactivate: go to the project dashboard → Endpoints → toggle this one back on.\n\n" +
672
+ yamlBody
673
+ : yamlBody
674
+
675
+ await writeFileEnsured(join(outDir, relPath), content)
654
676
  filesWritten.push(relPath)
655
677
  } catch (e) {
656
678
  errors.push({ endpoint: row.name, error: e.message })
@@ -730,6 +752,9 @@ export const dypaiPullTool = {
730
752
  const toolEndpoints = (endpoints || [])
731
753
  .filter(e => e.is_tool)
732
754
  .map(e => ({ name: e.name, description: e.tool_description || null }))
755
+ const inactiveEndpoints = (endpoints || [])
756
+ .filter(e => e.is_active === false)
757
+ .map(e => e.name)
733
758
 
734
759
  const overview = {
735
760
  project: projectInfo ? {
@@ -739,9 +764,12 @@ export const dypaiPullTool = {
739
764
  } : { id: resolvedProjectId || "(from token)" },
740
765
  endpoints: {
741
766
  total: (endpoints || []).length,
767
+ active: (endpoints || []).filter(e => e.is_active !== false).length,
768
+ inactive: inactiveEndpoints.length,
742
769
  groups: Object.keys(byGroup).filter(g => g !== "(no group)").sort(),
743
770
  by_group: byGroup,
744
771
  tool_endpoints: toolEndpoints,
772
+ inactive_endpoints: inactiveEndpoints.length > 0 ? inactiveEndpoints : undefined,
745
773
  },
746
774
  credentials: (credentials || []).map(c => ({ name: c.name, type: c.type })),
747
775
  realtime_policies: (realtimePolicies || []).length,
@@ -7,7 +7,13 @@
7
7
  import { proxyToolCall } from "../proxy.js"
8
8
 
9
9
  async function execSql(projectId, sql) {
10
- const args = projectId ? { project_id: projectId, sql } : { sql }
10
+ // Bypass remote execute_sql auto-LIMIT 20 so the schema dump is complete.
11
+ // Without this, a project with >20 columns across public.* (very normal)
12
+ // would produce a truncated schema.sql silently — breaks the validator and
13
+ // any agent that reads schema.sql before writing SQL.
14
+ const hasLimit = /\bLIMIT\b/i.test(sql)
15
+ const finalSql = hasLimit ? sql : `${sql.replace(/;?\s*$/, "")} LIMIT 100000`
16
+ const args = projectId ? { project_id: projectId, sql: finalSql } : { sql: finalSql }
11
17
  const result = await proxyToolCall("execute_sql", args)
12
18
  if (result?.error) throw new Error(`SQL error: ${result.error}`)
13
19
  if (!result?.rows) throw new Error(`Unexpected SQL response: ${JSON.stringify(result).slice(0, 300)}`)