@dypai-ai/mcp 1.2.2 → 1.2.3

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.2.2",
3
+ "version": "1.2.3",
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",
@@ -129,6 +129,15 @@ export async function proxyToolCall(toolName, args) {
129
129
  if (typeof parsed === "string" && /^(Error:|Input validation error:|You don't have)/i.test(parsed)) {
130
130
  throw new Error(parsed)
131
131
  }
132
+ // Other remote errors come as a JSON object with success:false but no isError
133
+ // flag. The push pipeline was treating these as successes — promote them to
134
+ // throws here so the caller's try/catch sees them.
135
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
136
+ if (parsed.success === false || parsed.ok === false) {
137
+ const msg = parsed.error || parsed.message || parsed.detail || JSON.stringify(parsed).slice(0, 300)
138
+ throw new Error(typeof msg === "string" ? msg : JSON.stringify(msg))
139
+ }
140
+ }
132
141
  return parsed
133
142
  }
134
143
  return response.result
@@ -61,26 +61,52 @@ function endpointPayload(row) {
61
61
  return p
62
62
  }
63
63
 
64
+ /**
65
+ * Treat a remote tool response as a definite success only when it has at
66
+ * least one of the markers we expect from a real mutation. Anything else
67
+ * (empty object, error string masquerading as data, missing id) becomes
68
+ * an error so the push doesn't lie to the agent.
69
+ */
70
+ function assertMutationOK(result, op, name) {
71
+ if (!result || typeof result !== "object") {
72
+ throw new Error(`${op} ${name}: empty response from remote (got ${JSON.stringify(result).slice(0, 120)})`)
73
+ }
74
+ if (result.error) {
75
+ throw new Error(`${op} ${name}: ${typeof result.error === "string" ? result.error : JSON.stringify(result.error)}`)
76
+ }
77
+ // Successful create returns { id, name } or { ok: true }; update/delete return
78
+ // { message } or { ok: true }. If none of these markers are present the call
79
+ // probably failed silently.
80
+ const hasMarker = result.id || result.ok === true || result.message || result.endpoint_id || result.success === true
81
+ if (!hasMarker) {
82
+ throw new Error(`${op} ${name}: response missing success markers — ${JSON.stringify(result).slice(0, 200)}`)
83
+ }
84
+ return result
85
+ }
86
+
64
87
  async function applyCreate(canonicalRow, projectId) {
65
- return proxyToolCall("create_endpoint", {
88
+ const res = await proxyToolCall("create_endpoint", {
66
89
  ...(projectId ? { project_id: projectId } : {}),
67
90
  ...endpointPayload(canonicalRow),
68
91
  })
92
+ return assertMutationOK(res, "create", canonicalRow.name)
69
93
  }
70
94
 
71
95
  async function applyUpdate(canonicalRow, endpointId, projectId) {
72
- return proxyToolCall("update_endpoint", {
96
+ const res = await proxyToolCall("update_endpoint", {
73
97
  ...(projectId ? { project_id: projectId } : {}),
74
98
  endpoint_id: endpointId,
75
99
  updates: endpointPayload(canonicalRow),
76
100
  })
101
+ return assertMutationOK(res, "update", canonicalRow.name)
77
102
  }
78
103
 
79
104
  async function applyDelete(endpointId, projectId) {
80
- return proxyToolCall("delete_endpoint", {
105
+ const res = await proxyToolCall("delete_endpoint", {
81
106
  ...(projectId ? { project_id: projectId } : {}),
82
107
  endpoint_id: endpointId,
83
108
  })
109
+ return assertMutationOK(res, "delete", endpointId)
84
110
  }
85
111
 
86
112
  // ─── Realtime policies sync ────────────────────────────────────────────────