@nylas/helix-mcp-server 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.d.ts +10 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +233 -0
- package/dist/cli.js.map +1 -0
- package/dist/html-to-markdown.d.ts +15 -0
- package/dist/html-to-markdown.d.ts.map +1 -0
- package/dist/html-to-markdown.js +234 -0
- package/dist/html-to-markdown.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +49 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +323 -0
- package/dist/server.js.map +1 -0
- package/dist/shape-response.d.ts +19 -0
- package/dist/shape-response.d.ts.map +1 -0
- package/dist/shape-response.js +172 -0
- package/dist/shape-response.js.map +1 -0
- package/dist/tools/calendar.d.ts +3 -0
- package/dist/tools/calendar.d.ts.map +1 -0
- package/dist/tools/calendar.js +46 -0
- package/dist/tools/calendar.js.map +1 -0
- package/dist/tools/contacts.d.ts +3 -0
- package/dist/tools/contacts.d.ts.map +1 -0
- package/dist/tools/contacts.js +23 -0
- package/dist/tools/contacts.js.map +1 -0
- package/dist/tools/email.d.ts +3 -0
- package/dist/tools/email.d.ts.map +1 -0
- package/dist/tools/email.js +54 -0
- package/dist/tools/email.js.map +1 -0
- package/dist/tools/identity.d.ts +3 -0
- package/dist/tools/identity.d.ts.map +1 -0
- package/dist/tools/identity.js +18 -0
- package/dist/tools/identity.js.map +1 -0
- package/dist/tools/types.d.ts +10 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/package.json +48 -0
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI for @nylas/helix-mcp-server.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* npx @nylas/helix-mcp-server --setup # Interactive setup: device code flow → registers Claude Code over HTTP
|
|
7
|
+
* npx @nylas/helix-mcp-server # Prints migration guidance for legacy stdio setups
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;GAMG"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI for @nylas/helix-mcp-server.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* npx @nylas/helix-mcp-server --setup # Interactive setup: device code flow → registers Claude Code over HTTP
|
|
7
|
+
* npx @nylas/helix-mcp-server # Prints migration guidance for legacy stdio setups
|
|
8
|
+
*/
|
|
9
|
+
import { execFile } from 'node:child_process';
|
|
10
|
+
const DEFAULT_HELIX_URL = 'https://helix.nylas.com';
|
|
11
|
+
const CONFIGURED_HELIX_URL = process.env.HELIX_URL || DEFAULT_HELIX_URL;
|
|
12
|
+
const HELIX_URL = normalizeHelixUrl(CONFIGURED_HELIX_URL);
|
|
13
|
+
async function main() {
|
|
14
|
+
const args = process.argv.slice(2);
|
|
15
|
+
if (args.includes('--setup')) {
|
|
16
|
+
await runSetup();
|
|
17
|
+
}
|
|
18
|
+
else if (args.includes('--uninstall')) {
|
|
19
|
+
await runUninstall();
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
console.error('[helix-mcp] Usage:');
|
|
23
|
+
console.error(' npx @nylas/helix-mcp-server --setup # Set up Helix MCP in Claude Code');
|
|
24
|
+
console.error(' npx @nylas/helix-mcp-server --uninstall # Remove Helix MCP from Claude Code');
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async function runSetup() {
|
|
29
|
+
console.log('');
|
|
30
|
+
console.log(' Helix MCP Server Setup');
|
|
31
|
+
console.log(' ──────────────────────');
|
|
32
|
+
console.log('');
|
|
33
|
+
if (HELIX_URL !== CONFIGURED_HELIX_URL) {
|
|
34
|
+
console.log(` Using ${HELIX_URL} for local auth so dashboard cookies work.`);
|
|
35
|
+
console.log('');
|
|
36
|
+
}
|
|
37
|
+
// Step 1: Register as an OAuth client via DCR
|
|
38
|
+
console.log(' Registering with Helix...');
|
|
39
|
+
let clientId = '';
|
|
40
|
+
try {
|
|
41
|
+
const registerRes = await fetch(`${HELIX_URL}/oauth/register`, {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
headers: { 'Content-Type': 'application/json' },
|
|
44
|
+
body: JSON.stringify({
|
|
45
|
+
client_name: 'Claude Code',
|
|
46
|
+
redirect_uris: ['urn:ietf:wg:oauth:2.0:oob'],
|
|
47
|
+
grant_types: ['urn:ietf:params:oauth:grant-type:device_code', 'refresh_token'],
|
|
48
|
+
response_types: ['code'],
|
|
49
|
+
token_endpoint_auth_method: 'none',
|
|
50
|
+
}),
|
|
51
|
+
});
|
|
52
|
+
if (!registerRes.ok) {
|
|
53
|
+
const err = await registerRes.text();
|
|
54
|
+
console.error(` Failed to register: ${err}`);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
const registration = await registerRes.json();
|
|
58
|
+
clientId = registration.client_id;
|
|
59
|
+
}
|
|
60
|
+
catch (e) {
|
|
61
|
+
console.error(` Could not reach ${HELIX_URL}. Is it running?`);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
// Step 2: Request device code
|
|
65
|
+
console.log(' Requesting device code...');
|
|
66
|
+
const scope = 'email.read email.send calendar.read calendar.write contacts.read identity.read';
|
|
67
|
+
const deviceRes = await fetch(`${HELIX_URL}/oauth/device/code`, {
|
|
68
|
+
method: 'POST',
|
|
69
|
+
headers: { 'Content-Type': 'application/json' },
|
|
70
|
+
body: JSON.stringify({ client_id: clientId, scope }),
|
|
71
|
+
});
|
|
72
|
+
if (!deviceRes.ok) {
|
|
73
|
+
const err = await deviceRes.text();
|
|
74
|
+
console.error(` Failed to get device code: ${err}`);
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
const device = await deviceRes.json();
|
|
78
|
+
// Step 3: Show code and open browser
|
|
79
|
+
console.log('');
|
|
80
|
+
console.log(` Your code: ${device.user_code}`);
|
|
81
|
+
console.log('');
|
|
82
|
+
console.log(` Opening ${device.verification_uri_complete}`);
|
|
83
|
+
console.log(' Paste the code above if prompted.');
|
|
84
|
+
console.log('');
|
|
85
|
+
openBrowser(device.verification_uri_complete);
|
|
86
|
+
// Step 4: Poll for approval
|
|
87
|
+
console.log(' Waiting for approval...');
|
|
88
|
+
const pollInterval = (device.interval || 5) * 1000;
|
|
89
|
+
const deadline = Date.now() + device.expires_in * 1000;
|
|
90
|
+
const tokens = await new Promise((resolve, reject) => {
|
|
91
|
+
const poll = async () => {
|
|
92
|
+
if (Date.now() > deadline) {
|
|
93
|
+
reject(new Error('Device code expired. Run setup again.'));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
const tokenRes = await fetch(`${HELIX_URL}/oauth/token`, {
|
|
98
|
+
method: 'POST',
|
|
99
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
100
|
+
body: new URLSearchParams({
|
|
101
|
+
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
|
|
102
|
+
device_code: device.device_code,
|
|
103
|
+
client_id: clientId,
|
|
104
|
+
}),
|
|
105
|
+
});
|
|
106
|
+
if (tokenRes.ok) {
|
|
107
|
+
resolve(await tokenRes.json());
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const err = await tokenRes.json();
|
|
111
|
+
if (err.error === 'authorization_pending') {
|
|
112
|
+
setTimeout(poll, pollInterval);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (err.error === 'slow_down') {
|
|
116
|
+
setTimeout(poll, pollInterval * 2);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
reject(new Error(`Authorization failed: ${err.error}`));
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
reject(e);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
setTimeout(poll, pollInterval);
|
|
126
|
+
});
|
|
127
|
+
// Step 5: Register Claude Code MCP config
|
|
128
|
+
console.log(' Writing Claude Code config...');
|
|
129
|
+
const mcpEndpoint = buildMcpEndpoint(HELIX_URL);
|
|
130
|
+
const manualCommand = buildClaudeCodeRegistrationCommand(mcpEndpoint, tokens.access_token);
|
|
131
|
+
const registeredWithClaudeCli = await registerWithClaudeCli(mcpEndpoint, tokens.access_token);
|
|
132
|
+
console.log('');
|
|
133
|
+
console.log(' Done. Helix is now available in Claude Code.');
|
|
134
|
+
console.log('');
|
|
135
|
+
if (registeredWithClaudeCli) {
|
|
136
|
+
console.log(' Registered via: claude mcp add --transport http -s user helix ...');
|
|
137
|
+
console.log(' Verify with: claude mcp get helix');
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
console.log(' Automatic Claude CLI registration failed.');
|
|
141
|
+
console.log(' Run this command manually:');
|
|
142
|
+
console.log(` ${manualCommand}`);
|
|
143
|
+
}
|
|
144
|
+
console.log(' Restart Claude Code to activate.');
|
|
145
|
+
console.log('');
|
|
146
|
+
}
|
|
147
|
+
async function runUninstall() {
|
|
148
|
+
console.log('');
|
|
149
|
+
console.log(' Helix MCP Server Uninstall');
|
|
150
|
+
console.log(' ──────────────────────────');
|
|
151
|
+
console.log('');
|
|
152
|
+
try {
|
|
153
|
+
await execFileAsync('claude', ['mcp', 'remove', 'helix', '-s', 'user']);
|
|
154
|
+
console.log(' Removed helix MCP server from Claude Code.');
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
console.log(' helix MCP server was not registered in Claude Code.');
|
|
158
|
+
}
|
|
159
|
+
console.log('');
|
|
160
|
+
console.log(' Done. Restart Claude Code to apply.');
|
|
161
|
+
console.log('');
|
|
162
|
+
}
|
|
163
|
+
function openBrowser(url) {
|
|
164
|
+
const cmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'cmd' : 'xdg-open';
|
|
165
|
+
const args = process.platform === 'win32' ? ['/c', 'start', url] : [url];
|
|
166
|
+
execFile(cmd, args, (err) => {
|
|
167
|
+
if (err) {
|
|
168
|
+
console.log(` Open this URL in your browser:`);
|
|
169
|
+
console.log(` ${url}`);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
function buildMcpEndpoint(helixUrl) {
|
|
174
|
+
return `${helixUrl.replace(/\/+$/, '')}/mcp`;
|
|
175
|
+
}
|
|
176
|
+
function buildClaudeCodeRegistrationCommand(mcpEndpoint, accessToken) {
|
|
177
|
+
return `claude mcp add --transport http -s user helix ${mcpEndpoint} --header 'Authorization: Bearer ${accessToken}'`;
|
|
178
|
+
}
|
|
179
|
+
async function registerWithClaudeCli(mcpEndpoint, accessToken) {
|
|
180
|
+
try {
|
|
181
|
+
await execFileAsync('claude', ['mcp', 'remove', 'helix', '-s', 'user']);
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
// Ignore; the server may not exist yet.
|
|
185
|
+
}
|
|
186
|
+
try {
|
|
187
|
+
await execFileAsync('claude', [
|
|
188
|
+
'mcp',
|
|
189
|
+
'add',
|
|
190
|
+
'--transport',
|
|
191
|
+
'http',
|
|
192
|
+
'-s',
|
|
193
|
+
'user',
|
|
194
|
+
'helix',
|
|
195
|
+
mcpEndpoint,
|
|
196
|
+
'--header',
|
|
197
|
+
`Authorization: Bearer ${accessToken}`,
|
|
198
|
+
]);
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function execFileAsync(command, args) {
|
|
206
|
+
return new Promise((resolve, reject) => {
|
|
207
|
+
execFile(command, args, (err) => {
|
|
208
|
+
if (err) {
|
|
209
|
+
reject(err);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
resolve();
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
function normalizeHelixUrl(url) {
|
|
217
|
+
try {
|
|
218
|
+
const parsed = new URL(url);
|
|
219
|
+
if (parsed.hostname === '127.0.0.1' || parsed.hostname === '[::1]' || parsed.hostname === '::1') {
|
|
220
|
+
parsed.hostname = 'localhost';
|
|
221
|
+
return parsed.toString().replace(/\/$/, '');
|
|
222
|
+
}
|
|
223
|
+
return parsed.toString().replace(/\/$/, '');
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
return url.replace(/\/$/, '');
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
main().catch((err) => {
|
|
230
|
+
console.error(err);
|
|
231
|
+
process.exit(1);
|
|
232
|
+
});
|
|
233
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight HTML email → Markdown converter.
|
|
3
|
+
*
|
|
4
|
+
* Applies the same heuristic philosophy as the web reader engine
|
|
5
|
+
* (noise detection, boilerplate/tracker stripping, signature detection)
|
|
6
|
+
* but works without a DOM parser so it runs in Node, Deno, and Workers.
|
|
7
|
+
*
|
|
8
|
+
* Designed for email HTML — not arbitrary web pages.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Convert an HTML email body to clean Markdown.
|
|
12
|
+
* Returns the original string if it doesn't look like HTML.
|
|
13
|
+
*/
|
|
14
|
+
export declare function htmlToMarkdown(html: string): string;
|
|
15
|
+
//# sourceMappingURL=html-to-markdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-to-markdown.d.ts","sourceRoot":"","sources":["../src/html-to-markdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAyCH;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAmJnD"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight HTML email → Markdown converter.
|
|
3
|
+
*
|
|
4
|
+
* Applies the same heuristic philosophy as the web reader engine
|
|
5
|
+
* (noise detection, boilerplate/tracker stripping, signature detection)
|
|
6
|
+
* but works without a DOM parser so it runs in Node, Deno, and Workers.
|
|
7
|
+
*
|
|
8
|
+
* Designed for email HTML — not arbitrary web pages.
|
|
9
|
+
*/
|
|
10
|
+
// ── Patterns ────────────────────────────────────────────────
|
|
11
|
+
const BLOCK_TAGS = new Set([
|
|
12
|
+
'p', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
|
|
13
|
+
'li', 'tr', 'td', 'th', 'blockquote', 'pre',
|
|
14
|
+
'ul', 'ol', 'table', 'hr', 'br', 'dt', 'dd',
|
|
15
|
+
'section', 'article', 'header', 'footer', 'main', 'aside', 'nav',
|
|
16
|
+
]);
|
|
17
|
+
const STRIP_TAGS = new Set([
|
|
18
|
+
'script', 'style', 'noscript', 'iframe', 'object', 'embed',
|
|
19
|
+
'svg', 'canvas', 'form', 'input', 'button', 'select', 'textarea',
|
|
20
|
+
'head', 'meta', 'link', 'template',
|
|
21
|
+
]);
|
|
22
|
+
const BOILERPLATE_PATTERN = /unsubscribe|email.preferences|opt.?out|manage.*subscription|privacy.?policy|view.in.browser|view.this.email|trouble.viewing|add.us.to.your|no.longer.wish|mailing.list|this.email.was.sent|^\s*sent.from.my/i;
|
|
23
|
+
const TRACKER_HOST_PATTERN = /hubspotlinks\.com|hs-analytics\.net|mandrillapp\.com|mailchi\.mp|list-manage\.com|sendgrid\.net|mailgun\.(org|us)|\.click\.|\.trk\./i;
|
|
24
|
+
const SIGNATURE_PATTERN = /^(\-\-\s*$|regards,|best,|thanks,|cheers,|sincerely,|kind regards|sent from my|get outlook)/im;
|
|
25
|
+
const QUOTED_REPLY_PATTERN = /^(on\s.+\swrote:$|from:\s|sent:\s|_{5,}|>{1,}\s)/im;
|
|
26
|
+
/** Entity map for the most common HTML entities */
|
|
27
|
+
const ENTITY_MAP = {
|
|
28
|
+
'&': '&', '<': '<', '>': '>', '"': '"',
|
|
29
|
+
''': "'", ''': "'", ' ': ' ', '—': '—',
|
|
30
|
+
'–': '–', '«': '«', '»': '»', '…': '…',
|
|
31
|
+
'•': '•', '·': '·', '©': '©', '®': '®',
|
|
32
|
+
'™': '™', '’': '\u2019', '‘': '\u2018',
|
|
33
|
+
'”': '\u201D', '“': '\u201C',
|
|
34
|
+
};
|
|
35
|
+
// ── Core converter ──────────────────────────────────────────
|
|
36
|
+
/**
|
|
37
|
+
* Convert an HTML email body to clean Markdown.
|
|
38
|
+
* Returns the original string if it doesn't look like HTML.
|
|
39
|
+
*/
|
|
40
|
+
export function htmlToMarkdown(html) {
|
|
41
|
+
const source = html.trim();
|
|
42
|
+
if (!source)
|
|
43
|
+
return '';
|
|
44
|
+
if (!looksLikeHtml(source))
|
|
45
|
+
return normalizeWhitespace(source);
|
|
46
|
+
let work = source;
|
|
47
|
+
// 1. Strip invisible / dangerous tags (with their content)
|
|
48
|
+
for (const tag of STRIP_TAGS) {
|
|
49
|
+
work = work.replace(new RegExp(`<${tag}[^>]*>[\\s\\S]*?<\\/${tag}>`, 'gi'), '');
|
|
50
|
+
}
|
|
51
|
+
// 2. Strip HTML comments
|
|
52
|
+
work = work.replace(/<!--[\s\S]*?-->/g, '');
|
|
53
|
+
// 3. Convert block-level structure to markdown before stripping tags
|
|
54
|
+
// Headings
|
|
55
|
+
work = work.replace(/<h([1-6])[^>]*>([\s\S]*?)<\/h\1>/gi, (_m, level, content) => {
|
|
56
|
+
const text = stripTags(content).trim();
|
|
57
|
+
if (!text)
|
|
58
|
+
return '';
|
|
59
|
+
return `\n${'#'.repeat(Number(level))} ${text}\n`;
|
|
60
|
+
});
|
|
61
|
+
// Blockquotes
|
|
62
|
+
work = work.replace(/<blockquote[^>]*>([\s\S]*?)<\/blockquote>/gi, (_m, content) => {
|
|
63
|
+
const text = stripTags(content).trim();
|
|
64
|
+
if (!text)
|
|
65
|
+
return '';
|
|
66
|
+
return `\n${text.split('\n').map((line) => `> ${line}`).join('\n')}\n`;
|
|
67
|
+
});
|
|
68
|
+
// Preformatted
|
|
69
|
+
work = work.replace(/<pre[^>]*>([\s\S]*?)<\/pre>/gi, (_m, content) => {
|
|
70
|
+
const text = decodeEntities(content.replace(/<br\s*\/?>/gi, '\n').replace(/<[^>]+>/g, ''));
|
|
71
|
+
return `\n\`\`\`\n${text}\n\`\`\`\n`;
|
|
72
|
+
});
|
|
73
|
+
// Code (inline)
|
|
74
|
+
work = work.replace(/<code[^>]*>([\s\S]*?)<\/code>/gi, (_m, content) => {
|
|
75
|
+
const text = stripTags(content).trim();
|
|
76
|
+
return text ? `\`${text}\`` : '';
|
|
77
|
+
});
|
|
78
|
+
// Lists — ordered
|
|
79
|
+
work = work.replace(/<ol[^>]*>([\s\S]*?)<\/ol>/gi, (_m, content) => {
|
|
80
|
+
let idx = 0;
|
|
81
|
+
return `\n${content.replace(/<li[^>]*>([\s\S]*?)<\/li>/gi, (_lm, li) => {
|
|
82
|
+
idx++;
|
|
83
|
+
return `${idx}. ${stripTags(li).trim()}\n`;
|
|
84
|
+
})}`;
|
|
85
|
+
});
|
|
86
|
+
// Lists — unordered
|
|
87
|
+
work = work.replace(/<ul[^>]*>([\s\S]*?)<\/ul>/gi, (_m, content) => {
|
|
88
|
+
return `\n${content.replace(/<li[^>]*>([\s\S]*?)<\/li>/gi, (_lm, li) => {
|
|
89
|
+
return `- ${stripTags(li).trim()}\n`;
|
|
90
|
+
})}`;
|
|
91
|
+
});
|
|
92
|
+
// Table rows → pipe-separated (simple)
|
|
93
|
+
work = work.replace(/<table[^>]*>([\s\S]*?)<\/table>/gi, (_m, content) => {
|
|
94
|
+
const rows = [];
|
|
95
|
+
const rowPattern = /<tr[^>]*>([\s\S]*?)<\/tr>/gi;
|
|
96
|
+
let rowMatch;
|
|
97
|
+
while ((rowMatch = rowPattern.exec(content)) !== null) {
|
|
98
|
+
const cells = [];
|
|
99
|
+
const cellPattern = /<(?:td|th)[^>]*>([\s\S]*?)<\/(?:td|th)>/gi;
|
|
100
|
+
let cellMatch;
|
|
101
|
+
const rowContent = rowMatch[1] ?? '';
|
|
102
|
+
while ((cellMatch = cellPattern.exec(rowContent)) !== null) {
|
|
103
|
+
cells.push(stripTags(cellMatch[1] ?? '').trim());
|
|
104
|
+
}
|
|
105
|
+
if (cells.length > 0 && cells.some(c => c.length > 0)) {
|
|
106
|
+
rows.push(`| ${cells.join(' | ')} |`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (rows.length === 0)
|
|
110
|
+
return '';
|
|
111
|
+
const firstRow = rows[0];
|
|
112
|
+
// Add separator after first row (treat as header)
|
|
113
|
+
const sep = `| ${firstRow.split('|').slice(1, -1).map(() => '---').join(' | ')} |`;
|
|
114
|
+
return `\n${firstRow}\n${sep}\n${rows.slice(1).join('\n')}\n`;
|
|
115
|
+
});
|
|
116
|
+
// Horizontal rules
|
|
117
|
+
work = work.replace(/<hr[^>]*\/?>/gi, '\n---\n');
|
|
118
|
+
// Line breaks
|
|
119
|
+
work = work.replace(/<br\s*\/?>/gi, '\n');
|
|
120
|
+
// Bold / strong
|
|
121
|
+
work = work.replace(/<(?:strong|b)[^>]*>([\s\S]*?)<\/(?:strong|b)>/gi, (_m, c) => {
|
|
122
|
+
const t = stripTags(c).trim();
|
|
123
|
+
return t ? `**${t}**` : '';
|
|
124
|
+
});
|
|
125
|
+
// Italic / emphasis
|
|
126
|
+
work = work.replace(/<(?:em|i)[^>]*>([\s\S]*?)<\/(?:em|i)>/gi, (_m, c) => {
|
|
127
|
+
const t = stripTags(c).trim();
|
|
128
|
+
return t ? `*${t}*` : '';
|
|
129
|
+
});
|
|
130
|
+
// Strikethrough
|
|
131
|
+
work = work.replace(/<(?:del|s|strike)[^>]*>([\s\S]*?)<\/(?:del|s|strike)>/gi, (_m, c) => {
|
|
132
|
+
const t = stripTags(c).trim();
|
|
133
|
+
return t ? `~~${t}~~` : '';
|
|
134
|
+
});
|
|
135
|
+
// Links — preserve href as markdown link
|
|
136
|
+
work = work.replace(/<a[^>]*href=["']([^"']*)["'][^>]*>([\s\S]*?)<\/a>/gi, (_m, href, content) => {
|
|
137
|
+
const text = stripTags(content).trim();
|
|
138
|
+
const cleanHref = decodeEntities(href.trim());
|
|
139
|
+
if (!text)
|
|
140
|
+
return '';
|
|
141
|
+
if (!cleanHref || cleanHref.startsWith('javascript:') || cleanHref.startsWith('data:'))
|
|
142
|
+
return text;
|
|
143
|
+
// Skip tracker URLs — just show the link text
|
|
144
|
+
if (TRACKER_HOST_PATTERN.test(cleanHref))
|
|
145
|
+
return text;
|
|
146
|
+
// If text is just the URL, use bare URL
|
|
147
|
+
if (text === cleanHref || text === cleanHref.replace(/^https?:\/\//, ''))
|
|
148
|
+
return cleanHref;
|
|
149
|
+
return `[${text}](${cleanHref})`;
|
|
150
|
+
});
|
|
151
|
+
// Images — alt text only (email images are usually decorative)
|
|
152
|
+
work = work.replace(/<img[^>]*alt=["']([^"']+)["'][^>]*\/?>/gi, (_m, alt) => {
|
|
153
|
+
const text = alt.trim();
|
|
154
|
+
return text && text.length > 2 ? `[${text}]` : '';
|
|
155
|
+
});
|
|
156
|
+
// Remove remaining images without useful alt
|
|
157
|
+
work = work.replace(/<img[^>]*\/?>/gi, '');
|
|
158
|
+
// 4. Insert paragraph breaks for remaining block tags
|
|
159
|
+
for (const tag of BLOCK_TAGS) {
|
|
160
|
+
work = work.replace(new RegExp(`<${tag}[^>]*>`, 'gi'), '\n');
|
|
161
|
+
work = work.replace(new RegExp(`</${tag}>`, 'gi'), '\n');
|
|
162
|
+
}
|
|
163
|
+
// 5. Strip any remaining HTML tags
|
|
164
|
+
work = stripTags(work);
|
|
165
|
+
// 6. Decode entities
|
|
166
|
+
work = decodeEntities(work);
|
|
167
|
+
// 7. Normalize whitespace
|
|
168
|
+
work = normalizeWhitespace(work);
|
|
169
|
+
// 8. Apply heuristics — strip boilerplate, signatures, quoted replies
|
|
170
|
+
work = applyEmailHeuristics(work);
|
|
171
|
+
return work.trim();
|
|
172
|
+
}
|
|
173
|
+
// ── Heuristics ──────────────────────────────────────────────
|
|
174
|
+
function applyEmailHeuristics(text) {
|
|
175
|
+
const lines = text.split('\n');
|
|
176
|
+
const output = [];
|
|
177
|
+
let hitSignature = false;
|
|
178
|
+
let hitQuotedReply = false;
|
|
179
|
+
for (const line of lines) {
|
|
180
|
+
// Stop at signature boundary
|
|
181
|
+
if (!hitSignature && SIGNATURE_PATTERN.test(line)) {
|
|
182
|
+
// Keep the closing line itself (e.g., "Best, Alex") but stop after
|
|
183
|
+
if (/^(regards,|best,|thanks,|cheers,|sincerely,|kind regards)/i.test(line.trim())) {
|
|
184
|
+
output.push(line);
|
|
185
|
+
}
|
|
186
|
+
hitSignature = true;
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
if (hitSignature)
|
|
190
|
+
continue;
|
|
191
|
+
// Stop at quoted reply boundary
|
|
192
|
+
if (!hitQuotedReply && QUOTED_REPLY_PATTERN.test(line)) {
|
|
193
|
+
hitQuotedReply = true;
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (hitQuotedReply)
|
|
197
|
+
continue;
|
|
198
|
+
// Skip boilerplate lines
|
|
199
|
+
if (BOILERPLATE_PATTERN.test(line) && line.trim().length < 400)
|
|
200
|
+
continue;
|
|
201
|
+
output.push(line);
|
|
202
|
+
}
|
|
203
|
+
return output.join('\n');
|
|
204
|
+
}
|
|
205
|
+
// ── Helpers ─────────────────────────────────────────────────
|
|
206
|
+
function looksLikeHtml(source) {
|
|
207
|
+
return /<[a-z][\s\S]*?>/i.test(source.slice(0, 1000));
|
|
208
|
+
}
|
|
209
|
+
function stripTags(html) {
|
|
210
|
+
return decodeEntities(html.replace(/<[^>]+>/g, ''));
|
|
211
|
+
}
|
|
212
|
+
function decodeEntities(text) {
|
|
213
|
+
let result = text;
|
|
214
|
+
for (const [entity, char] of Object.entries(ENTITY_MAP)) {
|
|
215
|
+
result = result.split(entity).join(char);
|
|
216
|
+
}
|
|
217
|
+
// Numeric entities
|
|
218
|
+
result = result.replace(/&#x([0-9a-f]+);/gi, (_m, hex) => String.fromCodePoint(Number.parseInt(hex, 16)));
|
|
219
|
+
result = result.replace(/&#(\d+);/g, (_m, dec) => String.fromCodePoint(Number(dec)));
|
|
220
|
+
return result;
|
|
221
|
+
}
|
|
222
|
+
function normalizeWhitespace(text) {
|
|
223
|
+
return text
|
|
224
|
+
// Collapse runs of spaces/tabs (not newlines)
|
|
225
|
+
.replace(/[^\S\n]+/g, ' ')
|
|
226
|
+
// Collapse 3+ consecutive newlines to 2
|
|
227
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
228
|
+
// Trim leading/trailing whitespace per line
|
|
229
|
+
.split('\n')
|
|
230
|
+
.map((line) => line.trim())
|
|
231
|
+
.join('\n')
|
|
232
|
+
.trim();
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=html-to-markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-to-markdown.js","sourceRoot":"","sources":["../src/html-to-markdown.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { createMcpServer, type McpContext } from './server.js';
|
|
2
|
+
export { emailTools } from './tools/email.js';
|
|
3
|
+
export { calendarTools } from './tools/calendar.js';
|
|
4
|
+
export { contactsTools } from './tools/contacts.js';
|
|
5
|
+
export { identityTools } from './tools/identity.js';
|
|
6
|
+
export type { ToolDefinition, ToolCategory } from './tools/types.js';
|
|
7
|
+
export type { ResponseDetail, BodyFormat } from './shape-response.js';
|
|
8
|
+
export { htmlToMarkdown } from './html-to-markdown.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACpE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { createMcpServer } from './server.js';
|
|
2
|
+
export { emailTools } from './tools/email.js';
|
|
3
|
+
export { calendarTools } from './tools/calendar.js';
|
|
4
|
+
export { contactsTools } from './tools/contacts.js';
|
|
5
|
+
export { identityTools } from './tools/identity.js';
|
|
6
|
+
export { htmlToMarkdown } from './html-to-markdown.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAmB,MAAM,aAAa,CAAA;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAGnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { ToolCategory } from './tools/types.js';
|
|
3
|
+
import { type ResponseDetail, type BodyFormat } from './shape-response.js';
|
|
4
|
+
export interface NylasApiClient {
|
|
5
|
+
fetch(path: string, init?: RequestInit): Promise<Response>;
|
|
6
|
+
}
|
|
7
|
+
export interface McpContext {
|
|
8
|
+
userId: string;
|
|
9
|
+
grantId: string;
|
|
10
|
+
scopes: string[];
|
|
11
|
+
nylasApiUrl: string;
|
|
12
|
+
nylasApiKey: string;
|
|
13
|
+
/** Resolve the best grant for a capability (falls back from primary to any capable grant). */
|
|
14
|
+
resolveGrantId?: (capability: string) => Promise<string>;
|
|
15
|
+
/** Check whether an action requires approval. Returns approved=false if pending. */
|
|
16
|
+
checkApproval?: (actionType: string, payload: unknown, summary: string) => Promise<{
|
|
17
|
+
approved: boolean;
|
|
18
|
+
pendingActionId?: string;
|
|
19
|
+
}>;
|
|
20
|
+
/** Log an action to the audit trail. */
|
|
21
|
+
logAction?: (actionType: string, source: string, summary: string, status: 'success' | 'error' | 'pending_approval') => Promise<void>;
|
|
22
|
+
/** Log any tool call (reads + writes) to the audit trail. */
|
|
23
|
+
logToolCall?: (toolName: string, args: Record<string, unknown>, durationMs: number) => Promise<void>;
|
|
24
|
+
/** Identity data for context-aware responses. */
|
|
25
|
+
identity?: {
|
|
26
|
+
displayName: string;
|
|
27
|
+
tone: string;
|
|
28
|
+
verbosity: string;
|
|
29
|
+
customInstructions: string | null;
|
|
30
|
+
approvalPolicy: string;
|
|
31
|
+
capabilities: string[];
|
|
32
|
+
templateId: string | null;
|
|
33
|
+
};
|
|
34
|
+
/** Token optimization settings. */
|
|
35
|
+
tokenOptimization?: {
|
|
36
|
+
responseDetail: ResponseDetail;
|
|
37
|
+
enabledTools: ToolCategory[];
|
|
38
|
+
maxBodyLength?: number;
|
|
39
|
+
/** Format for email body content: 'html' (raw), 'text' (stripped), 'markdown' (heuristic conversion). Default: 'text'. */
|
|
40
|
+
bodyFormat?: BodyFormat;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Create an MCP server with AI identity tools registered.
|
|
45
|
+
* The server is stateless — context is provided per-request via the API client.
|
|
46
|
+
* Tools are filtered by enabledTools and responses shaped by responseDetail.
|
|
47
|
+
*/
|
|
48
|
+
export declare function createMcpServer(getContext: () => Promise<McpContext>): McpServer;
|
|
49
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAKnE,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACpE,OAAO,EAAqB,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAE7F,MAAM,WAAW,cAAc;IAC9B,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CAC1D;AAED,MAAM,WAAW,UAAU;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,8FAA8F;IAC9F,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACxD,oFAAoF;IACpF,aAAa,CAAC,EAAE,CACf,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,KACX,OAAO,CAAC;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC7D,wCAAwC;IACxC,SAAS,CAAC,EAAE,CACX,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,kBAAkB,KAC5C,OAAO,CAAC,IAAI,CAAC,CAAA;IAClB,6DAA6D;IAC7D,WAAW,CAAC,EAAE,CACb,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,UAAU,EAAE,MAAM,KACd,OAAO,CAAC,IAAI,CAAC,CAAA;IAClB,iDAAiD;IACjD,QAAQ,CAAC,EAAE;QACV,WAAW,EAAE,MAAM,CAAA;QACnB,IAAI,EAAE,MAAM,CAAA;QACZ,SAAS,EAAE,MAAM,CAAA;QACjB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAA;QACjC,cAAc,EAAE,MAAM,CAAA;QACtB,YAAY,EAAE,MAAM,EAAE,CAAA;QACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;KACzB,CAAA;IACD,mCAAmC;IACnC,iBAAiB,CAAC,EAAE;QACnB,cAAc,EAAE,cAAc,CAAA;QAC9B,YAAY,EAAE,YAAY,EAAE,CAAA;QAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,0HAA0H;QAC1H,UAAU,CAAC,EAAE,UAAU,CAAA;KACvB,CAAA;CACD;AAQD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,aA8GpE"}
|