@delega-dev/mcp 1.0.6 → 1.0.8
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/README.md +7 -0
- package/dist/index.js +95 -31
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -34,9 +34,16 @@ Add to your MCP client config (e.g. Claude Desktop `claude_desktop_config.json`)
|
|
|
34
34
|
|----------|---------|-------------|
|
|
35
35
|
| `DELEGA_API_URL` | `http://127.0.0.1:18890` | Delega API endpoint |
|
|
36
36
|
| `DELEGA_AGENT_KEY` | (none) | Agent API key for authenticated requests |
|
|
37
|
+
| `DELEGA_REVEAL_AGENT_KEYS` | `0` | Set to `1` only if you want MCP tool output to print full agent API keys |
|
|
37
38
|
|
|
38
39
|
For the hosted tier, use `https://api.delega.dev` as the URL.
|
|
39
40
|
|
|
41
|
+
## Security Notes
|
|
42
|
+
|
|
43
|
+
- Non-local `DELEGA_API_URL` values must use `https://`.
|
|
44
|
+
- Agent keys are passed through environment variables rather than command-line arguments, which avoids process-list leakage.
|
|
45
|
+
- MCP tool output redacts full agent API keys by default. Set `DELEGA_REVEAL_AGENT_KEYS=1` only when you explicitly want them printed back to the client.
|
|
46
|
+
|
|
40
47
|
## Tools
|
|
41
48
|
|
|
42
49
|
| Tool | Description |
|
package/dist/index.js
CHANGED
|
@@ -7,14 +7,34 @@ import { z } from "zod";
|
|
|
7
7
|
|
|
8
8
|
// src/delega-client.ts
|
|
9
9
|
var DEFAULT_BASE_URL = "http://127.0.0.1:18890";
|
|
10
|
+
var LOCAL_API_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1"]);
|
|
11
|
+
var DelegaApiError = class extends Error {
|
|
12
|
+
status;
|
|
13
|
+
statusText;
|
|
14
|
+
responseBody;
|
|
15
|
+
constructor(status, statusText, responseBody) {
|
|
16
|
+
super(`Delega API request failed (${status} ${statusText})`);
|
|
17
|
+
this.name = "DelegaApiError";
|
|
18
|
+
this.status = status;
|
|
19
|
+
this.statusText = statusText;
|
|
20
|
+
this.responseBody = responseBody;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
function normalizeBaseUrl(rawUrl) {
|
|
24
|
+
const parsed = new URL(rawUrl);
|
|
25
|
+
if (parsed.protocol !== "https:" && !LOCAL_API_HOSTS.has(parsed.hostname)) {
|
|
26
|
+
throw new Error("Delega API URL must use HTTPS unless it points to localhost");
|
|
27
|
+
}
|
|
28
|
+
return rawUrl.replace(/\/+$/, "");
|
|
29
|
+
}
|
|
10
30
|
var DelegaClient = class {
|
|
11
31
|
baseUrl;
|
|
12
32
|
agentKey;
|
|
13
33
|
pathPrefix;
|
|
14
34
|
constructor(baseUrl, agentKey) {
|
|
15
|
-
this.baseUrl = (baseUrl || DEFAULT_BASE_URL)
|
|
35
|
+
this.baseUrl = normalizeBaseUrl(baseUrl || DEFAULT_BASE_URL);
|
|
16
36
|
this.agentKey = agentKey;
|
|
17
|
-
this.pathPrefix = this.baseUrl.
|
|
37
|
+
this.pathPrefix = new URL(this.baseUrl).hostname === "api.delega.dev" ? "/v1" : "/api";
|
|
18
38
|
}
|
|
19
39
|
async request(method, path, body, query) {
|
|
20
40
|
const url = new URL(path, this.baseUrl);
|
|
@@ -38,9 +58,7 @@ var DelegaClient = class {
|
|
|
38
58
|
});
|
|
39
59
|
if (!res.ok) {
|
|
40
60
|
const text = await res.text().catch(() => "");
|
|
41
|
-
throw new
|
|
42
|
-
`Delega API error: ${res.status} ${res.statusText}${text ? ` \u2014 ${text}` : ""}`
|
|
43
|
-
);
|
|
61
|
+
throw new DelegaApiError(res.status, res.statusText, text);
|
|
44
62
|
}
|
|
45
63
|
if (res.status === 204) {
|
|
46
64
|
return void 0;
|
|
@@ -130,15 +148,62 @@ function formatTask(t) {
|
|
|
130
148
|
function formatProject(p) {
|
|
131
149
|
return `[#${p.id}] ${p.name}`;
|
|
132
150
|
}
|
|
151
|
+
function maskApiKey(key) {
|
|
152
|
+
if (key.length <= 12) return key;
|
|
153
|
+
return `${key.slice(0, 8)}...${key.slice(-4)}`;
|
|
154
|
+
}
|
|
133
155
|
function formatAgent(a) {
|
|
134
156
|
const lines = [];
|
|
135
157
|
lines.push(`[#${a.id}] ${a.name}${a.display_name ? ` (${a.display_name})` : ""}`);
|
|
136
158
|
if (a.description) lines.push(` Description: ${a.description}`);
|
|
137
|
-
if (a.api_key)
|
|
159
|
+
if (a.api_key) {
|
|
160
|
+
if (process.env.DELEGA_REVEAL_AGENT_KEYS === "1") {
|
|
161
|
+
lines.push(` API Key: ${a.api_key}`);
|
|
162
|
+
} else {
|
|
163
|
+
lines.push(` API Key Preview: ${maskApiKey(a.api_key)}`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
138
166
|
if (a.permissions?.length) lines.push(` Permissions: ${a.permissions.join(", ")}`);
|
|
139
167
|
if (a.active !== void 0) lines.push(` Active: ${a.active ? "yes" : "no"}`);
|
|
140
168
|
return lines.join("\n");
|
|
141
169
|
}
|
|
170
|
+
function sanitizeToolError(error) {
|
|
171
|
+
if (error instanceof DelegaApiError) {
|
|
172
|
+
if (error.responseBody) {
|
|
173
|
+
console.error("Delega API error response:", {
|
|
174
|
+
status: error.status,
|
|
175
|
+
statusText: error.statusText,
|
|
176
|
+
body: error.responseBody
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
if (error.status === 400 || error.status === 422) {
|
|
180
|
+
return "Delega API rejected the request. Check the tool inputs and try again.";
|
|
181
|
+
}
|
|
182
|
+
if (error.status === 401) {
|
|
183
|
+
return "Delega API authentication failed. Check DELEGA_AGENT_KEY.";
|
|
184
|
+
}
|
|
185
|
+
if (error.status === 403) {
|
|
186
|
+
return "Delega API denied this action.";
|
|
187
|
+
}
|
|
188
|
+
if (error.status === 404) {
|
|
189
|
+
return "The requested Delega resource was not found.";
|
|
190
|
+
}
|
|
191
|
+
if (error.status >= 500) {
|
|
192
|
+
return "Delega API returned a server error.";
|
|
193
|
+
}
|
|
194
|
+
return `Delega API request failed (${error.status} ${error.statusText}).`;
|
|
195
|
+
}
|
|
196
|
+
if (error instanceof Error) {
|
|
197
|
+
return error.message;
|
|
198
|
+
}
|
|
199
|
+
return "Unexpected error";
|
|
200
|
+
}
|
|
201
|
+
function toolErrorResult(error) {
|
|
202
|
+
return {
|
|
203
|
+
content: [{ type: "text", text: `Error: ${sanitizeToolError(error)}` }],
|
|
204
|
+
isError: true
|
|
205
|
+
};
|
|
206
|
+
}
|
|
142
207
|
var server = new McpServer({
|
|
143
208
|
name: "delega-mcp",
|
|
144
209
|
version: "1.0.0"
|
|
@@ -160,8 +225,8 @@ server.tool(
|
|
|
160
225
|
}
|
|
161
226
|
const text = tasks.map(formatTask).join("\n\n");
|
|
162
227
|
return { content: [{ type: "text", text }] };
|
|
163
|
-
} catch (
|
|
164
|
-
return
|
|
228
|
+
} catch (error) {
|
|
229
|
+
return toolErrorResult(error);
|
|
165
230
|
}
|
|
166
231
|
}
|
|
167
232
|
);
|
|
@@ -175,8 +240,8 @@ server.tool(
|
|
|
175
240
|
try {
|
|
176
241
|
const task = await client.getTask(task_id);
|
|
177
242
|
return { content: [{ type: "text", text: formatTask(task) }] };
|
|
178
|
-
} catch (
|
|
179
|
-
return
|
|
243
|
+
} catch (error) {
|
|
244
|
+
return toolErrorResult(error);
|
|
180
245
|
}
|
|
181
246
|
}
|
|
182
247
|
);
|
|
@@ -199,8 +264,8 @@ server.tool(
|
|
|
199
264
|
|
|
200
265
|
${formatTask(task)}` }]
|
|
201
266
|
};
|
|
202
|
-
} catch (
|
|
203
|
-
return
|
|
267
|
+
} catch (error) {
|
|
268
|
+
return toolErrorResult(error);
|
|
204
269
|
}
|
|
205
270
|
}
|
|
206
271
|
);
|
|
@@ -224,8 +289,8 @@ server.tool(
|
|
|
224
289
|
|
|
225
290
|
${formatTask(task)}` }]
|
|
226
291
|
};
|
|
227
|
-
} catch (
|
|
228
|
-
return
|
|
292
|
+
} catch (error) {
|
|
293
|
+
return toolErrorResult(error);
|
|
229
294
|
}
|
|
230
295
|
}
|
|
231
296
|
);
|
|
@@ -244,8 +309,8 @@ server.tool(
|
|
|
244
309
|
Next occurrence: ${task.next_occurrence}`;
|
|
245
310
|
}
|
|
246
311
|
return { content: [{ type: "text", text }] };
|
|
247
|
-
} catch (
|
|
248
|
-
return
|
|
312
|
+
} catch (error) {
|
|
313
|
+
return toolErrorResult(error);
|
|
249
314
|
}
|
|
250
315
|
}
|
|
251
316
|
);
|
|
@@ -261,8 +326,8 @@ server.tool(
|
|
|
261
326
|
return {
|
|
262
327
|
content: [{ type: "text", text: `Task #${task_id} deleted.` }]
|
|
263
328
|
};
|
|
264
|
-
} catch (
|
|
265
|
-
return
|
|
329
|
+
} catch (error) {
|
|
330
|
+
return toolErrorResult(error);
|
|
266
331
|
}
|
|
267
332
|
}
|
|
268
333
|
);
|
|
@@ -286,8 +351,8 @@ server.tool(
|
|
|
286
351
|
}
|
|
287
352
|
]
|
|
288
353
|
};
|
|
289
|
-
} catch (
|
|
290
|
-
return
|
|
354
|
+
} catch (error) {
|
|
355
|
+
return toolErrorResult(error);
|
|
291
356
|
}
|
|
292
357
|
}
|
|
293
358
|
);
|
|
@@ -303,8 +368,8 @@ server.tool(
|
|
|
303
368
|
}
|
|
304
369
|
const text = projects.map(formatProject).join("\n");
|
|
305
370
|
return { content: [{ type: "text", text }] };
|
|
306
|
-
} catch (
|
|
307
|
-
return
|
|
371
|
+
} catch (error) {
|
|
372
|
+
return toolErrorResult(error);
|
|
308
373
|
}
|
|
309
374
|
}
|
|
310
375
|
);
|
|
@@ -327,8 +392,8 @@ server.tool(
|
|
|
327
392
|
}
|
|
328
393
|
}
|
|
329
394
|
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
330
|
-
} catch (
|
|
331
|
-
return
|
|
395
|
+
} catch (error) {
|
|
396
|
+
return toolErrorResult(error);
|
|
332
397
|
}
|
|
333
398
|
}
|
|
334
399
|
);
|
|
@@ -344,8 +409,8 @@ server.tool(
|
|
|
344
409
|
}
|
|
345
410
|
const text = agents.map(formatAgent).join("\n\n");
|
|
346
411
|
return { content: [{ type: "text", text }] };
|
|
347
|
-
} catch (
|
|
348
|
-
return
|
|
412
|
+
} catch (error) {
|
|
413
|
+
return toolErrorResult(error);
|
|
349
414
|
}
|
|
350
415
|
}
|
|
351
416
|
);
|
|
@@ -361,15 +426,14 @@ server.tool(
|
|
|
361
426
|
async (params) => {
|
|
362
427
|
try {
|
|
363
428
|
const agent = await client.registerAgent(params);
|
|
429
|
+
const warning = process.env.DELEGA_REVEAL_AGENT_KEYS === "1" ? "\n\n\u26A0\uFE0F Save the API key \u2014 it won't be shown again." : "\n\nAPI keys are redacted by default in MCP output. Set DELEGA_REVEAL_AGENT_KEYS=1 to reveal them.";
|
|
364
430
|
return {
|
|
365
431
|
content: [{ type: "text", text: `Agent registered:
|
|
366
432
|
|
|
367
|
-
${formatAgent(agent)}
|
|
368
|
-
|
|
369
|
-
\u26A0\uFE0F Save the API key \u2014 it won't be shown again.` }]
|
|
433
|
+
${formatAgent(agent)}${warning}` }]
|
|
370
434
|
};
|
|
371
|
-
} catch (
|
|
372
|
-
return
|
|
435
|
+
} catch (error) {
|
|
436
|
+
return toolErrorResult(error);
|
|
373
437
|
}
|
|
374
438
|
}
|
|
375
439
|
);
|