@odatano/nightgate-mcp 0.5.1 → 0.7.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/CHANGELOG.md +107 -0
- package/README.md +117 -96
- package/dist/builder.d.ts +1 -1
- package/dist/builder.js +36 -17
- package/dist/builder.js.map +1 -1
- package/dist/client.d.ts +12 -1
- package/dist/client.js +26 -3
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +12 -8
- package/dist/config.js +4 -4
- package/dist/config.js.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/server.js +1 -1
- package/dist/tools.js +80 -73
- package/dist/tools.js.map +1 -1
- package/package.json +4 -3
package/dist/client.js
CHANGED
|
@@ -2,13 +2,37 @@
|
|
|
2
2
|
export class NightgateApiError extends Error {
|
|
3
3
|
status;
|
|
4
4
|
code;
|
|
5
|
-
|
|
5
|
+
detail;
|
|
6
|
+
constructor(status, code, message,
|
|
7
|
+
/** Extra fields of a gateway error body (unitsLeft, price, topup, products, validUntil, retryAfterSeconds). */
|
|
8
|
+
detail) {
|
|
6
9
|
super(message);
|
|
7
10
|
this.status = status;
|
|
8
11
|
this.code = code;
|
|
12
|
+
this.detail = detail;
|
|
9
13
|
this.name = 'NightgateApiError';
|
|
10
14
|
}
|
|
11
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Two error shapes reach the client: CAP's `{ error: { code, message } }`
|
|
18
|
+
* from NIGHTGATE itself, and the ODATANO ACCESS gateway's `{ error: "<text>",
|
|
19
|
+
* ...detail }` (401 key problems, 402 units exhausted with a top-up hint,
|
|
20
|
+
* 403 closed action or product not on the key, 429 with Retry-After).
|
|
21
|
+
*/
|
|
22
|
+
export function apiError(status, payload, headers, fallback) {
|
|
23
|
+
const body = (payload && typeof payload === 'object' ? payload : {});
|
|
24
|
+
const err = body.error;
|
|
25
|
+
if (typeof err === 'string') {
|
|
26
|
+
const { error: _e, ...rest } = body;
|
|
27
|
+
const detail = { ...rest };
|
|
28
|
+
const retry = headers.get('retry-after');
|
|
29
|
+
if (retry)
|
|
30
|
+
detail.retryAfterSeconds = Number(retry);
|
|
31
|
+
return new NightgateApiError(status, undefined, err, Object.keys(detail).length ? detail : undefined);
|
|
32
|
+
}
|
|
33
|
+
const e = (err ?? {});
|
|
34
|
+
return new NightgateApiError(status, e.code, e.message ?? fallback);
|
|
35
|
+
}
|
|
12
36
|
export function int64(value) {
|
|
13
37
|
const digits = String(value);
|
|
14
38
|
if (!/^\d+$/.test(digits))
|
|
@@ -83,8 +107,7 @@ export class NightgateClient {
|
|
|
83
107
|
payload = { raw: text };
|
|
84
108
|
}
|
|
85
109
|
if (!response.ok) {
|
|
86
|
-
|
|
87
|
-
throw new NightgateApiError(response.status, err?.code, err?.message ?? `NIGHTGATE request failed with HTTP ${response.status}`);
|
|
110
|
+
throw apiError(response.status, payload, response.headers, `NIGHTGATE request failed with HTTP ${response.status}`);
|
|
88
111
|
}
|
|
89
112
|
return stripODataNoise(payload);
|
|
90
113
|
}
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,sEAAsE;AACtE,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAExB;IACA;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Server configuration, environment-driven
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Server configuration, environment-driven. The connection variables are the
|
|
3
|
+
* same for every ODATANO MCP server (ODATANO_ACCESS_*): one key from
|
|
4
|
+
* https://api.odatano.dev configures the Midnight and the Cardano server alike.
|
|
5
|
+
* A direct NIGHTGATE instance (local `cds watch`, an own deployment) is reached
|
|
6
|
+
* by pointing ODATANO_ACCESS_URL at it.
|
|
5
7
|
*/
|
|
6
8
|
export interface NightgateMcpConfig {
|
|
7
|
-
/** Base URL
|
|
9
|
+
/** Base URL: the ODATANO ACCESS gateway (default https://api.odatano.dev) or a direct NIGHTGATE host app. */
|
|
8
10
|
baseUrl: string;
|
|
9
11
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
12
|
+
* ODATANO_ACCESS_KEY. The usual value is an ODATANO ACCESS key (`oda_...`),
|
|
13
|
+
* sent as `Authorization: Bearer`; the gateway swaps in the agent grant.
|
|
14
|
+
* Against a direct NIGHTGATE instance an `ngat_...` agent-grant token goes
|
|
15
|
+
* as `x-agent-token` (optionally alongside basic transport auth); anything
|
|
16
|
+
* else is a plain bearer.
|
|
13
17
|
*/
|
|
14
18
|
token?: string;
|
|
15
|
-
/**
|
|
19
|
+
/** ODATANO_ACCESS_USER / _PASSWORD: basic auth for a direct instance (CAP dev/mocked auth); never for agents. */
|
|
16
20
|
username?: string;
|
|
17
21
|
password?: string;
|
|
18
22
|
/** OData service path of the main Nightgate service. */
|
package/dist/config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export function loadConfig(env = process.env) {
|
|
2
|
-
const baseUrl = (env.
|
|
2
|
+
const baseUrl = (env.ODATANO_ACCESS_URL || 'https://api.odatano.dev').replace(/\/+$/, '');
|
|
3
3
|
const timeoutMs = Number(env.NIGHTGATE_TIMEOUT_MS ?? 30000);
|
|
4
4
|
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
5
5
|
throw new Error(`Invalid NIGHTGATE_TIMEOUT_MS: ${env.NIGHTGATE_TIMEOUT_MS}`);
|
|
@@ -14,9 +14,9 @@ export function loadConfig(env = process.env) {
|
|
|
14
14
|
}
|
|
15
15
|
return {
|
|
16
16
|
baseUrl,
|
|
17
|
-
token: env.
|
|
18
|
-
username: env.
|
|
19
|
-
password: env.
|
|
17
|
+
token: env.ODATANO_ACCESS_KEY || undefined,
|
|
18
|
+
username: env.ODATANO_ACCESS_USER || undefined,
|
|
19
|
+
password: env.ODATANO_ACCESS_PASSWORD || undefined,
|
|
20
20
|
servicePath: env.NIGHTGATE_SERVICE_PATH ?? '/api/v1/nightgate',
|
|
21
21
|
timeoutMs,
|
|
22
22
|
seedHex,
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AA0CA,MAAM,UAAU,UAAU,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC7D,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,kBAAkB,IAAI,yBAAyB,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC1F,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,oBAAoB,IAAI,KAAK,CAAC,CAAC;IAC5D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,iCAAiC,GAAG,CAAC,oBAAoB,EAAE,CAAC,CAAC;IAC/E,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,CAAC,iBAAiB,IAAI,SAAS,CAAC;IACnD,IAAI,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,8BAA8B,OAAO,gCAAgC,CAAC,CAAC;IACzF,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,CAAC,kBAAkB,IAAI,SAAS,CAAC;IACpD,IAAI,OAAO,IAAI,CAAC,sCAAsC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACnF,CAAC;IACD,OAAO;QACL,OAAO;QACP,KAAK,EAAE,GAAG,CAAC,kBAAkB,IAAI,SAAS;QAC1C,QAAQ,EAAE,GAAG,CAAC,mBAAmB,IAAI,SAAS;QAC9C,QAAQ,EAAE,GAAG,CAAC,uBAAuB,IAAI,SAAS;QAClD,WAAW,EAAE,GAAG,CAAC,sBAAsB,IAAI,mBAAmB;QAC9D,SAAS;QACT,OAAO;QACP,OAAO;QACP,cAAc,EAAE,GAAG,CAAC,0BAA0B,IAAI,SAAS;QAC3D,YAAY,EAAE,GAAG,CAAC,wBAAwB,IAAI,SAAS;QACvD,OAAO,EAAE,GAAG,CAAC,kBAAkB,IAAI,SAAS;QAC5C,eAAe,EAAE,GAAG,CAAC,4BAA4B,IAAI,SAAS;QAC9D,UAAU,EAAE,GAAG,CAAC,sBAAsB,IAAI,SAAS;QACnD,cAAc,EAAE,GAAG,CAAC,0BAA0B,IAAI,SAAS;KAC5D,CAAC;AACJ,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,9 @@ async function main() {
|
|
|
6
6
|
const config = loadConfig();
|
|
7
7
|
const server = buildServer(config);
|
|
8
8
|
// stdio transport: stdout is the protocol channel, diagnostics go to stderr
|
|
9
|
+
if (!config.token && !config.username && /api.odatano.dev$/.test(config.baseUrl)) {
|
|
10
|
+
console.error('nightgate-mcp: ODATANO_ACCESS_KEY is not set; api.odatano.dev answers 401 without a key (sign in, redeem a code or buy a pack at https://api.odatano.dev)');
|
|
11
|
+
}
|
|
9
12
|
console.error(`nightgate-mcp: connecting tools to ${config.baseUrl}${config.servicePath}`);
|
|
10
13
|
await server.connect(new StdioServerTransport());
|
|
11
14
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,4EAA4E;IAC5E,OAAO,CAAC,KAAK,CAAC,sCAAsC,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAC3F,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;AACnD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,GAAG,CAAC,CAAC;IACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,4EAA4E;IAC5E,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QACjF,OAAO,CAAC,KAAK,CAAC,2JAA2J,CAAC,CAAC;IAC7K,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,sCAAsC,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAC3F,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;AACnD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,GAAG,CAAC,CAAC;IACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/dist/server.js
CHANGED
|
@@ -3,7 +3,7 @@ import { NightgateClient } from './client.js';
|
|
|
3
3
|
import { registerTools } from './tools.js';
|
|
4
4
|
/** Build the MCP server with all tools registered; transport is the caller's choice. */
|
|
5
5
|
export function buildServer(config) {
|
|
6
|
-
const server = new McpServer({ name: 'nightgate', version: '0.
|
|
6
|
+
const server = new McpServer({ name: 'nightgate', version: '0.7.0' });
|
|
7
7
|
registerTools(server, new NightgateClient(config), config);
|
|
8
8
|
return server;
|
|
9
9
|
}
|
package/dist/tools.js
CHANGED
|
@@ -122,6 +122,7 @@ const membershipClaim = z.object({
|
|
|
122
122
|
const documentIntegrityClaim = z.object({
|
|
123
123
|
predicate: z.literal('documentIntegrity'),
|
|
124
124
|
payloadHashB: hex64('payloadHashB').describe('The second document (A is the batch payloadHash)'),
|
|
125
|
+
attesterIdB: hex64('attesterIdB').optional().describe('Document B\'s attester; default the batch attester'),
|
|
125
126
|
allowedMask: z.number().int().min(0).max(MAX_MASK - 1)
|
|
126
127
|
.describe('Packed slot mask, one bit per slot of the vault width (16 bits by default, 32 on attestation-vault-32), bit i = slot i MAY differ. Must leave at least one real schema slot constrained, otherwise the claim is vacuous and rejected'),
|
|
127
128
|
schema: schemaSlots,
|
|
@@ -135,6 +136,7 @@ const documentIntegrityClaim = z.object({
|
|
|
135
136
|
const documentDiffClaim = z.object({
|
|
136
137
|
predicate: z.literal('documentDiff'),
|
|
137
138
|
payloadHashB: hex64('payloadHashB').describe('The second document (A is the batch payloadHash)'),
|
|
139
|
+
attesterIdB: hex64('attesterIdB').optional().describe('Document B\'s attester; default the batch attester'),
|
|
138
140
|
k: z.number().int().min(1).max(MAX_SLOT_WIDTH).describe('Minimum number of differing slots to prove, up to the vault width'),
|
|
139
141
|
schema: schemaSlots,
|
|
140
142
|
openingA: documentOpening,
|
|
@@ -148,12 +150,21 @@ const documentDiffClaim = z.object({
|
|
|
148
150
|
export function registerTools(server, client, config) {
|
|
149
151
|
const run = wrapHandler(client);
|
|
150
152
|
server.registerTool('verify_attestation', {
|
|
151
|
-
description: 'Verify against LIVE Midnight contract state that
|
|
152
|
-
'AttestationVault (crawler-free, no txHash needed).
|
|
153
|
-
'
|
|
153
|
+
description: 'Verify against LIVE Midnight contract state that an attester\'s record of a payload ' +
|
|
154
|
+
'hash stands in an AttestationVault (crawler-free, no txHash needed). A record is ONE ' +
|
|
155
|
+
'attester\'s attestation of ONE payload (ledger key recordKey(attesterId, payloadHash)): ' +
|
|
156
|
+
'name it by attesterId + payloadHash, or by a bound documentId, which resolves to exactly ' +
|
|
157
|
+
'one record and reveals its attester. Optionally also checks that the anchored content ' +
|
|
158
|
+
'root / schema id match. Returns verified:false (not an error) when absent; the result ' +
|
|
159
|
+
'carries attesterId, payloadHash, recordKey and documentId.',
|
|
154
160
|
inputSchema: {
|
|
155
161
|
contractAddress: z.string().min(1).describe('AttestationVault contract address'),
|
|
156
|
-
|
|
162
|
+
attesterId: hex64('attesterId').optional()
|
|
163
|
+
.describe('The attester whose record to check (64 hex; get_attester_identity for this server\'s own). Required unless documentId is given'),
|
|
164
|
+
payloadHash: hex64('payloadHash').optional()
|
|
165
|
+
.describe('The attested payload hash (sha256, 64 hex). Required with attesterId; next to documentId it must match the bound record'),
|
|
166
|
+
documentId: hex64('documentId').optional()
|
|
167
|
+
.describe('A bound document id (64 hex): resolves the record through the vault\'s document bindings'),
|
|
157
168
|
contentRoot: hex64('contentRoot').optional().describe('Optional anchored content root to check (64 hex)'),
|
|
158
169
|
schemaId: hex64('schemaId').optional()
|
|
159
170
|
.describe('Optional anchored schema id to check; the result reports schemaOk, so an examiner can pin the canonical field list'),
|
|
@@ -161,23 +172,32 @@ export function registerTools(server, client, config) {
|
|
|
161
172
|
.describe('Read from another network public indexer instead of the configured one'),
|
|
162
173
|
compiledArtifactRef: z.string().optional().describe("Contract artifact ref, defaults to 'attestation-vault'"),
|
|
163
174
|
},
|
|
164
|
-
}, run(async (args) =>
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
175
|
+
}, run(async (args) => {
|
|
176
|
+
if (!args.documentId && !(args.attesterId && args.payloadHash)) {
|
|
177
|
+
throw new Error('name the record: attesterId + payloadHash, or documentId');
|
|
178
|
+
}
|
|
179
|
+
return client.callFunction('verifyAttestationState', {
|
|
180
|
+
contractAddress: args.contractAddress,
|
|
181
|
+
attesterId: args.attesterId,
|
|
182
|
+
payloadHash: args.payloadHash,
|
|
183
|
+
documentId: args.documentId,
|
|
184
|
+
contentRoot: args.contentRoot,
|
|
185
|
+
schemaId: args.schemaId,
|
|
186
|
+
compiledArtifactRef: args.compiledArtifactRef,
|
|
187
|
+
network: args.network,
|
|
188
|
+
});
|
|
189
|
+
}));
|
|
172
190
|
server.registerTool('verify_predicate', {
|
|
173
191
|
description: 'Verify against LIVE Midnight contract state that a ZK claim was recorded true on-chain. ' +
|
|
174
192
|
'Id-free: works for proofs NIGHTGATE never saw. Numeric predicates (lessOrEqual / ' +
|
|
175
193
|
'greaterOrEqual) need threshold (the SAME scaled integer the circuit hashed; a scaling ' +
|
|
176
194
|
'mismatch yields verified:false) and optionally fieldKey for field-bound proofs. ' +
|
|
177
195
|
'bytesEquality needs fieldKey + expectedDigest; setMembership needs fieldKey + setRoot ' +
|
|
178
|
-
'(recompute it from the published list via prepare_membership_set).'
|
|
196
|
+
'(recompute it from the published list via prepare_membership_set). Every claim is bound ' +
|
|
197
|
+
'to ONE attester\'s record of the document, so attesterId is part of the coordinates.',
|
|
179
198
|
inputSchema: {
|
|
180
199
|
contractAddress: z.string().min(1).describe('AttestationVault contract address'),
|
|
200
|
+
attesterId: hex64('attesterId').describe('The attester whose record of payloadHash carries the claim (64 hex)'),
|
|
181
201
|
payloadHash: hex64('payloadHash').describe('The attestation payload hash (64 hex)'),
|
|
182
202
|
predicate: z.enum(['lessOrEqual', 'greaterOrEqual', 'bytesEquality', 'setMembership',
|
|
183
203
|
'documentIntegrity', 'documentDiff']).describe('Claim kind'),
|
|
@@ -191,6 +211,8 @@ export function registerTools(server, client, config) {
|
|
|
191
211
|
.describe("setMembership only: the canonical allow-list set root"),
|
|
192
212
|
payloadHashB: hex64('payloadHashB').optional()
|
|
193
213
|
.describe('Cross-root kinds: the second document. (A, B) order is part of the claim, query it as proven'),
|
|
214
|
+
attesterIdB: hex64('attesterIdB').optional()
|
|
215
|
+
.describe('Cross-root kinds: document B\'s attester; defaults to attesterId'),
|
|
194
216
|
allowedMask: z.number().int().min(0).max(MAX_MASK).optional()
|
|
195
217
|
.describe('documentIntegrity only: the packed slot mask that was proven (16 bits by default, 32 on attestation-vault-32)'),
|
|
196
218
|
k: z.number().int().min(1).max(MAX_SLOT_WIDTH).optional()
|
|
@@ -217,7 +239,9 @@ export function registerTools(server, client, config) {
|
|
|
217
239
|
}
|
|
218
240
|
return client.callFunction('verifyPredicateState', {
|
|
219
241
|
contractAddress: args.contractAddress,
|
|
242
|
+
attesterId: args.attesterId,
|
|
220
243
|
payloadHash: args.payloadHash,
|
|
244
|
+
attesterIdB: args.attesterIdB,
|
|
221
245
|
fieldKey: args.fieldKey,
|
|
222
246
|
predicate: args.predicate,
|
|
223
247
|
threshold: args.threshold === undefined ? undefined : int64(args.threshold),
|
|
@@ -328,12 +352,11 @@ export function registerTools(server, client, config) {
|
|
|
328
352
|
})));
|
|
329
353
|
server.registerTool('anchor_document', {
|
|
330
354
|
description: 'Anchor a document content hash on the Midnight chain via the AttestationVault attest ' +
|
|
331
|
-
'circuit. Commits only the sha256 + public metadata; you are responsible
|
|
332
|
-
'actual bytes at storageRef.
|
|
333
|
-
'
|
|
334
|
-
'
|
|
335
|
-
'
|
|
336
|
-
' Also returns documentId for verify_document.',
|
|
355
|
+
'circuit (one transaction). Commits only the sha256 + public metadata; you are responsible ' +
|
|
356
|
+
'for storing the actual bytes at storageRef. The on-chain record is keyed by the session\'s ' +
|
|
357
|
+
'attester id AND the hash, so nobody can pre-empt or take over it; the same hash anchored ' +
|
|
358
|
+
'by another identity is a separate record. ' + POLL_HINT +
|
|
359
|
+
' Also returns documentId for verify_document and attesterId, which verifiers need next to the hash.',
|
|
337
360
|
inputSchema: {
|
|
338
361
|
sha256: hex64('sha256').describe('sha256 of the document content (64 hex), becomes the on-chain payload hash'),
|
|
339
362
|
storageRef: z.string().min(1).describe('Where the bytes live, e.g. file://, s3://, ipfs://'),
|
|
@@ -342,8 +365,6 @@ export function registerTools(server, client, config) {
|
|
|
342
365
|
contentType: z.string().optional().describe('MIME type, informational'),
|
|
343
366
|
size: z.number().int().nonnegative().optional().describe('Content size in bytes, informational'),
|
|
344
367
|
metadata: z.record(z.unknown()).optional().describe('Public metadata object; its hash is anchored alongside'),
|
|
345
|
-
nonce: hex64('nonce').optional()
|
|
346
|
-
.describe('Guarded REVEAL: the secret nonce from prepare_anchor_commitment, after commit_document_anchor finalized. Same sha256 and metadata as the commitment'),
|
|
347
368
|
compiledArtifactRef: z.string().optional().describe("Contract artifact ref, defaults to 'attestation-vault'"),
|
|
348
369
|
idempotencyKey: z.string().optional().describe('Dedupes retries of the same anchor request'),
|
|
349
370
|
sponsorSessionId: z.string().uuid().optional().describe('Optional second session that pays the dust fee'),
|
|
@@ -354,7 +375,6 @@ export function registerTools(server, client, config) {
|
|
|
354
375
|
size: args.size,
|
|
355
376
|
storageRef: args.storageRef,
|
|
356
377
|
metadata: args.metadata === undefined ? undefined : JSON.stringify(args.metadata),
|
|
357
|
-
nonce: args.nonce,
|
|
358
378
|
sessionId: args.sessionId,
|
|
359
379
|
contractAddress: args.contractAddress,
|
|
360
380
|
compiledArtifactRef: args.compiledArtifactRef,
|
|
@@ -370,6 +390,8 @@ export function registerTools(server, client, config) {
|
|
|
370
390
|
'at local proving time, nothing is submitted. ' + POLL_HINT,
|
|
371
391
|
inputSchema: {
|
|
372
392
|
payloadHash: hex64('payloadHash').describe('Attestation payload hash (64 hex)'),
|
|
393
|
+
attesterId: hex64('attesterId').optional()
|
|
394
|
+
.describe('The attester whose record of payloadHash the claim is bound to (64 hex); default the session\'s own. A contentRoot can only be anchored under the session\'s own record'),
|
|
373
395
|
fieldKey: hex64('fieldKey').describe('Canonical field id (64 hex, public)'),
|
|
374
396
|
value: z.string().regex(/^\d+$/, 'value must be a non-negative integer (decimal string)')
|
|
375
397
|
.describe('Scaled integer field value (witness only, never persisted)'),
|
|
@@ -389,6 +411,7 @@ export function registerTools(server, client, config) {
|
|
|
389
411
|
},
|
|
390
412
|
}, run(async (args) => client.callAction('issueFieldPredicateAttestation', {
|
|
391
413
|
payloadHash: args.payloadHash,
|
|
414
|
+
attesterId: args.attesterId,
|
|
392
415
|
fieldKey: args.fieldKey,
|
|
393
416
|
value: args.value,
|
|
394
417
|
fieldSalt: args.fieldSalt,
|
|
@@ -441,6 +464,8 @@ export function registerTools(server, client, config) {
|
|
|
441
464
|
'supplied it is anchored first. ' + POLL_HINT,
|
|
442
465
|
inputSchema: {
|
|
443
466
|
payloadHash: hex64('payloadHash').describe('Attestation payload hash (64 hex)'),
|
|
467
|
+
attesterId: hex64('attesterId').optional()
|
|
468
|
+
.describe('The attester whose record of payloadHash the claim is bound to (64 hex); default the session\'s own. A contentRoot can only be anchored under the session\'s own record'),
|
|
444
469
|
fieldKey: hex64('fieldKey').describe('Canonical field id (64 hex, public)'),
|
|
445
470
|
expectedValue: z.string().min(1).optional()
|
|
446
471
|
.describe('Raw expected string (the server digests the EXACT string; pass this OR expectedDigest)'),
|
|
@@ -463,6 +488,7 @@ export function registerTools(server, client, config) {
|
|
|
463
488
|
}
|
|
464
489
|
return client.callAction('issueFieldEqualityAttestation', {
|
|
465
490
|
payloadHash: args.payloadHash,
|
|
491
|
+
attesterId: args.attesterId,
|
|
466
492
|
fieldKey: args.fieldKey,
|
|
467
493
|
expectedValue: args.expectedValue,
|
|
468
494
|
expectedDigest: args.expectedDigest,
|
|
@@ -488,6 +514,8 @@ export function registerTools(server, client, config) {
|
|
|
488
514
|
'contentRoot is supplied it is anchored first. ' + POLL_HINT,
|
|
489
515
|
inputSchema: {
|
|
490
516
|
payloadHash: hex64('payloadHash').describe('Attestation payload hash (64 hex)'),
|
|
517
|
+
attesterId: hex64('attesterId').optional()
|
|
518
|
+
.describe('The attester whose record of payloadHash the claim is bound to (64 hex); default the session\'s own. A contentRoot can only be anchored under the session\'s own record'),
|
|
491
519
|
fieldKey: hex64('fieldKey').describe('Canonical field id (64 hex, public)'),
|
|
492
520
|
value: z.string().min(1).optional()
|
|
493
521
|
.describe('Raw member string (witness only; pass this OR valueDigest)'),
|
|
@@ -522,6 +550,7 @@ export function registerTools(server, client, config) {
|
|
|
522
550
|
}
|
|
523
551
|
return client.callAction('issueFieldMembershipAttestation', {
|
|
524
552
|
payloadHash: args.payloadHash,
|
|
553
|
+
attesterId: args.attesterId,
|
|
525
554
|
fieldKey: args.fieldKey,
|
|
526
555
|
value: args.value,
|
|
527
556
|
valueDigest: args.valueDigest,
|
|
@@ -552,6 +581,8 @@ export function registerTools(server, client, config) {
|
|
|
552
581
|
'assuming all-or-nothing. ' + POLL_HINT,
|
|
553
582
|
inputSchema: {
|
|
554
583
|
payloadHash: hex64('payloadHash').describe('Shared attestation payload hash; also document A of any cross-root claim (64 hex)'),
|
|
584
|
+
attesterId: hex64('attesterId').optional()
|
|
585
|
+
.describe('The attester whose record of payloadHash the claim is bound to (64 hex); default the session\'s own. A contentRoot can only be anchored under the session\'s own record'),
|
|
555
586
|
claims: z.array(z.union([numericClaim, equalityClaim, membershipClaim, documentIntegrityClaim, documentDiffClaim]))
|
|
556
587
|
.min(1).max(8)
|
|
557
588
|
.describe('1-8 claims on the same payload hash; any mix of numeric, bytesEquality, setMembership, documentIntegrity and documentDiff'),
|
|
@@ -569,6 +600,7 @@ export function registerTools(server, client, config) {
|
|
|
569
600
|
}
|
|
570
601
|
return client.callAction('issueFieldPredicateAttestationBatch', {
|
|
571
602
|
payloadHash: args.payloadHash,
|
|
603
|
+
attesterId: args.attesterId,
|
|
572
604
|
contentRoot: args.contentRoot,
|
|
573
605
|
schemaId: args.schemaId,
|
|
574
606
|
claimsJson: JSON.stringify(args.claims.map((c) => 'threshold' in c ? { ...c, threshold: String(c.threshold) } : c)),
|
|
@@ -590,6 +622,10 @@ export function registerTools(server, client, config) {
|
|
|
590
622
|
inputSchema: {
|
|
591
623
|
payloadHashA: hex64('payloadHashA').describe('Anchored document A (64 hex)'),
|
|
592
624
|
payloadHashB: hex64('payloadHashB').describe('Anchored document B; must differ from A'),
|
|
625
|
+
attesterIdA: hex64('attesterIdA').optional()
|
|
626
|
+
.describe('Document A\'s attester (64 hex); default the session\'s own'),
|
|
627
|
+
attesterIdB: hex64('attesterIdB').optional()
|
|
628
|
+
.describe('Document B\'s attester (64 hex); default attesterIdA'),
|
|
593
629
|
allowedMask: z.number().int().min(0).max(MAX_MASK - 1)
|
|
594
630
|
.describe('Packed slot mask, one bit per slot of the vault width (16 bits by default, 32 on attestation-vault-32), bit i = slot i MAY differ. At least one real schema slot must stay constrained'),
|
|
595
631
|
schema: schemaSlots,
|
|
@@ -610,6 +646,8 @@ export function registerTools(server, client, config) {
|
|
|
610
646
|
return client.callAction('issueDocumentIntegrityAttestation', {
|
|
611
647
|
payloadHashA: args.payloadHashA,
|
|
612
648
|
payloadHashB: args.payloadHashB,
|
|
649
|
+
attesterIdA: args.attesterIdA,
|
|
650
|
+
attesterIdB: args.attesterIdB,
|
|
613
651
|
allowedMask: args.allowedMask,
|
|
614
652
|
schemaJson: JSON.stringify(args.schema),
|
|
615
653
|
openingAJson: JSON.stringify(args.openingA),
|
|
@@ -635,6 +673,10 @@ export function registerTools(server, client, config) {
|
|
|
635
673
|
inputSchema: {
|
|
636
674
|
payloadHashA: hex64('payloadHashA').describe('Anchored document A (64 hex)'),
|
|
637
675
|
payloadHashB: hex64('payloadHashB').describe('Anchored document B; must differ from A'),
|
|
676
|
+
attesterIdA: hex64('attesterIdA').optional()
|
|
677
|
+
.describe('Document A\'s attester (64 hex); default the session\'s own'),
|
|
678
|
+
attesterIdB: hex64('attesterIdB').optional()
|
|
679
|
+
.describe('Document B\'s attester (64 hex); default attesterIdA'),
|
|
638
680
|
k: z.number().int().min(1).max(MAX_SLOT_WIDTH).describe('Minimum number of differing slots to prove, up to the vault width'),
|
|
639
681
|
schema: schemaSlots,
|
|
640
682
|
openingA: documentOpening,
|
|
@@ -651,6 +693,8 @@ export function registerTools(server, client, config) {
|
|
|
651
693
|
}, run(async (args) => client.callAction('issueDocumentDiffAttestation', {
|
|
652
694
|
payloadHashA: args.payloadHashA,
|
|
653
695
|
payloadHashB: args.payloadHashB,
|
|
696
|
+
attesterIdA: args.attesterIdA,
|
|
697
|
+
attesterIdB: args.attesterIdB,
|
|
654
698
|
k: args.k,
|
|
655
699
|
schemaJson: JSON.stringify(args.schema),
|
|
656
700
|
openingAJson: JSON.stringify(args.openingA),
|
|
@@ -664,46 +708,6 @@ export function registerTools(server, client, config) {
|
|
|
664
708
|
idempotencyKey: args.idempotencyKey,
|
|
665
709
|
sponsorSessionId: args.sponsorSessionId,
|
|
666
710
|
})));
|
|
667
|
-
server.registerTool('prepare_anchor_commitment', {
|
|
668
|
-
description: 'Phase 0 of guarded anchoring: compute the opaque commitment for commit_document_anchor ' +
|
|
669
|
-
'plus the nonce the later reveal needs. Compute-only and synchronous. STORE the nonce and ' +
|
|
670
|
-
'keep it SECRET until the reveal: it is exactly what a mempool front-runner cannot forge. ' +
|
|
671
|
-
'Pass the same metadata here and to anchor_document. Use this when the payload hash is ' +
|
|
672
|
-
'secret until anchoring; for publicly known identifiers, registrar pre-assignment is the ' +
|
|
673
|
-
'better protection.',
|
|
674
|
-
inputSchema: {
|
|
675
|
-
sha256: hex64('sha256').describe('sha256 of the document content (64 hex)'),
|
|
676
|
-
metadata: z.record(z.unknown()).optional()
|
|
677
|
-
.describe('Public metadata object; MUST equal the metadata passed to anchor_document later'),
|
|
678
|
-
nonce: hex64('nonce').optional().describe('Reuse a specific nonce; omit for a fresh random one'),
|
|
679
|
-
},
|
|
680
|
-
}, run(async (args) => client.callAction('prepareAnchorCommitment', {
|
|
681
|
-
sha256: args.sha256,
|
|
682
|
-
metadata: args.metadata === undefined ? undefined : JSON.stringify(args.metadata),
|
|
683
|
-
nonce: args.nonce,
|
|
684
|
-
})));
|
|
685
|
-
server.registerTool('commit_document_anchor', {
|
|
686
|
-
description: 'Phase 1 of guarded anchoring: record the opaque commitment on-chain. Observers learn ' +
|
|
687
|
-
'nothing about the payload. Once this job finalizes, call anchor_document with the SAME ' +
|
|
688
|
-
'sha256 and metadata plus the nonce to reveal; a plain attest that front-ran the reveal is ' +
|
|
689
|
-
'taken over in-circuit, and everything the front-runner recorded meanwhile (content root, ' +
|
|
690
|
-
'disclosure grants, claims) stops counting. ' + POLL_HINT,
|
|
691
|
-
inputSchema: {
|
|
692
|
-
commitment: hex64('commitment').describe('The commitment from prepare_anchor_commitment (64 hex)'),
|
|
693
|
-
sessionId: z.string().uuid().describe('Wallet session id that signs and submits; the SAME session must reveal'),
|
|
694
|
-
contractAddress: z.string().min(1).describe('AttestationVault deployment'),
|
|
695
|
-
compiledArtifactRef: z.string().optional().describe("Contract artifact ref, defaults to 'attestation-vault'"),
|
|
696
|
-
idempotencyKey: z.string().optional().describe('Dedupes retries'),
|
|
697
|
-
sponsorSessionId: z.string().uuid().optional().describe('Optional second session that pays the dust fee'),
|
|
698
|
-
},
|
|
699
|
-
}, run(async (args) => client.callAction('commitDocumentAnchor', {
|
|
700
|
-
commitment: args.commitment,
|
|
701
|
-
sessionId: args.sessionId,
|
|
702
|
-
contractAddress: args.contractAddress,
|
|
703
|
-
compiledArtifactRef: args.compiledArtifactRef,
|
|
704
|
-
idempotencyKey: args.idempotencyKey,
|
|
705
|
-
sponsorSessionId: args.sponsorSessionId,
|
|
706
|
-
})));
|
|
707
711
|
server.registerTool('grant_disclosure', {
|
|
708
712
|
description: 'Grant a disclosure level for an attestation to a grantee identity, on-chain via the ' +
|
|
709
713
|
'AttestationVault. Attester-only: the transaction is rejected in-circuit unless the ' +
|
|
@@ -764,16 +768,19 @@ export function registerTools(server, client, config) {
|
|
|
764
768
|
'server. params by call: attest {payloadHash, metadataHash}; anchorContentRoot ' +
|
|
765
769
|
'{payloadHash, contentRoot, schemaId}; grantDisclosure {payloadHash, grantee, level 0|1|2}; ' +
|
|
766
770
|
'revokeDisclosure {payloadHash, grantee}; registerPassport {passportId, ownerId}; ' +
|
|
767
|
-
'bindPassport {passportId, payloadHash}
|
|
768
|
-
'
|
|
769
|
-
'server and no witness ever sent
|
|
770
|
-
'
|
|
771
|
-
'
|
|
772
|
-
'
|
|
773
|
-
'
|
|
774
|
-
'
|
|
775
|
-
'
|
|
776
|
-
'
|
|
771
|
+
'bindPassport {passportId, payloadHash}. The owner-gated calls address THIS builder\'s own ' +
|
|
772
|
+
'record of the payload (the circuit derives recordKey(attesterId, payloadHash) from the ' +
|
|
773
|
+
'caller). ZK CLAIMS, proven here with no wallet on the server and no witness ever sent ' +
|
|
774
|
+
'to it, address a record explicitly: pass payloadHash (this builder\'s record) or ' +
|
|
775
|
+
'payloadHash + attesterId (another attester\'s record) or recordKey directly: ' +
|
|
776
|
+
'proveFieldPredicate {payloadHash, fieldKey, threshold, op 0=lessOrEqual|1=greaterOrEqual} ' +
|
|
777
|
+
'plus merkleProof {fieldValue, fieldSalt, siblings, dirs}; proveFieldEquality ' +
|
|
778
|
+
'{payloadHash, fieldKey, expectedDigest} plus merkleProof {fieldSalt, siblings, dirs}; ' +
|
|
779
|
+
'proveFieldMembership {payloadHash, fieldKey, setRoot} plus merkleProof {fieldDigest, ' +
|
|
780
|
+
'fieldSalt, siblings, dirs, setProof}; proveFieldsUnchangedExcept {payloadHashA, ' +
|
|
781
|
+
'payloadHashB, allowedMask} and proveFieldsDiffer {payloadHashA, payloadHashB, k} ' +
|
|
782
|
+
'(optionally attesterIdA / attesterIdB, or recordKeyA / recordKeyB), both plus docPair ' +
|
|
783
|
+
'{schema, openingA, openingB}. Every witness field comes straight out of ' +
|
|
777
784
|
'prepare_document_proof. All hashes 64 hex. The built bytes are valid for ' +
|
|
778
785
|
'the transaction TTL (~30 min) and against the contract state at build time: if the ' +
|
|
779
786
|
'sponsor job ends CHAIN_EXECUTION_FAILED, build again.',
|
|
@@ -911,7 +918,7 @@ function wrapHandler(_client) {
|
|
|
911
918
|
}
|
|
912
919
|
catch (err) {
|
|
913
920
|
if (err instanceof NightgateApiError) {
|
|
914
|
-
const detail = { httpStatus: err.status, code: err.code ?? null, message: err.message };
|
|
921
|
+
const detail = { httpStatus: err.status, code: err.code ?? null, message: err.message, ...(err.detail ?? {}) };
|
|
915
922
|
return { content: [{ type: 'text', text: JSON.stringify(detail, null, 2) }], isError: true };
|
|
916
923
|
}
|
|
917
924
|
const message = err instanceof Error ? err.message : String(err);
|