@ziggs-ai/ziggs-mcp 0.1.1 → 0.1.3

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 CHANGED
@@ -29,6 +29,12 @@ Full walkthrough: [`examples/claude-code.md`](examples/claude-code.md)
29
29
  | Send message | `ziggs_send_message` |
30
30
  | Propose + respond | `ziggs_propose_agreement`, `ziggs_respond_to_agreement` |
31
31
 
32
+ Automated verify (same MCP path as `claude mcp add` + `npx`):
33
+
34
+ ```bash
35
+ ZIGGS_OPERATOR_KEY=<agent-scoped> node scripts/smoke-ziggs-mcp-z430-e2e.mjs
36
+ ```
37
+
32
38
  ---
33
39
 
34
40
  ## Cursor (local dev / monorepo)
@@ -89,6 +95,16 @@ ZIGGS_OPERATOR_KEY_A=... ZIGGS_AGENT_ID_A=... \
89
95
  ZIGGS_OPERATOR_KEY_B=... ZIGGS_AGENT_ID_B=... \
90
96
  ZIGGS_SMOKE_CHAT_ID=... \
91
97
  node scripts/smoke-ziggs-mcp-context.mjs
98
+
99
+ # ZIG-433 tools-only (npx trust tools after publish)
100
+ ZIGGS_OPERATOR_KEY=<agent-scoped> node scripts/smoke-ziggs-mcp-z433-e2e.mjs --tools-only
101
+
102
+ # ZIG-433 full two-org (delegate → approval → from-now read → revoke)
103
+ ZIGGS_OPERATOR_KEY_A=... ZIGGS_AGENT_ID_A=... \
104
+ ZIGGS_OPERATOR_KEY_B=... ZIGGS_AGENT_ID_B=... \
105
+ ZIGGS_APPROVER_OPERATOR_KEY=... ZIGGS_APPROVER_USER_ID=... \
106
+ ZIGGS_SMOKE_CHAT_ID=... \
107
+ node scripts/smoke-ziggs-mcp-z433-e2e.mjs
92
108
  ```
93
109
 
94
110
  ---
@@ -101,6 +117,11 @@ ZIGGS_SMOKE_CHAT_ID=... \
101
117
  | `ziggs_read_context` | `GET /context/read/:type` |
102
118
  | `ziggs_record_artifact` | `POST /artifacts` |
103
119
  | `ziggs_list_artifacts` | `GET /artifacts` |
120
+ | `ziggs_search_agents` | Agent search (ZIG-433) |
121
+ | `ziggs_list_my_grants` | `GET /context/grants` |
122
+ | `ziggs_issue_grant` | Chat admission or `POST /context/grants` |
123
+ | `ziggs_delegate_grant` | `POST /context/grants/:id/delegate` |
124
+ | `ziggs_revoke_grant` | `DELETE /context/grants/:id` |
104
125
  | `ziggs_smoke_impersonation` | Smoke step 1 |
105
126
  | `ziggs_get_scope` | `GET /scope?via=` |
106
127
  | `ziggs_list_my_agreements` | `GET /agreements?scope=mine` |
@@ -131,6 +152,10 @@ Logs must use **stderr** only (stdio MCP transport).
131
152
  2. Tag `ziggs-mcp-v*` → CI publishes `@ziggs-ai/ziggs-mcp`.
132
153
 
133
154
  ```bash
134
- git tag api-client-v0.1.5 && git push origin api-client-v0.1.5
135
- git tag ziggs-mcp-v0.1.0 && git push origin ziggs-mcp-v0.1.0
155
+ git tag api-client-v0.1.8 && git push origin api-client-v0.1.8
156
+ git tag ziggs-mcp-v0.1.3 && git push origin ziggs-mcp-v0.1.3
136
157
  ```
158
+
159
+ CI publishes on tag push. Push **api-client tag first**, then ziggs-mcp.
160
+
161
+ npm `--provenance` is not used: npm only supports provenance when the GitHub source repo is **public** (agentplus is private → 422).
package/dist/tools.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { randomUUID } from 'node:crypto';
2
2
  import { z } from 'zod';
3
3
  import { getAgreement, getMyAgreements, listMyChats, openConversation, proposeDirectTo, respondToAgreement, ScopeClient, MessagesClient, sendChatMessage, ContextDiscoveryClient, ContextReadClient, ArtifactsClient, getBackendUrl, } from '@ziggs-ai/api-client';
4
+ import { registerTrustTools } from './trustTools.js';
4
5
  function textResult(data) {
5
6
  return {
6
7
  content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
@@ -303,4 +304,5 @@ export function registerZiggsTools(server, creds, cfg) {
303
304
  return toolError(e.message);
304
305
  }
305
306
  });
307
+ registerTrustTools(server, creds);
306
308
  }
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { type Creds } from '@ziggs-ai/api-client';
3
+ /** ZIG-433 — agent search + context grant management through MCP. */
4
+ export declare function registerTrustTools(server: McpServer, creds: Creds): void;
@@ -0,0 +1,166 @@
1
+ import { z } from 'zod';
2
+ import { AgentSearchClient, ContextGrantsClient, addChatMember, } from '@ziggs-ai/api-client';
3
+ function textResult(data) {
4
+ return {
5
+ content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
6
+ };
7
+ }
8
+ function toolError(message) {
9
+ return {
10
+ content: [{ type: 'text', text: message }],
11
+ isError: true,
12
+ };
13
+ }
14
+ const grantScopeKindSchema = z.enum(['chat', 'agreement', 'org']);
15
+ const contextTemporalSchema = z.enum(['from-now', 'from-start']);
16
+ /** ZIG-433 — agent search + context grant management through MCP. */
17
+ export function registerTrustTools(server, creds) {
18
+ server.tool('ziggs_search_agents', 'Search published agents by query (AgentSearchClient). Use returned agentId in grant/issue tools — do not guess ids.', {
19
+ query: z.string().describe('Natural language or keyword search'),
20
+ limit: z.number().optional().describe('Max results (default server-side)'),
21
+ minScore: z.number().optional().describe('Minimum match score filter'),
22
+ }, async ({ query, limit, minScore }) => {
23
+ try {
24
+ const client = new AgentSearchClient(creds.operatorKey, creds.agentId);
25
+ const result = await client.searchAgents(query, { limit, minScore });
26
+ if (!result.success) {
27
+ return toolError(result.error ?? result.message ?? 'search failed');
28
+ }
29
+ return textResult({
30
+ count: result.agents?.length ?? 0,
31
+ agents: result.agents ?? [],
32
+ });
33
+ }
34
+ catch (e) {
35
+ return toolError(e.message);
36
+ }
37
+ });
38
+ server.tool('ziggs_list_my_grants', 'List context grants held by the delegate agent (GET /context/grants). Returns grantId, scope, temporal, watermarkAt, expiresAt — no content.', {
39
+ holderId: z
40
+ .string()
41
+ .optional()
42
+ .describe('Admin only: list grants for another agent id'),
43
+ }, async ({ holderId }) => {
44
+ try {
45
+ const client = new ContextGrantsClient(creds.operatorKey, creds.agentId);
46
+ const grants = await client.listGrants(holderId);
47
+ return textResult({ count: grants.length, grants });
48
+ }
49
+ catch (e) {
50
+ return toolError(e.message);
51
+ }
52
+ });
53
+ server.tool('ziggs_issue_grant', 'Issue bounded context access. Chat scope: admits agent via POST /chats/:id/members (agent-invite → pending_approval until humans consent). Agreement/org scope: POST /context/grants (requires context:admin on operator key). Defaults: from-now, narrow scope.', {
54
+ holderId: z.string().describe('Bare agent id receiving the grant'),
55
+ scopeKind: grantScopeKindSchema,
56
+ scopeId: z.string().describe('chatId, agreementId, or orgId'),
57
+ temporal: contextTemporalSchema
58
+ .optional()
59
+ .describe('from-now (default) or from-start (approval-gated on chat)'),
60
+ expiresAt: z
61
+ .string()
62
+ .optional()
63
+ .nullable()
64
+ .describe('ISO-8601 expiry; omit for platform default TTL'),
65
+ }, async ({ holderId, scopeKind, scopeId, temporal, expiresAt }) => {
66
+ const resolvedTemporal = temporal ?? 'from-now';
67
+ try {
68
+ if (scopeKind === 'chat') {
69
+ const result = await addChatMember({
70
+ chatId: scopeId,
71
+ memberId: holderId,
72
+ memberType: 'agent',
73
+ temporal: resolvedTemporal,
74
+ }, creds);
75
+ if ('status' in result && result.status === 'pending') {
76
+ return textResult({
77
+ status: 'pending_approval',
78
+ message: 'Human approval required before the grant is issued (ZIG-426). Surface this to the user — do not treat as success.',
79
+ scope: { kind: 'chat', id: scopeId },
80
+ holderId,
81
+ temporal: resolvedTemporal,
82
+ pendingAdmission: result.pendingAdmission,
83
+ });
84
+ }
85
+ return textResult({
86
+ status: 'granted',
87
+ scope: { kind: 'chat', id: scopeId },
88
+ holderId,
89
+ temporal: resolvedTemporal,
90
+ bounds: {
91
+ temporal: resolvedTemporal,
92
+ note: 'from-now: readable content starts at grant watermark; from-start requires unanimous approval',
93
+ },
94
+ chat: 'chat' in result ? result.chat : undefined,
95
+ });
96
+ }
97
+ const client = new ContextGrantsClient(creds.operatorKey, creds.agentId);
98
+ const grant = await client.issueGrant({
99
+ holderId,
100
+ scope: { kind: scopeKind, id: scopeId },
101
+ temporal: resolvedTemporal,
102
+ expiresAt,
103
+ });
104
+ return textResult({
105
+ status: 'granted',
106
+ grant,
107
+ bounds: {
108
+ temporal: grant.temporal,
109
+ watermarkAt: grant.watermarkAt,
110
+ expiresAt: grant.expiresAt,
111
+ },
112
+ });
113
+ }
114
+ catch (e) {
115
+ return toolError(e.message);
116
+ }
117
+ });
118
+ server.tool('ziggs_delegate_grant', 'Delegate a narrower child grant from one you hold (POST /context/grants/:id/delegate). Delegation only narrows scope/expiry/temporal — never broadens.', {
119
+ parentGrantId: z.string(),
120
+ holderId: z.string().describe('Agent receiving the delegated grant'),
121
+ scopeKind: grantScopeKindSchema,
122
+ scopeId: z.string(),
123
+ temporal: contextTemporalSchema.describe('from-now or from-start (must be same-or-narrower)'),
124
+ expiresAt: z.string().optional().nullable(),
125
+ watermarkAt: z
126
+ .string()
127
+ .optional()
128
+ .describe('from-now watermark ISO-8601 (optional; server may default)'),
129
+ }, async ({ parentGrantId, holderId, scopeKind, scopeId, temporal, expiresAt, watermarkAt, }) => {
130
+ try {
131
+ const client = new ContextGrantsClient(creds.operatorKey, creds.agentId);
132
+ const grant = await client.delegateGrant(parentGrantId, {
133
+ holderId,
134
+ scope: { kind: scopeKind, id: scopeId },
135
+ temporal,
136
+ expiresAt,
137
+ watermarkAt,
138
+ });
139
+ return textResult({
140
+ status: 'delegated',
141
+ parentGrantId,
142
+ grant,
143
+ bounds: {
144
+ temporal: grant.temporal,
145
+ watermarkAt: grant.watermarkAt,
146
+ expiresAt: grant.expiresAt,
147
+ },
148
+ });
149
+ }
150
+ catch (e) {
151
+ return toolError(e.message);
152
+ }
153
+ });
154
+ server.tool('ziggs_revoke_grant', 'Revoke a context grant and its descendants (DELETE /context/grants/:id). Requires context:admin on the operator key.', {
155
+ grantId: z.string(),
156
+ }, async ({ grantId }) => {
157
+ try {
158
+ const client = new ContextGrantsClient(creds.operatorKey, creds.agentId);
159
+ const result = await client.revokeGrant(grantId);
160
+ return textResult({ grantId, ...result });
161
+ }
162
+ catch (e) {
163
+ return toolError(e.message);
164
+ }
165
+ });
166
+ }
@@ -37,7 +37,14 @@ Ask Claude to call tools in order:
37
37
  2. `ziggs_send_message` (chat you belong to)
38
38
  3. `ziggs_propose_agreement` + `ziggs_respond_to_agreement` (optional)
39
39
 
40
- Paste the session transcript in the PR when verifying ZIG-430.
40
+ Paste the session transcript in the PR when verifying ZIG-430, or run:
41
+
42
+ ```bash
43
+ cd agentplus
44
+ ZIGGS_OPERATOR_KEY=<agent-scoped> node scripts/smoke-ziggs-mcp-z430-e2e.mjs
45
+ ```
46
+
47
+ (Same MCP stdio path as `claude mcp add` + `npx -y @ziggs-ai/ziggs-mcp`.)
41
48
 
42
49
  ## Fleet key alternative
43
50
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ziggs-ai/ziggs-mcp",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
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": {
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "@modelcontextprotocol/sdk": "^1.29.0",
20
- "@ziggs-ai/api-client": "^0.1.6",
20
+ "@ziggs-ai/api-client": "^0.1.8",
21
21
  "dotenv": "^16.6.1",
22
22
  "zod": "^3.24.2"
23
23
  },