@intangle/mcp-server 2.1.2 → 2.1.4

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