nostr-bray 1.18.2 → 1.20.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/README.md +84 -80
- package/dist/identity/tools.js +20 -12
- package/dist/index.js +4 -3
- package/dist/relay/tools.js +7 -7
- package/dist/safety/tools.js +3 -3
- package/dist/social/tools.js +41 -41
- package/dist/trust/tools.js +16 -16
- package/dist/util/tools.js +14 -14
- package/dist/zap/tools.js +26 -11
- package/llms-full.txt +95 -89
- package/llms.txt +15 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
[](./LICENSE)
|
|
9
9
|
[](./tsconfig.json)
|
|
10
10
|
|
|
11
|
-
An MCP server that gives AI agents a full Nostr identity — not just a key pair, but a hierarchical identity tree with personas, attestations, ring signatures, encrypted DMs, and duress detection.
|
|
11
|
+
An MCP server that gives AI agents a full Nostr identity — not just a key pair, but a hierarchical identity tree with personas, attestations, ring signatures, encrypted DMs, and duress detection. 77 tools across 10 groups.
|
|
12
12
|
|
|
13
13
|
## The Problem
|
|
14
14
|
|
|
@@ -68,140 +68,144 @@ Or with a secret file (recommended):
|
|
|
68
68
|
|
|
69
69
|
## Tool Groups
|
|
70
70
|
|
|
71
|
-
### Identity (
|
|
71
|
+
### Identity (12 tools)
|
|
72
72
|
|
|
73
73
|
| Tool | Description |
|
|
74
74
|
|------|-------------|
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
79
|
-
| `
|
|
80
|
-
| `
|
|
81
|
-
| `
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
75
|
+
| `whoami` | Returns the active identity's npub |
|
|
76
|
+
| `identity-create` | Generate a fresh identity with BIP-39 mnemonic |
|
|
77
|
+
| `identity-derive` | Derive a child identity by purpose and index |
|
|
78
|
+
| `identity-derive-persona` | Derive a named persona (work, personal, anonymous) |
|
|
79
|
+
| `identity-switch` | Switch active identity — all tools operate as the new identity |
|
|
80
|
+
| `identity-list` | List all known identities (public info only) |
|
|
81
|
+
| `identity-prove` | Create blind/full linkage proof |
|
|
82
|
+
| `identity-backup-shamir` | Split master secret into Shamir shard files |
|
|
83
|
+
| `identity-restore-shamir` | Reconstruct secret from shard files |
|
|
84
|
+
| `identity-backup` | Fetch profile, contacts, relay list as portable bundle |
|
|
85
|
+
| `identity-restore` | Re-sign migratable events under the active identity |
|
|
86
|
+
| `identity-migrate` | Full migration with preview, confirmation, and linkage proof |
|
|
86
87
|
|
|
87
88
|
### Social (14 tools)
|
|
88
89
|
|
|
89
90
|
| Tool | Description |
|
|
90
91
|
|------|-------------|
|
|
91
|
-
| `
|
|
92
|
-
| `
|
|
93
|
-
| `
|
|
94
|
-
| `
|
|
95
|
-
| `
|
|
96
|
-
| `
|
|
97
|
-
| `
|
|
98
|
-
| `
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
92
|
+
| `social-post` | Post a text note (kind 1) |
|
|
93
|
+
| `social-reply` | Reply with correct e-tag and p-tag threading |
|
|
94
|
+
| `social-react` | React to an event (kind 7) |
|
|
95
|
+
| `social-delete` | Request deletion of your event (kind 5) |
|
|
96
|
+
| `social-repost` | Repost/boost an event (kind 6) |
|
|
97
|
+
| `social-profile-get` | Fetch and parse a kind 0 profile |
|
|
98
|
+
| `social-profile-set` | Set profile with overwrite safety guard |
|
|
99
|
+
| `dm-send` | Send encrypted DM (NIP-17 default, NIP-04 opt-in) |
|
|
100
|
+
| `dm-read` | Read and decrypt received DMs |
|
|
101
|
+
| `contacts-get` | Fetch contact list (kind 3 follows) |
|
|
102
|
+
| `contacts-follow` | Follow a pubkey (publishes updated kind 3) |
|
|
103
|
+
| `contacts-unfollow` | Unfollow a pubkey |
|
|
104
|
+
| `social-notifications` | Fetch mentions, replies, reactions, zap receipts |
|
|
105
|
+
| `social-feed` | Fetch kind 1 text note feed |
|
|
105
106
|
|
|
106
107
|
### Trust (11 tools)
|
|
107
108
|
|
|
108
109
|
| Tool | Description |
|
|
109
110
|
|------|-------------|
|
|
110
|
-
| `
|
|
111
|
-
| `
|
|
112
|
-
| `
|
|
113
|
-
| `
|
|
114
|
-
| `
|
|
115
|
-
| `
|
|
116
|
-
| `
|
|
117
|
-
| `
|
|
118
|
-
| `
|
|
119
|
-
| `
|
|
120
|
-
| `
|
|
121
|
-
|
|
122
|
-
### Relay (
|
|
111
|
+
| `trust-attest` | Create kind 31000 verifiable attestation |
|
|
112
|
+
| `trust-read` | Read attestations by subject/type/attestor |
|
|
113
|
+
| `trust-verify` | Validate attestation structure |
|
|
114
|
+
| `trust-revoke` | Revoke an attestation (identity check) |
|
|
115
|
+
| `trust-request` | Send attestation request via NIP-17 |
|
|
116
|
+
| `trust-request-list` | Scan DMs for attestation requests |
|
|
117
|
+
| `trust-proof-publish` | Publish linkage proof (kind 30078) with confirmation |
|
|
118
|
+
| `trust-ring-prove` | Anonymous group membership proof (ring signature) |
|
|
119
|
+
| `trust-ring-verify` | Verify ring signature proof |
|
|
120
|
+
| `trust-spoken-challenge` | Generate spoken verification token |
|
|
121
|
+
| `trust-spoken-verify` | Verify spoken token response |
|
|
122
|
+
|
|
123
|
+
### Relay (5 tools)
|
|
123
124
|
|
|
124
125
|
| Tool | Description |
|
|
125
126
|
|------|-------------|
|
|
126
|
-
| `
|
|
127
|
-
| `
|
|
128
|
-
| `
|
|
129
|
-
| `
|
|
127
|
+
| `relay-list` | List relays with shared-relay warnings |
|
|
128
|
+
| `relay-set` | Publish kind 10002 relay list |
|
|
129
|
+
| `relay-add` | Add relay to active identity (in-memory) |
|
|
130
|
+
| `relay-query` | Query events from relays by kind, author, tags, or time range |
|
|
131
|
+
| `relay-info` | Fetch NIP-11 relay information document |
|
|
130
132
|
|
|
131
133
|
### Zap (7 tools)
|
|
132
134
|
|
|
133
135
|
| Tool | Description |
|
|
134
136
|
|------|-------------|
|
|
135
|
-
| `
|
|
136
|
-
| `
|
|
137
|
-
| `
|
|
138
|
-
| `
|
|
139
|
-
| `
|
|
140
|
-
| `
|
|
141
|
-
| `
|
|
137
|
+
| `zap-send` | Pay a Lightning invoice via NWC |
|
|
138
|
+
| `zap-balance` | Request wallet balance via NWC |
|
|
139
|
+
| `zap-make-invoice` | Generate a Lightning invoice via NWC |
|
|
140
|
+
| `zap-lookup-invoice` | Check invoice payment status via NWC |
|
|
141
|
+
| `zap-list-transactions` | List recent Lightning transactions |
|
|
142
|
+
| `zap-receipts` | Parse zap receipts (amount, sender, message) |
|
|
143
|
+
| `zap-decode` | Decode bolt11 invoice fields |
|
|
142
144
|
|
|
143
145
|
### Safety (2 tools)
|
|
144
146
|
|
|
145
147
|
| Tool | Description |
|
|
146
148
|
|------|-------------|
|
|
147
|
-
| `
|
|
148
|
-
| `
|
|
149
|
+
| `safety-configure` | Configure an alternative identity persona |
|
|
150
|
+
| `safety-activate` | Switch to alternative identity |
|
|
149
151
|
|
|
150
152
|
### Blossom (3 tools)
|
|
151
153
|
|
|
152
154
|
| Tool | Description |
|
|
153
155
|
|------|-------------|
|
|
154
|
-
| `
|
|
155
|
-
| `
|
|
156
|
-
| `
|
|
156
|
+
| `blossom-upload` | Upload file to a blossom media server |
|
|
157
|
+
| `blossom-list` | List blobs for a pubkey |
|
|
158
|
+
| `blossom-delete` | Delete a blob by SHA-256 hash |
|
|
157
159
|
|
|
158
160
|
### Groups — NIP-29 (4 tools)
|
|
159
161
|
|
|
160
162
|
| Tool | Description |
|
|
161
163
|
|------|-------------|
|
|
162
|
-
| `
|
|
163
|
-
| `
|
|
164
|
-
| `
|
|
165
|
-
| `
|
|
164
|
+
| `group-info` | Fetch group metadata |
|
|
165
|
+
| `group-chat` | Read group chat messages |
|
|
166
|
+
| `group-send` | Send message to a group |
|
|
167
|
+
| `group-members` | List group members |
|
|
166
168
|
|
|
167
169
|
### Community NIPs (2 tools)
|
|
168
170
|
|
|
169
171
|
| Tool | Description |
|
|
170
172
|
|------|-------------|
|
|
171
|
-
| `
|
|
172
|
-
| `
|
|
173
|
+
| `nip-publish` | Publish a community NIP (kind 30817) |
|
|
174
|
+
| `nip-read` | Fetch community NIPs |
|
|
173
175
|
|
|
174
|
-
### Utility (
|
|
176
|
+
### Utility (18 tools)
|
|
175
177
|
|
|
176
178
|
| Tool | Description |
|
|
177
179
|
|------|-------------|
|
|
178
180
|
| `decode` | Decode npub/nsec/note/nevent/nprofile/naddr |
|
|
179
|
-
| `
|
|
180
|
-
| `
|
|
181
|
-
| `
|
|
182
|
-
| `
|
|
183
|
-
| `
|
|
184
|
-
| `
|
|
185
|
-
| `
|
|
186
|
-
| `
|
|
181
|
+
| `encode-npub` | Encode hex pubkey as npub |
|
|
182
|
+
| `encode-note` | Encode hex event ID as note |
|
|
183
|
+
| `encode-nprofile` | Encode pubkey + relays as nprofile |
|
|
184
|
+
| `encode-nevent` | Encode event ID + relays as nevent |
|
|
185
|
+
| `encode-naddr` | Encode addressable event as naddr |
|
|
186
|
+
| `encode-nsec` | Encode hex private key as nsec |
|
|
187
|
+
| `key-public` | Derive pubkey from secret key |
|
|
188
|
+
| `key-encrypt` | Encrypt a secret key with a password (NIP-49 ncryptsec) |
|
|
189
|
+
| `key-decrypt` | Decrypt an ncryptsec (NIP-49) with a password |
|
|
190
|
+
| `verify-event` | Verify event hash and signature |
|
|
187
191
|
| `filter` | Test if an event matches a filter |
|
|
188
|
-
| `
|
|
189
|
-
| `
|
|
192
|
+
| `nip44-encrypt` | NIP-44 encrypt for a recipient |
|
|
193
|
+
| `nip44-decrypt` | NIP-44 decrypt from a sender |
|
|
190
194
|
| `count` | Count events matching a filter |
|
|
191
195
|
| `fetch` | Fetch events by nip19 code |
|
|
192
|
-
| `
|
|
193
|
-
| `
|
|
196
|
+
| `nip-list` | List all official NIPs |
|
|
197
|
+
| `nip-show` | Show a specific NIP's content |
|
|
194
198
|
|
|
195
199
|
## Identity Switching
|
|
196
200
|
|
|
197
201
|
The killer feature. Every tool operates as the "active identity." Switch with a single call:
|
|
198
202
|
|
|
199
203
|
```
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
204
|
+
identity-derive-persona("work") → npub1abc...
|
|
205
|
+
identity-switch("work") → now operating as work persona
|
|
206
|
+
social-post("Hello from work!") → signed by npub1abc...
|
|
207
|
+
identity-switch("master") → back to master
|
|
208
|
+
social-post("Back to main") → signed by master npub
|
|
205
209
|
```
|
|
206
210
|
|
|
207
211
|
Derived identities are cryptographically unlinkable unless you publish a linkage proof.
|
package/dist/identity/tools.js
CHANGED
|
@@ -6,7 +6,15 @@ import { handleBackupShamir, handleRestoreShamir } from './shamir.js';
|
|
|
6
6
|
import { hexId } from '../validation.js';
|
|
7
7
|
import { handleIdentityBackup, handleIdentityRestore, handleIdentityMigrate } from './migration.js';
|
|
8
8
|
export function registerIdentityTools(server, deps) {
|
|
9
|
-
server.registerTool('
|
|
9
|
+
server.registerTool('whoami', {
|
|
10
|
+
description: 'Returns the active identity\'s npub. The simplest way to check which identity is currently in use.',
|
|
11
|
+
annotations: { readOnlyHint: true },
|
|
12
|
+
}, async () => {
|
|
13
|
+
return {
|
|
14
|
+
content: [{ type: 'text', text: deps.ctx.activeNpub }],
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
server.registerTool('identity-create', {
|
|
10
18
|
description: 'Generate a fresh Nostr identity with a BIP-39 mnemonic seed. Returns { npub, mnemonic }. Store the mnemonic securely — it will not be shown again. Use this when the user needs a brand new identity unrelated to the current one.',
|
|
11
19
|
annotations: { readOnlyHint: false },
|
|
12
20
|
}, async () => {
|
|
@@ -15,7 +23,7 @@ export function registerIdentityTools(server, deps) {
|
|
|
15
23
|
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
16
24
|
};
|
|
17
25
|
});
|
|
18
|
-
server.registerTool('
|
|
26
|
+
server.registerTool('identity-derive', {
|
|
19
27
|
description: 'Derive a child Nostr identity from the master key by purpose and index. Deterministic — same inputs always produce the same npub. Returns { npub, purpose, index }. Use identity_switch after deriving to operate as the new identity.',
|
|
20
28
|
inputSchema: {
|
|
21
29
|
purpose: z.string().describe('Purpose string for derivation (e.g. "messaging", "signing")'),
|
|
@@ -28,7 +36,7 @@ export function registerIdentityTools(server, deps) {
|
|
|
28
36
|
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
29
37
|
};
|
|
30
38
|
});
|
|
31
|
-
server.registerTool('
|
|
39
|
+
server.registerTool('identity-derive-persona', {
|
|
32
40
|
description: 'Derive a named persona (e.g. "work", "personal", "anonymous"). Like identity_derive but uses a human-readable name. Returns { npub, personaName, index }. Follow with identity_switch to activate.',
|
|
33
41
|
inputSchema: {
|
|
34
42
|
name: z.string().describe('Persona name (e.g. "work", "personal", "anonymous")'),
|
|
@@ -41,7 +49,7 @@ export function registerIdentityTools(server, deps) {
|
|
|
41
49
|
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
42
50
|
};
|
|
43
51
|
});
|
|
44
|
-
server.registerTool('
|
|
52
|
+
server.registerTool('identity-switch', {
|
|
45
53
|
description: 'Switch the active Nostr identity. ALL subsequent tool calls will sign events and query relays as the new identity. Pass "master" to return to root. Returns { npub } of the now-active identity. This is the key tool for multi-persona workflows.',
|
|
46
54
|
inputSchema: {
|
|
47
55
|
target: z.string().describe('Purpose, persona name, or "master" to switch to'),
|
|
@@ -54,17 +62,17 @@ export function registerIdentityTools(server, deps) {
|
|
|
54
62
|
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
55
63
|
};
|
|
56
64
|
});
|
|
57
|
-
server.registerTool('
|
|
65
|
+
server.registerTool('identity-list', {
|
|
58
66
|
description: 'List all known identities (master + all derived). Returns array of { npub, purpose, index, personaName }. Never includes private keys. Use this to see what identities are available before switching.',
|
|
59
67
|
inputSchema: {
|
|
60
|
-
output: z.enum(['json', 'human']).default('
|
|
68
|
+
output: z.enum(['json', 'human']).default('human').describe('Response format'),
|
|
61
69
|
},
|
|
62
70
|
annotations: { readOnlyHint: true },
|
|
63
71
|
}, async ({ output }) => {
|
|
64
72
|
const result = handleIdentityList(deps.ctx);
|
|
65
73
|
return toolResponse(result, output, fmt.formatIdentityList);
|
|
66
74
|
});
|
|
67
|
-
server.registerTool('
|
|
75
|
+
server.registerTool('identity-prove', {
|
|
68
76
|
description: 'Create a cryptographic linkage proof between the master key and the active identity. "blind" (default) proves they share a master without revealing how the child was derived. "full" also reveals the purpose and index. Returns a LinkageProof object that can be verified by anyone with nsec-tree. Use trust_proof_publish to make it permanent on relays.',
|
|
69
77
|
inputSchema: {
|
|
70
78
|
mode: z.enum(['blind', 'full']).default('blind').describe('Proof mode: "blind" hides derivation path, "full" reveals purpose and index'),
|
|
@@ -76,7 +84,7 @@ export function registerIdentityTools(server, deps) {
|
|
|
76
84
|
content: [{ type: 'text', text: JSON.stringify(proof, null, 2) }],
|
|
77
85
|
};
|
|
78
86
|
});
|
|
79
|
-
server.registerTool('
|
|
87
|
+
server.registerTool('identity-backup-shamir', {
|
|
80
88
|
description: 'Split the active identity\'s private key into Shamir shard files using threshold secret sharing. Any "threshold" shards can reconstruct the key. Files written with 0600 permissions via atomic rename. Returns file paths only — shard content never appears in the response.',
|
|
81
89
|
inputSchema: {
|
|
82
90
|
threshold: z.number().int().min(2).describe('Minimum shards needed to reconstruct'),
|
|
@@ -98,7 +106,7 @@ export function registerIdentityTools(server, deps) {
|
|
|
98
106
|
}, null, 2) }],
|
|
99
107
|
};
|
|
100
108
|
});
|
|
101
|
-
server.registerTool('
|
|
109
|
+
server.registerTool('identity-restore-shamir', {
|
|
102
110
|
description: 'Reconstruct a secret from Shamir shard files. Returns the restored npub for verification.',
|
|
103
111
|
inputSchema: {
|
|
104
112
|
files: z.array(z.string()).describe('Paths to shard files'),
|
|
@@ -121,7 +129,7 @@ export function registerIdentityTools(server, deps) {
|
|
|
121
129
|
}, null, 2) }],
|
|
122
130
|
};
|
|
123
131
|
});
|
|
124
|
-
server.registerTool('
|
|
132
|
+
server.registerTool('identity-backup', {
|
|
125
133
|
description: 'Fetch profile, contacts, relay list, and attestations for a pubkey. Returns a portable JSON bundle (no private keys).',
|
|
126
134
|
inputSchema: {
|
|
127
135
|
pubkeyHex: hexId.describe('Hex pubkey to back up'),
|
|
@@ -139,7 +147,7 @@ export function registerIdentityTools(server, deps) {
|
|
|
139
147
|
}, null, 2) }],
|
|
140
148
|
};
|
|
141
149
|
});
|
|
142
|
-
server.registerTool('
|
|
150
|
+
server.registerTool('identity-restore', {
|
|
143
151
|
description: 'Re-sign migratable events (profile, contacts, relay list) under the active identity. Skips attestations (trust chain protection).',
|
|
144
152
|
inputSchema: {
|
|
145
153
|
pubkeyHex: hexId.describe('Hex pubkey of the original identity to restore from'),
|
|
@@ -154,7 +162,7 @@ export function registerIdentityTools(server, deps) {
|
|
|
154
162
|
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
155
163
|
};
|
|
156
164
|
});
|
|
157
|
-
server.registerTool('
|
|
165
|
+
server.registerTool('identity-migrate', {
|
|
158
166
|
description: 'Migrate from an old identity to the active one. Shows preview first — set confirm: true to execute. Publishes linkage proof and re-signs migratable events.',
|
|
159
167
|
inputSchema: {
|
|
160
168
|
oldPubkeyHex: z.string().describe('Hex pubkey of the old identity'),
|
package/dist/index.js
CHANGED
|
@@ -32,9 +32,10 @@ export const deps = { ctx: ctx, pool, nip65, nwcUri: config.nwcUri };
|
|
|
32
32
|
config.secretKey = '';
|
|
33
33
|
config.nwcUri = undefined;
|
|
34
34
|
config.bunkerUri = undefined;
|
|
35
|
-
// Load master identity relay list
|
|
36
|
-
|
|
37
|
-
pool.reconfigure(ctx.activeNpub, masterRelays);
|
|
35
|
+
// Load master identity relay list in the background — don't block tool registration
|
|
36
|
+
nip65.loadForIdentity(ctx.activeNpub).then(masterRelays => {
|
|
37
|
+
pool.reconfigure(ctx.activeNpub, masterRelays);
|
|
38
|
+
}).catch(e => console.error('NIP-65 relay load failed:', e.message));
|
|
38
39
|
const server = new McpServer({ name: 'nostr-bray', version: '0.1.0' });
|
|
39
40
|
// Phase 2: Identity tools
|
|
40
41
|
registerIdentityTools(server, deps);
|
package/dist/relay/tools.js
CHANGED
|
@@ -4,18 +4,18 @@ import { toolResponse } from '../tool-response.js';
|
|
|
4
4
|
import * as fmt from '../format.js';
|
|
5
5
|
import { handleRelayList, handleRelaySet, handleRelayAdd, handleRelayInfo, handleRelayQuery } from './handlers.js';
|
|
6
6
|
export function registerRelayTools(server, deps) {
|
|
7
|
-
server.registerTool('
|
|
7
|
+
server.registerTool('relay-list', {
|
|
8
8
|
description: 'List the relay set (read/write) for the active identity. Optionally check for shared relays with another identity.',
|
|
9
9
|
inputSchema: {
|
|
10
10
|
compareWithNpub: z.string().optional().describe('Compare shared relays with this npub'),
|
|
11
|
-
output: z.enum(['json', 'human']).default('
|
|
11
|
+
output: z.enum(['json', 'human']).default('human').describe('Response format'),
|
|
12
12
|
},
|
|
13
13
|
annotations: { readOnlyHint: true },
|
|
14
14
|
}, async ({ compareWithNpub, output }) => {
|
|
15
15
|
const result = handleRelayList(deps.ctx, deps.pool, compareWithNpub);
|
|
16
16
|
return toolResponse(result, output, fmt.formatRelays);
|
|
17
17
|
});
|
|
18
|
-
server.registerTool('
|
|
18
|
+
server.registerTool('relay-set', {
|
|
19
19
|
description: 'Publish a kind 10002 relay list for the active identity. Warns if a relay list already exists.',
|
|
20
20
|
inputSchema: {
|
|
21
21
|
relays: z.array(z.object({
|
|
@@ -24,7 +24,7 @@ export function registerRelayTools(server, deps) {
|
|
|
24
24
|
})).describe('Relay entries'),
|
|
25
25
|
confirm: z.boolean().default(false).describe('Set true to overwrite existing relay list'),
|
|
26
26
|
},
|
|
27
|
-
annotations: { readOnlyHint: false },
|
|
27
|
+
annotations: { readOnlyHint: false, destructiveHint: true },
|
|
28
28
|
}, async ({ relays, confirm }) => {
|
|
29
29
|
const result = await handleRelaySet(deps.ctx, deps.pool, { relays, confirm });
|
|
30
30
|
return {
|
|
@@ -33,7 +33,7 @@ export function registerRelayTools(server, deps) {
|
|
|
33
33
|
: { published: true, id: result.event.id }, null, 2) }],
|
|
34
34
|
};
|
|
35
35
|
});
|
|
36
|
-
server.registerTool('
|
|
36
|
+
server.registerTool('relay-add', {
|
|
37
37
|
description: 'Add a single relay to the active identity\'s relay set (in-memory only — does not publish kind 10002).',
|
|
38
38
|
inputSchema: {
|
|
39
39
|
url: relayUrl.describe('Relay WebSocket URL'),
|
|
@@ -46,7 +46,7 @@ export function registerRelayTools(server, deps) {
|
|
|
46
46
|
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
47
47
|
};
|
|
48
48
|
});
|
|
49
|
-
server.registerTool('
|
|
49
|
+
server.registerTool('relay-query', {
|
|
50
50
|
description: 'Query events from Nostr relays by kind, author, tags, or time range. Useful for discovering events, scanning for specific kinds, or investigating unknown event schemas. Uses explicit relays if provided, otherwise the active identity\'s read relays.',
|
|
51
51
|
inputSchema: {
|
|
52
52
|
kinds: z.array(z.number().int()).optional().describe('Event kinds to filter by (e.g. [30301, 31000])'),
|
|
@@ -74,7 +74,7 @@ export function registerRelayTools(server, deps) {
|
|
|
74
74
|
content: [{ type: 'text', text: JSON.stringify({ count: events.length, events: summary }, null, 2) }],
|
|
75
75
|
};
|
|
76
76
|
});
|
|
77
|
-
server.registerTool('
|
|
77
|
+
server.registerTool('relay-info', {
|
|
78
78
|
description: 'Fetch the NIP-11 relay information document for a relay URL.',
|
|
79
79
|
inputSchema: {
|
|
80
80
|
url: relayUrl.describe('Relay WebSocket URL (wss://...)'),
|
package/dist/safety/tools.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { handleDuressConfigure, handleDuressActivate } from './handlers.js';
|
|
3
3
|
export function registerSafetyTools(server, deps) {
|
|
4
|
-
server.registerTool('
|
|
4
|
+
server.registerTool('safety-configure', {
|
|
5
5
|
description: 'Configure an alternative identity persona and pre-warm relay connections.',
|
|
6
6
|
inputSchema: {
|
|
7
7
|
personaName: z.string().default('anonymous').describe('Persona name for the alternative identity'),
|
|
@@ -14,12 +14,12 @@ export function registerSafetyTools(server, deps) {
|
|
|
14
14
|
};
|
|
15
15
|
});
|
|
16
16
|
// Description intentionally does NOT mention duress — appears as normal identity switch
|
|
17
|
-
server.registerTool('
|
|
17
|
+
server.registerTool('safety-activate', {
|
|
18
18
|
description: 'Switch to an alternative identity configuration.',
|
|
19
19
|
inputSchema: {
|
|
20
20
|
personaName: z.string().default('anonymous').describe('Persona name to switch to'),
|
|
21
21
|
},
|
|
22
|
-
annotations: { readOnlyHint: false },
|
|
22
|
+
annotations: { readOnlyHint: false, destructiveHint: true },
|
|
23
23
|
}, async ({ personaName }) => {
|
|
24
24
|
const result = handleDuressActivate(deps.ctx, { personaName });
|
|
25
25
|
return {
|