@ziggs-ai/ziggs-mcp 0.1.10 → 0.1.11
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 +10 -1
- package/dist/tools.js +9 -5
- package/dist/trustTools.js +96 -3
- package/package.json +1 -1
- package/skills/ziggs/references/grants-and-approvals.md +20 -4
package/README.md
CHANGED
|
@@ -179,6 +179,12 @@ ZIGGS_OPERATOR_KEY_B=... ZIGGS_AGENT_ID_B=... \
|
|
|
179
179
|
ZIGGS_APPROVER_OPERATOR_KEY=... ZIGGS_APPROVER_USER_ID=... \
|
|
180
180
|
ZIGGS_SMOKE_CHAT_ID=... \
|
|
181
181
|
node scripts/smoke-ziggs-mcp-z433-e2e.mjs
|
|
182
|
+
|
|
183
|
+
# ZIG-481 / ZIG-520 party handshake (link agreement, prod)
|
|
184
|
+
HTTP_URL=https://api.ziggsai.com \
|
|
185
|
+
OP_KEY_A=... AGENT_A=... USER_B=... OP_KEY_B=... AGENT_B=... \
|
|
186
|
+
npm run smoke:zig-481-prod
|
|
187
|
+
# Runbook: docs/evals/party-connection-two-claude.md (ZIG-521)
|
|
182
188
|
```
|
|
183
189
|
|
|
184
190
|
---
|
|
@@ -197,6 +203,9 @@ ZIGGS_SMOKE_CHAT_ID=... \
|
|
|
197
203
|
| `ziggs_issue_grant` | Chat admission or `POST /context/grants` |
|
|
198
204
|
| `ziggs_delegate_grant` | `POST /context/grants/:id/delegate` |
|
|
199
205
|
| `ziggs_revoke_grant` | `DELETE /context/grants/:id` |
|
|
206
|
+
| `ziggs_request_link` | `POST /agreements` `{engagementKind:"link"}` (ZIG-481 — a link is just an agreement) |
|
|
207
|
+
| `ziggs_list_links` | `GET /agreements?engagementKind=link` |
|
|
208
|
+
| `ziggs_revoke_link` | `DELETE /agreements/:agreementId` |
|
|
200
209
|
| `ziggs_smoke_impersonation` | Smoke step 1 |
|
|
201
210
|
| `ziggs_get_scope` | `GET /scope?via=` |
|
|
202
211
|
| `ziggs_list_my_agreements` | `GET /agreements?scope=mine` |
|
|
@@ -206,7 +215,7 @@ ZIGGS_SMOKE_CHAT_ID=... \
|
|
|
206
215
|
| `ziggs_list_messages` | `GET /chats/:id/messages` |
|
|
207
216
|
| `ziggs_send_message` | `POST /chats/:id/messages` |
|
|
208
217
|
| `ziggs_propose_agreement` | `POST /agreements/proposals` |
|
|
209
|
-
| `ziggs_respond_to_agreement` | `
|
|
218
|
+
| `ziggs_respond_to_agreement` | `PUT /agreements/:id/approvals/:partyId` (owner principal; approves hire, service, and `link` proposals) |
|
|
210
219
|
|
|
211
220
|
---
|
|
212
221
|
|
package/dist/tools.js
CHANGED
|
@@ -133,7 +133,7 @@ export function registerZiggsTools(server, creds, cfg) {
|
|
|
133
133
|
return toolError(e.message);
|
|
134
134
|
}
|
|
135
135
|
});
|
|
136
|
-
server.tool('ziggs_open_conversation', 'Open or reuse a chat with a user or agent participant.', {
|
|
136
|
+
server.tool('ziggs_open_conversation', 'Open or reuse a chat with a user or agent participant. To reach an agent in ANOTHER org, an unpublished delegate must establish a link first — call ziggs_request_link (if you have its agent id) or ziggs_create_link_invite (if you do not) and have it approved/claimed — otherwise this fails with AGENT_NOT_PUBLISHED.', {
|
|
137
137
|
participantId: z.string().describe('User or agent id to converse with'),
|
|
138
138
|
}, async ({ participantId }) => {
|
|
139
139
|
try {
|
|
@@ -164,7 +164,7 @@ export function registerZiggsTools(server, creds, cfg) {
|
|
|
164
164
|
return toolError(e.message);
|
|
165
165
|
}
|
|
166
166
|
});
|
|
167
|
-
server.tool('ziggs_send_message', 'Send a chat message as the delegate agent (requires chat membership).', {
|
|
167
|
+
server.tool('ziggs_send_message', 'Send a chat message as the delegate agent (requires chat membership). Cross-org first contact requires an ACTIVE link first (ziggs_request_link / ziggs_create_link_invite, then approve/claim); without it, messaging an agent outside your org fails with AGENT_NOT_PUBLISHED.', {
|
|
168
168
|
chatId: z.string(),
|
|
169
169
|
receiverId: z.string().describe('User or agent id receiving the message'),
|
|
170
170
|
text: z.string(),
|
|
@@ -217,13 +217,17 @@ export function registerZiggsTools(server, creds, cfg) {
|
|
|
217
217
|
return toolError(e.message);
|
|
218
218
|
}
|
|
219
219
|
});
|
|
220
|
-
server.tool('ziggs_respond_to_agreement', 'Approve or reject a pending
|
|
220
|
+
server.tool('ziggs_respond_to_agreement', 'Approve or reject a pending agreement (ZIG-524). Uses PUT /approvals/:partyId or POST /claim for open broadcast.', {
|
|
221
221
|
agreementId: z.string(),
|
|
222
222
|
action: z.enum(['approve', 'reject']),
|
|
223
223
|
}, async ({ agreementId, action }) => {
|
|
224
224
|
try {
|
|
225
|
-
const
|
|
226
|
-
|
|
225
|
+
const claims = decodeOperatorKeyClaims(creds.operatorKey);
|
|
226
|
+
const ownerId = claims?.ownerId ?? cfg.ZIGGS_OWNER_USER_ID;
|
|
227
|
+
const updated = await respondToAgreement(agreementId, action, creds, {
|
|
228
|
+
ownerUserId: ownerId,
|
|
229
|
+
});
|
|
230
|
+
return textResult({ agreement: updated });
|
|
227
231
|
}
|
|
228
232
|
catch (e) {
|
|
229
233
|
return toolError(e.message);
|
package/dist/trustTools.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { AgentSearchClient, ContextGrantsClient, addChatMember, } from '@ziggs-ai/api-client';
|
|
2
|
+
import { AgentSearchClient, ContextGrantsClient, createAgreement, listAgreements, revokeAgreement, claimLink, addChatMember, } from '@ziggs-ai/api-client';
|
|
3
3
|
function textResult(data) {
|
|
4
4
|
return {
|
|
5
5
|
content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
|
|
@@ -15,8 +15,8 @@ const grantScopeKindSchema = z.enum(['chat', 'agreement', 'org']);
|
|
|
15
15
|
const contextTemporalSchema = z.enum(['from-now', 'from-start']);
|
|
16
16
|
/** ZIG-433 — agent search + context grant management through MCP. */
|
|
17
17
|
export function registerTrustTools(server, creds) {
|
|
18
|
-
server.tool('ziggs_search_agents', '
|
|
19
|
-
query: z.string().describe('
|
|
18
|
+
server.tool('ziggs_search_agents', 'Find agents (AgentSearchClient). A keyword/natural-language query searches PUBLISHED agents only. Passing an EXACT agent id resolves that one agent even if it is unpublished/private — use this to look up a delegate someone shared their id for, then ziggs_request_link against it (ZIG-480). Use returned agentId in grant/issue tools — do not guess ids.', {
|
|
19
|
+
query: z.string().describe('Keyword/natural-language search (published agents) OR an exact agent id (resolves that agent even if unpublished)'),
|
|
20
20
|
limit: z.number().optional().describe('Max results (default server-side)'),
|
|
21
21
|
minScore: z.number().optional().describe('Minimum match score filter'),
|
|
22
22
|
}, async ({ query, limit, minScore }) => {
|
|
@@ -151,6 +151,99 @@ export function registerTrustTools(server, creds) {
|
|
|
151
151
|
return toolError(e.message);
|
|
152
152
|
}
|
|
153
153
|
});
|
|
154
|
+
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.', {
|
|
155
|
+
providerId: z
|
|
156
|
+
.string()
|
|
157
|
+
.describe('Bare agent id to link with (the target delegate). Use ziggs_search_agents or a known delegate id — do not guess.'),
|
|
158
|
+
message: z
|
|
159
|
+
.string()
|
|
160
|
+
.optional()
|
|
161
|
+
.describe('Optional note shown to the counterparty human on approval (agreement description)'),
|
|
162
|
+
}, async ({ providerId, message }) => {
|
|
163
|
+
try {
|
|
164
|
+
const { agreement } = await createAgreement({ engagementKind: 'link', providerId, description: message }, creds);
|
|
165
|
+
return textResult({
|
|
166
|
+
status: 'pending',
|
|
167
|
+
message: 'Link agreement created — the counterparty owner must approve (ziggs_respond_to_agreement) before cross-org reach. Surface pending state to the human.',
|
|
168
|
+
agreement,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
catch (e) {
|
|
172
|
+
return toolError(e.message);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
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.', {
|
|
176
|
+
message: z
|
|
177
|
+
.string()
|
|
178
|
+
.optional()
|
|
179
|
+
.describe('Optional note shown to whoever opens the invite (agreement description)'),
|
|
180
|
+
}, async ({ message }) => {
|
|
181
|
+
try {
|
|
182
|
+
const { agreement } = await createAgreement({ engagementKind: 'link', description: message }, creds);
|
|
183
|
+
return textResult({
|
|
184
|
+
status: 'open',
|
|
185
|
+
inviteId: agreement.agreementId,
|
|
186
|
+
message: 'Open link invite created. Share inviteId (agreementId) with the counterparty; they claim it via ziggs_claim_link_invite. No agent id needed on either side.',
|
|
187
|
+
agreement,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
catch (e) {
|
|
191
|
+
return toolError(e.message);
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
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.', {
|
|
195
|
+
agreementId: z
|
|
196
|
+
.string()
|
|
197
|
+
.describe('The invite id (agreementId) shared by the issuer'),
|
|
198
|
+
}, async ({ agreementId }) => {
|
|
199
|
+
try {
|
|
200
|
+
const { agreement } = await claimLink(agreementId, creds);
|
|
201
|
+
return textResult({
|
|
202
|
+
status: 'linked',
|
|
203
|
+
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.',
|
|
204
|
+
agreement,
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
catch (e) {
|
|
208
|
+
return toolError(e.message);
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
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.', {}, async () => {
|
|
212
|
+
try {
|
|
213
|
+
const links = await listAgreements({ engagementKind: 'link' }, creds);
|
|
214
|
+
const hasActive = links.some((a) => a.status === 'active');
|
|
215
|
+
return textResult({
|
|
216
|
+
count: links.length,
|
|
217
|
+
links,
|
|
218
|
+
...(hasActive
|
|
219
|
+
? {
|
|
220
|
+
nextSteps: 'A link is reach-only. Use ziggs_open_conversation (participantId = peer agent id) and/or ziggs_issue_grant before reading context.',
|
|
221
|
+
}
|
|
222
|
+
: {}),
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
catch (e) {
|
|
226
|
+
return toolError(e.message);
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
server.tool('ziggs_revoke_link', 'Revoke a bilateral link agreement (DELETE /agreements/:agreementId, ZIG-481). Either party may revoke; cross-org reach ends immediately.', {
|
|
230
|
+
agreementId: z
|
|
231
|
+
.string()
|
|
232
|
+
.describe('agreementId of the link agreement (from ziggs_list_links)'),
|
|
233
|
+
}, async ({ agreementId }) => {
|
|
234
|
+
try {
|
|
235
|
+
const result = await revokeAgreement(agreementId, creds);
|
|
236
|
+
return textResult({
|
|
237
|
+
status: 'revoked',
|
|
238
|
+
message: 'Link revoked — unpublished cross-org reach to this peer is blocked again.',
|
|
239
|
+
agreementId,
|
|
240
|
+
agreement: result.agreement,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
catch (e) {
|
|
244
|
+
return toolError(e.message);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
154
247
|
server.tool('ziggs_revoke_grant', 'Revoke a context grant and its descendants (DELETE /context/grants/:id). Requires context:admin on the operator key.', {
|
|
155
248
|
grantId: z.string(),
|
|
156
249
|
}, async ({ grantId }) => {
|
package/package.json
CHANGED
|
@@ -29,8 +29,24 @@ 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
|
|
33
|
+
counterparty owner approves it, and unpublished delegates can then reach each other.
|
|
34
|
+
|
|
32
35
|
1. Human describes goal and counterparty.
|
|
33
|
-
2. `
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
2. Create the link with **`ziggs_request_link`** (`providerId` = the target delegate agent id;
|
|
37
|
+
use `ziggs_search_agents` to find published service agents — do not guess ids).
|
|
38
|
+
3. Target human approves via **`ziggs_respond_to_agreement`** (action `approve`) when the
|
|
39
|
+
pending link agreement shows in their inbox / `ziggs_list_links`. This is the same generic
|
|
40
|
+
approval tool used for hire and service proposals — there is no separate link-response tool.
|
|
41
|
+
4. **A link ≠ a grant.** The link only allows unpublished delegates to *reach* each other. To
|
|
42
|
+
chat or read context, continue with **`ziggs_open_conversation`** (participantId = peer agent
|
|
43
|
+
id) and/or **`ziggs_issue_grant`** — still approval-gated when exposing existing scope.
|
|
44
|
+
5. `ziggs_read_context` only after grant is active.
|
|
45
|
+
6. `ziggs_revoke_grant` when context access should end; **`ziggs_revoke_link`** when the
|
|
46
|
+
bilateral link should end.
|
|
47
|
+
|
|
48
|
+
**Org join:** accepting an org invite auto-links inviter ↔ joiner delegates when both exist (no separate MCP step).
|
|
49
|
+
|
|
50
|
+
## Web UI (Settings → Connections)
|
|
51
|
+
|
|
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.
|