@ziggs-ai/ziggs-mcp 0.1.22 → 0.1.23

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
@@ -204,8 +204,9 @@ OP_KEY_A=... AGENT_A=... USER_B=... OP_KEY_B=... AGENT_B=... \
204
204
  | `ziggs_revoke_grant` | `DELETE /context/grants/:id` |
205
205
  | `ziggs_request_link` | `POST /agreements` `{engagementKind:"link"}` (ZIG-481 — a link is just an agreement) |
206
206
  | `ziggs_list_links` | `GET /agreements?engagementKind=link` |
207
- | `ziggs_revoke_link` | `DELETE /agreements/:agreementId` |
208
- | `ziggs_smoke_impersonation` | Smoke step 1 |
207
+ | `ziggs_revoke_link` | `DELETE /agreements/:agreementId` (see also `ziggs_revoke_agreement`) |
208
+ | `ziggs_revoke_agreement` | `DELETE /agreements/:id` — any agreement (hire/service/quest/link), ZIG-207 |
209
+ | `ziggs_smoke_impersonation` | [Internal/debug] connectivity check — not part of normal delegate workflow |
209
210
  | `ziggs_get_scope` | `GET /scope?via=` |
210
211
  | `ziggs_list_my_agreements` | `GET /agreements?scope=mine` |
211
212
  | `ziggs_get_agreement` | `GET /agreements/:id` |
package/dist/config.d.ts CHANGED
@@ -8,7 +8,7 @@ declare const envSchema: z.ZodObject<{
8
8
  ZIGGS_OPERATOR_KEY: z.ZodString;
9
9
  /** Optional when the operator key is agent-scoped (ZIG-279). */
10
10
  ZIGGS_AGENT_ID: z.ZodOptional<z.ZodString>;
11
- /** Human user id for payer-side proposals (ZIG-222 smoke step 2). */
11
+ /** Human user id for payer-side proposals — defaults the payer on propose/publish tools. */
12
12
  ZIGGS_OWNER_USER_ID: z.ZodOptional<z.ZodString>;
13
13
  }, "strip", z.ZodTypeAny, {
14
14
  ZIGGS_OPERATOR_KEY: string;
package/dist/config.js CHANGED
@@ -9,7 +9,7 @@ const envSchema = z.object({
9
9
  ZIGGS_OPERATOR_KEY: z.string().min(1, 'ZIGGS_OPERATOR_KEY is required'),
10
10
  /** Optional when the operator key is agent-scoped (ZIG-279). */
11
11
  ZIGGS_AGENT_ID: z.string().optional(),
12
- /** Human user id for payer-side proposals (ZIG-222 smoke step 2). */
12
+ /** Human user id for payer-side proposals — defaults the payer on propose/publish tools. */
13
13
  ZIGGS_OWNER_USER_ID: z.string().optional(),
14
14
  });
15
15
  /** Load delegate credentials from the environment (ZIG-222 / ZIG-430). */
package/dist/tools.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { randomUUID } from 'node:crypto';
2
2
  import { z } from 'zod';
3
- import { getAgreement, getMyAgreements, listMyChats, openConversation, proposeDirectTo, proposeBroadcast, publishOffer, respondToAgreement, ScopeClient, sendChatMessage, ContextDiscoveryClient, ContextReadClient, InboxClient, createTask, updateTaskState, replaceTaskPlan, listTasks, getBackendUrl, } from '@ziggs-ai/api-client';
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';
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 { formatPendingDecisionsPayload, resolveWebAppOrigin, buildPendingNextActions, } from './pendingDecisions.js';
8
8
  import { PROTOCOL } from './protocol/delegateProtocol.js';
9
- import { READ_ONLY, WRITE } from './toolAnnotations.js';
9
+ import { READ_ONLY, WRITE, DESTRUCTIVE } from './toolAnnotations.js';
10
10
  // ZIG-557: the protocol sentences (loop / ack / humanAttention) are sourced
11
11
  // from the shared const so this description can't drift from SKILL / server
12
12
  // instructions / .cursorrules.
@@ -140,6 +140,37 @@ async function proxyConnection(creds, input) {
140
140
  const result = parsed?.['result'];
141
141
  return result ?? parsed;
142
142
  }
143
+ /**
144
+ * ZIG-641 — cross-connection discovery: every connection this agent holds a
145
+ * grant for, joined with provider + health, so ziggs_connection_proxy's
146
+ * connectionId/grantId no longer has to arrive out of band. Same leak guard
147
+ * doesn't apply here (the backend never returns credential material for this
148
+ * route), but the response is still scanned defensively for consistency
149
+ * with proxyConnection.
150
+ */
151
+ async function listConnectionsForHolder(creds) {
152
+ const url = `${getBackendUrl()}/connections/grants`;
153
+ const res = await fetch(url, {
154
+ method: 'GET',
155
+ headers: {
156
+ Authorization: `Bearer ${creds.operatorKey}`,
157
+ 'X-Agent-Id': creds.agentId,
158
+ },
159
+ });
160
+ const body = await res.text().catch(() => '');
161
+ if (!res.ok) {
162
+ throw new Error(`GET /connections/grants ${res.status} ${body.slice(0, 200)}`);
163
+ }
164
+ assertNoLeakedSecret(body);
165
+ let parsed = body;
166
+ try {
167
+ parsed = body ? JSON.parse(body) : null;
168
+ }
169
+ catch {
170
+ parsed = body;
171
+ }
172
+ return parsed?.['connections'] ?? [];
173
+ }
143
174
  async function loadSessionActionsPayload(creds, cfg) {
144
175
  const webOrigin = resolveWebAppOrigin(cfg.ZIGGS_WEB_URL);
145
176
  const client = new InboxClient(creds.operatorKey, creds.agentId);
@@ -155,11 +186,11 @@ async function loadSessionActionsPayload(creds, cfg) {
155
186
  return formatPendingDecisionsPayload(inbox, webOrigin, { activeTasks });
156
187
  }
157
188
  export function registerZiggsTools(server, creds, cfg) {
158
- server.tool('ziggs_connection_status', 'ZIG-503 — Verify MCP OAuth binding: delegate agent id, owner user id, and org scope. Call after connect before inbox/chats. Includes pendingDecisions summary when approve/reject is waiting (ZIG-625).', {}, READ_ONLY, async () => {
189
+ server.tool('ziggs_auth_status', 'ZIG-503 — Verify MCP OAuth binding: delegate agent id, owner user id, and org scope. Call after connect before inbox/chats. Includes pendingDecisions summary when approve/reject is waiting (ZIG-625). (Renamed from ziggs_connection_status — "connection" now refers only to third-party credential connections, see ziggs_connection_proxy.)', {}, READ_ONLY, async () => {
159
190
  const claims = decodeOperatorKeyClaims(creds.operatorKey);
160
191
  const boundOrgId = claims?.boundOrgId?.trim() || null;
161
192
  const webOrigin = resolveWebAppOrigin(cfg.ZIGGS_WEB_URL);
162
- let sessionActions = {
193
+ let pendingDecisions = {
163
194
  pendingCount: 0,
164
195
  hasPending: false,
165
196
  activeWorkCount: 0,
@@ -168,11 +199,11 @@ export function registerZiggsTools(server, creds, cfg) {
168
199
  hasActionable: false,
169
200
  };
170
201
  try {
171
- sessionActions = await loadSessionActionsPayload(creds, cfg);
202
+ pendingDecisions = await loadSessionActionsPayload(creds, cfg);
172
203
  }
173
204
  catch {
174
- sessionActions = {
175
- ...sessionActions,
205
+ pendingDecisions = {
206
+ ...pendingDecisions,
176
207
  fetchError: 'Could not load inbox/tasks — call ziggs_pending_decisions.',
177
208
  };
178
209
  }
@@ -190,9 +221,8 @@ export function registerZiggsTools(server, creds, cfg) {
190
221
  apiBase: getBackendUrl(),
191
222
  webAppOrigin: webOrigin,
192
223
  docs: 'https://ziggsai.com/docs',
193
- sessionActions,
194
- pendingDecisions: sessionActions,
195
- sessionStartHint: sessionActions.hasActionable === true
224
+ pendingDecisions,
225
+ sessionStartHint: pendingDecisions.hasActionable === true
196
226
  ? 'Call ziggs_pending_decisions and paste sessionChatCard for the human before other work.'
197
227
  : 'Next: ziggs_inbox or ziggs_pending_decisions at session start.',
198
228
  });
@@ -214,7 +244,7 @@ export function registerZiggsTools(server, creds, cfg) {
214
244
  return toolError(e.message);
215
245
  }
216
246
  });
217
- server.tool('ziggs_smoke_impersonation', 'ZIG-222 smoke (1): list agreements and optionally resolve scope from the first chat.', {}, READ_ONLY, async () => {
247
+ 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 () => {
218
248
  try {
219
249
  const agreements = await getMyAgreements({}, creds);
220
250
  const chats = await listMyChats(creds);
@@ -236,12 +266,12 @@ export function registerZiggsTools(server, creds, cfg) {
236
266
  }
237
267
  });
238
268
  server.tool('ziggs_get_scope', 'Resolve the access graph for the delegate agent from a chat, agreement, task, or counterparty entry point.', {
239
- viaKind: scopeKindSchema.describe('Entry kind'),
240
- viaId: z.string().describe('Entry id'),
241
- }, READ_ONLY, async ({ viaKind, viaId }) => {
269
+ scopeKind: scopeKindSchema.describe('Entry kind'),
270
+ scopeId: z.string().describe('Entry id'),
271
+ }, READ_ONLY, async ({ scopeKind, scopeId }) => {
242
272
  try {
243
273
  const client = new ScopeClient(creds.operatorKey, creds.agentId);
244
- const result = await client.get(viaKind, viaId);
274
+ const result = await client.get(scopeKind, scopeId);
245
275
  return textResult(result);
246
276
  }
247
277
  catch (e) {
@@ -320,7 +350,7 @@ export function registerZiggsTools(server, creds, cfg) {
320
350
  return toolError(e.message);
321
351
  }
322
352
  });
323
- server.tool('ziggs_propose_agreement', 'ZIG-222 smoke (2): propose as payer-side delegate. Requires payerId (or ZIGGS_OWNER_USER_ID). No hire/spend.', {
353
+ server.tool('ziggs_propose_agreement', 'Propose a direct service agreement to one counterparty in a chat, as the payer-side delegate. Requires payerId (or ZIGGS_OWNER_USER_ID). price is recorded on the agreement but does not itself trigger a transfer — V1 has no real payment rail yet.', {
324
354
  proposedTo: z.string(),
325
355
  chatId: z.string(),
326
356
  description: z.string(),
@@ -421,6 +451,17 @@ export function registerZiggsTools(server, creds, cfg) {
421
451
  return toolError(e.message);
422
452
  }
423
453
  });
454
+ server.tool('ziggs_revoke_agreement', 'Revoke any agreement you are a party to — hire, service, quest, or link (DELETE /agreements/:id, ZIG-207). Either party may revoke; this ends the engagement immediately. ziggs_revoke_link calls the same endpoint with link-flavored messaging; use whichever reads clearer for the agreement kind.', {
455
+ agreementId: z.string().describe('Agreement to revoke'),
456
+ }, DESTRUCTIVE, async ({ agreementId }) => {
457
+ try {
458
+ const result = await revokeAgreement(agreementId, creds);
459
+ return textResult({ status: 'revoked', agreementId, agreement: result.agreement });
460
+ }
461
+ catch (e) {
462
+ return toolError(e.message);
463
+ }
464
+ });
424
465
  server.tool('ziggs_inbox', ZIGGS_INBOX_DESCRIPTION, {
425
466
  ack: z
426
467
  .array(z.object({
@@ -553,9 +594,13 @@ export function registerZiggsTools(server, creds, cfg) {
553
594
  agreementId: z.string().describe('Agreement this task belongs to'),
554
595
  description: z.string().describe('What the task entails'),
555
596
  parentTaskId: z.string().optional().describe('Parent task id for sub-tasks'),
556
- }, WRITE, async ({ agreementId, description, parentTaskId }) => {
597
+ assigneeId: z
598
+ .string()
599
+ .optional()
600
+ .describe('Agent or user ID to explicitly assign this task to — must be a party to the agreement'),
601
+ }, WRITE, async ({ agreementId, description, parentTaskId, assigneeId }) => {
557
602
  try {
558
- const task = await createTask({ agreementId, description, parentTaskId }, creds);
603
+ const task = await createTask({ agreementId, description, parentTaskId, assigneeId }, creds);
559
604
  return textResult({ ok: true, task });
560
605
  }
561
606
  catch (e) {
@@ -602,16 +647,25 @@ export function registerZiggsTools(server, creds, cfg) {
602
647
  return toolError(e.message);
603
648
  }
604
649
  });
605
- server.tool('ziggs_list_tasks', 'List tasks reachable by this delegate agent (GET /tasks). Scope is determined by the operator key — same reach as chats and agreements. Supports optional state filter and cursor pagination.', {
650
+ server.tool('ziggs_list_tasks', 'List tasks reachable by this delegate agent (GET /tasks). Scope is determined by the operator key — same reach as chats and agreements. Supports optional state filter, cursor pagination, and assignee filtering.', {
606
651
  state: z
607
652
  .string()
608
653
  .optional()
609
654
  .describe('Filter by state: active, completed, failed, cancelled'),
610
655
  cursor: z.string().optional().describe('Opaque cursor from prior nextCursor'),
611
656
  limit: z.number().optional().describe('Max rows (default server-side)'),
612
- }, READ_ONLY, async ({ state, cursor, limit }) => {
657
+ assignedTo: z
658
+ .string()
659
+ .optional()
660
+ .describe('Filter to tasks explicitly assigned to this agent/user id (ZIG-586)'),
661
+ assignedToMe: z
662
+ .boolean()
663
+ .optional()
664
+ .describe('Shorthand for assignedTo=<this delegate\'s own agent id>. Takes precedence over assignedTo if both are set.'),
665
+ }, READ_ONLY, async ({ state, cursor, limit, assignedTo, assignedToMe }) => {
613
666
  try {
614
- const result = await listTasks({ state, cursor, limit }, creds);
667
+ const effectiveAssignedTo = assignedToMe ? creds.agentId : assignedTo;
668
+ const result = await listTasks({ state, cursor, limit, assignedTo: effectiveAssignedTo }, creds);
615
669
  return textResult(result);
616
670
  }
617
671
  catch (e) {
@@ -621,10 +675,10 @@ export function registerZiggsTools(server, creds, cfg) {
621
675
  // ---------------------------------------------------------------------------
622
676
  // Connection proxy (ZIG-569)
623
677
  // ---------------------------------------------------------------------------
624
- server.tool('ziggs_connection_proxy', "Use a stored connection (e.g. the owner's GitHub) without ever seeing the credential. " +
678
+ server.tool('ziggs_connection_proxy', "Use a stored connection (a third-party credential, e.g. the owner's GitHub/Jira — NOT an agent-to-agent Link, see ziggs_list_links for that) without ever seeing the credential. " +
625
679
  'Calls the backend connections proxy with a grant the owner issued to this agent: the proxy enforces the grant, decrypts the token server-side, makes the upstream provider call, and returns the result (token-leak guarded on both sides). ' +
626
680
  'Provide connectionId, grantId, the provider action (e.g. repo:read), and an optional action-specific payload. ' +
627
- 'You must already hold connectionId + grantId (the owner shares them out-of-band); listing connections an agent holds grants for is a separate tool/ticket.', {
681
+ "Don't know connectionId/grantId yet? Call ziggs_list_my_connections first.", {
628
682
  connectionId: z.string().describe('Connection to act on'),
629
683
  grantId: z
630
684
  .string()
@@ -648,5 +702,16 @@ export function registerZiggsTools(server, creds, cfg) {
648
702
  return toolError(e.message);
649
703
  }
650
704
  });
705
+ server.tool('ziggs_list_my_connections', 'ZIG-641 — discover the third-party connections (credentials like GitHub/Jira, NOT agent-to-agent Links — see ziggs_list_links for that) you hold grants for (e.g. "is GitHub connected?") without the owner sharing connectionId/grantId out of band. ' +
706
+ 'Returns, per connection: connectionId, provider, the grantId(s) you hold, each grant\'s allowed-action caveats, and health (linked/expired/revoked) for both the connection and each grant. ' +
707
+ 'Read-only — never returns credential material. Feed the connectionId + a grantId with health "linked" into ziggs_connection_proxy to actually use it.', {}, READ_ONLY, async () => {
708
+ try {
709
+ const connections = await listConnectionsForHolder(creds);
710
+ return textResult({ connections });
711
+ }
712
+ catch (e) {
713
+ return toolError(e.message);
714
+ }
715
+ });
651
716
  registerTrustTools(server, creds, cfg);
652
717
  }
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { AgentSearchClient, ContextGrantsClient, createAgreement, listAgreements, revokeAgreement, claimLink, addChatMember, } from '@ziggs-ai/api-client';
2
+ import { AgentSearchClient, ContextGrantsClient, createAgreement, listAgreements, revokeAgreement, claimAgreement, addChatMember, } from '@ziggs-ai/api-client';
3
3
  import { READ_ONLY, WRITE, DESTRUCTIVE } from './toolAnnotations.js';
4
4
  function textResult(data) {
5
5
  return {
@@ -154,7 +154,7 @@ export function registerTrustTools(server, creds, cfg) {
154
154
  return toolError(e.message);
155
155
  }
156
156
  });
157
- server.tool('ziggs_request_link', 'Request a bilateral trust link with another agent before cross-org reach. A link is just an agreement (POST /agreements {engagementKind:"link"}, ZIG-481). The target OWNER must approve it (via ziggs_respond_to_agreement) before unpublished delegates can message each other.', {
157
+ server.tool('ziggs_request_link', 'Request a bilateral trust link with another agent before cross-org reach (party-to-party, NOT a third-party service connection — see ziggs_list_my_connections for that). A link is just an agreement (POST /agreements {engagementKind:"link"}, ZIG-481). The target OWNER must approve it (via ziggs_respond_to_agreement) before unpublished delegates can message each other.', {
158
158
  providerId: z
159
159
  .string()
160
160
  .describe('Bare agent id to link with (the target delegate). Use ziggs_search_agents or a known delegate id — do not guess.'),
@@ -175,7 +175,7 @@ export function registerTrustTools(server, creds, cfg) {
175
175
  return toolError(e.message);
176
176
  }
177
177
  });
178
- server.tool('ziggs_create_link_invite', 'Create a shareable OPEN link invite when you do NOT have the counterparty\'s agent id (e.g. connecting across orgs) (ZIG-525). Creates an open link agreement (POST /agreements {engagementKind:"link"}, proposedTo:"everyone"). Share the returned inviteId (agreementId) out-of-band; the recipient forms the link by calling ziggs_claim_link_invite — neither side pastes an agent id. Revoke via ziggs_revoke_link to disable.', {
178
+ server.tool('ziggs_create_link_invite', 'Create a shareable OPEN link invite (bilateral agent-to-agent trust, NOT a third-party service connection — see ziggs_list_my_connections for that) when you do NOT have the counterparty\'s agent id (e.g. connecting across orgs) (ZIG-525). Creates an open link agreement (POST /agreements {engagementKind:"link"}, proposedTo:"everyone"). Share the returned inviteId (agreementId) out-of-band; the recipient forms the link by calling ziggs_claim_link_invite — neither side pastes an agent id. Revoke via ziggs_revoke_link to disable.', {
179
179
  message: z
180
180
  .string()
181
181
  .optional()
@@ -195,13 +195,13 @@ export function registerTrustTools(server, creds, cfg) {
195
195
  return toolError(e.message);
196
196
  }
197
197
  });
198
- server.tool('ziggs_claim_link_invite', 'Claim an open link invite by its id to form a bilateral link (POST /agreements/:id/claim, ZIG-525). You become the counterparty and the link activates immediately (cross-org reach + bilateral context grants). You cannot claim your own invite.', {
198
+ server.tool('ziggs_claim_link_invite', 'Claim an open link invite by its id to form a bilateral link (agent-to-agent trust, NOT a third-party service connection — see ziggs_list_my_connections for that) (POST /agreements/:id/claim, ZIG-525). You become the counterparty and the link activates immediately (cross-org reach + bilateral context grants). You cannot claim your own invite.', {
199
199
  agreementId: z
200
200
  .string()
201
201
  .describe('The invite id (agreementId) shared by the issuer'),
202
202
  }, WRITE, async ({ agreementId }) => {
203
203
  try {
204
- const { agreement } = await claimLink(agreementId, creds);
204
+ const { agreement } = await claimAgreement(agreementId, creds);
205
205
  return textResult({
206
206
  status: 'linked',
207
207
  message: 'Link invite claimed — you are now linked. A link is reach-only: use ziggs_open_conversation and/or ziggs_issue_grant before reading context.',
@@ -212,7 +212,7 @@ export function registerTrustTools(server, creds, cfg) {
212
212
  return toolError(e.message);
213
213
  }
214
214
  });
215
- server.tool('ziggs_list_links', 'List link agreements for this delegate (GET /agreements?engagementKind=link, ZIG-481). Each item exposes parties.creatorAgent (requester), parties.providerAgent (target), parties.proposedTo (target owner), proposal.status and status. Approve pending links via ziggs_respond_to_agreement.', {}, READ_ONLY, async () => {
215
+ server.tool('ziggs_list_links', 'List link agreements for this delegate — bilateral agent-to-agent trust relationships, NOT third-party service connections (see ziggs_list_my_connections for those) (GET /agreements?engagementKind=link, ZIG-481). Each item exposes parties.creatorAgent (requester), parties.providerAgent (target), parties.proposedTo (target owner), proposal.status and status. Approve pending links via ziggs_respond_to_agreement.', {}, READ_ONLY, async () => {
216
216
  try {
217
217
  const links = await listAgreements({ engagementKind: 'link' }, creds);
218
218
  const hasActive = links.some((a) => a.status === 'active');
@@ -230,7 +230,7 @@ export function registerTrustTools(server, creds, cfg) {
230
230
  return toolError(e.message);
231
231
  }
232
232
  });
233
- server.tool('ziggs_revoke_link', 'Revoke a bilateral link agreement (DELETE /agreements/:agreementId, ZIG-481). Either party may revoke; cross-org reach ends immediately.', {
233
+ server.tool('ziggs_revoke_link', 'Revoke a bilateral link agreement — agent-to-agent trust, NOT a third-party service connection (DELETE /agreements/:agreementId, ZIG-481). Either party may revoke; cross-org reach ends immediately. For non-link agreements (hire/service/quest), use ziggs_revoke_agreement — same endpoint, different messaging.', {
234
234
  agreementId: z
235
235
  .string()
236
236
  .describe('agreementId of the link agreement (from ziggs_list_links)'),
@@ -22,10 +22,10 @@ node scripts/smoke-zig-500-v4-claude-code.mjs # Claude Code CLI parity
22
22
  | ZIG-496 discovery (well-known, 401 docs) | `--discovery-only` | Client uses same URLs |
23
23
  | OAuth → Bearer → full tool surface | `--auto` or smoke creds | Connect in IDE |
24
24
  | No stub-only tools | fails if only `authenticate` / `complete_authentication` | Tool picker shows `ziggs_*` |
25
- | Runtime tools work | `ziggs_connection_status` + `ziggs_inbox` | Same smoke in IDE |
25
+ | Runtime tools work | `ziggs_auth_status` + `ziggs_inbox` | Same smoke in IDE |
26
26
  | Restart not required | N/A | Tools visible right after OAuth |
27
27
 
28
- **Pass:** Native MCP OAuth — client discovers metadata, gets Bearer, `tools/list` returns ≥12 `ziggs_*` tools, and inbox/connection_status succeed.
28
+ **Pass:** Native MCP OAuth — client discovers metadata, gets Bearer, `tools/list` returns ≥12 `ziggs_*` tools, and inbox/auth_status succeed.
29
29
 
30
30
  **Fail:** OAuth OK but tools empty, stub-only list, or inbox 404 → comment on [ZIG-500](https://linear.app/ziggsai/issue/ZIG-500) with tool list + smoke output.
31
31
 
@@ -64,7 +64,7 @@ Use a **throwaway directory** (no existing Ziggs plugin or stdio MCP).
64
64
 
65
65
  Ask Claude to call in order:
66
66
 
67
- 1. `ziggs_connection_status` — confirm agent + org binding
67
+ 1. `ziggs_auth_status` — confirm agent + org binding
68
68
  2. `ziggs_inbox` or `ziggs_list_chats`
69
69
  3. `ziggs_send_message` (chat you belong to)
70
70
 
@@ -113,7 +113,7 @@ Automated: smoke-zig-500-v4-path.mjs --discovery-only → pass/fail
113
113
  Automated: smoke-zig-500-v4-path.mjs --auto → Path A, N tools, inbox pass/fail
114
114
  Manual OAuth connect: pass/fail
115
115
  Tool count after OAuth (no restart): __
116
- ziggs_connection_status: pass/fail
116
+ ziggs_auth_status: pass/fail
117
117
  ziggs_inbox: pass/fail
118
118
  Notes:
119
119
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ziggs-ai/ziggs-mcp",
3
- "version": "0.1.22",
3
+ "version": "0.1.23",
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": {
@@ -38,7 +38,7 @@ The sections below elaborate this protocol with tools, examples, and edge cases.
38
38
 
39
39
  ## Session start — pending decisions + inbox
40
40
 
41
- 1. Call **`ziggs_connection_status`** after OAuth connect (includes a pending summary).
41
+ 1. Call **`ziggs_auth_status`** after OAuth connect (includes a pending summary).
42
42
  2. Call **`ziggs_pending_decisions`** — if `pendingCount > 0`, **paste `decisionChatCard` for the human** before anything else (ZIG-625). Wait for explicit approve/reject; then `ziggs_respond_to_agreement`.
43
43
  3. Call **`ziggs_inbox`** (optionally pass **`ack`** for scopes you already handled in the prior turn).
44
44
  4. Read the envelope: scope news counts, `humanAttention`, and **`decisionChatCard`** when present.
@@ -103,4 +103,4 @@ When coordinating with another org’s delegate:
103
103
  2. Run **`ziggs_inbox`** — empty inbox is fine.
104
104
  3. Ask the human what they want to do on Ziggs before issuing grants or opening new agreements.
105
105
 
106
- Connection credentials live **only** in MCP host config — never in this skill or in chat.
106
+ MCP connection credentials (the transport auth to this server) live **only** in MCP host config — never in this skill or in chat. This is separate from third-party connection credentials (GitHub/Jira, `ziggs_connection_proxy`), which the backend holds and the agent never sees.
@@ -29,7 +29,8 @@ These commonly surface as **`pending_approval`** or blocked tool errors:
29
29
 
30
30
  ## Trust tool sequence (cross-org)
31
31
 
32
- A **link is just an agreement** (`engagementKind: "link"`, ZIG-481). Create it, the
32
+ A **link** (bilateral agent-to-agent trust — not a `ziggs_connection_proxy` third-party
33
+ connection) **is just an agreement** (`engagementKind: "link"`, ZIG-481). Create it, the
33
34
  counterparty owner approves it, and unpublished delegates can then reach each other.
34
35
 
35
36
  1. Human describes goal and counterparty.
@@ -43,10 +44,12 @@ counterparty owner approves it, and unpublished delegates can then reach each ot
43
44
  id) and/or **`ziggs_issue_grant`** — still approval-gated when exposing existing scope.
44
45
  5. `ziggs_read_context` only after grant is active.
45
46
  6. `ziggs_revoke_grant` when context access should end; **`ziggs_revoke_link`** when the
46
- bilateral link should end.
47
+ bilateral link should end. For a non-link agreement (hire/service/quest), use
48
+ **`ziggs_revoke_agreement`** instead — same endpoint, link-agnostic messaging.
47
49
 
48
50
  **Org join:** accepting an org invite auto-links inviter ↔ joiner delegates when both exist (no separate MCP step).
49
51
 
50
52
  ## Web UI (Settings → Connections)
51
53
 
52
- After an agent link appears under **Connected**, use your Claude delegate (MCP) for **`ziggs_open_conversation`** or **`ziggs_issue_grant`**. The web UI manages handshake only — not chat or context grants.
54
+ Confusingly named after the *other* "connection" (this is the agent-link handshake UI, not
55
+ `ziggs_connection_proxy` third-party connections). After an agent link appears under **Connected**, use your Claude delegate (MCP) for **`ziggs_open_conversation`** or **`ziggs_issue_grant`**. The web UI manages handshake only — not chat or context grants.