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,56 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import * as dotenv from 'dotenv';
5
+ import createServer from '../dist/index.js';
6
+ import { brand, brandApiKey, brandApiBase } from '../dist/config/brand.js';
7
+
8
+ // Main function for CLI execution
9
+ async function main() {
10
+ // Load environment variables
11
+ dotenv.config();
12
+
13
+ // Brand (and thus API env vars / tool set) is selected by the BRAND env var.
14
+ const config = {
15
+ apiKey: brandApiKey(),
16
+ apiBase: brandApiBase(),
17
+ };
18
+
19
+ // Validate config
20
+ if (!config.apiKey) {
21
+ console.error(
22
+ `WARNING: Set ${brand.envPrefix}_API_KEY in environment variables to ensure you don't hit the rate limit`
23
+ );
24
+ }
25
+
26
+ // Create server with config
27
+ const server = createServer({ config });
28
+
29
+ // Create STDIO transport
30
+ const transport = new StdioServerTransport();
31
+
32
+ // Handle graceful shutdown
33
+ process.on("SIGINT", async () => {
34
+ await server.close();
35
+ process.exit(0);
36
+ });
37
+
38
+ process.on("SIGTERM", async () => {
39
+ await server.close();
40
+ process.exit(0);
41
+ });
42
+
43
+ try {
44
+ await server.connect(transport);
45
+ // Server is running - no console output to avoid protocol interference
46
+ } catch (error) {
47
+ console.error("ERROR: MCP server failed to connect", error);
48
+ process.exit(1);
49
+ }
50
+ }
51
+
52
+ // Run the main function
53
+ main().catch((error) => {
54
+ console.error("ERROR: Fatal error of MCP server", error);
55
+ process.exit(1);
56
+ });
@@ -0,0 +1,3 @@
1
+ import { GraphResponse } from "../types/index.js";
2
+ export declare function makeInfraNodusRequest(endpoint: string, body: any, method?: string): Promise<GraphResponse>;
3
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGlD,wBAAsB,qBAAqB,CAC1C,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,GAAG,EACT,MAAM,GAAE,MAAe,GACrB,OAAO,CAAC,aAAa,CAAC,CAgCxB"}
@@ -0,0 +1,30 @@
1
+ import { getConfig } from "./config-store.js";
2
+ export async function makeInfraNodusRequest(endpoint, body, method = "POST") {
3
+ try {
4
+ const config = getConfig();
5
+ const requestBody = { ...body, modal: "mcp_server" };
6
+ const response = await fetch(`${config.apiBase}${endpoint}`, {
7
+ method,
8
+ headers: {
9
+ "Content-Type": "application/json",
10
+ Authorization: `Bearer ${config.apiKey}`,
11
+ },
12
+ ...(method !== "GET" && { body: JSON.stringify(requestBody) }),
13
+ });
14
+ if (!response.ok) {
15
+ const errorText = await response.text();
16
+ throw new Error(`API request failed (${response.status}): ${errorText}`);
17
+ }
18
+ const data = await response.json();
19
+ // Handle wrapped response format
20
+ if (data.entriesAndGraphOfContext) {
21
+ return data.entriesAndGraphOfContext;
22
+ }
23
+ return data;
24
+ }
25
+ catch (error) {
26
+ // Don't log to console as it interferes with MCP protocol
27
+ throw error;
28
+ }
29
+ }
30
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAC1C,QAAgB,EAChB,IAAS,EACT,SAAiB,MAAM;IAEvB,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAE3B,MAAM,WAAW,GAAG,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;QAErD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,OAAO,GAAG,QAAQ,EAAE,EAAE;YAC5D,MAAM;YACN,OAAO,EAAE;gBACR,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,MAAM,CAAC,MAAM,EAAE;aACxC;YACD,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC;SAC9D,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YAClB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,CAAC,MAAM,MAAM,SAAS,EAAE,CAAC,CAAC;QAC1E,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAEnC,iCAAiC;QACjC,IAAI,IAAI,CAAC,wBAAwB,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC,wBAAwB,CAAC;QACtC,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,0DAA0D;QAC1D,MAAM,KAAK,CAAC;IACb,CAAC;AACF,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Config } from "../config/index.js";
2
+ export declare function runWithConfig<T>(config: Config, fn: () => T): T;
3
+ export declare function getConfig(): Config;
4
+ //# sourceMappingURL=config-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-store.d.ts","sourceRoot":"","sources":["../../src/api/config-store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAK5C,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAE/D;AAED,wBAAgB,SAAS,IAAI,MAAM,CAMlC"}
@@ -0,0 +1,12 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ import { brandApiBase } from "../config/brand.js";
3
+ const configStorage = new AsyncLocalStorage();
4
+ export function runWithConfig(config, fn) {
5
+ return configStorage.run(config, fn);
6
+ }
7
+ export function getConfig() {
8
+ return (configStorage.getStore() ??
9
+ global.brandConfig ??
10
+ { apiKey: "", apiBase: brandApiBase() });
11
+ }
12
+ //# sourceMappingURL=config-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-store.js","sourceRoot":"","sources":["../../src/api/config-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,aAAa,GAAG,IAAI,iBAAiB,EAAU,CAAC;AAEtD,MAAM,UAAU,aAAa,CAAI,MAAc,EAAE,EAAW;IAC3D,OAAO,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,SAAS;IACxB,OAAO,CACN,aAAa,CAAC,QAAQ,EAAE;QACvB,MAAc,CAAC,WAAW;QAC3B,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,CACvC,CAAC;AACH,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * OAuth2-style authentication provider for the MCP HTTP server
3
+ * Validates API keys and issues JWT access tokens
4
+ */
5
+ import { InfraNodusUserInfo, TokenResponse, AuthenticatedRequest, RegisteredClient, ClientRegistrationRequest, ClientRegistrationResponse } from "./types.js";
6
+ /**
7
+ * Validate an API key by calling the /api/v1/userId endpoint
8
+ * Returns user info if valid, null if invalid
9
+ */
10
+ export declare function validateApiKey(apiKey: string): Promise<InfraNodusUserInfo | null>;
11
+ /**
12
+ * Exchange an API key for a JWT access token
13
+ */
14
+ export declare function exchangeApiKeyForToken(apiKey: string): Promise<TokenResponse | null>;
15
+ /**
16
+ * Verify a JWT access token and return the authenticated request context
17
+ * This is now stateless - all info is in the JWT itself
18
+ */
19
+ export declare function verifyAccessToken(token: string): AuthenticatedRequest | null;
20
+ /**
21
+ * Revoke a session (logout)
22
+ */
23
+ export declare function revokeSession(sessionId: string): boolean;
24
+ /**
25
+ * Get session count (for monitoring)
26
+ */
27
+ export declare function getSessionCount(): number;
28
+ /**
29
+ * Clean up expired sessions (call periodically)
30
+ */
31
+ export declare function cleanupExpiredSessions(): number;
32
+ /**
33
+ * Register a new OAuth2 client
34
+ */
35
+ export declare function registerClient(request: ClientRegistrationRequest): ClientRegistrationResponse;
36
+ /**
37
+ * Get a registered client by ID
38
+ */
39
+ export declare function getClient(clientId: string): RegisteredClient | null;
40
+ /**
41
+ * Validate client credentials
42
+ */
43
+ export declare function validateClient(clientId: string, clientSecret?: string): boolean;
44
+ /**
45
+ * Validate redirect URI for a client
46
+ */
47
+ export declare function validateRedirectUri(clientId: string, redirectUri: string): boolean;
48
+ /**
49
+ * Create an authorization code (as a signed JWT for stateless validation across instances)
50
+ */
51
+ export declare function createAuthorizationCode(clientId: string, redirectUri: string, apiKey: string, scope?: string, codeChallenge?: string, codeChallengeMethod?: string): string;
52
+ /**
53
+ * Exchange authorization code for token
54
+ */
55
+ export declare function exchangeAuthorizationCode(code: string, clientId: string, redirectUri: string, codeVerifier?: string): Promise<TokenResponse | null>;
56
+ //# sourceMappingURL=oauth-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-provider.d.ts","sourceRoot":"","sources":["../../src/auth/oauth-provider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EACN,kBAAkB,EAElB,aAAa,EAEb,oBAAoB,EACpB,gBAAgB,EAChB,yBAAyB,EACzB,0BAA0B,EAE1B,MAAM,YAAY,CAAC;AAmBpB;;;GAGG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAmCvF;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA4B1F;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAmC5E;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAa/C;AAYD;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,yBAAyB,GAAG,0BAA0B,CA0B7F;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAEnE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAK/E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAIlF;AAQD;;GAEG;AACH,wBAAgB,uBAAuB,CACtC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,EACd,aAAa,CAAC,EAAE,MAAM,EACtB,mBAAmB,CAAC,EAAE,MAAM,GAC1B,MAAM,CAcR;AAeD;;GAEG;AACH,wBAAsB,yBAAyB,CAC9C,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAwC/B"}
@@ -0,0 +1,295 @@
1
+ /**
2
+ * OAuth2-style authentication provider for the MCP HTTP server
3
+ * Validates API keys and issues JWT access tokens
4
+ */
5
+ import jwt from "jsonwebtoken";
6
+ import crypto from "crypto";
7
+ import { brandApiBase } from "../config/brand.js";
8
+ // In-memory stores
9
+ const sessions = new Map();
10
+ const clients = new Map();
11
+ const authorizationCodes = new Map();
12
+ // Configuration
13
+ const JWT_SECRET = process.env.JWT_SECRET || crypto.randomBytes(32).toString("hex");
14
+ const TOKEN_EXPIRY_SECONDS = 86400 * 365 * 100; // 100 years - effectively never expires
15
+ const BRAND_API_BASE = brandApiBase();
16
+ /**
17
+ * Hash an API key for storage in JWT (we don't store the actual key in the token)
18
+ */
19
+ function hashApiKey(apiKey) {
20
+ return crypto.createHash("sha256").update(apiKey).digest("hex").slice(0, 16);
21
+ }
22
+ /**
23
+ * Validate an API key by calling the /api/v1/userId endpoint
24
+ * Returns user info if valid, null if invalid
25
+ */
26
+ export async function validateApiKey(apiKey) {
27
+ try {
28
+ const response = await fetch(`${BRAND_API_BASE}/userId`, {
29
+ method: "POST",
30
+ headers: {
31
+ "Content-Type": "application/json",
32
+ Authorization: `Bearer ${apiKey}`,
33
+ },
34
+ body: JSON.stringify({}),
35
+ });
36
+ if (!response.ok) {
37
+ return null;
38
+ }
39
+ const data = await response.json();
40
+ // Check for valid response format: {"userId": 486, "userName": "circadian"}
41
+ if (data && typeof data.userId === "number" && typeof data.userName === "string") {
42
+ return {
43
+ userId: data.userId,
44
+ userName: data.userName,
45
+ };
46
+ }
47
+ // Check for error indicators
48
+ if (!data || data.error || typeof data === "string") {
49
+ return null;
50
+ }
51
+ return null;
52
+ }
53
+ catch (error) {
54
+ // Network error or invalid response
55
+ return null;
56
+ }
57
+ }
58
+ /**
59
+ * Exchange an API key for a JWT access token
60
+ */
61
+ export async function exchangeApiKeyForToken(apiKey) {
62
+ // Validate the API key against the brand API
63
+ const userInfo = await validateApiKey(apiKey);
64
+ if (!userInfo) {
65
+ return null;
66
+ }
67
+ // Create a stateless session ID (just for tracking, not stored in memory)
68
+ const sessionId = crypto.randomUUID();
69
+ // Create JWT payload - include API key directly for stateless verification
70
+ // The JWT is signed so it can't be tampered with
71
+ const payload = {
72
+ type: "access_token",
73
+ userId: userInfo.userId,
74
+ userName: userInfo.userName,
75
+ apiKey: apiKey, // Include API key for stateless verification
76
+ sessionId: sessionId,
77
+ };
78
+ // Sign JWT
79
+ const accessToken = jwt.sign(payload, JWT_SECRET, { expiresIn: TOKEN_EXPIRY_SECONDS });
80
+ return {
81
+ access_token: accessToken,
82
+ token_type: "Bearer",
83
+ expires_in: TOKEN_EXPIRY_SECONDS,
84
+ };
85
+ }
86
+ /**
87
+ * Verify a JWT access token and return the authenticated request context
88
+ * This is now stateless - all info is in the JWT itself
89
+ */
90
+ export function verifyAccessToken(token) {
91
+ try {
92
+ const decoded = jwt.verify(token, JWT_SECRET);
93
+ // Check if this is an auth_code being used as access token (wrong!)
94
+ if (decoded.type === "auth_code") {
95
+ console.log(`[AUTH] Received auth_code instead of access_token`);
96
+ return null;
97
+ }
98
+ // Need API key in the token for stateless verification
99
+ if (!decoded.apiKey) {
100
+ console.log(`[AUTH] Token missing apiKey - old format token, needs re-auth`);
101
+ return null;
102
+ }
103
+ // All info is in the JWT - no need to look up session
104
+ return {
105
+ userId: decoded.userId,
106
+ userName: decoded.userName,
107
+ apiKey: decoded.apiKey,
108
+ sessionId: decoded.sessionId,
109
+ };
110
+ }
111
+ catch (error) {
112
+ // Invalid or expired token
113
+ console.log(`[AUTH] JWT verification error: ${error.message}`);
114
+ return null;
115
+ }
116
+ }
117
+ /**
118
+ * Revoke a session (logout)
119
+ */
120
+ export function revokeSession(sessionId) {
121
+ return sessions.delete(sessionId);
122
+ }
123
+ /**
124
+ * Get session count (for monitoring)
125
+ */
126
+ export function getSessionCount() {
127
+ return sessions.size;
128
+ }
129
+ /**
130
+ * Clean up expired sessions (call periodically)
131
+ */
132
+ export function cleanupExpiredSessions() {
133
+ const now = Date.now();
134
+ const expiryMs = TOKEN_EXPIRY_SECONDS * 1000;
135
+ let cleaned = 0;
136
+ for (const [sessionId, session] of sessions.entries()) {
137
+ if (now - session.createdAt > expiryMs) {
138
+ sessions.delete(sessionId);
139
+ cleaned++;
140
+ }
141
+ }
142
+ return cleaned;
143
+ }
144
+ // Start periodic cleanup every 10 minutes
145
+ setInterval(() => {
146
+ cleanupExpiredSessions();
147
+ cleanupExpiredAuthCodes();
148
+ }, 10 * 60 * 1000);
149
+ // ============================================================================
150
+ // OAuth2 Dynamic Client Registration (RFC 7591)
151
+ // ============================================================================
152
+ /**
153
+ * Register a new OAuth2 client
154
+ */
155
+ export function registerClient(request) {
156
+ const clientId = crypto.randomUUID();
157
+ const clientSecret = crypto.randomBytes(32).toString("hex");
158
+ const client = {
159
+ client_id: clientId,
160
+ client_secret: clientSecret,
161
+ redirect_uris: request.redirect_uris,
162
+ client_name: request.client_name,
163
+ created_at: Date.now(),
164
+ };
165
+ clients.set(clientId, client);
166
+ return {
167
+ client_id: clientId,
168
+ client_secret: clientSecret,
169
+ client_id_issued_at: Math.floor(Date.now() / 1000),
170
+ client_secret_expires_at: 0, // Never expires
171
+ redirect_uris: request.redirect_uris,
172
+ client_name: request.client_name,
173
+ token_endpoint_auth_method: request.token_endpoint_auth_method || "client_secret_post",
174
+ grant_types: request.grant_types || ["authorization_code"],
175
+ response_types: request.response_types || ["code"],
176
+ scope: request.scope,
177
+ };
178
+ }
179
+ /**
180
+ * Get a registered client by ID
181
+ */
182
+ export function getClient(clientId) {
183
+ return clients.get(clientId) || null;
184
+ }
185
+ /**
186
+ * Validate client credentials
187
+ */
188
+ export function validateClient(clientId, clientSecret) {
189
+ const client = clients.get(clientId);
190
+ if (!client)
191
+ return false;
192
+ if (clientSecret && client.client_secret !== clientSecret)
193
+ return false;
194
+ return true;
195
+ }
196
+ /**
197
+ * Validate redirect URI for a client
198
+ */
199
+ export function validateRedirectUri(clientId, redirectUri) {
200
+ const client = clients.get(clientId);
201
+ if (!client)
202
+ return false;
203
+ return client.redirect_uris.includes(redirectUri);
204
+ }
205
+ // ============================================================================
206
+ // OAuth2 Authorization Code Flow
207
+ // ============================================================================
208
+ const AUTH_CODE_EXPIRY_SECONDS = 600; // 10 minutes
209
+ /**
210
+ * Create an authorization code (as a signed JWT for stateless validation across instances)
211
+ */
212
+ export function createAuthorizationCode(clientId, redirectUri, apiKey, scope, codeChallenge, codeChallengeMethod) {
213
+ // Create a JWT-based authorization code that can be validated by any instance
214
+ const payload = {
215
+ type: "auth_code",
216
+ client_id: clientId,
217
+ redirect_uri: redirectUri,
218
+ api_key: apiKey, // Encrypted or hashed in production
219
+ scope,
220
+ code_challenge: codeChallenge,
221
+ code_challenge_method: codeChallengeMethod,
222
+ };
223
+ const code = jwt.sign(payload, JWT_SECRET, { expiresIn: AUTH_CODE_EXPIRY_SECONDS });
224
+ return code;
225
+ }
226
+ // Track used codes to prevent replay — stores hash → timestamp for TTL cleanup
227
+ const usedCodes = new Map();
228
+ /**
229
+ * Exchange authorization code for token
230
+ */
231
+ export async function exchangeAuthorizationCode(code, clientId, redirectUri, codeVerifier) {
232
+ try {
233
+ // Decode the JWT-based authorization code
234
+ const authCode = jwt.verify(code, JWT_SECRET);
235
+ // Validate it's an auth code
236
+ if (authCode.type !== "auth_code")
237
+ return null;
238
+ // Validate client_id and redirect_uri match
239
+ if (authCode.client_id !== clientId)
240
+ return null;
241
+ if (authCode.redirect_uri !== redirectUri)
242
+ return null;
243
+ // Check if code was already used (replay protection)
244
+ const codeHash = crypto.createHash("sha256").update(code).digest("hex").slice(0, 16);
245
+ if (usedCodes.has(codeHash))
246
+ return null;
247
+ usedCodes.set(codeHash, Date.now());
248
+ // Validate PKCE if used
249
+ if (authCode.code_challenge) {
250
+ if (!codeVerifier)
251
+ return null;
252
+ let computedChallenge;
253
+ if (authCode.code_challenge_method === "S256") {
254
+ computedChallenge = crypto
255
+ .createHash("sha256")
256
+ .update(codeVerifier)
257
+ .digest("base64url");
258
+ }
259
+ else {
260
+ computedChallenge = codeVerifier; // plain method
261
+ }
262
+ if (computedChallenge !== authCode.code_challenge)
263
+ return null;
264
+ }
265
+ // Exchange the API key for a token
266
+ return exchangeApiKeyForToken(authCode.api_key);
267
+ }
268
+ catch (error) {
269
+ // Invalid or expired JWT
270
+ return null;
271
+ }
272
+ }
273
+ /**
274
+ * Clean up expired authorization codes
275
+ */
276
+ function cleanupExpiredAuthCodes() {
277
+ const now = Date.now();
278
+ let cleaned = 0;
279
+ for (const [code, authCode] of authorizationCodes.entries()) {
280
+ if (authCode.expires_at < now) {
281
+ authorizationCodes.delete(code);
282
+ cleaned++;
283
+ }
284
+ }
285
+ // Clean up used code hashes older than the auth code expiry window
286
+ const usedCodeTtlMs = AUTH_CODE_EXPIRY_SECONDS * 1000;
287
+ for (const [hash, timestamp] of usedCodes.entries()) {
288
+ if (now - timestamp > usedCodeTtlMs) {
289
+ usedCodes.delete(hash);
290
+ cleaned++;
291
+ }
292
+ }
293
+ return cleaned;
294
+ }
295
+ //# sourceMappingURL=oauth-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-provider.js","sourceRoot":"","sources":["../../src/auth/oauth-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Auth-related types for the HTTP server
3
+ */
4
+ export interface InfraNodusUserInfo {
5
+ userId: number;
6
+ userName: string;
7
+ }
8
+ export interface TokenPayload {
9
+ userId: number;
10
+ userName: string;
11
+ apiKeyHash: string;
12
+ iat: number;
13
+ exp: number;
14
+ }
15
+ export interface TokenResponse {
16
+ access_token: string;
17
+ token_type: "Bearer";
18
+ expires_in: number;
19
+ }
20
+ export interface TokenRequest {
21
+ api_key: string;
22
+ grant_type?: "api_key";
23
+ }
24
+ export interface SessionData {
25
+ userId: number;
26
+ userName: string;
27
+ apiKey: string;
28
+ createdAt: number;
29
+ }
30
+ export interface AuthenticatedRequest {
31
+ userId: number;
32
+ userName: string;
33
+ apiKey: string;
34
+ sessionId: string;
35
+ }
36
+ export interface ErrorResponse {
37
+ error: string;
38
+ error_description?: string;
39
+ }
40
+ export interface ClientRegistrationRequest {
41
+ redirect_uris: string[];
42
+ client_name?: string;
43
+ token_endpoint_auth_method?: string;
44
+ grant_types?: string[];
45
+ response_types?: string[];
46
+ scope?: string;
47
+ }
48
+ export interface ClientRegistrationResponse {
49
+ client_id: string;
50
+ client_secret?: string;
51
+ client_id_issued_at?: number;
52
+ client_secret_expires_at?: number;
53
+ redirect_uris: string[];
54
+ client_name?: string;
55
+ token_endpoint_auth_method: string;
56
+ grant_types: string[];
57
+ response_types: string[];
58
+ scope?: string;
59
+ }
60
+ export interface RegisteredClient {
61
+ client_id: string;
62
+ client_secret: string;
63
+ redirect_uris: string[];
64
+ client_name?: string;
65
+ created_at: number;
66
+ }
67
+ export interface AuthorizationRequest {
68
+ response_type: string;
69
+ client_id: string;
70
+ redirect_uri: string;
71
+ scope?: string;
72
+ state?: string;
73
+ code_challenge?: string;
74
+ code_challenge_method?: string;
75
+ }
76
+ export interface AuthorizationCode {
77
+ code: string;
78
+ client_id: string;
79
+ redirect_uri: string;
80
+ api_key: string;
81
+ scope?: string;
82
+ code_challenge?: string;
83
+ code_challenge_method?: string;
84
+ expires_at: number;
85
+ }
86
+ export interface TokenRequestAuthCode {
87
+ grant_type: "authorization_code";
88
+ code: string;
89
+ redirect_uri: string;
90
+ client_id: string;
91
+ code_verifier?: string;
92
+ }
93
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Auth-related types for the HTTP server
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Brand configuration.
3
+ *
4
+ * One codebase ships as multiple branded MCP servers. The active brand is
5
+ * selected at runtime by the BRAND environment variable (set per deploy target,
6
+ * e.g. in each Fly app's [env] block). This keeps a single source tree and a
7
+ * single built image — only BRAND (and the per-app secrets) differ between
8
+ * deployments.
9
+ *
10
+ * Defaults to "infranodus" (the full product, all tools exposed) when BRAND is
11
+ * unset, so a missing BRAND never silently hides tools.
12
+ */
13
+ export type BrandId = "infranodus" | "keywordgraph";
14
+ export interface BrandDef {
15
+ id: BrandId;
16
+ /** Human-facing product name shown in titles, resources, and auth pages. */
17
+ name: string;
18
+ /** Bare domain, e.g. for links and copy. */
19
+ domain: string;
20
+ /** Default API base when the brand's *_API_BASE env var is unset. */
21
+ apiBase: string;
22
+ /** Prefix for this brand's env vars: `${envPrefix}_API_KEY`, `${envPrefix}_API_BASE`. */
23
+ envPrefix: string;
24
+ /** MCP server identifier reported to clients. */
25
+ serverName: string;
26
+ /**
27
+ * Tool `name` values NOT registered for this brand. Every tool file is always
28
+ * compiled in; this list is the single source of truth for which ones a brand
29
+ * exposes. New upstream tools appear in every brand automatically unless added
30
+ * here.
31
+ */
32
+ excludedTools: string[];
33
+ /**
34
+ * npm publish identity. The committed package.json holds one brand; the
35
+ * publish script (scripts/publish-brand.mjs) rewrites these fields for the
36
+ * brand being published, then restores. `binName` must match a launcher in
37
+ * bin/ that bakes in this brand's BRAND value.
38
+ */
39
+ npm: {
40
+ packageName: string;
41
+ binName: string;
42
+ description: string;
43
+ repository: string;
44
+ keywords: string[];
45
+ };
46
+ }
47
+ export declare const brand: BrandDef;
48
+ /**
49
+ * API key for the active brand. Prefers the brand-specific var
50
+ * (`${envPrefix}_API_KEY`) and falls back to the other brand's var so a single
51
+ * key works in mixed local setups.
52
+ */
53
+ export declare function brandApiKey(): string;
54
+ /** API base for the active brand: brand-specific env var, else the brand default. */
55
+ export declare function brandApiBase(): string;
56
+ /** Whether a tool (by its MCP `name`) is exposed for the active brand. */
57
+ export declare function isToolEnabled(name: string): boolean;
58
+ //# sourceMappingURL=brand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brand.d.ts","sourceRoot":"","sources":["../../src/config/brand.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,MAAM,OAAO,GAAG,YAAY,GAAG,cAAc,CAAC;AAEpD,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,OAAO,CAAC;IACZ,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAC;IAChB,yFAAyF;IACzF,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB;;;;;OAKG;IACH,GAAG,EAAE;QACJ,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;CACF;AAsED,eAAO,MAAM,KAAK,EAAE,QAAyB,CAAC;AAE9C;;;;GAIG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAOpC;AAED,qFAAqF;AACrF,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD"}