linkedin-toolkit-mcp 2.0.2 → 2.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/setup.js ADDED
@@ -0,0 +1,584 @@
1
+ /**
2
+ * `lit setup` — everything between "I found this repo" and "my agent can use
3
+ * it", minus the three clicks Chrome will not let anybody automate.
4
+ *
5
+ * The old path was: find the Releases page, download a zip, unzip it somewhere
6
+ * you will not delete, turn on Developer mode, Load unpacked, run a server,
7
+ * find the pairing token, paste it, then hand-write a JSON config block for
8
+ * whichever agent you use. Seven steps, six of which a computer can do.
9
+ *
10
+ * This module does the six. Everything here is a small function with its
11
+ * dependencies passed in — `fetch`, the filesystem, the clock, the
12
+ * environment — so the whole flow is testable without a network, a Chrome, or
13
+ * a home directory.
14
+ *
15
+ * What it deliberately does not do:
16
+ * - claim Chrome opened a page it may have ignored (see `chromeLaunch`);
17
+ * - write a client config file it cannot parse (a malformed file is refused,
18
+ * never rewritten);
19
+ * - install anything outside `~/.linkedin-toolkit` unless asked.
20
+ */
21
+ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync, copyFileSync, } from 'node:fs';
22
+ import { homedir } from 'node:os';
23
+ import { dirname, join, resolve } from 'node:path';
24
+ import { fileURLToPath } from 'node:url';
25
+ import { inflateRawSync } from 'node:zlib';
26
+ export const REPO = 'OpenRecruiterTools/linkedin-toolkit';
27
+ export const RELEASES_URL = `https://github.com/${REPO}/releases`;
28
+ /** A setup step that failed for a reason the user can act on. */
29
+ export class SetupError extends Error {
30
+ howToFix;
31
+ constructor(message, howToFix) {
32
+ super(message);
33
+ this.howToFix = howToFix;
34
+ this.name = 'SetupError';
35
+ }
36
+ }
37
+ export const realFs = {
38
+ existsSync,
39
+ mkdirSync,
40
+ readFileSync,
41
+ readdirSync,
42
+ renameSync,
43
+ rmSync,
44
+ writeFileSync,
45
+ copyFileSync,
46
+ };
47
+ /* ------------------------------------------------------------------ *
48
+ * Which zip, and where from
49
+ * ------------------------------------------------------------------ */
50
+ /**
51
+ * The release asset for one version.
52
+ *
53
+ * The release workflow names the zip from the tag, so `linkedin-toolkit-mcp`
54
+ * 2.1.0 and `linkedin-toolkit-extension-v2.1.0.zip` are the same release by
55
+ * construction. A version the user passed by hand may carry a leading `v`.
56
+ */
57
+ export function extensionZipUrl(version) {
58
+ const bare = String(version).trim().replace(/^v/, '');
59
+ if (!/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(bare)) {
60
+ throw new SetupError(`"${version}" is not a version. Pass one like 2.1.0, or leave --version off to use the installed one.`);
61
+ }
62
+ return `${RELEASES_URL}/download/v${bare}/linkedin-toolkit-extension-v${bare}.zip`;
63
+ }
64
+ /** The API read that answers "what is the newest release, and what is in it?" */
65
+ export function latestReleaseApiUrl() {
66
+ return `https://api.github.com/repos/${REPO}/releases/latest`;
67
+ }
68
+ const ASSET = /^linkedin-toolkit-extension-v(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)\.zip$/;
69
+ /**
70
+ * Resolve the newest release's extension asset.
71
+ *
72
+ * `releases/latest/download/<name>` cannot be used directly because the asset
73
+ * name carries the version, which is the thing we do not know — so the release
74
+ * is read through the API and its asset list is matched.
75
+ */
76
+ export async function resolveLatestRelease(fetchImpl) {
77
+ let response;
78
+ try {
79
+ response = await fetchImpl(latestReleaseApiUrl(), {
80
+ headers: { accept: 'application/vnd.github+json' },
81
+ });
82
+ }
83
+ catch (err) {
84
+ throw new SetupError(`Could not reach GitHub to find the latest release: ${err instanceof Error ? err.message : String(err)}`, `Download the zip by hand from ${RELEASES_URL} and point Chrome at the unzipped folder.`);
85
+ }
86
+ if (!response.ok) {
87
+ throw new SetupError(`GitHub answered ${response.status} for the latest release.`, `Download the zip by hand from ${RELEASES_URL}.`);
88
+ }
89
+ const body = (await response.json().catch(() => null));
90
+ const assets = Array.isArray(body?.assets) ? body.assets : [];
91
+ for (const asset of assets) {
92
+ const match = ASSET.exec(String(asset?.name ?? ''));
93
+ if (match && typeof asset?.browser_download_url === 'string') {
94
+ return { url: asset.browser_download_url, version: match[1], source: 'latest' };
95
+ }
96
+ }
97
+ throw new SetupError('The latest release carries no linkedin-toolkit-extension zip.', `Look at ${RELEASES_URL} and download whichever asset is there.`);
98
+ }
99
+ /**
100
+ * Download the extension zip for `version`, falling back to the latest release.
101
+ *
102
+ * The fallback is the normal case on a fork, on a pre-release npm install, or
103
+ * any time the npm package is published slightly ahead of the GitHub release —
104
+ * and it is reported, because installing a different version than you asked
105
+ * for should never be silent.
106
+ */
107
+ export async function downloadExtension(options) {
108
+ const fetchImpl = options.fetchImpl ?? fetch;
109
+ const wanted = {
110
+ url: extensionZipUrl(options.version),
111
+ version: options.version.replace(/^v/, ''),
112
+ source: 'version',
113
+ };
114
+ let chosen = wanted;
115
+ let response = null;
116
+ try {
117
+ response = await fetchImpl(wanted.url, { redirect: 'follow' });
118
+ }
119
+ catch {
120
+ response = null;
121
+ }
122
+ if (!response || !response.ok) {
123
+ chosen = await resolveLatestRelease(fetchImpl);
124
+ try {
125
+ response = await fetchImpl(chosen.url, { redirect: 'follow' });
126
+ }
127
+ catch (err) {
128
+ throw new SetupError(`Could not download ${chosen.url}: ${err instanceof Error ? err.message : String(err)}`, `Download it by hand from ${RELEASES_URL}.`);
129
+ }
130
+ if (!response.ok) {
131
+ throw new SetupError(`GitHub answered ${response.status} for ${chosen.url}.`, `Download it by hand from ${RELEASES_URL}.`);
132
+ }
133
+ }
134
+ const buffer = Buffer.from(await response.arrayBuffer());
135
+ return { ...chosen, buffer };
136
+ }
137
+ /* ------------------------------------------------------------------ *
138
+ * Reading the zip
139
+ *
140
+ * A dependency-free reader, because the only zip it ever opens is one this
141
+ * repo built, and because unpacking an archive from the internet is exactly
142
+ * the place to control entry names rather than trust a library's defaults.
143
+ * ------------------------------------------------------------------ */
144
+ const EOCD_SIGNATURE = 0x06054b50;
145
+ const CENTRAL_SIGNATURE = 0x02014b50;
146
+ const LOCAL_SIGNATURE = 0x04034b50;
147
+ /** Every file in the archive, decompressed. Directory entries are dropped. */
148
+ export function readZip(buffer) {
149
+ if (buffer.length < 22)
150
+ throw new SetupError('That download is too small to be a zip file.');
151
+ let eocd = -1;
152
+ const from = Math.max(0, buffer.length - 66_000);
153
+ for (let i = buffer.length - 22; i >= from; i--) {
154
+ if (buffer.readUInt32LE(i) === EOCD_SIGNATURE) {
155
+ eocd = i;
156
+ break;
157
+ }
158
+ }
159
+ if (eocd === -1)
160
+ throw new SetupError('That file is not a zip archive (no end-of-archive record).');
161
+ const count = buffer.readUInt16LE(eocd + 10);
162
+ let offset = buffer.readUInt32LE(eocd + 16);
163
+ const entries = [];
164
+ for (let i = 0; i < count; i++) {
165
+ if (offset + 46 > buffer.length || buffer.readUInt32LE(offset) !== CENTRAL_SIGNATURE) {
166
+ throw new SetupError('That zip file is damaged (its directory does not line up).');
167
+ }
168
+ const method = buffer.readUInt16LE(offset + 10);
169
+ const compressedSize = buffer.readUInt32LE(offset + 20);
170
+ const nameLength = buffer.readUInt16LE(offset + 28);
171
+ const extraLength = buffer.readUInt16LE(offset + 30);
172
+ const commentLength = buffer.readUInt16LE(offset + 32);
173
+ const localOffset = buffer.readUInt32LE(offset + 42);
174
+ const name = buffer.toString('utf8', offset + 46, offset + 46 + nameLength);
175
+ offset += 46 + nameLength + extraLength + commentLength;
176
+ if (name.endsWith('/'))
177
+ continue;
178
+ if (localOffset + 30 > buffer.length || buffer.readUInt32LE(localOffset) !== LOCAL_SIGNATURE) {
179
+ throw new SetupError(`That zip file is damaged (no local header for ${name}).`);
180
+ }
181
+ const localNameLength = buffer.readUInt16LE(localOffset + 26);
182
+ const localExtraLength = buffer.readUInt16LE(localOffset + 28);
183
+ const start = localOffset + 30 + localNameLength + localExtraLength;
184
+ const raw = buffer.subarray(start, start + compressedSize);
185
+ let data;
186
+ if (method === 0)
187
+ data = Buffer.from(raw);
188
+ else if (method === 8)
189
+ data = inflateRawSync(raw);
190
+ else
191
+ throw new SetupError(`${name} uses an unsupported compression method (${method}).`);
192
+ entries.push({ name, data });
193
+ }
194
+ return entries;
195
+ }
196
+ /**
197
+ * Is this a LinkedIn Toolkit extension zip?
198
+ *
199
+ * The failure this catches is mundane and common: GitHub served an HTML error
200
+ * page, a proxy served a login page, or the release has no asset — and the
201
+ * bytes get unpacked into a folder Chrome then refuses. Checking the magic
202
+ * number and the manifest turns that into one sentence.
203
+ */
204
+ export function validateExtensionZip(buffer) {
205
+ const magic = buffer.subarray(0, 2).toString('latin1');
206
+ if (magic !== 'PK') {
207
+ const head = buffer.subarray(0, 40).toString('utf8').replace(/\s+/g, ' ').trim();
208
+ throw new SetupError(`What downloaded is not a zip file (it starts "${head}").`, `That is usually an error page. Check ${RELEASES_URL} in a browser.`);
209
+ }
210
+ const entries = readZip(buffer);
211
+ const manifest = entries.find((entry) => entry.name === 'manifest.json');
212
+ if (!manifest) {
213
+ throw new SetupError('That zip has no manifest.json at its top level, so Chrome could not load it.', `Check the asset on ${RELEASES_URL}.`);
214
+ }
215
+ let parsed;
216
+ try {
217
+ parsed = JSON.parse(manifest.data.toString('utf8'));
218
+ }
219
+ catch {
220
+ throw new SetupError('The manifest.json inside that zip is not valid JSON.');
221
+ }
222
+ if (!parsed?.version || parsed?.manifest_version !== 3) {
223
+ throw new SetupError('The manifest.json inside that zip is not a Chrome MV3 manifest.');
224
+ }
225
+ return { entries, manifestVersion: String(parsed.version), name: String(parsed.name ?? 'extension') };
226
+ }
227
+ /** Reject anything that would write outside the target folder. */
228
+ export function safeEntryName(name) {
229
+ const normalized = name.replace(/\\/g, '/');
230
+ if (normalized.startsWith('/') ||
231
+ /^[A-Za-z]:/.test(normalized) ||
232
+ normalized.split('/').some((part) => part === '..')) {
233
+ throw new SetupError(`That zip contains an unsafe path (${name}); nothing was written.`);
234
+ }
235
+ return normalized;
236
+ }
237
+ /** Write every entry under `dir`, creating the folders it needs. */
238
+ export function unpackZipTo(entries, dir, fs = realFs) {
239
+ fs.mkdirSync(dir, { recursive: true });
240
+ let written = 0;
241
+ for (const entry of entries) {
242
+ const target = join(dir, safeEntryName(entry.name));
243
+ fs.mkdirSync(dirname(target), { recursive: true });
244
+ fs.writeFileSync(target, entry.data);
245
+ written++;
246
+ }
247
+ return written;
248
+ }
249
+ /**
250
+ * Replace `target` with `staged`, keeping a working folder at all times.
251
+ *
252
+ * Chrome loads the extension from this folder on every start, so a half-
253
+ * written folder is a broken extension until the user notices. The new copy is
254
+ * unpacked beside it and only then swapped in; if the swap fails, the previous
255
+ * copy goes back.
256
+ */
257
+ export function swapIn(options) {
258
+ const fs = options.fs ?? realFs;
259
+ const { target, staged } = options;
260
+ const existed = fs.existsSync(target);
261
+ if (!existed) {
262
+ fs.mkdirSync(dirname(target), { recursive: true });
263
+ fs.renameSync(staged, target);
264
+ return { replaced: false };
265
+ }
266
+ const parked = `${target}.old-${(options.now ?? Date.now)()}`;
267
+ fs.renameSync(target, parked);
268
+ try {
269
+ fs.renameSync(staged, target);
270
+ }
271
+ catch (err) {
272
+ fs.renameSync(parked, target);
273
+ throw new SetupError(`Could not replace ${target}: ${err instanceof Error ? err.message : String(err)}`, 'The previous copy is untouched. Close anything holding that folder open and try again.');
274
+ }
275
+ fs.rmSync(parked, { recursive: true, force: true });
276
+ return { replaced: true };
277
+ }
278
+ /** Download, check, unpack, swap. The whole of step (a) in one call. */
279
+ export async function installExtension(options) {
280
+ const fs = options.fs ?? realFs;
281
+ const now = options.now ?? Date.now;
282
+ const download = await downloadExtension({ version: options.version, fetchImpl: options.fetchImpl });
283
+ const { entries, manifestVersion } = validateExtensionZip(download.buffer);
284
+ const target = resolve(options.dir);
285
+ const staged = `${target}.tmp-${process.pid}-${now()}`;
286
+ fs.rmSync(staged, { recursive: true, force: true });
287
+ let files;
288
+ try {
289
+ files = unpackZipTo(entries, staged, fs);
290
+ }
291
+ catch (err) {
292
+ fs.rmSync(staged, { recursive: true, force: true });
293
+ throw err;
294
+ }
295
+ const { replaced } = swapIn({ target, staged, fs, now });
296
+ return {
297
+ url: download.url,
298
+ version: download.version,
299
+ source: download.source,
300
+ dir: target,
301
+ files,
302
+ replaced,
303
+ manifestVersion,
304
+ };
305
+ }
306
+ /**
307
+ * The version of `linkedin-toolkit-mcp` that is actually running.
308
+ *
309
+ * The extension and the server are released together from one tag, so the
310
+ * installed package version is the right default for which zip to fetch. This
311
+ * reads the package's own manifest rather than a constant, so a published
312
+ * build can never disagree with itself about what it is.
313
+ */
314
+ export function packageVersion(read = (path) => readFileSync(path, 'utf8')) {
315
+ try {
316
+ const path = fileURLToPath(new URL('../package.json', import.meta.url));
317
+ const version = JSON.parse(read(path))?.version;
318
+ return typeof version === 'string' && version ? version : null;
319
+ }
320
+ catch {
321
+ return null;
322
+ }
323
+ }
324
+ /** Where the extension lives unless `--dir` says otherwise. */
325
+ export function defaultExtensionDir(home = process.env.LINKEDIN_TOOLKIT_HOME) {
326
+ return join(home || join(homedir(), '.linkedin-toolkit'), 'extension');
327
+ }
328
+ /**
329
+ * How to ask Chrome to show `chrome://extensions`, if we can ask at all.
330
+ *
331
+ * Chrome ignores `chrome://` URLs handed to it on the command line in most
332
+ * builds — it opens a new tab page instead and says nothing. So this never
333
+ * reports success: it either asks and tells the user to type the URL if
334
+ * nothing appeared, or it does not ask and says why. Claiming a page opened
335
+ * when it did not is worse than not trying.
336
+ */
337
+ export function chromeLaunch(platform, env = process.env, exists = (path) => existsSync(path)) {
338
+ const url = 'chrome://extensions';
339
+ if (platform === 'darwin') {
340
+ return { kind: 'spawn', command: 'open', args: ['-a', 'Google Chrome', url] };
341
+ }
342
+ if (platform === 'win32') {
343
+ const roots = [env.PROGRAMFILES, env['PROGRAMFILES(X86)'], env.LOCALAPPDATA].filter((root) => Boolean(root));
344
+ for (const root of roots) {
345
+ const exe = join(root, 'Google', 'Chrome', 'Application', 'chrome.exe');
346
+ if (exists(exe))
347
+ return { kind: 'spawn', command: exe, args: [url] };
348
+ }
349
+ return {
350
+ kind: 'none',
351
+ reason: 'Chrome is not in its usual place under Program Files or AppData',
352
+ };
353
+ }
354
+ if (platform === 'linux') {
355
+ for (const exe of [
356
+ '/usr/bin/google-chrome',
357
+ '/usr/bin/google-chrome-stable',
358
+ '/usr/bin/chromium',
359
+ '/usr/bin/chromium-browser',
360
+ '/snap/bin/chromium',
361
+ ]) {
362
+ if (exists(exe))
363
+ return { kind: 'spawn', command: exe, args: [url] };
364
+ }
365
+ return { kind: 'none', reason: 'no Chrome or Chromium binary was found on this machine' };
366
+ }
367
+ return { kind: 'none', reason: `this platform (${platform}) has no known Chrome location` };
368
+ }
369
+ /* ------------------------------------------------------------------ *
370
+ * MCP client configuration
371
+ * ------------------------------------------------------------------ */
372
+ export const CLIENTS = [
373
+ 'claude-desktop',
374
+ 'claude-code',
375
+ 'cursor',
376
+ 'windsurf',
377
+ 'vscode',
378
+ 'n8n',
379
+ 'print',
380
+ ];
381
+ export const SERVER_KEY = 'linkedin-toolkit';
382
+ /** The stdio entry every MCP client gets, in that client's spelling. */
383
+ export function serverEntry(client) {
384
+ const base = { command: 'npx', args: ['-y', 'linkedin-toolkit-mcp'] };
385
+ // VS Code's own schema wants the transport named; the rest infer stdio.
386
+ return client === 'vscode' ? { type: 'stdio', ...base } : base;
387
+ }
388
+ /**
389
+ * Where each client keeps its MCP config, per OS.
390
+ *
391
+ * Two are project-scoped by design (`.mcp.json`, `.vscode/mcp.json`) because
392
+ * that is where those clients look first and where a user can see them; two
393
+ * are user-scoped because the client has no project scope. n8n is printed, not
394
+ * written: its MCP client is configured inside a workflow in the n8n UI — and
395
+ * on the usual Docker install the config is not even on this machine — so
396
+ * there is no file here to merge into.
397
+ */
398
+ export function clientTarget(id, context) {
399
+ const env = context.env ?? process.env;
400
+ const home = context.home ?? homedir();
401
+ const cwd = context.cwd ?? process.cwd();
402
+ switch (id) {
403
+ case 'claude-code':
404
+ return {
405
+ id,
406
+ label: 'Claude Code',
407
+ mode: 'write',
408
+ path: join(cwd, '.mcp.json'),
409
+ key: 'mcpServers',
410
+ note: 'Project-scoped. Claude Code asks you to approve the server the first time you open this folder.',
411
+ };
412
+ case 'claude-desktop': {
413
+ const path = context.platform === 'win32'
414
+ ? join(env.APPDATA || join(home, 'AppData', 'Roaming'), 'Claude', 'claude_desktop_config.json')
415
+ : context.platform === 'darwin'
416
+ ? join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json')
417
+ : join(env.XDG_CONFIG_HOME || join(home, '.config'), 'Claude', 'claude_desktop_config.json');
418
+ return {
419
+ id,
420
+ label: 'Claude Desktop',
421
+ mode: 'write',
422
+ path,
423
+ key: 'mcpServers',
424
+ note: 'Quit and reopen Claude Desktop afterwards — a window reload is not enough.',
425
+ };
426
+ }
427
+ case 'cursor':
428
+ return {
429
+ id,
430
+ label: 'Cursor',
431
+ mode: 'write',
432
+ path: join(home, '.cursor', 'mcp.json'),
433
+ key: 'mcpServers',
434
+ note: 'User-scoped, so every project gets it. For one project only, put the same block in .cursor/mcp.json.',
435
+ };
436
+ case 'windsurf':
437
+ return {
438
+ id,
439
+ label: 'Windsurf',
440
+ mode: 'write',
441
+ path: join(home, '.codeium', 'windsurf', 'mcp_config.json'),
442
+ key: 'mcpServers',
443
+ note: 'Settings → Cascade → MCP Servers → Refresh picks it up without restarting.',
444
+ };
445
+ case 'vscode':
446
+ return {
447
+ id,
448
+ label: 'VS Code',
449
+ mode: 'write',
450
+ path: join(cwd, '.vscode', 'mcp.json'),
451
+ key: 'servers',
452
+ note: 'Workspace-scoped. VS Code shows a Start button above the server entry; agent mode then lists the tools.',
453
+ };
454
+ case 'n8n':
455
+ return {
456
+ id,
457
+ label: 'n8n',
458
+ mode: 'print',
459
+ key: 'mcpServers',
460
+ note: 'n8n has no MCP config file: the MCP Client Tool node is configured inside a workflow, and a Docker ' +
461
+ 'install cannot see this machine\'s filesystem anyway. Use the command below in the node, or point it ' +
462
+ 'at `lit serve --http`. See docs/agents/n8n.md.',
463
+ };
464
+ case 'print':
465
+ default:
466
+ return {
467
+ id: 'print',
468
+ label: 'any MCP client',
469
+ mode: 'print',
470
+ key: 'mcpServers',
471
+ note: 'Paste this into your client\'s MCP config. docs/clients.md has the file path for each one.',
472
+ };
473
+ }
474
+ }
475
+ /** The snippet a print-only client gets. */
476
+ export function configSnippet(client) {
477
+ const target = clientTarget(client, { platform: process.platform });
478
+ return `${JSON.stringify({ [target.key]: { [SERVER_KEY]: serverEntry(client) } }, null, 2)}\n`;
479
+ }
480
+ /**
481
+ * Merge our entry into an existing client config without touching anything else.
482
+ *
483
+ * A config file people have edited by hand is not ours to rewrite. Anything we
484
+ * cannot parse — malformed JSON, a top level that is not an object, a
485
+ * `mcpServers` that is not an object — is refused with the path, so the user
486
+ * fixes their file rather than losing it to us.
487
+ */
488
+ export function mergeMcpConfig(options) {
489
+ const { existing, key, entry } = options;
490
+ const name = options.name ?? SERVER_KEY;
491
+ const where = options.path ? ` in ${options.path}` : '';
492
+ let root = {};
493
+ if (existing !== null && existing.trim() !== '') {
494
+ let parsed;
495
+ try {
496
+ parsed = JSON.parse(existing);
497
+ }
498
+ catch (err) {
499
+ throw new SetupError(`The config file${where} is not valid JSON, so it was left alone: ${err instanceof Error ? err.message : String(err)}`, 'Fix the file (or move it aside) and run the command again. Nothing was written.');
500
+ }
501
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
502
+ throw new SetupError(`The config file${where} does not hold a JSON object, so it was left alone.`, 'Fix the file (or move it aside) and run the command again. Nothing was written.');
503
+ }
504
+ root = parsed;
505
+ }
506
+ const current = root[key];
507
+ if (current !== undefined && (current === null || typeof current !== 'object' || Array.isArray(current))) {
508
+ throw new SetupError(`"${key}"${where} is not a JSON object, so the file was left alone.`, 'Fix the file (or move it aside) and run the command again. Nothing was written.');
509
+ }
510
+ const servers = { ...(current ?? {}) };
511
+ const kept = Object.keys(servers).filter((server) => server !== name);
512
+ const changed = JSON.stringify(servers[name] ?? null) !== JSON.stringify(entry);
513
+ servers[name] = entry;
514
+ return {
515
+ contents: `${JSON.stringify({ ...root, [key]: servers }, null, 2)}\n`,
516
+ changed,
517
+ kept,
518
+ };
519
+ }
520
+ /** `2026-09-18T14-22-05Z`, so backups sort and never collide on a retry. */
521
+ export function backupStamp(at) {
522
+ return new Date(at).toISOString().replace(/\.\d+Z$/, 'Z').replace(/:/g, '-');
523
+ }
524
+ /**
525
+ * Write (or pretend to write) one client's config.
526
+ *
527
+ * The original is copied to `<file>.bak-<timestamp>` before it is replaced —
528
+ * this is somebody's editor config, and a merge bug should cost them a rename,
529
+ * not their other MCP servers.
530
+ */
531
+ export function writeClientConfig(options) {
532
+ const fs = options.fs ?? realFs;
533
+ const now = options.now ?? Date.now;
534
+ const { target } = options;
535
+ if (!target.path)
536
+ throw new SetupError(`${target.label} has no config file to write.`);
537
+ const existed = fs.existsSync(target.path);
538
+ const existing = existed ? fs.readFileSync(target.path, 'utf8').toString() : null;
539
+ const merged = mergeMcpConfig({
540
+ existing,
541
+ key: target.key,
542
+ entry: options.entry,
543
+ path: target.path,
544
+ });
545
+ if (options.dryRun) {
546
+ return { path: target.path, action: 'dry-run', kept: merged.kept, created: !existed };
547
+ }
548
+ if (!merged.changed && existed) {
549
+ return { path: target.path, action: 'unchanged', kept: merged.kept, created: false };
550
+ }
551
+ let backup;
552
+ if (existed) {
553
+ backup = `${target.path}.bak-${backupStamp(now())}`;
554
+ fs.copyFileSync(target.path, backup);
555
+ }
556
+ fs.mkdirSync(dirname(target.path), { recursive: true });
557
+ fs.writeFileSync(target.path, merged.contents, 'utf8');
558
+ return { path: target.path, action: 'written', backup, kept: merged.kept, created: !existed };
559
+ }
560
+ /* ------------------------------------------------------------------ *
561
+ * Words
562
+ * ------------------------------------------------------------------ */
563
+ /** The three things Chrome will not let any installer do for you. */
564
+ export function chromeSteps(dir) {
565
+ return [
566
+ ' 1. Open chrome://extensions (type it in the address bar — it does not come up in search).',
567
+ ' 2. Turn on "Developer mode", top right.',
568
+ ` 3. Click "Load unpacked" and choose this exact folder:\n\n ${dir}\n`,
569
+ ];
570
+ }
571
+ /** What `lit setup` says when the extension never paired. */
572
+ export function pairingTimeoutMessage(seconds) {
573
+ return [
574
+ `Not paired after ${seconds}s — the extension has not connected to this server.`,
575
+ '',
576
+ 'That is normal if you have not finished the three Chrome steps above yet; nothing is lost.',
577
+ 'When you have loaded the extension:',
578
+ '',
579
+ ' 1. Run: lit serve --http',
580
+ ' 2. Open the toolkit popup → Settings → Local bridge, paste the pairing token, enable it.',
581
+ ' 3. Check it: lit status',
582
+ ].join('\n');
583
+ }
584
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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"}
package/dist/tools.d.ts CHANGED
@@ -10,7 +10,7 @@ import { type BridgeResponse } from './bridge.js';
10
10
  import { type RequestOrigin, type ToolDef } from './contract.js';
11
11
  import type { Toolkit } from './toolkit.js';
12
12
  export declare const SERVER_NAME = "linkedin-toolkit";
13
- export declare const SERVER_VERSION = "2.0.0";
13
+ export declare const SERVER_VERSION = "2.1.0";
14
14
  /**
15
15
  * A tool result: the JSON text an agent reads plus machine-readable output.
16
16
  *
package/dist/tools.js CHANGED
@@ -10,7 +10,7 @@ import { TOOLS, toolInputSchema, } from './contract.js';
10
10
  import { registerResources } from './resources.js';
11
11
  import { registerPrompts } from './prompts.js';
12
12
  export const SERVER_NAME = 'linkedin-toolkit';
13
- export const SERVER_VERSION = '2.0.0';
13
+ export const SERVER_VERSION = '2.1.0';
14
14
  /**
15
15
  * A tool result: the JSON text an agent reads plus machine-readable output.
16
16
  *