cuemap-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kaan Demirel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # CueMap MCP Server
2
+
3
+ The [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server for CueMap, allowing AI coding assistants (like Claude Desktop, Cursor, Windsurf, and Antigravity) to instantly recall codebase context using the CueMap engine.
4
+
5
+ ## Zero-Config Deployment
6
+
7
+ The CueMap MCP Server is designed to work completely out-of-the-box. When started, it automatically manages a high-performance Rust instance of the CueMap Server in the background.
8
+
9
+ You do **not** need to install or run the CueMap CLI manually. The correct pre-compiled binary for your operating system is automatically downloaded via optional NPM dependencies.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ # Global installation makes the `cuemap-mcp` command available
15
+ npm install -g @cuemap/mcp-server
16
+ ```
17
+
18
+ *(Note: Ensure your package manager is configured to download `optionalDependencies` so the local Rust binary is included).*
19
+
20
+ ## Configuration (Environment Variables)
21
+
22
+ By default, the embedded engine runs on port `8080`. You can customize the server behavior by passing the following environment variables in your MCP configuration:
23
+
24
+ - `CUEMAP_PORT`: Override the port the embedded engine binds to (default: `8080`).
25
+ - `CUEMAP_CONFIG_PATH`: Absolute path to a custom `server_config.toml` to configure advanced Engine tuning, background jobs, and RAG search parameters.
26
+ - `CUEMAP_URL`: If you prefer to bypass the embedded engine and connect to a remotely hosted or separately running CueMap server, specify its URL here (e.g. `http://localhost:8080`).
27
+
28
+ ## Using with AI Agents
29
+
30
+ To use this MCP server with your AI assistant, add it to your assistant's MCP configuration file.
31
+
32
+ ### Example Configuration (Claude Desktop)
33
+
34
+ ```json
35
+ {
36
+ "mcpServers": {
37
+ "cuemap": {
38
+ "command": "npx",
39
+ "args": [
40
+ "-y",
41
+ "@cuemap/mcp-server"
42
+ ],
43
+ "env": {
44
+ "CUEMAP_PORT": "8080"
45
+ }
46
+ }
47
+ }
48
+ }
49
+ ```
50
+
51
+ ## Available Tools
52
+
53
+ - **`cuemap_init`**: Autonomously initializes a CueMap project for a given local repository path. This triggers the Self-Learning Agent to instantly ingest the codebase so `cuemap_recall` can be used.
54
+ - `path` (string): Absolute path to the local repository.
55
+ - `projectName` (string, optional): The ID of the project to create. Defaults to the folder name of the path.
56
+
57
+ - **`cuemap_recall`**: Recalls context about a codebase from your CueMap integrated brain. Uses natural language and semantic search to find relevant information.
58
+ - `query` (string): The natural language query to search for.
59
+ - `limit` (number, optional): Maximum results to return (default: 10).
60
+ - `projects` (string[], optional): List of project IDs to scope the search to. Multiple enables cross-project queries.
61
+ - `cues` (string[], optional): Specific cue tags to filter the search.
62
+ - `depth` (number, optional): Depth of multi-hop recall expander (default: 1).
63
+ - `auto_reinforce` (boolean, optional): Automatically reinforce retrieved memories (default: false).
64
+ - `min_intersection` (number, optional): Minimum required cue intersection count (default: 0).
65
+ - `explain` (boolean, optional): Include scoring explanation data in results (default: false).
66
+ - `disable_pattern_completion` (boolean, optional): Skip pattern completion inference.
67
+ - `disable_salience_bias` (boolean, optional): Disable salience scoring bias.
68
+ - `disable_systems_consolidation` (boolean, optional): Skip returning summary/consolidated memories.
69
+ - `disable_alias_expansion` (boolean, optional): Disable lexicon synonym injection during querying.
70
+
71
+ ## License
72
+
73
+ MIT - See the [LICENSE](LICENSE) file for more details.
package/build/index.js ADDED
@@ -0,0 +1,224 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
8
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
9
+ const zod_1 = require("zod");
10
+ const cuemap_1 = __importDefault(require("cuemap"));
11
+ const child_process_1 = require("child_process");
12
+ const path_1 = __importDefault(require("path"));
13
+ const os_1 = __importDefault(require("os"));
14
+ const fs_1 = __importDefault(require("fs"));
15
+ let engineProcess = null;
16
+ let CUEMAP_URL = process.env.CUEMAP_URL;
17
+ let client;
18
+ const server = new mcp_js_1.McpServer({
19
+ name: "cuemap-mcp",
20
+ version: "1.0.0",
21
+ });
22
+ function getCuemapBinaryPath() {
23
+ if (process.env.CUEMAP_BIN)
24
+ return process.env.CUEMAP_BIN;
25
+ // Check optional dependencies dynamically
26
+ try {
27
+ const platform = os_1.default.platform();
28
+ const arch = os_1.default.arch();
29
+ const pkgName = `@cuemap/engine-${platform}-${arch}`;
30
+ const resolved = require.resolve(`${pkgName}/package.json`);
31
+ const binPath = path_1.default.join(path_1.default.dirname(resolved), "bin", "cuemap");
32
+ if (fs_1.default.existsSync(binPath))
33
+ return binPath;
34
+ }
35
+ catch (e) {
36
+ // Ignored
37
+ }
38
+ // Fallback: Check locally built binary (for development)
39
+ const localPath = path_1.default.resolve(__dirname, "../../rust_engine/target/release/cuemap");
40
+ if (fs_1.default.existsSync(localPath))
41
+ return localPath;
42
+ return null;
43
+ }
44
+ async function startEngine() {
45
+ if (CUEMAP_URL) {
46
+ console.error(`Using external CueMap engine at ${CUEMAP_URL}`);
47
+ return;
48
+ }
49
+ const binPath = getCuemapBinaryPath();
50
+ if (!binPath) {
51
+ console.error("Could not find cuemap binary. Please install the correct optional dependency, set CUEMAP_BIN, or set CUEMAP_URL to an existing instance.");
52
+ console.error("Falling back to expecting 'cuemap' in PATH.");
53
+ }
54
+ const execPath = binPath || "cuemap";
55
+ const port = process.env.CUEMAP_PORT || "8080";
56
+ CUEMAP_URL = `http://127.0.0.1:${port}`;
57
+ const args = ["start", "--port", port];
58
+ if (process.env.CUEMAP_CONFIG_PATH) {
59
+ args.push("--config", process.env.CUEMAP_CONFIG_PATH);
60
+ console.error(`Using custom config at ${process.env.CUEMAP_CONFIG_PATH}`);
61
+ }
62
+ console.error(`Starting Embedded CueMap Engine on port ${port}...`);
63
+ engineProcess = (0, child_process_1.spawn)(execPath, args, {
64
+ stdio: "ignore",
65
+ env: { ...process.env, CUEMAP_PORT: port }
66
+ });
67
+ engineProcess.on("error", (err) => {
68
+ console.error("Failed to start embedded engine:", err);
69
+ });
70
+ engineProcess.on("exit", (code) => {
71
+ console.error(`Embedded engine exited with code ${code}`);
72
+ });
73
+ process.on("SIGINT", () => {
74
+ if (engineProcess)
75
+ engineProcess.kill("SIGINT");
76
+ process.exit(0);
77
+ });
78
+ process.on("SIGTERM", () => {
79
+ if (engineProcess)
80
+ engineProcess.kill("SIGTERM");
81
+ process.exit(0);
82
+ });
83
+ // Wait slightly to ensure startup
84
+ await new Promise(resolve => setTimeout(resolve, 2000));
85
+ }
86
+ async function main() {
87
+ await startEngine();
88
+ client = new cuemap_1.default({ url: CUEMAP_URL });
89
+ server.registerTool("cuemap_init", {
90
+ description: "Initialize a CueMap project for a given local repository path. This triggers the Self-Learning Agent to ingest the codebase. Call this if the user hasn't set up the project yet or if cuemap_recall returns empty.",
91
+ inputSchema: zod_1.z.object({
92
+ path: zod_1.z.string().describe("Absolute path to the local repository."),
93
+ projectName: zod_1.z.string().optional().describe("The ID of the project to create. Defaults to the folder name of the path.")
94
+ })
95
+ }, async (args) => {
96
+ try {
97
+ const pName = args.projectName || path_1.default.basename(args.path);
98
+ const projects = await client.listProjects();
99
+ if (!projects.includes(pName)) {
100
+ await client.createProject(pName);
101
+ }
102
+ await client.setProjectWatchDir(pName, args.path);
103
+ console.error(`Started ingestion for project ${pName} at ${args.path}`);
104
+ // Polling for job completion
105
+ let isComplete = false;
106
+ let checks = 0;
107
+ while (!isComplete && checks < 60) {
108
+ const status = await client.jobsStatus(pName);
109
+ if (status.phase === "idle") {
110
+ isComplete = true;
111
+ break;
112
+ }
113
+ checks++;
114
+ await new Promise(r => setTimeout(r, 1000));
115
+ }
116
+ if (isComplete) {
117
+ return {
118
+ content: [{ type: "text", text: `Successfully initialized and ingested project ${pName}. You can now use cuemap_recall.` }]
119
+ };
120
+ }
121
+ else {
122
+ return {
123
+ content: [{ type: "text", text: `Project ${pName} initialized, but ingestion is still actively running in the background. Partial results may be returned by cuemap_recall.` }]
124
+ };
125
+ }
126
+ }
127
+ catch (error) {
128
+ console.error("Error initializing CueMap project", error);
129
+ return {
130
+ content: [{ type: "text", text: `Error initializing project: ${error?.message || "Unknown error"}` }],
131
+ isError: true,
132
+ };
133
+ }
134
+ });
135
+ server.registerTool("cuemap_recall", {
136
+ description: "Recall context about a codebase from a CueMap integerated brain. Uses natural language and semantic search to find relevant information.",
137
+ inputSchema: zod_1.z.object({
138
+ query: zod_1.z.string().describe("The natural language query to search the codebase memory for."),
139
+ limit: zod_1.z.number().optional().describe("Optional limit on the number of results to return. Default is 10."),
140
+ projects: zod_1.z.array(zod_1.z.string()).optional().describe("Optional list of project IDs to scope the search to. Provide multiple for cross-project recall. If not provided, searches the default project."),
141
+ cues: zod_1.z.array(zod_1.z.string()).optional().describe("Optional list of specific cues/tags to filter the search."),
142
+ depth: zod_1.z.number().optional().describe("Depth of multi-hop recall. Default is 1."),
143
+ auto_reinforce: zod_1.z.boolean().optional().describe("Automatically reinforce retrieved memories. Default is false."),
144
+ min_intersection: zod_1.z.number().optional().describe("Minimum intersection count for retrieval. Default is 0."),
145
+ explain: zod_1.z.boolean().optional().describe("Include explain component for debug information in results. Default is false."),
146
+ disable_pattern_completion: zod_1.z.boolean().optional().describe("Disable pattern completion inference. Default is false."),
147
+ disable_salience_bias: zod_1.z.boolean().optional().describe("Disable salience bias scoring. Default is false."),
148
+ disable_systems_consolidation: zod_1.z.boolean().optional().describe("Disable systems consolidation (exclude summaries). Default is false."),
149
+ disable_alias_expansion: zod_1.z.boolean().optional().describe("Disable alias expansion during querying. Default is false."),
150
+ }),
151
+ }, async (args) => {
152
+ try {
153
+ const { query, limit = 10, projects, cues, depth = 1, auto_reinforce = false, min_intersection, explain = false, disable_pattern_completion = false, disable_salience_bias = false, disable_systems_consolidation = false, disable_alias_expansion = false } = args;
154
+ const results = await client.recall(query, cues, projects, limit, depth, auto_reinforce, min_intersection, explain, disable_pattern_completion, disable_salience_bias, disable_systems_consolidation, disable_alias_expansion);
155
+ let items = [];
156
+ if (results.results && Array.isArray(results.results)) {
157
+ if (results.results.length > 0 && results.results[0].project_id) {
158
+ results.results.forEach((projectRes) => {
159
+ if (projectRes.results && Array.isArray(projectRes.results)) {
160
+ items = items.concat(projectRes.results.map((r) => ({ ...r, project_id: projectRes.project_id })));
161
+ }
162
+ });
163
+ }
164
+ else {
165
+ items = results.results;
166
+ }
167
+ }
168
+ if (!items || items.length === 0) {
169
+ return {
170
+ content: [
171
+ {
172
+ type: "text",
173
+ text: "No results found for the query in CueMap.",
174
+ },
175
+ ],
176
+ };
177
+ }
178
+ let formattedText = `CueMap found ${items.length} relevant results:\n\n`;
179
+ items.forEach((r, i) => {
180
+ const scoreStr = r.score !== undefined ? ` (Score: ${Number(r.score).toFixed(2)})` : '';
181
+ formattedText += `### Result ${i + 1}${scoreStr}\n`;
182
+ const projectId = r.project_id || (projects && projects.length === 1 ? projects[0] : null);
183
+ if (projectId)
184
+ formattedText += `*Project: ${projectId}*\n`;
185
+ if (r.timestamp) {
186
+ const date = new Date(r.timestamp);
187
+ formattedText += `*Timestamp: ${date.toISOString()}*\n`;
188
+ }
189
+ else if (r.created_at) {
190
+ const date = new Date(r.created_at * 1000);
191
+ formattedText += `*Timestamp: ${date.toISOString()}*\n`;
192
+ }
193
+ formattedText += `${r.content}\n\n`;
194
+ });
195
+ return {
196
+ content: [
197
+ {
198
+ type: "text",
199
+ text: formattedText,
200
+ },
201
+ ],
202
+ };
203
+ }
204
+ catch (error) {
205
+ console.error("Error calling CueMap engine", error);
206
+ return {
207
+ content: [
208
+ {
209
+ type: "text",
210
+ text: `Error executing cuemap_recall tool: ${error?.message || "Unknown error"}`,
211
+ },
212
+ ],
213
+ isError: true,
214
+ };
215
+ }
216
+ });
217
+ const transport = new stdio_js_1.StdioServerTransport();
218
+ await server.connect(transport);
219
+ console.error("CueMap MCP server running on stdio");
220
+ }
221
+ main().catch((error) => {
222
+ console.error("Server error:", error);
223
+ process.exit(1);
224
+ });
Binary file
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "cuemap-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for CueMap",
5
+ "main": "build/index.js",
6
+ "bin": {
7
+ "cuemap-mcp": "./build/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "start": "node build/index.js",
12
+ "dev": "tsc --watch"
13
+ },
14
+ "keywords": [
15
+ "mcp",
16
+ "model-context-protocol",
17
+ "cuemap",
18
+ "memory",
19
+ "rag"
20
+ ],
21
+ "author": "Kaan Demirel",
22
+ "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/cuemap-dev/cuemap-mcp.git"
26
+ },
27
+ "type": "commonjs",
28
+ "dependencies": {
29
+ "@modelcontextprotocol/sdk": "^1.27.1",
30
+ "cuemap": "^0.6.4",
31
+ "zod": "^4.3.6"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^25.3.3",
35
+ "typescript": "^5.9.3"
36
+ },
37
+ "optionalDependencies": {
38
+ "@cuemap/engine-darwin-arm64": "^0.6.4",
39
+ "@cuemap/engine-darwin-x64": "^0.6.4",
40
+ "@cuemap/engine-linux-x64": "^0.6.4",
41
+ "@cuemap/engine-win32-x64": "^0.6.4"
42
+ }
43
+ }
package/src/index.ts ADDED
@@ -0,0 +1,267 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import { z } from "zod";
6
+ import CueMap from "cuemap";
7
+ import { spawn, ChildProcess } from "child_process";
8
+ import path from "path";
9
+ import os from "os";
10
+ import fs from "fs";
11
+
12
+ let engineProcess: ChildProcess | null = null;
13
+ let CUEMAP_URL = process.env.CUEMAP_URL;
14
+ let client: CueMap;
15
+
16
+ const server = new McpServer({
17
+ name: "cuemap-mcp",
18
+ version: "1.0.0",
19
+ });
20
+
21
+ function getCuemapBinaryPath(): string | null {
22
+ if (process.env.CUEMAP_BIN) return process.env.CUEMAP_BIN;
23
+
24
+ // Check optional dependencies dynamically
25
+ try {
26
+ const platform = os.platform();
27
+ const arch = os.arch();
28
+ const pkgName = `@cuemap/engine-${platform}-${arch}`;
29
+ const resolved = require.resolve(`${pkgName}/package.json`);
30
+ const binPath = path.join(path.dirname(resolved), "bin", "cuemap");
31
+ if (fs.existsSync(binPath)) return binPath;
32
+ } catch (e) {
33
+ // Ignored
34
+ }
35
+
36
+ // Fallback: Check locally built binary (for development)
37
+ const localPath = path.resolve(__dirname, "../../rust_engine/target/release/cuemap");
38
+ if (fs.existsSync(localPath)) return localPath;
39
+
40
+ return null;
41
+ }
42
+
43
+ async function startEngine(): Promise<void> {
44
+ if (CUEMAP_URL) {
45
+ console.error(`Using external CueMap engine at ${CUEMAP_URL}`);
46
+ return;
47
+ }
48
+
49
+ const binPath = getCuemapBinaryPath();
50
+ if (!binPath) {
51
+ console.error("Could not find cuemap binary. Please install the correct optional dependency, set CUEMAP_BIN, or set CUEMAP_URL to an existing instance.");
52
+ console.error("Falling back to expecting 'cuemap' in PATH.");
53
+ }
54
+
55
+ const execPath = binPath || "cuemap";
56
+ const port = process.env.CUEMAP_PORT || "8080";
57
+ CUEMAP_URL = `http://127.0.0.1:${port}`;
58
+
59
+ const args = ["start", "--port", port];
60
+ if (process.env.CUEMAP_CONFIG_PATH) {
61
+ args.push("--config", process.env.CUEMAP_CONFIG_PATH);
62
+ console.error(`Using custom config at ${process.env.CUEMAP_CONFIG_PATH}`);
63
+ }
64
+
65
+ console.error(`Starting Embedded CueMap Engine on port ${port}...`);
66
+ engineProcess = spawn(execPath, args, {
67
+ stdio: "ignore",
68
+ env: { ...process.env, CUEMAP_PORT: port }
69
+ });
70
+
71
+ engineProcess.on("error", (err) => {
72
+ console.error("Failed to start embedded engine:", err);
73
+ });
74
+
75
+ engineProcess.on("exit", (code) => {
76
+ console.error(`Embedded engine exited with code ${code}`);
77
+ });
78
+
79
+ process.on("SIGINT", () => {
80
+ if (engineProcess) engineProcess.kill("SIGINT");
81
+ process.exit(0);
82
+ });
83
+ process.on("SIGTERM", () => {
84
+ if (engineProcess) engineProcess.kill("SIGTERM");
85
+ process.exit(0);
86
+ });
87
+
88
+ // Wait slightly to ensure startup
89
+ await new Promise(resolve => setTimeout(resolve, 2000));
90
+ }
91
+
92
+ async function main() {
93
+ await startEngine();
94
+
95
+ client = new CueMap({ url: CUEMAP_URL });
96
+
97
+ server.registerTool(
98
+ "cuemap_init",
99
+ {
100
+ description: "Initialize a CueMap project for a given local repository path. This triggers the Self-Learning Agent to ingest the codebase. Call this if the user hasn't set up the project yet or if cuemap_recall returns empty.",
101
+ inputSchema: z.object({
102
+ path: z.string().describe("Absolute path to the local repository."),
103
+ projectName: z.string().optional().describe("The ID of the project to create. Defaults to the folder name of the path.")
104
+ })
105
+ },
106
+ async (args) => {
107
+ try {
108
+ const pName = args.projectName || path.basename(args.path);
109
+
110
+ const projects = await client.listProjects();
111
+ if (!projects.includes(pName)) {
112
+ await client.createProject(pName);
113
+ }
114
+
115
+ await client.setProjectWatchDir(pName, args.path);
116
+ console.error(`Started ingestion for project ${pName} at ${args.path}`);
117
+
118
+ // Polling for job completion
119
+ let isComplete = false;
120
+ let checks = 0;
121
+ while (!isComplete && checks < 60) {
122
+ const status = await client.jobsStatus(pName);
123
+ if (status.phase === "idle") {
124
+ isComplete = true;
125
+ break;
126
+ }
127
+ checks++;
128
+ await new Promise(r => setTimeout(r, 1000));
129
+ }
130
+
131
+ if (isComplete) {
132
+ return {
133
+ content: [{ type: "text" as const, text: `Successfully initialized and ingested project ${pName}. You can now use cuemap_recall.` }]
134
+ };
135
+ } else {
136
+ return {
137
+ content: [{ type: "text" as const, text: `Project ${pName} initialized, but ingestion is still actively running in the background. Partial results may be returned by cuemap_recall.` }]
138
+ };
139
+ }
140
+ } catch (error: any) {
141
+ console.error("Error initializing CueMap project", error);
142
+ return {
143
+ content: [{ type: "text" as const, text: `Error initializing project: ${error?.message || "Unknown error"}` }],
144
+ isError: true,
145
+ };
146
+ }
147
+ }
148
+ );
149
+
150
+ server.registerTool(
151
+ "cuemap_recall",
152
+ {
153
+ description: "Recall context about a codebase from a CueMap integerated brain. Uses natural language and semantic search to find relevant information.",
154
+ inputSchema: z.object({
155
+ query: z.string().describe("The natural language query to search the codebase memory for."),
156
+ limit: z.number().optional().describe("Optional limit on the number of results to return. Default is 10."),
157
+ projects: z.array(z.string()).optional().describe("Optional list of project IDs to scope the search to. Provide multiple for cross-project recall. If not provided, searches the default project."),
158
+ cues: z.array(z.string()).optional().describe("Optional list of specific cues/tags to filter the search."),
159
+ depth: z.number().optional().describe("Depth of multi-hop recall. Default is 1."),
160
+ auto_reinforce: z.boolean().optional().describe("Automatically reinforce retrieved memories. Default is false."),
161
+ min_intersection: z.number().optional().describe("Minimum intersection count for retrieval. Default is 0."),
162
+ explain: z.boolean().optional().describe("Include explain component for debug information in results. Default is false."),
163
+ disable_pattern_completion: z.boolean().optional().describe("Disable pattern completion inference. Default is false."),
164
+ disable_salience_bias: z.boolean().optional().describe("Disable salience bias scoring. Default is false."),
165
+ disable_systems_consolidation: z.boolean().optional().describe("Disable systems consolidation (exclude summaries). Default is false."),
166
+ disable_alias_expansion: z.boolean().optional().describe("Disable alias expansion during querying. Default is false."),
167
+ }),
168
+ },
169
+ async (args) => {
170
+ try {
171
+ const {
172
+ query, limit = 10, projects, cues,
173
+ depth = 1, auto_reinforce = false, min_intersection,
174
+ explain = false, disable_pattern_completion = false,
175
+ disable_salience_bias = false, disable_systems_consolidation = false,
176
+ disable_alias_expansion = false
177
+ } = args;
178
+
179
+ const results = await client.recall(
180
+ query,
181
+ cues,
182
+ projects,
183
+ limit,
184
+ depth,
185
+ auto_reinforce,
186
+ min_intersection,
187
+ explain,
188
+ disable_pattern_completion,
189
+ disable_salience_bias,
190
+ disable_systems_consolidation,
191
+ disable_alias_expansion
192
+ );
193
+
194
+ let items: any[] = [];
195
+
196
+ if (results.results && Array.isArray(results.results)) {
197
+ if (results.results.length > 0 && results.results[0].project_id) {
198
+ results.results.forEach((projectRes: any) => {
199
+ if (projectRes.results && Array.isArray(projectRes.results)) {
200
+ items = items.concat(projectRes.results.map((r: any) => ({ ...r, project_id: projectRes.project_id })));
201
+ }
202
+ });
203
+ } else {
204
+ items = results.results;
205
+ }
206
+ }
207
+
208
+ if (!items || items.length === 0) {
209
+ return {
210
+ content: [
211
+ {
212
+ type: "text" as const,
213
+ text: "No results found for the query in CueMap.",
214
+ },
215
+ ],
216
+ };
217
+ }
218
+
219
+ let formattedText = `CueMap found ${items.length} relevant results:\n\n`;
220
+ items.forEach((r: any, i: number) => {
221
+ const scoreStr = r.score !== undefined ? ` (Score: ${Number(r.score).toFixed(2)})` : '';
222
+ formattedText += `### Result ${i + 1}${scoreStr}\n`;
223
+ const projectId = r.project_id || (projects && projects.length === 1 ? projects[0] : null);
224
+ if (projectId) formattedText += `*Project: ${projectId}*\n`;
225
+ if (r.timestamp) {
226
+ const date = new Date(r.timestamp);
227
+ formattedText += `*Timestamp: ${date.toISOString()}*\n`;
228
+ } else if (r.created_at) {
229
+ const date = new Date(r.created_at * 1000);
230
+ formattedText += `*Timestamp: ${date.toISOString()}*\n`;
231
+ }
232
+
233
+ formattedText += `${r.content}\n\n`;
234
+ });
235
+
236
+ return {
237
+ content: [
238
+ {
239
+ type: "text" as const,
240
+ text: formattedText,
241
+ },
242
+ ],
243
+ };
244
+ } catch (error: any) {
245
+ console.error("Error calling CueMap engine", error);
246
+ return {
247
+ content: [
248
+ {
249
+ type: "text" as const,
250
+ text: `Error executing cuemap_recall tool: ${error?.message || "Unknown error"}`,
251
+ },
252
+ ],
253
+ isError: true,
254
+ };
255
+ }
256
+ }
257
+ );
258
+
259
+ const transport = new StdioServerTransport();
260
+ await server.connect(transport);
261
+ console.error("CueMap MCP server running on stdio");
262
+ }
263
+
264
+ main().catch((error) => {
265
+ console.error("Server error:", error);
266
+ process.exit(1);
267
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "CommonJS",
5
+ "moduleResolution": "Node",
6
+ "rootDir": "./src",
7
+ "outDir": "./build",
8
+ "esModuleInterop": true,
9
+ "strict": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true
12
+ },
13
+ "include": [
14
+ "src/**/*"
15
+ ]
16
+ }