@j0hanz/fetch-url-mcp 1.12.7 → 1.12.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/dist/http/auth.d.ts +2 -2
  2. package/dist/http/auth.d.ts.map +1 -1
  3. package/dist/http/auth.js +4 -5
  4. package/dist/http/index.d.ts +6 -0
  5. package/dist/http/index.d.ts.map +1 -0
  6. package/dist/http/index.js +5 -0
  7. package/dist/http/native.d.ts +73 -0
  8. package/dist/http/native.d.ts.map +1 -1
  9. package/dist/http/native.js +554 -10
  10. package/dist/http/rate-limit.d.ts +1 -1
  11. package/dist/http/rate-limit.d.ts.map +1 -1
  12. package/dist/http/rate-limit.js +3 -4
  13. package/dist/index.d.ts +17 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +67 -6
  16. package/dist/lib/config.js +2 -2
  17. package/dist/lib/core.d.ts +56 -4
  18. package/dist/lib/core.d.ts.map +1 -1
  19. package/dist/lib/core.js +155 -4
  20. package/dist/lib/error/classes.d.ts +19 -0
  21. package/dist/lib/error/classes.d.ts.map +1 -0
  22. package/dist/lib/error/classes.js +107 -0
  23. package/dist/lib/error/classify.d.ts +4 -0
  24. package/dist/lib/error/classify.d.ts.map +1 -0
  25. package/dist/lib/error/classify.js +154 -0
  26. package/dist/lib/error/codes.d.ts +23 -0
  27. package/dist/lib/error/codes.d.ts.map +1 -0
  28. package/dist/lib/error/codes.js +22 -0
  29. package/dist/lib/error/index.d.ts +6 -0
  30. package/dist/lib/error/index.d.ts.map +1 -0
  31. package/dist/lib/error/index.js +5 -0
  32. package/dist/lib/{error-messages.d.ts → error/messages.d.ts} +2 -2
  33. package/dist/lib/error/messages.d.ts.map +1 -0
  34. package/dist/lib/{error-messages.js → error/messages.js} +2 -2
  35. package/dist/lib/{tool-errors.d.ts → error/payload.d.ts} +7 -13
  36. package/dist/lib/error/payload.d.ts.map +1 -0
  37. package/dist/lib/error/payload.js +108 -0
  38. package/dist/lib/mcp-interop.d.ts.map +1 -1
  39. package/dist/lib/mcp-interop.js +4 -6
  40. package/dist/lib/net/http.d.ts.map +1 -0
  41. package/dist/lib/{http.js → net/http.js} +4 -7
  42. package/dist/lib/net/index.d.ts +4 -0
  43. package/dist/lib/net/index.d.ts.map +1 -0
  44. package/dist/lib/net/index.js +3 -0
  45. package/dist/lib/{fetch-pipeline.d.ts → net/pipeline.d.ts} +3 -3
  46. package/dist/lib/net/pipeline.d.ts.map +1 -0
  47. package/dist/lib/{fetch-pipeline.js → net/pipeline.js} +3 -5
  48. package/dist/lib/{url.d.ts → net/url.d.ts} +1 -1
  49. package/dist/lib/net/url.d.ts.map +1 -0
  50. package/dist/lib/{url.js → net/url.js} +3 -5
  51. package/dist/lib/utils.d.ts +2 -18
  52. package/dist/lib/utils.d.ts.map +1 -1
  53. package/dist/lib/utils.js +29 -104
  54. package/dist/resources/index.d.ts.map +1 -1
  55. package/dist/resources/index.js +8 -5
  56. package/dist/schemas.d.ts +1 -1
  57. package/dist/server.d.ts.map +1 -1
  58. package/dist/server.js +7 -9
  59. package/dist/tasks/index.d.ts +2 -0
  60. package/dist/tasks/index.d.ts.map +1 -0
  61. package/dist/tasks/index.js +1 -0
  62. package/dist/tasks/manager.d.ts +123 -1
  63. package/dist/tasks/manager.d.ts.map +1 -1
  64. package/dist/tasks/manager.js +745 -10
  65. package/dist/tools/{fetch-url.d.ts → index.d.ts} +4 -5
  66. package/dist/tools/index.d.ts.map +1 -0
  67. package/dist/tools/{fetch-url.js → index.js} +6 -8
  68. package/dist/transform/index.d.ts +279 -0
  69. package/dist/transform/index.d.ts.map +1 -0
  70. package/dist/transform/index.js +5234 -0
  71. package/package.json +2 -2
  72. package/dist/cli.d.ts +0 -19
  73. package/dist/cli.d.ts.map +0 -1
  74. package/dist/cli.js +0 -65
  75. package/dist/http/health.d.ts +0 -8
  76. package/dist/http/health.d.ts.map +0 -1
  77. package/dist/http/health.js +0 -152
  78. package/dist/http/helpers.d.ts +0 -68
  79. package/dist/http/helpers.d.ts.map +0 -1
  80. package/dist/http/helpers.js +0 -402
  81. package/dist/lib/error-codes.d.ts +0 -13
  82. package/dist/lib/error-codes.d.ts.map +0 -1
  83. package/dist/lib/error-codes.js +0 -12
  84. package/dist/lib/error-messages.d.ts.map +0 -1
  85. package/dist/lib/fetch-pipeline.d.ts.map +0 -1
  86. package/dist/lib/http.d.ts.map +0 -1
  87. package/dist/lib/logger-names.d.ts +0 -16
  88. package/dist/lib/logger-names.d.ts.map +0 -1
  89. package/dist/lib/logger-names.js +0 -15
  90. package/dist/lib/session.d.ts +0 -44
  91. package/dist/lib/session.d.ts.map +0 -1
  92. package/dist/lib/session.js +0 -137
  93. package/dist/lib/tool-errors.d.ts.map +0 -1
  94. package/dist/lib/tool-errors.js +0 -253
  95. package/dist/lib/url.d.ts.map +0 -1
  96. package/dist/lib/zod.d.ts +0 -3
  97. package/dist/lib/zod.d.ts.map +0 -1
  98. package/dist/lib/zod.js +0 -27
  99. package/dist/tasks/call-contract.d.ts +0 -25
  100. package/dist/tasks/call-contract.d.ts.map +0 -1
  101. package/dist/tasks/call-contract.js +0 -59
  102. package/dist/tasks/execution.d.ts +0 -16
  103. package/dist/tasks/execution.d.ts.map +0 -1
  104. package/dist/tasks/execution.js +0 -241
  105. package/dist/tasks/handlers.d.ts +0 -11
  106. package/dist/tasks/handlers.d.ts.map +0 -1
  107. package/dist/tasks/handlers.js +0 -157
  108. package/dist/tasks/owner.d.ts +0 -43
  109. package/dist/tasks/owner.d.ts.map +0 -1
  110. package/dist/tasks/owner.js +0 -144
  111. package/dist/tasks/registry.d.ts +0 -20
  112. package/dist/tasks/registry.d.ts.map +0 -1
  113. package/dist/tasks/registry.js +0 -40
  114. package/dist/tasks/waiters.d.ts +0 -27
  115. package/dist/tasks/waiters.d.ts.map +0 -1
  116. package/dist/tasks/waiters.js +0 -114
  117. package/dist/tools/fetch-url.d.ts.map +0 -1
  118. package/dist/transform/dom-prep.d.ts +0 -16
  119. package/dist/transform/dom-prep.d.ts.map +0 -1
  120. package/dist/transform/dom-prep.js +0 -1287
  121. package/dist/transform/html-translators.d.ts +0 -5
  122. package/dist/transform/html-translators.d.ts.map +0 -1
  123. package/dist/transform/html-translators.js +0 -697
  124. package/dist/transform/markdown-cleanup.d.ts +0 -10
  125. package/dist/transform/markdown-cleanup.d.ts.map +0 -1
  126. package/dist/transform/markdown-cleanup.js +0 -542
  127. package/dist/transform/metadata.d.ts +0 -18
  128. package/dist/transform/metadata.d.ts.map +0 -1
  129. package/dist/transform/metadata.js +0 -462
  130. package/dist/transform/next-flight.d.ts +0 -2
  131. package/dist/transform/next-flight.d.ts.map +0 -1
  132. package/dist/transform/next-flight.js +0 -374
  133. package/dist/transform/shared.d.ts +0 -8
  134. package/dist/transform/shared.d.ts.map +0 -1
  135. package/dist/transform/shared.js +0 -137
  136. package/dist/transform/transform.d.ts +0 -38
  137. package/dist/transform/transform.d.ts.map +0 -1
  138. package/dist/transform/transform.js +0 -1042
  139. package/dist/transform/types.d.ts +0 -124
  140. package/dist/transform/types.d.ts.map +0 -1
  141. package/dist/transform/types.js +0 -5
  142. package/dist/transform/worker-pool.d.ts +0 -76
  143. package/dist/transform/worker-pool.d.ts.map +0 -1
  144. package/dist/transform/worker-pool.js +0 -725
  145. /package/dist/lib/{http.d.ts → net/http.d.ts} +0 -0
package/dist/index.js CHANGED
@@ -1,12 +1,73 @@
1
1
  #!/usr/bin/env node
2
2
  import process from 'node:process';
3
- import { serverVersion } from './lib/core.js';
4
- import { logError } from './lib/core.js';
5
- import { Loggers } from './lib/logger-names.js';
6
- import { toError } from './lib/utils.js';
7
- import { parseCliArgs, renderCliUsage } from './cli.js';
8
- import { startHttpServer } from './http/native.js';
3
+ import { parseArgs } from 'node:util';
4
+ import { logError, Loggers, serverVersion } from './lib/core.js';
5
+ import { getErrorMessage, toError } from './lib/error/index.js';
6
+ import { startHttpServer } from './http/index.js';
9
7
  import { startStdioServer } from './server.js';
8
+ const usageLines = [
9
+ 'Fetch URL MCP server',
10
+ '',
11
+ 'Usage:',
12
+ ' fetch-url-mcp [--stdio|-s | --http] [--help|-h] [--version|-v]',
13
+ '',
14
+ 'Options:',
15
+ ' --stdio, -s Run in stdio mode (default).',
16
+ ' --http Run in Streamable HTTP mode.',
17
+ ' --help, -h Show this help message.',
18
+ ' --version, -v Show server version.',
19
+ '',
20
+ ];
21
+ const optionSchema = {
22
+ stdio: { type: 'boolean', short: 's', default: false },
23
+ http: { type: 'boolean', default: false },
24
+ help: { type: 'boolean', short: 'h', default: false },
25
+ version: { type: 'boolean', short: 'v', default: false },
26
+ };
27
+ function toBoolean(value) {
28
+ return value === true;
29
+ }
30
+ function readCliFlag(values, key) {
31
+ return toBoolean(values[key]);
32
+ }
33
+ function buildCliValues(values) {
34
+ return {
35
+ stdio: readCliFlag(values, 'stdio'),
36
+ http: readCliFlag(values, 'http'),
37
+ help: readCliFlag(values, 'help'),
38
+ version: readCliFlag(values, 'version'),
39
+ };
40
+ }
41
+ export function renderCliUsage() {
42
+ return `${usageLines.join('\n')}\n`;
43
+ }
44
+ export function parseCliArgs(args) {
45
+ try {
46
+ const { values } = parseArgs({
47
+ args: [...args],
48
+ options: optionSchema,
49
+ strict: true,
50
+ allowPositionals: false,
51
+ });
52
+ const cliValues = buildCliValues(values);
53
+ if (cliValues.stdio && cliValues.http) {
54
+ return {
55
+ ok: false,
56
+ message: 'Choose either --stdio or --http, not both',
57
+ };
58
+ }
59
+ return {
60
+ ok: true,
61
+ values: cliValues,
62
+ };
63
+ }
64
+ catch (error) {
65
+ return {
66
+ ok: false,
67
+ message: getErrorMessage(error),
68
+ };
69
+ }
70
+ }
10
71
  const FORCE_EXIT_TIMEOUT_MS = 10_000;
11
72
  let forcedExitTimer;
12
73
  function writeAndExit(stream, text, code) {
@@ -2,8 +2,8 @@ import { readFileSync } from 'node:fs';
2
2
  import { findPackageJSON } from 'node:module';
3
3
  import process from 'node:process';
4
4
  import { z } from 'zod';
5
- import { buildIpv4, isIP, normalizeHostname, stripTrailingDots, } from './url.js';
6
- import { getErrorMessage } from './utils.js';
5
+ import { getErrorMessage } from './error/index.js';
6
+ import { buildIpv4, isIP, normalizeHostname, stripTrailingDots, } from './net/url.js';
7
7
  // ── Version ─────────────────────────────────────────────────────────
8
8
  function getObjectProperty(value, key) {
9
9
  return value[key];
@@ -1,6 +1,5 @@
1
1
  import { type McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import type { SessionEntry } from './session.js';
3
- import type { SessionStore } from './session.js';
2
+ import type { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
4
3
  export { config, enableHttpMode, serverVersion } from './config.js';
5
4
  type LogMetadata = Record<string, unknown>;
6
5
  interface RequestContext {
@@ -27,10 +26,63 @@ export declare function logError(message: string, error?: Error | LogMetadata, l
27
26
  export declare function logCritical(message: string, error?: Error | LogMetadata, logger?: string): void;
28
27
  export declare function setLogLevel(level: string, sessionId?: string): void;
29
28
  export declare function redactUrl(rawUrl: string): string;
30
- export type { SessionEntry, SessionStore } from './session.js';
31
- export { composeCloseHandlers, createSessionStore, createSlotTracker, ensureSessionCapacity, reserveSessionSlot, } from './session.js';
32
29
  export declare function startSessionCleanupLoop(store: SessionStore, sessionTtlMs: number, options?: {
33
30
  onEvictSession?: (session: SessionEntry) => Promise<void> | void;
34
31
  cleanupIntervalMs?: number;
35
32
  }): AbortController;
33
+ /**
34
+ * Logger names for different components of the application.
35
+ */
36
+ export declare const Loggers: {
37
+ readonly LOG_AUTH: "auth";
38
+ readonly LOG_HTTP: "http";
39
+ readonly LOG_SESSION: "session";
40
+ readonly LOG_SERVER: "server";
41
+ readonly LOG_FETCH: "fetch";
42
+ readonly LOG_TRANSFORM: "transform";
43
+ readonly LOG_TASKS: "tasks";
44
+ readonly LOG_RATE_LIMIT: "rate-limit";
45
+ readonly LOG_MCP: "mcp";
46
+ readonly LOG_FETCH_URL: "fetch-url";
47
+ };
48
+ export interface SessionEntry {
49
+ readonly server: McpServer;
50
+ readonly transport: StreamableHTTPServerTransport;
51
+ createdAt: number;
52
+ lastSeen: number;
53
+ protocolInitialized: boolean;
54
+ negotiatedProtocolVersion: string;
55
+ authFingerprint: string;
56
+ }
57
+ export interface SessionStore {
58
+ get: (sessionId: string) => SessionEntry | undefined;
59
+ touch: (sessionId: string) => void;
60
+ set: (sessionId: string, entry: SessionEntry) => void;
61
+ remove: (sessionId: string) => SessionEntry | undefined;
62
+ size: () => number;
63
+ inFlight: () => number;
64
+ incrementInFlight: () => void;
65
+ decrementInFlight: () => void;
66
+ clear: () => SessionEntry[];
67
+ evictExpired: () => {
68
+ id: string;
69
+ entry: SessionEntry;
70
+ }[];
71
+ evictOldest: () => SessionEntry | undefined;
72
+ }
73
+ interface SlotTracker {
74
+ readonly releaseSlot: () => void;
75
+ readonly markInitialized: () => void;
76
+ readonly isInitialized: () => boolean;
77
+ }
78
+ type CloseHandler = (() => void) | undefined;
79
+ export declare function composeCloseHandlers(first: CloseHandler, second: CloseHandler): CloseHandler;
80
+ export declare function createSessionStore(sessionTtlMs: number): SessionStore;
81
+ export declare function createSlotTracker(store: SessionStore): SlotTracker;
82
+ export declare function reserveSessionSlot(store: SessionStore, maxSessions: number): boolean;
83
+ export declare function ensureSessionCapacity({ store, maxSessions, evictOldest, }: {
84
+ store: SessionStore;
85
+ maxSessions: number;
86
+ evictOldest: (store: SessionStore) => boolean;
87
+ }): boolean;
36
88
  //# sourceMappingURL=core.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/lib/core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/lib/core.ts"],"names":[],"mappings":"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"}
package/dist/lib/core.js CHANGED
@@ -1,10 +1,10 @@
1
+ import {} from '@modelcontextprotocol/sdk/server/mcp.js';
1
2
  import { AsyncLocalStorage } from 'node:async_hooks';
2
3
  import process from 'node:process';
3
4
  import { getSystemErrorMessage, inspect, stripVTControlCharacters, } from 'node:util';
4
- import {} from '@modelcontextprotocol/sdk/server/mcp.js';
5
5
  import { config } from './config.js';
6
- import { Loggers } from './logger-names.js';
7
- import { getErrorMessage, isAbortError, startAbortableIntervalLoop, } from './utils.js';
6
+ import { getErrorMessage, isAbortError } from './error/index.js';
7
+ import { startAbortableIntervalLoop } from './utils.js';
8
8
  export { config, enableHttpMode, serverVersion } from './config.js';
9
9
  const requestContext = new AsyncLocalStorage({
10
10
  name: 'requestContext',
@@ -502,7 +502,6 @@ export function redactUrl(rawUrl) {
502
502
  url.search = '';
503
503
  return url.toString();
504
504
  }
505
- export { composeCloseHandlers, createSessionStore, createSlotTracker, ensureSessionCapacity, reserveSessionSlot, } from './session.js';
506
505
  const MIN_CLEANUP_INTERVAL_MS = 10_000;
507
506
  const MAX_CLEANUP_INTERVAL_MS = 60_000;
508
507
  const SESSION_CLOSE_BATCH_SIZE = 10;
@@ -626,3 +625,155 @@ export function startSessionCleanupLoop(store, sessionTtlMs, options) {
626
625
  const loop = new SessionCleanupLoop(store, sessionTtlMs, options?.onEvictSession, options?.cleanupIntervalMs);
627
626
  return loop.start();
628
627
  }
628
+ /**
629
+ * Logger names for different components of the application.
630
+ */
631
+ export const Loggers = {
632
+ LOG_AUTH: 'auth',
633
+ LOG_HTTP: 'http',
634
+ LOG_SESSION: 'session',
635
+ LOG_SERVER: 'server',
636
+ LOG_FETCH: 'fetch',
637
+ LOG_TRANSFORM: 'transform',
638
+ LOG_TASKS: 'tasks',
639
+ LOG_RATE_LIMIT: 'rate-limit',
640
+ LOG_MCP: 'mcp',
641
+ LOG_FETCH_URL: 'fetch-url',
642
+ };
643
+ export function composeCloseHandlers(first, second) {
644
+ if (!first)
645
+ return second;
646
+ if (!second)
647
+ return first;
648
+ return () => {
649
+ try {
650
+ first();
651
+ }
652
+ finally {
653
+ second();
654
+ }
655
+ };
656
+ }
657
+ /* -------------------------------------------------------------------------------------------------
658
+ * In-memory session store
659
+ * ------------------------------------------------------------------------------------------------- */
660
+ class InMemorySessionStore {
661
+ sessionTtlMs;
662
+ sessions = new Map();
663
+ inflight = 0;
664
+ constructor(sessionTtlMs) {
665
+ this.sessionTtlMs = sessionTtlMs;
666
+ }
667
+ get(sessionId) {
668
+ if (sessionId.length === 0)
669
+ return undefined;
670
+ return this.sessions.get(sessionId);
671
+ }
672
+ touch(sessionId) {
673
+ if (sessionId.length === 0)
674
+ return;
675
+ const session = this.sessions.get(sessionId);
676
+ if (!session)
677
+ return;
678
+ session.lastSeen = Date.now();
679
+ this.sessions.delete(sessionId);
680
+ this.sessions.set(sessionId, session);
681
+ }
682
+ set(sessionId, entry) {
683
+ if (sessionId.length === 0)
684
+ return;
685
+ this.sessions.delete(sessionId);
686
+ this.sessions.set(sessionId, entry);
687
+ }
688
+ remove(sessionId) {
689
+ if (sessionId.length === 0)
690
+ return undefined;
691
+ const session = this.sessions.get(sessionId);
692
+ this.sessions.delete(sessionId);
693
+ return session;
694
+ }
695
+ size() {
696
+ return this.sessions.size;
697
+ }
698
+ inFlight() {
699
+ return this.inflight;
700
+ }
701
+ incrementInFlight() {
702
+ this.inflight += 1;
703
+ }
704
+ decrementInFlight() {
705
+ if (this.inflight === 0)
706
+ return;
707
+ this.inflight -= 1;
708
+ }
709
+ clear() {
710
+ const entries = [...this.sessions.values()];
711
+ this.sessions.clear();
712
+ return entries;
713
+ }
714
+ evictExpired() {
715
+ const now = Date.now();
716
+ const evicted = [];
717
+ for (const [id, session] of this.sessions.entries()) {
718
+ if (this.sessionTtlMs > 0 && now - session.lastSeen > this.sessionTtlMs) {
719
+ this.sessions.delete(id);
720
+ evicted.push({ id, entry: session });
721
+ }
722
+ else {
723
+ break;
724
+ }
725
+ }
726
+ return evicted;
727
+ }
728
+ evictOldest() {
729
+ const oldest = this.sessions.keys().next();
730
+ if (oldest.done)
731
+ return undefined;
732
+ const session = this.sessions.get(oldest.value);
733
+ this.sessions.delete(oldest.value);
734
+ return session;
735
+ }
736
+ }
737
+ export function createSessionStore(sessionTtlMs) {
738
+ const store = new InMemorySessionStore(sessionTtlMs);
739
+ return store;
740
+ }
741
+ /* -------------------------------------------------------------------------------------------------
742
+ * Slot tracking and capacity
743
+ * ------------------------------------------------------------------------------------------------- */
744
+ export function createSlotTracker(store) {
745
+ let slotReleased = false;
746
+ let initialized = false;
747
+ return {
748
+ releaseSlot() {
749
+ if (slotReleased)
750
+ return;
751
+ slotReleased = true;
752
+ store.decrementInFlight();
753
+ },
754
+ markInitialized() {
755
+ initialized = true;
756
+ },
757
+ isInitialized() {
758
+ return initialized;
759
+ },
760
+ };
761
+ }
762
+ export function reserveSessionSlot(store, maxSessions) {
763
+ if (maxSessions <= 0)
764
+ return false;
765
+ if (store.size() + store.inFlight() >= maxSessions)
766
+ return false;
767
+ store.incrementInFlight();
768
+ return true;
769
+ }
770
+ export function ensureSessionCapacity({ store, maxSessions, evictOldest, }) {
771
+ if (maxSessions <= 0)
772
+ return false;
773
+ if (store.size() + store.inFlight() < maxSessions)
774
+ return true;
775
+ if (store.size() > 0 && evictOldest(store)) {
776
+ return store.size() + store.inFlight() < maxSessions;
777
+ }
778
+ return false;
779
+ }
@@ -0,0 +1,19 @@
1
+ export declare function isError(value: unknown): value is Error;
2
+ export declare class FetchError extends Error {
3
+ readonly url: string;
4
+ readonly statusCode: number;
5
+ readonly code: string;
6
+ readonly details: Readonly<Record<string, unknown>>;
7
+ constructor(message: string, url: string, httpStatus?: number, details?: Record<string, unknown>, options?: ErrorOptions);
8
+ }
9
+ export declare class CodedError extends Error {
10
+ readonly code: string;
11
+ constructor(message: string, code: string, options?: ErrorOptions);
12
+ }
13
+ export declare function isAbortError(error: unknown): boolean;
14
+ export declare function isSystemError(error: unknown): error is NodeJS.ErrnoException;
15
+ export declare function getErrorMessage(error: unknown): string;
16
+ export declare function toError(error: unknown): Error;
17
+ export declare function throwIfAborted(signal: AbortSignal | undefined, url: string, stage: string): void;
18
+ export declare function createAbortError(url: string, stage: string): FetchError;
19
+ //# sourceMappingURL=classes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classes.d.ts","sourceRoot":"","sources":["../../../src/lib/error/classes.ts"],"names":[],"mappings":"AAWA,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,KAAK,CAQtD;AAMD,qBAAa,UAAW,SAAQ,KAAK;IAOjC,QAAQ,CAAC,GAAG,EAAE,MAAM;IANtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;gBAGlD,OAAO,EAAE,MAAM,EACN,GAAG,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACrC,OAAO,CAAC,EAAE,YAAY;CAezB;AAED,qBAAa,UAAW,SAAQ,KAAK;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBACV,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAKlE;AAID,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEpD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,cAAc,CAK5E;AAMD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAsBtD;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAE7C;AAID,wBAAgB,cAAc,CAC5B,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ,IAAI,CAYN;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,CAMvE"}
@@ -0,0 +1,107 @@
1
+ import { inspect } from 'node:util';
2
+ import { isObject } from '../utils.js';
3
+ import { SystemErrors } from './codes.js';
4
+ export function isError(value) {
5
+ const maybeIsError = Error.isError;
6
+ if (typeof maybeIsError === 'function') {
7
+ const result = maybeIsError(value);
8
+ if (typeof result === 'boolean')
9
+ return result;
10
+ }
11
+ return value instanceof Error;
12
+ }
13
+ // ── Error classes ──────────────────────────────────────────────────
14
+ const DEFAULT_HTTP_STATUS = 502;
15
+ export class FetchError extends Error {
16
+ url;
17
+ statusCode;
18
+ code;
19
+ details;
20
+ constructor(message, url, httpStatus, details = {}, options) {
21
+ super(message, options);
22
+ this.url = url;
23
+ this.name = 'FetchError';
24
+ this.statusCode = httpStatus ?? DEFAULT_HTTP_STATUS;
25
+ this.details = Object.freeze({ url, httpStatus, ...details });
26
+ const explicitCode = this.details['code'];
27
+ if (typeof explicitCode === 'string') {
28
+ this.code = explicitCode;
29
+ }
30
+ else if (httpStatus) {
31
+ this.code = `HTTP_${httpStatus}`;
32
+ }
33
+ else {
34
+ this.code = SystemErrors.FETCH_ERROR;
35
+ }
36
+ }
37
+ }
38
+ export class CodedError extends Error {
39
+ code;
40
+ constructor(message, code, options) {
41
+ super(message, options);
42
+ this.code = code;
43
+ this.name = 'CodedError';
44
+ }
45
+ }
46
+ // ── Error guards ───────────────────────────────────────────────────
47
+ export function isAbortError(error) {
48
+ return isError(error) && error.name === 'AbortError';
49
+ }
50
+ export function isSystemError(error) {
51
+ if (!isError(error))
52
+ return false;
53
+ if (!('code' in error))
54
+ return false;
55
+ const { code } = error;
56
+ return typeof code === 'string';
57
+ }
58
+ // ── Error extraction ───────────────────────────────────────────────
59
+ const UNKNOWN_ERROR_MESSAGE = 'Unknown error';
60
+ export function getErrorMessage(error) {
61
+ if (isError(error))
62
+ return error.message;
63
+ if (typeof error === 'string' && error.length > 0)
64
+ return error;
65
+ if (isObject(error) &&
66
+ typeof error['message'] === 'string' &&
67
+ error['message'].length > 0) {
68
+ return error['message'];
69
+ }
70
+ if (error === null || error === undefined)
71
+ return UNKNOWN_ERROR_MESSAGE;
72
+ try {
73
+ return inspect(error, {
74
+ depth: 2,
75
+ maxStringLength: 200,
76
+ breakLength: Infinity,
77
+ compact: true,
78
+ colors: false,
79
+ });
80
+ }
81
+ catch {
82
+ return UNKNOWN_ERROR_MESSAGE;
83
+ }
84
+ }
85
+ export function toError(error) {
86
+ return isError(error) ? error : new Error(getErrorMessage(error));
87
+ }
88
+ // ── Abort helpers ──────────────────────────────────────────────────
89
+ export function throwIfAborted(signal, url, stage) {
90
+ if (!signal?.aborted)
91
+ return;
92
+ if (signal.reason instanceof Error && signal.reason.name === 'TimeoutError') {
93
+ const error = new FetchError('Request timeout', url, 504, {
94
+ reason: 'timeout',
95
+ stage,
96
+ });
97
+ throw error;
98
+ }
99
+ throw createAbortError(url, stage);
100
+ }
101
+ export function createAbortError(url, stage) {
102
+ const error = new FetchError('Request was canceled', url, 499, {
103
+ reason: 'aborted',
104
+ stage,
105
+ });
106
+ return error;
107
+ }
@@ -0,0 +1,4 @@
1
+ import { type ToolErrorLogMeta, type ToolErrorResponse } from './payload.js';
2
+ export declare function handleToolError(error: unknown, url: string, fallbackMessage?: string): ToolErrorResponse;
3
+ export declare function classifyAndLogToolError(error: unknown, meta: ToolErrorLogMeta, loggerName: string, toolName: string, fallbackMessage: string): ToolErrorResponse;
4
+ //# sourceMappingURL=classify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../../src/lib/error/classify.ts"],"names":[],"mappings":"AAKA,OAAO,EAIL,KAAK,gBAAgB,EAErB,KAAK,iBAAiB,EACvB,MAAM,cAAc,CAAC;AA4JtB,wBAAgB,eAAe,CAC7B,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,MAAM,EACX,eAAe,SAAqB,GACnC,iBAAiB,CAInB;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,gBAAgB,EACtB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,GACtB,iBAAiB,CAuCnB"}
@@ -0,0 +1,154 @@
1
+ import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
2
+ import { logError, logWarn } from '../core.js';
3
+ import { FetchError, isAbortError, isSystemError } from './classes.js';
4
+ import { ErrorCategory, SystemErrors } from './codes.js';
5
+ import { createToolErrorResponse, sanitizeToolErrorDetails, stripMcpErrorPrefix, } from './payload.js';
6
+ function toToolErrorResponse(payload) {
7
+ return createToolErrorResponse(payload.error, payload.url, payload);
8
+ }
9
+ function isValidationError(error) {
10
+ return (error instanceof Error &&
11
+ isSystemError(error) &&
12
+ error.code === SystemErrors.VALIDATION_ERROR);
13
+ }
14
+ function buildUpstreamHttpMessage(error) {
15
+ const { statusCode } = error;
16
+ if (statusCode === 404) {
17
+ return `We couldn't find the resource at the target URL.`;
18
+ }
19
+ return `An error occurred when communicating with the target URL.`;
20
+ }
21
+ function mapFetchToolError(error, fallbackUrl) {
22
+ const { code: detailsCode, reason } = error.details;
23
+ let { code } = error;
24
+ if (typeof detailsCode === 'string') {
25
+ code = detailsCode;
26
+ }
27
+ else if (reason === SystemErrors.QUEUE_FULL) {
28
+ code = SystemErrors.QUEUE_FULL;
29
+ }
30
+ const url = error.url || fallbackUrl;
31
+ const details = sanitizeToolErrorDetails(error.details);
32
+ if (reason === 'timeout') {
33
+ return {
34
+ error: 'The request to the target timed out.',
35
+ url,
36
+ category: ErrorCategory.UPSTREAM_TIMEOUT,
37
+ code,
38
+ statusCode: error.statusCode,
39
+ upstreamMessage: error.message,
40
+ ...(details ? { details } : {}),
41
+ };
42
+ }
43
+ if (reason === 'aborted') {
44
+ return {
45
+ error: 'The request to the target was cancelled.',
46
+ url,
47
+ category: ErrorCategory.UPSTREAM_ABORTED,
48
+ code,
49
+ statusCode: error.statusCode,
50
+ upstreamMessage: error.message,
51
+ ...(details ? { details } : {}),
52
+ };
53
+ }
54
+ if (reason === SystemErrors.QUEUE_FULL) {
55
+ return {
56
+ error: error.message,
57
+ url,
58
+ category: ErrorCategory.QUEUE_FULL,
59
+ code,
60
+ statusCode: error.statusCode,
61
+ ...(details ? { details } : {}),
62
+ };
63
+ }
64
+ const isRealHttpError = typeof error.details['httpStatus'] === 'number';
65
+ if (isRealHttpError && error.statusCode >= 400) {
66
+ return {
67
+ error: buildUpstreamHttpMessage(error),
68
+ url,
69
+ category: error.statusCode === 429
70
+ ? ErrorCategory.UPSTREAM_RATE_LIMITED
71
+ : ErrorCategory.UPSTREAM_HTTP_ERROR,
72
+ code,
73
+ statusCode: error.statusCode,
74
+ upstreamMessage: error.message,
75
+ ...(details ? { details } : {}),
76
+ };
77
+ }
78
+ return {
79
+ error: error.message,
80
+ url,
81
+ category: ErrorCategory.FETCH_ERROR,
82
+ code,
83
+ statusCode: error.statusCode,
84
+ ...(details ? { details } : {}),
85
+ };
86
+ }
87
+ function mapGenericToolError(error, url, fallbackMessage) {
88
+ if (isValidationError(error)) {
89
+ return {
90
+ error: error.message,
91
+ url,
92
+ category: ErrorCategory.VALIDATION_ERROR,
93
+ code: SystemErrors.VALIDATION_ERROR,
94
+ };
95
+ }
96
+ const isAborted = isAbortError(error);
97
+ return {
98
+ error: error instanceof Error
99
+ ? error.message
100
+ : `${fallbackMessage}: unknown error`,
101
+ url,
102
+ category: isAborted
103
+ ? ErrorCategory.UPSTREAM_ABORTED
104
+ : ErrorCategory.FETCH_ERROR,
105
+ code: isAborted ? SystemErrors.ABORTED : SystemErrors.FETCH_ERROR,
106
+ };
107
+ }
108
+ function mapMcpToolError(error, url) {
109
+ return {
110
+ error: stripMcpErrorPrefix(error.message),
111
+ url,
112
+ category: ErrorCategory.MCP_ERROR,
113
+ code: error.code,
114
+ statusCode: error.code,
115
+ ...(error.data !== undefined ? { data: error.data } : {}),
116
+ };
117
+ }
118
+ function resolveToolErrorPayload(error, url, fallbackMessage) {
119
+ if (error instanceof FetchError) {
120
+ return mapFetchToolError(error, url);
121
+ }
122
+ if (error instanceof McpError) {
123
+ return mapMcpToolError(error, url);
124
+ }
125
+ return mapGenericToolError(error, url, fallbackMessage);
126
+ }
127
+ export function handleToolError(error, url, fallbackMessage = 'Operation failed') {
128
+ return toToolErrorResponse(resolveToolErrorPayload(error, url, fallbackMessage));
129
+ }
130
+ export function classifyAndLogToolError(error, meta, loggerName, toolName, fallbackMessage) {
131
+ if (error instanceof McpError) {
132
+ if (error.code === ErrorCode.MethodNotFound) {
133
+ logError(`${toolName} tool protocol error`, { url: meta.url, durationMs: meta.durationMs, error }, loggerName);
134
+ throw error;
135
+ }
136
+ logWarn(`${toolName} tool error`, { url: meta.url, durationMs: meta.durationMs, error }, loggerName);
137
+ return handleToolError(error, meta.url, fallbackMessage);
138
+ }
139
+ if (error instanceof FetchError || isAbortError(error)) {
140
+ logWarn(`${toolName} request failed`, {
141
+ url: meta.url,
142
+ error: error instanceof Error ? error.message : String(error),
143
+ durationMs: meta.durationMs,
144
+ }, loggerName);
145
+ }
146
+ else {
147
+ logError(`${toolName} request failed unexpectedly`, {
148
+ url: meta.url,
149
+ error: error instanceof Error ? error.message : String(error),
150
+ durationMs: meta.durationMs,
151
+ }, loggerName);
152
+ }
153
+ return handleToolError(error, meta.url, fallbackMessage);
154
+ }
@@ -0,0 +1,23 @@
1
+ export declare const SystemErrors: {
2
+ readonly EBLOCKED: "EBLOCKED";
3
+ readonly ETIMEOUT: "ETIMEOUT";
4
+ readonly EINVAL: "EINVAL";
5
+ readonly ENODATA: "ENODATA";
6
+ readonly EBADREDIRECT: "EBADREDIRECT";
7
+ readonly EUNSUPPORTEDPROTOCOL: "EUNSUPPORTEDPROTOCOL";
8
+ readonly FETCH_ERROR: "FETCH_ERROR";
9
+ readonly ABORTED: "ABORTED";
10
+ readonly QUEUE_FULL: "queue_full";
11
+ readonly VALIDATION_ERROR: "VALIDATION_ERROR";
12
+ };
13
+ export declare const ErrorCategory: {
14
+ readonly UPSTREAM_TIMEOUT: "upstream_timeout";
15
+ readonly UPSTREAM_ABORTED: "upstream_aborted";
16
+ readonly UPSTREAM_RATE_LIMITED: "upstream_rate_limited";
17
+ readonly UPSTREAM_HTTP_ERROR: "upstream_http_error";
18
+ readonly QUEUE_FULL: "queue_full";
19
+ readonly FETCH_ERROR: "fetch_error";
20
+ readonly VALIDATION_ERROR: "validation_error";
21
+ readonly MCP_ERROR: "mcp_error";
22
+ };
23
+ //# sourceMappingURL=codes.d.ts.map