nostr-bray 1.27.0 → 1.27.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/catalog.js +9 -3
- package/dist/relay/handlers.d.ts +1 -0
- package/dist/relay/handlers.js +2 -0
- package/dist/relay/tools.js +34 -6
- package/package.json +1 -1
package/dist/catalog.js
CHANGED
|
@@ -108,11 +108,17 @@ export class ActionCatalog {
|
|
|
108
108
|
description: 'Execute an action found via search-actions. Pass the exact action name and its parameters.',
|
|
109
109
|
inputSchema: {
|
|
110
110
|
action: z.string().describe('Action name from search-actions results'),
|
|
111
|
-
params: z.record(z.string(), z.unknown()).
|
|
111
|
+
params: z.record(z.string(), z.unknown()).optional().describe('Parameters for the action (see search-actions results for expected params). Alias: parameters.'),
|
|
112
|
+
// Alias for clients that naturally reach for "parameters" rather than "params".
|
|
113
|
+
// Without this, MCP SDK strips unknown keys from the validated args and the
|
|
114
|
+
// inner action handler receives an empty object, causing spurious
|
|
115
|
+
// "expected string, received undefined" validation failures.
|
|
116
|
+
parameters: z.record(z.string(), z.unknown()).optional().describe('Alias for params. Either field is accepted.'),
|
|
112
117
|
},
|
|
113
118
|
annotations: { openWorldHint: true },
|
|
114
|
-
}, async ({ action, params }) => {
|
|
115
|
-
|
|
119
|
+
}, async ({ action, params, parameters }) => {
|
|
120
|
+
const resolved = (params ?? parameters ?? {});
|
|
121
|
+
return catalog.execute(action, resolved);
|
|
116
122
|
});
|
|
117
123
|
}
|
|
118
124
|
}
|
package/dist/relay/handlers.d.ts
CHANGED
package/dist/relay/handlers.js
CHANGED
|
@@ -81,6 +81,8 @@ export function handleRelayAdd(ctx, pool, args) {
|
|
|
81
81
|
/** Query events from relays by arbitrary filter. Uses explicit relays if provided, otherwise the active identity's read relays. */
|
|
82
82
|
export async function handleRelayQuery(pool, npub, args) {
|
|
83
83
|
const filter = {};
|
|
84
|
+
if (args.ids?.length)
|
|
85
|
+
filter.ids = args.ids;
|
|
84
86
|
if (args.kinds?.length)
|
|
85
87
|
filter.kinds = args.kinds;
|
|
86
88
|
if (args.authors?.length)
|
package/dist/relay/tools.js
CHANGED
|
@@ -50,21 +50,49 @@ export function registerRelayTools(server, deps) {
|
|
|
50
50
|
};
|
|
51
51
|
});
|
|
52
52
|
server.registerTool('relay-query', {
|
|
53
|
-
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.',
|
|
53
|
+
description: 'Query events from Nostr relays by kind, author, ids, 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. Filter fields may be supplied either as top-level arguments or wrapped in a single "filter" object (both shapes are accepted).',
|
|
54
54
|
inputSchema: {
|
|
55
|
+
ids: z.array(z.string()).optional().describe('Event IDs (hex) to fetch directly'),
|
|
55
56
|
kinds: z.array(z.number().int()).optional().describe('Event kinds to filter by (e.g. [30301, 31000])'),
|
|
56
57
|
authors: z.array(z.string()).optional().describe('Hex pubkeys of event authors'),
|
|
57
58
|
tags: z.record(z.string(), z.array(z.string())).optional().describe('Tag filters as key-value pairs (e.g. {"#p": ["hex..."], "#d": ["prefix"]})'),
|
|
58
|
-
since: z.number().int().optional().describe('Unix timestamp
|
|
59
|
-
until: z.number().int().optional().describe('Unix timestamp
|
|
60
|
-
limit: z.number().int().min(1).max(500).
|
|
59
|
+
since: z.number().int().optional().describe('Unix timestamp, only events created after this time'),
|
|
60
|
+
until: z.number().int().optional().describe('Unix timestamp, only events created before this time'),
|
|
61
|
+
limit: z.number().int().min(1).max(500).optional().describe('Maximum number of events to return (default 50, max 500)'),
|
|
61
62
|
relays: z.array(relayUrl).optional().describe('Explicit relay URLs to query (overrides identity relay set)'),
|
|
62
63
|
search: z.string().optional().describe('Full-text search query (NIP-50). Only works on relays that support NIP-50; others will ignore it.'),
|
|
64
|
+
// Alias: some MCP clients naturally wrap the whole filter in a single "filter" object.
|
|
65
|
+
// Without this alias the MCP SDK silently strips the unknown key, leaving the handler
|
|
66
|
+
// with an empty argument set and returning a broad firehose of events.
|
|
67
|
+
filter: z.object({
|
|
68
|
+
ids: z.array(z.string()).optional(),
|
|
69
|
+
kinds: z.array(z.number().int()).optional(),
|
|
70
|
+
authors: z.array(z.string()).optional(),
|
|
71
|
+
tags: z.record(z.string(), z.array(z.string())).optional(),
|
|
72
|
+
since: z.number().int().optional(),
|
|
73
|
+
until: z.number().int().optional(),
|
|
74
|
+
limit: z.number().int().min(1).max(500).optional(),
|
|
75
|
+
search: z.string().optional(),
|
|
76
|
+
}).optional().describe('Alias: all filter fields wrapped in a single object. Merged with any top-level fields; top-level values win on conflict.'),
|
|
63
77
|
},
|
|
64
78
|
annotations: { readOnlyHint: true },
|
|
65
|
-
}, async (
|
|
79
|
+
}, async (args) => {
|
|
80
|
+
// Merge nested "filter" alias with top-level fields. Top-level values win on conflict so
|
|
81
|
+
// the canonical form stays authoritative, but a caller that only supplies "filter" still
|
|
82
|
+
// gets everything through. Without this merge the MCP SDK strips the unknown top-level
|
|
83
|
+
// "filter" key and the handler receives an empty object, yielding a firehose response.
|
|
84
|
+
const f = args.filter ?? {};
|
|
85
|
+
const mergedLimit = args.limit ?? f.limit ?? 50;
|
|
66
86
|
const events = await handleRelayQuery(deps.pool, deps.ctx.activeNpub, {
|
|
67
|
-
|
|
87
|
+
ids: args.ids ?? f.ids,
|
|
88
|
+
kinds: args.kinds ?? f.kinds,
|
|
89
|
+
authors: args.authors ?? f.authors,
|
|
90
|
+
tags: args.tags ?? f.tags,
|
|
91
|
+
since: args.since ?? f.since,
|
|
92
|
+
until: args.until ?? f.until,
|
|
93
|
+
limit: mergedLimit,
|
|
94
|
+
relays: args.relays,
|
|
95
|
+
search: args.search ?? f.search,
|
|
68
96
|
});
|
|
69
97
|
const summary = events.map(e => ({
|
|
70
98
|
id: e.id,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nostr-bray",
|
|
3
|
-
"version": "1.27.
|
|
3
|
+
"version": "1.27.1",
|
|
4
4
|
"description": "Trust-aware Nostr for AI and humans. Three dimensions of trust -- verification, proximity, and access -- woven into every interaction.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|