@ziggs-ai/ziggs-mcp 0.41.6 → 0.41.8
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/CHANGELOG.md +11 -0
- package/README.md +0 -1
- package/dist/directorySurface.js +2 -2
- package/dist/inboxCompact.d.ts +24 -17
- package/dist/inboxCompact.js +80 -37
- package/dist/retiredCalls.d.ts +12 -0
- package/dist/retiredCalls.js +29 -0
- package/dist/retiredTools.d.ts +62 -0
- package/dist/retiredTools.js +174 -0
- package/dist/server.js +2 -0
- package/dist/surface.js +9 -1
- package/dist/toolAliases.d.ts +5 -8
- package/dist/toolAliases.js +5 -10
- package/dist/tools.js +4 -2
- package/dist/trustTools.d.ts +2 -2
- package/dist/trustTools.js +2 -2
- package/package.json +3 -3
- package/skills/ziggs/references/grants-and-approvals.md +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.41.8
|
|
6
|
+
|
|
7
|
+
- Calling a tool Ziggs removed now answers with an error the assistant can act on, not the SDK's bare "not found". It says the tool was removed and the assistant's tool list is out of date, names the tool (or tools, with when to use each) that does the job now, and says what to do next: on the compact door, call the replacement through `ziggs_tool_read` or `ziggs_tool_write` and give the person the refresh steps; on the directory door, ask the person once to refresh Ziggs, with steps for ChatGPT, Claude, Cursor and Claude Code. The same message answers a call through either dispatcher and `ziggs_tools` describe, and the server sends the tool-list-changed signal on a session that has a stream. `ziggs_tools` search finds the replacement for a retired word. 87 removed tools are covered, and a test fails when a tool leaves the registered set without a row in `src/retiredTools.ts`.
|
|
8
|
+
- Bucket tools no longer take `agreement` items: an agreement brings its people into a bucket rather than going into one. `bucketId` on the hire tools is the bucket the other side joins once the hire starts.
|
|
9
|
+
|
|
10
|
+
## 0.41.7
|
|
11
|
+
|
|
12
|
+
- `ziggs_artifact_share` is removed from every surface, the directory included: an artifact reaches people only by being added to a bucket.
|
|
13
|
+
- The inbox groups rows by the bucket they were sent in: each section lists its buckets, each with `bucketId`, `revision`, `count` and its rows oldest first, every row saying its own `from`. Rows in no bucket you are in stay grouped by sender, then thread.
|
|
14
|
+
- The compact door lists the bucket tools: create, list, read, insert, remove, duplicate, move (into another bucket or a new one), add members, join, send inside a bucket, remove a member, rename and delete.
|
|
15
|
+
|
|
5
16
|
## 0.41.6
|
|
6
17
|
|
|
7
18
|
## 0.41.5
|
package/README.md
CHANGED
|
@@ -160,7 +160,6 @@ Startup validates the key shape, expiry (JWT `exp`), and agent resolution. Error
|
|
|
160
160
|
| `ziggs_context_read` | `GET /context/read/:type` |
|
|
161
161
|
| `ziggs_artifact_record` | `POST /artifacts` |
|
|
162
162
|
| `ziggs_artifact_list` | `GET /artifacts` |
|
|
163
|
-
| `ziggs_artifact_share` | `POST /context/artifacts/:id/share` |
|
|
164
163
|
| `ziggs_artifact_attach` | `POST /tasks/:id/artifacts` or `POST /agreements/:id/artifacts`; exact message references use `ziggs_message_send` |
|
|
165
164
|
| `ziggs_artifact_upload_url` | `POST /artifacts/upload-url` (+ optional S3 PUT) |
|
|
166
165
|
| `ziggs_artifact_complete_file` | `POST /artifacts/:id/complete` |
|
package/dist/directorySurface.js
CHANGED
|
@@ -11,7 +11,7 @@ ziggs_agreement_respond ziggs_agreement_revoke ziggs_agreement_counter ziggs_agr
|
|
|
11
11
|
ziggs_inbox_changes ziggs_inbox_peek ziggs_inbox ziggs_inbox_show ziggs_inbox_claim ziggs_inbox_ack ziggs_inbox_defer
|
|
12
12
|
ziggs_grant_list ziggs_context_expand_reach ziggs_context_discover_grantable
|
|
13
13
|
ziggs_open ziggs_access_explain ziggs_context_read
|
|
14
|
-
ziggs_artifact_record ziggs_artifact_list ziggs_artifact_find
|
|
14
|
+
ziggs_artifact_record ziggs_artifact_list ziggs_artifact_find
|
|
15
15
|
ziggs_artifact_attach ziggs_artifact_contribution_review ziggs_artifact_contribute
|
|
16
16
|
ziggs_artifact_upload_url ziggs_artifact_complete_file ziggs_artifact_download
|
|
17
17
|
ziggs_message_read ziggs_message_send ziggs_message_replies ziggs_message_list ziggs_message_controls
|
|
@@ -34,7 +34,7 @@ const OPEN_WORLD = new Set(`
|
|
|
34
34
|
ziggs_agent_search ziggs_agent_get ziggs_marketplace_view
|
|
35
35
|
ziggs_agreement_buy ziggs_agreement_bid ziggs_agreement_broker ziggs_agreement_request
|
|
36
36
|
ziggs_agreement_handoff ziggs_agreement_claim ziggs_agreement_subcontract
|
|
37
|
-
ziggs_task_delegate
|
|
37
|
+
ziggs_task_delegate ziggs_artifact_attach ziggs_artifact_contribute
|
|
38
38
|
ziggs_message_send ziggs_context_delegate ziggs_access_request
|
|
39
39
|
ziggs_link_propose ziggs_introduction_mint ziggs_introduction_redeem
|
|
40
40
|
`.trim().split(/\s+/));
|
package/dist/inboxCompact.d.ts
CHANGED
|
@@ -27,11 +27,12 @@
|
|
|
27
27
|
* the ack step's — is passed through byte for byte.
|
|
28
28
|
*
|
|
29
29
|
* The rows are written grouped rather than as one flat list: by who they are
|
|
30
|
-
* for, then by
|
|
31
|
-
* about. A flat list mixed the
|
|
32
|
-
* only passes along to its person and mail
|
|
33
|
-
* assistants, and the split lived in one sentence of
|
|
34
|
-
* still there, oldest first inside its thread;
|
|
30
|
+
* for, then by the bucket they were sent in, or, outside a bucket, by who sent
|
|
31
|
+
* them and the chat, task or agreement they are about. A flat list mixed the
|
|
32
|
+
* assistant's own work with mail it only passes along to its person and mail
|
|
33
|
+
* for the person's other assistants, and the split lived in one sentence of
|
|
34
|
+
* counts. Every row is still there, oldest first inside its bucket or thread;
|
|
35
|
+
* see {@link groupDeliveries}.
|
|
35
36
|
*/
|
|
36
37
|
type Json = Record<string, unknown>;
|
|
37
38
|
/** One delivery row, without what it would say by default or elsewhere. */
|
|
@@ -54,20 +55,26 @@ export type InboxSection = (typeof INBOX_SECTIONS)[number];
|
|
|
54
55
|
*/
|
|
55
56
|
export declare function sectionOf(row: Json, agentIds: readonly string[]): InboxSection;
|
|
56
57
|
/**
|
|
57
|
-
* The window's rows, grouped: section, then
|
|
58
|
+
* The window's rows, grouped: section, then bucket, then the rows in it. A
|
|
59
|
+
* row in no bucket the reader is in goes under its sender, then its thread.
|
|
58
60
|
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* side did, not news from anyone.
|
|
61
|
+
* A bucket is the context its rows were sent in, so it holds them together
|
|
62
|
+
* whoever sent them: each of its rows says its own `from`, oldest first. The
|
|
63
|
+
* bucket's name and contents are a bucket read away; a reply to one of its
|
|
64
|
+
* messages goes back into it.
|
|
64
65
|
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
66
|
+
* Nothing is hidden and nothing is reordered within a bucket or a thread.
|
|
67
|
+
* Groups and threads are written in the order their oldest row arrived, which
|
|
68
|
+
* is the order the server sends (oldest first), except that the reader's own
|
|
69
|
+
* actions and their person's outside a bucket come last in a section: they
|
|
70
|
+
* are a record of what this side did, not news from anyone.
|
|
71
|
+
*
|
|
72
|
+
* A row drops only what its place in the grouping says: its bucket (the
|
|
73
|
+
* group's), the sender (a sender group's `from`), the thread's own id, the
|
|
74
|
+
* assignee in `forYou` when the connection has one assistant, and
|
|
75
|
+
* `needsHuman` in `forYourPerson`. A thread names the first agreement its
|
|
76
|
+
* rows sit under; a row under another one keeps its own, and a row under none
|
|
77
|
+
* says `agreementId: null`, so every row reads back exactly.
|
|
71
78
|
*/
|
|
72
79
|
export declare function groupDeliveries(rows: readonly Json[], reader: InboxReader, compactRow?: (row: Json) => Json): Partial<Record<InboxSection, Json[]>>;
|
|
73
80
|
/**
|
package/dist/inboxCompact.js
CHANGED
|
@@ -27,11 +27,12 @@
|
|
|
27
27
|
* the ack step's — is passed through byte for byte.
|
|
28
28
|
*
|
|
29
29
|
* The rows are written grouped rather than as one flat list: by who they are
|
|
30
|
-
* for, then by
|
|
31
|
-
* about. A flat list mixed the
|
|
32
|
-
* only passes along to its person and mail
|
|
33
|
-
* assistants, and the split lived in one sentence of
|
|
34
|
-
* still there, oldest first inside its thread;
|
|
30
|
+
* for, then by the bucket they were sent in, or, outside a bucket, by who sent
|
|
31
|
+
* them and the chat, task or agreement they are about. A flat list mixed the
|
|
32
|
+
* assistant's own work with mail it only passes along to its person and mail
|
|
33
|
+
* for the person's other assistants, and the split lived in one sentence of
|
|
34
|
+
* counts. Every row is still there, oldest first inside its bucket or thread;
|
|
35
|
+
* see {@link groupDeliveries}.
|
|
35
36
|
*/
|
|
36
37
|
const isRecord = (v) => !!v && typeof v === 'object' && !Array.isArray(v);
|
|
37
38
|
/** Session fields `ziggs_auth_status` carries; the inbox does not repeat them. */
|
|
@@ -125,51 +126,77 @@ function anchorOf(row) {
|
|
|
125
126
|
return ['agreementId', String(row.agreementId)];
|
|
126
127
|
return [row.kind === 'artifact' ? 'artifactId' : 'resourceId', String(row.resourceId)];
|
|
127
128
|
}
|
|
129
|
+
/** The bucket the server says a row was put in, if any. */
|
|
130
|
+
function bucketOf(row) {
|
|
131
|
+
const bucket = row.bucket;
|
|
132
|
+
if (!isRecord(bucket) || !bucket.bucketId)
|
|
133
|
+
return null;
|
|
134
|
+
return { bucketId: String(bucket.bucketId), revision: bucket.revision };
|
|
135
|
+
}
|
|
128
136
|
/**
|
|
129
|
-
* The window's rows, grouped: section, then
|
|
137
|
+
* The window's rows, grouped: section, then bucket, then the rows in it. A
|
|
138
|
+
* row in no bucket the reader is in goes under its sender, then its thread.
|
|
139
|
+
*
|
|
140
|
+
* A bucket is the context its rows were sent in, so it holds them together
|
|
141
|
+
* whoever sent them: each of its rows says its own `from`, oldest first. The
|
|
142
|
+
* bucket's name and contents are a bucket read away; a reply to one of its
|
|
143
|
+
* messages goes back into it.
|
|
130
144
|
*
|
|
131
|
-
* Nothing is hidden and nothing is reordered within a thread.
|
|
132
|
-
* threads are written in the order their oldest row arrived, which
|
|
133
|
-
* order the server sends (oldest first), except that the reader's own
|
|
134
|
-
* and their person's come last in a section: they
|
|
135
|
-
* side did, not news from anyone.
|
|
145
|
+
* Nothing is hidden and nothing is reordered within a bucket or a thread.
|
|
146
|
+
* Groups and threads are written in the order their oldest row arrived, which
|
|
147
|
+
* is the order the server sends (oldest first), except that the reader's own
|
|
148
|
+
* actions and their person's outside a bucket come last in a section: they
|
|
149
|
+
* are a record of what this side did, not news from anyone.
|
|
136
150
|
*
|
|
137
|
-
* A row drops only what its place in the grouping says:
|
|
138
|
-
* group's `from`), the thread's own id, the
|
|
139
|
-
* connection has one assistant, and
|
|
140
|
-
* names the first agreement its
|
|
141
|
-
*
|
|
142
|
-
* back exactly.
|
|
151
|
+
* A row drops only what its place in the grouping says: its bucket (the
|
|
152
|
+
* group's), the sender (a sender group's `from`), the thread's own id, the
|
|
153
|
+
* assignee in `forYou` when the connection has one assistant, and
|
|
154
|
+
* `needsHuman` in `forYourPerson`. A thread names the first agreement its
|
|
155
|
+
* rows sit under; a row under another one keeps its own, and a row under none
|
|
156
|
+
* says `agreementId: null`, so every row reads back exactly.
|
|
143
157
|
*/
|
|
144
158
|
export function groupDeliveries(rows, reader, compactRow = (row) => ({ ...row })) {
|
|
145
159
|
const sections = new Map();
|
|
146
160
|
for (const row of rows) {
|
|
147
161
|
const section = sectionOf(row, reader.agentIds);
|
|
162
|
+
let groups = sections.get(section);
|
|
163
|
+
if (!groups)
|
|
164
|
+
sections.set(section, (groups = new Map()));
|
|
165
|
+
const bucket = bucketOf(row);
|
|
166
|
+
if (bucket) {
|
|
167
|
+
const key = `bucket:${bucket.bucketId}`;
|
|
168
|
+
let group = groups.get(key);
|
|
169
|
+
if (!group)
|
|
170
|
+
groups.set(key, (group = { kind: 'bucket', ...bucket, rows: [] }));
|
|
171
|
+
group.rows.push(row);
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
148
174
|
const from = row.actorId ? String(row.actorId) : null;
|
|
149
175
|
const anchor = anchorOf(row);
|
|
150
|
-
let
|
|
151
|
-
if (!senders)
|
|
152
|
-
sections.set(section, (senders = new Map()));
|
|
153
|
-
let group = senders.get(String(from));
|
|
176
|
+
let group = groups.get(`from:${from}`);
|
|
154
177
|
if (!group)
|
|
155
|
-
|
|
178
|
+
groups.set(`from:${from}`, (group = { kind: 'sender', from, threads: new Map() }));
|
|
156
179
|
const key = anchor.join(':');
|
|
157
180
|
let thread = group.threads.get(key);
|
|
158
181
|
if (!thread)
|
|
159
182
|
group.threads.set(key, (thread = { anchor, rows: [] }));
|
|
160
183
|
thread.rows.push(row);
|
|
161
184
|
}
|
|
162
|
-
const own = (
|
|
185
|
+
const own = (g) => g.kind === 'sender' &&
|
|
186
|
+
g.from !== null &&
|
|
187
|
+
(reader.agentIds.includes(g.from) || g.from === reader.personId);
|
|
163
188
|
const out = {};
|
|
164
189
|
for (const section of INBOX_SECTIONS) {
|
|
165
|
-
const
|
|
166
|
-
if (!
|
|
190
|
+
const groups = sections.get(section);
|
|
191
|
+
if (!groups)
|
|
167
192
|
continue;
|
|
168
|
-
const ordered = [...
|
|
193
|
+
const ordered = [...groups.values()];
|
|
169
194
|
out[section] = [
|
|
170
|
-
...ordered.filter((g) => !own(g
|
|
171
|
-
...ordered.filter((g) => own(g
|
|
195
|
+
...ordered.filter((g) => !own(g)),
|
|
196
|
+
...ordered.filter((g) => own(g)),
|
|
172
197
|
].map((g) => {
|
|
198
|
+
if (g.kind === 'bucket')
|
|
199
|
+
return writeBucket(g, section, reader, compactRow);
|
|
173
200
|
const threads = [...g.threads.values()].map((t) => writeThread(t, section, reader, compactRow));
|
|
174
201
|
const count = [...g.threads.values()].reduce((n, t) => n + t.rows.length, 0);
|
|
175
202
|
return {
|
|
@@ -183,6 +210,29 @@ export function groupDeliveries(rows, reader, compactRow = (row) => ({ ...row })
|
|
|
183
210
|
}
|
|
184
211
|
return out;
|
|
185
212
|
}
|
|
213
|
+
/** What a row's section already says about it. */
|
|
214
|
+
function dropWhatTheSectionSays(row, section, reader) {
|
|
215
|
+
if (section === 'forYou') {
|
|
216
|
+
if (reader.agentIds.length === 1)
|
|
217
|
+
delete row.assigneeId;
|
|
218
|
+
if (row.assignedToConnection === true)
|
|
219
|
+
delete row.assignedToConnection;
|
|
220
|
+
}
|
|
221
|
+
if (section === 'forYourPerson')
|
|
222
|
+
delete row.needsHuman;
|
|
223
|
+
}
|
|
224
|
+
function writeBucket(group, section, reader, compactRow) {
|
|
225
|
+
const rows = group.rows.map((original) => {
|
|
226
|
+
const { actorId, ...row } = compactRow(original);
|
|
227
|
+
// Every row of one read carries the bucket's revision at that read; one
|
|
228
|
+
// that somehow differs keeps its own.
|
|
229
|
+
if (bucketOf(row)?.revision === group.revision)
|
|
230
|
+
delete row.bucket;
|
|
231
|
+
dropWhatTheSectionSays(row, section, reader);
|
|
232
|
+
return actorId ? { from: actorId, ...row } : row;
|
|
233
|
+
});
|
|
234
|
+
return { bucketId: group.bucketId, revision: group.revision, count: rows.length, rows };
|
|
235
|
+
}
|
|
186
236
|
function writeThread(thread, section, reader, compactRow) {
|
|
187
237
|
const [field, id] = thread.anchor;
|
|
188
238
|
const lifted = field === 'agreementId'
|
|
@@ -199,14 +249,7 @@ function writeThread(thread, section, reader, compactRow) {
|
|
|
199
249
|
else if (!row.agreementId)
|
|
200
250
|
row.agreementId = null;
|
|
201
251
|
}
|
|
202
|
-
|
|
203
|
-
if (reader.agentIds.length === 1)
|
|
204
|
-
delete row.assigneeId;
|
|
205
|
-
if (row.assignedToConnection === true)
|
|
206
|
-
delete row.assignedToConnection;
|
|
207
|
-
}
|
|
208
|
-
if (section === 'forYourPerson')
|
|
209
|
-
delete row.needsHuman;
|
|
252
|
+
dropWhatTheSectionSays(row, section, reader);
|
|
210
253
|
return row;
|
|
211
254
|
});
|
|
212
255
|
return { [field]: id, ...(lifted ? { agreementId: lifted } : {}), rows };
|
|
@@ -299,5 +342,5 @@ export function windowNote(deliveries, selfAgentIds) {
|
|
|
299
342
|
const parts = INBOX_SECTIONS.filter((s) => s === 'forYou' || count(s) > 0).map((s) => `${s} ${count(s)} (${words[s]})`);
|
|
300
343
|
const reach = outOfReach ? ` ${outOfReach} of them ${outOfReach === 1 ? 'is' : 'are'} out of reach.` : '';
|
|
301
344
|
const total = `${rows.length} ${rows.length === 1 ? 'delivery' : 'deliveries'}`;
|
|
302
|
-
return `Those counts are decisions and tasks, not messages. This window has ${total}, grouped by who they are for, then by sender: ${parts.join(', ')}.${reach}`;
|
|
345
|
+
return `Those counts are decisions and tasks, not messages. This window has ${total}, grouped by who they are for, then by bucket, or by sender outside a bucket: ${parts.join(', ')}.${reach}`;
|
|
303
346
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { type Door } from './retiredTools.js';
|
|
3
|
+
/**
|
|
4
|
+
* Answer a direct call to a removed tool with the removed-tool message, before
|
|
5
|
+
* the MCP SDK can say only that the tool was not found. Wraps whatever
|
|
6
|
+
* `tools/call` handler is installed, so call it after every other one.
|
|
7
|
+
*
|
|
8
|
+
* On a session that keeps an open stream, the tool-list-changed signal goes out
|
|
9
|
+
* as well, so an app that acts on it reloads its list without its person doing
|
|
10
|
+
* anything. A session with no stream has nobody to tell; that is not an error.
|
|
11
|
+
*/
|
|
12
|
+
export declare function answerRetiredCalls(server: McpServer, door: Door): void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import { doorContext, retiredTool, retiredToolResult } from './retiredTools.js';
|
|
3
|
+
/**
|
|
4
|
+
* Answer a direct call to a removed tool with the removed-tool message, before
|
|
5
|
+
* the MCP SDK can say only that the tool was not found. Wraps whatever
|
|
6
|
+
* `tools/call` handler is installed, so call it after every other one.
|
|
7
|
+
*
|
|
8
|
+
* On a session that keeps an open stream, the tool-list-changed signal goes out
|
|
9
|
+
* as well, so an app that acts on it reloads its list without its person doing
|
|
10
|
+
* anything. A session with no stream has nobody to tell; that is not an error.
|
|
11
|
+
*/
|
|
12
|
+
export function answerRetiredCalls(server, door) {
|
|
13
|
+
const inner = server.server;
|
|
14
|
+
const built = inner._requestHandlers?.get('tools/call');
|
|
15
|
+
if (!built)
|
|
16
|
+
return;
|
|
17
|
+
server.server.setRequestHandler(CallToolRequestSchema, (async (req, extra) => {
|
|
18
|
+
const retired = retiredTool(req.params.name);
|
|
19
|
+
if (!retired)
|
|
20
|
+
return built(req, extra);
|
|
21
|
+
try {
|
|
22
|
+
server.sendToolListChanged();
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// No open stream on this session.
|
|
26
|
+
}
|
|
27
|
+
return retiredToolResult(req.params.name, retired, doorContext(server, door));
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
/**
|
|
3
|
+
* Tools we removed, and what replaced them.
|
|
4
|
+
*
|
|
5
|
+
* An assistant that loaded its Ziggs tool list before a removal still holds the
|
|
6
|
+
* old name. Without this table the call dies on the MCP SDK's bare "not found",
|
|
7
|
+
* and the assistant tells its person Ziggs is broken. Every way of reaching a
|
|
8
|
+
* tool by name reads this table: a direct call, both dispatchers, and describe.
|
|
9
|
+
*
|
|
10
|
+
* Retired names are never registered, so they never appear in `tools/list`.
|
|
11
|
+
* Removing a tool adds its row in the same change; retiredTools.test.ts fails
|
|
12
|
+
* when a name leaves the registered set without one.
|
|
13
|
+
*/
|
|
14
|
+
export interface Replacement {
|
|
15
|
+
tool: string;
|
|
16
|
+
/** When to use this one, for a job that was split across several tools. */
|
|
17
|
+
when?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface RetiredTool {
|
|
20
|
+
/** The tools that do the job now. Empty when nothing replaces it. */
|
|
21
|
+
use: Replacement[];
|
|
22
|
+
/** What changed, in one line. */
|
|
23
|
+
note?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare const RETIRED_TOOLS: Readonly<Record<string, RetiredTool>>;
|
|
26
|
+
export declare function retiredTool(name: string): RetiredTool | undefined;
|
|
27
|
+
/** The replacement tools for a search word such as `commission` or `ziggs_quest`. */
|
|
28
|
+
export declare function retiredReplacementsFor(needle: string): string[];
|
|
29
|
+
export type Door = 'compact' | 'directory';
|
|
30
|
+
/** How a person refreshes Ziggs in the app the connection came from. */
|
|
31
|
+
export declare function refreshSteps(clientName: string | undefined): string;
|
|
32
|
+
/**
|
|
33
|
+
* The tool result for a call to a removed tool: an ordinary error the assistant
|
|
34
|
+
* can act on. The compact door can call the replacement through its dispatcher
|
|
35
|
+
* at once; the directory door cannot call a tool that is not in its list, so
|
|
36
|
+
* its message asks the person to refresh, once.
|
|
37
|
+
*/
|
|
38
|
+
export declare function retiredToolResult(name: string, retired: RetiredTool, ctx: {
|
|
39
|
+
door: Door;
|
|
40
|
+
clientName?: string;
|
|
41
|
+
}): {
|
|
42
|
+
structuredContent: {
|
|
43
|
+
error: {
|
|
44
|
+
code: string;
|
|
45
|
+
message: string;
|
|
46
|
+
retired: {
|
|
47
|
+
name: string;
|
|
48
|
+
replacements: Replacement[];
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
content: {
|
|
53
|
+
type: "text";
|
|
54
|
+
text: string;
|
|
55
|
+
}[];
|
|
56
|
+
isError: boolean;
|
|
57
|
+
};
|
|
58
|
+
/** Which door this server was built for, and the client's name once it has connected. */
|
|
59
|
+
export declare function doorContext(server: McpServer, door: Door): {
|
|
60
|
+
door: Door;
|
|
61
|
+
clientName: string | undefined;
|
|
62
|
+
};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { toolError } from './toolError.js';
|
|
2
|
+
const same = (tool, note) => ({ use: [{ tool }], ...(note ? { note } : {}) });
|
|
3
|
+
const gone = (note) => ({ use: [], note });
|
|
4
|
+
const split = (...use) => ({
|
|
5
|
+
use: use.map(([tool, when]) => ({ tool, when })),
|
|
6
|
+
});
|
|
7
|
+
/** One tool does the same job under a new name. */
|
|
8
|
+
const RENAMED = [
|
|
9
|
+
['ziggs_agreement_commission', 'ziggs_agreement_buy'],
|
|
10
|
+
['ziggs_agreement_quest', 'ziggs_agreement_request'],
|
|
11
|
+
['ziggs_cancel_task', 'ziggs_task_cancel'],
|
|
12
|
+
['ziggs_chat_open', 'ziggs_message_send', 'There is no room to open; send the message.'],
|
|
13
|
+
['ziggs_chat_send', 'ziggs_message_send'],
|
|
14
|
+
['ziggs_claim_link_invite', 'ziggs_agreement_claim'],
|
|
15
|
+
['ziggs_claim_offer', 'ziggs_agreement_claim'],
|
|
16
|
+
['ziggs_connection_status', 'ziggs_auth_status'],
|
|
17
|
+
['ziggs_context_request', 'ziggs_access_request'],
|
|
18
|
+
['ziggs_conversation_send', 'ziggs_message_send'],
|
|
19
|
+
['ziggs_counter_agreement', 'ziggs_agreement_counter'],
|
|
20
|
+
['ziggs_create_link_invite', 'ziggs_link_propose'],
|
|
21
|
+
['ziggs_create_party_connection_invite', 'ziggs_link_propose'],
|
|
22
|
+
['ziggs_create_task', 'ziggs_task_create'],
|
|
23
|
+
['ziggs_delegate_grant', 'ziggs_context_delegate'],
|
|
24
|
+
['ziggs_discover_grantable', 'ziggs_context_discover_grantable'],
|
|
25
|
+
['ziggs_expand_context', 'ziggs_context_expand_reach'],
|
|
26
|
+
['ziggs_fulfill_agreement', 'ziggs_agreement_fulfill'],
|
|
27
|
+
['ziggs_get_active_tasks', 'ziggs_task_list'],
|
|
28
|
+
['ziggs_get_agent', 'ziggs_agent_get'],
|
|
29
|
+
['ziggs_get_agreement', 'ziggs_agreement_get'],
|
|
30
|
+
['ziggs_get_scope', 'ziggs_context_snapshot'],
|
|
31
|
+
['ziggs_get_task', 'ziggs_task_get'],
|
|
32
|
+
['ziggs_inbox_park', 'ziggs_inbox_defer'],
|
|
33
|
+
['ziggs_issue_grant', 'ziggs_context_delegate'],
|
|
34
|
+
['ziggs_link_create_invite', 'ziggs_link_propose'],
|
|
35
|
+
['ziggs_list_connections', 'ziggs_connection_list'],
|
|
36
|
+
['ziggs_list_grants', 'ziggs_grant_list'],
|
|
37
|
+
['ziggs_list_links', 'ziggs_link_list'],
|
|
38
|
+
['ziggs_list_messages', 'ziggs_message_list'],
|
|
39
|
+
['ziggs_list_my_agreements', 'ziggs_agreement_list'],
|
|
40
|
+
['ziggs_list_my_connections', 'ziggs_connection_list'],
|
|
41
|
+
['ziggs_list_my_grants', 'ziggs_grant_list'],
|
|
42
|
+
['ziggs_list_my_orgs', 'ziggs_org_list'],
|
|
43
|
+
['ziggs_list_party_connections', 'ziggs_link_list'],
|
|
44
|
+
['ziggs_list_tasks', 'ziggs_task_list'],
|
|
45
|
+
['ziggs_open_conversation', 'ziggs_message_send'],
|
|
46
|
+
['ziggs_pending_decisions', 'ziggs_inbox', 'A fresh inbox read carries the decisions.'],
|
|
47
|
+
['ziggs_publish_quest', 'ziggs_agreement_request'],
|
|
48
|
+
['ziggs_read_context', 'ziggs_context_read'],
|
|
49
|
+
['ziggs_record_artifact', 'ziggs_artifact_record'],
|
|
50
|
+
['ziggs_redeem_party_connection_invite', 'ziggs_agreement_claim'],
|
|
51
|
+
['ziggs_request_connection_status', 'ziggs_connection_list'],
|
|
52
|
+
['ziggs_request_link', 'ziggs_link_propose'],
|
|
53
|
+
['ziggs_request_party_connection', 'ziggs_link_propose'],
|
|
54
|
+
['ziggs_respond_to_agreement', 'ziggs_agreement_respond'],
|
|
55
|
+
['ziggs_respond_to_party_connection', 'ziggs_agreement_respond'],
|
|
56
|
+
['ziggs_revoke_agreement', 'ziggs_agreement_revoke'],
|
|
57
|
+
['ziggs_revoke_grant', 'ziggs_context_revoke_grant'],
|
|
58
|
+
['ziggs_revoke_link', 'ziggs_agreement_revoke'],
|
|
59
|
+
['ziggs_revoke_party_connection', 'ziggs_agreement_revoke'],
|
|
60
|
+
['ziggs_search_agents', 'ziggs_agent_search'],
|
|
61
|
+
['ziggs_send_message', 'ziggs_message_send'],
|
|
62
|
+
['ziggs_set_task_result', 'ziggs_task_set_result'],
|
|
63
|
+
];
|
|
64
|
+
const PROPOSE = split(['ziggs_agreement_buy', 'you pay a named party'], ['ziggs_agreement_bid', 'you offer your work to a named party'], ['ziggs_agreement_request', 'an open call for anyone'], ['ziggs_agreement_broker', 'you arrange a deal between others'], ['ziggs_agreement_handoff', 'you pass your work on to someone else'], ['ziggs_link_propose', 'you want a link']);
|
|
65
|
+
const LISTING = gone("Posting and pausing a listing is the person's job in the web app. Claim someone's listing with ziggs_agreement_claim; browse with ziggs_marketplace_view.");
|
|
66
|
+
const ROOMS = gone('Rooms are gone. Read with ziggs_inbox or ziggs_message_list.');
|
|
67
|
+
const ANSWERS = gone('Messages are fyi or request now; there are no answer requests. Read replies with ziggs_message_replies.');
|
|
68
|
+
const PAYMENT = gone('Agents do not move points. ziggs_payment_balance is the only payment tool.');
|
|
69
|
+
const OTHER = [
|
|
70
|
+
['ziggs_agreement_propose', PROPOSE],
|
|
71
|
+
['ziggs_propose_agreement', PROPOSE],
|
|
72
|
+
['ziggs_context_issue_grant', split(['ziggs_context_delegate', 'a slice of a grant you hold'], ['ziggs_bucket_insert', 'one file: add it to a bucket'])],
|
|
73
|
+
['ziggs_conversation_read', split(['ziggs_message_read', 'one message'], ['ziggs_message_list', 'the whole thread, with conversationOf'])],
|
|
74
|
+
['ziggs_discover_context', split(['ziggs_grant_list', 'what you hold'], ['ziggs_context_discover_grantable', 'what exists that you cannot read yet'])],
|
|
75
|
+
['ziggs_list_artifacts', split(['ziggs_artifact_list', 'what you wrote'], ['ziggs_context_read', 'what is in a scope, with type artifacts'])],
|
|
76
|
+
['ziggs_post_task_plan_step', split(['ziggs_task_replace_plan', 'the whole plan'], ['ziggs_task_update_steps', 'progress only'])],
|
|
77
|
+
['ziggs_tool', split(['ziggs_tool_read', 'reads'], ['ziggs_tool_write', 'writes'])],
|
|
78
|
+
['ziggs_agreement_offer', LISTING],
|
|
79
|
+
['ziggs_publish_offer', LISTING],
|
|
80
|
+
['ziggs_listing_pause', LISTING],
|
|
81
|
+
['ziggs_listing_resume', LISTING],
|
|
82
|
+
['ziggs_chat_list', ROOMS],
|
|
83
|
+
['ziggs_list_chats', ROOMS],
|
|
84
|
+
['ziggs_message_answers', ANSWERS],
|
|
85
|
+
['ziggs_message_answer_cancel', ANSWERS],
|
|
86
|
+
['ziggs_payment_attenuate_grant', PAYMENT],
|
|
87
|
+
['ziggs_payment_hold', PAYMENT],
|
|
88
|
+
['ziggs_payment_issue_grant', PAYMENT],
|
|
89
|
+
['ziggs_payment_release', PAYMENT],
|
|
90
|
+
['ziggs_payment_resolve_wallet', PAYMENT],
|
|
91
|
+
['ziggs_payment_revoke_grant', PAYMENT],
|
|
92
|
+
['ziggs_payment_transfer', PAYMENT],
|
|
93
|
+
['ziggs_payment_wait_for_approval', PAYMENT],
|
|
94
|
+
['ziggs_context_record_message', gone('Send messages with ziggs_message_send.')],
|
|
95
|
+
['ziggs_context_record_thought', gone('Nothing replaces it. Save finished work with ziggs_artifact_record.')],
|
|
96
|
+
['ziggs_get_subtasks', gone('Nothing replaces it. Nearest: ziggs_task_list, ziggs_task_get.')],
|
|
97
|
+
['ziggs_mark_task_processing', gone('Nothing replaces it. Nearest: ziggs_inbox_claim.')],
|
|
98
|
+
['ziggs_update_task_state', gone('Nothing replaces it. Finish with ziggs_task_set_result or stop with ziggs_task_cancel.')],
|
|
99
|
+
['ziggs_switch_org', gone('The workspace is chosen when Ziggs is connected. See them with ziggs_org_list.')],
|
|
100
|
+
['ziggs_request_connection', gone('Requesting a connection is not a Ziggs MCP tool any more. See yours with ziggs_connection_list.')],
|
|
101
|
+
['ziggs_artifact_reextract', gone('Not an agent tool any more.')],
|
|
102
|
+
['ziggs_provision_relay_workers', gone('Not an agent tool any more. Engage agents with the agreement tools and ziggs_task_create.')],
|
|
103
|
+
];
|
|
104
|
+
export const RETIRED_TOOLS = Object.freeze({
|
|
105
|
+
...Object.fromEntries(RENAMED.map(([name, tool, note]) => [name, same(tool, note)])),
|
|
106
|
+
...Object.fromEntries(OTHER),
|
|
107
|
+
});
|
|
108
|
+
export function retiredTool(name) {
|
|
109
|
+
return Object.hasOwn(RETIRED_TOOLS, name) ? RETIRED_TOOLS[name] : undefined;
|
|
110
|
+
}
|
|
111
|
+
/** The replacement tools for a search word such as `commission` or `ziggs_quest`. */
|
|
112
|
+
export function retiredReplacementsFor(needle) {
|
|
113
|
+
const hits = new Set();
|
|
114
|
+
for (const candidate of [needle, `ziggs_${needle}`, `ziggs_agreement_${needle}`]) {
|
|
115
|
+
for (const entry of retiredTool(candidate)?.use ?? [])
|
|
116
|
+
hits.add(entry.tool);
|
|
117
|
+
}
|
|
118
|
+
return [...hits];
|
|
119
|
+
}
|
|
120
|
+
/** How a person refreshes Ziggs in the app the connection came from. */
|
|
121
|
+
export function refreshSteps(clientName) {
|
|
122
|
+
const name = (clientName ?? '').toLowerCase();
|
|
123
|
+
if (name.includes('chatgpt') || name.includes('openai'))
|
|
124
|
+
return 'In ChatGPT: Settings → Apps & Connectors → Ziggs → Refresh. ChatGPT never refreshes by itself. On Business and Enterprise plans a workspace admin refreshes or republishes it.';
|
|
125
|
+
if (name.includes('cursor'))
|
|
126
|
+
return 'In Cursor: turn Ziggs off and on in MCP settings, or restart Cursor. Cursor ignores the list-changed signal.';
|
|
127
|
+
if (name.includes('claude-code') || name.includes('claude code'))
|
|
128
|
+
return 'In Claude Code: run /mcp and reconnect Ziggs, or start a new session.';
|
|
129
|
+
if (name.includes('claude'))
|
|
130
|
+
return 'In Claude: Settings → Connectors → Ziggs → ⋯ → refresh the tool list, or remove Ziggs and add it again.';
|
|
131
|
+
return "Reconnect Ziggs in the app's connector settings, or start a new conversation.";
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* The tool result for a call to a removed tool: an ordinary error the assistant
|
|
135
|
+
* can act on. The compact door can call the replacement through its dispatcher
|
|
136
|
+
* at once; the directory door cannot call a tool that is not in its list, so
|
|
137
|
+
* its message asks the person to refresh, once.
|
|
138
|
+
*/
|
|
139
|
+
export function retiredToolResult(name, retired, ctx) {
|
|
140
|
+
const lines = [`${name} was removed from Ziggs, so your list of Ziggs tools is out of date.`];
|
|
141
|
+
if (retired.note)
|
|
142
|
+
lines.push(retired.note);
|
|
143
|
+
if (retired.use.length === 1) {
|
|
144
|
+
lines.push(`Use ${retired.use[0].tool} for this now.`);
|
|
145
|
+
}
|
|
146
|
+
else if (retired.use.length > 1) {
|
|
147
|
+
lines.push(`This job is now done by more than one tool: ${retired.use.map((u) => `${u.tool} (${u.when})`).join('; ')}.`);
|
|
148
|
+
}
|
|
149
|
+
if (ctx.door === 'compact') {
|
|
150
|
+
lines.push(retired.use.length
|
|
151
|
+
? 'Call the replacement now through ziggs_tool_read (read-only tools) or ziggs_tool_write (tools that change something), and also give your person these steps so your tool list is current:'
|
|
152
|
+
: 'Give your person these steps so your tool list is current:');
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
lines.push('You cannot call a tool that is not in your list. Ask your person, once per conversation, to refresh Ziggs:');
|
|
156
|
+
}
|
|
157
|
+
lines.push(refreshSteps(ctx.clientName));
|
|
158
|
+
const result = toolError(lines.join(' '));
|
|
159
|
+
const error = {
|
|
160
|
+
...result.structuredContent.error,
|
|
161
|
+
code: 'TOOL_RETIRED',
|
|
162
|
+
message: lines.join(' '),
|
|
163
|
+
retired: { name, replacements: retired.use },
|
|
164
|
+
};
|
|
165
|
+
return {
|
|
166
|
+
structuredContent: { error },
|
|
167
|
+
content: [{ type: 'text', text: JSON.stringify({ error }, null, 2) }],
|
|
168
|
+
isError: true,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/** Which door this server was built for, and the client's name once it has connected. */
|
|
172
|
+
export function doorContext(server, door) {
|
|
173
|
+
return { door, clientName: server.server.getClientVersion()?.name };
|
|
174
|
+
}
|
package/dist/server.js
CHANGED
|
@@ -10,6 +10,7 @@ import { loadConfig } from './config.js';
|
|
|
10
10
|
import { credsFromConfig } from './creds.js';
|
|
11
11
|
import { registerZiggsTools } from './tools.js';
|
|
12
12
|
import { applySurfacePolicy, listWithoutSchemaDialect } from './surface.js';
|
|
13
|
+
import { answerRetiredCalls } from './retiredCalls.js';
|
|
13
14
|
import { backendToolPick } from './toolPick.js';
|
|
14
15
|
import { renderConnectText } from './protocol/connectText.js';
|
|
15
16
|
import { CHANNEL_CAPABILITY, observeFor, startInboxChannel } from './inboxChannel.js';
|
|
@@ -44,6 +45,7 @@ export function createZiggsMcpServer(creds, cfg) {
|
|
|
44
45
|
if (cfg.directConnection !== false)
|
|
45
46
|
applySurfacePolicy(server, { pickTool: backendToolPick(creds) });
|
|
46
47
|
listWithoutSchemaDialect(server);
|
|
48
|
+
answerRetiredCalls(server, cfg.directConnection === false ? 'directory' : 'compact');
|
|
47
49
|
return server;
|
|
48
50
|
}
|
|
49
51
|
/** Drop this process's inbox host. Best-effort — shutdown must not fail on it. */
|
package/dist/surface.js
CHANGED
|
@@ -6,6 +6,7 @@ import { registerStrictTool } from './strictParams.js';
|
|
|
6
6
|
import { toolError } from './toolError.js';
|
|
7
7
|
import { textResult } from './capabilityAdapter.js';
|
|
8
8
|
import { aliasMatches } from './toolAliases.js';
|
|
9
|
+
import { doorContext, retiredReplacementsFor, retiredTool, retiredToolResult } from './retiredTools.js';
|
|
9
10
|
import { pickLine } from './toolPick.js';
|
|
10
11
|
import { catalogEntry, catalogFor, catalogRow, describeEntry, removeCatalogEntry, } from './toolCatalog.js';
|
|
11
12
|
/**
|
|
@@ -141,6 +142,9 @@ function registerDispatcher(server, lane) {
|
|
|
141
142
|
}, lane.annotations, async ({ tool, args }) => {
|
|
142
143
|
const entry = catalogEntry(server, tool);
|
|
143
144
|
if (!entry) {
|
|
145
|
+
const retired = retiredTool(tool);
|
|
146
|
+
if (retired)
|
|
147
|
+
return retiredToolResult(tool, retired, doorContext(server, 'compact'));
|
|
144
148
|
return toolError(`No such tool: ${tool}. Call ${TOOLS_CATALOG_NAME} for the full list of names.`);
|
|
145
149
|
}
|
|
146
150
|
// Each lane carries one kind of tool, so its annotation is true of every
|
|
@@ -218,6 +222,9 @@ export function applySurfacePolicy(server, opts = {}) {
|
|
|
218
222
|
unknown.push(name);
|
|
219
223
|
}
|
|
220
224
|
if (!found.length) {
|
|
225
|
+
const retired = unknown.map((name) => [name, retiredTool(name)]).find(([, r]) => r);
|
|
226
|
+
if (retired?.[1])
|
|
227
|
+
return retiredToolResult(retired[0], retired[1], doorContext(server, 'compact'));
|
|
221
228
|
return toolError(`No such tool: ${unknown.join(', ')}. Call ${TOOLS_CATALOG_NAME} with no arguments for the full list of names.`);
|
|
222
229
|
}
|
|
223
230
|
return textResult({
|
|
@@ -250,7 +257,8 @@ export function applySurfacePolicy(server, opts = {}) {
|
|
|
250
257
|
const rows = (needle
|
|
251
258
|
? all.filter((e) => e.name.toLowerCase().includes(needle) ||
|
|
252
259
|
e.title.toLowerCase().includes(needle) ||
|
|
253
|
-
aliasMatches(e.name, needle)
|
|
260
|
+
aliasMatches(e.name, needle) ||
|
|
261
|
+
retiredReplacementsFor(needle).includes(e.name))
|
|
254
262
|
: all).map((entry) => withCall(entry, catalogRow(entry)));
|
|
255
263
|
return textResult({
|
|
256
264
|
count: rows.length,
|
package/dist/toolAliases.d.ts
CHANGED
|
@@ -13,15 +13,12 @@
|
|
|
13
13
|
* appear in a catalog row, and cost nothing at connect time because the search
|
|
14
14
|
* runs server-side.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
16
|
+
* The word belonging here is the plain-English word for the intent, when our
|
|
17
|
+
* name is a term of art: "hire" for claim (the default) and for buy (a direct
|
|
18
|
+
* proposal), "subcontract" for the parent-rail verb.
|
|
17
19
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* "subcontract" for the parent-rail verb.
|
|
21
|
-
* 2. A name we retired. `agreement_commission` and `agreement_quest` were
|
|
22
|
-
* renamed before the surface went public; anything still holding the old
|
|
23
|
-
* word searches it and lands on the tool that replaced it, rather than on
|
|
24
|
-
* nothing.
|
|
20
|
+
* A retired name is not an alias: retiredTools.ts holds those, and search
|
|
21
|
+
* reads it, so anything still holding an old name lands on its replacement.
|
|
25
22
|
*/
|
|
26
23
|
export declare const SEARCH_ALIASES: Readonly<Record<string, readonly string[]>>;
|
|
27
24
|
/** Does `needle` match one of this tool's aliases? Substring, both ways. */
|
package/dist/toolAliases.js
CHANGED
|
@@ -13,15 +13,12 @@
|
|
|
13
13
|
* appear in a catalog row, and cost nothing at connect time because the search
|
|
14
14
|
* runs server-side.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
16
|
+
* The word belonging here is the plain-English word for the intent, when our
|
|
17
|
+
* name is a term of art: "hire" for claim (the default) and for buy (a direct
|
|
18
|
+
* proposal), "subcontract" for the parent-rail verb.
|
|
17
19
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* "subcontract" for the parent-rail verb.
|
|
21
|
-
* 2. A name we retired. `agreement_commission` and `agreement_quest` were
|
|
22
|
-
* renamed before the surface went public; anything still holding the old
|
|
23
|
-
* word searches it and lands on the tool that replaced it, rather than on
|
|
24
|
-
* nothing.
|
|
20
|
+
* A retired name is not an alias: retiredTools.ts holds those, and search
|
|
21
|
+
* reads it, so anything still holding an old name lands on its replacement.
|
|
25
22
|
*/
|
|
26
23
|
export const SEARCH_ALIASES = {
|
|
27
24
|
ziggs_message_send: ['contact', 'message someone', 'teammate', 'group'],
|
|
@@ -30,14 +27,12 @@ export const SEARCH_ALIASES = {
|
|
|
30
27
|
ziggs_agreement_claim: ['hire'],
|
|
31
28
|
ziggs_agreement_buy: [
|
|
32
29
|
'hire',
|
|
33
|
-
'commission', // retired name
|
|
34
30
|
'procure',
|
|
35
31
|
'outsource',
|
|
36
32
|
'engage',
|
|
37
33
|
],
|
|
38
34
|
ziggs_agreement_bid: ['sell', 'pitch', 'apply', 'tender', 'quote'],
|
|
39
35
|
ziggs_agreement_request: [
|
|
40
|
-
'quest', // retired name
|
|
41
36
|
'wanted',
|
|
42
37
|
'open call',
|
|
43
38
|
'rfp',
|
package/dist/tools.js
CHANGED
|
@@ -2,7 +2,7 @@ import { MESSAGING_CAPABILITIES } from '@ziggs-ai/api-client';
|
|
|
2
2
|
import { isDirectorySurface } from './directorySurface.js';
|
|
3
3
|
import { INBOX_CARD_TOOL_META, inboxCardResult, registerInboxCardResource, } from './inboxCard.js';
|
|
4
4
|
import { z } from 'zod';
|
|
5
|
-
import { presentResourceActions, getAgreement, getMyAgreements, respondToAgreement, revokeAgreement, counterAgreement, fulfillAgreement, ConnectionsClient, ContextReadClient, GrantsClient, InboxClient, SessionsClient, AssistantConnectionClient, createTask, updateTaskState, acknowledgeTaskControl, replaceTaskPlan, updateTaskPlanSteps, listTasks, getTask, getBackendUrl, fetchMyOrgs, fetchSessionAccess, isMcpOAuthDelegateSession, GRANTS_CAPABILITIES, AGREEMENT_TERMS_PARAMS, AGREEMENT_VERB_CAPABILITIES, LISTING_DOOR_CAPABILITIES, CONTEXT_GRANT_SCOPE_KINDS, contextReadCapability, openCapability, accessExplainCapability, contextExpandReachCapability, contextDiscoverGrantableCapability, recordArtifactCapability, listArtifactsCapability, findArtifactsCapability,
|
|
5
|
+
import { presentResourceActions, getAgreement, getMyAgreements, respondToAgreement, revokeAgreement, counterAgreement, fulfillAgreement, ConnectionsClient, ContextReadClient, GrantsClient, InboxClient, SessionsClient, AssistantConnectionClient, createTask, updateTaskState, acknowledgeTaskControl, replaceTaskPlan, updateTaskPlanSteps, listTasks, getTask, getBackendUrl, fetchMyOrgs, fetchSessionAccess, isMcpOAuthDelegateSession, GRANTS_CAPABILITIES, BUCKET_CAPABILITIES, AGREEMENT_TERMS_PARAMS, AGREEMENT_VERB_CAPABILITIES, LISTING_DOOR_CAPABILITIES, CONTEXT_GRANT_SCOPE_KINDS, contextReadCapability, openCapability, accessExplainCapability, contextExpandReachCapability, contextDiscoverGrantableCapability, recordArtifactCapability, listArtifactsCapability, findArtifactsCapability, attachArtifactCapability, reviewArtifactContributionCapability, contributeArtifactCapability, uploadArtifactUrlCapability, completeArtifactFileCapability, downloadArtifactCapability, connectionProxyCapability, requestConnectionCapability, agreementClaimCapability, agreementSubcontractCapability, listTasksCapability, cancelTaskCapability, delegateTaskCapability, marketplaceViewCapability, parseListFields, pickListedRows, listedFieldNote, sessionOrientation, presentTaskOutcome, explainRefusedRead, RESOURCE_HIDDEN_MESSAGE, SOURCES_DESCRIPTION, } from '@ziggs-ai/api-client';
|
|
6
6
|
import { decodeOperatorKeyClaims } from './operatorKey.js';
|
|
7
7
|
import { registerTrustTools } from './trustTools.js';
|
|
8
8
|
import { registerPaymentTools } from './paymentTools.js';
|
|
@@ -801,6 +801,9 @@ export function registerZiggsTools(server, creds, cfg) {
|
|
|
801
801
|
}
|
|
802
802
|
});
|
|
803
803
|
registerCapabilities(server, GRANTS_CAPABILITIES, creds);
|
|
804
|
+
// Buckets: compact door only until runs work in buckets; the directory
|
|
805
|
+
// allow-list leaves them out.
|
|
806
|
+
registerCapabilities(server, BUCKET_CAPABILITIES, creds);
|
|
804
807
|
registerCapability(server, contextExpandReachCapability, creds);
|
|
805
808
|
registerCapability(server, contextDiscoverGrantableCapability, creds);
|
|
806
809
|
registerCapability(server, openCapability, creds);
|
|
@@ -827,7 +830,6 @@ export function registerZiggsTools(server, creds, cfg) {
|
|
|
827
830
|
// question and carries its own honesty: what it searched, and what it could
|
|
828
831
|
// not.
|
|
829
832
|
registerCapability(server, findArtifactsCapability, creds);
|
|
830
|
-
registerCapability(server, shareArtifactCapability, creds);
|
|
831
833
|
registerCapability(server, attachArtifactCapability, creds);
|
|
832
834
|
registerCapability(server, reviewArtifactContributionCapability, creds);
|
|
833
835
|
registerCapability(server, contributeArtifactCapability, creds);
|
package/dist/trustTools.d.ts
CHANGED
|
@@ -5,6 +5,6 @@ import type { ZiggsMcpConfig } from './config.js';
|
|
|
5
5
|
* The SDK-twin tools (search/get, links, delegate) come from the shared
|
|
6
6
|
* capability layer; only revoking a grant stays MCP-local. Issuing one is a
|
|
7
7
|
* person's act (POST /context/grants takes a signed-in session), so there is
|
|
8
|
-
* no agent tool for it: an
|
|
9
|
-
*
|
|
8
|
+
* no agent tool for it: an artifact reaches people through a bucket, and an
|
|
9
|
+
* agent passes on a slice of its own grant with context_delegate. */
|
|
10
10
|
export declare function registerTrustTools(server: McpServer, creds: Creds, cfg?: ZiggsMcpConfig): void;
|
package/dist/trustTools.js
CHANGED
|
@@ -9,8 +9,8 @@ const DEFAULT_WEB_URL = 'https://ziggsai.com';
|
|
|
9
9
|
* The SDK-twin tools (search/get, links, delegate) come from the shared
|
|
10
10
|
* capability layer; only revoking a grant stays MCP-local. Issuing one is a
|
|
11
11
|
* person's act (POST /context/grants takes a signed-in session), so there is
|
|
12
|
-
* no agent tool for it: an
|
|
13
|
-
*
|
|
12
|
+
* no agent tool for it: an artifact reaches people through a bucket, and an
|
|
13
|
+
* agent passes on a slice of its own grant with context_delegate. */
|
|
14
14
|
export function registerTrustTools(server, creds, cfg) {
|
|
15
15
|
const webUrl = cfg?.ZIGGS_WEB_URL?.replace(/\/$/, '') ?? DEFAULT_WEB_URL;
|
|
16
16
|
registerCapabilities(server, DISCOVERY_CAPABILITIES, creds);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ziggs-ai/ziggs-mcp",
|
|
3
|
-
"version": "0.41.
|
|
3
|
+
"version": "0.41.8",
|
|
4
4
|
"description": "MCP server for Claude Code, Cursor, and other MCP hosts — act as your Ziggs delegate agent",
|
|
5
5
|
"homepage": "https://ziggsai.com/docs",
|
|
6
6
|
"bugs": {
|
|
@@ -51,13 +51,13 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
54
|
-
"@ziggs-ai/api-client": "0.40.
|
|
54
|
+
"@ziggs-ai/api-client": "0.40.6",
|
|
55
55
|
"dotenv": "^16.6.1",
|
|
56
56
|
"zod": "^3.24.2",
|
|
57
57
|
"zod-to-json-schema": "^3.25.1"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@ziggs-ai/agent-sdk": "0.46.
|
|
60
|
+
"@ziggs-ai/agent-sdk": "0.46.4"
|
|
61
61
|
},
|
|
62
62
|
"engines": {
|
|
63
63
|
"node": ">=20"
|
|
@@ -56,7 +56,7 @@ counterparty owner approves it, and unpublished delegates can then reach each ot
|
|
|
56
56
|
3. Target human approves via **`ziggs_agreement_respond`** (action `approve`) when the
|
|
57
57
|
pending link agreement shows in their inbox / `ziggs_link_list`. This is the same generic
|
|
58
58
|
approval tool used for hire and service proposals: there is no separate link-response tool.
|
|
59
|
-
4. **`ziggs_message_send`** with explicit readers, delivery recipients and any requested answer. To
|
|
59
|
+
4. **`ziggs_message_send`** with explicit readers, delivery recipients and any requested answer. To give someone an artifact, add it to a bucket with them (**`ziggs_bucket_insert`**, or **`ziggs_bucket_create`** with items); use **`ziggs_context_delegate`** for a bounded slice of a grant you hold. Contact, sharing and work remain separate operations.
|
|
60
60
|
5. To read their context, they grant it or you ask with **`ziggs_access_request`**.
|
|
61
61
|
6. `ziggs_context_revoke_grant` when context access should end; **`ziggs_agreement_revoke`** when
|
|
62
62
|
the agreement should end (any kind: hire, service, request, offer, or link).
|
|
@@ -83,4 +83,4 @@ which workspace it is, and call `ziggs_introduction_redeem` with `confirm: true`
|
|
|
83
83
|
## Web UI (Settings → Connections)
|
|
84
84
|
|
|
85
85
|
Confusingly named after the *other* "connection" (this is the agent-link handshake UI, not
|
|
86
|
-
`ziggs_connection_proxy` third-party connections). After an agent link appears under **Connected**, use your Claude delegate (MCP) for **`ziggs_message_send`**,
|
|
86
|
+
`ziggs_connection_proxy` third-party connections). After an agent link appears under **Connected**, use your Claude delegate (MCP) for **`ziggs_message_send`**, a bucket with them, or **`ziggs_context_delegate`**. The web UI manages handshake only, not chat or context grants.
|