@arabold/docs-mcp-server 1.7.0 → 1.8.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.
@@ -144,55 +144,8 @@ var logger = {
144
144
  }
145
145
  };
146
146
 
147
- // node_modules/uuid/dist/esm-node/stringify.js
148
- var byteToHex = [];
149
- for (let i = 0; i < 256; ++i) {
150
- byteToHex.push((i + 256).toString(16).slice(1));
151
- }
152
- function unsafeStringify(arr, offset = 0) {
153
- return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
154
- }
155
-
156
- // node_modules/uuid/dist/esm-node/rng.js
157
- import crypto from "node:crypto";
158
- var rnds8Pool = new Uint8Array(256);
159
- var poolPtr = rnds8Pool.length;
160
- function rng() {
161
- if (poolPtr > rnds8Pool.length - 16) {
162
- crypto.randomFillSync(rnds8Pool);
163
- poolPtr = 0;
164
- }
165
- return rnds8Pool.slice(poolPtr, poolPtr += 16);
166
- }
167
-
168
- // node_modules/uuid/dist/esm-node/native.js
169
- import crypto2 from "node:crypto";
170
- var native_default = {
171
- randomUUID: crypto2.randomUUID
172
- };
173
-
174
- // node_modules/uuid/dist/esm-node/v4.js
175
- function v4(options, buf, offset) {
176
- if (native_default.randomUUID && !buf && !options) {
177
- return native_default.randomUUID();
178
- }
179
- options = options || {};
180
- const rnds = options.random || (options.rng || rng)();
181
- rnds[6] = rnds[6] & 15 | 64;
182
- rnds[8] = rnds[8] & 63 | 128;
183
- if (buf) {
184
- offset = offset || 0;
185
- for (let i = 0; i < 16; ++i) {
186
- buf[offset + i] = rnds[i];
187
- }
188
- return buf;
189
- }
190
- return unsafeStringify(rnds);
191
- }
192
- var v4_default = v4;
193
-
194
- // src/utils/url.ts
195
- import psl from "psl";
147
+ // src/scraper/fetcher/HttpFetcher.ts
148
+ import axios from "axios";
196
149
 
197
150
  // src/utils/errors.ts
198
151
  var ScraperError = class extends Error {
@@ -224,67 +177,7 @@ var RedirectError = class extends ScraperError {
224
177
  }
225
178
  };
226
179
 
227
- // src/utils/url.ts
228
- var defaultNormalizerOptions = {
229
- ignoreCase: true,
230
- removeHash: true,
231
- removeTrailingSlash: true,
232
- removeQuery: false,
233
- removeIndex: true
234
- };
235
- function normalizeUrl(url, options = defaultNormalizerOptions) {
236
- try {
237
- const parsedUrl = new URL(url);
238
- const finalOptions = { ...defaultNormalizerOptions, ...options };
239
- const normalized = new URL(parsedUrl.origin + parsedUrl.pathname);
240
- if (finalOptions.removeIndex) {
241
- normalized.pathname = normalized.pathname.replace(
242
- /\/index\.(html|htm|asp|php|jsp)$/i,
243
- "/"
244
- );
245
- }
246
- if (finalOptions.removeTrailingSlash && normalized.pathname.length > 1) {
247
- normalized.pathname = normalized.pathname.replace(/\/+$/, "");
248
- }
249
- const preservedHash = !finalOptions.removeHash ? parsedUrl.hash : "";
250
- const preservedSearch = !finalOptions.removeQuery ? parsedUrl.search : "";
251
- let result = normalized.origin + normalized.pathname;
252
- if (preservedSearch) {
253
- result += preservedSearch;
254
- }
255
- if (preservedHash) {
256
- result += preservedHash;
257
- }
258
- if (finalOptions.ignoreCase) {
259
- result = result.toLowerCase();
260
- }
261
- return result;
262
- } catch {
263
- return url;
264
- }
265
- }
266
- function validateUrl(url) {
267
- try {
268
- new URL(url);
269
- } catch (error) {
270
- throw new InvalidUrlError(url, error instanceof Error ? error : void 0);
271
- }
272
- }
273
- function hasSameHostname(urlA, urlB) {
274
- return urlA.hostname.toLowerCase() === urlB.hostname.toLowerCase();
275
- }
276
- function hasSameDomain(urlA, urlB) {
277
- const domainA = psl.get(urlA.hostname.toLowerCase());
278
- const domainB = psl.get(urlB.hostname.toLowerCase());
279
- return domainA !== null && domainA === domainB;
280
- }
281
- function isSubpath(baseUrl, targetUrl) {
282
- const basePath = baseUrl.pathname.endsWith("/") ? baseUrl.pathname : `${baseUrl.pathname}/`;
283
- return targetUrl.pathname.startsWith(basePath);
284
- }
285
-
286
180
  // src/scraper/fetcher/HttpFetcher.ts
287
- import axios from "axios";
288
181
  var HttpFetcher = class {
289
182
  MAX_RETRIES = 6;
290
183
  BASE_DELAY = 1e3;
@@ -394,29 +287,6 @@ var FileFetcher = class {
394
287
  }
395
288
  };
396
289
 
397
- // src/scraper/strategies/BaseScraperStrategy.ts
398
- import { URL as URL2 } from "node:url";
399
-
400
- // src/pipeline/errors.ts
401
- var PipelineError = class extends Error {
402
- constructor(message, cause) {
403
- super(message);
404
- this.cause = cause;
405
- this.name = this.constructor.name;
406
- if (cause?.stack) {
407
- this.stack = `${this.stack}
408
- Caused by: ${cause.stack}`;
409
- }
410
- }
411
- };
412
- var PipelineStateError = class extends PipelineError {
413
- };
414
- var CancellationError = class extends PipelineError {
415
- constructor(message = "Operation cancelled") {
416
- super(message);
417
- }
418
- };
419
-
420
290
  // src/scraper/processor/HtmlProcessor.ts
421
291
  import createDOMPurify from "dompurify";
422
292
  import { JSDOM } from "jsdom";
@@ -439,7 +309,7 @@ var HtmlProcessor = class {
439
309
  "input",
440
310
  "textarea",
441
311
  "select",
442
- "form",
312
+ // "form", // Known issue: Some pages use alerts for important content
443
313
  ".ads",
444
314
  ".advertisement",
445
315
  ".banner",
@@ -472,18 +342,16 @@ var HtmlProcessor = class {
472
342
  ".signup-form",
473
343
  ".tooltip",
474
344
  ".dropdown-menu",
475
- ".alert",
345
+ // ".alert", // Known issue: Some pages use alerts for important content
476
346
  ".breadcrumb",
477
347
  ".pagination",
478
- '[role="alert"]',
348
+ // '[role="alert"]', // Known issue: Some pages use alerts for important content
479
349
  '[role="banner"]',
480
350
  '[role="dialog"]',
481
351
  '[role="alertdialog"]',
482
352
  '[role="region"][aria-label*="skip" i]',
483
353
  '[aria-modal="true"]',
484
- ".noprint",
485
- "figure",
486
- "sup"
354
+ ".noprint"
487
355
  ];
488
356
  constructor(options) {
489
357
  this.turndownService = new TurndownService({
@@ -514,9 +382,17 @@ var HtmlProcessor = class {
514
382
  }
515
383
  }
516
384
  }
385
+ const text3 = (() => {
386
+ const clone = element.cloneNode(true);
387
+ const brElements = Array.from(clone.querySelectorAll("br"));
388
+ for (const br of brElements) {
389
+ br.replaceWith("\n");
390
+ }
391
+ return clone.textContent;
392
+ })();
517
393
  return `
518
394
  \`\`\`${language}
519
- ${node2.textContent}
395
+ ${text3}
520
396
  \`\`\`
521
397
  `;
522
398
  }
@@ -622,6 +498,136 @@ var MarkdownProcessor = class {
622
498
  }
623
499
  };
624
500
 
501
+ // node_modules/uuid/dist/esm-node/stringify.js
502
+ var byteToHex = [];
503
+ for (let i = 0; i < 256; ++i) {
504
+ byteToHex.push((i + 256).toString(16).slice(1));
505
+ }
506
+ function unsafeStringify(arr, offset = 0) {
507
+ return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
508
+ }
509
+
510
+ // node_modules/uuid/dist/esm-node/rng.js
511
+ import crypto from "node:crypto";
512
+ var rnds8Pool = new Uint8Array(256);
513
+ var poolPtr = rnds8Pool.length;
514
+ function rng() {
515
+ if (poolPtr > rnds8Pool.length - 16) {
516
+ crypto.randomFillSync(rnds8Pool);
517
+ poolPtr = 0;
518
+ }
519
+ return rnds8Pool.slice(poolPtr, poolPtr += 16);
520
+ }
521
+
522
+ // node_modules/uuid/dist/esm-node/native.js
523
+ import crypto2 from "node:crypto";
524
+ var native_default = {
525
+ randomUUID: crypto2.randomUUID
526
+ };
527
+
528
+ // node_modules/uuid/dist/esm-node/v4.js
529
+ function v4(options, buf, offset) {
530
+ if (native_default.randomUUID && !buf && !options) {
531
+ return native_default.randomUUID();
532
+ }
533
+ options = options || {};
534
+ const rnds = options.random || (options.rng || rng)();
535
+ rnds[6] = rnds[6] & 15 | 64;
536
+ rnds[8] = rnds[8] & 63 | 128;
537
+ if (buf) {
538
+ offset = offset || 0;
539
+ for (let i = 0; i < 16; ++i) {
540
+ buf[offset + i] = rnds[i];
541
+ }
542
+ return buf;
543
+ }
544
+ return unsafeStringify(rnds);
545
+ }
546
+ var v4_default = v4;
547
+
548
+ // src/utils/url.ts
549
+ import psl from "psl";
550
+ var defaultNormalizerOptions = {
551
+ ignoreCase: true,
552
+ removeHash: true,
553
+ removeTrailingSlash: true,
554
+ removeQuery: false,
555
+ removeIndex: true
556
+ };
557
+ function normalizeUrl(url, options = defaultNormalizerOptions) {
558
+ try {
559
+ const parsedUrl = new URL(url);
560
+ const finalOptions = { ...defaultNormalizerOptions, ...options };
561
+ const normalized = new URL(parsedUrl.origin + parsedUrl.pathname);
562
+ if (finalOptions.removeIndex) {
563
+ normalized.pathname = normalized.pathname.replace(
564
+ /\/index\.(html|htm|asp|php|jsp)$/i,
565
+ "/"
566
+ );
567
+ }
568
+ if (finalOptions.removeTrailingSlash && normalized.pathname.length > 1) {
569
+ normalized.pathname = normalized.pathname.replace(/\/+$/, "");
570
+ }
571
+ const preservedHash = !finalOptions.removeHash ? parsedUrl.hash : "";
572
+ const preservedSearch = !finalOptions.removeQuery ? parsedUrl.search : "";
573
+ let result = normalized.origin + normalized.pathname;
574
+ if (preservedSearch) {
575
+ result += preservedSearch;
576
+ }
577
+ if (preservedHash) {
578
+ result += preservedHash;
579
+ }
580
+ if (finalOptions.ignoreCase) {
581
+ result = result.toLowerCase();
582
+ }
583
+ return result;
584
+ } catch {
585
+ return url;
586
+ }
587
+ }
588
+ function validateUrl(url) {
589
+ try {
590
+ new URL(url);
591
+ } catch (error) {
592
+ throw new InvalidUrlError(url, error instanceof Error ? error : void 0);
593
+ }
594
+ }
595
+ function hasSameHostname(urlA, urlB) {
596
+ return urlA.hostname.toLowerCase() === urlB.hostname.toLowerCase();
597
+ }
598
+ function hasSameDomain(urlA, urlB) {
599
+ const domainA = psl.get(urlA.hostname.toLowerCase());
600
+ const domainB = psl.get(urlB.hostname.toLowerCase());
601
+ return domainA !== null && domainA === domainB;
602
+ }
603
+ function isSubpath(baseUrl, targetUrl) {
604
+ const basePath = baseUrl.pathname.endsWith("/") ? baseUrl.pathname : `${baseUrl.pathname}/`;
605
+ return targetUrl.pathname.startsWith(basePath);
606
+ }
607
+
608
+ // src/scraper/strategies/BaseScraperStrategy.ts
609
+ import { URL as URL2 } from "node:url";
610
+
611
+ // src/pipeline/errors.ts
612
+ var PipelineError = class extends Error {
613
+ constructor(message, cause) {
614
+ super(message);
615
+ this.cause = cause;
616
+ this.name = this.constructor.name;
617
+ if (cause?.stack) {
618
+ this.stack = `${this.stack}
619
+ Caused by: ${cause.stack}`;
620
+ }
621
+ }
622
+ };
623
+ var PipelineStateError = class extends PipelineError {
624
+ };
625
+ var CancellationError = class extends PipelineError {
626
+ constructor(message = "Operation cancelled") {
627
+ super(message);
628
+ }
629
+ };
630
+
625
631
  // src/scraper/strategies/BaseScraperStrategy.ts
626
632
  var DEFAULT_MAX_PAGES = 100;
627
633
  var DEFAULT_MAX_DEPTH = 3;
@@ -1315,57 +1321,54 @@ var LibraryNotFoundError = class extends ToolError {
1315
1321
  }
1316
1322
  };
1317
1323
 
1318
- // src/tools/SearchTool.ts
1319
- var SearchTool = class {
1320
- docService;
1321
- constructor(docService) {
1322
- this.docService = docService;
1324
+ // src/tools/FetchUrlTool.ts
1325
+ var FetchUrlTool = class {
1326
+ constructor(httpFetcher, fileFetcher, processor) {
1327
+ this.processor = processor;
1328
+ this.fetchers = [httpFetcher, fileFetcher];
1323
1329
  }
1330
+ /**
1331
+ * Collection of fetchers that will be tried in order for a given URL.
1332
+ */
1333
+ fetchers;
1334
+ /**
1335
+ * Fetches content from a URL and converts it to Markdown.
1336
+ * Supports both HTTP/HTTPS URLs and local file URLs (file://).
1337
+ * @returns The processed Markdown content
1338
+ * @throws {ToolError} If fetching or processing fails
1339
+ */
1324
1340
  async execute(options) {
1325
- const { library, version = "latest", query, limit = 5, exactMatch = false } = options;
1326
- logger.info(
1327
- `\u{1F50D} Searching ${library}@${version} for: ${query}${exactMatch ? " (exact match)" : ""}`
1328
- );
1329
- try {
1330
- await this.docService.validateLibraryExists(library);
1331
- let versionToSearch = version;
1332
- if (!exactMatch) {
1333
- const versionResult = await this.docService.findBestVersion(library, version);
1334
- versionToSearch = versionResult.bestMatch;
1335
- }
1336
- const results = await this.docService.searchStore(
1337
- library,
1338
- versionToSearch,
1339
- query,
1340
- limit
1341
+ const { url } = options;
1342
+ const canFetchResults = this.fetchers.map((f) => f.canFetch(url));
1343
+ const fetcherIndex = canFetchResults.findIndex((result) => result === true);
1344
+ if (fetcherIndex === -1) {
1345
+ throw new ToolError(
1346
+ `Invalid URL: ${url}. Must be an HTTP/HTTPS URL or a file:// URL.`,
1347
+ this.constructor.name
1341
1348
  );
1342
- logger.info(`\u2705 Found ${results.length} matching results`);
1343
- return { results };
1349
+ }
1350
+ const fetcher = this.fetchers[fetcherIndex];
1351
+ try {
1352
+ logger.info(`\u{1F4E1} Fetching ${url}...`);
1353
+ const rawContent = await fetcher.fetch(url, {
1354
+ followRedirects: options.followRedirects ?? true,
1355
+ maxRetries: 3
1356
+ });
1357
+ logger.info("\u{1F504} Converting to Markdown...");
1358
+ const processed = await this.processor.process(rawContent);
1359
+ logger.info(`\u2705 Successfully converted ${url} to Markdown`);
1360
+ return processed.content;
1344
1361
  } catch (error) {
1345
- if (error instanceof LibraryNotFoundError) {
1346
- logger.info(`\u2139\uFE0F Library not found: ${error.message}`);
1347
- return {
1348
- results: [],
1349
- error: {
1350
- message: error.message,
1351
- suggestions: error.suggestions
1352
- }
1353
- };
1354
- }
1355
- if (error instanceof VersionNotFoundError) {
1356
- logger.info(`\u2139\uFE0F Version not found: ${error.message}`);
1357
- return {
1358
- results: [],
1359
- error: {
1360
- message: error.message,
1361
- availableVersions: error.availableVersions
1362
- }
1363
- };
1362
+ if (error instanceof ScraperError) {
1363
+ throw new ToolError(
1364
+ `Failed to fetch or process URL: ${error.message}`,
1365
+ this.constructor.name
1366
+ );
1364
1367
  }
1365
- logger.error(
1366
- `\u274C Search failed: ${error instanceof Error ? error.message : "Unknown error"}`
1368
+ throw new ToolError(
1369
+ `Failed to fetch or process URL: ${error instanceof Error ? error.message : String(error)}`,
1370
+ this.constructor.name
1367
1371
  );
1368
- throw error;
1369
1372
  }
1370
1373
  }
1371
1374
  };
@@ -1531,72 +1534,69 @@ var ScrapeTool = class {
1531
1534
  }
1532
1535
  };
1533
1536
 
1534
- // src/tools/ListJobsTool.ts
1535
- var ListJobsTool = class {
1536
- manager;
1537
- // Change property name and type
1538
- /**
1539
- * Creates an instance of ListJobsTool.
1540
- * @param manager The PipelineManager instance.
1541
- */
1542
- constructor(manager) {
1543
- this.manager = manager;
1537
+ // src/tools/SearchTool.ts
1538
+ var SearchTool = class {
1539
+ docService;
1540
+ constructor(docService) {
1541
+ this.docService = docService;
1544
1542
  }
1545
- /**
1546
- * Executes the tool to retrieve a list of pipeline jobs.
1547
- * @param input - The input parameters, optionally including a status filter.
1548
- * @returns A promise that resolves with the list of simplified job objects.
1549
- * @throws {PipelineStateError} If the pipeline manager is somehow unavailable.
1550
- */
1551
- async execute(input) {
1552
- const jobs = await this.manager.getJobs(input.status);
1553
- const simplifiedJobs = jobs.map(
1554
- (job) => ({
1555
- id: job.id,
1556
- library: job.library,
1557
- version: job.version,
1558
- status: job.status,
1559
- createdAt: job.createdAt.toISOString(),
1560
- startedAt: job.startedAt?.toISOString() ?? null,
1561
- finishedAt: job.finishedAt?.toISOString() ?? null,
1562
- error: job.error?.message ?? null
1563
- })
1543
+ async execute(options) {
1544
+ const { library, version, query, limit = 5, exactMatch = false } = options;
1545
+ if (exactMatch && (!version || version === "latest")) {
1546
+ await this.docService.validateLibraryExists(library);
1547
+ const versions = await this.docService.listVersions(library);
1548
+ throw new VersionNotFoundError(
1549
+ library,
1550
+ "latest",
1551
+ versions
1552
+ // versions already has the correct { version: string, indexed: boolean } format
1553
+ );
1554
+ }
1555
+ const resolvedVersion = version || "latest";
1556
+ logger.info(
1557
+ `\u{1F50D} Searching ${library}@${resolvedVersion} for: ${query}${exactMatch ? " (exact match)" : ""}`
1564
1558
  );
1565
- return { jobs: simplifiedJobs };
1566
- }
1567
- };
1568
-
1569
- // src/tools/GetJobInfoTool.ts
1570
- var GetJobInfoTool = class {
1571
- manager;
1572
- /**
1573
- * Creates an instance of GetJobInfoTool.
1574
- * @param manager The PipelineManager instance.
1575
- */
1576
- constructor(manager) {
1577
- this.manager = manager;
1578
- }
1579
- /**
1580
- * Executes the tool to retrieve simplified info for a specific job.
1581
- * @param input - The input parameters, containing the jobId.
1582
- * @returns A promise that resolves with the simplified job info or null if not found.
1583
- */
1584
- async execute(input) {
1585
- const job = await this.manager.getJob(input.jobId);
1586
- if (!job) {
1587
- return { job: null };
1559
+ try {
1560
+ await this.docService.validateLibraryExists(library);
1561
+ let versionToSearch = resolvedVersion;
1562
+ if (!exactMatch) {
1563
+ const versionResult = await this.docService.findBestVersion(library, version);
1564
+ versionToSearch = versionResult.bestMatch;
1565
+ }
1566
+ const results = await this.docService.searchStore(
1567
+ library,
1568
+ versionToSearch,
1569
+ query,
1570
+ limit
1571
+ );
1572
+ logger.info(`\u2705 Found ${results.length} matching results`);
1573
+ return { results };
1574
+ } catch (error) {
1575
+ if (error instanceof LibraryNotFoundError) {
1576
+ logger.info(`\u2139\uFE0F Library not found: ${error.message}`);
1577
+ return {
1578
+ results: [],
1579
+ error: {
1580
+ message: error.message,
1581
+ suggestions: error.suggestions
1582
+ }
1583
+ };
1584
+ }
1585
+ if (error instanceof VersionNotFoundError) {
1586
+ logger.info(`\u2139\uFE0F Version not found: ${error.message}`);
1587
+ return {
1588
+ results: [],
1589
+ error: {
1590
+ message: error.message,
1591
+ availableVersions: error.availableVersions
1592
+ }
1593
+ };
1594
+ }
1595
+ logger.error(
1596
+ `\u274C Search failed: ${error instanceof Error ? error.message : "Unknown error"}`
1597
+ );
1598
+ throw error;
1588
1599
  }
1589
- const jobInfo = {
1590
- id: job.id,
1591
- library: job.library,
1592
- version: job.version,
1593
- status: job.status,
1594
- createdAt: job.createdAt.toISOString(),
1595
- startedAt: job.startedAt?.toISOString() ?? null,
1596
- finishedAt: job.finishedAt?.toISOString() ?? null,
1597
- error: job.error?.message ?? null
1598
- };
1599
- return { job: jobInfo };
1600
1600
  }
1601
1601
  };
1602
1602
 
@@ -1657,6 +1657,75 @@ var CancelJobTool = class {
1657
1657
  }
1658
1658
  };
1659
1659
 
1660
+ // src/tools/GetJobInfoTool.ts
1661
+ var GetJobInfoTool = class {
1662
+ manager;
1663
+ /**
1664
+ * Creates an instance of GetJobInfoTool.
1665
+ * @param manager The PipelineManager instance.
1666
+ */
1667
+ constructor(manager) {
1668
+ this.manager = manager;
1669
+ }
1670
+ /**
1671
+ * Executes the tool to retrieve simplified info for a specific job.
1672
+ * @param input - The input parameters, containing the jobId.
1673
+ * @returns A promise that resolves with the simplified job info or null if not found.
1674
+ */
1675
+ async execute(input) {
1676
+ const job = await this.manager.getJob(input.jobId);
1677
+ if (!job) {
1678
+ return { job: null };
1679
+ }
1680
+ const jobInfo = {
1681
+ id: job.id,
1682
+ library: job.library,
1683
+ version: job.version,
1684
+ status: job.status,
1685
+ createdAt: job.createdAt.toISOString(),
1686
+ startedAt: job.startedAt?.toISOString() ?? null,
1687
+ finishedAt: job.finishedAt?.toISOString() ?? null,
1688
+ error: job.error?.message ?? null
1689
+ };
1690
+ return { job: jobInfo };
1691
+ }
1692
+ };
1693
+
1694
+ // src/tools/ListJobsTool.ts
1695
+ var ListJobsTool = class {
1696
+ manager;
1697
+ // Change property name and type
1698
+ /**
1699
+ * Creates an instance of ListJobsTool.
1700
+ * @param manager The PipelineManager instance.
1701
+ */
1702
+ constructor(manager) {
1703
+ this.manager = manager;
1704
+ }
1705
+ /**
1706
+ * Executes the tool to retrieve a list of pipeline jobs.
1707
+ * @param input - The input parameters, optionally including a status filter.
1708
+ * @returns A promise that resolves with the list of simplified job objects.
1709
+ * @throws {PipelineStateError} If the pipeline manager is somehow unavailable.
1710
+ */
1711
+ async execute(input) {
1712
+ const jobs = await this.manager.getJobs(input.status);
1713
+ const simplifiedJobs = jobs.map(
1714
+ (job) => ({
1715
+ id: job.id,
1716
+ library: job.library,
1717
+ version: job.version,
1718
+ status: job.status,
1719
+ createdAt: job.createdAt.toISOString(),
1720
+ startedAt: job.startedAt?.toISOString() ?? null,
1721
+ finishedAt: job.finishedAt?.toISOString() ?? null,
1722
+ error: job.error?.message ?? null
1723
+ })
1724
+ );
1725
+ return { jobs: simplifiedJobs };
1726
+ }
1727
+ };
1728
+
1660
1729
  // src/tools/RemoveTool.ts
1661
1730
  var RemoveToolInputSchema = {
1662
1731
  type: "object",
@@ -11269,7 +11338,8 @@ var DocumentManagementService = class {
11269
11338
  dbPath = path3.join(dbDir, "documents.db");
11270
11339
  logger.debug(`\u{1F4BE} Using database directory from DOCS_MCP_STORE_PATH: ${dbDir}`);
11271
11340
  } else {
11272
- const oldDbDir = path3.join(process.cwd(), ".store");
11341
+ const projectRoot = path3.resolve(import.meta.dirname, "..");
11342
+ const oldDbDir = path3.join(projectRoot, ".store");
11273
11343
  const oldDbPath = path3.join(oldDbDir, "documents.db");
11274
11344
  const oldDbExists = existsSync(oldDbPath);
11275
11345
  if (oldDbExists) {
@@ -11498,17 +11568,21 @@ var DocumentManagementService = class {
11498
11568
  export {
11499
11569
  setLogLevel,
11500
11570
  logger,
11571
+ HttpFetcher,
11572
+ FileFetcher,
11573
+ HtmlProcessor,
11501
11574
  PipelineJobStatus,
11502
11575
  PipelineManager,
11576
+ CancelJobTool,
11503
11577
  VersionNotFoundError,
11504
- SearchTool,
11578
+ FetchUrlTool,
11505
11579
  FindVersionTool,
11506
- ListLibrariesTool,
11507
- ScrapeTool,
11508
- ListJobsTool,
11509
11580
  GetJobInfoTool,
11510
- CancelJobTool,
11581
+ ListJobsTool,
11582
+ ListLibrariesTool,
11511
11583
  RemoveTool,
11584
+ ScrapeTool,
11585
+ SearchTool,
11512
11586
  DocumentManagementService
11513
11587
  };
11514
- //# sourceMappingURL=chunk-FAZDXJQN.js.map
11588
+ //# sourceMappingURL=chunk-ADZQJG2M.js.map