@ziggs-ai/ziggs-mcp 0.1.31 → 0.1.33

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/README.md CHANGED
@@ -206,7 +206,7 @@ OP_KEY_A=... AGENT_A=... USER_B=... OP_KEY_B=... AGENT_B=... \
206
206
  | `ziggs_revoke_link` | `DELETE /agreements/:agreementId` (see also `ziggs_revoke_agreement`) |
207
207
  | `ziggs_revoke_agreement` | `DELETE /agreements/:id` — any agreement (hire/service/quest/link) |
208
208
  | `ziggs_smoke_impersonation` | [Internal/debug] connectivity check — only when `ZIGGS_MCP_DEBUG=1`; not part of normal delegate workflow |
209
- | `ziggs_get_scope` | `GET /scope?via=` |
209
+ | `ziggs_context_snapshot` | `GET /context/snapshot?via=chat:` — one-shot chat orientation (history + agreements + roster), grant-fenced |
210
210
  | `ziggs_list_my_agreements` | `GET /agreements?scope=mine` |
211
211
  | `ziggs_get_agreement` | `GET /agreements/:id` |
212
212
  | `ziggs_list_chats` | `GET /chats/mine` |
package/dist/toolError.js CHANGED
@@ -13,7 +13,7 @@ const HTTP_STATUS = /(?:^|\s)([1-5]\d{2})(?=\s|$)/;
13
13
  const SCOPE_DENIED_HINT = 'You are not authorized for this scope. To get access: ask the counterparty ' +
14
14
  'to issue you a context grant (they run ziggs_issue_grant), or request a ' +
15
15
  'bilateral link first (ziggs_request_link). Check what you can already ' +
16
- 'reach with ziggs_discover_context / ziggs_get_scope.';
16
+ 'reach with ziggs_discover_context / ziggs_context_snapshot.';
17
17
  function codeForStatus(status) {
18
18
  if (status === 401)
19
19
  return 'NOT_AUTHENTICATED';
package/dist/tools.js CHANGED
@@ -1,11 +1,20 @@
1
1
  import { randomUUID } from 'node:crypto';
2
2
  import { z } from 'zod';
3
- import { getAgreement, getMyAgreements, listMyChats, openConversation, proposeDirectTo, proposeBroadcast, publishOffer, respondToAgreement, revokeAgreement, ScopeClient, sendChatMessage, ContextDiscoveryClient, ContextReadClient, InboxClient, createTask, updateTaskState, replaceTaskPlan, listTasks, getBackendUrl, } from '@ziggs-ai/api-client';
3
+ import { getAgreement, getMyAgreements, listMyChats, openConversation, proposeDirectTo, proposeBroadcast, publishOffer, claimOffer, provisionRelayWorkers, respondToAgreement, revokeAgreement, sendChatMessage, ContextDiscoveryClient, ContextReadClient, InboxClient, createTask, updateTaskState, replaceTaskPlan, listTasks, getBackendUrl, } from '@ziggs-ai/api-client';
4
4
  import { decodeOperatorKeyClaims } from './operatorKey.js';
5
5
  import { registerTrustTools } from './trustTools.js';
6
6
  import { formatInboxToolResult, buildReadContextReadPlan, } from './inboxToolResult.js';
7
7
  import { filterTasksForDelegate, formatPendingDecisionsPayload, resolveWebAppOrigin, buildPendingNextActions, } from './pendingDecisions.js';
8
8
  import { PROTOCOL } from './protocol/delegateProtocol.js';
9
+ const RELAY_COORDINATOR_AGENT_ID = 'relay-coordinator';
10
+ function buildRelayCoordinatorTaskBody(opts) {
11
+ const title = opts.title?.trim() || 'Relay coordinator job';
12
+ return {
13
+ agreementId: opts.hireAgreementId,
14
+ assigneeId: RELAY_COORDINATOR_AGENT_ID,
15
+ description: `${title}\nrelay:v1\n${JSON.stringify(opts.payload)}`,
16
+ };
17
+ }
9
18
  import { READ_ONLY, WRITE, DESTRUCTIVE } from './toolAnnotations.js';
10
19
  import { toolError } from './toolError.js';
11
20
  // ZIG-557: the protocol sentences (loop / ack / humanAttention) are sourced
@@ -50,7 +59,6 @@ function textResult(data) {
50
59
  content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
51
60
  };
52
61
  }
53
- const scopeKindSchema = z.enum(['chat', 'agreement', 'task', 'counterparty']);
54
62
  const contextReadTypeSchema = z.enum([
55
63
  'messages',
56
64
  'artifacts',
@@ -444,21 +452,21 @@ export function registerZiggsTools(server, creds, cfg) {
444
452
  }
445
453
  });
446
454
  if (cfg.debugTools) {
447
- server.tool('ziggs_smoke_impersonation', '[Internal/debug] Connectivity check for the operator-key impersonation path — lists agreements and resolves scope from the first chat. Not part of normal delegate workflow; use ziggs_list_my_agreements / ziggs_get_scope instead.', {}, READ_ONLY, async () => {
455
+ server.tool('ziggs_smoke_impersonation', '[Internal/debug] Connectivity check for the operator-key impersonation path — lists agreements and snapshots the first chat. Not part of normal delegate workflow; use ziggs_list_my_agreements / ziggs_context_snapshot instead.', {}, READ_ONLY, async () => {
448
456
  try {
449
457
  const agreements = await getMyAgreements({}, creds);
450
458
  const chats = await listMyChats(creds);
451
- let scope = null;
459
+ let snapshot = null;
452
460
  const firstChatId = chats[0]?.chatId;
453
461
  if (firstChatId) {
454
- const client = new ScopeClient(creds.operatorKey, creds.agentId);
455
- scope = await client.get('chat', firstChatId);
462
+ const client = new ContextReadClient(creds.operatorKey, creds.agentId);
463
+ snapshot = await client.snapshot(firstChatId, { maxMessages: 5 });
456
464
  }
457
465
  return textResult({
458
466
  ok: true,
459
467
  agreementsCount: agreements.length,
460
468
  chatsCount: chats.length,
461
- scope,
469
+ snapshot,
462
470
  });
463
471
  }
464
472
  catch (e) {
@@ -466,13 +474,20 @@ export function registerZiggsTools(server, creds, cfg) {
466
474
  }
467
475
  });
468
476
  }
469
- server.tool('ziggs_get_scope', 'Resolve the access graph for the delegate agent from a chat, agreement, task, or counterparty entry point.', {
470
- scopeKind: scopeKindSchema.describe('Entry kind'),
471
- scopeId: z.string().describe('Entry id'),
472
- }, READ_ONLY, async ({ scopeKind, scopeId }) => {
477
+ server.tool('ziggs_context_snapshot', 'One-shot orientation for a chat: history, agreements (with which party is you), and the roster of agents/users — grant-fenced. Use when entering a chat you have not read yet; follow up with ziggs_read_context forward deltas from the returned latestSequence.', {
478
+ chatId: z.string().describe('Chat id to snapshot'),
479
+ maxMessages: z.number().optional().describe('Optional message history cap'),
480
+ contextGrantId: z
481
+ .string()
482
+ .optional()
483
+ .describe('Optional grant id when reading under a context grant'),
484
+ }, READ_ONLY, async ({ chatId, maxMessages, contextGrantId }) => {
473
485
  try {
474
- const client = new ScopeClient(creds.operatorKey, creds.agentId);
475
- const result = await client.get(scopeKind, scopeId);
486
+ const client = new ContextReadClient(creds.operatorKey, creds.agentId);
487
+ const result = await client.snapshot(chatId, {
488
+ maxMessages,
489
+ contextGrantId,
490
+ });
476
491
  return textResult(result);
477
492
  }
478
493
  catch (e) {
@@ -637,6 +652,70 @@ export function registerZiggsTools(server, creds, cfg) {
637
652
  return toolError(e.message);
638
653
  }
639
654
  });
655
+ server.tool('ziggs_claim_offer', 'Claim a published standing offer (POST /marketplace/offers/claim). Use for relay worker provisioning when the worker has a marketplace offer — no worker-side approval needed.', {
656
+ agreementId: z.string().describe('Open offer agreementId to claim'),
657
+ }, WRITE, async ({ agreementId }) => {
658
+ try {
659
+ const offer = await claimOffer(agreementId, creds);
660
+ return textResult({ offer });
661
+ }
662
+ catch (e) {
663
+ return toolError(e.message);
664
+ }
665
+ });
666
+ server.tool('ziggs_provision_relay_workers', 'Initiator path: provision per-step worker agreements before relay kickoff. Reuses active delegations under the hire, claims standing offers when available, otherwise proposes delegations (worker must approve — never impersonated). Returns relay:v1 payload and POST /tasks body when all steps are active.', {
667
+ hireAgreementId: z.string(),
668
+ chatId: z
669
+ .string()
670
+ .optional()
671
+ .describe('Required when a step has no standing offer and needs delegation under the hire'),
672
+ inputArtifactIds: z.array(z.string()).optional(),
673
+ steps: z.array(z.object({
674
+ stepId: z.string(),
675
+ order: z.number(),
676
+ assigneeId: z.string(),
677
+ description: z.string(),
678
+ offerAgreementId: z
679
+ .string()
680
+ .optional()
681
+ .describe('Explicit open offer to claim for this worker'),
682
+ })),
683
+ kickoff: z
684
+ .boolean()
685
+ .optional()
686
+ .describe('When true and readyForKickoff, also POST /tasks on the hire for relay-coordinator'),
687
+ }, WRITE, async ({ hireAgreementId, chatId, inputArtifactIds, steps, kickoff }) => {
688
+ try {
689
+ const result = await provisionRelayWorkers({
690
+ creds,
691
+ hireAgreementId,
692
+ chatId,
693
+ inputArtifactIds,
694
+ steps,
695
+ });
696
+ const relayTaskBody = buildRelayCoordinatorTaskBody({
697
+ hireAgreementId,
698
+ payload: result.payload,
699
+ });
700
+ let task;
701
+ if (kickoff && result.readyForKickoff) {
702
+ task = await createTask(relayTaskBody, creds);
703
+ }
704
+ return textResult({
705
+ ...result,
706
+ relayTaskBody,
707
+ task,
708
+ nextSteps: result.readyForKickoff
709
+ ? kickoff && task
710
+ ? 'Relay coordinator task created — watch Execution for step progress.'
711
+ : 'All worker agreements active — POST relayTaskBody via createTask or set kickoff=true.'
712
+ : `Worker approval pending on: ${result.pendingApprovals.join(', ')}. Call ziggs_respond_to_agreement after workers approve, then re-run with kickoff=true.`,
713
+ });
714
+ }
715
+ catch (e) {
716
+ return toolError(e.message);
717
+ }
718
+ });
640
719
  server.tool('ziggs_respond_to_agreement', 'Approve or reject a pending agreement. Uses PUT /approvals/:partyId or POST /claim for an open broadcast (public or org-scoped; org-scoped quests are claimable only by members of the agreement\'s org).', {
641
720
  agreementId: z.string(),
642
721
  action: z.enum(['approve', 'reject']),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ziggs-ai/ziggs-mcp",
3
- "version": "0.1.31",
3
+ "version": "0.1.33",
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": {
@@ -36,7 +36,7 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@modelcontextprotocol/sdk": "^1.29.0",
39
- "@ziggs-ai/api-client": "^0.1.25",
39
+ "@ziggs-ai/api-client": "^0.1.28",
40
40
  "dotenv": "^16.6.1",
41
41
  "zod": "^3.24.2"
42
42
  },
@@ -100,7 +100,7 @@ When coordinating with another org’s delegate:
100
100
 
101
101
  ## Boarding checklist (cold session)
102
102
 
103
- 1. Confirm MCP tools are available (e.g. `ziggs_list_chats` or `ziggs_get_scope`).
103
+ 1. Confirm MCP tools are available (e.g. `ziggs_list_chats` or `ziggs_context_snapshot`).
104
104
  2. Run **`ziggs_inbox`** — empty inbox is fine.
105
105
  3. Ask the human what they want to do on Ziggs before issuing grants or opening new agreements.
106
106