@dypai-ai/mcp 1.7.9 → 1.7.10

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.7.9",
3
+ "version": "1.7.10",
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",
@@ -10,6 +10,7 @@
10
10
  */
11
11
 
12
12
  import { proxyToolCall } from "../proxy.js"
13
+ import { fetchRemoteCredentials } from "./remote-metadata.js"
13
14
 
14
15
  async function execSql(projectId, sql) {
15
16
  // Bypass remote execute_sql auto-LIMIT 20 so describe counts match reality.
@@ -59,7 +60,7 @@ export const dypaiDescribeTool = {
59
60
  LEFT JOIN system.endpoints_group g ON g.id = e.group_id
60
61
  ORDER BY e.name
61
62
  `),
62
- execSql(project_id, "SELECT name, type FROM system.credentials ORDER BY name"),
63
+ fetchRemoteCredentials(project_id).catch(() => null),
63
64
  execSql(project_id, "SELECT name, description FROM system.roles ORDER BY name"),
64
65
  execSql(project_id, `
65
66
  SELECT id, name, public FROM storage.buckets ORDER BY name
@@ -17,6 +17,7 @@ import {
17
17
  runEffectiveWorkflows,
18
18
  } from "../../lib/effective-workflows-runner.js"
19
19
  import { findEndpointNameCollisions } from "./endpoint-names.js"
20
+ import { fetchRemoteCredentials } from "./remote-metadata.js"
20
21
 
21
22
  const ENDPOINT_NAME_RE = /^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$/
22
23
 
@@ -195,7 +196,7 @@ export async function fetchRemoteState(projectId) {
195
196
  FROM system.endpoints
196
197
  ORDER BY name
197
198
  `)
198
- const credentials = await execSql(projectId, "SELECT id, name, type FROM system.credentials")
199
+ const credentials = await fetchRemoteCredentials(projectId)
199
200
  const groups = await execSql(projectId, "SELECT id, name FROM system.endpoints_group")
200
201
 
201
202
  const mapsCtx = {
@@ -22,6 +22,7 @@ import { api } from "../../api.js"
22
22
  import { serializeEndpoint } from "./codec.js"
23
23
  import { dumpPublicSchema } from "./schema-dump.js"
24
24
  import { findEndpointNameCollisions, findLegacyAliasEndpointNames } from "./endpoint-names.js"
25
+ import { fetchRemoteCredentials } from "./remote-metadata.js"
25
26
  // Codegen was removed from v1 — the agent reads dypai/schema.sql + endpoint YAMLs
26
27
  // directly instead of relying on auto-generated TS types. The codegen.js file
27
28
  // still lives on disk in case we resurface it later with a leaner design.
@@ -817,7 +818,7 @@ export const dypaiPullTool = {
817
818
  FROM system.endpoints
818
819
  ORDER BY name
819
820
  `),
820
- execSql(project_id, "SELECT id, name, type FROM system.credentials"),
821
+ fetchRemoteCredentials(project_id),
821
822
  execSql(project_id, "SELECT id, name FROM system.endpoints_group"),
822
823
  dumpPublicSchema(project_id),
823
824
  // Dump the global node catalog (central control plane) in one call.
@@ -0,0 +1,40 @@
1
+ import { proxyToolCall } from "../proxy.js"
2
+
3
+ const CREDENTIAL_PAGE_SIZE = 50
4
+
5
+ /**
6
+ * Read credential metadata through the dedicated, secret-safe MCP tool.
7
+ *
8
+ * `execute_sql` intentionally rejects system.credentials because that table
9
+ * also stores encrypted secret material. Sync only needs id/name/type, which
10
+ * get_app_credentials exposes without returning any secret values.
11
+ */
12
+ export async function fetchRemoteCredentials(
13
+ projectId,
14
+ { call = proxyToolCall, pageSize = CREDENTIAL_PAGE_SIZE } = {},
15
+ ) {
16
+ const credentials = []
17
+ let offset = 0
18
+
19
+ while (true) {
20
+ const args = { limit: pageSize, offset }
21
+ if (projectId) args.project_id = projectId
22
+
23
+ const result = await call("get_app_credentials", args)
24
+ const page = Array.isArray(result?.credentials) ? result.credentials : []
25
+ credentials.push(...page)
26
+
27
+ const total = Number(result?.total)
28
+ if (
29
+ page.length === 0
30
+ || page.length < pageSize
31
+ || (Number.isFinite(total) && credentials.length >= total)
32
+ ) {
33
+ return credentials
34
+ }
35
+
36
+ offset += page.length
37
+ }
38
+ }
39
+
40
+ export const __testing = { CREDENTIAL_PAGE_SIZE }