@heznpc/imcp 1.0.0 → 1.2.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/README.md +179 -212
- package/dist/calendar/scripts.js +11 -8
- package/dist/calendar/scripts.js.map +1 -1
- package/dist/cli/doctor.d.ts +7 -0
- package/dist/cli/doctor.js +135 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/init.d.ts +8 -0
- package/dist/cli/init.js +145 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cross/tools.d.ts +7 -0
- package/dist/cross/tools.js +81 -0
- package/dist/cross/tools.js.map +1 -0
- package/dist/finder/scripts.js +3 -3
- package/dist/finder/tools.js +1 -1
- package/dist/finder/tools.js.map +1 -1
- package/dist/index.js +105 -22
- package/dist/index.js.map +1 -1
- package/dist/mail/scripts.d.ts +2 -0
- package/dist/mail/scripts.js +42 -0
- package/dist/mail/scripts.js.map +1 -1
- package/dist/mail/tools.d.ts +1 -1
- package/dist/mail/tools.js +45 -2
- package/dist/mail/tools.js.map +1 -1
- package/dist/messages/scripts.js +56 -19
- package/dist/messages/scripts.js.map +1 -1
- package/dist/messages/tools.d.ts +1 -1
- package/dist/messages/tools.js +6 -1
- package/dist/messages/tools.js.map +1 -1
- package/dist/shared/config.d.ts +23 -0
- package/dist/shared/config.js +112 -1
- package/dist/shared/config.js.map +1 -1
- package/dist/shared/hitl-guard.d.ts +8 -0
- package/dist/shared/hitl-guard.js +39 -0
- package/dist/shared/hitl-guard.js.map +1 -0
- package/dist/shared/hitl.d.ts +16 -0
- package/dist/shared/hitl.js +131 -0
- package/dist/shared/hitl.js.map +1 -0
- package/dist/shared/resources.d.ts +10 -1
- package/dist/shared/resources.js +199 -45
- package/dist/shared/resources.js.map +1 -1
- package/dist/shared/setup.d.ts +2 -1
- package/dist/shared/setup.js +23 -14
- package/dist/shared/setup.js.map +1 -1
- package/dist/shortcuts/prompts.d.ts +2 -0
- package/dist/shortcuts/prompts.js +148 -0
- package/dist/shortcuts/prompts.js.map +1 -0
- package/dist/system/scripts.js +4 -2
- package/dist/system/scripts.js.map +1 -1
- package/dist/system/tools.js +2 -2
- package/dist/system/tools.js.map +1 -1
- package/dist/tv/scripts.d.ts +6 -0
- package/dist/tv/scripts.js +121 -0
- package/dist/tv/scripts.js.map +1 -0
- package/dist/tv/tools.d.ts +3 -0
- package/dist/tv/tools.js +95 -0
- package/dist/tv/tools.js.map +1 -0
- package/package.json +5 -4
package/dist/mail/tools.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { runJxa } from "../shared/jxa.js";
|
|
3
3
|
import { ok, err } from "../shared/result.js";
|
|
4
|
-
import { listMailboxesScript, listMessagesScript, readMessageScript, searchMessagesScript, markReadScript, flagMessageScript, getUnreadCountScript, moveMessageScript, listAccountsScript, } from "./scripts.js";
|
|
5
|
-
export function registerMailTools(server,
|
|
4
|
+
import { listMailboxesScript, listMessagesScript, readMessageScript, searchMessagesScript, markReadScript, flagMessageScript, getUnreadCountScript, moveMessageScript, listAccountsScript, sendMailScript, replyMailScript, } from "./scripts.js";
|
|
5
|
+
export function registerMailTools(server, config) {
|
|
6
|
+
const { allowSendMail } = config;
|
|
6
7
|
server.registerTool("list_mailboxes", {
|
|
7
8
|
title: "List Mailboxes",
|
|
8
9
|
description: "List all mailboxes across accounts with unread counts.",
|
|
@@ -141,5 +142,47 @@ export function registerMailTools(server, _config) {
|
|
|
141
142
|
return err(`Failed to list accounts: ${e instanceof Error ? e.message : String(e)}`);
|
|
142
143
|
}
|
|
143
144
|
});
|
|
145
|
+
// ── Send tools (gated by allowSendMail) ──
|
|
146
|
+
server.registerTool("send_mail", {
|
|
147
|
+
title: "Send Email",
|
|
148
|
+
description: "Compose and send an email via Apple Mail. Requires allowSendMail config.",
|
|
149
|
+
inputSchema: {
|
|
150
|
+
to: z.array(z.string()).min(1).describe("Recipient email addresses"),
|
|
151
|
+
subject: z.string().describe("Email subject"),
|
|
152
|
+
body: z.string().describe("Email body text"),
|
|
153
|
+
cc: z.array(z.string()).optional().describe("CC recipients"),
|
|
154
|
+
bcc: z.array(z.string()).optional().describe("BCC recipients"),
|
|
155
|
+
account: z.string().optional().describe("Sender email address (uses default account if omitted)"),
|
|
156
|
+
},
|
|
157
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
158
|
+
}, async ({ to, subject, body, cc, bcc, account }) => {
|
|
159
|
+
if (!allowSendMail)
|
|
160
|
+
return err("Sending mail is disabled. Set allowSendMail: true in config or IMCP_ALLOW_SEND_MAIL=true.");
|
|
161
|
+
try {
|
|
162
|
+
return ok(await runJxa(sendMailScript(to, subject, body, cc, bcc, account)));
|
|
163
|
+
}
|
|
164
|
+
catch (e) {
|
|
165
|
+
return err(`Failed to send mail: ${e instanceof Error ? e.message : String(e)}`);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
server.registerTool("reply_mail", {
|
|
169
|
+
title: "Reply to Email",
|
|
170
|
+
description: "Reply to an email message. Requires allowSendMail config.",
|
|
171
|
+
inputSchema: {
|
|
172
|
+
id: z.string().describe("Original message ID to reply to"),
|
|
173
|
+
body: z.string().describe("Reply body text"),
|
|
174
|
+
replyAll: z.boolean().optional().default(false).describe("Reply to all recipients (default: false)"),
|
|
175
|
+
},
|
|
176
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
177
|
+
}, async ({ id, body, replyAll }) => {
|
|
178
|
+
if (!allowSendMail)
|
|
179
|
+
return err("Sending mail is disabled. Set allowSendMail: true in config or IMCP_ALLOW_SEND_MAIL=true.");
|
|
180
|
+
try {
|
|
181
|
+
return ok(await runJxa(replyMailScript(id, body, replyAll)));
|
|
182
|
+
}
|
|
183
|
+
catch (e) {
|
|
184
|
+
return err(`Failed to reply: ${e instanceof Error ? e.message : String(e)}`);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
144
187
|
}
|
|
145
188
|
//# sourceMappingURL=tools.js.map
|
package/dist/mail/tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/mail/tools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/mail/tools.ts"],"names":[],"mappings":"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"}
|
package/dist/messages/scripts.js
CHANGED
|
@@ -8,15 +8,23 @@ export function listChatsScript(limit) {
|
|
|
8
8
|
const result = [];
|
|
9
9
|
for (let i = 0; i < count; i++) {
|
|
10
10
|
const c = chats[i];
|
|
11
|
-
|
|
11
|
+
let parts = [];
|
|
12
|
+
try {
|
|
13
|
+
const participants = c.participants();
|
|
14
|
+
parts = participants.map(p => {
|
|
15
|
+
let name = null, handle = null;
|
|
16
|
+
try { name = p.name(); } catch(e) {}
|
|
17
|
+
try { handle = p.handle(); } catch(e) {}
|
|
18
|
+
return {name, handle};
|
|
19
|
+
});
|
|
20
|
+
} catch(e) {}
|
|
21
|
+
let updated = null;
|
|
22
|
+
try { updated = c.updatedDate() ? c.updatedDate().toISOString() : null; } catch(e) {}
|
|
12
23
|
result.push({
|
|
13
24
|
id: c.id(),
|
|
14
25
|
name: c.name() || null,
|
|
15
|
-
participants:
|
|
16
|
-
|
|
17
|
-
handle: p.handle()
|
|
18
|
-
})),
|
|
19
|
-
updated: c.updatedDate() ? c.updatedDate().toISOString() : null
|
|
26
|
+
participants: parts,
|
|
27
|
+
updated: updated
|
|
20
28
|
});
|
|
21
29
|
}
|
|
22
30
|
JSON.stringify({total: chats.length, returned: count, chats: result});
|
|
@@ -28,12 +36,23 @@ export function readChatScript(chatId) {
|
|
|
28
36
|
const chats = Messages.chats.whose({id: '${esc(chatId)}'})();
|
|
29
37
|
if (chats.length === 0) throw new Error('Chat not found: ${esc(chatId)}');
|
|
30
38
|
const chat = chats[0];
|
|
31
|
-
|
|
39
|
+
let parts = [];
|
|
40
|
+
try {
|
|
41
|
+
const participants = chat.participants();
|
|
42
|
+
parts = participants.map(p => {
|
|
43
|
+
let name = null, handle = null;
|
|
44
|
+
try { name = p.name(); } catch(e) {}
|
|
45
|
+
try { handle = p.handle(); } catch(e) {}
|
|
46
|
+
return {name, handle};
|
|
47
|
+
});
|
|
48
|
+
} catch(e) {}
|
|
49
|
+
let updated = null;
|
|
50
|
+
try { updated = chat.updatedDate() ? chat.updatedDate().toISOString() : null; } catch(e) {}
|
|
32
51
|
JSON.stringify({
|
|
33
52
|
id: chat.id(),
|
|
34
53
|
name: chat.name() || null,
|
|
35
|
-
participants:
|
|
36
|
-
updated:
|
|
54
|
+
participants: parts,
|
|
55
|
+
updated: updated
|
|
37
56
|
});
|
|
38
57
|
`;
|
|
39
58
|
}
|
|
@@ -46,17 +65,30 @@ export function searchMessagesScript(query, limit) {
|
|
|
46
65
|
for (const chat of chats) {
|
|
47
66
|
if (result.length >= ${limit}) break;
|
|
48
67
|
const name = chat.name() || '';
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
68
|
+
let parts = [];
|
|
69
|
+
let participantNames = '';
|
|
70
|
+
let participantHandles = '';
|
|
71
|
+
try {
|
|
72
|
+
const participants = chat.participants();
|
|
73
|
+
parts = participants.map(p => {
|
|
74
|
+
let pn = null, ph = null;
|
|
75
|
+
try { pn = p.name(); } catch(e) {}
|
|
76
|
+
try { ph = p.handle(); } catch(e) {}
|
|
77
|
+
return {name: pn, handle: ph};
|
|
78
|
+
});
|
|
79
|
+
participantNames = parts.map(p => p.name || '').join(' ');
|
|
80
|
+
participantHandles = parts.map(p => p.handle || '').join(' ');
|
|
81
|
+
} catch(e) {}
|
|
52
82
|
if (name.toLowerCase().includes(q) ||
|
|
53
83
|
participantNames.toLowerCase().includes(q) ||
|
|
54
84
|
participantHandles.toLowerCase().includes(q)) {
|
|
85
|
+
let updated = null;
|
|
86
|
+
try { updated = chat.updatedDate() ? chat.updatedDate().toISOString() : null; } catch(e) {}
|
|
55
87
|
result.push({
|
|
56
88
|
id: chat.id(),
|
|
57
89
|
name: name || null,
|
|
58
|
-
participants:
|
|
59
|
-
updated:
|
|
90
|
+
participants: parts,
|
|
91
|
+
updated: updated
|
|
60
92
|
});
|
|
61
93
|
}
|
|
62
94
|
}
|
|
@@ -92,11 +124,16 @@ export function listParticipantsScript(chatId) {
|
|
|
92
124
|
const chats = Messages.chats.whose({id: '${esc(chatId)}'})();
|
|
93
125
|
if (chats.length === 0) throw new Error('Chat not found: ${esc(chatId)}');
|
|
94
126
|
const chat = chats[0];
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
127
|
+
let result = [];
|
|
128
|
+
try {
|
|
129
|
+
const participants = chat.participants();
|
|
130
|
+
result = participants.map(p => {
|
|
131
|
+
let name = null, handle = null;
|
|
132
|
+
try { name = p.name(); } catch(e) {}
|
|
133
|
+
try { handle = p.handle(); } catch(e) {}
|
|
134
|
+
return {name, handle};
|
|
135
|
+
});
|
|
136
|
+
} catch(e) {}
|
|
100
137
|
JSON.stringify({chatId: '${esc(chatId)}', chatName: chat.name() || null, participants: result});
|
|
101
138
|
`;
|
|
102
139
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scripts.js","sourceRoot":"","sources":["../../src/messages/scripts.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAE7C,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEvC,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO;;;2CAGkC,KAAK
|
|
1
|
+
{"version":3,"file":"scripts.js","sourceRoot":"","sources":["../../src/messages/scripts.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAE7C,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEvC,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO;;;2CAGkC,KAAK;;;;;;;;;;;;;;;;;;;;;;;;GAwB7C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,OAAO;;+CAEsC,GAAG,CAAC,MAAM,CAAC;+DACK,GAAG,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;GAoBvE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,KAAa,EACb,KAAa;IAEb,OAAO;;;iBAGQ,GAAG,CAAC,KAAK,CAAC;;;6BAGE,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8B/B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,IAAY;IAEZ,OAAO;;;;oDAI2C,GAAG,CAAC,MAAM,CAAC;2EACY,GAAG,CAAC,MAAM,CAAC;qBACjE,GAAG,CAAC,IAAI,CAAC;uCACS,GAAG,CAAC,MAAM,CAAC,aAAa,GAAG,CAAC,IAAI,CAAC;GACrE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,MAAc,EACd,QAAgB;IAEhB,OAAO;;;;oDAI2C,GAAG,CAAC,MAAM,CAAC;2EACY,GAAG,CAAC,MAAM,CAAC;yBAC7D,GAAG,CAAC,QAAQ,CAAC;;uCAEC,GAAG,CAAC,MAAM,CAAC,aAAa,GAAG,CAAC,QAAQ,CAAC;GACzE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,MAAc;IACnD,OAAO;;+CAEsC,GAAG,CAAC,MAAM,CAAC;+DACK,GAAG,CAAC,MAAM,CAAC;;;;;;;;;;;;+BAY3C,GAAG,CAAC,MAAM,CAAC;GACvC,CAAC;AACJ,CAAC"}
|
package/dist/messages/tools.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import type { ImcpConfig } from "../shared/config.js";
|
|
3
|
-
export declare function registerMessagesTools(server: McpServer,
|
|
3
|
+
export declare function registerMessagesTools(server: McpServer, config: ImcpConfig): void;
|
package/dist/messages/tools.js
CHANGED
|
@@ -2,7 +2,8 @@ import { z } from "zod";
|
|
|
2
2
|
import { runJxa } from "../shared/jxa.js";
|
|
3
3
|
import { ok, err } from "../shared/result.js";
|
|
4
4
|
import { listChatsScript, readChatScript, searchMessagesScript, sendMessageScript, sendFileScript, listParticipantsScript, } from "./scripts.js";
|
|
5
|
-
export function registerMessagesTools(server,
|
|
5
|
+
export function registerMessagesTools(server, config) {
|
|
6
|
+
const { allowSendMessages } = config;
|
|
6
7
|
server.registerTool("list_chats", {
|
|
7
8
|
title: "List Chats",
|
|
8
9
|
description: "List recent chats in Messages with participants and last update time.",
|
|
@@ -58,6 +59,8 @@ export function registerMessagesTools(server, _config) {
|
|
|
58
59
|
},
|
|
59
60
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
60
61
|
}, async ({ target, text }) => {
|
|
62
|
+
if (!allowSendMessages)
|
|
63
|
+
return err("Sending messages is disabled. Set IMCP_ALLOW_SEND_MESSAGES=true to enable.");
|
|
61
64
|
try {
|
|
62
65
|
return ok(await runJxa(sendMessageScript(target, text)));
|
|
63
66
|
}
|
|
@@ -74,6 +77,8 @@ export function registerMessagesTools(server, _config) {
|
|
|
74
77
|
},
|
|
75
78
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
76
79
|
}, async ({ target, filePath }) => {
|
|
80
|
+
if (!allowSendMessages)
|
|
81
|
+
return err("Sending messages is disabled. Set IMCP_ALLOW_SEND_MESSAGES=true to enable.");
|
|
77
82
|
try {
|
|
78
83
|
return ok(await runJxa(sendFileScript(target, filePath)));
|
|
79
84
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/messages/tools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EACL,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,EACd,sBAAsB,GACvB,MAAM,cAAc,CAAC;AAEtB,MAAM,UAAU,qBAAqB,CAAC,MAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/messages/tools.ts"],"names":[],"mappings":"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"}
|
package/dist/shared/config.d.ts
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
|
+
export type HitlLevel = "off" | "destructive-only" | "all-writes" | "all";
|
|
2
|
+
export interface HitlConfig {
|
|
3
|
+
level: HitlLevel;
|
|
4
|
+
whitelist: Set<string>;
|
|
5
|
+
timeout: number;
|
|
6
|
+
socketPath: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const MODULE_NAMES: readonly ["notes", "reminders", "calendar", "contacts", "mail", "messages", "music", "finder", "safari", "system", "photos", "shortcuts", "intelligence", "tv"];
|
|
9
|
+
/** Core modules enabled by default when no config.json exists */
|
|
10
|
+
export declare const STARTER_MODULES: ReadonlySet<string>;
|
|
11
|
+
export type ModuleName = (typeof MODULE_NAMES)[number];
|
|
1
12
|
export interface ImcpConfig {
|
|
2
13
|
/** Include shared notes/folders in results. Default: false */
|
|
3
14
|
includeShared: boolean;
|
|
15
|
+
/** Set of disabled module names */
|
|
16
|
+
disabledModules: Set<string>;
|
|
17
|
+
/** Set of module names that require share approval */
|
|
18
|
+
shareApprovalModules: Set<string>;
|
|
19
|
+
/** Allow sending messages via Messages app. Default: true */
|
|
20
|
+
allowSendMessages: boolean;
|
|
21
|
+
/** Allow sending emails via Mail app. Default: true */
|
|
22
|
+
allowSendMail: boolean;
|
|
23
|
+
/** Human-in-the-loop confirmation config */
|
|
24
|
+
hitl: HitlConfig;
|
|
4
25
|
}
|
|
5
26
|
export declare function parseConfig(): ImcpConfig;
|
|
27
|
+
export declare function isModuleEnabled(config: ImcpConfig, moduleName: string): boolean;
|
|
28
|
+
export declare function needsShareApproval(config: ImcpConfig, moduleName: string): boolean;
|
package/dist/shared/config.js
CHANGED
|
@@ -1,6 +1,117 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
const HITL_LEVELS = ["off", "destructive-only", "all-writes", "all"];
|
|
4
|
+
export const MODULE_NAMES = [
|
|
5
|
+
"notes",
|
|
6
|
+
"reminders",
|
|
7
|
+
"calendar",
|
|
8
|
+
"contacts",
|
|
9
|
+
"mail",
|
|
10
|
+
"messages",
|
|
11
|
+
"music",
|
|
12
|
+
"finder",
|
|
13
|
+
"safari",
|
|
14
|
+
"system",
|
|
15
|
+
"photos",
|
|
16
|
+
"shortcuts",
|
|
17
|
+
"intelligence",
|
|
18
|
+
"tv",
|
|
19
|
+
];
|
|
20
|
+
/** Core modules enabled by default when no config.json exists */
|
|
21
|
+
export const STARTER_MODULES = new Set([
|
|
22
|
+
"notes",
|
|
23
|
+
"reminders",
|
|
24
|
+
"calendar",
|
|
25
|
+
"shortcuts",
|
|
26
|
+
"system",
|
|
27
|
+
]);
|
|
28
|
+
function loadFileConfig() {
|
|
29
|
+
try {
|
|
30
|
+
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
31
|
+
const file = join(home, ".config", "imcp", "config.json");
|
|
32
|
+
const data = readFileSync(file, "utf-8");
|
|
33
|
+
return { config: JSON.parse(data), fileExists: true };
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return { config: {}, fileExists: false };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
1
39
|
export function parseConfig() {
|
|
40
|
+
const { config: file, fileExists } = loadFileConfig();
|
|
41
|
+
const fullMode = process.env.IMCP_FULL === "true" || process.argv.includes("--full");
|
|
42
|
+
// Disabled modules: env vars override, then JSON fallback, then starter preset
|
|
43
|
+
const disabledModules = new Set();
|
|
44
|
+
const fileDisabled = new Set(file.disabledModules ?? []);
|
|
45
|
+
for (const mod of MODULE_NAMES) {
|
|
46
|
+
const envKey = `IMCP_DISABLE_${mod.toUpperCase()}`;
|
|
47
|
+
const envVal = process.env[envKey];
|
|
48
|
+
if (envVal === "true") {
|
|
49
|
+
disabledModules.add(mod);
|
|
50
|
+
}
|
|
51
|
+
else if (envVal === undefined && fileDisabled.has(mod)) {
|
|
52
|
+
disabledModules.add(mod);
|
|
53
|
+
}
|
|
54
|
+
else if (envVal === undefined && !fileExists && !fullMode && !STARTER_MODULES.has(mod)) {
|
|
55
|
+
// No config.json & not --full: apply starter preset
|
|
56
|
+
disabledModules.add(mod);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Share approval: env var overrides, then JSON fallback
|
|
60
|
+
const shareApprovalModules = new Set();
|
|
61
|
+
const shareApprovalEnv = process.env.IMCP_SHARE_APPROVAL;
|
|
62
|
+
if (shareApprovalEnv) {
|
|
63
|
+
for (const raw of shareApprovalEnv.split(",")) {
|
|
64
|
+
const mod = raw.trim().toLowerCase();
|
|
65
|
+
if (mod && MODULE_NAMES.includes(mod)) {
|
|
66
|
+
shareApprovalModules.add(mod);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else if (file.shareApproval) {
|
|
71
|
+
for (const mod of file.shareApproval) {
|
|
72
|
+
if (MODULE_NAMES.includes(mod)) {
|
|
73
|
+
shareApprovalModules.add(mod);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Boolean configs: env var > JSON > default
|
|
78
|
+
const includeShared = process.env.IMCP_INCLUDE_SHARED !== undefined
|
|
79
|
+
? process.env.IMCP_INCLUDE_SHARED === "true"
|
|
80
|
+
: (file.includeShared ?? false);
|
|
81
|
+
const allowSendMessages = process.env.IMCP_ALLOW_SEND_MESSAGES !== undefined
|
|
82
|
+
? process.env.IMCP_ALLOW_SEND_MESSAGES !== "false"
|
|
83
|
+
: (file.allowSendMessages ?? true);
|
|
84
|
+
const allowSendMail = process.env.IMCP_ALLOW_SEND_MAIL !== undefined
|
|
85
|
+
? process.env.IMCP_ALLOW_SEND_MAIL !== "false"
|
|
86
|
+
: (file.allowSendMail ?? true);
|
|
87
|
+
// HITL config: env var > JSON > default
|
|
88
|
+
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
89
|
+
const hitlLevelRaw = process.env.IMCP_HITL_LEVEL ?? file.hitl?.level ?? "off";
|
|
90
|
+
const hitlLevel = HITL_LEVELS.includes(hitlLevelRaw)
|
|
91
|
+
? hitlLevelRaw
|
|
92
|
+
: "off";
|
|
93
|
+
const hitlWhitelist = new Set(file.hitl?.whitelist ?? []);
|
|
94
|
+
const hitlTimeout = file.hitl?.timeout ?? 30;
|
|
95
|
+
const hitlSocketPath = join(home, ".config", "imcp", "hitl.sock");
|
|
96
|
+
const hitl = {
|
|
97
|
+
level: hitlLevel,
|
|
98
|
+
whitelist: hitlWhitelist,
|
|
99
|
+
timeout: hitlTimeout,
|
|
100
|
+
socketPath: hitlSocketPath,
|
|
101
|
+
};
|
|
2
102
|
return {
|
|
3
|
-
includeShared
|
|
103
|
+
includeShared,
|
|
104
|
+
disabledModules,
|
|
105
|
+
shareApprovalModules,
|
|
106
|
+
allowSendMessages,
|
|
107
|
+
allowSendMail,
|
|
108
|
+
hitl,
|
|
4
109
|
};
|
|
5
110
|
}
|
|
111
|
+
export function isModuleEnabled(config, moduleName) {
|
|
112
|
+
return !config.disabledModules.has(moduleName);
|
|
113
|
+
}
|
|
114
|
+
export function needsShareApproval(config, moduleName) {
|
|
115
|
+
return config.shareApprovalModules.has(moduleName);
|
|
116
|
+
}
|
|
6
117
|
//# sourceMappingURL=config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/shared/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/shared/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { ImcpConfig } from "./config.js";
|
|
3
|
+
import type { HitlClient } from "./hitl.js";
|
|
4
|
+
/**
|
|
5
|
+
* Monkey-patches server.registerTool so every subsequent registration
|
|
6
|
+
* goes through HITL approval when the policy requires it.
|
|
7
|
+
*/
|
|
8
|
+
export declare function installHitlGuard(server: McpServer, hitlClient: HitlClient, config: ImcpConfig): void;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { err } from "./result.js";
|
|
2
|
+
function shouldRequireApproval(level, annotations, whitelist, toolName) {
|
|
3
|
+
if (whitelist.has(toolName))
|
|
4
|
+
return false;
|
|
5
|
+
switch (level) {
|
|
6
|
+
case "off":
|
|
7
|
+
return false;
|
|
8
|
+
case "destructive-only":
|
|
9
|
+
return annotations.destructiveHint === true;
|
|
10
|
+
case "all-writes":
|
|
11
|
+
return annotations.readOnlyHint === false;
|
|
12
|
+
case "all":
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Monkey-patches server.registerTool so every subsequent registration
|
|
18
|
+
* goes through HITL approval when the policy requires it.
|
|
19
|
+
*/
|
|
20
|
+
export function installHitlGuard(server, hitlClient, config) {
|
|
21
|
+
const original = server.registerTool.bind(server);
|
|
22
|
+
const patched = (name, toolConfig, callback) => {
|
|
23
|
+
const annotations = toolConfig.annotations ?? {};
|
|
24
|
+
if (!shouldRequireApproval(config.hitl.level, annotations, config.hitl.whitelist, name)) {
|
|
25
|
+
return original(name, toolConfig, callback);
|
|
26
|
+
}
|
|
27
|
+
const wrapped = async (...args) => {
|
|
28
|
+
const toolArgs = (args[0] ?? {});
|
|
29
|
+
const approved = await hitlClient.requestApproval(name, toolArgs, annotations.destructiveHint ?? false, annotations.openWorldHint ?? false);
|
|
30
|
+
if (!approved) {
|
|
31
|
+
return err(`Action denied: "${name}" requires user approval. The user denied or did not respond in time.`);
|
|
32
|
+
}
|
|
33
|
+
return callback(...args);
|
|
34
|
+
};
|
|
35
|
+
return original(name, toolConfig, wrapped);
|
|
36
|
+
};
|
|
37
|
+
server.registerTool = patched;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=hitl-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hitl-guard.js","sourceRoot":"","sources":["../../src/shared/hitl-guard.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AASlC,SAAS,qBAAqB,CAC5B,KAAgB,EAChB,WAA4B,EAC5B,SAAsB,EACtB,QAAgB;IAEhB,IAAI,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1C,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,KAAK;YACR,OAAO,KAAK,CAAC;QACf,KAAK,kBAAkB;YACrB,OAAO,WAAW,CAAC,eAAe,KAAK,IAAI,CAAC;QAC9C,KAAK,YAAY;YACf,OAAO,WAAW,CAAC,YAAY,KAAK,KAAK,CAAC;QAC5C,KAAK,KAAK;YACR,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAiB,EACjB,UAAsB,EACtB,MAAkB;IAElB,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAElD,MAAM,OAAO,GAAG,CACd,IAAY,EACZ,UAAqE,EACrE,QAAyC,EACzC,EAAE;QACF,MAAM,WAAW,GAAoB,UAAU,CAAC,WAAW,IAAI,EAAE,CAAC;QAElE,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC;YACxF,OAAO,QAAQ,CAAC,IAAI,EAAE,UAA4C,EAAE,QAA0C,CAAC,CAAC;QAClH,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,EAAE,GAAG,IAAe,EAAE,EAAE;YAC3C,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAA4B,CAAC;YAC5D,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,eAAe,CAC/C,IAAI,EACJ,QAAQ,EACR,WAAW,CAAC,eAAe,IAAI,KAAK,EACpC,WAAW,CAAC,aAAa,IAAI,KAAK,CACnC,CAAC;YACF,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,GAAG,CACR,mBAAmB,IAAI,uEAAuE,CAC/F,CAAC;YACJ,CAAC;YACD,OAAQ,QAAyC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC7D,CAAC,CAAC;QAEF,OAAO,QAAQ,CAAC,IAAI,EAAE,UAA4C,EAAE,OAAyC,CAAC,CAAC;IACjH,CAAC,CAAC;IACF,MAAM,CAAC,YAAY,GAAG,OAAqC,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { HitlConfig } from "./config.js";
|
|
2
|
+
export declare class HitlClient {
|
|
3
|
+
private config;
|
|
4
|
+
private socket;
|
|
5
|
+
private pending;
|
|
6
|
+
private buffer;
|
|
7
|
+
private connecting;
|
|
8
|
+
private connectPromise;
|
|
9
|
+
constructor(config: HitlConfig);
|
|
10
|
+
requestApproval(tool: string, args: Record<string, unknown>, destructive: boolean, openWorld: boolean): Promise<boolean>;
|
|
11
|
+
private ensureConnected;
|
|
12
|
+
private connect;
|
|
13
|
+
private onData;
|
|
14
|
+
private denyAllPending;
|
|
15
|
+
dispose(): void;
|
|
16
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { createConnection } from "node:net";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
export class HitlClient {
|
|
4
|
+
config;
|
|
5
|
+
socket = null;
|
|
6
|
+
pending = new Map();
|
|
7
|
+
buffer = "";
|
|
8
|
+
connecting = false;
|
|
9
|
+
connectPromise = null;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
}
|
|
13
|
+
async requestApproval(tool, args, destructive, openWorld) {
|
|
14
|
+
try {
|
|
15
|
+
await this.ensureConnected();
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
console.error(`[hitl] socket unreachable at ${this.config.socketPath} — denying "${tool}"`);
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
const id = randomUUID();
|
|
22
|
+
const request = {
|
|
23
|
+
id,
|
|
24
|
+
type: "hitl_request",
|
|
25
|
+
tool,
|
|
26
|
+
args,
|
|
27
|
+
destructive,
|
|
28
|
+
openWorld,
|
|
29
|
+
};
|
|
30
|
+
return new Promise((resolve) => {
|
|
31
|
+
const timer = setTimeout(() => {
|
|
32
|
+
this.pending.delete(id);
|
|
33
|
+
console.error(`[hitl] timeout waiting for approval of "${tool}" — denying`);
|
|
34
|
+
resolve(false);
|
|
35
|
+
}, this.config.timeout * 1000);
|
|
36
|
+
this.pending.set(id, {
|
|
37
|
+
resolve: (approved) => {
|
|
38
|
+
clearTimeout(timer);
|
|
39
|
+
resolve(approved);
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
try {
|
|
43
|
+
this.socket.write(JSON.stringify(request) + "\n");
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
clearTimeout(timer);
|
|
47
|
+
this.pending.delete(id);
|
|
48
|
+
console.error(`[hitl] failed to send request for "${tool}" — denying`);
|
|
49
|
+
resolve(false);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
ensureConnected() {
|
|
54
|
+
if (this.socket && !this.socket.destroyed) {
|
|
55
|
+
return Promise.resolve();
|
|
56
|
+
}
|
|
57
|
+
if (this.connectPromise) {
|
|
58
|
+
return this.connectPromise;
|
|
59
|
+
}
|
|
60
|
+
this.connectPromise = this.connect();
|
|
61
|
+
return this.connectPromise;
|
|
62
|
+
}
|
|
63
|
+
connect() {
|
|
64
|
+
return new Promise((resolve, reject) => {
|
|
65
|
+
this.connecting = true;
|
|
66
|
+
const socket = createConnection({ path: this.config.socketPath }, () => {
|
|
67
|
+
this.socket = socket;
|
|
68
|
+
this.connecting = false;
|
|
69
|
+
this.connectPromise = null;
|
|
70
|
+
this.buffer = "";
|
|
71
|
+
resolve();
|
|
72
|
+
});
|
|
73
|
+
socket.setEncoding("utf-8");
|
|
74
|
+
socket.on("data", (chunk) => {
|
|
75
|
+
this.onData(chunk);
|
|
76
|
+
});
|
|
77
|
+
socket.on("error", (error) => {
|
|
78
|
+
if (this.connecting) {
|
|
79
|
+
this.connecting = false;
|
|
80
|
+
this.connectPromise = null;
|
|
81
|
+
reject(error);
|
|
82
|
+
}
|
|
83
|
+
this.denyAllPending("socket error");
|
|
84
|
+
});
|
|
85
|
+
socket.on("close", () => {
|
|
86
|
+
this.socket = null;
|
|
87
|
+
this.connectPromise = null;
|
|
88
|
+
this.denyAllPending("socket closed");
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
onData(chunk) {
|
|
93
|
+
this.buffer += chunk;
|
|
94
|
+
const lines = this.buffer.split("\n");
|
|
95
|
+
// Keep the last incomplete line in the buffer
|
|
96
|
+
this.buffer = lines.pop() ?? "";
|
|
97
|
+
for (const line of lines) {
|
|
98
|
+
const trimmed = line.trim();
|
|
99
|
+
if (!trimmed)
|
|
100
|
+
continue;
|
|
101
|
+
try {
|
|
102
|
+
const msg = JSON.parse(trimmed);
|
|
103
|
+
if (msg.type === "hitl_response" && msg.id) {
|
|
104
|
+
const entry = this.pending.get(msg.id);
|
|
105
|
+
if (entry) {
|
|
106
|
+
this.pending.delete(msg.id);
|
|
107
|
+
entry.resolve(msg.approved);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
console.error("[hitl] failed to parse response:", trimmed);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
denyAllPending(reason) {
|
|
117
|
+
for (const [id, entry] of this.pending) {
|
|
118
|
+
console.error(`[hitl] ${reason} — denying pending request ${id}`);
|
|
119
|
+
entry.resolve(false);
|
|
120
|
+
}
|
|
121
|
+
this.pending.clear();
|
|
122
|
+
}
|
|
123
|
+
dispose() {
|
|
124
|
+
if (this.socket) {
|
|
125
|
+
this.socket.destroy();
|
|
126
|
+
this.socket = null;
|
|
127
|
+
}
|
|
128
|
+
this.denyAllPending("dispose");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=hitl.js.map
|