@naumu/mcp 0.6.4 → 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/dist/index.js +160 -479
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -118,7 +118,7 @@ var NaumuClient = class {
|
|
|
118
118
|
// ../mcp-core/src/instructions.ts
|
|
119
119
|
var NAUMU_INSTRUCTIONS = `The Naumu MCP server gives structured access to Naumu knowledge graphs (also called spaces). Prefer these tools over WebFetch whenever the user mentions a naumu.ai URL \u2014 Naumu pages are client-rendered React, so WebFetch returns an empty shell with no data.
|
|
120
120
|
|
|
121
|
-
Getting information about a space:
|
|
121
|
+
Getting information about a space: use naumu_ask. It puts your question to the @Naumu agent (which has full read access and inspects the graph for you) and returns a synthesised, node-grounded answer with the exact source node ids and a confidence hint, in a single call. It is the authoritative answer for what is in a space, what is new or recently changed, how something works, or any summary - present it and its sources directly. Do NOT then re-read the graph yourself with naumu_get_schema, naumu_filter, naumu_get_node or fetch to verify or sanity-check the answer: that repeats work naumu_ask already did and is dramatically slower (it can turn a 40-second answer into minutes). Trust the answer and its cited sources. Reach for a granular read only to fetch one specific node the answer pointed to, or for a need naumu_ask genuinely cannot serve (naumu_search to locate nodes by meaning, naumu_list_threads + naumu_read_thread for conversation history). Recording the question and answer as a visible conversation in the space is expected and useful, so do not avoid naumu_ask to prevent creating a thread. To hand @Naumu work to carry out in the background (add knowledge, make changes, record a status update), use naumu_delegate.
|
|
122
122
|
|
|
123
123
|
IMPORTANT: graphId is a UUID (e.g. "0464cbfa-60ca-41b3-ac8f-bbeb8243a193"). The value in the URL right after /spaces/ is a slug (e.g. "naumu-0464cbfa"), NOT the graphId. You must resolve the slug to a graphId first.
|
|
124
124
|
|
|
@@ -127,20 +127,9 @@ Call naumu_list_graphs and find the graph whose 'slug' field matches the URL seg
|
|
|
127
127
|
|
|
128
128
|
URL \u2192 tool mapping (the value after /spaces/ is the slug \u2014 resolve it first):
|
|
129
129
|
- naumu.ai/spaces/{slug} \u2192 naumu_list_graphs (resolve), then naumu_get_schema for an overview
|
|
130
|
-
- naumu.ai/spaces/{slug}/views/{viewId} \u2192 naumu_list_graphs (resolve), then naumu_get_view, then naumu_list_view_nodes
|
|
131
130
|
- naumu.ai/spaces/{slug}/nodes/{nodeId} \u2192 naumu_list_graphs (resolve), then naumu_get_node
|
|
132
131
|
- naumu.ai/spaces/{slug}/chat/{threadId} \u2192 naumu_list_graphs (resolve), then naumu_read_thread
|
|
133
|
-
- Other panel URLs (notes, canvases, conversations, members, settings, schema, heat, health, changelog) have no dedicated tool \u2014 fall back to naumu_get_node with the relevant id, or naumu_get_schema for the space-level question.
|
|
134
|
-
|
|
135
|
-
Recommended workflow when a user pastes a view URL:
|
|
136
|
-
1. naumu_list_graphs \u2014 find the graph whose slug matches the URL. Note its 'id' (the UUID) as graphId.
|
|
137
|
-
2. naumu_get_view {graphId, viewId} \u2014 read the returned 'summary' and 'filters' to understand what the view returns. This is cheap.
|
|
138
|
-
3. naumu_list_view_nodes {graphId, viewId} \u2014 page through results.
|
|
139
|
-
- fields:"summary" (default) for {id, label, type} per node \u2014 best for browsing.
|
|
140
|
-
- fields:"id" for {id} only \u2014 best when you just need to count or iterate.
|
|
141
|
-
- fields:"full" for the complete node payload \u2014 only when you need every attribute.
|
|
142
|
-
- The response always includes totalCount, so you don't need to page through everything to get a count.
|
|
143
|
-
4. naumu_get_node {graphId, nodeId} for per-node detail when needed.
|
|
132
|
+
- Other panel URLs (notes, canvases, views, conversations, members, settings, schema, heat, health, changelog) have no dedicated tool \u2014 fall back to naumu_get_node with the relevant id, or naumu_get_schema for the space-level question.
|
|
144
133
|
|
|
145
134
|
Localhost URLs (http://localhost:3000/spaces/{slug}/...) follow the same shape \u2014 resolve the slug the same way. The MCP backend host is configured separately; the URL the user pastes is just for parsing structure.`;
|
|
146
135
|
|
|
@@ -151,7 +140,7 @@ function registerListGraphs(server2, client2) {
|
|
|
151
140
|
"naumu_list_graphs",
|
|
152
141
|
{
|
|
153
142
|
title: "List Graphs",
|
|
154
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
143
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
155
144
|
description: "List all knowledge graphs (spaces) the authenticated user has access to. Returns graph IDs, names, and roles.",
|
|
156
145
|
inputSchema: z.object({})
|
|
157
146
|
},
|
|
@@ -219,8 +208,7 @@ function formatSchema(schema) {
|
|
|
219
208
|
if (v.description) value.description = v.description;
|
|
220
209
|
return value;
|
|
221
210
|
});
|
|
222
|
-
const attr = { name: a.name, values };
|
|
223
|
-
if (a.type) attr.type = a.type;
|
|
211
|
+
const attr = { name: a.name, type: a.type ?? "select", values };
|
|
224
212
|
if (a.description) attr.description = a.description;
|
|
225
213
|
return attr;
|
|
226
214
|
});
|
|
@@ -234,7 +222,7 @@ function registerGetSchema(server2, client2) {
|
|
|
234
222
|
"naumu_get_schema",
|
|
235
223
|
{
|
|
236
224
|
title: "Get Graph Schema",
|
|
237
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
225
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
238
226
|
description: "Get the schema definition for a knowledge graph; call this before classifying a new node into a type, before picking an attribute value, or before extending the schema. Returns a ROUND-TRIPPABLE structural schema: each `types[]` entry has the SAME shape `naumu_update_schema` ingests (type, description, structured `connections: { parent?, required, suggested }` with parent NESTED - not a string, and structured attributes), so you can copy a type straight back into naumu_update_schema without losing data (notably the parent relation). Descriptions are short, contrastive notes from the schema author explaining what each type/attribute/value is for and how it differs from similar-sounding ones.",
|
|
239
227
|
inputSchema: z3.object({
|
|
240
228
|
graphId: z3.string().describe("The graph ID")
|
|
@@ -268,16 +256,16 @@ var ConnectionSchema = z4.object({
|
|
|
268
256
|
var AttributeValueSchema = z4.object({
|
|
269
257
|
label: z4.string().describe("Display label for this enum value"),
|
|
270
258
|
color: z4.string().optional().describe('Optional hex color (e.g. "#ff5722")'),
|
|
271
|
-
description: z4.string().optional().describe('Short note distinguishing this value from sibling values (e.g. "closed-won -
|
|
259
|
+
description: z4.string().optional().describe('Short note distinguishing this value from sibling values (e.g. "closed-won - signed and revenue committed"). Encouraged when the label alone is ambiguous.')
|
|
272
260
|
});
|
|
273
261
|
var AttributeSchema = z4.object({
|
|
274
262
|
name: z4.string().describe('Attribute key (e.g. "stage", "status", "category")'),
|
|
275
|
-
type: z4.enum(["select", "multiselect", "string", "number", "date"]).
|
|
263
|
+
type: z4.enum(["select", "multiselect", "string", "number", "date"]).describe('Attribute type (required). select/multiselect define a closed set of categories with values; string/number/date hold free-form per-node data with values []. Calendar dates use "date", not select values.'),
|
|
276
264
|
values: z4.array(AttributeValueSchema).describe("Allowed enum values for select/multiselect; pass [] for string/number/date."),
|
|
277
265
|
description: z4.string().optional().describe("Short note explaining what this attribute captures and how it differs from similarly-named attributes elsewhere in the schema. Strongly encouraged.")
|
|
278
266
|
});
|
|
279
267
|
var NodeTypeSchema = z4.object({
|
|
280
|
-
type: z4.string().describe("Type name in PascalCase (e.g.
|
|
268
|
+
type: z4.string().describe("Type name in PascalCase (e.g. TypeA, TypeB)"),
|
|
281
269
|
connections: z4.object({
|
|
282
270
|
parent: ConnectionSchema.optional().describe("Optional parent relation (this type nests under another via this connection)."),
|
|
283
271
|
required: z4.array(ConnectionSchema).default([]).describe("Required outgoing connections to other types."),
|
|
@@ -288,7 +276,7 @@ var NodeTypeSchema = z4.object({
|
|
|
288
276
|
'Default visibility for NEW nodes of this type when no explicit visibility is passed on creation. Does NOT retroactively change visibility on existing nodes. "open" = visible to anyone with the space link (including non-members), "internal" = visible to all space members, "restricted" = only members explicitly granted access. Omit to leave the type unset - it then falls back to the space-level defaultVisibility.'
|
|
289
277
|
),
|
|
290
278
|
color: z4.string().optional().describe("Optional hex color for instances of this type."),
|
|
291
|
-
description: z4.string().optional().describe('Short one-sentence description of what this type represents AND how it differs from semantically similar types (e.g. "
|
|
279
|
+
description: z4.string().optional().describe('Short one-sentence description of what this type represents AND how it differs from semantically similar types (e.g. "Type A - distinct from Type B, which is broader"). Strongly encouraged on every type. Future agents rely on this when classifying a new node into one of several similar-sounding types.')
|
|
292
280
|
});
|
|
293
281
|
var SchemaDefinitionSchema = z4.object({
|
|
294
282
|
description: z4.string().optional().describe("Schema-level description / domain summary."),
|
|
@@ -300,7 +288,7 @@ function registerUpdateSchema(server2, client2) {
|
|
|
300
288
|
{
|
|
301
289
|
title: "Update Graph Schema",
|
|
302
290
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
|
|
303
|
-
description: "Replace the graph schema with a new full definition; use to bootstrap an empty graph (cold-start) or fully replace mid-build. STRUCTURAL RULES (load-bearing): (1) HIERARCHICAL with a single root - exactly ONE type has no parent; every other type MUST declare a parent. (2) Each parent / required / suggested connection is XOR: ONE concrete target_node OR polymorphic=true - never both, never a list of multiple targets. (3) DEFAULT TO CONCRETE target_node. Polymorphic is the ESCAPE HATCH - reserve for genuinely cross-cutting concepts like Comment or Tag (entities that validly attach to many distinct types). If you find yourself making most parents polymorphic, you are avoiding the design work - pick concrete relationships instead. If you can't pick a concrete parent, you may be missing a type - add the missing type first. (4) Same-type nesting is implicit: a node can be placed under another of its same type using the existing parent relation - never add a self-relation just to enable nesting. (5) Always provide `description` on every node type, attribute, and select value - one short, contrastive sentence (what it IS and what it is NOT vs sibling types/attrs/values). This is the single strongest disambiguation signal for future agents classifying nodes. When replacing mid-build, call naumu_get_schema first (it returns a round-trippable structural schema you can copy back) and send the FULL new schema; anything you omit is removed. PARENT PRESERVATION: omitting a type's `connections.parent` PRESERVES its existing parent (so a round-trip never silently orphans a type). To intentionally remove a parent and make a type a root, send `parent: null` explicitly. (A parent whose target type you delete is dropped automatically.) Conventions: type names PascalCase
|
|
291
|
+
description: "Replace the graph schema with a new full definition; use to bootstrap an empty graph (cold-start) or fully replace mid-build. STRUCTURAL RULES (load-bearing): (1) HIERARCHICAL with a single root - exactly ONE type has no parent; every other type MUST declare a parent. (2) Each parent / required / suggested connection is XOR: ONE concrete target_node OR polymorphic=true - never both, never a list of multiple targets. (3) DEFAULT TO CONCRETE target_node. Polymorphic is the ESCAPE HATCH - reserve for genuinely cross-cutting concepts like Comment or Tag (entities that validly attach to many distinct types). If you find yourself making most parents polymorphic, you are avoiding the design work - pick concrete relationships instead. If you can't pick a concrete parent, you may be missing a type - add the missing type first. (4) Same-type nesting is implicit: a node can be placed under another of its same type using the existing parent relation - never add a self-relation just to enable nesting. (5) Always provide `description` on every node type, attribute, and select value - one short, contrastive sentence (what it IS and what it is NOT vs sibling types/attrs/values). This is the single strongest disambiguation signal for future agents classifying nodes. When replacing mid-build, call naumu_get_schema first (it returns a round-trippable structural schema you can copy back) and send the FULL new schema; anything you omit is removed. PARENT PRESERVATION: omitting a type's `connections.parent` PRESERVES its existing parent (so a round-trip never silently orphans a type). To intentionally remove a parent and make a type a root, send `parent: null` explicitly. (A parent whose target type you delete is dropped automatically.) Conventions: type names PascalCase, relation names UPPER_SNAKE_CASE. Bias toward general types - refine via attributes or nested children, not type proliferation.",
|
|
304
292
|
inputSchema: z4.object({
|
|
305
293
|
graphId: z4.string().describe("The graph ID"),
|
|
306
294
|
schema: SchemaDefinitionSchema
|
|
@@ -327,13 +315,13 @@ var ConnectionSchema2 = z5.object({
|
|
|
327
315
|
var AttributeValueSchema2 = z5.object({
|
|
328
316
|
label: z5.string(),
|
|
329
317
|
color: z5.string().optional(),
|
|
330
|
-
description: z5.string().optional().describe('Short note distinguishing this value from sibling values (e.g. for status="closed-won", "
|
|
318
|
+
description: z5.string().optional().describe('Short note distinguishing this value from sibling values (e.g. for status="closed-won", "signed and revenue committed"). Encouraged when the label alone is ambiguous.')
|
|
331
319
|
});
|
|
332
320
|
var AttributeSchema2 = z5.object({
|
|
333
321
|
name: z5.string(),
|
|
334
|
-
type: z5.enum(["select", "multiselect", "string", "number", "date"]).
|
|
322
|
+
type: z5.enum(["select", "multiselect", "string", "number", "date"]).describe('Attribute type (required). select/multiselect define a closed set of categories with values; string/number/date hold free-form per-node data with values []. Calendar dates use "date", not select values.'),
|
|
335
323
|
values: z5.array(AttributeValueSchema2).default([]),
|
|
336
|
-
description: z5.string().optional().describe('Short note explaining what this attribute captures and how it differs from similarly-named attributes on other types (e.g. "stage on
|
|
324
|
+
description: z5.string().optional().describe('Short note explaining what this attribute captures and how it differs from similarly-named attributes on other types (e.g. "stage on Type A" vs "stage on Type B"). Strongly encouraged.')
|
|
337
325
|
});
|
|
338
326
|
function registerAddNodeType(server2, client2) {
|
|
339
327
|
server2.registerTool(
|
|
@@ -341,7 +329,7 @@ function registerAddNodeType(server2, client2) {
|
|
|
341
329
|
{
|
|
342
330
|
title: "Add Node Type to Schema",
|
|
343
331
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
|
|
344
|
-
description: 'Add one new node type to the schema; use to extend an existing schema without resending the whole thing (cheaper than naumu_update_schema). STRUCTURAL RULES: (1) Schemas are hierarchical with a single root. If schema is empty, the first type IS the root - omit `parent`. Every subsequent type MUST set `parent`. (2) DEFAULT TO CONCRETE - pass {relation, target_node: <existing type>}. Polymorphic is the ESCAPE HATCH - use {relation, polymorphic: true} ONLY for genuinely cross-cutting concepts like Comment or Tag (types that validly attach to many distinct parents). If you can\'t pick a concrete parent, you may be missing a type - add the missing type first instead of falling back to polymorphic. (3) Required/suggested connections also each take ONE concrete target_node OR polymorphic - never a list. Default concrete there too. (4) Type name PascalCase
|
|
332
|
+
description: 'Add one new node type to the schema; use to extend an existing schema without resending the whole thing (cheaper than naumu_update_schema). STRUCTURAL RULES: (1) Schemas are hierarchical with a single root. If schema is empty, the first type IS the root - omit `parent`. Every subsequent type MUST set `parent`. (2) DEFAULT TO CONCRETE - pass {relation, target_node: <existing type>}. Polymorphic is the ESCAPE HATCH - use {relation, polymorphic: true} ONLY for genuinely cross-cutting concepts like Comment or Tag (types that validly attach to many distinct parents). If you can\'t pick a concrete parent, you may be missing a type - add the missing type first instead of falling back to polymorphic. (3) Required/suggested connections also each take ONE concrete target_node OR polymorphic - never a list. Default concrete there too. (4) Type name PascalCase. Relation names UPPER_SNAKE_CASE. (5) ALWAYS provide `description` - one short sentence that says what this type is AND what it is NOT relative to semantically close types (e.g. "Type A \u2014 distinct from Type B, which is broader"). This is the single strongest signal future agents have when classifying a node into one of several similar-sounding types. Returns an error if the type already exists - use naumu_add_attribute / naumu_add_connection to extend it.',
|
|
345
333
|
inputSchema: z5.object({
|
|
346
334
|
graphId: z5.string(),
|
|
347
335
|
type: z5.string().describe("PascalCase type name"),
|
|
@@ -395,7 +383,7 @@ function registerAddConnection(server2, client2) {
|
|
|
395
383
|
{
|
|
396
384
|
title: "Add Connection to Node Type",
|
|
397
385
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
|
|
398
|
-
description: 'Add one connection from an existing node type to another; use to extend a type\'s relations without resending the whole schema. `kind`: "parent" (sets/replaces - every non-root type needs exactly one parent; only ONE type in the whole schema has no parent), "required" (must exist on instances), "suggested" (optional). Each connection is XOR: ONE concrete target_node OR polymorphic=true - never both. DEFAULT TO CONCRETE target_node. Polymorphic is the ESCAPE HATCH - reserve for genuinely cross-cutting relations (e.g. a Tag-style relation that validly applies to many distinct types). If you can\'t pick a concrete target, you may be missing a type - add it first instead of falling back to polymorphic. Same-type nesting (e.g.
|
|
386
|
+
description: 'Add one connection from an existing node type to another; use to extend a type\'s relations without resending the whole schema. `kind`: "parent" (sets/replaces - every non-root type needs exactly one parent; only ONE type in the whole schema has no parent), "required" (must exist on instances), "suggested" (optional). Each connection is XOR: ONE concrete target_node OR polymorphic=true - never both. DEFAULT TO CONCRETE target_node. Polymorphic is the ESCAPE HATCH - reserve for genuinely cross-cutting relations (e.g. a Tag-style relation that validly applies to many distinct types). If you can\'t pick a concrete target, you may be missing a type - add it first instead of falling back to polymorphic. Same-type nesting (e.g. Type A under Type A) does NOT need a new connection - use the existing parent relation. Relation name UPPER_SNAKE_CASE.',
|
|
399
387
|
inputSchema: z6.object({
|
|
400
388
|
graphId: z6.string(),
|
|
401
389
|
source_type: z6.string().describe("Existing node type to add the connection to."),
|
|
@@ -445,12 +433,12 @@ function registerAddAttribute(server2, client2) {
|
|
|
445
433
|
{
|
|
446
434
|
title: "Add Attribute to Node Type",
|
|
447
435
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
|
|
448
|
-
description: 'Add or extend an attribute on an existing node type; use to add a field or merge new enum values into an existing one. If the attribute name doesn\'t exist, it is created. If it exists and is a select/multiselect, new values are merged in (existing values kept).
|
|
436
|
+
description: 'Add or extend an attribute on an existing node type; use to add a field or merge new enum values into an existing one. If the attribute name doesn\'t exist, it is created. If it exists and is a select/multiselect, new values are merged in (existing values kept). Date values on nodes are written via naumu_update_node as either an ISO date string "YYYY-MM-DD" (single day) or an object { start, end? } with ISO date strings (inclusive range). Strongly encouraged to provide `description` on the attribute and on each value - short, contrastive notes (e.g. attribute "stage - sales funnel position; distinct from status which captures health/blockers", value "closed-won - deal signed and revenue committed"). Descriptions are the single strongest signal future agents use when picking which attribute/value to set.',
|
|
449
437
|
inputSchema: z7.object({
|
|
450
438
|
graphId: z7.string(),
|
|
451
439
|
node_type: z7.string().describe("Existing node type to add the attribute to."),
|
|
452
440
|
name: z7.string().describe('Attribute key (e.g. "stage", "status").'),
|
|
453
|
-
type: z7.enum(["select", "multiselect", "string", "number", "date"]).
|
|
441
|
+
type: z7.enum(["select", "multiselect", "string", "number", "date"]).describe('Attribute type (required). select/multiselect define a closed set of categories - provide their values. string/number/date hold free-form per-node data - pass values: []. A specific calendar date is per-node data, so use type "date" and write the date on the node, rather than adding the date as a select value.'),
|
|
454
442
|
values: z7.array(
|
|
455
443
|
z7.object({
|
|
456
444
|
label: z7.string(),
|
|
@@ -498,7 +486,7 @@ function registerSearch(server2, client2) {
|
|
|
498
486
|
"naumu_search",
|
|
499
487
|
{
|
|
500
488
|
title: "Search Graph",
|
|
501
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
489
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
502
490
|
description: 'Hybrid search over graph nodes; use for meaning-based lookup when you don\'t know the exact label. Combines exact-token text matching (good for UUIDs, proper nouns, specific labels) with semantic similarity (good for paraphrase and meaning), then fuses both rankings with Reciprocal Rank Fusion. Returns the top matches with a `matchedVia` tag - `both` is the highest-confidence signal, then `semantic`, then `text`. Use `naumu_filter` for structured queries by type and attributes (e.g. "all in-progress Tasks"). Tip: include both synonyms ("authentication login SSO") and exact tokens you remember in the same query - the fusion handles both.',
|
|
503
491
|
inputSchema: z8.object({
|
|
504
492
|
graphId: z8.string().describe("The graph ID"),
|
|
@@ -506,7 +494,7 @@ function registerSearch(server2, client2) {
|
|
|
506
494
|
'Search query text. Mix synonyms and exact tokens freely (e.g. "auth login SSO 2fa Twitter handle").'
|
|
507
495
|
),
|
|
508
496
|
limit: z8.number().optional().default(20).describe("Max results to return (default 20, max 200). Adaptive cutoff may return fewer when the top match is weak."),
|
|
509
|
-
nodeTypes: z8.array(z8.string()).optional().describe('Filter to specific node types (e.g. ["
|
|
497
|
+
nodeTypes: z8.array(z8.string()).optional().describe('Filter to specific node types (e.g. ["Type A", "Type B"])')
|
|
510
498
|
})
|
|
511
499
|
},
|
|
512
500
|
async ({ graphId, query, limit, nodeTypes }) => {
|
|
@@ -529,11 +517,11 @@ function registerFilter(server2, client2) {
|
|
|
529
517
|
"naumu_filter",
|
|
530
518
|
{
|
|
531
519
|
title: "Filter Graph Nodes",
|
|
532
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
520
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
533
521
|
description: 'Filter nodes by type and attributes with deterministic, complete results; use for structured queries like "all in-progress Tasks" or "Bugs not yet resolved." Unlike search tools, this returns every matching node (up to the limit) - no semantic ranking, no missed results. Results are sorted by sortKey or recency.',
|
|
534
522
|
inputSchema: z9.object({
|
|
535
523
|
graphId: z9.string().describe("The graph ID"),
|
|
536
|
-
nodeTypes: z9.array(z9.string()).optional().describe('Filter to specific node types (e.g. ["
|
|
524
|
+
nodeTypes: z9.array(z9.string()).optional().describe('Filter to specific node types (e.g. ["Type A", "Type B"])'),
|
|
537
525
|
includeAttributes: z9.record(z9.string(), z9.array(z9.string())).optional().describe(
|
|
538
526
|
'Only include nodes where attribute matches one of the values. Example: {"Status": ["Todo", "In Progress"]}'
|
|
539
527
|
),
|
|
@@ -572,7 +560,7 @@ function registerGetNode(server2, client2) {
|
|
|
572
560
|
"naumu_get_node",
|
|
573
561
|
{
|
|
574
562
|
title: "Get Node",
|
|
575
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
563
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
576
564
|
description: "Get a single node with all its properties and connections (incoming and outgoing edges).",
|
|
577
565
|
inputSchema: z10.object({
|
|
578
566
|
graphId: z10.string().describe("The graph ID"),
|
|
@@ -592,7 +580,7 @@ function registerGetNode(server2, client2) {
|
|
|
592
580
|
import { z as z11 } from "zod";
|
|
593
581
|
var NodeInput = z11.object({
|
|
594
582
|
label: z11.string().describe("Display name of the node"),
|
|
595
|
-
type: z11.string().describe("Node type from the graph schema
|
|
583
|
+
type: z11.string().describe("Node type from the graph schema"),
|
|
596
584
|
content: z11.string().min(1).describe("Rich text content / description. REQUIRED - every node must explain what it is."),
|
|
597
585
|
attributes: z11.record(z11.string(), z11.unknown()).optional().describe("Additional key-value attributes")
|
|
598
586
|
});
|
|
@@ -883,7 +871,7 @@ function registerAsk(server2, client2) {
|
|
|
883
871
|
idempotentHint: false,
|
|
884
872
|
openWorldHint: true
|
|
885
873
|
},
|
|
886
|
-
description: 'Ask @Naumu a question about a space and get a synthesised answer
|
|
874
|
+
description: 'Ask @Naumu a question about a space and get back a synthesised, node-grounded answer with the exact source node ids it used and a confidence hint. This is THE tool for any question about a space - what is in it, what is new or recently changed, how something works, or a summary of any topic. @Naumu has full read access and has already inspected the graph for you, so its answer is authoritative: present it and its cited sources directly. Do NOT independently re-read the graph (naumu_get_schema, naumu_filter, naumu_get_node, fetch) to verify or flesh out the answer - that repeats work @Naumu already did and is far slower. Reach for a granular read ONLY to pull a specific node the answer pointed to but did not fully include. Returns { answer, sources, confidence, threadId, status }; the answer is saved as a visible conversation in the space, which is expected and useful, so do not avoid the tool to prevent creating a thread. On a very long synthesis it may return status "processing" with a threadId - in that case wait a few seconds and call naumu_read_thread with that threadId for the final answer, and still do not fall back to manual digging. To hand @Naumu work to carry out (add knowledge, make changes, record status) without waiting, use naumu_delegate instead.',
|
|
887
875
|
inputSchema: z17.object({
|
|
888
876
|
graphId: z17.string().describe("The space (graph) id to ask about."),
|
|
889
877
|
question: z17.string().max(4e3).describe("The question for @Naumu. Up to 4000 characters.")
|
|
@@ -963,184 +951,8 @@ function registerDelegate(server2, client2) {
|
|
|
963
951
|
);
|
|
964
952
|
}
|
|
965
953
|
|
|
966
|
-
// ../mcp-core/src/tools/get-view.ts
|
|
967
|
-
import { z as z19 } from "zod";
|
|
968
|
-
function registerGetView(server2, client2) {
|
|
969
|
-
server2.registerTool(
|
|
970
|
-
"naumu_get_view",
|
|
971
|
-
{
|
|
972
|
-
title: "Get View",
|
|
973
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
974
|
-
description: "Fetch a saved Naumu view's configuration plus a one-line natural-language summary of its filters; call this BEFORE naumu_list_view_nodes whenever you encounter a view URL. The summary tells you what data the view returns so you can decide whether to page through it. Returns: id, name, description, summary, filters, and table column config.",
|
|
975
|
-
inputSchema: z19.object({
|
|
976
|
-
graphId: z19.string().describe("The graph (space) ID. From naumu.ai URLs this is the value after /spaces/."),
|
|
977
|
-
viewId: z19.string().describe('The view ID (typically prefixed with "view_").')
|
|
978
|
-
})
|
|
979
|
-
},
|
|
980
|
-
async ({ graphId, viewId }) => {
|
|
981
|
-
const data = await client2.get(`/api/graphs/${graphId}/views/${viewId}`);
|
|
982
|
-
return {
|
|
983
|
-
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
984
|
-
};
|
|
985
|
-
}
|
|
986
|
-
);
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
// ../mcp-core/src/tools/list-view-nodes.ts
|
|
990
|
-
import { z as z20 } from "zod";
|
|
991
|
-
function registerListViewNodes(server2, client2) {
|
|
992
|
-
server2.registerTool(
|
|
993
|
-
"naumu_list_view_nodes",
|
|
994
|
-
{
|
|
995
|
-
title: "List View Nodes",
|
|
996
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
997
|
-
description: 'List nodes that match a saved view; pair with naumu_get_view first to read the view\'s filters and decide what payload size you need. Cursor-paginated.\n\nResponse shape: { nodes, totalCount, nextCursor, hasMore }. Use totalCount to know how many results exist without paging through them. Use hasMore (boolean) to decide whether to fetch the next page; pass nextCursor back as `cursor` to do so.\n\nfields parameter:\n- "summary" (default): {id, label, type} - best for browsing.\n- "id": {id} only - use when you need to count or iterate cheaply.\n- "full": full node payload with all attributes - use when you need every property.\n\nDefault page size 25, max 100.',
|
|
998
|
-
inputSchema: z20.object({
|
|
999
|
-
graphId: z20.string().describe("The graph (space) ID."),
|
|
1000
|
-
viewId: z20.string().describe("The view ID."),
|
|
1001
|
-
cursor: z20.string().optional().describe("Opaque cursor from a previous response's nextCursor. Omit for the first page."),
|
|
1002
|
-
limit: z20.number().int().min(1).max(100).optional().describe("Page size, default 25, max 100."),
|
|
1003
|
-
fields: z20.enum(["id", "summary", "full"]).optional().describe('How much detail per node. Default "summary".')
|
|
1004
|
-
})
|
|
1005
|
-
},
|
|
1006
|
-
async ({ graphId, viewId, cursor, limit, fields }) => {
|
|
1007
|
-
const params = new URLSearchParams();
|
|
1008
|
-
if (cursor) params.set("cursor", cursor);
|
|
1009
|
-
if (limit !== void 0) params.set("limit", String(limit));
|
|
1010
|
-
if (fields) params.set("fields", fields);
|
|
1011
|
-
const qs = params.toString();
|
|
1012
|
-
const path = `/api/graphs/${graphId}/views/${viewId}/nodes${qs ? `?${qs}` : ""}`;
|
|
1013
|
-
const data = await client2.get(path);
|
|
1014
|
-
return {
|
|
1015
|
-
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
1016
|
-
};
|
|
1017
|
-
}
|
|
1018
|
-
);
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
// ../mcp-core/src/tools/list-canvases.ts
|
|
1022
|
-
import { z as z21 } from "zod";
|
|
1023
|
-
function registerListCanvases(server2, client2) {
|
|
1024
|
-
server2.registerTool(
|
|
1025
|
-
"naumu_list_canvases",
|
|
1026
|
-
{
|
|
1027
|
-
title: "List Canvases",
|
|
1028
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
1029
|
-
description: "List freeform drawing canvases in a graph. Each canvas is an Excalidraw-style sketch surface that may contain shapes, text, freehand strokes, images, bookmark cards, and embedded references to graph nodes.",
|
|
1030
|
-
inputSchema: z21.object({
|
|
1031
|
-
graphId: z21.string().describe("The graph ID to list canvases for")
|
|
1032
|
-
})
|
|
1033
|
-
},
|
|
1034
|
-
async ({ graphId }) => {
|
|
1035
|
-
const data = await client2.get(`/api/canvases?graphId=${encodeURIComponent(graphId)}`);
|
|
1036
|
-
return {
|
|
1037
|
-
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
1038
|
-
};
|
|
1039
|
-
}
|
|
1040
|
-
);
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
// ../mcp-core/src/tools/get-canvas-elements.ts
|
|
1044
|
-
import { z as z22 } from "zod";
|
|
1045
|
-
function registerGetCanvasElements(server2, client2) {
|
|
1046
|
-
server2.registerTool(
|
|
1047
|
-
"naumu_get_canvas_elements",
|
|
1048
|
-
{
|
|
1049
|
-
title: "Get Canvas Elements",
|
|
1050
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
1051
|
-
description: "Read the structured JSON contents of a canvas - every shape, text, line, freehand stroke, image, bookmark card, and entity-embed with their positions, colors, and text. Use this when you need to reason about what a user has drawn without needing to see the visual output.",
|
|
1052
|
-
inputSchema: z22.object({
|
|
1053
|
-
canvasId: z22.string().describe("The canvas ID")
|
|
1054
|
-
})
|
|
1055
|
-
},
|
|
1056
|
-
async ({ canvasId }) => {
|
|
1057
|
-
const data = await client2.get(`/api/canvases/${encodeURIComponent(canvasId)}/elements`);
|
|
1058
|
-
return {
|
|
1059
|
-
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
1060
|
-
};
|
|
1061
|
-
}
|
|
1062
|
-
);
|
|
1063
|
-
}
|
|
1064
|
-
|
|
1065
|
-
// ../mcp-core/src/tools/get-canvas-image.ts
|
|
1066
|
-
import { z as z23 } from "zod";
|
|
1067
|
-
var MAX_INLINE_BYTES = 4 * 1024 * 1024;
|
|
1068
|
-
function registerGetCanvasImage(server2, client2) {
|
|
1069
|
-
server2.registerTool(
|
|
1070
|
-
"naumu_get_canvas_image",
|
|
1071
|
-
{
|
|
1072
|
-
title: "Get Canvas Image",
|
|
1073
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
1074
|
-
description: 'Render a canvas to a PNG image so you can visually inspect what was drawn - freehand strokes, spatial layout, sketches. Returns the image inline by default so any MCP host can see it directly. Use `mode: "url"` if you specifically need a signed URL (e.g. very large canvases, or to share the link).',
|
|
1075
|
-
inputSchema: z23.object({
|
|
1076
|
-
canvasId: z23.string().describe("The canvas ID"),
|
|
1077
|
-
scale: z23.union([z23.literal(1), z23.literal(2)]).default(2).describe("Pixel density (1 or 2). Default is 2 for retina-quality output."),
|
|
1078
|
-
theme: z23.enum(["light", "dark"]).default("light").describe("Background theme to render with."),
|
|
1079
|
-
mode: z23.enum(["inline", "url"]).default("inline").describe(
|
|
1080
|
-
"`inline` (default) embeds the PNG directly so vision-capable hosts see it. `url` returns a signed S3 URL that expires in 1 hour - useful for large canvases or sharing."
|
|
1081
|
-
)
|
|
1082
|
-
})
|
|
1083
|
-
},
|
|
1084
|
-
async ({ canvasId, scale, theme, mode }) => {
|
|
1085
|
-
if (mode === "url") {
|
|
1086
|
-
return await fetchAsUrl(client2, canvasId, scale, theme);
|
|
1087
|
-
}
|
|
1088
|
-
const params = new URLSearchParams({
|
|
1089
|
-
scale: String(scale),
|
|
1090
|
-
theme
|
|
1091
|
-
});
|
|
1092
|
-
const { buffer, contentType } = await client2.getBinary(
|
|
1093
|
-
`/api/canvases/${encodeURIComponent(canvasId)}/image?${params.toString()}`
|
|
1094
|
-
);
|
|
1095
|
-
if (buffer.byteLength > MAX_INLINE_BYTES) {
|
|
1096
|
-
return await fetchAsUrl(client2, canvasId, scale, theme, {
|
|
1097
|
-
reason: `Canvas PNG is ${formatBytes(buffer.byteLength)}, exceeds inline limit ${formatBytes(MAX_INLINE_BYTES)} \u2014 returning signed URL instead.`
|
|
1098
|
-
});
|
|
1099
|
-
}
|
|
1100
|
-
const base64 = bufferToBase64(buffer);
|
|
1101
|
-
return {
|
|
1102
|
-
content: [
|
|
1103
|
-
{
|
|
1104
|
-
type: "image",
|
|
1105
|
-
data: base64,
|
|
1106
|
-
mimeType: contentType.startsWith("image/") ? contentType : "image/png"
|
|
1107
|
-
}
|
|
1108
|
-
]
|
|
1109
|
-
};
|
|
1110
|
-
}
|
|
1111
|
-
);
|
|
1112
|
-
}
|
|
1113
|
-
async function fetchAsUrl(client2, canvasId, scale, theme, extra) {
|
|
1114
|
-
const params = new URLSearchParams({
|
|
1115
|
-
as: "url",
|
|
1116
|
-
scale: String(scale),
|
|
1117
|
-
theme
|
|
1118
|
-
});
|
|
1119
|
-
const data = await client2.get(
|
|
1120
|
-
`/api/canvases/${encodeURIComponent(canvasId)}/image?${params.toString()}`
|
|
1121
|
-
);
|
|
1122
|
-
const payload = extra ? { ...data, note: extra.reason } : data;
|
|
1123
|
-
return {
|
|
1124
|
-
content: [{ type: "text", text: JSON.stringify(payload, null, 2) }]
|
|
1125
|
-
};
|
|
1126
|
-
}
|
|
1127
|
-
function bufferToBase64(buffer) {
|
|
1128
|
-
if (typeof Buffer !== "undefined") {
|
|
1129
|
-
return Buffer.from(buffer).toString("base64");
|
|
1130
|
-
}
|
|
1131
|
-
let binary = "";
|
|
1132
|
-
for (let i = 0; i < buffer.byteLength; i++) {
|
|
1133
|
-
binary += String.fromCharCode(buffer[i]);
|
|
1134
|
-
}
|
|
1135
|
-
return btoa(binary);
|
|
1136
|
-
}
|
|
1137
|
-
function formatBytes(bytes) {
|
|
1138
|
-
if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
1139
|
-
return `${(bytes / 1024).toFixed(1)}KB`;
|
|
1140
|
-
}
|
|
1141
|
-
|
|
1142
954
|
// ../mcp-core/src/tools/post-message.ts
|
|
1143
|
-
import { z as
|
|
955
|
+
import { z as z19 } from "zod";
|
|
1144
956
|
function registerPostMessage(server2, client2) {
|
|
1145
957
|
server2.registerTool(
|
|
1146
958
|
"naumu_post_message",
|
|
@@ -1155,11 +967,11 @@ function registerPostMessage(server2, client2) {
|
|
|
1155
967
|
openWorldHint: false
|
|
1156
968
|
},
|
|
1157
969
|
description: 'Post a message in a Naumu thread you participate in. Use it to reply to humans (or other bots) in a thread that pinged you. Plain text is accepted by default; for rendered @mentions pass a Tiptap JSON document with mention nodes (`{ type: "mention", attrs: { id, label } }`) and set contentFormat to "tiptap". @mentioning people loops them in without invoking @Naumu. To attach files call naumu_request_attachment_upload first, PUT the bytes to the returned uploadUrl, then pass the resulting attachmentIds here. The message needs either `content` or `attachmentIds`. Returns the created message JSON. To get a synthesised answer from @Naumu, use naumu_ask.',
|
|
1158
|
-
inputSchema:
|
|
1159
|
-
threadId:
|
|
1160
|
-
content:
|
|
1161
|
-
contentFormat:
|
|
1162
|
-
attachmentIds:
|
|
970
|
+
inputSchema: z19.object({
|
|
971
|
+
threadId: z19.string().describe("The thread ID to post into. You must be a participant in this thread."),
|
|
972
|
+
content: z19.string().optional().describe('Message body. Plain text by default; pass a Tiptap JSON document only if contentFormat is set to "tiptap". Optional when `attachmentIds` is provided.'),
|
|
973
|
+
contentFormat: z19.enum(["tiptap", "text"]).optional().describe('Format of `content`. Defaults to "text". Use "tiptap" for rendered mentions/embeds, e.g. a doc containing `{ type: "mention", attrs: { id: userIdOrIdentityId, label: displayName } }`.'),
|
|
974
|
+
attachmentIds: z19.array(z19.string().min(1)).max(25).optional().describe("Attachment IDs from prior `naumu_request_attachment_upload` calls. Each must be a successfully-uploaded pending attachment in this graph (1-hour TTL). Up to 25 per message.")
|
|
1163
975
|
})
|
|
1164
976
|
},
|
|
1165
977
|
async ({ threadId, content, contentFormat, attachmentIds }) => {
|
|
@@ -1185,18 +997,18 @@ function registerPostMessage(server2, client2) {
|
|
|
1185
997
|
}
|
|
1186
998
|
|
|
1187
999
|
// ../mcp-core/src/tools/read-thread.ts
|
|
1188
|
-
import { z as
|
|
1000
|
+
import { z as z20 } from "zod";
|
|
1189
1001
|
function registerReadThread(server2, client2) {
|
|
1190
1002
|
server2.registerTool(
|
|
1191
1003
|
"naumu_read_thread",
|
|
1192
1004
|
{
|
|
1193
1005
|
title: "Read Thread",
|
|
1194
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
1006
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
1195
1007
|
description: 'Read messages from a Naumu thread. Returns paginated history ordered newest-first; each message carries a `status` (`processing` while @Naumu is still composing, `complete` when done). Use this to pick up an answer after naumu_ask returns status "processing", or to read what naumu_delegate produced. Use `before` (timestamp ms) to page further back. Default page size 50, max 200.',
|
|
1196
|
-
inputSchema:
|
|
1197
|
-
threadId:
|
|
1198
|
-
before:
|
|
1199
|
-
limit:
|
|
1008
|
+
inputSchema: z20.object({
|
|
1009
|
+
threadId: z20.string().describe("The thread ID to read from."),
|
|
1010
|
+
before: z20.number().optional().describe("Unix timestamp in milliseconds. Returns messages strictly older than this. Omit for the newest page."),
|
|
1011
|
+
limit: z20.number().int().min(1).max(200).optional().describe("Page size, default 50, max 200.")
|
|
1200
1012
|
})
|
|
1201
1013
|
},
|
|
1202
1014
|
async ({ threadId, before, limit }) => {
|
|
@@ -1222,15 +1034,15 @@ function registerReadThread(server2, client2) {
|
|
|
1222
1034
|
}
|
|
1223
1035
|
|
|
1224
1036
|
// ../mcp-core/src/tools/whoami.ts
|
|
1225
|
-
import { z as
|
|
1037
|
+
import { z as z21 } from "zod";
|
|
1226
1038
|
function registerWhoami(server2, client2, allToolNames) {
|
|
1227
1039
|
server2.registerTool(
|
|
1228
1040
|
"naumu_whoami",
|
|
1229
1041
|
{
|
|
1230
1042
|
title: "Who Am I",
|
|
1231
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
1043
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
1232
1044
|
description: 'Return who the calling key is plus the live MCP tool manifest, so you can bootstrap before the first real operation. A bot identity key returns its Identity row (id, graphId, name, instructions, allowedTools). A user API key returns `kind: "user"` with userId, name, and email - a person spans many graphs, so resolve a specific graph via naumu_list_graphs. No arguments. Always available regardless of the permission grid.',
|
|
1233
|
-
inputSchema:
|
|
1045
|
+
inputSchema: z21.object({})
|
|
1234
1046
|
},
|
|
1235
1047
|
async () => {
|
|
1236
1048
|
try {
|
|
@@ -1253,7 +1065,7 @@ function registerWhoami(server2, client2, allToolNames) {
|
|
|
1253
1065
|
}
|
|
1254
1066
|
|
|
1255
1067
|
// ../mcp-core/src/tools/list-threads.ts
|
|
1256
|
-
import { z as
|
|
1068
|
+
import { z as z22 } from "zod";
|
|
1257
1069
|
function sanitizeThreadParticipants(thread) {
|
|
1258
1070
|
if (!thread || typeof thread !== "object" || !("participantEmails" in thread)) {
|
|
1259
1071
|
return thread;
|
|
@@ -1266,12 +1078,12 @@ function registerListThreads(server2, client2) {
|
|
|
1266
1078
|
"naumu_list_threads",
|
|
1267
1079
|
{
|
|
1268
1080
|
title: "List Threads",
|
|
1269
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
1081
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
1270
1082
|
description: "List threads sorted by last activity (newest first), for self-discovery before deciding which to engage. With a user API key, pass `graphId` to list threads you can see in that space (resolve it via naumu_list_graphs). With a bot identity key, omit `graphId` to list threads in your own graph \u2014 each row carries an `isParticipant` flag (TRUE means you were explicitly invited and your replies fan out via webhook). Page back with `cursor` set to the oldest `lastActivityAt` from the previous page.",
|
|
1271
|
-
inputSchema:
|
|
1272
|
-
graphId:
|
|
1273
|
-
cursor:
|
|
1274
|
-
limit:
|
|
1083
|
+
inputSchema: z22.object({
|
|
1084
|
+
graphId: z22.string().optional().describe("Graph (space) ID. Required for user API keys; omit for bot identity keys (defaults to your own graph)."),
|
|
1085
|
+
cursor: z22.number().int().optional().describe("Unix timestamp ms \u2014 returns threads with `lastActivityAt` strictly older than this. Omit for the newest page."),
|
|
1086
|
+
limit: z22.number().int().min(1).max(200).optional().describe("Page size, default 50, max 200.")
|
|
1275
1087
|
})
|
|
1276
1088
|
},
|
|
1277
1089
|
async ({ graphId, cursor, limit }) => {
|
|
@@ -1307,7 +1119,7 @@ function registerListThreads(server2, client2) {
|
|
|
1307
1119
|
}
|
|
1308
1120
|
|
|
1309
1121
|
// ../mcp-core/src/tools/get-thread.ts
|
|
1310
|
-
import { z as
|
|
1122
|
+
import { z as z23 } from "zod";
|
|
1311
1123
|
function sanitizeThreadParticipants2(thread) {
|
|
1312
1124
|
if (!thread || typeof thread !== "object" || !("participantEmails" in thread)) {
|
|
1313
1125
|
return thread;
|
|
@@ -1320,10 +1132,10 @@ function registerGetThread(server2, client2) {
|
|
|
1320
1132
|
"naumu_get_thread",
|
|
1321
1133
|
{
|
|
1322
1134
|
title: "Get Thread",
|
|
1323
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
1135
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
1324
1136
|
description: "Fetch a single thread, including the human participant roster (`participantDetails` \u2014 userId, name, image) and bot roster (`identityParticipants` \u2014 id, name, isSystem). Use this when `naumu_list_threads` surfaced a candidate and you want to know exactly who is in it before posting. Pair with `naumu_read_thread` for message history.",
|
|
1325
|
-
inputSchema:
|
|
1326
|
-
threadId:
|
|
1137
|
+
inputSchema: z23.object({
|
|
1138
|
+
threadId: z23.string().describe("The thread ID to fetch.")
|
|
1327
1139
|
})
|
|
1328
1140
|
},
|
|
1329
1141
|
async ({ threadId }) => {
|
|
@@ -1345,7 +1157,7 @@ function registerGetThread(server2, client2) {
|
|
|
1345
1157
|
}
|
|
1346
1158
|
|
|
1347
1159
|
// ../mcp-core/src/tools/create-thread.ts
|
|
1348
|
-
import { z as
|
|
1160
|
+
import { z as z24 } from "zod";
|
|
1349
1161
|
function registerCreateThread(server2, client2) {
|
|
1350
1162
|
server2.registerTool(
|
|
1351
1163
|
"naumu_create_thread",
|
|
@@ -1360,22 +1172,22 @@ function registerCreateThread(server2, client2) {
|
|
|
1360
1172
|
openWorldHint: false
|
|
1361
1173
|
},
|
|
1362
1174
|
description: "Start a new conversation in a space. You are auto-attached as a participant, and the thread's formal creator is your primary owner (the user who registered you), so it shows in their sidebar. Optional `participants` adds humans (by userId) and other bots (by identityId) at creation. Optional `initialMessage` opens the conversation as your first message. Tagging people loops them in without invoking @Naumu; only an explicit @Naumu mention, or naumu_ask, brings the agent in. Returns the created thread (including its id) so you can follow up with naumu_post_message.",
|
|
1363
|
-
inputSchema:
|
|
1364
|
-
title:
|
|
1365
|
-
participants:
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
type:
|
|
1369
|
-
userId:
|
|
1175
|
+
inputSchema: z24.object({
|
|
1176
|
+
title: z24.string().min(1).max(200).optional().describe('Thread title shown in the sidebar. If omitted, Naumu generates a default like "Conversation YYYY-MM-DD".'),
|
|
1177
|
+
participants: z24.array(
|
|
1178
|
+
z24.discriminatedUnion("type", [
|
|
1179
|
+
z24.object({
|
|
1180
|
+
type: z24.literal("user"),
|
|
1181
|
+
userId: z24.string().min(1).describe("User UUID \u2014 get these from `naumu_get_thread`/`naumu_read_thread` participant rosters or webhook payloads.")
|
|
1370
1182
|
}),
|
|
1371
|
-
|
|
1372
|
-
type:
|
|
1373
|
-
identityId:
|
|
1183
|
+
z24.object({
|
|
1184
|
+
type: z24.literal("identity"),
|
|
1185
|
+
identityId: z24.string().min(1).describe("Identity id (`identity-\u2026` or `id-\u2026`). Other bots in the same graph can be co-attached to multi-bot threads.")
|
|
1374
1186
|
})
|
|
1375
1187
|
])
|
|
1376
1188
|
).max(32).optional().describe("Up to 32 humans and/or other bots to attach at creation. Your primary owner is added automatically \u2014 you do NOT need to list them here."),
|
|
1377
|
-
initialMessage:
|
|
1378
|
-
visibility:
|
|
1189
|
+
initialMessage: z24.string().min(1).max(32e3).optional().describe("Markdown body for the first message. Authored by you (the bot), so it appears in the thread under your name."),
|
|
1190
|
+
visibility: z24.enum(["restricted", "internal", "open"]).optional().describe("`restricted` (invite-only, default) hides from non-participants. `internal` is visible to space members. `open` is visible to anyone who can see the space.")
|
|
1379
1191
|
})
|
|
1380
1192
|
},
|
|
1381
1193
|
async ({ title, participants, initialMessage, visibility }) => {
|
|
@@ -1401,7 +1213,7 @@ function registerCreateThread(server2, client2) {
|
|
|
1401
1213
|
}
|
|
1402
1214
|
|
|
1403
1215
|
// ../mcp-core/src/tools/request-attachment-upload.ts
|
|
1404
|
-
import { z as
|
|
1216
|
+
import { z as z25 } from "zod";
|
|
1405
1217
|
function registerRequestAttachmentUpload(server2, client2) {
|
|
1406
1218
|
server2.registerTool(
|
|
1407
1219
|
"naumu_request_attachment_upload",
|
|
@@ -1409,12 +1221,12 @@ function registerRequestAttachmentUpload(server2, client2) {
|
|
|
1409
1221
|
title: "Request Attachment Upload",
|
|
1410
1222
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
1411
1223
|
description: 'Request a presigned S3 upload URL to attach a file to a message; use when you want to deliver generated content as a file (a markdown report, a PDF, an image, an audio recording, a video). Same flow Naumu users use for file uploads: get a signed URL, PUT the bytes to it directly, then call `naumu_post_message` with the returned `attachmentId` in `attachmentIds`. Per-MIME size caps apply (typically 50MB umbrella, 10MB for agent-readable types).\n\nReturns `{ attachmentId, uploadUrl, method, requiredHeaders, expiresAt }`. Use these EXACTLY:\n\u2022 `method` is "PUT".\n\u2022 Send every header in `requiredHeaders` (Content-Type matters for S3 signature validation).\n\u2022 Do NOT add an Authorization header - the URL itself is the auth.\n\u2022 Do NOT log `uploadUrl` - it is a bearer capability for the duration of the TTL.\n\u2022 `expiresAt` is a Unix-ms timestamp; the pending attachment vanishes at that moment whether or not you uploaded. Call `naumu_post_message` with the attachmentId before then or the upload orphans.\n\nServer-side checks at post time enforce that the attachment was uploaded by you, in this graph, for this thread - you cannot reuse an upload across threads.',
|
|
1412
|
-
inputSchema:
|
|
1413
|
-
threadId:
|
|
1414
|
-
fileName:
|
|
1415
|
-
fileType:
|
|
1416
|
-
fileSize:
|
|
1417
|
-
audioDurationSec:
|
|
1224
|
+
inputSchema: z25.object({
|
|
1225
|
+
threadId: z25.string().describe("Thread the attachment will land in. You must be a participant. The pending attachment is keyed to this thread - you cannot reuse it for a different one."),
|
|
1226
|
+
fileName: z25.string().min(1).describe("Original filename (with extension). Used as the display name in the message and for the S3 object suffix. Special characters are sanitized server-side."),
|
|
1227
|
+
fileType: z25.string().min(1).describe("MIME type, e.g. `application/pdf`, `image/png`, `text/markdown`, `audio/mpeg`, `video/mp4`. The S3 PUT will enforce this Content-Type."),
|
|
1228
|
+
fileSize: z25.number().int().positive().describe("File size in bytes. Validated against per-MIME caps before the URL is issued - exceeding the cap returns a 400."),
|
|
1229
|
+
audioDurationSec: z25.number().positive().optional().describe("For audio attachments, duration in seconds. Validated against the audio recording cap (currently 8 hours).")
|
|
1418
1230
|
})
|
|
1419
1231
|
},
|
|
1420
1232
|
async ({ threadId, fileName, fileType, fileSize, audioDurationSec }) => {
|
|
@@ -1444,7 +1256,7 @@ function registerRequestAttachmentUpload(server2, client2) {
|
|
|
1444
1256
|
}
|
|
1445
1257
|
|
|
1446
1258
|
// ../mcp-core/src/tools/add-reaction.ts
|
|
1447
|
-
import { z as
|
|
1259
|
+
import { z as z26 } from "zod";
|
|
1448
1260
|
function registerAddReaction(server2, client2) {
|
|
1449
1261
|
server2.registerTool(
|
|
1450
1262
|
"naumu_add_reaction",
|
|
@@ -1452,10 +1264,10 @@ function registerAddReaction(server2, client2) {
|
|
|
1452
1264
|
title: "Add Reaction",
|
|
1453
1265
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
1454
1266
|
description: 'Add an emoji reaction to a message in a thread you are participating in; use for lightweight acknowledgement instead of posting a message. Idempotent - calling twice with the same emoji is a no-op (use `naumu_remove_reaction` to undo). Returns `{ ok, messageId, emoji, alreadyExisted, reactionCount, reactions }` so you can confirm the state without re-reading the thread; `alreadyExisted: true` means the reaction was already on the message and the call was a no-op.\n\nWhen to react vs. when to post a message:\n\u2022 React (no message) for lightweight acknowledgement (\u{1F440}, \u2705, \u{1F44D}), appreciation (\u2764\uFE0F, \u{1F64C}), laughter (\u{1F602}), or "I saw this".\n\u2022 Post a message for direct questions, clarification, important corrections, or final results - situations where words are required.\n\u2022 For long tasks: react \u{1F440} first to acknowledge, optionally post a short "On it - I\'ll report back" if the work will take >20s, do the work, then post the final result.\n\u2022 Ignore casual human banter, side-conversations someone else already answered, or anything where you would only say "ok"/"nice"/"lol".\n\nUse at most one reaction per message unless explicitly useful. Reactions are social backpressure relief, not a sparkle-confetti channel.',
|
|
1455
|
-
inputSchema:
|
|
1456
|
-
threadId:
|
|
1457
|
-
messageId:
|
|
1458
|
-
emoji:
|
|
1267
|
+
inputSchema: z26.object({
|
|
1268
|
+
threadId: z26.string().describe("Thread containing the message. You must be a participant."),
|
|
1269
|
+
messageId: z26.string().describe("The message to react to."),
|
|
1270
|
+
emoji: z26.string().min(1).describe('Emoji character (e.g. "\u{1F440}", "\u2705", "\u2764\uFE0F"). Custom-emoji shortcodes are NOT supported here - pass a real Unicode emoji.')
|
|
1459
1271
|
})
|
|
1460
1272
|
},
|
|
1461
1273
|
async ({ threadId, messageId, emoji }) => {
|
|
@@ -1479,7 +1291,7 @@ function registerAddReaction(server2, client2) {
|
|
|
1479
1291
|
}
|
|
1480
1292
|
|
|
1481
1293
|
// ../mcp-core/src/tools/remove-reaction.ts
|
|
1482
|
-
import { z as
|
|
1294
|
+
import { z as z27 } from "zod";
|
|
1483
1295
|
function registerRemoveReaction(server2, client2) {
|
|
1484
1296
|
server2.registerTool(
|
|
1485
1297
|
"naumu_remove_reaction",
|
|
@@ -1487,10 +1299,10 @@ function registerRemoveReaction(server2, client2) {
|
|
|
1487
1299
|
title: "Remove Reaction",
|
|
1488
1300
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
1489
1301
|
description: "Remove your own emoji reaction from a message; use to walk back an acknowledgement you previously added. Idempotent - calling on a reaction you never added is a no-op. Pair with `naumu_add_reaction` (e.g. you reacted \u{1F440} to start a task and want to clear it after a final result message lands). Returns `{ ok, messageId, emoji, alreadyExisted, reactionCount, reactions }` - `alreadyExisted: false` means there was nothing to remove and the call was a no-op.",
|
|
1490
|
-
inputSchema:
|
|
1491
|
-
threadId:
|
|
1492
|
-
messageId:
|
|
1493
|
-
emoji:
|
|
1302
|
+
inputSchema: z27.object({
|
|
1303
|
+
threadId: z27.string().describe("Thread containing the message. You must be a participant."),
|
|
1304
|
+
messageId: z27.string().describe("The message to remove your reaction from."),
|
|
1305
|
+
emoji: z27.string().min(1).describe("Emoji character to remove (must match what you originally reacted with).")
|
|
1494
1306
|
})
|
|
1495
1307
|
},
|
|
1496
1308
|
async ({ threadId, messageId, emoji }) => {
|
|
@@ -1514,7 +1326,7 @@ function registerRemoveReaction(server2, client2) {
|
|
|
1514
1326
|
}
|
|
1515
1327
|
|
|
1516
1328
|
// ../mcp-core/src/tools/naumu-typing.ts
|
|
1517
|
-
import { z as
|
|
1329
|
+
import { z as z28 } from "zod";
|
|
1518
1330
|
function registerNaumuTyping(server2, client2) {
|
|
1519
1331
|
server2.registerTool(
|
|
1520
1332
|
"naumu_typing",
|
|
@@ -1525,9 +1337,9 @@ function registerNaumuTyping(server2, client2) {
|
|
|
1525
1337
|
// repeating the same state is a no-op renew, so idempotent.
|
|
1526
1338
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
1527
1339
|
description: 'Show or hide your "is typing\u2026" pill in a thread; use to signal that you are composing a reply. Call with `state: "start"` the moment you decide to compose a reply (before any LLM call), and the server holds the pill alive - re-broadcasting on a short interval - until you stop, post a message, or the lease cap (~5 min) fires. You do NOT need to refresh on a timer; that\'s the lease\'s job.\n\nThe pill clears automatically when:\n\u2022 you call this tool with `state: "stop"`\n\u2022 you call `naumu_post_message` for the same thread (cleared on commit)\n\u2022 the lease cap expires\n\nUse `start` whenever you start work, even if you might end up not replying - call `stop` if you decide NOT to post. Calling `start` while a lease is already active renews it (resets the cap), so a long-running run can call `start` again as a heartbeat without breaking the indicator. You must be a participant of the thread.',
|
|
1528
|
-
inputSchema:
|
|
1529
|
-
threadId:
|
|
1530
|
-
state:
|
|
1340
|
+
inputSchema: z28.object({
|
|
1341
|
+
threadId: z28.string().describe("The thread ID to set typing in. You must be a participant."),
|
|
1342
|
+
state: z28.enum(["start", "stop"]).describe('"start" acquires/renews the lease; "stop" ends it and clears the pill immediately.')
|
|
1531
1343
|
})
|
|
1532
1344
|
},
|
|
1533
1345
|
async ({ threadId, state }) => {
|
|
@@ -1548,16 +1360,16 @@ function registerNaumuTyping(server2, client2) {
|
|
|
1548
1360
|
}
|
|
1549
1361
|
|
|
1550
1362
|
// ../mcp-core/src/tools/note-read.ts
|
|
1551
|
-
import { z as
|
|
1363
|
+
import { z as z29 } from "zod";
|
|
1552
1364
|
function registerNoteRead(server2, client2) {
|
|
1553
1365
|
server2.registerTool(
|
|
1554
1366
|
"naumu_note_read",
|
|
1555
1367
|
{
|
|
1556
1368
|
title: "Read Note",
|
|
1557
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
1369
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
1558
1370
|
description: "Read the current contents of a note as markdown; use before editing so you know what you're working with. `naumu_note_find_replace` and the section-based tools (`naumu_note_insert`, `naumu_note_replace_section`, `naumu_note_delete_section`) anchor on text/headings present in the live doc.",
|
|
1559
|
-
inputSchema:
|
|
1560
|
-
noteId:
|
|
1371
|
+
inputSchema: z29.object({
|
|
1372
|
+
noteId: z29.string().describe("The note (Thought) ID")
|
|
1561
1373
|
})
|
|
1562
1374
|
},
|
|
1563
1375
|
async ({ noteId }) => {
|
|
@@ -1570,7 +1382,7 @@ function registerNoteRead(server2, client2) {
|
|
|
1570
1382
|
}
|
|
1571
1383
|
|
|
1572
1384
|
// ../mcp-core/src/tools/note-append.ts
|
|
1573
|
-
import { z as
|
|
1385
|
+
import { z as z30 } from "zod";
|
|
1574
1386
|
function registerNoteAppend(server2, client2) {
|
|
1575
1387
|
server2.registerTool(
|
|
1576
1388
|
"naumu_note_append",
|
|
@@ -1578,9 +1390,9 @@ function registerNoteAppend(server2, client2) {
|
|
|
1578
1390
|
title: "Append to Note",
|
|
1579
1391
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
1580
1392
|
description: "Append markdown blocks to the end of a note; use for additive note writing that never touches existing content. Other participants see your colored cursor while the write lands. Markdown supports headings (1-3), bold/italic/code, lists, blockquotes, code blocks, links, and tables.",
|
|
1581
|
-
inputSchema:
|
|
1582
|
-
noteId:
|
|
1583
|
-
markdown:
|
|
1393
|
+
inputSchema: z30.object({
|
|
1394
|
+
noteId: z30.string().describe("The note (Thought) ID to append to"),
|
|
1395
|
+
markdown: z30.string().min(1).describe("Markdown content to append at the end of the note")
|
|
1584
1396
|
})
|
|
1585
1397
|
},
|
|
1586
1398
|
async ({ noteId, markdown }) => {
|
|
@@ -1593,7 +1405,7 @@ function registerNoteAppend(server2, client2) {
|
|
|
1593
1405
|
}
|
|
1594
1406
|
|
|
1595
1407
|
// ../mcp-core/src/tools/note-insert.ts
|
|
1596
|
-
import { z as
|
|
1408
|
+
import { z as z31 } from "zod";
|
|
1597
1409
|
function registerNoteInsert(server2, client2) {
|
|
1598
1410
|
server2.registerTool(
|
|
1599
1411
|
"naumu_note_insert",
|
|
@@ -1601,10 +1413,10 @@ function registerNoteInsert(server2, client2) {
|
|
|
1601
1413
|
title: "Insert After Heading",
|
|
1602
1414
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
1603
1415
|
description: "Insert markdown content into a note immediately after a named section; use to add content under a specific heading without rewriting it. The section ends at the next heading of equal-or-higher level (or end of doc). 404 if no heading matches `headingText` exactly - call `naumu_note_read` first to see the live structure.",
|
|
1604
|
-
inputSchema:
|
|
1605
|
-
noteId:
|
|
1606
|
-
headingText:
|
|
1607
|
-
markdown:
|
|
1416
|
+
inputSchema: z31.object({
|
|
1417
|
+
noteId: z31.string().describe("The note (Thought) ID"),
|
|
1418
|
+
headingText: z31.string().min(1).describe("Exact text of the heading whose section the new content follows"),
|
|
1419
|
+
markdown: z31.string().min(1).describe("Markdown content to insert at the end of that section")
|
|
1608
1420
|
})
|
|
1609
1421
|
},
|
|
1610
1422
|
async ({ noteId, headingText, markdown }) => {
|
|
@@ -1620,7 +1432,7 @@ function registerNoteInsert(server2, client2) {
|
|
|
1620
1432
|
}
|
|
1621
1433
|
|
|
1622
1434
|
// ../mcp-core/src/tools/note-replace-section.ts
|
|
1623
|
-
import { z as
|
|
1435
|
+
import { z as z32 } from "zod";
|
|
1624
1436
|
function registerNoteReplaceSection(server2, client2) {
|
|
1625
1437
|
server2.registerTool(
|
|
1626
1438
|
"naumu_note_replace_section",
|
|
@@ -1628,11 +1440,11 @@ function registerNoteReplaceSection(server2, client2) {
|
|
|
1628
1440
|
title: "Replace Section",
|
|
1629
1441
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
|
|
1630
1442
|
description: "Replace the body under a named heading with new markdown; use to rewrite one section of a note while leaving the rest intact. By default the heading row itself is preserved (set `keepHeading: false` to drop it too). 404 if no heading matches.",
|
|
1631
|
-
inputSchema:
|
|
1632
|
-
noteId:
|
|
1633
|
-
headingText:
|
|
1634
|
-
markdown:
|
|
1635
|
-
keepHeading:
|
|
1443
|
+
inputSchema: z32.object({
|
|
1444
|
+
noteId: z32.string().describe("The note (Thought) ID"),
|
|
1445
|
+
headingText: z32.string().min(1).describe("Exact text of the heading anchoring the section"),
|
|
1446
|
+
markdown: z32.string().describe("Replacement markdown for the section body"),
|
|
1447
|
+
keepHeading: z32.boolean().optional().describe("Whether to keep the heading row itself. Default true.")
|
|
1636
1448
|
})
|
|
1637
1449
|
},
|
|
1638
1450
|
async ({ noteId, headingText, markdown, keepHeading }) => {
|
|
@@ -1649,7 +1461,7 @@ function registerNoteReplaceSection(server2, client2) {
|
|
|
1649
1461
|
}
|
|
1650
1462
|
|
|
1651
1463
|
// ../mcp-core/src/tools/note-delete-section.ts
|
|
1652
|
-
import { z as
|
|
1464
|
+
import { z as z33 } from "zod";
|
|
1653
1465
|
function registerNoteDeleteSection(server2, client2) {
|
|
1654
1466
|
server2.registerTool(
|
|
1655
1467
|
"naumu_note_delete_section",
|
|
@@ -1657,9 +1469,9 @@ function registerNoteDeleteSection(server2, client2) {
|
|
|
1657
1469
|
title: "Delete Section",
|
|
1658
1470
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
|
|
1659
1471
|
description: "\u26A0 DESTRUCTIVE: remove a heading row plus its body (down to the next heading of equal-or-higher level); ONLY use when the user explicitly asks to drop a section. Anything inside that section is gone - there is no per-call undo. If you're unsure which heading they meant, call `naumu_note_read` first to see the current structure. Returns 404 if `headingText` does not exactly match any live heading.",
|
|
1660
|
-
inputSchema:
|
|
1661
|
-
noteId:
|
|
1662
|
-
headingText:
|
|
1472
|
+
inputSchema: z33.object({
|
|
1473
|
+
noteId: z33.string().describe("The note (Thought) ID"),
|
|
1474
|
+
headingText: z33.string().min(1).describe("Exact text of the heading whose section will be deleted")
|
|
1663
1475
|
})
|
|
1664
1476
|
},
|
|
1665
1477
|
async ({ noteId, headingText }) => {
|
|
@@ -1674,7 +1486,7 @@ function registerNoteDeleteSection(server2, client2) {
|
|
|
1674
1486
|
}
|
|
1675
1487
|
|
|
1676
1488
|
// ../mcp-core/src/tools/note-replace.ts
|
|
1677
|
-
import { z as
|
|
1489
|
+
import { z as z34 } from "zod";
|
|
1678
1490
|
function registerNoteReplace(server2, client2) {
|
|
1679
1491
|
server2.registerTool(
|
|
1680
1492
|
"naumu_note_replace",
|
|
@@ -1682,9 +1494,9 @@ function registerNoteReplace(server2, client2) {
|
|
|
1682
1494
|
title: "Replace Note",
|
|
1683
1495
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
|
|
1684
1496
|
description: "\u26A0 DESTRUCTIVE: replace the entire note content with new markdown; ONLY use when the user explicitly asks to rewrite/replace the whole note. Any concurrent human edits made during the call are silently overwritten. For additive work prefer `naumu_note_append`. For section-level edits use `naumu_note_replace_section`. For inline tweaks use `naumu_note_find_replace`. Read with `naumu_note_read` first if you weren't the last writer.",
|
|
1685
|
-
inputSchema:
|
|
1686
|
-
noteId:
|
|
1687
|
-
markdown:
|
|
1497
|
+
inputSchema: z34.object({
|
|
1498
|
+
noteId: z34.string().describe("The note (Thought) ID"),
|
|
1499
|
+
markdown: z34.string().describe("New markdown content for the entire note")
|
|
1688
1500
|
})
|
|
1689
1501
|
},
|
|
1690
1502
|
async ({ noteId, markdown }) => {
|
|
@@ -1697,7 +1509,7 @@ function registerNoteReplace(server2, client2) {
|
|
|
1697
1509
|
}
|
|
1698
1510
|
|
|
1699
1511
|
// ../mcp-core/src/tools/note-find-replace.ts
|
|
1700
|
-
import { z as
|
|
1512
|
+
import { z as z35 } from "zod";
|
|
1701
1513
|
function registerNoteFindReplace(server2, client2) {
|
|
1702
1514
|
server2.registerTool(
|
|
1703
1515
|
"naumu_note_find_replace",
|
|
@@ -1705,11 +1517,11 @@ function registerNoteFindReplace(server2, client2) {
|
|
|
1705
1517
|
title: "Find/Replace in Note",
|
|
1706
1518
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
|
|
1707
1519
|
description: "Literal find/replace within a note's text content; use for mid-paragraph tweaks the section-based tools can't target. Marks (bold, italic, code, etc.) are preserved on the surrounding text. \u26A0 The match is literal-substring across every text leaf in the doc; an overly generic `find` (e.g. \" a \") can rewrite the doc unrecognizably. Pick a phrase distinctive enough to land where you mean. By default replaces every occurrence; set `all: false` for first-only. Returns `{ replacements }` so you can sanity-check the count.",
|
|
1708
|
-
inputSchema:
|
|
1709
|
-
noteId:
|
|
1710
|
-
find:
|
|
1711
|
-
replace:
|
|
1712
|
-
all:
|
|
1520
|
+
inputSchema: z35.object({
|
|
1521
|
+
noteId: z35.string().describe("The note (Thought) ID"),
|
|
1522
|
+
find: z35.string().min(1).describe("Substring to search for. Literal - no regex."),
|
|
1523
|
+
replace: z35.string().describe("Replacement string. May be empty to delete the match."),
|
|
1524
|
+
all: z35.boolean().optional().describe("Replace all occurrences (default true). Pass false to replace only the first.")
|
|
1713
1525
|
})
|
|
1714
1526
|
},
|
|
1715
1527
|
async ({ noteId, find, replace, all }) => {
|
|
@@ -1725,107 +1537,8 @@ function registerNoteFindReplace(server2, client2) {
|
|
|
1725
1537
|
);
|
|
1726
1538
|
}
|
|
1727
1539
|
|
|
1728
|
-
// ../mcp-core/src/tools/canvas-add-element.ts
|
|
1729
|
-
import { z as z41 } from "zod";
|
|
1730
|
-
var ELEMENT_TYPES = [
|
|
1731
|
-
"rectangle",
|
|
1732
|
-
"ellipse",
|
|
1733
|
-
"diamond",
|
|
1734
|
-
"text",
|
|
1735
|
-
"line",
|
|
1736
|
-
"arrow",
|
|
1737
|
-
"freehand",
|
|
1738
|
-
"image",
|
|
1739
|
-
"bookmark-card",
|
|
1740
|
-
"entity-embed"
|
|
1741
|
-
];
|
|
1742
|
-
function registerCanvasAddElement(server2, client2) {
|
|
1743
|
-
server2.registerTool(
|
|
1744
|
-
"naumu_canvas_add_element",
|
|
1745
|
-
{
|
|
1746
|
-
title: "Add Canvas Element",
|
|
1747
|
-
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
1748
|
-
description: "Add a new element to a canvas; use to draw a shape, text, or embed onto a drawing surface. Other participants see your colored cursor at the element's center while it lands. The server fills in `id`, `version`, `fractionalIndex`, and `seed` automatically - pass only `type`, position (`x`, `y`), and size (`width`, `height`); other fields are optional and have sensible defaults (stroke #1e1e1e, no fill, opacity 1, etc.). For text elements, set `label` and `fontSize`. Coordinates are canvas-space (the same units the live editor uses).",
|
|
1749
|
-
inputSchema: z41.object({
|
|
1750
|
-
canvasId: z41.string().describe("The canvas ID"),
|
|
1751
|
-
element: z41.object({
|
|
1752
|
-
type: z41.enum(ELEMENT_TYPES).describe("Element shape"),
|
|
1753
|
-
x: z41.number().describe("Top-left x coordinate in canvas space"),
|
|
1754
|
-
y: z41.number().describe("Top-left y coordinate in canvas space"),
|
|
1755
|
-
width: z41.number().describe("Width in canvas units"),
|
|
1756
|
-
height: z41.number().describe("Height in canvas units"),
|
|
1757
|
-
strokeColor: z41.string().optional().describe("Stroke color (hex). Default #1e1e1e."),
|
|
1758
|
-
fillColor: z41.string().optional().describe('Fill color (hex) or "transparent". Default transparent.'),
|
|
1759
|
-
strokeWidth: z41.number().optional().describe("Stroke width. Default 2."),
|
|
1760
|
-
opacity: z41.number().min(0).max(1).optional().describe("0..1, default 1"),
|
|
1761
|
-
roughness: z41.number().min(0).max(2).optional().describe("Hand-drawn roughness 0..2. Default 1."),
|
|
1762
|
-
label: z41.string().optional().describe("Optional label/text content"),
|
|
1763
|
-
labelFontSize: z41.number().optional().describe("Label font size"),
|
|
1764
|
-
angle: z41.number().optional().describe("Rotation in radians. Default 0.")
|
|
1765
|
-
}).passthrough().describe("Element fields. Pass only what you set - defaults fill the rest.")
|
|
1766
|
-
})
|
|
1767
|
-
},
|
|
1768
|
-
async ({ canvasId, element }) => {
|
|
1769
|
-
const data = await client2.post(`/api/canvases/${canvasId}/elements`, { element });
|
|
1770
|
-
return {
|
|
1771
|
-
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
1772
|
-
};
|
|
1773
|
-
}
|
|
1774
|
-
);
|
|
1775
|
-
}
|
|
1776
|
-
|
|
1777
|
-
// ../mcp-core/src/tools/canvas-update-element.ts
|
|
1778
|
-
import { z as z42 } from "zod";
|
|
1779
|
-
function registerCanvasUpdateElement(server2, client2) {
|
|
1780
|
-
server2.registerTool(
|
|
1781
|
-
"naumu_canvas_update_element",
|
|
1782
|
-
{
|
|
1783
|
-
title: "Update Canvas Element",
|
|
1784
|
-
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
|
|
1785
|
-
description: "Patch an existing canvas element; use to move, resize, recolor, or relabel a shape already on the canvas. Only the fields you pass in `changes` are updated - `id`, `version`, `createdBy`, and `isDeleted` are server-managed and ignored if present. Useful for moving (`x`, `y`), resizing (`width`, `height`), recoloring (`strokeColor`, `fillColor`), or relabeling (`label`).",
|
|
1786
|
-
inputSchema: z42.object({
|
|
1787
|
-
canvasId: z42.string().describe("The canvas ID"),
|
|
1788
|
-
elementId: z42.string().describe("The element ID returned by `naumu_canvas_add_element` or `naumu_get_canvas_elements`"),
|
|
1789
|
-
changes: z42.record(z42.string(), z42.unknown()).describe("Partial element fields to merge in. Server bumps `version` automatically.")
|
|
1790
|
-
})
|
|
1791
|
-
},
|
|
1792
|
-
async ({ canvasId, elementId, changes }) => {
|
|
1793
|
-
const data = await client2.patch(
|
|
1794
|
-
`/api/canvases/${canvasId}/elements/${elementId}`,
|
|
1795
|
-
{ changes }
|
|
1796
|
-
);
|
|
1797
|
-
return {
|
|
1798
|
-
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
1799
|
-
};
|
|
1800
|
-
}
|
|
1801
|
-
);
|
|
1802
|
-
}
|
|
1803
|
-
|
|
1804
|
-
// ../mcp-core/src/tools/canvas-remove-element.ts
|
|
1805
|
-
import { z as z43 } from "zod";
|
|
1806
|
-
function registerCanvasRemoveElement(server2, client2) {
|
|
1807
|
-
server2.registerTool(
|
|
1808
|
-
"naumu_canvas_remove_element",
|
|
1809
|
-
{
|
|
1810
|
-
title: "Remove Canvas Element",
|
|
1811
|
-
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
|
|
1812
|
-
description: "Soft-delete a canvas element; use to remove a shape from a canvas. The element is tombstoned (isDeleted=true) so concurrent edits don't resurrect it. 404 if the element id is not present on this canvas.",
|
|
1813
|
-
inputSchema: z43.object({
|
|
1814
|
-
canvasId: z43.string().describe("The canvas ID"),
|
|
1815
|
-
elementId: z43.string().describe("The element ID to delete")
|
|
1816
|
-
})
|
|
1817
|
-
},
|
|
1818
|
-
async ({ canvasId, elementId }) => {
|
|
1819
|
-
const data = await client2.del(`/api/canvases/${canvasId}/elements/${elementId}`);
|
|
1820
|
-
return {
|
|
1821
|
-
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
1822
|
-
};
|
|
1823
|
-
}
|
|
1824
|
-
);
|
|
1825
|
-
}
|
|
1826
|
-
|
|
1827
1540
|
// ../mcp-core/src/tools/create-note.ts
|
|
1828
|
-
import { z as
|
|
1541
|
+
import { z as z36 } from "zod";
|
|
1829
1542
|
function registerCreateNote(server2, client2) {
|
|
1830
1543
|
server2.registerTool(
|
|
1831
1544
|
"naumu_create_note",
|
|
@@ -1833,9 +1546,9 @@ function registerCreateNote(server2, client2) {
|
|
|
1833
1546
|
title: "Create Note",
|
|
1834
1547
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
1835
1548
|
description: "Create a new empty note in a graph; use when you need a fresh note to write into. Returns the new note row including its `id` - pass that id to `naumu_note_append` / `naumu_note_replace` to fill in the content. Bots can only create notes in their own graph.",
|
|
1836
|
-
inputSchema:
|
|
1837
|
-
graphId:
|
|
1838
|
-
title:
|
|
1549
|
+
inputSchema: z36.object({
|
|
1550
|
+
graphId: z36.string().describe("The graph ID to create the note in"),
|
|
1551
|
+
title: z36.string().optional().describe("Optional title for the note")
|
|
1839
1552
|
})
|
|
1840
1553
|
},
|
|
1841
1554
|
async ({ graphId, title }) => {
|
|
@@ -1847,31 +1560,8 @@ function registerCreateNote(server2, client2) {
|
|
|
1847
1560
|
);
|
|
1848
1561
|
}
|
|
1849
1562
|
|
|
1850
|
-
// ../mcp-core/src/tools/create-canvas.ts
|
|
1851
|
-
import { z as z45 } from "zod";
|
|
1852
|
-
function registerCreateCanvas(server2, client2) {
|
|
1853
|
-
server2.registerTool(
|
|
1854
|
-
"naumu_create_canvas",
|
|
1855
|
-
{
|
|
1856
|
-
title: "Create Canvas",
|
|
1857
|
-
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
1858
|
-
description: "Create a new empty canvas in a graph; use when you need a fresh drawing surface. Returns the new canvas row including its `id` - pass that id to `naumu_canvas_add_element` to start drawing. Bots can only create canvases in their own graph.",
|
|
1859
|
-
inputSchema: z45.object({
|
|
1860
|
-
graphId: z45.string().describe("The graph ID to create the canvas in"),
|
|
1861
|
-
title: z45.string().optional().describe("Optional title for the canvas")
|
|
1862
|
-
})
|
|
1863
|
-
},
|
|
1864
|
-
async ({ graphId, title }) => {
|
|
1865
|
-
const data = await client2.post("/api/canvases", { graphId, title });
|
|
1866
|
-
return {
|
|
1867
|
-
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
1868
|
-
};
|
|
1869
|
-
}
|
|
1870
|
-
);
|
|
1871
|
-
}
|
|
1872
|
-
|
|
1873
1563
|
// ../mcp-core/src/tools/list-schema-violations.ts
|
|
1874
|
-
import { z as
|
|
1564
|
+
import { z as z37 } from "zod";
|
|
1875
1565
|
var DEFAULT_EXAMPLE_LIMIT = 5;
|
|
1876
1566
|
var rowsForKind = (violations, kind) => {
|
|
1877
1567
|
const rows = [];
|
|
@@ -1895,14 +1585,14 @@ function registerListSchemaViolations(server2, client2) {
|
|
|
1895
1585
|
"naumu_list_schema_violations",
|
|
1896
1586
|
{
|
|
1897
1587
|
title: "List Schema Violations",
|
|
1898
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
1588
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
1899
1589
|
description: "Audit a graph against its schema. By default returns a compact summary: total counts plus, for each violation kind, its count and up to 5 example nodes (id/label/type/message) \u2014 small enough not to flood the client. Violation kinds: parent_missing (schema expects a parent edge that does not exist), parent_multiple (more than one parent edge where one is expected), parent_mismatch (parent edge has wrong target type or relation label), parent_not_backbone (an edge uses a backbone/parent relation but is not stored as a backbone edge, so the subtree stays off the hierarchy), unknown_relation (edge uses a relation not in the schema), invalid_connection_target (edge connects to a type the schema does not allow for this source), unknown_type (node carries a type no longer in the schema), disconnected (node heads a group with no backbone path to the main tree). To see every node for one kind, pass `kind` to filter; `limit` caps how many rows are returned (examples in the default summary, or full rows when `kind` is set). Use for audits, import-verification, and CI-style checks after batch writes.",
|
|
1900
|
-
inputSchema:
|
|
1901
|
-
graphId:
|
|
1902
|
-
kind:
|
|
1590
|
+
inputSchema: z37.object({
|
|
1591
|
+
graphId: z37.string().describe("The graph ID"),
|
|
1592
|
+
kind: z37.string().optional().describe(
|
|
1903
1593
|
'Drill into one violation kind (e.g. "parent_not_backbone"). Returns the full list of nodes with that kind, up to `limit`, instead of the summary.'
|
|
1904
1594
|
),
|
|
1905
|
-
limit:
|
|
1595
|
+
limit: z37.number().int().min(1).optional().describe(
|
|
1906
1596
|
"Max rows to return. When `kind` is set, caps the full drill-down list (default: all). Otherwise caps example nodes per kind in the summary (default: 5)."
|
|
1907
1597
|
)
|
|
1908
1598
|
})
|
|
@@ -1954,18 +1644,18 @@ function registerListSchemaViolations(server2, client2) {
|
|
|
1954
1644
|
}
|
|
1955
1645
|
|
|
1956
1646
|
// ../mcp-core/src/tools/list-dense-nodes.ts
|
|
1957
|
-
import { z as
|
|
1647
|
+
import { z as z38 } from "zod";
|
|
1958
1648
|
function registerListDenseNodes(server2, client2) {
|
|
1959
1649
|
server2.registerTool(
|
|
1960
1650
|
"naumu_list_dense_nodes",
|
|
1961
1651
|
{
|
|
1962
1652
|
title: "List Dense Nodes",
|
|
1963
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
1964
|
-
description: 'Return nodes whose
|
|
1965
|
-
inputSchema:
|
|
1966
|
-
graphId:
|
|
1967
|
-
minConnections:
|
|
1968
|
-
nodeTypes:
|
|
1653
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
1654
|
+
description: 'Return nodes whose child count (children via parent edges; mesh cross-links don\'t count) is \u2265 minConnections, grouped by type; use for /restructure hub detection. Each row includes `same_typed_child_count` - the number of children of the SAME type as the node (the Naumu hub-pattern signal) and `connection_count` - its total children. Sort the response by `same_typed_child_count` descending and route any node with \u226510 same-typed children through a mini-hub split. Pass `nodeTypes` (comma-separated) to restrict to a subset (e.g. ["Type A","Type B"]). Cheap to call - runs a single Cypher aggregation.',
|
|
1655
|
+
inputSchema: z38.object({
|
|
1656
|
+
graphId: z38.string().describe("The graph ID"),
|
|
1657
|
+
minConnections: z38.number().int().min(1).describe("Minimum number of children (parent edges; mesh cross-links excluded). Typical: 10 for hub detection, 11 to count only hubs that exceed the round-4 \u226410 threshold."),
|
|
1658
|
+
nodeTypes: z38.array(z38.string()).optional().describe("Optional list of node types to restrict the scan to.")
|
|
1969
1659
|
})
|
|
1970
1660
|
},
|
|
1971
1661
|
async ({ graphId, minConnections, nodeTypes }) => {
|
|
@@ -1983,19 +1673,19 @@ function registerListDenseNodes(server2, client2) {
|
|
|
1983
1673
|
}
|
|
1984
1674
|
|
|
1985
1675
|
// ../mcp-core/src/tools/list-node-connections.ts
|
|
1986
|
-
import { z as
|
|
1676
|
+
import { z as z39 } from "zod";
|
|
1987
1677
|
function registerListNodeConnections(server2, client2) {
|
|
1988
1678
|
server2.registerTool(
|
|
1989
1679
|
"naumu_list_node_connections",
|
|
1990
1680
|
{
|
|
1991
1681
|
title: "List Node Connections",
|
|
1992
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
1682
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
1993
1683
|
description: 'Return a single node\'s edges (non-system) with the connected node on the other side; use during /restructure to confirm mini-hub candidates and verify reparenting outcomes. Filter with `edgeType` (relation label) and `direction` ("in" | "out" | "both", default both). Response: `{ node: {id,label,type}, edges: [{relation, direction, isParent, other: {id,label,type}}] }`.',
|
|
1994
|
-
inputSchema:
|
|
1995
|
-
graphId:
|
|
1996
|
-
nodeId:
|
|
1997
|
-
edgeType:
|
|
1998
|
-
direction:
|
|
1684
|
+
inputSchema: z39.object({
|
|
1685
|
+
graphId: z39.string().describe("The graph ID"),
|
|
1686
|
+
nodeId: z39.string().describe("The node ID to inspect"),
|
|
1687
|
+
edgeType: z39.string().optional().describe('Restrict to a specific relation label (e.g. "ASSOCIATED_WITH"). Case-insensitive; non-alphanum chars are normalized.'),
|
|
1688
|
+
direction: z39.enum(["in", "out", "both"]).optional().describe('Edge direction filter - "in" (incoming), "out" (outgoing), "both" (default).')
|
|
1999
1689
|
})
|
|
2000
1690
|
},
|
|
2001
1691
|
async ({ graphId, nodeId, edgeType, direction }) => {
|
|
@@ -2013,7 +1703,7 @@ function registerListNodeConnections(server2, client2) {
|
|
|
2013
1703
|
}
|
|
2014
1704
|
|
|
2015
1705
|
// ../mcp-core/src/tools/reparent.ts
|
|
2016
|
-
import { z as
|
|
1706
|
+
import { z as z40 } from "zod";
|
|
2017
1707
|
function registerReparent(server2, client2) {
|
|
2018
1708
|
server2.registerTool(
|
|
2019
1709
|
"naumu_reparent",
|
|
@@ -2021,11 +1711,11 @@ function registerReparent(server2, client2) {
|
|
|
2021
1711
|
title: "Reparent Node",
|
|
2022
1712
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
2023
1713
|
description: 'Atomically swap a node\'s parent edge; use to move a child under a different parent (e.g. during /restructure to reparent children under newly-created mini-hubs). Deletes any existing `isParent: true` edges on the node and creates a new one to `newParentId` with relation `newRelation`. Preserves the node\'s id, content, attributes, and embedding - does NOT trigger embedding regeneration because only the parent edge changes. Idempotent: if the node already has the requested parent edge, response is `status: "skipped"`. Response shape: `{nodeId, oldParentId, newParentId, newRelation, status: "moved" | "skipped"}`.',
|
|
2024
|
-
inputSchema:
|
|
2025
|
-
graphId:
|
|
2026
|
-
nodeId:
|
|
2027
|
-
newParentId:
|
|
2028
|
-
newRelation:
|
|
1714
|
+
inputSchema: z40.object({
|
|
1715
|
+
graphId: z40.string().describe("The graph ID"),
|
|
1716
|
+
nodeId: z40.string().describe("The child node to reparent"),
|
|
1717
|
+
newParentId: z40.string().describe("The new parent node id"),
|
|
1718
|
+
newRelation: z40.string().describe('The new parent edge relation label (e.g. "PART_OF"). Must be valid per the schema for (child.type, relation, parent.type).')
|
|
2029
1719
|
})
|
|
2030
1720
|
},
|
|
2031
1721
|
async ({ graphId, nodeId, newParentId, newRelation }) => {
|
|
@@ -2041,7 +1731,7 @@ function registerReparent(server2, client2) {
|
|
|
2041
1731
|
}
|
|
2042
1732
|
|
|
2043
1733
|
// ../mcp-core/src/tools/batch-reparent.ts
|
|
2044
|
-
import { z as
|
|
1734
|
+
import { z as z41 } from "zod";
|
|
2045
1735
|
function registerBatchReparent(server2, client2) {
|
|
2046
1736
|
server2.registerTool(
|
|
2047
1737
|
"naumu_batch_reparent",
|
|
@@ -2049,11 +1739,11 @@ function registerBatchReparent(server2, client2) {
|
|
|
2049
1739
|
title: "Batch Reparent Nodes",
|
|
2050
1740
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
2051
1741
|
description: 'Reparent 1-25 nodes onto a shared `newParentId` with the same `newRelation`; use to move a same-typed cluster under a freshly-created mini-hub in /restructure. Same semantics as `naumu_reparent` per-node: atomic swap of the isParent edge, preserves id/content/attributes/embedding, no re-embedding. Idempotent per node (already-parented nodes return `status: "skipped"`). Per-node response array: `[{nodeId, oldParentId, newParentId, status: "moved" | "skipped" | "error", error?}]`.',
|
|
2052
|
-
inputSchema:
|
|
2053
|
-
graphId:
|
|
2054
|
-
newParentId:
|
|
2055
|
-
newRelation:
|
|
2056
|
-
nodeIds:
|
|
1742
|
+
inputSchema: z41.object({
|
|
1743
|
+
graphId: z41.string().describe("The graph ID"),
|
|
1744
|
+
newParentId: z41.string().describe("Parent node id every nodeId in the batch will be parented to"),
|
|
1745
|
+
newRelation: z41.string().describe("Parent edge relation label (must be valid per schema for child.type \u2192 parent.type)"),
|
|
1746
|
+
nodeIds: z41.array(z41.string()).min(1).max(25).describe("1\u201325 child node ids to reparent under `newParentId`")
|
|
2057
1747
|
})
|
|
2058
1748
|
},
|
|
2059
1749
|
async ({ graphId, newParentId, newRelation, nodeIds }) => {
|
|
@@ -2070,7 +1760,7 @@ function registerBatchReparent(server2, client2) {
|
|
|
2070
1760
|
}
|
|
2071
1761
|
|
|
2072
1762
|
// ../mcp-core/src/tools/chatgpt-search.ts
|
|
2073
|
-
import { z as
|
|
1763
|
+
import { z as z42 } from "zod";
|
|
2074
1764
|
|
|
2075
1765
|
// ../mcp-core/src/public-origin.ts
|
|
2076
1766
|
function publicOrigin() {
|
|
@@ -2122,10 +1812,10 @@ function registerChatgptSearch(server2, client2) {
|
|
|
2122
1812
|
"search",
|
|
2123
1813
|
{
|
|
2124
1814
|
title: "Search",
|
|
2125
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
1815
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
2126
1816
|
description: "Search across all of the knowledge graphs (spaces) you can access and return the most relevant nodes. Returns `{ results: [{ id, title, url }] }`. Pass each result `id` to the `fetch` tool to read the full node. (This is the cross-space entry point for ChatGPT/Deep Research; within a single space, `naumu_search` exposes more controls.)",
|
|
2127
|
-
inputSchema:
|
|
2128
|
-
query:
|
|
1817
|
+
inputSchema: z42.object({
|
|
1818
|
+
query: z42.string().describe('Search query text. Mix synonyms and exact tokens freely (e.g. "auth login SSO 2fa").')
|
|
2129
1819
|
})
|
|
2130
1820
|
},
|
|
2131
1821
|
async ({ query }) => {
|
|
@@ -2157,7 +1847,7 @@ function registerChatgptSearch(server2, client2) {
|
|
|
2157
1847
|
}
|
|
2158
1848
|
|
|
2159
1849
|
// ../mcp-core/src/tools/chatgpt-fetch.ts
|
|
2160
|
-
import { z as
|
|
1850
|
+
import { z as z43 } from "zod";
|
|
2161
1851
|
var NON_ATTRIBUTE_PROPS = /* @__PURE__ */ new Set([
|
|
2162
1852
|
"id",
|
|
2163
1853
|
"label",
|
|
@@ -2220,10 +1910,10 @@ function registerChatgptFetch(server2, client2) {
|
|
|
2220
1910
|
"fetch",
|
|
2221
1911
|
{
|
|
2222
1912
|
title: "Fetch",
|
|
2223
|
-
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
1913
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
2224
1914
|
description: "Fetch the full contents of a node returned by the `search` tool. Pass the result `id` verbatim (format `<graphId>:<nodeId>`). Returns `{ id, title, text, url }` where `text` is the node content plus its type, attributes, and connections.",
|
|
2225
|
-
inputSchema:
|
|
2226
|
-
id:
|
|
1915
|
+
inputSchema: z43.object({
|
|
1916
|
+
id: z43.string().describe("A resource id from a previous `search` result, in the form `<graphId>:<nodeId>`.")
|
|
2227
1917
|
})
|
|
2228
1918
|
},
|
|
2229
1919
|
async ({ id }) => {
|
|
@@ -2277,8 +1967,6 @@ var TOOL_REGISTRARS = {
|
|
|
2277
1967
|
naumu_search: registerSearch,
|
|
2278
1968
|
naumu_filter: registerFilter,
|
|
2279
1969
|
naumu_get_node: registerGetNode,
|
|
2280
|
-
naumu_get_view: registerGetView,
|
|
2281
|
-
naumu_list_view_nodes: registerListViewNodes,
|
|
2282
1970
|
naumu_add_node: registerAddNode,
|
|
2283
1971
|
naumu_update_node: registerUpdateNode,
|
|
2284
1972
|
naumu_add_edge: registerAddEdge,
|
|
@@ -2288,9 +1976,6 @@ var TOOL_REGISTRARS = {
|
|
|
2288
1976
|
naumu_ask: registerAsk,
|
|
2289
1977
|
naumu_delegate: registerDelegate,
|
|
2290
1978
|
// naumu_traverse omitted on purpose — backend stub returns 503 (see import note).
|
|
2291
|
-
naumu_list_canvases: registerListCanvases,
|
|
2292
|
-
naumu_get_canvas_elements: registerGetCanvasElements,
|
|
2293
|
-
naumu_get_canvas_image: registerGetCanvasImage,
|
|
2294
1979
|
naumu_post_message: registerPostMessage,
|
|
2295
1980
|
naumu_read_thread: registerReadThread,
|
|
2296
1981
|
naumu_whoami: registerWhoami,
|
|
@@ -2308,11 +1993,7 @@ var TOOL_REGISTRARS = {
|
|
|
2308
1993
|
naumu_note_delete_section: registerNoteDeleteSection,
|
|
2309
1994
|
naumu_note_replace: registerNoteReplace,
|
|
2310
1995
|
naumu_note_find_replace: registerNoteFindReplace,
|
|
2311
|
-
naumu_canvas_add_element: registerCanvasAddElement,
|
|
2312
|
-
naumu_canvas_update_element: registerCanvasUpdateElement,
|
|
2313
|
-
naumu_canvas_remove_element: registerCanvasRemoveElement,
|
|
2314
1996
|
naumu_create_note: registerCreateNote,
|
|
2315
|
-
naumu_create_canvas: registerCreateCanvas,
|
|
2316
1997
|
naumu_list_schema_violations: registerListSchemaViolations,
|
|
2317
1998
|
naumu_list_dense_nodes: registerListDenseNodes,
|
|
2318
1999
|
naumu_list_node_connections: registerListNodeConnections,
|
package/package.json
CHANGED