@ziggs-ai/ziggs-mcp 0.36.4 → 0.36.6

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.
@@ -22,6 +22,15 @@ export interface ToolErrorShape {
22
22
  * the same shape an open's action recovery has.
23
23
  */
24
24
  recovery?: Record<string, unknown>;
25
+ /** hidden | unreadable, the same outcome open and access_explain give. */
26
+ outcome?: string;
27
+ /** The resource the outcome is about. */
28
+ ref?: {
29
+ kind: string;
30
+ id: string;
31
+ };
32
+ /** For an unreadable resource: the request to make, as open lists it. */
33
+ actions?: unknown[];
25
34
  }
26
35
  /**
27
36
  * Classify a thrown client error (or a plain string this layer raised) into a
@@ -35,6 +44,26 @@ export declare function classifyToolError(input: unknown): ToolErrorShape;
35
44
  * HTTP status and server `code` that decide the hint.
36
45
  * A plain string is still accepted for refusals this layer raises on its own.
37
46
  */
47
+ /** A refused read, answered as open would: its outcome, and any request to make. */
48
+ export declare function refusalError(refusal: {
49
+ code: string;
50
+ message: string;
51
+ outcome?: string;
52
+ ref?: {
53
+ kind: string;
54
+ id: string;
55
+ };
56
+ actions?: unknown[];
57
+ }): {
58
+ structuredContent: {
59
+ error: ToolErrorShape;
60
+ };
61
+ content: {
62
+ type: "text";
63
+ text: string;
64
+ }[];
65
+ isError: boolean;
66
+ };
38
67
  export declare function toolError(input: unknown): {
39
68
  structuredContent: {
40
69
  error: ToolErrorShape;
package/dist/toolError.js CHANGED
@@ -5,6 +5,12 @@
5
5
  * `code`, `body` / `message`). No client-prefix strip, no HTTP-status regex,
6
6
  * no re-parsing a JSON body that was concatenated into the message string.
7
7
  */
8
+ /**
9
+ * The shared refusal vocabulary every read tool answers in (hidden,
10
+ * unreadable, invalid input), so an assistant can branch on the code instead
11
+ * of parsing each tool's sentence.
12
+ */
13
+ const SHARED_REFUSALS = new Set(['RESOURCE_HIDDEN', 'RESOURCE_UNREADABLE', 'INVALID_INPUT']);
8
14
  const SCOPE_DENIED_HINT = 'For missing access to a returned artifact, chat, agreement, or task, use ' +
9
15
  'ziggs_access_request with that original resource id and your purpose. It creates ' +
10
16
  'a pending access approval agreement; it grants no access. After approval, ' +
@@ -127,6 +133,9 @@ export function classifyToolError(input) {
127
133
  }
128
134
  function classify(input) {
129
135
  const { message, status, code: machineCode } = thrownFields(input);
136
+ if (machineCode && SHARED_REFUSALS.has(machineCode)) {
137
+ return { code: machineCode, message };
138
+ }
130
139
  if (machineCode === 'AGENT_LACKS_HUMAN_AUTHORITY') {
131
140
  return {
132
141
  code: 'AGENT_LACKS_HUMAN_AUTHORITY',
@@ -181,6 +190,17 @@ function classify(input) {
181
190
  * HTTP status and server `code` that decide the hint.
182
191
  * A plain string is still accepted for refusals this layer raises on its own.
183
192
  */
193
+ /** A refused read, answered as open would: its outcome, and any request to make. */
194
+ export function refusalError(refusal) {
195
+ const shape = { ...refusal };
196
+ return {
197
+ structuredContent: { error: shape },
198
+ content: [
199
+ { type: 'text', text: JSON.stringify({ error: shape }, null, 2) },
200
+ ],
201
+ isError: true,
202
+ };
203
+ }
184
204
  export function toolError(input) {
185
205
  const shape = classifyToolError(input);
186
206
  return {
package/dist/tools.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { isDirectorySurface } from './directorySurface.js';
2
2
  import { randomUUID } from 'node:crypto';
3
3
  import { z } from 'zod';
4
- import { presentResourceActions, getAgreement, getMyAgreements, listMyChats, respondToAgreement, revokeAgreement, counterAgreement, fulfillAgreement, sendChatMessage, ConnectionsClient, ContextReadClient, GrantsClient, InboxClient, createTask, updateTaskState, acknowledgeTaskControl, replaceTaskPlan, updateTaskPlanSteps, listTasks, getTask, getBackendUrl, fetchMyOrgs, fetchSessionAccess, isMcpOAuthDelegateSession, GRANTS_CAPABILITIES, AGREEMENT_VERB_CAPABILITIES, LISTING_DOOR_CAPABILITIES, CONTEXT_GRANT_SCOPE_KINDS, contextReadCapability, openCapability, accessExplainCapability, contextExpandReachCapability, contextDiscoverGrantableCapability, recordArtifactCapability, listArtifactsCapability, findArtifactsCapability, shareArtifactCapability, attachArtifactCapability, uploadArtifactUrlCapability, completeArtifactFileCapability, downloadArtifactCapability, openConversationCapability, connectionProxyCapability, requestConnectionCapability, agreementClaimCapability, agreementSubcontractCapability, listTasksCapability, cancelTaskCapability, marketplaceViewCapability, parseListFields, pickListedRows, projectChatListRows, sessionOrientation, presentSendResult, presentTaskOutcome, } from '@ziggs-ai/api-client';
4
+ import { presentResourceActions, getAgreement, getMyAgreements, listMyChats, respondToAgreement, revokeAgreement, counterAgreement, fulfillAgreement, sendChatMessage, ConnectionsClient, ContextReadClient, GrantsClient, InboxClient, createTask, updateTaskState, acknowledgeTaskControl, replaceTaskPlan, updateTaskPlanSteps, listTasks, getTask, getBackendUrl, fetchMyOrgs, fetchSessionAccess, isMcpOAuthDelegateSession, GRANTS_CAPABILITIES, AGREEMENT_VERB_CAPABILITIES, LISTING_DOOR_CAPABILITIES, CONTEXT_GRANT_SCOPE_KINDS, contextReadCapability, openCapability, accessExplainCapability, contextExpandReachCapability, contextDiscoverGrantableCapability, recordArtifactCapability, listArtifactsCapability, findArtifactsCapability, shareArtifactCapability, attachArtifactCapability, uploadArtifactUrlCapability, completeArtifactFileCapability, downloadArtifactCapability, openConversationCapability, connectionProxyCapability, requestConnectionCapability, agreementClaimCapability, agreementSubcontractCapability, listTasksCapability, cancelTaskCapability, marketplaceViewCapability, parseListFields, pickListedRows, projectChatListRows, sessionOrientation, presentSendResult, presentTaskOutcome, explainRefusedRead, RESOURCE_HIDDEN_MESSAGE, } from '@ziggs-ai/api-client';
5
5
  import { decodeOperatorKeyClaims } from './operatorKey.js';
6
6
  import { registerTrustTools } from './trustTools.js';
7
7
  import { registerPaymentTools } from './paymentTools.js';
@@ -12,7 +12,7 @@ import { agreementAppUrl, filterTasksForDelegate, formatPendingDecisionsPayload,
12
12
  import { resolveMcpConnectionTarget, withMcpGatewayClient, } from './mcpConnectionTools.js';
13
13
  import { readOnly, write, destructive } from './toolAnnotations.js';
14
14
  import { registerStrictTool } from './strictParams.js';
15
- import { toolError } from './toolError.js';
15
+ import { refusalError, toolError } from './toolError.js';
16
16
  import { registerCapability, registerCapabilities, textResult, } from './capabilityAdapter.js';
17
17
  // the strict artifact write (fail loudly, return the artifactId)
18
18
  // moved into ArtifactsClient.writeStrict, shared with the SDK's artifact_record.
@@ -245,7 +245,33 @@ function inboxFor(creds) {
245
245
  sessionName: creds.sessionName,
246
246
  });
247
247
  }
248
+ /** A get the server refused for reach (403) or existence (404). */
249
+ function isReadRefusal(e) {
250
+ const status = e?.status;
251
+ return status === 403 || status === 404;
252
+ }
248
253
  export function registerZiggsTools(server, creds, cfg) {
254
+ // A refused get answers as open would: the server's one judgement of
255
+ // hidden or unreadable, and for unreadable the request to make. When that
256
+ // judgement cannot be had, the original refusal stands (or, for a get that
257
+ // returned nothing at all, hidden).
258
+ const refusedRead = async (kind, id, cause) => {
259
+ const refusal = await explainRefusedRead(kind, id, {
260
+ creds,
261
+ webUrl: cfg.ZIGGS_WEB_URL,
262
+ surface: 'mcp',
263
+ });
264
+ if (refusal)
265
+ return refusalError(refusal);
266
+ return cause
267
+ ? toolError(cause)
268
+ : refusalError({
269
+ code: 'RESOURCE_HIDDEN',
270
+ message: RESOURCE_HIDDEN_MESSAGE,
271
+ outcome: 'hidden',
272
+ ref: { kind, id },
273
+ });
274
+ };
249
275
  // A binding check and nothing else. This used to also report the
250
276
  // pending/active counts and point at a separate decisions tool for the card,
251
277
  // which is how a session start came to cost three calls that each said some
@@ -359,10 +385,12 @@ export function registerZiggsTools(server, creds, cfg) {
359
385
  try {
360
386
  const agreement = await getAgreement(agreementId, creds);
361
387
  if (!agreement)
362
- return toolError(`Agreement not found: ${agreementId}`);
388
+ return refusedRead('agreement', agreementId);
363
389
  return textResult({ agreement });
364
390
  }
365
391
  catch (e) {
392
+ if (isReadRefusal(e))
393
+ return refusedRead('agreement', agreementId, e);
366
394
  return toolError(e);
367
395
  }
368
396
  });
@@ -1027,10 +1055,12 @@ export function registerZiggsTools(server, creds, cfg) {
1027
1055
  try {
1028
1056
  const task = await getTask(taskId, creds);
1029
1057
  if (!task)
1030
- return toolError(`Task not found: ${taskId}`);
1058
+ return refusedRead('task', taskId);
1031
1059
  return textResult({ task });
1032
1060
  }
1033
1061
  catch (e) {
1062
+ if (isReadRefusal(e))
1063
+ return refusedRead('task', taskId, e);
1034
1064
  return toolError(e);
1035
1065
  }
1036
1066
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ziggs-ai/ziggs-mcp",
3
- "version": "0.36.4",
3
+ "version": "0.36.6",
4
4
  "description": "MCP server for Claude Code, Cursor, and other MCP hosts — act as your Ziggs delegate agent",
5
5
  "type": "module",
6
6
  "bin": {
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@modelcontextprotocol/sdk": "^1.29.0",
43
- "@ziggs-ai/api-client": "0.36.2",
43
+ "@ziggs-ai/api-client": "0.36.4",
44
44
  "dotenv": "^16.6.1",
45
45
  "zod": "^3.24.2",
46
46
  "zod-to-json-schema": "^3.25.1"