@intangle/mcp-server 2.1.1 → 2.1.3

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 (3) hide show
  1. package/dist/index.js +188 -166
  2. package/index.ts +227 -203
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -11,189 +11,211 @@ import { readFileSync } from "fs";
11
11
  import { fileURLToPath } from "url";
12
12
  import { dirname, join } from "path";
13
13
  import { TOOLS } from "./tool-definitions.js";
14
- // Load environment variables from .env and .env.local
15
- config({ quiet: true });
16
- config({ path: ".env.local", quiet: true });
17
- // Base URL for API calls to Next.js app
18
- const API_BASE_URL = process.env.NEXT_APP_URL || "https://intangle.app";
19
- const MCP_API_KEY = process.env.MCP_API_KEY;
20
- // No space configuration needed - AI discovers spaces dynamically
21
- if (!MCP_API_KEY) {
22
- console.error("Error: MCP_API_KEY environment variable is required");
23
- console.error("Please set your Intangle API key in the Claude Desktop configuration");
24
- process.exit(1);
14
+ // ... imports ...
15
+ // Debug logging
16
+ import { appendFileSync } from "fs";
17
+ const DEBUG_LOG = "/tmp/intangle-mcp-debug.log";
18
+ function log(msg) {
19
+ try {
20
+ appendFileSync(DEBUG_LOG, `${new Date().toISOString()}: ${msg}\n`);
21
+ }
22
+ catch (e) { }
25
23
  }
26
- console.log("Intangle MCP Server starting - connecting to", API_BASE_URL);
27
- // Version checking - automatically read from package.json
28
- const __dirname = dirname(fileURLToPath(import.meta.url));
29
- let packageJson;
24
+ log("--- Server Starting ---");
30
25
  try {
31
- packageJson = JSON.parse(readFileSync(join(__dirname, "package.json"), "utf-8"));
32
- }
33
- catch {
34
- packageJson = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf-8"));
35
- }
36
- const CURRENT_VERSION = packageJson.version;
37
- let latestVersion = null;
38
- let versionCheckDone = false;
39
- async function checkVersion() {
40
- if (versionCheckDone)
41
- return;
26
+ // Load environment variables from .env and .env.local
27
+ config({ quiet: true });
28
+ config({ path: ".env.local", quiet: true });
29
+ // Base URL for API calls to Next.js app
30
+ const API_BASE_URL = process.env.NEXT_APP_URL || "https://intangle.app";
31
+ const MCP_API_KEY = process.env.MCP_API_KEY;
32
+ log(`CWD: ${process.cwd()}`);
33
+ log(`Has API Key: ${!!MCP_API_KEY}`);
34
+ log(`Node Version: ${process.version}`);
35
+ if (!MCP_API_KEY) {
36
+ log("Error: MCP_API_KEY environment variable is required");
37
+ console.error("Error: MCP_API_KEY environment variable is required");
38
+ console.error("Please set your Intangle API key in the Claude Desktop configuration");
39
+ process.exit(1);
40
+ }
41
+ console.error("Intangle MCP Server starting - connecting to", API_BASE_URL);
42
+ // Version checking - automatically read from package.json
43
+ const __dirname = dirname(fileURLToPath(import.meta.url));
44
+ let packageJson;
42
45
  try {
43
- const response = await fetch("https://registry.npmjs.org/@intangle/mcp-server/latest");
44
- const data = (await response.json());
45
- latestVersion = data.version;
46
- versionCheckDone = true;
47
- if (latestVersion && latestVersion !== CURRENT_VERSION) {
48
- console.warn("\n UPDATE AVAILABLE ");
49
- console.warn(`Current version: ${CURRENT_VERSION}`);
50
- console.warn(`Latest version: ${latestVersion}`);
51
- console.warn("Update with: npx @intangle/mcp-server@latest\n");
46
+ packageJson = JSON.parse(readFileSync(join(__dirname, "package.json"), "utf-8"));
47
+ }
48
+ catch {
49
+ packageJson = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf-8"));
50
+ }
51
+ const CURRENT_VERSION = packageJson.version;
52
+ let latestVersion = null;
53
+ let versionCheckDone = false;
54
+ async function checkVersion() {
55
+ if (versionCheckDone)
56
+ return;
57
+ try {
58
+ const response = await fetch("https://registry.npmjs.org/@intangle/mcp-server/latest");
59
+ const data = (await response.json());
60
+ latestVersion = data.version;
61
+ versionCheckDone = true;
62
+ if (latestVersion && latestVersion !== CURRENT_VERSION) {
63
+ console.error("\n UPDATE AVAILABLE ");
64
+ console.error(`Current version: ${CURRENT_VERSION}`);
65
+ console.error(`Latest version: ${latestVersion}`);
66
+ console.error("Update with: npx @intangle/mcp-server@latest\n");
67
+ }
68
+ else {
69
+ console.error(`✓ Running latest version (${CURRENT_VERSION})`);
70
+ }
52
71
  }
53
- else {
54
- console.log(`✓ Running latest version (${CURRENT_VERSION})`);
72
+ catch (error) {
73
+ // Silently fail version check - don't block startup
74
+ versionCheckDone = true;
55
75
  }
56
76
  }
57
- catch (error) {
58
- // Silently fail version check - don't block startup
59
- versionCheckDone = true;
77
+ // Check version on startup (non-blocking)
78
+ checkVersion();
79
+ async function makeApiCall(endpoint, data) {
80
+ const response = await fetch(`${API_BASE_URL}/api/mcp/${endpoint}`, {
81
+ method: "POST",
82
+ headers: {
83
+ "Content-Type": "application/json",
84
+ Authorization: `Bearer ${MCP_API_KEY}`,
85
+ "User-Agent": "MCP-Client-Stdio/1.1.2 (mcp)",
86
+ },
87
+ body: JSON.stringify(data),
88
+ });
89
+ if (!response.ok) {
90
+ throw new Error(`API call failed: ${response.status} ${response.statusText}`);
91
+ }
92
+ return response.json();
60
93
  }
61
- }
62
- // Check version on startup (non-blocking)
63
- checkVersion();
64
- async function makeApiCall(endpoint, data) {
65
- const response = await fetch(`${API_BASE_URL}/api/mcp/${endpoint}`, {
66
- method: "POST",
67
- headers: {
68
- "Content-Type": "application/json",
69
- Authorization: `Bearer ${MCP_API_KEY}`,
70
- "User-Agent": "MCP-Client-Stdio/1.1.2 (mcp)",
94
+ const server = new Server({
95
+ name: "intangle-memory",
96
+ version: "1.0.0",
97
+ vendor: "Intangle",
98
+ icon: "https://intangle.tools/icon.png",
99
+ }, {
100
+ capabilities: {
101
+ tools: {},
71
102
  },
72
- body: JSON.stringify(data),
73
103
  });
74
- if (!response.ok) {
75
- throw new Error(`API call failed: ${response.status} ${response.statusText}`);
104
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
105
+ tools: TOOLS,
106
+ }));
107
+ async function handleSearchMemories(args) {
108
+ const { space_id, query, topics } = args;
109
+ // Require space_id
110
+ if (!space_id) {
111
+ throw new Error("space_id is required. Use list_spaces to see available options.");
112
+ }
113
+ return makeApiCall("search-memories", {
114
+ space_id,
115
+ space_ids: [space_id], // Convert to array for backend compatibility
116
+ query,
117
+ topics,
118
+ });
76
119
  }
77
- return response.json();
78
- }
79
- const server = new Server({
80
- name: "intangle-memory",
81
- version: "1.0.0",
82
- vendor: "Intangle",
83
- icon: "https://intangle.tools/icon.png",
84
- }, {
85
- capabilities: {
86
- tools: {},
87
- },
88
- });
89
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
90
- tools: TOOLS,
91
- }));
92
- async function handleSearchMemories(args) {
93
- const { space_id, query, topics } = args;
94
- // Require space_id
95
- if (!space_id) {
96
- throw new Error("space_id is required. Use list_spaces to see available options.");
120
+ async function handleFetch(args) {
121
+ const { id, ids } = args;
122
+ return makeApiCall("fetch", { id, ids });
97
123
  }
98
- return makeApiCall("search-memories", {
99
- space_id,
100
- space_ids: [space_id], // Convert to array for backend compatibility
101
- query,
102
- topics,
103
- });
104
- }
105
- async function handleFetch(args) {
106
- const { id, ids } = args;
107
- return makeApiCall("fetch", { id, ids });
108
- }
109
- async function handleViewSpaces() {
110
- return makeApiCall("list-spaces", {});
111
- }
112
- async function handleCreateSpace(args) {
113
- return makeApiCall("create-space", args);
114
- }
115
- async function handleViewSpace(args) {
116
- const { space_id } = args;
117
- return makeApiCall("view-space", { space_id });
118
- }
119
- async function handleStart(args) {
120
- const { space_id } = args;
121
- return makeApiCall("start", { space_id });
122
- }
123
- async function handleUpdateSpace(args) {
124
- if (!args.space_id) {
125
- throw new Error("space_id is required. Use view_spaces to see available options.");
124
+ async function handleViewSpaces() {
125
+ return makeApiCall("list-spaces", {});
126
126
  }
127
- if (!args.add && !args.update && !args.delete) {
128
- throw new Error("At least one operation (add, update, delete) must be provided");
127
+ async function handleCreateSpace(args) {
128
+ return makeApiCall("create-space", args);
129
129
  }
130
- // Pass through to API with new structure
131
- return makeApiCall("update-memory", {
132
- space_id: args.space_id,
133
- add: args.add,
134
- update: args.update,
135
- delete: args.delete,
136
- });
137
- }
138
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
139
- const { name, arguments: args } = request.params;
140
- try {
141
- let result;
142
- switch (name) {
143
- case "search":
144
- result = await handleSearchMemories(args);
145
- break;
146
- case "fetch":
147
- result = await handleFetch(args);
148
- break;
149
- case "view_spaces":
150
- result = await handleViewSpaces();
151
- break;
152
- case "create_space":
153
- result = await handleCreateSpace(args);
154
- break;
155
- case "view_space":
156
- result = await handleViewSpace(args);
157
- break;
158
- case "start":
159
- result = await handleStart(args);
160
- break;
161
- case "update_space":
162
- result = await handleUpdateSpace(args);
163
- break;
164
- default:
165
- throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
130
+ async function handleViewSpace(args) {
131
+ const { space_id } = args;
132
+ return makeApiCall("view-space", { space_id });
133
+ }
134
+ async function handleStart(args) {
135
+ const { space_id } = args;
136
+ return makeApiCall("start", { space_id });
137
+ }
138
+ async function handleUpdateSpace(args) {
139
+ if (!args.space_id) {
140
+ throw new Error("space_id is required. Use view_spaces to see available options.");
166
141
  }
167
- // Extract response field for Layer 2 compressed tools, otherwise stringify full result
168
- let responseText;
169
- if (result &&
170
- typeof result === "object" &&
171
- "response" in result &&
172
- typeof result.response === "string") {
173
- // Tool has Layer 2 compression - use the formatted response field
174
- responseText = result.response;
142
+ if (!args.add && !args.update && !args.delete) {
143
+ throw new Error("At least one operation (add, update, delete) must be provided");
175
144
  }
176
- else {
177
- // Standard tool - return full JSON
178
- responseText = JSON.stringify(result, null, 2);
145
+ // Pass through to API with new structure
146
+ return makeApiCall("update-memory", {
147
+ space_id: args.space_id,
148
+ add: args.add,
149
+ update: args.update,
150
+ delete: args.delete,
151
+ });
152
+ }
153
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
154
+ const { name, arguments: args } = request.params;
155
+ try {
156
+ let result;
157
+ switch (name) {
158
+ case "search":
159
+ result = await handleSearchMemories(args);
160
+ break;
161
+ case "fetch":
162
+ result = await handleFetch(args);
163
+ break;
164
+ case "view_spaces":
165
+ result = await handleViewSpaces();
166
+ break;
167
+ case "create_space":
168
+ result = await handleCreateSpace(args);
169
+ break;
170
+ case "view_space":
171
+ result = await handleViewSpace(args);
172
+ break;
173
+ case "start":
174
+ result = await handleStart(args);
175
+ break;
176
+ case "update_space":
177
+ result = await handleUpdateSpace(args);
178
+ break;
179
+ default:
180
+ throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
181
+ }
182
+ // Extract response field for Layer 2 compressed tools, otherwise stringify full result
183
+ let responseText;
184
+ if (result &&
185
+ typeof result === "object" &&
186
+ "response" in result &&
187
+ typeof result.response === "string") {
188
+ // Tool has Layer 2 compression - use the formatted response field
189
+ responseText = result.response;
190
+ }
191
+ else {
192
+ // Standard tool - return full JSON
193
+ responseText = JSON.stringify(result, null, 2);
194
+ }
195
+ // Add version warning to response if outdated
196
+ if (latestVersion && latestVersion !== CURRENT_VERSION) {
197
+ const warning = `\n\n UPDATE AVAILABLE: MCP Server v${latestVersion} is available (you're on v${CURRENT_VERSION}). Update with: npx @intangle/mcp-server@latest`;
198
+ responseText += warning;
199
+ }
200
+ return {
201
+ content: [{ type: "text", text: responseText }],
202
+ };
179
203
  }
180
- // Add version warning to response if outdated
181
- if (latestVersion && latestVersion !== CURRENT_VERSION) {
182
- const warning = `\n\n UPDATE AVAILABLE: MCP Server v${latestVersion} is available (you're on v${CURRENT_VERSION}). Update with: npx @intangle/mcp-server@latest`;
183
- responseText += warning;
204
+ catch (error) {
205
+ throw new McpError(ErrorCode.InternalError, `Error executing tool ${name}: ${error instanceof Error ? error.message : String(error)}`);
184
206
  }
185
- return {
186
- content: [{ type: "text", text: responseText }],
187
- };
188
- }
189
- catch (error) {
190
- throw new McpError(ErrorCode.InternalError, `Error executing tool ${name}: ${error instanceof Error ? error.message : String(error)}`);
207
+ });
208
+ async function main() {
209
+ const transport = new StdioServerTransport();
210
+ await server.connect(transport);
211
+ log("Server connected to transport");
191
212
  }
192
- });
193
- async function main() {
194
- const transport = new StdioServerTransport();
195
- await server.connect(transport);
213
+ main().catch((err) => {
214
+ log(`Error in main: ${err}`);
215
+ process.exit(1);
216
+ });
196
217
  }
197
- main().catch(() => {
218
+ catch (err) {
219
+ log(`Fatal startup error: ${err}`);
198
220
  process.exit(1);
199
- });
221
+ }
package/index.ts CHANGED
@@ -19,245 +19,269 @@ import { fileURLToPath } from "url";
19
19
  import { dirname, join } from "path";
20
20
  import { TOOLS } from "./tool-definitions.js";
21
21
 
22
- // Load environment variables from .env and .env.local
23
- config({ quiet: true });
24
- config({ path: ".env.local", quiet: true });
22
+ // ... imports ...
25
23
 
26
- // Base URL for API calls to Next.js app
27
- const API_BASE_URL = process.env.NEXT_APP_URL || "https://intangle.app";
28
- const MCP_API_KEY = process.env.MCP_API_KEY;
29
-
30
- // No space configuration needed - AI discovers spaces dynamically
31
-
32
- if (!MCP_API_KEY) {
33
- console.error("Error: MCP_API_KEY environment variable is required");
34
- console.error(
35
- "Please set your Intangle API key in the Claude Desktop configuration",
36
- );
37
- process.exit(1);
24
+ // Debug logging
25
+ import { appendFileSync } from "fs";
26
+ const DEBUG_LOG = "/tmp/intangle-mcp-debug.log";
27
+ function log(msg: string) {
28
+ try {
29
+ appendFileSync(DEBUG_LOG, `${new Date().toISOString()}: ${msg}\n`);
30
+ } catch (e) {}
38
31
  }
39
32
 
40
- console.log("Intangle MCP Server starting - connecting to", API_BASE_URL);
33
+ log("--- Server Starting ---");
41
34
 
42
- // Version checking - automatically read from package.json
43
- const __dirname = dirname(fileURLToPath(import.meta.url));
44
- let packageJson;
45
35
  try {
46
- packageJson = JSON.parse(
47
- readFileSync(join(__dirname, "package.json"), "utf-8"),
48
- );
49
- } catch {
50
- packageJson = JSON.parse(
51
- readFileSync(join(__dirname, "../package.json"), "utf-8"),
52
- );
53
- }
54
- const CURRENT_VERSION = packageJson.version;
55
- let latestVersion: string | null = null;
56
- let versionCheckDone = false;
36
+ // Load environment variables from .env and .env.local
37
+ config({ quiet: true });
38
+ config({ path: ".env.local", quiet: true });
39
+
40
+ // Base URL for API calls to Next.js app
41
+ const API_BASE_URL = process.env.NEXT_APP_URL || "https://intangle.app";
42
+ const MCP_API_KEY = process.env.MCP_API_KEY;
43
+
44
+ log(`CWD: ${process.cwd()}`);
45
+ log(`Has API Key: ${!!MCP_API_KEY}`);
46
+ log(`Node Version: ${process.version}`);
47
+
48
+ if (!MCP_API_KEY) {
49
+ log("Error: MCP_API_KEY environment variable is required");
50
+ console.error("Error: MCP_API_KEY environment variable is required");
51
+ console.error(
52
+ "Please set your Intangle API key in the Claude Desktop configuration",
53
+ );
54
+ process.exit(1);
55
+ }
57
56
 
58
- async function checkVersion() {
59
- if (versionCheckDone) return;
57
+ console.error("Intangle MCP Server starting - connecting to", API_BASE_URL);
60
58
 
59
+ // Version checking - automatically read from package.json
60
+ const __dirname = dirname(fileURLToPath(import.meta.url));
61
+ let packageJson;
61
62
  try {
62
- const response = await fetch(
63
- "https://registry.npmjs.org/@intangle/mcp-server/latest",
63
+ packageJson = JSON.parse(
64
+ readFileSync(join(__dirname, "package.json"), "utf-8"),
64
65
  );
65
- const data = (await response.json()) as { version: string };
66
- latestVersion = data.version;
67
- versionCheckDone = true;
68
-
69
- if (latestVersion && latestVersion !== CURRENT_VERSION) {
70
- console.warn("\n UPDATE AVAILABLE ");
71
- console.warn(`Current version: ${CURRENT_VERSION}`);
72
- console.warn(`Latest version: ${latestVersion}`);
73
- console.warn("Update with: npx @intangle/mcp-server@latest\n");
74
- } else {
75
- console.log(`✓ Running latest version (${CURRENT_VERSION})`);
66
+ } catch {
67
+ packageJson = JSON.parse(
68
+ readFileSync(join(__dirname, "../package.json"), "utf-8"),
69
+ );
70
+ }
71
+ const CURRENT_VERSION = packageJson.version;
72
+ let latestVersion: string | null = null;
73
+ let versionCheckDone = false;
74
+
75
+ async function checkVersion() {
76
+ if (versionCheckDone) return;
77
+
78
+ try {
79
+ const response = await fetch(
80
+ "https://registry.npmjs.org/@intangle/mcp-server/latest",
81
+ );
82
+ const data = (await response.json()) as { version: string };
83
+ latestVersion = data.version;
84
+ versionCheckDone = true;
85
+
86
+ if (latestVersion && latestVersion !== CURRENT_VERSION) {
87
+ console.error("\n UPDATE AVAILABLE ");
88
+ console.error(`Current version: ${CURRENT_VERSION}`);
89
+ console.error(`Latest version: ${latestVersion}`);
90
+ console.error("Update with: npx @intangle/mcp-server@latest\n");
91
+ } else {
92
+ console.error(`✓ Running latest version (${CURRENT_VERSION})`);
93
+ }
94
+ } catch (error) {
95
+ // Silently fail version check - don't block startup
96
+ versionCheckDone = true;
76
97
  }
77
- } catch (error) {
78
- // Silently fail version check - don't block startup
79
- versionCheckDone = true;
80
98
  }
81
- }
82
99
 
83
- // Check version on startup (non-blocking)
84
- checkVersion();
85
-
86
- async function makeApiCall(endpoint: string, data: any) {
87
- const response = await fetch(`${API_BASE_URL}/api/mcp/${endpoint}`, {
88
- method: "POST",
89
- headers: {
90
- "Content-Type": "application/json",
91
- Authorization: `Bearer ${MCP_API_KEY}`,
92
- "User-Agent": "MCP-Client-Stdio/1.1.2 (mcp)",
93
- },
94
- body: JSON.stringify(data),
95
- });
100
+ // Check version on startup (non-blocking)
101
+ checkVersion();
102
+
103
+ async function makeApiCall(endpoint: string, data: any) {
104
+ const response = await fetch(`${API_BASE_URL}/api/mcp/${endpoint}`, {
105
+ method: "POST",
106
+ headers: {
107
+ "Content-Type": "application/json",
108
+ Authorization: `Bearer ${MCP_API_KEY}`,
109
+ "User-Agent": "MCP-Client-Stdio/1.1.2 (mcp)",
110
+ },
111
+ body: JSON.stringify(data),
112
+ });
113
+
114
+ if (!response.ok) {
115
+ throw new Error(
116
+ `API call failed: ${response.status} ${response.statusText}`,
117
+ );
118
+ }
96
119
 
97
- if (!response.ok) {
98
- throw new Error(
99
- `API call failed: ${response.status} ${response.statusText}`,
100
- );
120
+ return response.json();
101
121
  }
102
122
 
103
- return response.json();
104
- }
105
-
106
- const server = new Server(
107
- {
108
- name: "intangle-memory",
109
- version: "1.0.0",
110
- vendor: "Intangle",
111
- icon: "https://intangle.tools/icon.png",
112
- },
113
- {
114
- capabilities: {
115
- tools: {},
123
+ const server = new Server(
124
+ {
125
+ name: "intangle-memory",
126
+ version: "1.0.0",
127
+ vendor: "Intangle",
128
+ icon: "https://intangle.tools/icon.png",
116
129
  },
117
- },
118
- );
119
-
120
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
121
- tools: TOOLS,
122
- }));
123
-
124
- async function handleSearchMemories(args: any) {
125
- const { space_id, query, topics } = args as {
126
- space_id: string;
127
- query: string;
128
- topics?: string[];
129
- };
130
-
131
- // Require space_id
132
- if (!space_id) {
133
- throw new Error(
134
- "space_id is required. Use list_spaces to see available options.",
135
- );
136
- }
137
-
138
- return makeApiCall("search-memories", {
139
- space_id,
140
- space_ids: [space_id], // Convert to array for backend compatibility
141
- query,
142
- topics,
143
- });
144
- }
130
+ {
131
+ capabilities: {
132
+ tools: {},
133
+ },
134
+ },
135
+ );
145
136
 
146
- async function handleFetch(args: any) {
147
- const { id, ids } = args as { id?: string; ids?: string[] };
137
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
138
+ tools: TOOLS,
139
+ }));
148
140
 
149
- return makeApiCall("fetch", { id, ids });
150
- }
141
+ async function handleSearchMemories(args: any) {
142
+ const { space_id, query, topics } = args as {
143
+ space_id: string;
144
+ query: string;
145
+ topics?: string[];
146
+ };
151
147
 
152
- async function handleViewSpaces() {
153
- return makeApiCall("list-spaces", {});
154
- }
148
+ // Require space_id
149
+ if (!space_id) {
150
+ throw new Error(
151
+ "space_id is required. Use list_spaces to see available options.",
152
+ );
153
+ }
155
154
 
156
- async function handleCreateSpace(args: any) {
157
- return makeApiCall("create-space", args);
158
- }
155
+ return makeApiCall("search-memories", {
156
+ space_id,
157
+ space_ids: [space_id], // Convert to array for backend compatibility
158
+ query,
159
+ topics,
160
+ });
161
+ }
159
162
 
160
- async function handleViewSpace(args: any) {
161
- const { space_id } = args as { space_id: string };
162
- return makeApiCall("view-space", { space_id });
163
- }
163
+ async function handleFetch(args: any) {
164
+ const { id, ids } = args as { id?: string; ids?: string[] };
164
165
 
165
- async function handleStart(args: any) {
166
- const { space_id } = args as { space_id: string };
167
- return makeApiCall("start", { space_id });
168
- }
166
+ return makeApiCall("fetch", { id, ids });
167
+ }
169
168
 
170
- async function handleUpdateSpace(args: any) {
171
- if (!args.space_id) {
172
- throw new Error(
173
- "space_id is required. Use view_spaces to see available options.",
174
- );
169
+ async function handleViewSpaces() {
170
+ return makeApiCall("list-spaces", {});
175
171
  }
176
172
 
177
- if (!args.add && !args.update && !args.delete) {
178
- throw new Error(
179
- "At least one operation (add, update, delete) must be provided",
180
- );
173
+ async function handleCreateSpace(args: any) {
174
+ return makeApiCall("create-space", args);
181
175
  }
182
176
 
183
- // Pass through to API with new structure
184
- return makeApiCall("update-memory", {
185
- space_id: args.space_id,
186
- add: args.add,
187
- update: args.update,
188
- delete: args.delete,
189
- });
190
- }
177
+ async function handleViewSpace(args: any) {
178
+ const { space_id } = args as { space_id: string };
179
+ return makeApiCall("view-space", { space_id });
180
+ }
191
181
 
192
- server.setRequestHandler(CallToolRequestSchema, async (request: any) => {
193
- const { name, arguments: args } = request.params;
182
+ async function handleStart(args: any) {
183
+ const { space_id } = args as { space_id: string };
184
+ return makeApiCall("start", { space_id });
185
+ }
194
186
 
195
- try {
196
- let result: any;
197
-
198
- switch (name) {
199
- case "search":
200
- result = await handleSearchMemories(args);
201
- break;
202
- case "fetch":
203
- result = await handleFetch(args);
204
- break;
205
- case "view_spaces":
206
- result = await handleViewSpaces();
207
- break;
208
- case "create_space":
209
- result = await handleCreateSpace(args);
210
- break;
211
- case "view_space":
212
- result = await handleViewSpace(args);
213
- break;
214
- case "start":
215
- result = await handleStart(args);
216
- break;
217
- case "update_space":
218
- result = await handleUpdateSpace(args);
219
- break;
220
- default:
221
- throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
187
+ async function handleUpdateSpace(args: any) {
188
+ if (!args.space_id) {
189
+ throw new Error(
190
+ "space_id is required. Use view_spaces to see available options.",
191
+ );
222
192
  }
223
193
 
224
- // Extract response field for Layer 2 compressed tools, otherwise stringify full result
225
- let responseText: string;
226
- if (
227
- result &&
228
- typeof result === "object" &&
229
- "response" in result &&
230
- typeof result.response === "string"
231
- ) {
232
- // Tool has Layer 2 compression - use the formatted response field
233
- responseText = result.response;
234
- } else {
235
- // Standard tool - return full JSON
236
- responseText = JSON.stringify(result, null, 2);
194
+ if (!args.add && !args.update && !args.delete) {
195
+ throw new Error(
196
+ "At least one operation (add, update, delete) must be provided",
197
+ );
237
198
  }
238
199
 
239
- // Add version warning to response if outdated
240
- if (latestVersion && latestVersion !== CURRENT_VERSION) {
241
- const warning = `\n\n UPDATE AVAILABLE: MCP Server v${latestVersion} is available (you're on v${CURRENT_VERSION}). Update with: npx @intangle/mcp-server@latest`;
242
- responseText += warning;
200
+ // Pass through to API with new structure
201
+ return makeApiCall("update-memory", {
202
+ space_id: args.space_id,
203
+ add: args.add,
204
+ update: args.update,
205
+ delete: args.delete,
206
+ });
207
+ }
208
+
209
+ server.setRequestHandler(CallToolRequestSchema, async (request: any) => {
210
+ const { name, arguments: args } = request.params;
211
+
212
+ try {
213
+ let result: any;
214
+
215
+ switch (name) {
216
+ case "search":
217
+ result = await handleSearchMemories(args);
218
+ break;
219
+ case "fetch":
220
+ result = await handleFetch(args);
221
+ break;
222
+ case "view_spaces":
223
+ result = await handleViewSpaces();
224
+ break;
225
+ case "create_space":
226
+ result = await handleCreateSpace(args);
227
+ break;
228
+ case "view_space":
229
+ result = await handleViewSpace(args);
230
+ break;
231
+ case "start":
232
+ result = await handleStart(args);
233
+ break;
234
+ case "update_space":
235
+ result = await handleUpdateSpace(args);
236
+ break;
237
+ default:
238
+ throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
239
+ }
240
+
241
+ // Extract response field for Layer 2 compressed tools, otherwise stringify full result
242
+ let responseText: string;
243
+ if (
244
+ result &&
245
+ typeof result === "object" &&
246
+ "response" in result &&
247
+ typeof result.response === "string"
248
+ ) {
249
+ // Tool has Layer 2 compression - use the formatted response field
250
+ responseText = result.response;
251
+ } else {
252
+ // Standard tool - return full JSON
253
+ responseText = JSON.stringify(result, null, 2);
254
+ }
255
+
256
+ // Add version warning to response if outdated
257
+ if (latestVersion && latestVersion !== CURRENT_VERSION) {
258
+ const warning = `\n\n UPDATE AVAILABLE: MCP Server v${latestVersion} is available (you're on v${CURRENT_VERSION}). Update with: npx @intangle/mcp-server@latest`;
259
+ responseText += warning;
260
+ }
261
+
262
+ return {
263
+ content: [{ type: "text", text: responseText }],
264
+ };
265
+ } catch (error) {
266
+ throw new McpError(
267
+ ErrorCode.InternalError,
268
+ `Error executing tool ${name}: ${error instanceof Error ? error.message : String(error)}`,
269
+ );
243
270
  }
271
+ });
244
272
 
245
- return {
246
- content: [{ type: "text", text: responseText }],
247
- };
248
- } catch (error) {
249
- throw new McpError(
250
- ErrorCode.InternalError,
251
- `Error executing tool ${name}: ${error instanceof Error ? error.message : String(error)}`,
252
- );
273
+ async function main() {
274
+ const transport = new StdioServerTransport();
275
+ await server.connect(transport);
276
+ log("Server connected to transport");
253
277
  }
254
- });
255
278
 
256
- async function main() {
257
- const transport = new StdioServerTransport();
258
- await server.connect(transport);
259
- }
279
+ main().catch((err) => {
280
+ log(`Error in main: ${err}`);
281
+ process.exit(1);
282
+ });
260
283
 
261
- main().catch(() => {
284
+ } catch (err) {
285
+ log(`Fatal startup error: ${err}`);
262
286
  process.exit(1);
263
- });
287
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intangle/mcp-server",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "description": "Model Context Protocol server for Intangle - AI memory that persists across conversations",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",