@odatano/nightgate-mcp 0.18.1 → 0.18.2

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/docs/tools.md CHANGED
@@ -1,152 +1,153 @@
1
- # Tools of @odatano/nightgate-mcp
2
-
3
- Every tool and what it returns. Writes are built, proven and signed here with
4
- the caller seed, a sponsor pays the fee, and the tool waits until the job
5
- settled. Reads of contract state are free. Vault tools default to the shared
6
- sandbox vault of the network and to the `attestation-vault-32` lineage.
7
-
8
- ## First anchor
9
-
10
- With only `ODATANO_ACCESS_KEY` set:
11
-
12
- 1. `anchor_document` with the sha256 of a document. It builds the transaction,
13
- the sponsor pays, and after about a minute the answer carries `status`,
14
- `attesterId`, `txHash` and `check`.
15
- 2. `check` is the `verify_attestation` call that shows the record on-chain.
16
- Run it as given. It is free.
17
-
18
- The first build downloads the prover keys and creates the seed file (see
19
- [Seed](#seed)).
20
-
21
- ## All tools
22
-
23
- | Tool | What it does |
24
- |---|---|
25
- | `verify_attestation`, `verify_predicate` | Check a record or a ZK claim against live contract state; absent = `verified: false`. Free |
26
- | `prepare_document_proof`, `prepare_membership_set` | Build proof inputs: salted content tree, set root |
27
- | `anchor_document` | Anchor a document hash, optionally with its content root, in one call |
28
- | `submit_vault_call` | Any vault call in one call: ZK claims over a hidden field, claims across two documents, disclosure, passports |
29
- | `build_sponsorable_transaction`, `get_attester_identity` | Build a vault call and keep the bytes under a `txId` or in `outFile`, for a sponsor elsewhere. The attester id and shielded keys of the seed |
30
- | `sponsor_unbound_transaction`, `sponsor_finalized_transaction` | Hand bytes built elsewhere to a sponsor, by `txId` or `file`, and wait for the job |
31
- | `get_swap_wallet`, `read_swap_offer` | Shielded coins of the local wallet; what an offer gives and wants |
32
- | `build_swap_offer`, `take_swap_offer`, `revert_swap_offer` | Build one half of a shielded swap locally, take an offer, release a half |
33
- | `sponsor_swap` | Hand both halves of a swap, or a board offer plus the taker half, to a sponsor and wait |
34
- | `post_swap_offer`, `list_swap_offers`, `retire_swap_offer` | The server's offer board: post a maker half, find open offers, take yours down |
35
- | `get_swap_offer`, `my_swap_offers`, `get_board_status` | Follow one offer, see your own posts and their fills, read the board's counts without credentials |
36
- | `mint_token` | Mint a shielded token with a name of your own on a token factory; the seed is the issuer |
37
- | `derive_token_type` | Token type a minting contract produces |
38
- | `get_usage` | What the key has left and what each call cost. Free |
39
- | `analytics_*` | Midnight aggregates via ODATANO ASTRA, when the host serves it |
40
-
41
- Errors carry the server's HTTP status and `code` (`INVALID_ARGUMENT`, ...).
42
-
43
- ## What a write returns
44
-
45
- | Field | Meaning |
46
- |---|---|
47
- | `status` | `succeeded`, `failed`, or `pending` when the job is still open after 5 minutes or its status cannot be read |
48
- | `txHash` | Ledger identifier of the transaction |
49
- | `transactionHash` | Hash the explorers show, null until indexed |
50
- | `result` | The job result, for a swap `swap`, for a mint `tokenType` |
51
- | `errorCode`, `errorMessage`, `next` | Why it failed and what to do |
52
- | `statusError` | With `pending`: why the status could not be read |
53
- | `check` | `{ tool, args }`: the call that shows the effect on-chain |
54
- | `seed` | Only once, when this call created the seed file |
55
-
56
- `failed` with `CHAIN_EXECUTION_FAILED`: the transaction is on-chain but its
57
- contract call did not apply, usually because another call changed the same
58
- contract in that block. Run the tool again. It builds against the new state.
59
-
60
- A tool that was cut off, for example by a client timeout, or that came back
61
- `pending`: run it again with the same arguments. It picks up the job it
62
- started and submits nothing new, so there is no second fee.
63
-
64
- While a call runs it sends MCP progress every 5 seconds, so a client that
65
- resets its request timeout on progress keeps the call open. A proof takes
66
- several minutes. The MCP Inspector CLI ignores progress and stops after 60
67
- seconds, so it cannot run the writes. With `@modelcontextprotocol/sdk`, call
68
- `client.callTool(params, undefined, { timeout: 600000, resetTimeoutOnProgress: true })`.
69
-
70
- ## Sandbox vaults
71
-
72
- `contractAddress` defaults to the shared sandbox vault of the network. Both
73
- are `attestation-vault-32` and open to every key; a 16-slot
74
- `attestation-vault` needs its address:
75
-
76
- | Network | Vault |
77
- |---|---|
78
- | preprod | `ca0b1e3c601857a7b6940bbbbd6508654f5983b63aa36ccf8254f7700f89aead` |
79
- | preview | `31df87bc396ab32e8408b0ebfd1f8e7bf121f17e12e2ba360ed9f08c7ba40692` |
80
-
81
- Mainnet has no sandbox vault; pass `contractAddress` there.
82
-
83
- ## Seed
84
-
85
- The seed is the caller's identity on Midnight. Every record anchored with it
86
- belongs to its `attesterId`, and only it can prove claims on or revoke
87
- disclosures of those records.
88
-
89
- - `NIGHTGATE_SEED_HEX` set: that seed is used.
90
- - Unset: the seed is read from `NIGHTGATE_SEED_FILE` (default
91
- `~/.nightgate-mcp/seed`). Without that file the first tool that needs the
92
- seed creates it, readable by the owner only, and its answer carries
93
- `seed: { created, file, meaning }`.
94
-
95
- Keep the file and back it up. Every server on the same machine shares that
96
- file and so one identity. For separate identities, give each server its own
97
- `NIGHTGATE_SEED_HEX` or `NIGHTGATE_SEED_FILE`.
98
-
99
- ## Field claims
100
-
101
- 1. `prepare_document_proof` with the document and the fields to make
102
- provable. Keep `opening` with the document.
103
- 2. `anchor_document` with `sha256: payloadHash`, `contentRoot` and `schemaId`.
104
- 3. `submit_vault_call` with `proveFieldPredicate`, `proveFieldEquality` or
105
- `proveFieldMembership`, the params listed in `build_sponsorable_transaction`
106
- and the field's witness as `merkleProof`. The witness stays here.
107
- 4. `check` names the `verify_predicate` call for the claim.
108
-
109
- ## verify_attestation fields
110
-
111
- | Field | Meaning |
112
- |---|---|
113
- | `verified` | The record stands and every given check matched |
114
- | `attested` | The attester's record of `payloadHash` is in the vault |
115
- | `contentRootOk`, `schemaOk` | The given `contentRoot` and `schemaId` match the anchor |
116
- | `bindingRegistered` | Only for lookups by `documentId`: the vault registrar assigned that id to this attester. A record anchored without a document id reports `false`, and that is fine |
117
- | `recordKey` | Ledger key of the record, `recordKey(attesterId, payloadHash)` |
118
-
119
- ## Shielded swaps
120
-
121
- Two wallets exchange two shielded tokens without a contract. Each side builds
122
- one half, the halves mirror each other, a sponsor merges them and pays the fee.
123
- Needs a Midnight indexer the swap wallet syncs its coins from
124
- (`NIGHTGATE_INDEXER_HTTP_URL`, `NIGHTGATE_INDEXER_WS_URL`).
125
-
126
- 1. `get_swap_wallet`: balance, free coins and `spendable` per token type. The
127
- first call starts the sync of the shielded coins (about 5 minutes from
128
- genesis, seconds with `NIGHTGATE_SWAP_STATE_FILE`).
129
- 2. Maker: `build_swap_offer` with `give` and `want` returns the offer file
130
- (`swapoffer1...`) to publish, or `post_swap_offer` puts it on the server's
131
- board.
132
- 3. Taker: `list_swap_offers` or `read_swap_offer`, then `take_swap_offer` with
133
- `expect`, `submit: true` and, for a board entry, its `offerId`. It builds
134
- the mirror half, submits both and waits; the result carries `swap`.
135
- 4. The maker follows the offer with `get_swap_offer` or `my_swap_offers`
136
- (`filled` + `filledTxHash`); `list_swap_offers` with `status: all` and
137
- `since` is the board's change feed.
138
-
139
- - One half spends at most `NIGHTGATE_SWAP_MAX_INPUTS` coins, the smallest that
140
- fit. `give.amount` above `spendable` is refused before proving.
141
- - An offer fills once. Its coins stay reserved in the maker's wallet until the
142
- swap lands or `revert_swap_offer` releases them.
143
- - A refused submission keeps the proven half: `sponsor_swap` with its `halfId`.
144
- - The sponsor needs swaps switched on and both token types on its list; an
145
- agent grant needs `sponsorSwap` in `allowedActions`.
146
- - With `NIGHTGATE_PROOF_SERVER_URL` the proof server sees the coins a half
147
- spends: use one you run yourself.
148
- - Tokens to swap: `mint_token` mints on a token factory to this wallet, or to
149
- any wallet whose two keys are given; this needs
150
- `@odatano/contract-token-factory` next to `@odatano/nightgate-tx`. A landed
151
- mint makes the type known to the sponsor.
152
- - `get_board_status` says whether a sponsor is ready before anything is built.
1
+ # Tools of @odatano/nightgate-mcp
2
+
3
+ Every tool and what it returns. Writes are built, proven and signed here with
4
+ the caller seed, a sponsor pays the fee, and the tool waits until the job
5
+ settled. Reads of contract state are free. Vault tools default to the shared
6
+ sandbox vault of the network and to the `attestation-vault-32` lineage.
7
+
8
+ ## First anchor
9
+
10
+ With only `ODATANO_ACCESS_KEY` set:
11
+
12
+ 1. `anchor_document` with the sha256 of a document. It builds the transaction,
13
+ the sponsor pays, and after about a minute the answer carries `status`,
14
+ `attesterId`, `txHash` and `check`.
15
+ 2. `check` is the `verify_attestation` call that shows the record on-chain.
16
+ Run it as given. It is free.
17
+
18
+ The first build downloads the prover keys and creates the seed file (see
19
+ [Seed](#seed)).
20
+
21
+ ## All tools
22
+
23
+ | Tool | What it does |
24
+ |---|---|
25
+ | `verify_attestation`, `verify_predicate` | Check a record or a ZK claim against live contract state; absent = `verified: false`. Free |
26
+ | `prepare_document_proof`, `prepare_membership_set` | Build proof inputs: salted content tree, set root |
27
+ | `anchor_document` | Anchor a document hash, optionally with its content root, in one call |
28
+ | `submit_vault_call` | Any vault call in one call: ZK claims over a hidden field, claims across two documents, disclosure, passports |
29
+ | `build_sponsorable_transaction`, `get_attester_identity` | Build a vault call and keep the bytes under a `txId` or in `outFile`, for a sponsor elsewhere. The attester id and shielded keys of the seed |
30
+ | `sponsor_unbound_transaction`, `sponsor_finalized_transaction` | Hand bytes built elsewhere to a sponsor, by `txId` or `file`, and wait for the job |
31
+ | `get_swap_wallet`, `read_swap_offer` | Shielded coins of the local wallet; what an offer gives and wants |
32
+ | `build_swap_offer`, `take_swap_offer`, `revert_swap_offer` | Build one half of a shielded swap locally, take an offer, release a half |
33
+ | `sponsor_swap` | Hand both halves of a swap, or a board offer plus the taker half, to a sponsor and wait |
34
+ | `post_swap_offer`, `list_swap_offers`, `retire_swap_offer` | The server's offer board: post a maker half, find open offers, take yours down |
35
+ | `get_swap_offer`, `my_swap_offers`, `get_board_status` | Follow one offer, see your own posts and their fills, read the board's counts without credentials |
36
+ | `mint_token` | Mint a shielded token with a name of your own on a token factory; the seed is the issuer |
37
+ | `derive_token_type` | Token type a minting contract produces |
38
+ | `get_usage` | What the key has left and what each call cost. Free |
39
+ | `analytics_*` | Midnight aggregates via ODATANO ASTRA, when the host serves it |
40
+
41
+ Errors carry the server's HTTP status and `code` (`INVALID_ARGUMENT`, ...).
42
+
43
+ ## What a write returns
44
+
45
+ | Field | Meaning |
46
+ |---|---|
47
+ | `status` | `succeeded`, `failed`, or `pending` when the job is still open after 5 minutes or its status cannot be read |
48
+ | `txHash` | Ledger identifier of the transaction |
49
+ | `transactionHash` | Hash the explorers show, null until indexed |
50
+ | `result` | The job result, for a swap `swap`, for a mint `tokenType` |
51
+ | `errorCode`, `errorMessage`, `next` | Why it failed and what to do |
52
+ | `statusError` | With `pending`: why the status could not be read |
53
+ | `check` | `{ tool, args }`: the call that shows the effect on-chain |
54
+ | `seed` | Only once, when this call created the seed file |
55
+
56
+ `failed` with `CHAIN_EXECUTION_FAILED`: the transaction is on-chain but its
57
+ contract call did not apply, usually because another call changed the same
58
+ contract in that block. Run the tool again. It builds against the new state.
59
+
60
+ A tool that was cut off, for example by a client timeout, or that came back
61
+ `pending`: run it again with the same arguments. It picks up the job it
62
+ started and submits nothing new, so there is no second fee.
63
+
64
+ While a call runs it sends MCP progress every 5 seconds, so a client that
65
+ resets its request timeout on progress keeps the call open. A proof takes
66
+ several minutes. The MCP Inspector CLI ignores progress and stops after 60
67
+ seconds, so it cannot run the writes. With `@modelcontextprotocol/sdk`, call
68
+ `client.callTool(params, undefined, { timeout: 600000, resetTimeoutOnProgress: true })`.
69
+
70
+ ## Sandbox vaults
71
+
72
+ `contractAddress` defaults to the shared sandbox vault of the network. Both
73
+ are `attestation-vault-32` and open to every key; a 16-slot
74
+ `attestation-vault` needs its address:
75
+
76
+ | Network | Vault |
77
+ |---|---|
78
+ | preprod | `ca0b1e3c601857a7b6940bbbbd6508654f5983b63aa36ccf8254f7700f89aead` |
79
+ | preview | `31df87bc396ab32e8408b0ebfd1f8e7bf121f17e12e2ba360ed9f08c7ba40692` |
80
+
81
+ Mainnet has no sandbox vault; pass `contractAddress` there.
82
+
83
+ ## Seed
84
+
85
+ The seed is the caller's identity on Midnight. Every record anchored with it
86
+ belongs to its `attesterId`, and only it can prove claims on or revoke
87
+ disclosures of those records.
88
+
89
+ - `NIGHTGATE_SEED_HEX` set: that seed is used.
90
+ - Unset: the seed is read from `NIGHTGATE_SEED_FILE` (default
91
+ `~/.nightgate-mcp/seed`). Without that file the first tool that needs the
92
+ seed creates it, readable by the owner only, and its answer carries
93
+ `seed: { created, file, meaning }`.
94
+
95
+ Keep the file and back it up. Every server on the same machine shares that
96
+ file and so one identity. For separate identities, give each server its own
97
+ `NIGHTGATE_SEED_HEX` or `NIGHTGATE_SEED_FILE`.
98
+
99
+ ## Field claims
100
+
101
+ 1. `prepare_document_proof` with the document and the fields to make
102
+ provable. Keep `opening` with the document.
103
+ 2. `anchor_document` with `sha256: payloadHash`, `contentRoot` and `schemaId`.
104
+ 3. `submit_vault_call` with `proveFieldPredicate`, `proveFieldEquality` or
105
+ `proveFieldMembership`, the params listed in `build_sponsorable_transaction`
106
+ and the field's witness as `merkleProof`. The witness stays here.
107
+ 4. `check` names the `verify_predicate` call for the claim.
108
+
109
+ ## verify_attestation fields
110
+
111
+ | Field | Meaning |
112
+ |---|---|
113
+ | `verified` | The record stands and every given check matched |
114
+ | `attested` | The attester's record of `payloadHash` is in the vault |
115
+ | `contentRootOk`, `schemaOk` | The given `contentRoot` and `schemaId` match the anchor |
116
+ | `bindingRegistered` | Only for lookups by `documentId`: the vault registrar assigned that id to this attester. A record anchored without a document id reports `false`, and that is fine |
117
+ | `recordKey` | Ledger key of the record, `recordKey(attesterId, payloadHash)` |
118
+
119
+ ## Shielded swaps
120
+
121
+ Two wallets exchange two shielded tokens without a contract. Each side builds
122
+ one half, the halves mirror each other, a sponsor merges them and pays the fee.
123
+ Needs a Midnight indexer the swap wallet syncs its coins from
124
+ (`NIGHTGATE_INDEXER_HTTP_URL`, `NIGHTGATE_INDEXER_WS_URL`).
125
+
126
+ 1. `get_swap_wallet`: balance, free coins and `spendable` per token type. The
127
+ first call starts the sync of the shielded coins (about 5 minutes from
128
+ genesis, seconds with `NIGHTGATE_SWAP_STATE_FILE`). With offers posted from
129
+ this server it reads their state in one `listSwapOffers` call.
130
+ 2. Maker: `build_swap_offer` with `give` and `want` returns the offer file
131
+ (`swapoffer1...`) to publish, or `post_swap_offer` puts it on the server's
132
+ board.
133
+ 3. Taker: `list_swap_offers` or `read_swap_offer`, then `take_swap_offer` with
134
+ `expect`, `submit: true` and, for a board entry, its `offerId`. It builds
135
+ the mirror half, submits both and waits; the result carries `swap`.
136
+ 4. The maker follows the offer with `get_swap_offer` or `my_swap_offers`
137
+ (`filled` + `filledTxHash`); `list_swap_offers` with `status: all` and
138
+ `since` is the board's change feed.
139
+
140
+ - One half spends at most `NIGHTGATE_SWAP_MAX_INPUTS` coins, the smallest that
141
+ fit. `give.amount` above `spendable` is refused before proving.
142
+ - An offer fills once. Its coins stay reserved in the maker's wallet until the
143
+ swap lands or `revert_swap_offer` releases them.
144
+ - A refused submission keeps the proven half: `sponsor_swap` with its `halfId`.
145
+ - The sponsor needs swaps switched on and both token types on its list; an
146
+ agent grant needs `sponsorSwap` in `allowedActions`.
147
+ - With `NIGHTGATE_PROOF_SERVER_URL` the proof server sees the coins a half
148
+ spends: use one you run yourself.
149
+ - Tokens to swap: `mint_token` mints on a token factory to this wallet, or to
150
+ any wallet whose two keys are given; this needs
151
+ `@odatano/contract-token-factory` next to `@odatano/nightgate-tx`. A landed
152
+ mint makes the type known to the sponsor.
153
+ - `get_board_status` says whether a sponsor is ready before anything is built.
package/package.json CHANGED
@@ -1,66 +1,66 @@
1
- {
2
- "name": "@odatano/nightgate-mcp",
3
- "version": "0.18.1",
4
- "description": "MCP server exposing NIGHTGATE (Midnight blockchain attestation layer) to AI agents",
5
- "license": "Apache-2.0",
6
- "publishConfig": {
7
- "access": "public"
8
- },
9
- "type": "module",
10
- "main": "dist/index.js",
11
- "bin": {
12
- "nightgate-mcp": "dist/index.js"
13
- },
14
- "files": [
15
- "dist",
16
- "docs",
17
- "README.md",
18
- "CHANGELOG.md",
19
- "LICENSE"
20
- ],
21
- "engines": {
22
- "node": ">=20"
23
- },
24
- "scripts": {
25
- "build": "tsc -p tsconfig.json",
26
- "start": "node dist/index.js",
27
- "integration": "npm run build && node --env-file-if-exists=.env scripts/integration-mcp.mjs && node scripts/integration-swap.mjs",
28
- "live:sponsor-unbound": "npm run build && node --env-file-if-exists=.env scripts/live-sponsor-unbound.mjs",
29
- "prepublishOnly": "npm run build",
30
- "live:stdio": "npm run build && node --env-file-if-exists=.env scripts/live-stdio-smoke.mjs",
31
- "mcp": "node --env-file-if-exists=.env scripts/mcp-cli.mjs",
32
- "live:field-proof": "npm run build && node --env-file-if-exists=.env scripts/live-field-proof.mjs"
33
- },
34
- "repository": {
35
- "type": "git",
36
- "url": "git+https://github.com/ODATANO/NIGHTGATE-MCP.git"
37
- },
38
- "keywords": [
39
- "mcp",
40
- "model-context-protocol",
41
- "midnight",
42
- "blockchain",
43
- "attestation",
44
- "zero-knowledge",
45
- "odata",
46
- "sap-cap"
47
- ],
48
- "dependencies": {
49
- "@modelcontextprotocol/sdk": "^1.0.0",
50
- "@odatano/nightgate-tx": "^0.15.1",
51
- "zod": "^3.23.0"
52
- },
53
- "peerDependencies": {
54
- "@odatano/contract-token-factory": ">=0.1.0"
55
- },
56
- "peerDependenciesMeta": {
57
- "@odatano/contract-token-factory": {
58
- "optional": true
59
- }
60
- },
61
- "devDependencies": {
62
- "@odatano/contract-token-factory": "^0.1.0",
63
- "@types/node": "^20.0.0",
64
- "typescript": "^5.5.0"
65
- }
66
- }
1
+ {
2
+ "name": "@odatano/nightgate-mcp",
3
+ "version": "0.18.2",
4
+ "description": "MCP server exposing NIGHTGATE (Midnight blockchain attestation layer) to AI agents",
5
+ "license": "Apache-2.0",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "type": "module",
10
+ "main": "dist/index.js",
11
+ "bin": {
12
+ "nightgate-mcp": "dist/index.js"
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "docs",
17
+ "README.md",
18
+ "CHANGELOG.md",
19
+ "LICENSE"
20
+ ],
21
+ "engines": {
22
+ "node": ">=20"
23
+ },
24
+ "scripts": {
25
+ "build": "tsc -p tsconfig.json",
26
+ "start": "node dist/index.js",
27
+ "integration": "npm run build && node --env-file-if-exists=.env scripts/integration-mcp.mjs && node scripts/integration-swap.mjs",
28
+ "live:sponsor-unbound": "npm run build && node --env-file-if-exists=.env scripts/live-sponsor-unbound.mjs",
29
+ "prepublishOnly": "npm run build",
30
+ "live:stdio": "npm run build && node --env-file-if-exists=.env scripts/live-stdio-smoke.mjs",
31
+ "mcp": "node --env-file-if-exists=.env scripts/mcp-cli.mjs",
32
+ "live:field-proof": "npm run build && node --env-file-if-exists=.env scripts/live-field-proof.mjs"
33
+ },
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/ODATANO/NIGHTGATE-MCP.git"
37
+ },
38
+ "keywords": [
39
+ "mcp",
40
+ "model-context-protocol",
41
+ "midnight",
42
+ "blockchain",
43
+ "attestation",
44
+ "zero-knowledge",
45
+ "odata",
46
+ "sap-cap"
47
+ ],
48
+ "dependencies": {
49
+ "@modelcontextprotocol/sdk": "^1.0.0",
50
+ "@odatano/nightgate-tx": "^0.15.1",
51
+ "zod": "^3.23.0"
52
+ },
53
+ "peerDependencies": {
54
+ "@odatano/contract-token-factory": ">=0.1.0"
55
+ },
56
+ "peerDependenciesMeta": {
57
+ "@odatano/contract-token-factory": {
58
+ "optional": true
59
+ }
60
+ },
61
+ "devDependencies": {
62
+ "@odatano/contract-token-factory": "^0.1.0",
63
+ "@types/node": "^20.0.0",
64
+ "typescript": "^5.5.0"
65
+ }
66
+ }