keywordgraph-mcp-server 1.7.4 → 1.8.4

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.
Files changed (111) hide show
  1. package/README.md +57 -4
  2. package/dist/api/client.d.ts +3 -1
  3. package/dist/api/client.d.ts.map +1 -1
  4. package/dist/api/client.js +2 -1
  5. package/dist/api/client.js.map +1 -1
  6. package/dist/api/config-store.d.ts +11 -0
  7. package/dist/api/config-store.d.ts.map +1 -1
  8. package/dist/api/config-store.js +7 -0
  9. package/dist/api/config-store.js.map +1 -1
  10. package/dist/config/brand.d.ts.map +1 -1
  11. package/dist/config/brand.js +11 -0
  12. package/dist/config/brand.js.map +1 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +83 -6
  15. package/dist/index.js.map +1 -1
  16. package/dist/instructions.d.ts.map +1 -1
  17. package/dist/instructions.js +9 -2
  18. package/dist/instructions.js.map +1 -1
  19. package/dist/prompts/index.d.ts.map +1 -1
  20. package/dist/prompts/index.js +32 -0
  21. package/dist/prompts/index.js.map +1 -1
  22. package/dist/resources/about.d.ts.map +1 -1
  23. package/dist/resources/about.js +9 -1
  24. package/dist/resources/about.js.map +1 -1
  25. package/dist/schemas/index.d.ts +353 -63
  26. package/dist/schemas/index.d.ts.map +1 -1
  27. package/dist/schemas/index.js +407 -31
  28. package/dist/schemas/index.js.map +1 -1
  29. package/dist/tools/addProjectLearnings.d.ts +30 -0
  30. package/dist/tools/addProjectLearnings.d.ts.map +1 -0
  31. package/dist/tools/addProjectLearnings.js +197 -0
  32. package/dist/tools/addProjectLearnings.js.map +1 -0
  33. package/dist/tools/analyzeLlmResults.d.ts +1 -1
  34. package/dist/tools/analyzeLlmResults.d.ts.map +1 -1
  35. package/dist/tools/analyzeLlmResults.js +5 -2
  36. package/dist/tools/analyzeLlmResults.js.map +1 -1
  37. package/dist/tools/deleteGraph.d.ts +43 -0
  38. package/dist/tools/deleteGraph.d.ts.map +1 -0
  39. package/dist/tools/deleteGraph.js +145 -0
  40. package/dist/tools/deleteGraph.js.map +1 -0
  41. package/dist/tools/deleteStatements.d.ts +106 -0
  42. package/dist/tools/deleteStatements.d.ts.map +1 -0
  43. package/dist/tools/deleteStatements.js +288 -0
  44. package/dist/tools/deleteStatements.js.map +1 -0
  45. package/dist/tools/developConceptualBridges.d.ts +1 -1
  46. package/dist/tools/developLatentTopics.d.ts +1 -1
  47. package/dist/tools/developTextTool.d.ts +1 -1
  48. package/dist/tools/enableProjectLearnings.d.ts +27 -0
  49. package/dist/tools/enableProjectLearnings.d.ts.map +1 -0
  50. package/dist/tools/enableProjectLearnings.js +68 -0
  51. package/dist/tools/enableProjectLearnings.js.map +1 -0
  52. package/dist/tools/generateOntologyGraph.d.ts +10 -3
  53. package/dist/tools/generateOntologyGraph.d.ts.map +1 -1
  54. package/dist/tools/generateOntologyGraph.js +142 -34
  55. package/dist/tools/generateOntologyGraph.js.map +1 -1
  56. package/dist/tools/generateResearchIdeas.d.ts +1 -1
  57. package/dist/tools/generateResearchQuestions.d.ts +1 -1
  58. package/dist/tools/generateResponses.d.ts +1 -1
  59. package/dist/tools/getProjectLearnings.d.ts +30 -0
  60. package/dist/tools/getProjectLearnings.d.ts.map +1 -0
  61. package/dist/tools/getProjectLearnings.js +151 -0
  62. package/dist/tools/getProjectLearnings.js.map +1 -0
  63. package/dist/tools/index.d.ts +8 -0
  64. package/dist/tools/index.d.ts.map +1 -1
  65. package/dist/tools/index.js +8 -0
  66. package/dist/tools/index.js.map +1 -1
  67. package/dist/tools/optimizeKnowledgeBase.d.ts +40 -0
  68. package/dist/tools/optimizeKnowledgeBase.d.ts.map +1 -0
  69. package/dist/tools/optimizeKnowledgeBase.js +230 -0
  70. package/dist/tools/optimizeKnowledgeBase.js.map +1 -0
  71. package/dist/tools/optimizeReasoning.d.ts +1 -1
  72. package/dist/tools/optimizeTextStructure.d.ts +1 -1
  73. package/dist/tools/submitWorkflowFeedback.d.ts +35 -0
  74. package/dist/tools/submitWorkflowFeedback.d.ts.map +1 -0
  75. package/dist/tools/submitWorkflowFeedback.js +62 -0
  76. package/dist/tools/submitWorkflowFeedback.js.map +1 -0
  77. package/dist/tools/updateStatements.d.ts +134 -0
  78. package/dist/tools/updateStatements.d.ts.map +1 -0
  79. package/dist/tools/updateStatements.js +378 -0
  80. package/dist/tools/updateStatements.js.map +1 -0
  81. package/dist/types/index.d.ts +30 -0
  82. package/dist/types/index.d.ts.map +1 -1
  83. package/dist/utils/callTracking.d.ts +29 -0
  84. package/dist/utils/callTracking.d.ts.map +1 -0
  85. package/dist/utils/callTracking.js +88 -0
  86. package/dist/utils/callTracking.js.map +1 -0
  87. package/dist/utils/feedback.d.ts +63 -0
  88. package/dist/utils/feedback.d.ts.map +1 -0
  89. package/dist/utils/feedback.js +115 -0
  90. package/dist/utils/feedback.js.map +1 -0
  91. package/dist/utils/graphInput.d.ts +1 -0
  92. package/dist/utils/graphInput.d.ts.map +1 -1
  93. package/dist/utils/graphInput.js +1 -1
  94. package/dist/utils/graphInput.js.map +1 -1
  95. package/dist/utils/graphLookup.d.ts +29 -0
  96. package/dist/utils/graphLookup.d.ts.map +1 -0
  97. package/dist/utils/graphLookup.js +57 -0
  98. package/dist/utils/graphLookup.js.map +1 -0
  99. package/dist/utils/knowledgeBase.d.ts +21 -0
  100. package/dist/utils/knowledgeBase.d.ts.map +1 -0
  101. package/dist/utils/knowledgeBase.js +110 -0
  102. package/dist/utils/knowledgeBase.js.map +1 -0
  103. package/dist/utils/learnings.d.ts +119 -0
  104. package/dist/utils/learnings.d.ts.map +1 -0
  105. package/dist/utils/learnings.js +337 -0
  106. package/dist/utils/learnings.js.map +1 -0
  107. package/llms-full.infranodus.txt +39 -1
  108. package/llms-full.txt +39 -1
  109. package/llms.infranodus.txt +2 -0
  110. package/llms.txt +2 -0
  111. package/package.json +3 -2
@@ -0,0 +1,337 @@
1
+ /**
2
+ * Project learnings: an append-only, per-project graph (`learn-<slug>`) where
3
+ * the calling LLM saves what it learned about operating in a project, so the
4
+ * next session — on any client — can retrieve it.
5
+ *
6
+ * Consent model (see docs/drafts/project-learnings-graph.md): the graph only
7
+ * exists if the user explicitly asked for it via `enable_project_learnings`.
8
+ * `add_project_learnings` refuses when the graph is missing and never creates
9
+ * one. Statements carry their `type-*` label as plain per-statement metadata
10
+ * (`categories`), deliberately WITHOUT `categoriesAsMentions`: with that
11
+ * flag each label becomes a [[label]] mention node linked to every statement
12
+ * of that type, which in testing made the labels the most central nodes of
13
+ * the graph. As metadata the labels are returned with each statement and
14
+ * filterable, while the graph's nodes stay the real entities.
15
+ */
16
+ import { makeInfraNodusRequest } from "../api/client.js";
17
+ import { READ_ATTEMPTS, errorText, findGraphByName, firstPositive, } from "./graphLookup.js";
18
+ export const GRAPH_PREFIX = "learn-";
19
+ export const MAX_GRAPH_NAME_LENGTH = 28;
20
+ export const MARKER_CATEGORY = "learnings-enabled";
21
+ export const LEARNING_TYPES = [
22
+ "location",
23
+ "trap",
24
+ "convention",
25
+ "decision",
26
+ "workflow",
27
+ "question",
28
+ "approach",
29
+ ];
30
+ export const TYPE_CATEGORY_PREFIX = "type-";
31
+ export const SOURCE_CATEGORY_PREFIX = "source-";
32
+ /** Near-duplicate threshold on word-set Jaccard similarity. */
33
+ export const DEDUPE_THRESHOLD = 0.6;
34
+ export const MAX_STATEMENT_LENGTH = 400;
35
+ export function slugify(input) {
36
+ return input
37
+ .toLowerCase()
38
+ .replace(/[^a-z0-9]+/g, "-")
39
+ .replace(/^-+|-+$/g, "")
40
+ .replace(/-{2,}/g, "-");
41
+ }
42
+ export function learningsGraphName(project) {
43
+ const slug = slugify(project) || "project";
44
+ const room = MAX_GRAPH_NAME_LENGTH - GRAPH_PREFIX.length;
45
+ return GRAPH_PREFIX + slug.slice(0, room).replace(/-+$/g, "");
46
+ }
47
+ /**
48
+ * Not attached to statements any more: a per-client label links every
49
+ * statement of that client and became the most central node of the graph in
50
+ * testing. Kept so `toStoredLearning` can still read graphs written before
51
+ * that change.
52
+ */
53
+ export function sourceCategory(clientName) {
54
+ return SOURCE_CATEGORY_PREFIX + (slugify(clientName ?? "") || "unknown");
55
+ }
56
+ export function typeCategory(type) {
57
+ return TYPE_CATEGORY_PREFIX + type;
58
+ }
59
+ // ---------------------------------------------------------------------------
60
+ // Redaction lint
61
+ // ---------------------------------------------------------------------------
62
+ const SECRET_PATTERNS = [
63
+ /\bsk-[A-Za-z0-9_-]{8,}/, // OpenAI/Anthropic-style keys
64
+ /\bAKIA[0-9A-Z]{16}\b/, // AWS access key id
65
+ /\bbearer\s+[A-Za-z0-9._~+/=-]{12,}/i,
66
+ /\bapi[_-]?key\s*[:=]\s*['"]?[A-Za-z0-9._-]{8,}/i,
67
+ /\b(?:password|passwd|secret|token)\s*[:=]\s*['"]?\S{6,}/i,
68
+ /-----BEGIN [A-Z ]*PRIVATE KEY-----/,
69
+ /:\/\/[^\s/@]+:[^\s/@]+@/, // user:pass@host in a URL
70
+ /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/, // JWT
71
+ ];
72
+ /** Returns the indices (never the content) of statements that must not be stored. */
73
+ export function redactionIssues(statements) {
74
+ const issues = [];
75
+ statements.forEach((statement, index) => {
76
+ if (!statement || !statement.trim()) {
77
+ issues.push({ index, reason: "empty" });
78
+ return;
79
+ }
80
+ if (statement.length > MAX_STATEMENT_LENGTH) {
81
+ issues.push({ index, reason: "too-long" });
82
+ return;
83
+ }
84
+ if (SECRET_PATTERNS.some((pattern) => pattern.test(statement))) {
85
+ issues.push({ index, reason: "secret-like" });
86
+ }
87
+ });
88
+ return issues;
89
+ }
90
+ // ---------------------------------------------------------------------------
91
+ // Dedupe
92
+ // ---------------------------------------------------------------------------
93
+ const STOPWORDS = new Set([
94
+ "the", "and", "for", "that", "this", "with", "from", "are", "was", "were",
95
+ "has", "have", "not", "but", "its", "into", "when", "which", "also", "than",
96
+ "then", "there", "their", "they", "them", "been", "being", "use", "used",
97
+ "confirmed", "again",
98
+ ]);
99
+ export function tokenize(statement) {
100
+ const words = statement
101
+ .toLowerCase()
102
+ .replace(/\[\[|\]\]/g, " ")
103
+ .split(/[^a-z0-9._/-]+/)
104
+ .map((word) => word.replace(/^[._/-]+|[._/-]+$/g, ""))
105
+ .filter((word) => word.length >= 3 && !STOPWORDS.has(word));
106
+ return new Set(words);
107
+ }
108
+ export function jaccard(a, b) {
109
+ if (a.size === 0 || b.size === 0)
110
+ return 0;
111
+ let intersection = 0;
112
+ for (const word of a)
113
+ if (b.has(word))
114
+ intersection += 1;
115
+ const union = a.size + b.size - intersection;
116
+ return union === 0 ? 0 : intersection / union;
117
+ }
118
+ /**
119
+ * Compare candidates against what the graph already holds. A near-duplicate
120
+ * is not dropped — it is rewritten as a short "Confirmed again" statement so
121
+ * the repeat still raises the weight of the same entity links (that is how
122
+ * frequently re-learned things become central) without duplicating the text.
123
+ */
124
+ export function dedupeAgainstExisting(candidates, existing, threshold = DEDUPE_THRESHOLD) {
125
+ const existingTokens = existing.map((statement) => ({
126
+ statement,
127
+ tokens: tokenize(statement),
128
+ }));
129
+ const accepted = [];
130
+ return candidates.map((candidate) => {
131
+ const tokens = tokenize(candidate);
132
+ let best = null;
133
+ for (const entry of existingTokens) {
134
+ const similarity = jaccard(tokens, entry.tokens);
135
+ if (similarity >= threshold && (!best || similarity > best.similarity)) {
136
+ best = { statement: entry.statement, similarity };
137
+ }
138
+ }
139
+ // Also collapse duplicates within the same batch.
140
+ if (!best) {
141
+ for (const prior of accepted) {
142
+ if (jaccard(tokens, prior) >= threshold) {
143
+ best = { statement: "(earlier statement in this batch)", similarity: 1 };
144
+ break;
145
+ }
146
+ }
147
+ }
148
+ accepted.push(tokens);
149
+ if (best) {
150
+ return {
151
+ statement: best.statement.startsWith("(")
152
+ ? candidate
153
+ : `Confirmed again: ${stripConfirmedPrefix(best.statement)}`,
154
+ status: "reinforced",
155
+ matches: best.statement,
156
+ similarity: Number(best.similarity.toFixed(2)),
157
+ };
158
+ }
159
+ return { statement: candidate, status: "new" };
160
+ });
161
+ }
162
+ function stripConfirmedPrefix(statement) {
163
+ return statement.replace(/^(?:confirmed again:\s*)+/i, "");
164
+ }
165
+ // The retrying lookup and the error-envelope normaliser live in
166
+ // graphLookup.ts (shared with delete_statements); re-exported here so the
167
+ // existing imports and tests keep working.
168
+ export { READ_ATTEMPTS, errorText };
169
+ /** Exact-name lookup through /listGraphs (read-only; never creates anything). */
170
+ export async function findLearningsGraph(graphName) {
171
+ const found = await findGraphByName(graphName);
172
+ if (!found)
173
+ return { exists: false, categoriesOn: false };
174
+ return {
175
+ exists: true,
176
+ categoriesOn: found.textProcessingSettings?.categoriesAsMentions === true,
177
+ id: found.id,
178
+ url: found.defaultRevisionUrl ?? undefined,
179
+ createdAt: found.createdAt,
180
+ };
181
+ }
182
+ export function toStoredLearning(statement) {
183
+ if (!statement.content)
184
+ return null;
185
+ const categories = statement.categories ?? [];
186
+ return {
187
+ content: statement.content,
188
+ types: categories
189
+ .filter((category) => category.startsWith(TYPE_CATEGORY_PREFIX))
190
+ .map((category) => category.slice(TYPE_CATEGORY_PREFIX.length)),
191
+ source: categories
192
+ .find((category) => category.startsWith(SOURCE_CATEGORY_PREFIX))
193
+ ?.slice(SOURCE_CATEGORY_PREFIX.length),
194
+ categories,
195
+ createdAt: statement.createdAt,
196
+ };
197
+ }
198
+ export function isMarkerStatement(statement) {
199
+ return ((statement.categories ?? []).includes(MARKER_CATEGORY) ||
200
+ (statement.content ?? "").includes(`[[${MARKER_CATEGORY}]]`));
201
+ }
202
+ /**
203
+ * Read every statement of the graph (doNotSave; the graph must already exist —
204
+ * a missing name errors and is never created). "Select an existing graph
205
+ * context" on a graph that does exist means the request hit an instance
206
+ * with a stale contexts list (see firstPositive), not a parameter problem.
207
+ */
208
+ export async function fetchLearningsGraph(graphName) {
209
+ const queryParams = new URLSearchParams({
210
+ doNotSave: "true",
211
+ addStats: "true",
212
+ includeStatements: "true",
213
+ includeGraphSummary: "false",
214
+ extendedGraphSummary: "true",
215
+ includeGraph: "false",
216
+ compactGraph: "true",
217
+ compactStatements: "false",
218
+ aiTopics: "false",
219
+ });
220
+ let lastError = "Graph not found";
221
+ const response = await firstPositive(async (n) => {
222
+ try {
223
+ const result = await makeInfraNodusRequest(`/graphAndStatements?${queryParams.toString()}`, { name: graphName, aiTopics: "false", attempt: n });
224
+ if (result.error) {
225
+ lastError = errorText(result.error);
226
+ return null;
227
+ }
228
+ return result;
229
+ }
230
+ catch (error) {
231
+ lastError = error instanceof Error ? error.message : String(error);
232
+ return null;
233
+ }
234
+ });
235
+ if (!response)
236
+ throw new Error(lastError);
237
+ return { statements: response.statements ?? [], response };
238
+ }
239
+ /**
240
+ * Resolve whether learnings are enabled for a graph name: the graph exists
241
+ * and holds the marker statement written by `createLearningsGraph`. The
242
+ * listing supplies url/createdAt; reading by name is authoritative for
243
+ * existence (a missing graph errors and is never created) and is also what
244
+ * catches a graph the listing does not show yet (see firstPositive).
245
+ */
246
+ export async function checkEnabled(graphName) {
247
+ const info = await findLearningsGraph(graphName);
248
+ let statements;
249
+ try {
250
+ ({ statements } = await fetchLearningsGraph(graphName));
251
+ }
252
+ catch {
253
+ return { enabled: false, info, reason: "missing" };
254
+ }
255
+ if (statements.some(isMarkerStatement)) {
256
+ return { enabled: true, info: { ...info, exists: true } };
257
+ }
258
+ return {
259
+ enabled: false,
260
+ info: { ...info, exists: true },
261
+ reason: "not-a-learnings-graph",
262
+ };
263
+ }
264
+ /**
265
+ * Append statements (with parallel categories/timestamps) to an existing
266
+ * graph. Sent as a plain statements payload — NOT via prepareStatementsPayload,
267
+ * which would switch `categoriesAsMentions` on and turn the labels into nodes.
268
+ */
269
+ export async function appendLearnings(params) {
270
+ const payload = {
271
+ text: "",
272
+ statements: params.statements,
273
+ categories: params.categories,
274
+ timestamps: params.timestamps,
275
+ };
276
+ const queryParams = new URLSearchParams({
277
+ doNotSave: "false",
278
+ addStats: "false",
279
+ includeStatements: "false",
280
+ includeGraphSummary: "false",
281
+ extendedGraphSummary: "false",
282
+ includeGraph: "false",
283
+ compactGraph: "true",
284
+ compactStatements: "true",
285
+ aiTopics: "false",
286
+ });
287
+ // An instance with a stale contexts list (see firstPositive) treats an
288
+ // append to an existing graph as a create and the engine rejects it with
289
+ // "Context with this name already exists". That error is the only one
290
+ // worth retrying: it means the graph exists and another instance will
291
+ // append correctly.
292
+ let lastError = "Append failed";
293
+ for (let n = 0; n < READ_ATTEMPTS; n++) {
294
+ const response = await makeInfraNodusRequest(`/graphAndStatements?${queryParams.toString()}`, {
295
+ name: params.graphName,
296
+ aiTopics: "false",
297
+ contextType: "memory",
298
+ ...payload,
299
+ ...(n > 0 ? { attempt: n } : {}),
300
+ });
301
+ if (!response.error) {
302
+ return {
303
+ graphName: response.graphName ?? params.graphName,
304
+ graphUrl: response.graphUrl,
305
+ response,
306
+ };
307
+ }
308
+ lastError = errorText(response.error);
309
+ if (!/already exists/i.test(lastError))
310
+ break;
311
+ }
312
+ throw new Error(lastError);
313
+ }
314
+ /**
315
+ * Create the learnings graph. The marker statement (and its
316
+ * `learnings-enabled` category) is what `checkEnabled` looks for.
317
+ */
318
+ export async function createLearningsGraph(params) {
319
+ const now = new Date().toISOString();
320
+ const client = params.clientName?.trim() || "unknown client";
321
+ return appendLearnings({
322
+ graphName: params.graphName,
323
+ statements: [
324
+ `[[${MARKER_CATEGORY}]] Project [[${params.slug}]] learnings enabled on ${now.slice(0, 10)} from ${client}. Append-only graph of what agents learned about operating in this project.`,
325
+ ],
326
+ categories: [[MARKER_CATEGORY]],
327
+ timestamps: [now],
328
+ });
329
+ }
330
+ export function newestFirst(items) {
331
+ return [...items].sort((a, b) => {
332
+ const ta = a.createdAt ? Date.parse(a.createdAt) : 0;
333
+ const tb = b.createdAt ? Date.parse(b.createdAt) : 0;
334
+ return tb - ta;
335
+ });
336
+ }
337
+ //# sourceMappingURL=learnings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learnings.js","sourceRoot":"","sources":["../../src/utils/learnings.ts"],"names":[],"mappings":"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"}
@@ -37,7 +37,7 @@ Get API key at: https://infranodus.com/api-access
37
37
  7. **Comparing texts**: `overlap_between_texts` (similarities), `difference_between_texts` (what's missing in first text), `merged_graph_from_texts` (combined overview).
38
38
  8. **SEO/content optimization**: `generate_seo_report` (comprehensive, ~90s timeout needed) or run `analyze_google_search_results` → `analyze_related_search_queries` → `search_queries_vs_search_results` individually.
39
39
  9. **Memory**: `memory_add_relations` to persist knowledge graphs, `memory_get_relations` to retrieve. Use `[[wikilinks]]` for entity marking.
40
- 10. **Graph management**: `list_graphs` to discover existing graphs, `search` + `fetch` for content retrieval.
40
+ 10. **Graph management**: `list_graphs` to discover existing graphs, `search` + `fetch` for content retrieval, `delete_statements` to remove statements from your own graph by filter and `update_statements` to edit them in place (both dry run unless `confirm: true`; irreversible).
41
41
 
42
42
  ---
43
43
 
@@ -321,6 +321,44 @@ Fetch specific statements from a search result using the ID from `search`.
321
321
 
322
322
  ---
323
323
 
324
+ ### delete_statements
325
+
326
+ Delete statements from a graph in the user's own account, selected by one filter the server resolves. Irreversible once confirmed. Dry run by default: the response reports the matched count, a sample of the matched statements, and a per-category breakdown, and nothing is removed until the same filter is sent again with `confirm: true` (clients with MCP elicitation ask the user directly in the same call). A filter that matches nothing returns `deleted: 0` without asking. Never called on the assistant's own initiative.
327
+
328
+ **Parameters** (exactly one selector besides `graphName`):
329
+ - `graphName` (string, required): Graph in the user's own account (must exist; there is no `userName`)
330
+ - `categories` (string[]): Statements carrying any of these labels — everything from one source (a file path, page name, or `[[label]]` parent)
331
+ - `statements` (string[]): Exact statement text
332
+ - `query` (string): Case-insensitive substring, or `/regex/flags`
333
+ - `before`, `after` (ISO 8601): Time window; together they count as one selector
334
+ - `deleteAll` (boolean): Empty the graph but keep it (name, URL, settings survive)
335
+ - `statementIds` (number[]): Advanced; foreign ids are reported as `ignoredIds`
336
+ - `confirm` (boolean, default false): Perform the deletion
337
+
338
+ **Returns**: dry run — `dryRun: true`, `matchedCount`, `matched` (id, content, categories, timestamp), `matchedByCategory`, `filter`, `nextStep`; after confirmation — `deleted`, `removedIds`, `ignoredIds`, `remaining`, `graphName`, `graphUrl`.
339
+
340
+ **Typical use**: replace one source's statements after it changed (`delete_statements` with its category, then `create_knowledge_graph` to the same `graphName`), or rebuild a graph in place (`deleteAll`, then `create_knowledge_graph`).
341
+
342
+ ---
343
+
344
+ ### update_statements
345
+
346
+ Edit statements of a graph in the user's own account IN PLACE — their content, categories, or timestamp — keeping each statement's id, date, and position (unlike deleting and re-creating it). Irreversible once confirmed: the previous text survives only in the dry-run output. Dry run by default: the response reports the matched count and the before → after of every change, and nothing is written until the same arguments are sent again with `confirm: true` (clients with MCP elicitation ask the user directly in the same call). A request that matches nothing returns `updated: 0` without asking. New content is capped at 1000 characters — for longer text use `delete_statements` then `create_knowledge_graph`. Never called on the assistant's own initiative.
347
+
348
+ **Parameters** (one mode per call, besides `graphName`):
349
+ - `graphName` (string, required): Graph in the user's own account (must exist; there is no `userName`)
350
+ - Mode A — `edits` (array): one item per statement to rewrite, each with exactly one of `match` (its exact current text, e.g. from `analyze_existing_graph_by_name` with `includeStatements`) or `statementId`, and at least one of `content`, `categories` (full replacement), `timestamp` (ISO 8601). Items that match nothing are reported as `unmatched`
351
+ - Mode B — exactly one selector: `categories` (string[]), `statements` (string[]), `query` (substring or `/regex/flags`), `before`/`after` (ISO 8601 window), `all` (boolean), `statementIds` (number[]) — plus at least one of:
352
+ - `set` (object): `addCategories`, `removeCategories`, `categories` (full replacement; exclusive with add/remove), `timestamp`
353
+ - `replace` (object): `{ pattern, with }` — substring or `/regex/flags`, applied to the text of every selected statement (e.g. rename a `[[concept]]` or a source path everywhere)
354
+ - `confirm` (boolean, default false): Perform the update
355
+
356
+ **Returns**: dry run — `dryRun: true`, `matchedCount`, `updatedCount` (how many would change), `changes` (id, before, after; capped at 50), `unchanged`, `unmatched`, `rejected`, `mode`, `filter`, `nextStep`; after confirmation — `updated`, `changes`, `unchanged`, `unmatched`, `rejected`, `graphName`, `graphUrl` (plus a `note` when the write's count differs from the preview).
357
+
358
+ **Typical use**: fix a wrong statement without losing its place (`edits` with `match` and the new `content`), relabel a batch (`categories` selector with `set.addCategories`), or rename a concept or a source path across a graph (`all: true` with `replace`).
359
+
360
+ ---
361
+
324
362
  ### memory_add_relations
325
363
 
326
364
  Add relations to a knowledge graph memory. Creates the graph if it doesn't exist. By default uses `extractEntitiesOnly` for automatic entity detection, creating a high-level concept graph.
package/llms-full.txt CHANGED
@@ -37,7 +37,7 @@ Get API key at: https://infranodus.com/api-access
37
37
  7. **Comparing texts**: `overlap_between_texts` (similarities), `difference_between_texts` (what's missing in first text), `merged_graph_from_texts` (combined overview).
38
38
  8. **SEO/content optimization**: `generate_seo_report` (comprehensive, ~90s timeout needed) or run `analyze_google_search_results` → `analyze_related_search_queries` → `search_queries_vs_search_results` individually.
39
39
  9. **Memory**: `memory_add_relations` to persist knowledge graphs, `memory_get_relations` to retrieve. Use `[[wikilinks]]` for entity marking.
40
- 10. **Graph management**: `list_graphs` to discover existing graphs, `search` + `fetch` for content retrieval.
40
+ 10. **Graph management**: `list_graphs` to discover existing graphs, `search` + `fetch` for content retrieval, `delete_statements` to remove statements from your own graph by filter and `update_statements` to edit them in place (both dry run unless `confirm: true`; irreversible).
41
41
 
42
42
  ---
43
43
 
@@ -321,6 +321,44 @@ Fetch specific statements from a search result using the ID from `search`.
321
321
 
322
322
  ---
323
323
 
324
+ ### delete_statements
325
+
326
+ Delete statements from a graph in the user's own account, selected by one filter the server resolves. Irreversible once confirmed. Dry run by default: the response reports the matched count, a sample of the matched statements, and a per-category breakdown, and nothing is removed until the same filter is sent again with `confirm: true` (clients with MCP elicitation ask the user directly in the same call). A filter that matches nothing returns `deleted: 0` without asking. Never called on the assistant's own initiative.
327
+
328
+ **Parameters** (exactly one selector besides `graphName`):
329
+ - `graphName` (string, required): Graph in the user's own account (must exist; there is no `userName`)
330
+ - `categories` (string[]): Statements carrying any of these labels — everything from one source (a file path, page name, or `[[label]]` parent)
331
+ - `statements` (string[]): Exact statement text
332
+ - `query` (string): Case-insensitive substring, or `/regex/flags`
333
+ - `before`, `after` (ISO 8601): Time window; together they count as one selector
334
+ - `deleteAll` (boolean): Empty the graph but keep it (name, URL, settings survive)
335
+ - `statementIds` (number[]): Advanced; foreign ids are reported as `ignoredIds`
336
+ - `confirm` (boolean, default false): Perform the deletion
337
+
338
+ **Returns**: dry run — `dryRun: true`, `matchedCount`, `matched` (id, content, categories, timestamp), `matchedByCategory`, `filter`, `nextStep`; after confirmation — `deleted`, `removedIds`, `ignoredIds`, `remaining`, `graphName`, `graphUrl`.
339
+
340
+ **Typical use**: replace one source's statements after it changed (`delete_statements` with its category, then `create_knowledge_graph` to the same `graphName`), or rebuild a graph in place (`deleteAll`, then `create_knowledge_graph`).
341
+
342
+ ---
343
+
344
+ ### update_statements
345
+
346
+ Edit statements of a graph in the user's own account IN PLACE — their content, categories, or timestamp — keeping each statement's id, date, and position (unlike deleting and re-creating it). Irreversible once confirmed: the previous text survives only in the dry-run output. Dry run by default: the response reports the matched count and the before → after of every change, and nothing is written until the same arguments are sent again with `confirm: true` (clients with MCP elicitation ask the user directly in the same call). A request that matches nothing returns `updated: 0` without asking. New content is capped at 1000 characters — for longer text use `delete_statements` then `create_knowledge_graph`. Never called on the assistant's own initiative.
347
+
348
+ **Parameters** (one mode per call, besides `graphName`):
349
+ - `graphName` (string, required): Graph in the user's own account (must exist; there is no `userName`)
350
+ - Mode A — `edits` (array): one item per statement to rewrite, each with exactly one of `match` (its exact current text, e.g. from `analyze_existing_graph_by_name` with `includeStatements`) or `statementId`, and at least one of `content`, `categories` (full replacement), `timestamp` (ISO 8601). Items that match nothing are reported as `unmatched`
351
+ - Mode B — exactly one selector: `categories` (string[]), `statements` (string[]), `query` (substring or `/regex/flags`), `before`/`after` (ISO 8601 window), `all` (boolean), `statementIds` (number[]) — plus at least one of:
352
+ - `set` (object): `addCategories`, `removeCategories`, `categories` (full replacement; exclusive with add/remove), `timestamp`
353
+ - `replace` (object): `{ pattern, with }` — substring or `/regex/flags`, applied to the text of every selected statement (e.g. rename a `[[concept]]` or a source path everywhere)
354
+ - `confirm` (boolean, default false): Perform the update
355
+
356
+ **Returns**: dry run — `dryRun: true`, `matchedCount`, `updatedCount` (how many would change), `changes` (id, before, after; capped at 50), `unchanged`, `unmatched`, `rejected`, `mode`, `filter`, `nextStep`; after confirmation — `updated`, `changes`, `unchanged`, `unmatched`, `rejected`, `graphName`, `graphUrl` (plus a `note` when the write's count differs from the preview).
357
+
358
+ **Typical use**: fix a wrong statement without losing its place (`edits` with `match` and the new `content`), relabel a batch (`categories` selector with `set.addCategories`), or rename a concept or a source path across a graph (`all: true` with `replace`).
359
+
360
+ ---
361
+
324
362
  ### memory_add_relations
325
363
 
326
364
  Add relations to a knowledge graph memory. Creates the graph if it doesn't exist. By default uses `extractEntitiesOnly` for automatic entity detection, creating a high-level concept graph.
@@ -56,6 +56,8 @@
56
56
  - list_graphs: List all graphs with filtering by name, type, date, language
57
57
  - search: Search through existing InfraNodus graphs
58
58
  - fetch: Fetch specific search results from a graph
59
+ - delete_statements: Delete statements from your own graph by one filter (categories, statements, query, before/after, deleteAll, statementIds); dry run unless confirm: true; irreversible
60
+ - update_statements: Edit statements of your own graph in place (content, categories, timestamp) keeping id and position — specific statements by exact text or id (edits), or one selector with set/replace for bulk relabelling and find-and-replace; dry run showing before → after unless confirm: true; irreversible
59
61
 
60
62
  ## Optional
61
63
 
package/llms.txt CHANGED
@@ -56,6 +56,8 @@
56
56
  - list_graphs: List all graphs with filtering by name, type, date, language
57
57
  - search: Search through existing InfraNodus graphs
58
58
  - fetch: Fetch specific search results from a graph
59
+ - delete_statements: Delete statements from your own graph by one filter (categories, statements, query, before/after, deleteAll, statementIds); dry run unless confirm: true; irreversible
60
+ - update_statements: Edit statements of your own graph in place (content, categories, timestamp) keeping id and position — specific statements by exact text or id (edits), or one selector with set/replace for bulk relabelling and find-and-replace; dry run showing before → after unless confirm: true; irreversible
59
61
 
60
62
  ## Optional
61
63
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keywordgraph-mcp-server",
3
- "version": "1.7.4",
3
+ "version": "1.8.4",
4
4
  "description": "KeywordGraph MCP server - A Model Context Protocol server for network thinking and graph analysis",
5
5
  "type": "module",
6
6
  "module": "src/index.ts",
@@ -52,7 +52,8 @@
52
52
  "deploy:exalt": "fly deploy -c fly.exaltgrowth.toml",
53
53
  "publish:in": "npm run build:inspect && node scripts/publish-brand.mjs infranodus",
54
54
  "publish:kg": "npm run build:inspect && node scripts/publish-brand.mjs keywordgraph",
55
- "prepublishOnly": "npm run build:inspect"
55
+ "prepublishOnly": "npm run build:inspect",
56
+ "test": "npm run build:inspect && node --test 'test/**/*.test.mjs'"
56
57
  },
57
58
  "dependencies": {
58
59
  "@modelcontextprotocol/sdk": "^1.18.0",