@ziggs-ai/ziggs-mcp 0.1.12 → 0.1.13
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/dist/tools.js +75 -6
- package/package.json +2 -2
- package/skills/ziggs/references/inbox-rhythm.md +15 -0
package/dist/tools.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { getAgreement, getMyAgreements, listMyChats, openConversation, proposeDirectTo, respondToAgreement, ScopeClient, MessagesClient, sendChatMessage, ContextDiscoveryClient, ContextReadClient, InboxClient, ArtifactsClient, getBackendUrl, } from '@ziggs-ai/api-client';
|
|
3
|
+
import { getAgreement, getMyAgreements, listMyChats, openConversation, proposeDirectTo, respondToAgreement, ScopeClient, MessagesClient, sendChatMessage, ContextDiscoveryClient, ContextReadClient, InboxClient, ArtifactsClient, 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 } from './inboxToolResult.js';
|
|
@@ -38,7 +38,6 @@ async function writeArtifactStrict(creds, input) {
|
|
|
38
38
|
visibility: input.visibility,
|
|
39
39
|
chatId: input.chatId,
|
|
40
40
|
agreementId: input.agreementId,
|
|
41
|
-
taskId: input.taskId,
|
|
42
41
|
}),
|
|
43
42
|
});
|
|
44
43
|
if (!res.ok) {
|
|
@@ -236,7 +235,7 @@ export function registerZiggsTools(server, creds, cfg) {
|
|
|
236
235
|
return toolError(e.message);
|
|
237
236
|
}
|
|
238
237
|
});
|
|
239
|
-
server.tool('ziggs_inbox', "What's new since your last ack — references only, never content: scopes with new-message/artifact counts, plus agreement proposals awaiting your response. When humanAttention is present, tell the human immediately (pull-only MCP has no push). Flow: inbox → read
|
|
238
|
+
server.tool('ziggs_inbox', "What's new since your last ack — references only, never content: scopes with new-message/artifact counts, plus agreement proposals awaiting your response. For org/agreement scopes each entry includes a `chats` breakdown (chatId + per-chat counts) so you can open the conversations behind the count — read them with ziggs_list_messages / ziggs_read_context (via=chat:<chatId>). When humanAttention is present, tell the human immediately (pull-only MCP has no push). Flow: inbox → read → act → ack. Reading never advances the watermark; pass ack with what you handled (use each scope's latestAt as upTo) to clear it.", {
|
|
240
239
|
ack: z
|
|
241
240
|
.array(z.object({
|
|
242
241
|
kind: z.enum(['chat', 'agreement', 'org']),
|
|
@@ -312,9 +311,8 @@ export function registerZiggsTools(server, creds, cfg) {
|
|
|
312
311
|
.string()
|
|
313
312
|
.optional()
|
|
314
313
|
.describe('Target agreement (xor chatId)'),
|
|
315
|
-
taskId: z.string().optional().describe('Optional task link'),
|
|
316
314
|
content_type: z.string().optional().describe('Default text'),
|
|
317
|
-
}, async ({ text, visibility, chatId, agreementId,
|
|
315
|
+
}, async ({ text, visibility, chatId, agreementId, content_type }) => {
|
|
318
316
|
try {
|
|
319
317
|
if ((chatId && agreementId) || (!chatId && !agreementId)) {
|
|
320
318
|
return toolError('Pass exactly one of chatId or agreementId');
|
|
@@ -324,7 +322,6 @@ export function registerZiggsTools(server, creds, cfg) {
|
|
|
324
322
|
visibility,
|
|
325
323
|
chatId,
|
|
326
324
|
agreementId,
|
|
327
|
-
taskId,
|
|
328
325
|
content_type,
|
|
329
326
|
});
|
|
330
327
|
return textResult({ ok: true, visibility, chatId, agreementId });
|
|
@@ -351,5 +348,77 @@ export function registerZiggsTools(server, creds, cfg) {
|
|
|
351
348
|
return toolError(e.message);
|
|
352
349
|
}
|
|
353
350
|
});
|
|
351
|
+
// ---------------------------------------------------------------------------
|
|
352
|
+
// Task mutation tools (ZIG-555)
|
|
353
|
+
// ---------------------------------------------------------------------------
|
|
354
|
+
server.tool('ziggs_create_task', 'Create a task under an agreement. Every task belongs to exactly one agreement (agreementId required).', {
|
|
355
|
+
agreementId: z.string().describe('Agreement this task belongs to'),
|
|
356
|
+
description: z.string().describe('What the task entails'),
|
|
357
|
+
parentTaskId: z.string().optional().describe('Parent task id for sub-tasks'),
|
|
358
|
+
}, async ({ agreementId, description, parentTaskId }) => {
|
|
359
|
+
try {
|
|
360
|
+
const task = await createTask({ agreementId, description, parentTaskId }, creds);
|
|
361
|
+
return textResult({ ok: true, task });
|
|
362
|
+
}
|
|
363
|
+
catch (e) {
|
|
364
|
+
return toolError(e.message);
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
server.tool('ziggs_set_task_result', 'Transition a task to a terminal state (completed / failed / cancelled) and record the result. Enforces the state machine — only active tasks can be transitioned.', {
|
|
368
|
+
taskId: z.string(),
|
|
369
|
+
state: z.enum(['completed', 'failed', 'cancelled']),
|
|
370
|
+
result: z
|
|
371
|
+
.object({
|
|
372
|
+
summary: z.string().optional(),
|
|
373
|
+
status: z.string().optional(),
|
|
374
|
+
links: z.array(z.string()).optional(),
|
|
375
|
+
})
|
|
376
|
+
.passthrough()
|
|
377
|
+
.optional()
|
|
378
|
+
.describe('Outcome payload (summary, status, links, …)'),
|
|
379
|
+
errorMessage: z.string().optional().describe('Required when state=failed'),
|
|
380
|
+
}, async ({ taskId, state, result, errorMessage }) => {
|
|
381
|
+
try {
|
|
382
|
+
const task = await updateTaskState(taskId, state, { result, errorMessage }, creds);
|
|
383
|
+
return textResult({ ok: true, task });
|
|
384
|
+
}
|
|
385
|
+
catch (e) {
|
|
386
|
+
return toolError(e.message);
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
server.tool('ziggs_post_task_plan_step', 'Replace / advance the plan for a task. Provide the full ordered step list — existing steps are replaced. Use this to post progress as plan steps.', {
|
|
390
|
+
taskId: z.string(),
|
|
391
|
+
steps: z
|
|
392
|
+
.array(z.object({
|
|
393
|
+
stepId: z.string().describe('Stable id for this step (e.g. uuid)'),
|
|
394
|
+
description: z.string(),
|
|
395
|
+
order: z.number().int(),
|
|
396
|
+
}))
|
|
397
|
+
.describe('Full replacement step list (ordered)'),
|
|
398
|
+
}, async ({ taskId, steps }) => {
|
|
399
|
+
try {
|
|
400
|
+
const task = await replaceTaskPlan(taskId, steps, creds);
|
|
401
|
+
return textResult({ ok: true, task });
|
|
402
|
+
}
|
|
403
|
+
catch (e) {
|
|
404
|
+
return toolError(e.message);
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
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.', {
|
|
408
|
+
state: z
|
|
409
|
+
.string()
|
|
410
|
+
.optional()
|
|
411
|
+
.describe('Filter by state: active, completed, failed, cancelled'),
|
|
412
|
+
cursor: z.string().optional().describe('Opaque cursor from prior nextCursor'),
|
|
413
|
+
limit: z.number().optional().describe('Max rows (default server-side)'),
|
|
414
|
+
}, async ({ state, cursor, limit }) => {
|
|
415
|
+
try {
|
|
416
|
+
const result = await listTasks({ state, cursor, limit }, creds);
|
|
417
|
+
return textResult(result);
|
|
418
|
+
}
|
|
419
|
+
catch (e) {
|
|
420
|
+
return toolError(e.message);
|
|
421
|
+
}
|
|
422
|
+
});
|
|
354
423
|
registerTrustTools(server, creds, cfg);
|
|
355
424
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ziggs-ai/ziggs-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
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": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
37
|
-
"@ziggs-ai/api-client": "^0.1.
|
|
37
|
+
"@ziggs-ai/api-client": "^0.1.14",
|
|
38
38
|
"dotenv": "^16.6.1",
|
|
39
39
|
"zod": "^3.24.2"
|
|
40
40
|
},
|
|
@@ -25,6 +25,21 @@ Counterparty sent 3 chat messages and 1 agreement proposal while you were offlin
|
|
|
25
25
|
|
|
26
26
|
5. **`ziggs_inbox`** again — scoped news for handled chat should be empty. Proposals clear when responded, not on ack alone.
|
|
27
27
|
|
|
28
|
+
## Org / agreement scopes — which chats? (ZIG-543)
|
|
29
|
+
|
|
30
|
+
A `chat` scope's id *is* the chatId. For an **org** or **agreement** scope the
|
|
31
|
+
count spans many chats, so the entry includes a **`chats`** breakdown:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
{ scope: { kind: "org", id: "<orgId>" }, newMessages: 12, chats: [
|
|
35
|
+
{ chatId: "<id>", newMessages: 5, newArtifacts: 0, latestAt: "…" }, … ] }
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Open each conversation by its `chatId` — `ziggs_list_messages` or
|
|
39
|
+
`ziggs_read_context` (`via: chat:<chatId>`). Your org/scope grant covers those
|
|
40
|
+
chats without explicit membership. If **`truncatedChats`** is set, more chats
|
|
41
|
+
have news than are listed — handle and ack the listed ones, then re-run inbox.
|
|
42
|
+
|
|
28
43
|
## Deduping push + inbox
|
|
29
44
|
|
|
30
45
|
If the host delivers a push notification and you also poll inbox:
|