keywordgraph-mcp-server 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +629 -0
  3. package/bin/infranodus-mcp-server.js +8 -0
  4. package/bin/keywordgraph-mcp-server.js +8 -0
  5. package/bin/mcp-server.js +56 -0
  6. package/dist/api/client.d.ts +3 -0
  7. package/dist/api/client.d.ts.map +1 -0
  8. package/dist/api/client.js +30 -0
  9. package/dist/api/client.js.map +1 -0
  10. package/dist/api/config-store.d.ts +4 -0
  11. package/dist/api/config-store.d.ts.map +1 -0
  12. package/dist/api/config-store.js +12 -0
  13. package/dist/api/config-store.js.map +1 -0
  14. package/dist/auth/oauth-provider.d.ts +56 -0
  15. package/dist/auth/oauth-provider.d.ts.map +1 -0
  16. package/dist/auth/oauth-provider.js +295 -0
  17. package/dist/auth/oauth-provider.js.map +1 -0
  18. package/dist/auth/types.d.ts +93 -0
  19. package/dist/auth/types.d.ts.map +1 -0
  20. package/dist/auth/types.js +5 -0
  21. package/dist/auth/types.js.map +1 -0
  22. package/dist/config/brand.d.ts +58 -0
  23. package/dist/config/brand.d.ts.map +1 -0
  24. package/dist/config/brand.js +97 -0
  25. package/dist/config/brand.js.map +1 -0
  26. package/dist/config/index.d.ts +26 -0
  27. package/dist/config/index.d.ts.map +1 -0
  28. package/dist/config/index.js +20 -0
  29. package/dist/config/index.js.map +1 -0
  30. package/dist/http-server.d.ts +6 -0
  31. package/dist/http-server.d.ts.map +1 -0
  32. package/dist/http-server.js +907 -0
  33. package/dist/http-server.js.map +1 -0
  34. package/dist/index.d.ts +29 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +136 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/instructions.d.ts +11 -0
  39. package/dist/instructions.d.ts.map +1 -0
  40. package/dist/instructions.js +38 -0
  41. package/dist/instructions.js.map +1 -0
  42. package/dist/prompts/index.d.ts +24 -0
  43. package/dist/prompts/index.d.ts.map +1 -0
  44. package/dist/prompts/index.js +394 -0
  45. package/dist/prompts/index.js.map +1 -0
  46. package/dist/resources/about.d.ts +17 -0
  47. package/dist/resources/about.d.ts.map +1 -0
  48. package/dist/resources/about.js +64 -0
  49. package/dist/resources/about.js.map +1 -0
  50. package/dist/resources/llms-txt.d.ts +33 -0
  51. package/dist/resources/llms-txt.d.ts.map +1 -0
  52. package/dist/resources/llms-txt.js +65 -0
  53. package/dist/resources/llms-txt.js.map +1 -0
  54. package/dist/schemas/index.d.ts +1178 -0
  55. package/dist/schemas/index.d.ts.map +1 -0
  56. package/dist/schemas/index.js +1121 -0
  57. package/dist/schemas/index.js.map +1 -0
  58. package/dist/tools/addMemory.d.ts +36 -0
  59. package/dist/tools/addMemory.d.ts.map +1 -0
  60. package/dist/tools/addMemory.js +82 -0
  61. package/dist/tools/addMemory.js.map +1 -0
  62. package/dist/tools/analyzeExistingGraph.d.ts +37 -0
  63. package/dist/tools/analyzeExistingGraph.d.ts.map +1 -0
  64. package/dist/tools/analyzeExistingGraph.js +85 -0
  65. package/dist/tools/analyzeExistingGraph.js.map +1 -0
  66. package/dist/tools/analyzeLlmResults.d.ts +37 -0
  67. package/dist/tools/analyzeLlmResults.d.ts.map +1 -0
  68. package/dist/tools/analyzeLlmResults.js +165 -0
  69. package/dist/tools/analyzeLlmResults.js.map +1 -0
  70. package/dist/tools/analyzeText.d.ts +36 -0
  71. package/dist/tools/analyzeText.d.ts.map +1 -0
  72. package/dist/tools/analyzeText.js +97 -0
  73. package/dist/tools/analyzeText.js.map +1 -0
  74. package/dist/tools/createKnowledgeGraph.d.ts +36 -0
  75. package/dist/tools/createKnowledgeGraph.d.ts.map +1 -0
  76. package/dist/tools/createKnowledgeGraph.js +105 -0
  77. package/dist/tools/createKnowledgeGraph.js.map +1 -0
  78. package/dist/tools/developConceptualBridges.d.ts +34 -0
  79. package/dist/tools/developConceptualBridges.d.ts.map +1 -0
  80. package/dist/tools/developConceptualBridges.js +107 -0
  81. package/dist/tools/developConceptualBridges.js.map +1 -0
  82. package/dist/tools/developLatentConcepts copy.d.ts +27 -0
  83. package/dist/tools/developLatentConcepts copy.d.ts.map +1 -0
  84. package/dist/tools/developLatentConcepts copy.js +68 -0
  85. package/dist/tools/developLatentConcepts copy.js.map +1 -0
  86. package/dist/tools/developLatentConcepts.d.ts +27 -0
  87. package/dist/tools/developLatentConcepts.d.ts.map +1 -0
  88. package/dist/tools/developLatentConcepts.js +68 -0
  89. package/dist/tools/developLatentConcepts.js.map +1 -0
  90. package/dist/tools/developLatentTopics.d.ts +34 -0
  91. package/dist/tools/developLatentTopics.d.ts.map +1 -0
  92. package/dist/tools/developLatentTopics.js +107 -0
  93. package/dist/tools/developLatentTopics.js.map +1 -0
  94. package/dist/tools/developTextTool.d.ts +39 -0
  95. package/dist/tools/developTextTool.d.ts.map +1 -0
  96. package/dist/tools/developTextTool.js +210 -0
  97. package/dist/tools/developTextTool.js.map +1 -0
  98. package/dist/tools/generateContentGaps.d.ts +32 -0
  99. package/dist/tools/generateContentGaps.d.ts.map +1 -0
  100. package/dist/tools/generateContentGaps.js +96 -0
  101. package/dist/tools/generateContentGaps.js.map +1 -0
  102. package/dist/tools/generateContextualHint.d.ts +33 -0
  103. package/dist/tools/generateContextualHint.d.ts.map +1 -0
  104. package/dist/tools/generateContextualHint.js +99 -0
  105. package/dist/tools/generateContextualHint.js.map +1 -0
  106. package/dist/tools/generateDifferenceGraphFromTexts.d.ts +52 -0
  107. package/dist/tools/generateDifferenceGraphFromTexts.d.ts.map +1 -0
  108. package/dist/tools/generateDifferenceGraphFromTexts.js +160 -0
  109. package/dist/tools/generateDifferenceGraphFromTexts.js.map +1 -0
  110. package/dist/tools/generateGoogleResultsVsQueriesGraph.d.ts +37 -0
  111. package/dist/tools/generateGoogleResultsVsQueriesGraph.d.ts.map +1 -0
  112. package/dist/tools/generateGoogleResultsVsQueriesGraph.js +84 -0
  113. package/dist/tools/generateGoogleResultsVsQueriesGraph.js.map +1 -0
  114. package/dist/tools/generateGoogleSearchQueriesGraph.d.ts +39 -0
  115. package/dist/tools/generateGoogleSearchQueriesGraph.d.ts.map +1 -0
  116. package/dist/tools/generateGoogleSearchQueriesGraph.js +88 -0
  117. package/dist/tools/generateGoogleSearchQueriesGraph.js.map +1 -0
  118. package/dist/tools/generateGoogleSearchResultsGraph.d.ts +38 -0
  119. package/dist/tools/generateGoogleSearchResultsGraph.d.ts.map +1 -0
  120. package/dist/tools/generateGoogleSearchResultsGraph.js +88 -0
  121. package/dist/tools/generateGoogleSearchResultsGraph.js.map +1 -0
  122. package/dist/tools/generateKnowledgeGraph.d.ts +35 -0
  123. package/dist/tools/generateKnowledgeGraph.d.ts.map +1 -0
  124. package/dist/tools/generateKnowledgeGraph.js +105 -0
  125. package/dist/tools/generateKnowledgeGraph.js.map +1 -0
  126. package/dist/tools/generateMergedGraphFromTexts.d.ts +52 -0
  127. package/dist/tools/generateMergedGraphFromTexts.d.ts.map +1 -0
  128. package/dist/tools/generateMergedGraphFromTexts.js +160 -0
  129. package/dist/tools/generateMergedGraphFromTexts.js.map +1 -0
  130. package/dist/tools/generateOntologyGraph.d.ts +36 -0
  131. package/dist/tools/generateOntologyGraph.d.ts.map +1 -0
  132. package/dist/tools/generateOntologyGraph.js +171 -0
  133. package/dist/tools/generateOntologyGraph.js.map +1 -0
  134. package/dist/tools/generateOverlapGraphFromTexts.d.ts +52 -0
  135. package/dist/tools/generateOverlapGraphFromTexts.d.ts.map +1 -0
  136. package/dist/tools/generateOverlapGraphFromTexts.js +159 -0
  137. package/dist/tools/generateOverlapGraphFromTexts.js.map +1 -0
  138. package/dist/tools/generateResearchIdeas.d.ts +39 -0
  139. package/dist/tools/generateResearchIdeas.d.ts.map +1 -0
  140. package/dist/tools/generateResearchIdeas.js +117 -0
  141. package/dist/tools/generateResearchIdeas.js.map +1 -0
  142. package/dist/tools/generateResearchQuestions.d.ts +37 -0
  143. package/dist/tools/generateResearchQuestions.d.ts.map +1 -0
  144. package/dist/tools/generateResearchQuestions.js +111 -0
  145. package/dist/tools/generateResearchQuestions.js.map +1 -0
  146. package/dist/tools/generateResearchQuestionsFromGraph.d.ts +34 -0
  147. package/dist/tools/generateResearchQuestionsFromGraph.d.ts.map +1 -0
  148. package/dist/tools/generateResearchQuestionsFromGraph.js +75 -0
  149. package/dist/tools/generateResearchQuestionsFromGraph.js.map +1 -0
  150. package/dist/tools/generateResponses.d.ts +35 -0
  151. package/dist/tools/generateResponses.d.ts.map +1 -0
  152. package/dist/tools/generateResponses.js +112 -0
  153. package/dist/tools/generateResponses.js.map +1 -0
  154. package/dist/tools/generateResponsesFromGraph.d.ts +33 -0
  155. package/dist/tools/generateResponsesFromGraph.d.ts.map +1 -0
  156. package/dist/tools/generateResponsesFromGraph.js +74 -0
  157. package/dist/tools/generateResponsesFromGraph.js.map +1 -0
  158. package/dist/tools/generateSEOGraphTool.d.ts +39 -0
  159. package/dist/tools/generateSEOGraphTool.d.ts.map +1 -0
  160. package/dist/tools/generateSEOGraphTool.js +235 -0
  161. package/dist/tools/generateSEOGraphTool.js.map +1 -0
  162. package/dist/tools/generateTextOverview.d.ts +31 -0
  163. package/dist/tools/generateTextOverview.d.ts.map +1 -0
  164. package/dist/tools/generateTextOverview.js +68 -0
  165. package/dist/tools/generateTextOverview.js.map +1 -0
  166. package/dist/tools/generateTopicalClusters.d.ts +34 -0
  167. package/dist/tools/generateTopicalClusters.d.ts.map +1 -0
  168. package/dist/tools/generateTopicalClusters.js +134 -0
  169. package/dist/tools/generateTopicalClusters.js.map +1 -0
  170. package/dist/tools/getMemory.d.ts +32 -0
  171. package/dist/tools/getMemory.d.ts.map +1 -0
  172. package/dist/tools/getMemory.js +121 -0
  173. package/dist/tools/getMemory.js.map +1 -0
  174. package/dist/tools/index.d.ts +30 -0
  175. package/dist/tools/index.d.ts.map +1 -0
  176. package/dist/tools/index.js +30 -0
  177. package/dist/tools/index.js.map +1 -0
  178. package/dist/tools/listGraphs.d.ts +37 -0
  179. package/dist/tools/listGraphs.d.ts.map +1 -0
  180. package/dist/tools/listGraphs.js +127 -0
  181. package/dist/tools/listGraphs.js.map +1 -0
  182. package/dist/tools/optimizeTextStructure.d.ts +34 -0
  183. package/dist/tools/optimizeTextStructure.d.ts.map +1 -0
  184. package/dist/tools/optimizeTextStructure.js +108 -0
  185. package/dist/tools/optimizeTextStructure.js.map +1 -0
  186. package/dist/tools/retrieveContextForPromptFromGraph.d.ts +37 -0
  187. package/dist/tools/retrieveContextForPromptFromGraph.d.ts.map +1 -0
  188. package/dist/tools/retrieveContextForPromptFromGraph.js +80 -0
  189. package/dist/tools/retrieveContextForPromptFromGraph.js.map +1 -0
  190. package/dist/tools/searchGraph.d.ts +27 -0
  191. package/dist/tools/searchGraph.d.ts.map +1 -0
  192. package/dist/tools/searchGraph.js +57 -0
  193. package/dist/tools/searchGraph.js.map +1 -0
  194. package/dist/tools/searchGraphs.d.ts +33 -0
  195. package/dist/tools/searchGraphs.d.ts.map +1 -0
  196. package/dist/tools/searchGraphs.js +67 -0
  197. package/dist/tools/searchGraphs.js.map +1 -0
  198. package/dist/tools/searchGraphsFetch.d.ts +31 -0
  199. package/dist/tools/searchGraphsFetch.d.ts.map +1 -0
  200. package/dist/tools/searchGraphsFetch.js +78 -0
  201. package/dist/tools/searchGraphsFetch.js.map +1 -0
  202. package/dist/tools/sequentialThinking.d.ts +71 -0
  203. package/dist/tools/sequentialThinking.d.ts.map +1 -0
  204. package/dist/tools/sequentialThinking.js +218 -0
  205. package/dist/tools/sequentialThinking.js.map +1 -0
  206. package/dist/types/index.d.ts +378 -0
  207. package/dist/types/index.d.ts.map +1 -0
  208. package/dist/types/index.js +2 -0
  209. package/dist/types/index.js.map +1 -0
  210. package/dist/utils/progress.d.ts +21 -0
  211. package/dist/utils/progress.d.ts.map +1 -0
  212. package/dist/utils/progress.js +50 -0
  213. package/dist/utils/progress.js.map +1 -0
  214. package/dist/utils/transformers.d.ts +31 -0
  215. package/dist/utils/transformers.d.ts.map +1 -0
  216. package/dist/utils/transformers.js +484 -0
  217. package/dist/utils/transformers.js.map +1 -0
  218. package/dist/utils/urlContent.d.ts +35 -0
  219. package/dist/utils/urlContent.d.ts.map +1 -0
  220. package/dist/utils/urlContent.js +87 -0
  221. package/dist/utils/urlContent.js.map +1 -0
  222. package/llms-full.infranodus.txt +469 -0
  223. package/llms-full.keywordgraph.txt +469 -0
  224. package/llms-full.txt +469 -0
  225. package/llms.infranodus.txt +64 -0
  226. package/llms.keywordgraph.txt +64 -0
  227. package/llms.txt +64 -0
  228. package/package.json +78 -0
@@ -0,0 +1,87 @@
1
+ import { makeInfraNodusRequest } from "../api/client.js";
2
+ const HEADER_TAGS = ["h1", "h2", "h3", "h4", "h5", "h6"];
3
+ export function parseUrlConvertResponse(url, raw) {
4
+ const firstPage = (raw.firstPage ?? raw);
5
+ const statements = firstPage?.statements ?? [];
6
+ const headers = Array.isArray(firstPage?.headers) && firstPage.headers.length > 0
7
+ ? firstPage.headers
8
+ : statements
9
+ .filter((s) => HEADER_TAGS.includes((s.tag ?? "").toLowerCase()))
10
+ .map((s) => s.content ?? "")
11
+ .filter(Boolean);
12
+ const linksText = Array.isArray(firstPage?.linksText) && firstPage.linksText.length > 0
13
+ ? firstPage.linksText
14
+ : statements
15
+ .filter((s) => (s.tag ?? "").toLowerCase().includes("a"))
16
+ .map((s) => s.content ?? "")
17
+ .filter(Boolean);
18
+ const text = typeof firstPage?.text === "string" ? firstPage.text : "";
19
+ return {
20
+ url,
21
+ title: typeof firstPage?.title === "string" ? firstPage.title : "",
22
+ tags: [],
23
+ headers,
24
+ selectedElementsText: [],
25
+ language: "",
26
+ canonicalLink: url,
27
+ linksText,
28
+ text,
29
+ };
30
+ }
31
+ export function extractContentByType(result, contentToExtract) {
32
+ const mode = (contentToExtract ?? "all").toLowerCase();
33
+ if (mode === "header tags")
34
+ return result.headers.join("\n");
35
+ if (mode === "link tags")
36
+ return result.linksText.join("\n");
37
+ return result.text;
38
+ }
39
+ /** Heuristic: true if content looks like no usable plain text (e.g. JS only) */
40
+ export function isNoUsableText(content) {
41
+ if (!content || !content.trim())
42
+ return true;
43
+ const trimmed = content.trim();
44
+ // Very short and no space → likely code/minified
45
+ if (trimmed.length < 100 && !trimmed.includes(" "))
46
+ return true;
47
+ // Almost no letters → likely not readable text
48
+ const letters = (trimmed.match(/\p{L}/gu) ?? []).length;
49
+ return letters < 20;
50
+ }
51
+ export async function fetchUrlContent(url, proxy) {
52
+ const query = new URLSearchParams({ url });
53
+ if (proxy)
54
+ query.set("proxy", "true");
55
+ const response = await makeInfraNodusRequest(`/convert/url?${query.toString()}`, {}, "GET");
56
+ if (response && typeof response === "object" && "error" in response) {
57
+ throw new Error(response.error ?? "Failed to fetch URL");
58
+ }
59
+ return (response ?? {});
60
+ }
61
+ /**
62
+ * Fetches content from a URL via the /convert/url, optionally retrying
63
+ * with proxy if the initial response has no usable text. Returns extracted text
64
+ * by content type (all, header tags, link tags).
65
+ */
66
+ export async function fetchUrlContentAsText(url, options = {}) {
67
+ const contentToExtract = options.contentToExtract ?? "all";
68
+ const useProxy = options.useProxy === true;
69
+ try {
70
+ let raw = await fetchUrlContent(url, useProxy);
71
+ let parsed = parseUrlConvertResponse(url, raw);
72
+ let contentText = extractContentByType(parsed, contentToExtract);
73
+ if (!useProxy && isNoUsableText(contentText)) {
74
+ raw = await fetchUrlContent(url, true);
75
+ parsed = parseUrlConvertResponse(url, raw);
76
+ contentText = extractContentByType(parsed, contentToExtract);
77
+ }
78
+ return { ok: true, contentText };
79
+ }
80
+ catch (err) {
81
+ return {
82
+ ok: false,
83
+ error: err instanceof Error ? err.message : String(err),
84
+ };
85
+ }
86
+ }
87
+ //# sourceMappingURL=urlContent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urlContent.js","sourceRoot":"","sources":["../../src/utils/urlContent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,469 @@
1
+ # InfraNodus MCP Server — Full Documentation for LLMs
2
+
3
+ > MCP server for knowledge graph generation, text network analysis, content gap detection, and SEO optimization powered by InfraNodus API and graph theory algorithms. All tools accept text, URLs (including YouTube for automatic transcription), or existing InfraNodus graph names as input.
4
+
5
+ ## Quick Start
6
+
7
+ Install via npx (Claude Desktop / Cursor IDE):
8
+
9
+ ```json
10
+ {
11
+ "mcpServers": {
12
+ "infranodus": {
13
+ "command": "npx",
14
+ "args": ["-y", "infranodus-mcp-server"],
15
+ "env": {
16
+ "INFRANODUS_API_KEY": "YOUR_INFRANODUS_API_KEY"
17
+ }
18
+ }
19
+ }
20
+ }
21
+ ```
22
+
23
+ Or use the remote HTTP server: https://mcp.infranodus.com (OAuth authentication).
24
+
25
+ Get API key at: https://infranodus.com/api-access
26
+
27
+ ---
28
+
29
+ ## Workflow Patterns
30
+
31
+ 1. **Quick structural overview**: `generate_knowledge_graph` or `generate_topical_clusters` → get main topics, clusters, gaps.
32
+ 2. **Deep text development**: `develop_text_tool` (combines optimize + latent topics + conceptual bridges in one call with progress tracking).
33
+ 3. **Research ideation**: `generate_content_gaps` → `generate_research_questions` or `generate_research_ideas`. Use `useSeveralGaps` for diversity, `gapDepth` for less prominent gaps.
34
+ 4. **Text optimization**: `optimize_text_structure` (auto-detects bias/focus/dispersion and suggests appropriate development).
35
+ 5. **Outside-the-box thinking**: `develop_conceptual_bridges` (connects discourse to broader context) or set `shouldTranscend`/`transcendDiscourse: true`.
36
+ 6. **RAG augmentation**: `generate_contextual_hint` (lightweight structural summary) or `retrieve_from_knowledge_base` with `includeGraphSummary` (GraphRAG retrieval).
37
+ 7. **Comparing texts**: `overlap_between_texts` (similarities), `difference_between_texts` (what's missing in first text), `merged_graph_from_texts` (combined overview).
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
+ 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.
41
+
42
+ ---
43
+
44
+ ## Common Parameters
45
+
46
+ **Input types** (provide exactly one per call):
47
+ - `text` (string): Raw text to analyze
48
+ - `url` (string): Webpage or YouTube video URL (auto-transcribed)
49
+ - `graphName` (string): Name of an existing InfraNodus graph
50
+
51
+ **Entity detection** (`modifyAnalyzedText` parameter):
52
+ - `none` (default): Word co-occurrence graph
53
+ - `detectEntities`: Mix entities and words
54
+ - `extractEntitiesOnly`: Entity-only graph, best for ontologies and knowledge graphs
55
+
56
+ **AI models** (`modelToUse` parameter, no additional API keys needed):
57
+ - `gpt-4o`, `gpt-4o-mini`, `gpt-5.4`, `gpt-5.4-mini`
58
+ - `claude-sonnet-4.6`, `claude-opus-4.6`
59
+ - `gemini-2.5-flash`, `gemini-2.5-flash-lite`
60
+
61
+ **Response types** (`responseType` parameter):
62
+ - `response`: Default analytical response
63
+ - `idea`: Business-oriented idea
64
+ - `question`: Research questions
65
+ - `transcend`: Broader discourse connection
66
+
67
+ **Diversity metrics** (returned in graph analysis):
68
+ - `biased`: Text dominated by a single perspective — develop underrepresented topics
69
+ - `focused`: Text concentrated on specific themes — develop content gaps between clusters
70
+ - `diversified`: Good topic balance — develop content gaps for deeper connections
71
+ - `dispersed`: Too scattered — focus on the most common gap topics
72
+
73
+ ---
74
+
75
+ ## Tool Reference
76
+
77
+ ### generate_knowledge_graph
78
+
79
+ Generates a knowledge graph from text using network analysis. Shows main concepts (nodes), relations, topical clusters, and structural gaps. Returns diversity statistics, influential nodes, and a compact DOT-format graph.
80
+
81
+ **Use for**: Getting structural insights into text, estimating bias, finding content gaps, topical clusters, and relations.
82
+
83
+ **Parameters**:
84
+ - `text` / `url` / `graphName`: Input source (provide one)
85
+ - `includeGraph` (boolean): Include full graph structure with cluster details
86
+ - `includeStatements` (boolean): Include original statements
87
+ - `addNodesAndEdges` (boolean): Include raw nodes and edges
88
+ - `modifyAnalyzedText`: Entity detection mode
89
+
90
+ **Returns**: statistics (modularity, diversity_stats), contentGaps, mainTopicalClusters, mainConcepts, conceptualGateways, topRelations, topInfluentialNodes, knowledgeGraphByCluster.
91
+
92
+ ---
93
+
94
+ ### create_knowledge_graph
95
+
96
+ Creates and saves a knowledge graph in InfraNodus from text or URL. Returns the same analysis as `generate_knowledge_graph` plus a link to the saved graph.
97
+
98
+ **Parameters**:
99
+ - `graphName` (string, required): Name for the new graph
100
+ - `text` / `url`: Input source
101
+ - `includeGraph`, `includeStatements`, `addNodesAndEdges`, `modifyAnalyzedText`: Same as above
102
+
103
+ **Returns**: Same as generate_knowledge_graph + `graphName`, `graphUrl`.
104
+
105
+ ---
106
+
107
+ ### generate_topical_clusters
108
+
109
+ Extracts compact topical clusters from text. Each cluster includes: name, keywords, cluster ID, degree ratio (%), betweenness ratio (%).
110
+
111
+ **Use for**: Compact topical summaries, improving LLM output structure, establishing topical authority for SEO.
112
+
113
+ **Parameters**: `text` / `url` / `graphName`
114
+
115
+ **Returns**: `topicalClusters` array. Format: "ClusterName: keyword1 keyword2 ... (id | degree% | betweenness%)"
116
+
117
+ ---
118
+
119
+ ### generate_content_gaps
120
+
121
+ Identifies content gaps — missing connections between topical clusters that represent areas for development.
122
+
123
+ **Use for**: Finding underexplored topics, identifying opportunities for research or content development.
124
+
125
+ **Parameters**: `text` / `url` / `graphName`
126
+
127
+ **Returns**: `contentGaps` array. Format: "Gap N: ClusterA (keywords) -> ClusterB (keywords)"
128
+
129
+ ---
130
+
131
+ ### generate_research_questions
132
+
133
+ Generates research questions that bridge content gaps identified in text.
134
+
135
+ **Use for**: Generating prompts for LLM workflows, research ideation, bridging knowledge gaps.
136
+
137
+ **Parameters**:
138
+ - `text` / `url` / `graphName`: Input source
139
+ - `useSeveralGaps` (boolean): Generate questions for multiple gaps (more diverse)
140
+ - `gapDepth` (number): Explore less prominent gaps (0 = top gap)
141
+ - `modelToUse` (string): AI model to use
142
+
143
+ **Returns**: `questions` array of research question strings.
144
+
145
+ ---
146
+
147
+ ### generate_research_ideas
148
+
149
+ Generates ideas that develop the text further based on content gaps. By default stays within the text's context; with `shouldTranscend: true`, links to wider discourse.
150
+
151
+ **Parameters**:
152
+ - `text` / `url` / `graphName`: Input source
153
+ - `useSeveralGaps` (boolean): Ideas for multiple gaps
154
+ - `shouldTranscend` (boolean): Connect to broader discourse
155
+ - `responseType`: 'response' (analytical) or 'idea' (business-oriented)
156
+ - `modelToUse` (string): AI model to use
157
+
158
+ **Returns**: `responses` array of idea strings.
159
+
160
+ ---
161
+
162
+ ### generate_contextual_hint
163
+
164
+ Generates a structural summary for LLMs to have a general overview of a text's context. Ideal for GraphRAG augmentation where vector similarity retrieval is supplemented with structural understanding.
165
+
166
+ **Parameters**: `text` / `url` / `graphName`
167
+
168
+ **Returns**: `textOverview` string containing MainConcepts (with degree, betweenness, topic_id), MainTopics, TopicalGaps, ConceptualGateways, Relations, DiversityStatistics in XML-like tags.
169
+
170
+ ---
171
+
172
+ ### develop_latent_topics
173
+
174
+ Identifies underdeveloped topics in text and generates ideas to develop them further.
175
+
176
+ **Parameters**:
177
+ - `text` / `url` / `graphName`: Input source
178
+ - `requestMode`: 'transcend' (ideas beyond text) or 'question' (research questions)
179
+ - `modelToUse` (string): AI model
180
+
181
+ **Returns**: `ideas` array, `mainTopics`, `latentTopicsToDevelop` (DOT-format relations).
182
+
183
+ ---
184
+
185
+ ### develop_conceptual_bridges
186
+
187
+ Identifies gateway concepts (high influence-to-degree ratio nodes that link different topical clusters) and generates ideas to connect the discourse to broader contexts.
188
+
189
+ **Use for**: "Outside the box" thinking, linking discourse to different contexts.
190
+
191
+ **Parameters**:
192
+ - `text` / `url` / `graphName`: Input source
193
+ - `requestMode`: 'transcend' or 'question'
194
+ - `modelToUse` (string): AI model
195
+
196
+ **Returns**: `ideas` array, `latentConceptsToDevelop`, `latentConceptsRelations`.
197
+
198
+ ---
199
+
200
+ ### develop_text_tool
201
+
202
+ Comprehensive text development tool that chains multiple analyses in sequence with progress tracking:
203
+ 1. `optimize_text_structure` — gap-based ideas (adapts to text bias/focus/dispersion)
204
+ 2. `develop_latent_topics` — underdeveloped topic ideas
205
+ 3. `develop_conceptual_bridges` — broader context connections
206
+
207
+ **Parameters**:
208
+ - `text` / `url` / `graphName`: Input source
209
+ - `transcendDiscourse` (boolean): Connect to wider context
210
+ - `useSeveralGaps` (boolean): Multiple gaps
211
+ - `gapDepth` (number): Gap depth
212
+ - `modelToUse` (string): AI model
213
+
214
+ **Returns**: `contentGapIdeas`, `latentTopicsIdeas`, `conceptualBridgesIdeas`, `contentGaps`, `conceptualBridges`, `latentTopics`, `mainTopics`.
215
+
216
+ ---
217
+
218
+ ### optimize_text_structure
219
+
220
+ Analyzes text bias/coherence and generates development suggestions. Automatically adapts approach:
221
+ - **Biased text** → develops least represented topics
222
+ - **Focused/diversified text** → develops content gaps between clusters
223
+ - **Dispersed text** → focuses on most common gap topics
224
+
225
+ **Parameters**:
226
+ - `text` / `url` / `graphName`: Input source
227
+ - `responseType`: 'response', 'idea', 'question', or 'transcend'
228
+ - `modelToUse` (string): AI model
229
+
230
+ **Returns**: `suggestions` array, `diversity_stats`, `mainTopicalClusters`, `contentGaps`, `mainConcepts`, `topicsToDevelop`, `conceptualGateways`, `topRelations`.
231
+
232
+ ---
233
+
234
+ ### analyze_existing_graph_by_name
235
+
236
+ Retrieves and analyzes an existing graph from your InfraNodus account.
237
+
238
+ **Parameters**:
239
+ - `graphName` (string, required): Name of existing graph
240
+ - `includeStatements`, `includeGraph`, `addNodesAndEdges`, `includeGraphSummary`, `modifyAnalyzedText`
241
+
242
+ **Returns**: Full graph analysis (statistics, clusters, gaps, concepts, relations).
243
+
244
+ ---
245
+
246
+ ### analyze_text
247
+
248
+ General text analysis. Similar to `generate_knowledge_graph` but focuses on analysis results and recommendations rather than the graph structure.
249
+
250
+ **Parameters**:
251
+ - `text` / `url`: Input source
252
+ - `includeStatements`, `includeGraph`, `addNodesAndEdges`, `includeGraphSummary`, `modifyAnalyzedText`
253
+
254
+ **Returns**: statistics, contentGaps, mainTopicalClusters, mainConcepts, topRelations, statements.
255
+
256
+ ---
257
+
258
+ ### generate_responses_from_graph
259
+
260
+ Generate AI responses from an existing InfraNodus graph or ontology using a custom prompt.
261
+
262
+ **Parameters**:
263
+ - `text` / `url` / `graphName`: Input source
264
+ - `prompt` (string, required): Custom prompt for response generation
265
+ - `modelToUse` (string): AI model
266
+
267
+ **Returns**: AI-generated response based on graph context.
268
+
269
+ ---
270
+
271
+ ### retrieve_from_knowledge_base
272
+
273
+ GraphRAG retrieval from an existing knowledge graph. Retrieves statements relevant to a prompt using both vector similarity and graph-based retrieval.
274
+
275
+ **Parameters**:
276
+ - `graphName` (string, required): Name of existing graph
277
+ - `prompt` (string, required): Query prompt
278
+ - `includeGraphSummary` (boolean): Include structural overview for RAG augmentation
279
+ - `includeGraph`, `extendedGraphSummary`, `compactStatements`
280
+
281
+ **Returns**: `retrievedStatements` (with content, categories, similarity scores), optionally `graphSummary`.
282
+
283
+ ---
284
+
285
+ ### list_graphs
286
+
287
+ Lists all graphs in the user's account with optional filtering.
288
+
289
+ **Parameters**:
290
+ - `nameContains` (string): Filter by name (comma-separated for OR logic)
291
+ - `type` (string): Filter by type (STANDARD, MINDMAP, MEMORY, ONTOLOGY, CSV, PDF, etc.)
292
+ - `fromDate`, `toDate` (ISO string): Date range
293
+ - `language` (string): Language code
294
+ - `favorite` (boolean): Favorites only
295
+
296
+ **Returns**: `totalGraphs`, `filters`, `graphs` array (id, name, description, type, isFavorite, isPublic, createdAt, language).
297
+
298
+ ---
299
+
300
+ ### search
301
+
302
+ Search through existing InfraNodus graphs for statements containing a search term.
303
+
304
+ **Parameters**:
305
+ - `query` (string, required): Search term
306
+ - `contextNames` (string[]): Limit to specific graph names
307
+ - `contextTypes` (string[]): Limit to specific graph types
308
+
309
+ **Returns**: `results` array (id, title, url).
310
+
311
+ ---
312
+
313
+ ### fetch
314
+
315
+ Fetch specific statements from a search result using the ID from `search`.
316
+
317
+ **Parameters**:
318
+ - `id` (string, required): Search result ID (format: "username:graphName:query")
319
+
320
+ **Returns**: `id`, `title`, `text`, `url`.
321
+
322
+ ---
323
+
324
+ ### memory_add_relations
325
+
326
+ 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.
327
+
328
+ **Parameters**:
329
+ - `graphName` (string, required): Memory graph name (lowercase, dashes for spaces)
330
+ - `text` (string, required): Text with entities marked as `[[wikilinks]]` or auto-detected
331
+ - `modifyAnalyzedText`: Entity detection mode (default: 'extractEntitiesOnly')
332
+ - `includeGraph`, `includeStatements`, `addNodesAndEdges`
333
+
334
+ **Returns**: Full graph analysis + `graphName`, `graphUrl`.
335
+
336
+ ---
337
+
338
+ ### memory_get_relations
339
+
340
+ Retrieve relations from InfraNodus memory for a specific entity or context.
341
+
342
+ **Parameters**:
343
+ - `entityName` (string): Entity to search for (use `[[wikilinks]]` syntax, underscores for spaces)
344
+ - `memoryContextName` (string): Specific memory graph name (empty = search all)
345
+
346
+ **Returns**: `statements` array, `userName`, `graphNames`, `graphUrls`.
347
+
348
+ ---
349
+
350
+ ### overlap_between_texts
351
+
352
+ Find common topics and relations that exist across all provided texts/URLs/graphs. If at least one context has no intersections with the rest, no results are shown.
353
+
354
+ **Parameters**:
355
+ - `contexts` (array, required, min 2): Array of `{text: "..."}`, `{url: "..."}`, or `{graphName: "..."}`
356
+ - `includeStatements`, `includeGraph`, `addNodesAndEdges`, `modifyAnalyzedText`
357
+
358
+ **Returns**: Analysis of overlapping content only (clusters, concepts, relations, statements).
359
+
360
+ ---
361
+
362
+ ### difference_between_texts
363
+
364
+ Find what's missing in the first text/URL/graph that is present in the others. Shows topics and relations (not just keywords) because most texts share the same concepts — it's the relations that differ.
365
+
366
+ **Use for**: Finding content gaps relative to existing discourse, enriching content with missing perspectives.
367
+
368
+ **Parameters**:
369
+ - `contexts` (array, required, min 2): First item is the target; remaining items are references
370
+ - `includeStatements`, `includeGraph`, `addNodesAndEdges`, `modifyAnalyzedText`
371
+
372
+ **Returns**: Analysis of content present in references but missing from target.
373
+
374
+ ---
375
+
376
+ ### merged_graph_from_texts
377
+
378
+ Merge multiple sources into one graph. Provides topical clusters and gaps across the combined content.
379
+
380
+ **Use for**: Getting an overview of a discourse from multiple sources, identifying cross-source gaps.
381
+
382
+ **Parameters**:
383
+ - `contexts` (array, required, min 2): Array of `{text: "..."}`, `{url: "..."}`, or `{graphName: "..."}`
384
+ - `includeStatements`, `includeGraph`, `addNodesAndEdges`, `modifyAnalyzedText`
385
+
386
+ **Returns**: Combined graph analysis with merged clusters, gaps, and concepts.
387
+
388
+ ---
389
+
390
+ ### analyze_google_search_results
391
+
392
+ Generates a knowledge graph from Google search results for given queries. Shows what topics are covered in current search results (informational supply).
393
+
394
+ **Parameters**:
395
+ - `queries` (string[], required): Search queries
396
+ - `importLanguage` (string): Language code (EN, DE, FR, ES, etc.)
397
+ - `importCountry` (string): Country code (US, GB, DE, etc.)
398
+ - `showExtendedGraphInfo` (boolean): Include diversity stats and graph summary
399
+ - `includeSearchResults` (boolean): Include raw search result URLs
400
+ - `includeGraph`, `includeNodesAndEdges`
401
+
402
+ **Returns**: Graph analysis of search results (clusters, gaps, concepts) + optionally search result URLs.
403
+
404
+ ---
405
+
406
+ ### analyze_related_search_queries
407
+
408
+ Analyzes which search queries people use together with your queries (Google "people also search for"). Shows informational demand — what people are looking for.
409
+
410
+ **Parameters**:
411
+ - `queries` (string[], required): Search queries
412
+ - `importLanguage`, `importCountry`
413
+ - `keywordsSource`: 'related' (Google suggestions) or 'adwords' (broader range)
414
+ - `showExtendedGraphInfo`, `includeSearchQueries`, `includeGraph`, `includeNodesAndEdges`
415
+
416
+ **Returns**: Graph analysis of related queries + optionally raw queries with search volume.
417
+
418
+ ---
419
+
420
+ ### search_queries_vs_search_results
421
+
422
+ Finds clusters of high-volume search queries that don't appear in search results for the same requests. Reveals content gaps in current search results.
423
+
424
+ **Parameters**:
425
+ - `queries` (string[], required): Search queries
426
+ - `importLanguage`, `importCountry`
427
+ - `showExtendedGraphInfo`, `includeSearchQueries`, `includeGraph`
428
+
429
+ **Returns**: Analysis of queries people search for but don't find, with topical clusters and gaps.
430
+
431
+ ---
432
+
433
+ ### generate_seo_report
434
+
435
+ Comprehensive SEO analysis. Extracts text keywords, retrieves Google search results and search intent data, compares them, and synthesizes content ideas. Chains multiple API calls (~90 second timeout needed).
436
+
437
+ **Parameters**:
438
+ - `text` / `url`: Content to analyze
439
+ - `contentToExtract`: 'all' (default), 'header tags' (h1-h6), or 'link tags'
440
+ - `importLanguage`, `importCountry`
441
+ - `numberOfKeywordsToExtract` (number, max 4): Top keyword groups for analysis
442
+ - `numberOfTopicsToExtract` (number, max 4): Top topic clusters for analysis
443
+ - `useProxy` (boolean): Use proxy for URL fetch (if first request fails)
444
+
445
+ **Returns**:
446
+ - `inSearchResultsNotInText`: Topics in search results but not in your text
447
+ - `inSearchQueriesNotInText`: Topics people search for but not in your text
448
+ - `inSearchQueriesNotInResults`: Topics people search for but don't find anywhere
449
+ - `topMissingQueries`: Specific high-volume queries with search volume data
450
+
451
+ ---
452
+
453
+ ## Key Concepts
454
+
455
+ **Topical Clusters**: Groups of related concepts identified by community detection algorithms. Format: "Name: keyword1 keyword2 ... (cluster_id | degree_ratio% | betweenness_ratio%)"
456
+
457
+ **Content Gaps**: Missing connections between topical clusters. These represent areas where the discourse could be developed by linking currently disconnected themes.
458
+
459
+ **Conceptual Gateways**: Nodes with high betweenness centrality relative to their degree — they bridge different topical clusters and are optimal for connecting the discourse to broader contexts.
460
+
461
+ **Betweenness Centrality**: Measures how often a concept appears on shortest paths between other concepts. High betweenness = influential connector between different topic areas.
462
+
463
+ **Modularity**: Measures how well the graph divides into distinct communities. High modularity = clearly separated topics. Low modularity = highly interconnected discourse.
464
+
465
+ **Diversity Score**: Overall assessment of text structure balance:
466
+ - `biased`: Dominated by single perspective/cluster
467
+ - `focused`: Concentrated on specific themes with some variation
468
+ - `diversified`: Good balance across multiple topics
469
+ - `dispersed`: Too scattered, lacks coherent structure