@ziggs-ai/ziggs-mcp 0.11.0 → 0.13.0
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/inboxToolResult.js
CHANGED
|
@@ -65,7 +65,7 @@ export function buildReadPlan(inbox, grantsByScope, self = { agentId: '' }) {
|
|
|
65
65
|
// every time — the plan says to carry it to the human instead.
|
|
66
66
|
const mayAnswer = (facts) => resolvePendingApprovalPartyId({
|
|
67
67
|
pendingPartyIds: facts.pendingApprovalPartyIds ?? [],
|
|
68
|
-
|
|
68
|
+
proposedToIds: facts.proposedTo ? [facts.proposedTo] : [],
|
|
69
69
|
}, [self.agentId]) === self.agentId && self.agentId !== '';
|
|
70
70
|
for (const p of proposals) {
|
|
71
71
|
add(`respond:${p.agreementId}`, mayAnswer(p)
|
|
@@ -97,8 +97,8 @@ export declare function buildPaymentApprovalItems(approvals: Array<Record<string
|
|
|
97
97
|
* A task is "for me" when:
|
|
98
98
|
* - it is explicitly assigned (`assigneeId`) to one of my ids, or
|
|
99
99
|
* - it has no explicit assignee and one of my ids sits on the executing side
|
|
100
|
-
* of the task/agreement (executor, agent, provider
|
|
101
|
-
* proposedTo).
|
|
100
|
+
* of the task/agreement (executor, agent, or either column of the provider /
|
|
101
|
+
* proposedTo party sides).
|
|
102
102
|
* Tasks with no assignee and no readable agreement parties are excluded —
|
|
103
103
|
* "can't tell" must not render as "yours".
|
|
104
104
|
*/
|
package/dist/pendingDecisions.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { resolvePendingApprovalPartyId, } from '@ziggs-ai/api-client';
|
|
1
|
+
import { partySideIds, resolvePendingApprovalPartyId, } from '@ziggs-ai/api-client';
|
|
2
2
|
/** Chat/tool cues when {@link PendingDecisionItem.respondableBy} is `agent`. */
|
|
3
3
|
export function decisionRespondCues(item) {
|
|
4
4
|
if (item.respondableBy !== 'agent')
|
|
@@ -77,7 +77,7 @@ function respondableByFor(facts, self) {
|
|
|
77
77
|
// Agent id first: when both owe a decision, ours is the one we can act on.
|
|
78
78
|
const slot = resolvePendingApprovalPartyId({
|
|
79
79
|
pendingPartyIds: facts.pendingApprovalPartyIds ?? [],
|
|
80
|
-
|
|
80
|
+
proposedToIds: facts.proposedTo ? [facts.proposedTo] : [],
|
|
81
81
|
}, [self.agentId, self.ownerUserId]);
|
|
82
82
|
return slot != null && slot === self.agentId ? 'agent' : 'human';
|
|
83
83
|
}
|
|
@@ -171,8 +171,8 @@ export function buildPaymentApprovalItems(approvals, webOrigin) {
|
|
|
171
171
|
* A task is "for me" when:
|
|
172
172
|
* - it is explicitly assigned (`assigneeId`) to one of my ids, or
|
|
173
173
|
* - it has no explicit assignee and one of my ids sits on the executing side
|
|
174
|
-
* of the task/agreement (executor, agent, provider
|
|
175
|
-
* proposedTo).
|
|
174
|
+
* of the task/agreement (executor, agent, or either column of the provider /
|
|
175
|
+
* proposedTo party sides).
|
|
176
176
|
* Tasks with no assignee and no readable agreement parties are excluded —
|
|
177
177
|
* "can't tell" must not render as "yours".
|
|
178
178
|
*/
|
|
@@ -186,7 +186,7 @@ export function filterTasksForDelegate(tasks, selfIds) {
|
|
|
186
186
|
const p = t.agreement?.parties;
|
|
187
187
|
if (!p)
|
|
188
188
|
return false;
|
|
189
|
-
return
|
|
189
|
+
return [...partySideIds(p.provider), ...partySideIds(p.proposedTo)].some(mine);
|
|
190
190
|
});
|
|
191
191
|
}
|
|
192
192
|
export function buildActiveWorkItems(tasks, webOrigin) {
|
package/dist/tools.js
CHANGED
|
@@ -567,7 +567,7 @@ export function registerZiggsTools(server, creds, cfg) {
|
|
|
567
567
|
return toolError(e);
|
|
568
568
|
}
|
|
569
569
|
});
|
|
570
|
-
registerStrictTool(server, 'ziggs_agreement_fulfill', 'END an agreement you PROVIDE — permanently (POST /agreements/:id/fulfill). Fulfilling terminates the whole relationship, not one deliverable: every grant the agreement conferred (context, connection, payment) is revoked
|
|
570
|
+
registerStrictTool(server, 'ziggs_agreement_fulfill', 'END an agreement you PROVIDE — permanently (POST /agreements/:id/fulfill). Fulfilling terminates the whole relationship, not one deliverable: every grant the agreement conferred (context, connection, payment) is revoked and it cannot be reopened — the counterparty would have to re-hire you from scratch. Linked chats remain independent rooms governed by their own grants. Finished WORK is reported with ziggs_task_set_result, which closes the task and leaves the agreement standing for the next one. Only fulfill a count/time-bound engagement whose full scope is delivered and where nothing more is expected — never a standing hire that just finished a task. Party-gated server-side: only the providing side can fulfill.', {
|
|
571
571
|
agreementId: z.string().describe('The agreement you provide, to mark fulfilled'),
|
|
572
572
|
}, write('Close an agreement you provide'), async ({ agreementId }) => {
|
|
573
573
|
try {
|
|
@@ -722,11 +722,15 @@ export function registerZiggsTools(server, creds, cfg) {
|
|
|
722
722
|
assigneeId: z
|
|
723
723
|
.string()
|
|
724
724
|
.optional()
|
|
725
|
-
.describe('Agent or user ID to explicitly assign this task to — must
|
|
725
|
+
.describe('Agent or user ID to explicitly assign this task to — must hold a grant on the agreement, so you can only hand work to someone that contract already reaches'),
|
|
726
726
|
inputArtifactIds: z
|
|
727
727
|
.array(z.string())
|
|
728
728
|
.optional()
|
|
729
729
|
.describe('Artifact ids this task consumes as structured inputs — pass prior-step output handles without embedding them in description'),
|
|
730
|
+
waitsOn: z
|
|
731
|
+
.array(z.string())
|
|
732
|
+
.optional()
|
|
733
|
+
.describe('Task ids this task waits for. It is created now but its assignee is not woken, and cannot start it, until every task named here has finished — so you can state a join up front (four probes and a synthesis that waits on all four) instead of polling for each one and creating the next yourself. Releases when ALL of them are terminal, whatever state each reached; what a failed dependency means is your call. You must be able to read a task to name it here.'),
|
|
730
734
|
// POST /tasks and the SDK's task_create have always taken
|
|
731
735
|
// these three; only this surface hid them, so an agent on MCP had to
|
|
732
736
|
// create-then-replace_plan even when it already knew the steps.
|
|
@@ -760,7 +764,7 @@ export function registerZiggsTools(server, creds, cfg) {
|
|
|
760
764
|
.boolean()
|
|
761
765
|
.optional()
|
|
762
766
|
.describe('When true, restructuring the plan mid-task parks it for a fresh acknowledgement instead of applying silently.'),
|
|
763
|
-
}, write('Create a task'), async ({ agreementId, description, title, parentTaskId, assigneeId, inputArtifactIds, plan, planReviewTiming, requireMidWorkPlanAck, }) => {
|
|
767
|
+
}, write('Create a task'), async ({ agreementId, description, title, parentTaskId, assigneeId, inputArtifactIds, waitsOn, plan, planReviewTiming, requireMidWorkPlanAck, }) => {
|
|
764
768
|
try {
|
|
765
769
|
const task = await createTask({
|
|
766
770
|
agreementId,
|
|
@@ -769,6 +773,7 @@ export function registerZiggsTools(server, creds, cfg) {
|
|
|
769
773
|
parentTaskId,
|
|
770
774
|
assigneeId,
|
|
771
775
|
inputArtifactIds,
|
|
776
|
+
waitsOn,
|
|
772
777
|
plan,
|
|
773
778
|
planReviewTiming,
|
|
774
779
|
requireMidWorkPlanAck,
|
package/dist/trustTools.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { ContextGrantsClient, addChatMember, contextBounds, resolveOrgScopeId, LINK_CAPABILITIES, DISCOVERY_CAPABILITIES, contextDelegateCapability, } from '@ziggs-ai/api-client';
|
|
2
|
+
import { CONTEXT_GRANT_SCOPE_KINDS, ContextGrantsClient, addChatMember, contextBounds, resolveOrgScopeId, LINK_CAPABILITIES, DISCOVERY_CAPABILITIES, contextDelegateCapability, } from '@ziggs-ai/api-client';
|
|
3
3
|
import { write, destructive } from './toolAnnotations.js';
|
|
4
4
|
import { registerStrictTool } from './strictParams.js';
|
|
5
5
|
import { toolError } from './toolError.js';
|
|
6
6
|
import { registerCapabilities, registerCapability, textResult } from './capabilityAdapter.js';
|
|
7
|
-
// `artifact` is the narrowest context scope — one specific artifact,
|
|
8
|
-
//
|
|
9
|
-
|
|
7
|
+
// `artifact` is the narrowest context scope — one specific artifact, shared
|
|
8
|
+
// without sharing any container it sits in. `task` is a branch of a work graph:
|
|
9
|
+
// the named task and everything under it. Kept in step with the rail's own list
|
|
10
|
+
// (`CONTEXT_GRANT_SCOPE_KINDS`) rather than written out again — a literal subset
|
|
11
|
+
// still typechecks, which is how `task` was unaskable here after the server had
|
|
12
|
+
// it.
|
|
13
|
+
const grantScopeKindSchema = z.enum(CONTEXT_GRANT_SCOPE_KINDS);
|
|
10
14
|
const contextTemporalSchema = z.enum(['from-now', 'from-start']);
|
|
11
15
|
const DEFAULT_WEB_URL = 'https://ziggsai.com';
|
|
12
16
|
/** agent search + context grant management through MCP.
|
|
@@ -16,10 +20,10 @@ const DEFAULT_WEB_URL = 'https://ziggsai.com';
|
|
|
16
20
|
export function registerTrustTools(server, creds, cfg) {
|
|
17
21
|
const webUrl = cfg?.ZIGGS_WEB_URL?.replace(/\/$/, '') ?? DEFAULT_WEB_URL;
|
|
18
22
|
registerCapabilities(server, DISCOVERY_CAPABILITIES, creds);
|
|
19
|
-
registerStrictTool(server, 'ziggs_context_issue_grant', 'Issue bounded context access. Access comes from exactly two places and nothing else: an instrument authorizes it, or you delegate from a grant you already hold. The five instruments are creation (you made the scope), publication (the holder is a published agent), membership (you and the holder share an org), acceptance (a claimed invite or an approved admission), and agreement (a live deal whose parties cover both sides). The server names the instrument itself and refuses when none fits, saying what would create one, so you never pass a basis here. ONE scope works for you as a delegate: chat, which admits the agent via POST /chats/:id/members (agent-invite, pending_approval until humans consent). Agreement, org AND
|
|
23
|
+
registerStrictTool(server, 'ziggs_context_issue_grant', 'Issue bounded context access. Access comes from exactly two places and nothing else: an instrument authorizes it, or you delegate from a grant you already hold. The five instruments are creation (you made the scope), publication (the holder is a published agent), membership (you and the holder share an org), acceptance (a claimed invite or an approved admission), and agreement (a live deal whose parties cover both sides). The server names the instrument itself and refuses when none fits, saying what would create one, so you never pass a basis here. ONE scope works for you as a delegate: chat, which admits the agent via POST /chats/:id/members (agent-invite, pending_approval until humans consent). Agreement, org, artifact AND task scope all mint a NEW root grant, which is a human-authority action: acting for a principal you are denied (AGENT_LACKS_HUMAN_AUTHORITY) on all four alike, before the scope is even read. Your paths instead: ziggs_artifact_share for an artifact YOU authored (no human authority needed), ziggs_context_delegate to hand a peer a narrower slice of a grant you already hold — including a branch of a job you hold admit on — or ask your human to issue it. A delegated slice only narrows: never a stronger access kind, never a wider scope, never a later expiry than the parent. Artifact scope is always from-start (the artifact predates any watermark you could set) and refuses from-now. Defaults: from-now, narrow scope.', {
|
|
20
24
|
holderId: z.string().describe('Bare agent id receiving the grant'),
|
|
21
25
|
scopeKind: grantScopeKindSchema,
|
|
22
|
-
scopeId: z.string().describe('chatId, agreementId, orgId, or
|
|
26
|
+
scopeId: z.string().describe('chatId, agreementId, orgId, artifactId, or taskId'),
|
|
23
27
|
temporal: contextTemporalSchema
|
|
24
28
|
.optional()
|
|
25
29
|
.describe('from-now (default) or from-start (approval-gated on chat). Artifact ' +
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ziggs-ai/ziggs-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
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": {
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
42
|
-
"@ziggs-ai/api-client": "0.
|
|
42
|
+
"@ziggs-ai/api-client": "0.13.0",
|
|
43
43
|
"dotenv": "^16.6.1",
|
|
44
44
|
"zod": "^3.24.2",
|
|
45
45
|
"zod-to-json-schema": "^3.25.1"
|
|
@@ -45,16 +45,20 @@ connection) **is just an agreement** (`engagementKind: "link"`). Create it, the
|
|
|
45
45
|
counterparty owner approves it, and unpublished delegates can then reach each other.
|
|
46
46
|
|
|
47
47
|
1. Human describes goal and counterparty.
|
|
48
|
-
2.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
2. Connect with **`ziggs_link_propose`**: pass `to` = their email address, or the id of an
|
|
49
|
+
agent that answers to them (use `ziggs_agent_search` to find agents — do not guess ids).
|
|
50
|
+
The link is with the PERSON either way; an agent answering to an organisation is refused,
|
|
51
|
+
because a link connects two people. Leave `to` out and you get `shareUrl` to hand your
|
|
52
|
+
human; the recipient claims it with **`ziggs_agreement_claim`**. The reply is identical
|
|
53
|
+
every time, so it never reveals whether an address has an account.
|
|
52
54
|
3. Target human approves via **`ziggs_agreement_respond`** (action `approve`) when the
|
|
53
55
|
pending link agreement shows in their inbox / `ziggs_link_list`. This is the same generic
|
|
54
56
|
approval tool used for hire and service proposals — there is no separate link-response tool.
|
|
55
|
-
4. **A link ≠ a grant.** The link only
|
|
56
|
-
chat or read context, continue with **`ziggs_chat_open`** (participantId = peer
|
|
57
|
-
|
|
57
|
+
4. **A link ≠ a grant.** The link only makes the two people reachable to each other. To
|
|
58
|
+
chat or read context, continue with **`ziggs_chat_open`** (participantId = the peer
|
|
59
|
+
PRINCIPAL, a person: delivery lands in their mailbox and whoever runs that side picks it
|
|
60
|
+
up) and/or **`ziggs_context_issue_grant`** — still approval-gated when exposing existing
|
|
61
|
+
scope.
|
|
58
62
|
5. `ziggs_context_read` only after grant is active.
|
|
59
63
|
6. `ziggs_context_revoke_grant` when context access should end; **`ziggs_agreement_revoke`** when
|
|
60
64
|
the agreement should end — any kind: hire, service, request, offer, or link.
|