@naumu/mcp 0.15.0 → 0.16.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 +72 -9
- package/package.json +1 -1
- package/server.json +2 -2
package/dist/index.js
CHANGED
|
@@ -41,7 +41,7 @@ function parseRetryAfterSeconds(retryAfter) {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
// ../mcp-core/src/version.ts
|
|
44
|
-
var NAUMU_MCP_VERSION = "0.
|
|
44
|
+
var NAUMU_MCP_VERSION = "0.16.0";
|
|
45
45
|
|
|
46
46
|
// ../mcp-core/src/client.ts
|
|
47
47
|
var HEADER_VALUE_MAX_LENGTH = 100;
|
|
@@ -385,6 +385,54 @@ function registerGetSchema(server2, client2) {
|
|
|
385
385
|
|
|
386
386
|
// ../mcp-core/src/tools/update-schema.ts
|
|
387
387
|
import { z as z5 } from "zod";
|
|
388
|
+
|
|
389
|
+
// ../mcp-core/src/tools/reserved-names.ts
|
|
390
|
+
var RESERVED_ATTRIBUTE_NAMES = /* @__PURE__ */ new Set([
|
|
391
|
+
// RESERVED_ATTRIBUTE_KEYS
|
|
392
|
+
"id",
|
|
393
|
+
"label",
|
|
394
|
+
"type",
|
|
395
|
+
"content",
|
|
396
|
+
"embedding",
|
|
397
|
+
"visibility",
|
|
398
|
+
"source",
|
|
399
|
+
"graphid",
|
|
400
|
+
// CASED_SYSTEM_NODE_KEYS (lowercased)
|
|
401
|
+
"sortkey",
|
|
402
|
+
"createdat",
|
|
403
|
+
"updatedat",
|
|
404
|
+
"createdby",
|
|
405
|
+
"createdbyuserid",
|
|
406
|
+
"editableby",
|
|
407
|
+
"lastmodifiedat",
|
|
408
|
+
"lastmodifiedby",
|
|
409
|
+
"lastactivityat",
|
|
410
|
+
"heatscore",
|
|
411
|
+
"heatobserved",
|
|
412
|
+
"heatexpected",
|
|
413
|
+
"heatsurprise",
|
|
414
|
+
"heatcomputedat",
|
|
415
|
+
"heatconvsignal",
|
|
416
|
+
"heatconvcomputedat",
|
|
417
|
+
"__indexcolor",
|
|
418
|
+
// Canvas / force-layout scratch props
|
|
419
|
+
"x",
|
|
420
|
+
"y",
|
|
421
|
+
"vx",
|
|
422
|
+
"vy",
|
|
423
|
+
"fx",
|
|
424
|
+
"fy",
|
|
425
|
+
"index"
|
|
426
|
+
]);
|
|
427
|
+
function isReservedAttributeName(name) {
|
|
428
|
+
return RESERVED_ATTRIBUTE_NAMES.has(name.toLowerCase());
|
|
429
|
+
}
|
|
430
|
+
function reservedAttributeNameError(name, where) {
|
|
431
|
+
const scope = where ? ` (type "${where}")` : "";
|
|
432
|
+
return `Attribute name "${name}" is reserved by Naumu (system property)${scope}. Choose a different name.`;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// ../mcp-core/src/tools/update-schema.ts
|
|
388
436
|
var ConnectionSchema = z5.object({
|
|
389
437
|
relation: z5.string().describe("UPPER_SNAKE_CASE relation name (e.g. WORKS_AT, BUILT_BY, BELONGS_TO)"),
|
|
390
438
|
target_node: z5.string().optional().describe("Target type name. Omit when polymorphic=true."),
|
|
@@ -396,7 +444,12 @@ var AttributeValueSchema = z5.object({
|
|
|
396
444
|
description: z5.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.')
|
|
397
445
|
});
|
|
398
446
|
var AttributeSchema = z5.object({
|
|
399
|
-
|
|
447
|
+
// Reserved system property names (`source`, `type`, `createdAt`, `x`, ...)
|
|
448
|
+
// are rejected here so the agent gets a field-level error instead of a
|
|
449
|
+
// blanket 400 from the backend. See ./reserved-names.ts.
|
|
450
|
+
name: z5.string().describe('Attribute key (e.g. "stage", "status", "category")').refine((n) => !isReservedAttributeName(n), {
|
|
451
|
+
error: (iss) => reservedAttributeNameError(String(iss.input))
|
|
452
|
+
}),
|
|
400
453
|
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.'),
|
|
401
454
|
values: z5.array(AttributeValueSchema).describe("Allowed enum values for select/multiselect; pass [] for string/number/date."),
|
|
402
455
|
description: z5.string().optional().describe("Short note explaining what this attribute captures and how it differs from similarly-named attributes elsewhere in the schema. Strongly encouraged.")
|
|
@@ -594,6 +647,12 @@ function registerAddAttribute(server2, client2) {
|
|
|
594
647
|
})
|
|
595
648
|
},
|
|
596
649
|
async ({ graphId, node_type, name, type, values, description }) => {
|
|
650
|
+
if (isReservedAttributeName(name)) {
|
|
651
|
+
return {
|
|
652
|
+
content: [{ type: "text", text: JSON.stringify({ error: reservedAttributeNameError(name, node_type) }, null, 2) }],
|
|
653
|
+
isError: true
|
|
654
|
+
};
|
|
655
|
+
}
|
|
597
656
|
const current = await client2.get(`/api/graphs/${graphId}/schema`);
|
|
598
657
|
const schema = current.definition ? JSON.parse(current.definition) : { nodes: [] };
|
|
599
658
|
const node = schema.nodes.find((n) => n.type === node_type);
|
|
@@ -955,7 +1014,7 @@ Use naumu_get_schema to check valid attributes and values for this node type.`
|
|
|
955
1014
|
}
|
|
956
1015
|
|
|
957
1016
|
// ../mcp-core/src/tools/add-node.ts
|
|
958
|
-
var RESERVED_KEYS = /* @__PURE__ */ new Set(["id", "label", "type", "content"]);
|
|
1017
|
+
var RESERVED_KEYS = /* @__PURE__ */ new Set(["id", "label", "type", "content", "source"]);
|
|
959
1018
|
function normalizeNodeAttributes(schema, nodeType, attributes) {
|
|
960
1019
|
const attrMap = /* @__PURE__ */ new Map();
|
|
961
1020
|
const nodeDef = schema.nodes.find((n) => n.type === nodeType);
|
|
@@ -1237,23 +1296,27 @@ function registerDelegate(server2, client2) {
|
|
|
1237
1296
|
idempotentHint: false,
|
|
1238
1297
|
openWorldHint: true
|
|
1239
1298
|
},
|
|
1240
|
-
description: 'Hand @Naumu a task to carry out asynchronously: add knowledge, make graph-aware changes, or record a status update (e.g. "mark task X done", "log this deployment"). Returns immediately with a threadId; @Naumu works in the background and may take seconds to minutes. For status reports you can fire and forget. To read what @Naumu did, poll naumu_read_thread with the returned threadId. When you instead need an answer synchronously, use naumu_ask.
|
|
1299
|
+
description: 'Hand @Naumu a task to carry out asynchronously: add knowledge, make graph-aware changes, or record a status update (e.g. "mark task X done", "log this deployment"). Returns immediately with a threadId; @Naumu works in the background and may take seconds to minutes. For status reports you can fire and forget. To read what @Naumu did, poll naumu_read_thread with the returned threadId. When you instead need an answer synchronously, use naumu_ask. A new thread is visible to the whole space by default (it lands in the space\'s #misc feed), so delegated work reads as a shared work log. File it into specific topics instead by passing `topicIds` (see naumu_list_topics), or pass `private: true` to keep it between you and @Naumu. This always invokes @Naumu, even in threads where auto-response is paused, so the task text must never contain a literal "@Naumu" mention (plain text never renders or triggers a mention).',
|
|
1241
1300
|
inputSchema: z20.object({
|
|
1242
1301
|
graphId: z20.string().describe("The space (graph) id to act in."),
|
|
1243
1302
|
task: z20.string().describe("What you want @Naumu to do, add, or record."),
|
|
1244
1303
|
threadId: z20.string().optional().describe("Continue an existing conversation; omit to start a new one."),
|
|
1245
1304
|
topicIds: z20.array(z20.string()).max(8).optional().describe(
|
|
1246
|
-
"Topic ids (from naumu_list_topics) to file a NEW thread into, making it visible to those topics' members. Only used at creation; never adds topics to an existing thread, so it is ignored when threadId is provided. Omit to
|
|
1305
|
+
"Topic ids (from naumu_list_topics) to file a NEW thread into, making it visible to those topics' members. Only used at creation; never adds topics to an existing thread, so it is ignored when threadId is provided. Omit to share the thread with the whole space instead."
|
|
1306
|
+
),
|
|
1307
|
+
private: z20.boolean().optional().describe(
|
|
1308
|
+
"Keep a NEW thread between you and @Naumu instead of sharing it with the space. Default false. Only used at creation; ignored when threadId or topicIds are provided."
|
|
1247
1309
|
)
|
|
1248
1310
|
})
|
|
1249
1311
|
},
|
|
1250
|
-
async ({ graphId, task, threadId, topicIds }) => {
|
|
1312
|
+
async ({ graphId, task, threadId, topicIds, private: isPrivate }) => {
|
|
1251
1313
|
try {
|
|
1252
1314
|
let resolvedThreadId = threadId;
|
|
1253
1315
|
if (!resolvedThreadId) {
|
|
1316
|
+
const hasTopics = Boolean(topicIds && topicIds.length > 0);
|
|
1254
1317
|
const thread = await client2.post("/api/threads", {
|
|
1255
1318
|
graphId,
|
|
1256
|
-
...
|
|
1319
|
+
...hasTopics ? { topicIds } : { sharedWithSpace: !isPrivate }
|
|
1257
1320
|
});
|
|
1258
1321
|
resolvedThreadId = thread.id;
|
|
1259
1322
|
}
|
|
@@ -1385,7 +1448,7 @@ function registerReadThread(server2, client2) {
|
|
|
1385
1448
|
{
|
|
1386
1449
|
title: "Read Thread",
|
|
1387
1450
|
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
1388
|
-
description: 'Read messages from a Naumu thread. Returns paginated history ordered newest-first, or oldest-first when you pass `after`; 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, or `after` (timestamp ms) to catch up on what arrived since you last looked. To wait for the next message instead of re-reading on a timer, use naumu_wait_for_activity. Default page size 50, max 200. Agent messages carry `memoryScope.line`, a one-line statement of which Memory scope the answer used; surface it under the answer. To read or download
|
|
1451
|
+
description: 'Read messages from a Naumu thread. Returns paginated history ordered newest-first, or oldest-first when you pass `after`; 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, or `after` (timestamp ms) to catch up on what arrived since you last looked. To wait for the next message instead of re-reading on a timer, use naumu_wait_for_activity. Default page size 50, max 200. Agent messages carry `memoryScope.line`, a one-line statement of which Memory scope the answer used; surface it under the answer. Audio attachments are transcribed by Naumu at post time: read `attachments[].transcription` (plus `transcriptionSummary` and `transcriptionStatus`) straight from the message instead of downloading and transcribing the file. To read or download any other attachment, pass its `attachments[].id` to naumu_get_attachment.',
|
|
1389
1452
|
inputSchema: z23.object({
|
|
1390
1453
|
threadId: z23.string().describe("The thread ID to read from."),
|
|
1391
1454
|
before: z23.number().optional().describe("Unix timestamp in milliseconds. Returns messages strictly older than this. Omit for the newest page."),
|
|
@@ -1920,7 +1983,7 @@ function registerGetAttachment(server2, client2) {
|
|
|
1920
1983
|
{
|
|
1921
1984
|
title: "Get Attachment",
|
|
1922
1985
|
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
1923
|
-
description: "Read a chat attachment. Pass the `attachmentId` from a message's `attachments[].id` in naumu_read_thread (its `url` field works too - the id is extracted from it), and this resolves it into a short-lived download URL for the actual bytes.\n\nReturns a JSON text block with `{ attachmentId, downloadUrl, expiresInSeconds, note }`. Use `downloadUrl` EXACTLY as given:\n\u2022 GET it with no Authorization header - the URL itself is the auth, and adding one makes S3 answer 403.\n\u2022 It expires about 15 minutes after this call. Fetch it now; re-call this tool for a fresh URL rather than holding one.\n\u2022 Do not log it, quote it back to the user, or store it - it is a bearer capability for its whole lifetime.\n\nWhen the attachment is an image (or a video or PDF that has a generated poster), a downsized preview is also returned inline as an image block, so a visual attachment can often be understood without fetching anything. The preview is a thumbnail, not the original - fetch `downloadUrl` when you need full resolution or the exact file.\n\nAccess is checked the same way it is for a person: you only resolve attachments in threads you can already read.",
|
|
1986
|
+
description: "Read a chat attachment. Pass the `attachmentId` from a message's `attachments[].id` in naumu_read_thread (its `url` field works too - the id is extracted from it), and this resolves it into a short-lived download URL for the actual bytes.\n\nReturns a JSON text block with `{ attachmentId, downloadUrl, expiresInSeconds, note }`. Use `downloadUrl` EXACTLY as given:\n\u2022 GET it with no Authorization header - the URL itself is the auth, and adding one makes S3 answer 403.\n\u2022 It expires about 15 minutes after this call. Fetch it now; re-call this tool for a fresh URL rather than holding one.\n\u2022 Do not log it, quote it back to the user, or store it - it is a bearer capability for its whole lifetime.\n\nWhen the attachment is an image (or a video or PDF that has a generated poster), a downsized preview is also returned inline as an image block, so a visual attachment can often be understood without fetching anything. The preview is a thumbnail, not the original - fetch `downloadUrl` when you need full resolution or the exact file.\n\nAudio attachments do not need this tool for their contents: Naumu transcribes them at post time and naumu_read_thread returns the text as `attachments[].transcription` on the message - use that instead of downloading and transcribing the file.\n\nAccess is checked the same way it is for a person: you only resolve attachments in threads you can already read.",
|
|
1924
1987
|
inputSchema: z33.object({
|
|
1925
1988
|
attachmentId: z33.string().min(1).describe("Attachment id, from `attachments[].id` on a message returned by naumu_read_thread. A full or relative download URL is also accepted - the id is extracted from its last path segment.")
|
|
1926
1989
|
})
|
package/package.json
CHANGED
package/server.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "ai.naumu/mcp",
|
|
4
4
|
"title": "Naumu",
|
|
5
5
|
"description": "Search, extend, and act on your team's Naumu knowledge graph: notes, threads, and nodes.",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.16.0",
|
|
7
7
|
"websiteUrl": "https://naumu.ai",
|
|
8
8
|
"repository": {
|
|
9
9
|
"url": "https://github.com/naumu-ai/mcp",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"registryType": "npm",
|
|
28
28
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
29
29
|
"identifier": "@naumu/mcp",
|
|
30
|
-
"version": "0.
|
|
30
|
+
"version": "0.16.0",
|
|
31
31
|
"runtimeHint": "npx",
|
|
32
32
|
"transport": { "type": "stdio" },
|
|
33
33
|
"environmentVariables": [
|