@ziggs-ai/ziggs-mcp 0.16.0 → 0.17.1
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/config.d.ts +24 -0
- package/dist/config.js +22 -0
- package/dist/connectionCreds.d.ts +10 -2
- package/dist/connectionCreds.js +29 -4
- package/dist/creds.js +8 -0
- package/dist/mcpConnectionTools.js +3 -2
- package/dist/tools.js +12 -6
- package/package.json +2 -2
package/dist/config.d.ts
CHANGED
|
@@ -10,6 +10,26 @@ declare const envSchema: z.ZodObject<{
|
|
|
10
10
|
ZIGGS_AGENT_ID: z.ZodOptional<z.ZodString>;
|
|
11
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
|
+
/**
|
|
14
|
+
* The lane this server's calls belong to — a chat id, or `agrn-<agreementId>`.
|
|
15
|
+
* Sent as `X-Ziggs-Lane` on every fenced call. Unset means the agent acts for
|
|
16
|
+
* itself, which is right for a person who configured this server with their
|
|
17
|
+
* own key, and wrong for a delegate that has been hired: that one holds
|
|
18
|
+
* grants its CUSTOMER gave, and the server refuses those to a wake that
|
|
19
|
+
* states no lane.
|
|
20
|
+
*/
|
|
21
|
+
ZIGGS_LANE_ID: z.ZodOptional<z.ZodString>;
|
|
22
|
+
/**
|
|
23
|
+
* Pins this server's inbox host identity (`X-Ziggs-Instance`).
|
|
24
|
+
*
|
|
25
|
+
* One host owns an agent's inbox and a second is refused for 330 seconds, so
|
|
26
|
+
* a stdio server that a SCHEDULER respawns per run — the NanoClaw
|
|
27
|
+
* one-minute task starting `npx @ziggs-ai/ziggs-mcp` — is a new host every
|
|
28
|
+
* run and is refused by the previous run's lease. Set this to the same value
|
|
29
|
+
* on every run and they are one host. A server that stays up needs nothing:
|
|
30
|
+
* its process is its host.
|
|
31
|
+
*/
|
|
32
|
+
ZIGGS_INSTANCE_ID: z.ZodOptional<z.ZodString>;
|
|
13
33
|
/** Set to 1/true/yes to register internal/debug-only MCP tools. */
|
|
14
34
|
ZIGGS_MCP_DEBUG: z.ZodOptional<z.ZodString>;
|
|
15
35
|
/**
|
|
@@ -25,6 +45,8 @@ declare const envSchema: z.ZodObject<{
|
|
|
25
45
|
ZIGGS_WEB_URL?: string | undefined;
|
|
26
46
|
ZIGGS_AGENT_ID?: string | undefined;
|
|
27
47
|
ZIGGS_OWNER_USER_ID?: string | undefined;
|
|
48
|
+
ZIGGS_LANE_ID?: string | undefined;
|
|
49
|
+
ZIGGS_INSTANCE_ID?: string | undefined;
|
|
28
50
|
ZIGGS_MCP_DEBUG?: string | undefined;
|
|
29
51
|
ZIGGS_MCP_CORE_ONLY?: string | undefined;
|
|
30
52
|
}, {
|
|
@@ -34,6 +56,8 @@ declare const envSchema: z.ZodObject<{
|
|
|
34
56
|
ZIGGS_WEB_URL?: string | undefined;
|
|
35
57
|
ZIGGS_AGENT_ID?: string | undefined;
|
|
36
58
|
ZIGGS_OWNER_USER_ID?: string | undefined;
|
|
59
|
+
ZIGGS_LANE_ID?: string | undefined;
|
|
60
|
+
ZIGGS_INSTANCE_ID?: string | undefined;
|
|
37
61
|
ZIGGS_MCP_DEBUG?: string | undefined;
|
|
38
62
|
ZIGGS_MCP_CORE_ONLY?: string | undefined;
|
|
39
63
|
}>;
|
package/dist/config.js
CHANGED
|
@@ -12,6 +12,26 @@ const envSchema = z.object({
|
|
|
12
12
|
ZIGGS_AGENT_ID: z.string().optional(),
|
|
13
13
|
/** Human user id for payer-side proposals — defaults the payer on propose/publish tools. */
|
|
14
14
|
ZIGGS_OWNER_USER_ID: z.string().optional(),
|
|
15
|
+
/**
|
|
16
|
+
* The lane this server's calls belong to — a chat id, or `agrn-<agreementId>`.
|
|
17
|
+
* Sent as `X-Ziggs-Lane` on every fenced call. Unset means the agent acts for
|
|
18
|
+
* itself, which is right for a person who configured this server with their
|
|
19
|
+
* own key, and wrong for a delegate that has been hired: that one holds
|
|
20
|
+
* grants its CUSTOMER gave, and the server refuses those to a wake that
|
|
21
|
+
* states no lane.
|
|
22
|
+
*/
|
|
23
|
+
ZIGGS_LANE_ID: z.string().optional(),
|
|
24
|
+
/**
|
|
25
|
+
* Pins this server's inbox host identity (`X-Ziggs-Instance`).
|
|
26
|
+
*
|
|
27
|
+
* One host owns an agent's inbox and a second is refused for 330 seconds, so
|
|
28
|
+
* a stdio server that a SCHEDULER respawns per run — the NanoClaw
|
|
29
|
+
* one-minute task starting `npx @ziggs-ai/ziggs-mcp` — is a new host every
|
|
30
|
+
* run and is refused by the previous run's lease. Set this to the same value
|
|
31
|
+
* on every run and they are one host. A server that stays up needs nothing:
|
|
32
|
+
* its process is its host.
|
|
33
|
+
*/
|
|
34
|
+
ZIGGS_INSTANCE_ID: z.string().optional(),
|
|
15
35
|
/** Set to 1/true/yes to register internal/debug-only MCP tools. */
|
|
16
36
|
ZIGGS_MCP_DEBUG: z.string().optional(),
|
|
17
37
|
/**
|
|
@@ -37,6 +57,8 @@ export function loadConfig() {
|
|
|
37
57
|
ZIGGS_OPERATOR_KEY: process.env.ZIGGS_OPERATOR_KEY,
|
|
38
58
|
ZIGGS_AGENT_ID: process.env.ZIGGS_AGENT_ID,
|
|
39
59
|
ZIGGS_OWNER_USER_ID: process.env.ZIGGS_OWNER_USER_ID,
|
|
60
|
+
ZIGGS_LANE_ID: process.env.ZIGGS_LANE_ID,
|
|
61
|
+
ZIGGS_INSTANCE_ID: process.env.ZIGGS_INSTANCE_ID,
|
|
40
62
|
ZIGGS_MCP_DEBUG: process.env.ZIGGS_MCP_DEBUG,
|
|
41
63
|
ZIGGS_MCP_CORE_ONLY: process.env.ZIGGS_MCP_CORE_ONLY,
|
|
42
64
|
};
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { type Creds } from '@ziggs-ai/api-client';
|
|
2
2
|
import type { ZiggsMcpConfig } from './config.js';
|
|
3
3
|
export declare function parseBearerAuthorization(header: string | string[] | undefined): string;
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Per-connection credentials from HTTP Authorization.
|
|
6
|
+
*
|
|
7
|
+
* `laneId` is the wake's lane, read off `X-Ziggs-Lane` by the caller that
|
|
8
|
+
* mounts this server, exactly as `ownerUserId` is read off its own header. A
|
|
9
|
+
* connection that states none is fenced to the agent's own estate — right for
|
|
10
|
+
* a person who pasted their key, wrong for a delegate holding grants its
|
|
11
|
+
* customer gave.
|
|
12
|
+
*/
|
|
13
|
+
export declare function connectionFromBearer(bearer: string, httpBaseUrl: string, ownerUserId?: string, laneId?: string): {
|
|
6
14
|
creds: Creds;
|
|
7
15
|
cfg: ZiggsMcpConfig;
|
|
8
16
|
};
|
package/dist/connectionCreds.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { configureApiClient } from '@ziggs-ai/api-client';
|
|
1
|
+
import { configureApiClient, mcpConnectionIdentity, } from '@ziggs-ai/api-client';
|
|
2
2
|
import { MINT_KEY_HELP, decodeOperatorKeyClaims, isDirectoryBoarded, resolveDelegateAgentId, } from './operatorKey.js';
|
|
3
3
|
export function parseBearerAuthorization(header) {
|
|
4
4
|
const raw = Array.isArray(header) ? header[0] : header;
|
|
@@ -11,8 +11,16 @@ export function parseBearerAuthorization(header) {
|
|
|
11
11
|
}
|
|
12
12
|
return token;
|
|
13
13
|
}
|
|
14
|
-
/**
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Per-connection credentials from HTTP Authorization.
|
|
16
|
+
*
|
|
17
|
+
* `laneId` is the wake's lane, read off `X-Ziggs-Lane` by the caller that
|
|
18
|
+
* mounts this server, exactly as `ownerUserId` is read off its own header. A
|
|
19
|
+
* connection that states none is fenced to the agent's own estate — right for
|
|
20
|
+
* a person who pasted their key, wrong for a delegate holding grants its
|
|
21
|
+
* customer gave.
|
|
22
|
+
*/
|
|
23
|
+
export function connectionFromBearer(bearer, httpBaseUrl, ownerUserId, laneId) {
|
|
16
24
|
const resolvedAgentId = resolveDelegateAgentId(bearer, undefined);
|
|
17
25
|
if (httpBaseUrl) {
|
|
18
26
|
process.env.HTTP_URL = httpBaseUrl;
|
|
@@ -26,6 +34,7 @@ export function connectionFromBearer(bearer, httpBaseUrl, ownerUserId) {
|
|
|
26
34
|
HTTP_URL: httpBaseUrl,
|
|
27
35
|
ZIGGS_AGENT_ID: undefined,
|
|
28
36
|
ZIGGS_OWNER_USER_ID: ownerUserId,
|
|
37
|
+
ZIGGS_LANE_ID: laneId,
|
|
29
38
|
resolvedAgentId,
|
|
30
39
|
debugTools: false,
|
|
31
40
|
coreOnly: false,
|
|
@@ -35,8 +44,24 @@ export function connectionFromBearer(bearer, httpBaseUrl, ownerUserId) {
|
|
|
35
44
|
// ZiggsMcpConfig.directConnection.
|
|
36
45
|
directConnection: !isDirectoryBoarded(decodeOperatorKeyClaims(bearer)),
|
|
37
46
|
};
|
|
47
|
+
/**
|
|
48
|
+
* The inbox host is this CONNECTION, not the process serving it.
|
|
49
|
+
*
|
|
50
|
+
* This server also runs inside the API process, which serves every connected
|
|
51
|
+
* assistant and gets a new identity on every deploy. Stamping that made all
|
|
52
|
+
* of them one host and moved it under all of them at once, so a hosted
|
|
53
|
+
* `ziggs_inbox` read answered 409 for up to 330 seconds after each restart.
|
|
54
|
+
* The key is what stays put across both. Undefined only for a credential
|
|
55
|
+
* carrying no `keyId`, which then falls back to the process default.
|
|
56
|
+
*/
|
|
57
|
+
const instanceId = mcpConnectionIdentity(bearer);
|
|
38
58
|
return {
|
|
39
|
-
creds: {
|
|
59
|
+
creds: {
|
|
60
|
+
operatorKey: bearer,
|
|
61
|
+
agentId: resolvedAgentId,
|
|
62
|
+
...(laneId ? { laneId } : {}),
|
|
63
|
+
...(instanceId ? { instanceId } : {}),
|
|
64
|
+
},
|
|
40
65
|
cfg,
|
|
41
66
|
};
|
|
42
67
|
}
|
package/dist/creds.js
CHANGED
|
@@ -2,5 +2,13 @@ export function credsFromConfig(cfg) {
|
|
|
2
2
|
return {
|
|
3
3
|
operatorKey: cfg.ZIGGS_OPERATOR_KEY,
|
|
4
4
|
agentId: cfg.resolvedAgentId,
|
|
5
|
+
// The lane, so a hired delegate can spend the grants its customer gave it.
|
|
6
|
+
// Every client in this package reads it off `Creds`, so leaving it unset
|
|
7
|
+
// here silently fences all of them to the agent's own estate.
|
|
8
|
+
...(cfg.ZIGGS_LANE_ID ? { laneId: cfg.ZIGGS_LANE_ID } : {}),
|
|
9
|
+
// Unset means this process is the host, which is right for a server that
|
|
10
|
+
// stays up and wrong for one a scheduler respawns per run — that one pins
|
|
11
|
+
// ZIGGS_INSTANCE_ID so every run is the same host.
|
|
12
|
+
...(cfg.ZIGGS_INSTANCE_ID ? { instanceId: cfg.ZIGGS_INSTANCE_ID } : {}),
|
|
5
13
|
};
|
|
6
14
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
10
10
|
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
|
11
|
-
import { ConnectionsClient, getBackendUrl, } from '@ziggs-ai/api-client';
|
|
11
|
+
import { ConnectionsClient, getBackendUrl, laneHeader, } from '@ziggs-ai/api-client';
|
|
12
12
|
export function resolveMcpGatewayTarget(opts) {
|
|
13
13
|
if (!opts.connectionId)
|
|
14
14
|
throw new Error('connectionId is required');
|
|
@@ -25,7 +25,8 @@ export function resolveMcpGatewayTarget(opts) {
|
|
|
25
25
|
authorization: `Bearer ${opts.operatorKey}`,
|
|
26
26
|
'x-agent-id': opts.agentId,
|
|
27
27
|
'x-grant-id': opts.grantId,
|
|
28
|
-
|
|
28
|
+
// one helper for the lane, shared with every other door.
|
|
29
|
+
...laneHeader(opts.laneId),
|
|
29
30
|
},
|
|
30
31
|
};
|
|
31
32
|
}
|
package/dist/tools.js
CHANGED
|
@@ -68,7 +68,7 @@ function loadSessionReads(creds) {
|
|
|
68
68
|
// #4 — tasks and payments are independent; overlap them.
|
|
69
69
|
return Promise.allSettled([
|
|
70
70
|
listTasks({ state: 'active', limit: 20 }, creds),
|
|
71
|
-
new PaymentsClient(creds.operatorKey, creds.agentId).approvals({
|
|
71
|
+
new PaymentsClient(creds.operatorKey, creds.agentId, undefined, creds.laneId).approvals({
|
|
72
72
|
status: 'pending',
|
|
73
73
|
}),
|
|
74
74
|
]);
|
|
@@ -207,7 +207,7 @@ function registerConnectionTools(server, creds, cfg) {
|
|
|
207
207
|
? 'How to use a row: provider "mcp" → ziggs_mcp_tools_list / ziggs_mcp_tool_call; named connectors (github, jira, …) → ziggs_connection_proxy.'
|
|
208
208
|
: 'Rows are readable here but not callable over this connection: using a connection (an MCP server or a named connector such as github or jira) is only on a self-configured Ziggs MCP connection with an operator key.'), {}, readOnly('List connections you can use'), async () => {
|
|
209
209
|
try {
|
|
210
|
-
const connections = await new ConnectionsClient(creds.operatorKey, creds.agentId).listForHolder();
|
|
210
|
+
const connections = await new ConnectionsClient(creds.operatorKey, creds.agentId, undefined, creds.laneId).listForHolder();
|
|
211
211
|
return textResult({ connections });
|
|
212
212
|
}
|
|
213
213
|
catch (e) {
|
|
@@ -321,7 +321,7 @@ export function registerZiggsTools(server, creds, cfg) {
|
|
|
321
321
|
let snapshot = null;
|
|
322
322
|
const firstChatId = chats[0]?.chatId;
|
|
323
323
|
if (firstChatId) {
|
|
324
|
-
const client = new ContextReadClient(creds.operatorKey, creds.agentId);
|
|
324
|
+
const client = new ContextReadClient(creds.operatorKey, creds.agentId, undefined, firstChatId);
|
|
325
325
|
snapshot = await client.snapshot(firstChatId, { maxMessages: 5 });
|
|
326
326
|
}
|
|
327
327
|
return textResult({
|
|
@@ -345,7 +345,11 @@ export function registerZiggsTools(server, creds, cfg) {
|
|
|
345
345
|
.describe('Optional grant id when reading under a context grant'),
|
|
346
346
|
}, readOnly('Catch up on a chat'), async ({ chatId, maxMessages, contextGrantId }) => {
|
|
347
347
|
try {
|
|
348
|
-
|
|
348
|
+
// The chat being read IS the lane: a snapshot of someone else's room
|
|
349
|
+
// is a call inside that engagement, and stating it is what lets a hired
|
|
350
|
+
// delegate read the room it was hired into. Falls back to the
|
|
351
|
+
// connection's lane when no chat is named.
|
|
352
|
+
const client = new ContextReadClient(creds.operatorKey, creds.agentId, undefined, chatId || creds.laneId);
|
|
349
353
|
const result = await client.snapshot(chatId, {
|
|
350
354
|
maxMessages,
|
|
351
355
|
contextGrantId,
|
|
@@ -601,7 +605,9 @@ export function registerZiggsTools(server, creds, cfg) {
|
|
|
601
605
|
.describe('Long-poll: hold up to this many seconds (server-clamped, ~110 max) and return as soon as something new arrives — same response shape, no busy re-polling. Omit for an immediate snapshot.'),
|
|
602
606
|
}, readOnly('Check your inbox'), async ({ ack, handledResourceIds, waitSeconds }) => {
|
|
603
607
|
try {
|
|
604
|
-
|
|
608
|
+
// Unset on stdio: that process IS the host, and a scheduler that
|
|
609
|
+
// respawns it per run pins ZIGGS_INSTANCE_ID instead.
|
|
610
|
+
const client = new InboxClient(creds.operatorKey, creds.agentId, undefined, creds.instanceId);
|
|
605
611
|
// Ack-before-fetch is load-bearing; everything else is independent of
|
|
606
612
|
// the envelope until we know whether there are deliveries to tag.
|
|
607
613
|
const acked = ack
|
|
@@ -633,7 +639,7 @@ export function registerZiggsTools(server, creds, cfg) {
|
|
|
633
639
|
// own held context grants. Best-effort — the inbox still works
|
|
634
640
|
// untagged. All pages of live grants only (GET /grants also returns
|
|
635
641
|
// expired/revoked and paginates).
|
|
636
|
-
reach = await new GrantsClient(creds.operatorKey, creds.agentId).listAllGrants({
|
|
642
|
+
reach = await new GrantsClient(creds.operatorKey, creds.agentId, undefined, creds.laneId).listAllGrants({
|
|
637
643
|
// Every context scope kind — a literal subset here is how the CLI
|
|
638
644
|
// silently dropped a whole kind when `artifact` was added.
|
|
639
645
|
scopeKind: [...CONTEXT_GRANT_SCOPE_KINDS],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ziggs-ai/ziggs-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.1",
|
|
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.17.1",
|
|
43
43
|
"dotenv": "^16.6.1",
|
|
44
44
|
"zod": "^3.24.2",
|
|
45
45
|
"zod-to-json-schema": "^3.25.1"
|