@j0hanz/superfetch 2.4.2 → 2.4.4
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/cache.d.ts +9 -4
- package/dist/cache.js +279 -276
- package/dist/crypto.js +4 -3
- package/dist/dom-noise-removal.js +355 -297
- package/dist/fetch.d.ts +13 -7
- package/dist/fetch.js +636 -690
- package/dist/http-native.js +535 -474
- package/dist/instructions.md +38 -27
- package/dist/language-detection.js +190 -153
- package/dist/markdown-cleanup.js +171 -158
- package/dist/mcp.js +174 -14
- package/dist/resources.d.ts +2 -0
- package/dist/resources.js +44 -0
- package/dist/session.js +144 -105
- package/dist/tasks.d.ts +37 -0
- package/dist/tasks.js +66 -0
- package/dist/tools.d.ts +8 -10
- package/dist/tools.js +168 -148
- package/dist/transform.d.ts +3 -1
- package/dist/transform.js +680 -778
- package/package.json +6 -6
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { config } from './config.js';
|
|
3
|
+
import { stableStringify } from './json.js';
|
|
4
|
+
/* -------------------------------------------------------------------------------------------------
|
|
5
|
+
* Configuration Resource
|
|
6
|
+
* ------------------------------------------------------------------------------------------------- */
|
|
7
|
+
function scrubAuth(auth) {
|
|
8
|
+
return {
|
|
9
|
+
...auth,
|
|
10
|
+
clientSecret: auth.clientSecret ? '<REDACTED>' : undefined,
|
|
11
|
+
staticTokens: auth.staticTokens.map(() => '<REDACTED>'),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function scrubSecurity(security) {
|
|
15
|
+
return {
|
|
16
|
+
...security,
|
|
17
|
+
apiKey: security.apiKey ? '<REDACTED>' : undefined,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function scrubConfig(source) {
|
|
21
|
+
return {
|
|
22
|
+
...source,
|
|
23
|
+
auth: scrubAuth(source.auth),
|
|
24
|
+
security: scrubSecurity(source.security),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export function registerConfigResource(server) {
|
|
28
|
+
server.registerResource('config', new ResourceTemplate('internal://config', { list: undefined }), {
|
|
29
|
+
title: 'Server Configuration',
|
|
30
|
+
description: 'Current runtime configuration (secrets redacted)',
|
|
31
|
+
mimeType: 'application/json',
|
|
32
|
+
}, (uri) => {
|
|
33
|
+
const scrubbed = scrubConfig(config);
|
|
34
|
+
return {
|
|
35
|
+
contents: [
|
|
36
|
+
{
|
|
37
|
+
uri: uri.href,
|
|
38
|
+
mimeType: 'application/json',
|
|
39
|
+
text: stableStringify(scrubbed),
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
}
|
package/dist/session.js
CHANGED
|
@@ -14,128 +14,163 @@ export function composeCloseHandlers(first, second) {
|
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
/* -------------------------------------------------------------------------------------------------
|
|
18
|
+
* Cleanup loop
|
|
19
|
+
* ------------------------------------------------------------------------------------------------- */
|
|
18
20
|
function getCleanupIntervalMs(sessionTtlMs) {
|
|
19
|
-
return Math.min(Math.max(Math.floor(sessionTtlMs / 2),
|
|
21
|
+
return Math.min(Math.max(Math.floor(sessionTtlMs / 2), 10_000), 60_000);
|
|
20
22
|
}
|
|
21
23
|
function isAbortError(error) {
|
|
22
24
|
return error instanceof Error && error.name === 'AbortError';
|
|
23
25
|
}
|
|
24
26
|
function handleSessionCleanupError(error) {
|
|
25
|
-
if (isAbortError(error))
|
|
27
|
+
if (isAbortError(error))
|
|
26
28
|
return;
|
|
27
|
-
}
|
|
28
29
|
logWarn('Session cleanup loop failed', {
|
|
29
30
|
error: error instanceof Error ? error.message : 'Unknown error',
|
|
30
31
|
});
|
|
31
32
|
}
|
|
32
|
-
function moveSessionToEnd(sessions, sessionId, session) {
|
|
33
|
-
sessions.delete(sessionId);
|
|
34
|
-
sessions.set(sessionId, session);
|
|
35
|
-
}
|
|
36
33
|
function isSessionExpired(session, now, sessionTtlMs) {
|
|
37
34
|
return now - session.lastSeen > sessionTtlMs;
|
|
38
35
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
36
|
+
class SessionCleanupLoop {
|
|
37
|
+
store;
|
|
38
|
+
sessionTtlMs;
|
|
39
|
+
constructor(store, sessionTtlMs) {
|
|
40
|
+
this.store = store;
|
|
41
|
+
this.sessionTtlMs = sessionTtlMs;
|
|
42
|
+
}
|
|
43
|
+
start() {
|
|
44
|
+
const controller = new AbortController();
|
|
45
|
+
void this.run(controller.signal).catch(handleSessionCleanupError);
|
|
46
|
+
return controller;
|
|
47
|
+
}
|
|
48
|
+
async run(signal) {
|
|
49
|
+
const intervalMs = getCleanupIntervalMs(this.sessionTtlMs);
|
|
50
|
+
for await (const getNow of setIntervalPromise(intervalMs, Date.now, {
|
|
51
|
+
signal,
|
|
52
|
+
ref: false,
|
|
53
|
+
})) {
|
|
54
|
+
const now = getNow();
|
|
55
|
+
const evicted = this.store.evictExpired();
|
|
56
|
+
for (const session of evicted) {
|
|
57
|
+
void session.transport.close().catch((err) => {
|
|
58
|
+
logWarn('Failed to close expired session', {
|
|
59
|
+
error: err instanceof Error ? err : new Error(String(err)),
|
|
60
|
+
});
|
|
50
61
|
});
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
62
|
+
}
|
|
63
|
+
if (evicted.length > 0) {
|
|
64
|
+
logInfo('Expired sessions evicted', {
|
|
65
|
+
evicted: evicted.length,
|
|
66
|
+
timestamp: new Date(now).toISOString(),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
58
69
|
}
|
|
59
70
|
}
|
|
60
71
|
}
|
|
61
72
|
export function startSessionCleanupLoop(store, sessionTtlMs) {
|
|
62
|
-
|
|
63
|
-
void runSessionCleanupLoop(store, sessionTtlMs, controller.signal).catch(handleSessionCleanupError);
|
|
64
|
-
return controller;
|
|
73
|
+
return new SessionCleanupLoop(store, sessionTtlMs).start();
|
|
65
74
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
75
|
+
/* -------------------------------------------------------------------------------------------------
|
|
76
|
+
* Session store (in-memory, Map order used for LRU)
|
|
77
|
+
* ------------------------------------------------------------------------------------------------- */
|
|
78
|
+
function moveSessionToEnd(sessions, sessionId, session) {
|
|
79
|
+
sessions.delete(sessionId);
|
|
80
|
+
sessions.set(sessionId, session);
|
|
81
|
+
}
|
|
82
|
+
class InMemorySessionStore {
|
|
83
|
+
sessionTtlMs;
|
|
84
|
+
sessions = new Map();
|
|
85
|
+
inflight = 0;
|
|
86
|
+
constructor(sessionTtlMs) {
|
|
87
|
+
this.sessionTtlMs = sessionTtlMs;
|
|
88
|
+
}
|
|
89
|
+
get(sessionId) {
|
|
90
|
+
return this.sessions.get(sessionId);
|
|
91
|
+
}
|
|
92
|
+
touch(sessionId) {
|
|
93
|
+
const session = this.sessions.get(sessionId);
|
|
94
|
+
if (!session)
|
|
95
|
+
return;
|
|
96
|
+
session.lastSeen = Date.now();
|
|
97
|
+
moveSessionToEnd(this.sessions, sessionId, session);
|
|
98
|
+
}
|
|
99
|
+
set(sessionId, entry) {
|
|
100
|
+
this.sessions.set(sessionId, entry);
|
|
101
|
+
}
|
|
102
|
+
remove(sessionId) {
|
|
103
|
+
const session = this.sessions.get(sessionId);
|
|
104
|
+
this.sessions.delete(sessionId);
|
|
105
|
+
return session;
|
|
106
|
+
}
|
|
107
|
+
size() {
|
|
108
|
+
return this.sessions.size;
|
|
109
|
+
}
|
|
110
|
+
inFlight() {
|
|
111
|
+
return this.inflight;
|
|
112
|
+
}
|
|
113
|
+
incrementInFlight() {
|
|
114
|
+
this.inflight += 1;
|
|
115
|
+
}
|
|
116
|
+
decrementInFlight() {
|
|
117
|
+
if (this.inflight > 0)
|
|
118
|
+
this.inflight -= 1;
|
|
119
|
+
}
|
|
120
|
+
clear() {
|
|
121
|
+
const entries = [...this.sessions.values()];
|
|
122
|
+
this.sessions.clear();
|
|
123
|
+
return entries;
|
|
124
|
+
}
|
|
125
|
+
evictExpired() {
|
|
126
|
+
const now = Date.now();
|
|
127
|
+
const evicted = [];
|
|
128
|
+
for (const [id, session] of this.sessions.entries()) {
|
|
129
|
+
if (isSessionExpired(session, now, this.sessionTtlMs)) {
|
|
130
|
+
this.sessions.delete(id);
|
|
131
|
+
evicted.push(session);
|
|
109
132
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
133
|
+
}
|
|
134
|
+
return evicted;
|
|
135
|
+
}
|
|
136
|
+
evictOldest() {
|
|
137
|
+
const oldest = this.sessions.keys().next();
|
|
138
|
+
if (oldest.done)
|
|
139
|
+
return undefined;
|
|
140
|
+
const oldestId = oldest.value;
|
|
141
|
+
const session = this.sessions.get(oldestId);
|
|
142
|
+
this.sessions.delete(oldestId);
|
|
143
|
+
return session;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
export function createSessionStore(sessionTtlMs) {
|
|
147
|
+
return new InMemorySessionStore(sessionTtlMs);
|
|
148
|
+
}
|
|
149
|
+
/* -------------------------------------------------------------------------------------------------
|
|
150
|
+
* Slot tracker
|
|
151
|
+
* ------------------------------------------------------------------------------------------------- */
|
|
152
|
+
class SessionSlotTracker {
|
|
153
|
+
store;
|
|
154
|
+
slotReleased = false;
|
|
155
|
+
initialized = false;
|
|
156
|
+
constructor(store) {
|
|
157
|
+
this.store = store;
|
|
158
|
+
}
|
|
159
|
+
releaseSlot() {
|
|
160
|
+
if (this.slotReleased)
|
|
161
|
+
return;
|
|
162
|
+
this.slotReleased = true;
|
|
163
|
+
this.store.decrementInFlight();
|
|
164
|
+
}
|
|
165
|
+
markInitialized() {
|
|
166
|
+
this.initialized = true;
|
|
167
|
+
}
|
|
168
|
+
isInitialized() {
|
|
169
|
+
return this.initialized;
|
|
170
|
+
}
|
|
122
171
|
}
|
|
123
|
-
// --- Slot Tracker ---
|
|
124
172
|
export function createSlotTracker(store) {
|
|
125
|
-
|
|
126
|
-
let initialized = false;
|
|
127
|
-
return {
|
|
128
|
-
releaseSlot: () => {
|
|
129
|
-
if (slotReleased)
|
|
130
|
-
return;
|
|
131
|
-
slotReleased = true;
|
|
132
|
-
store.decrementInFlight();
|
|
133
|
-
},
|
|
134
|
-
markInitialized: () => {
|
|
135
|
-
initialized = true;
|
|
136
|
-
},
|
|
137
|
-
isInitialized: () => initialized,
|
|
138
|
-
};
|
|
173
|
+
return new SessionSlotTracker(store);
|
|
139
174
|
}
|
|
140
175
|
export function reserveSessionSlot(store, maxSessions) {
|
|
141
176
|
if (store.size() + store.inFlight() >= maxSessions) {
|
|
@@ -144,16 +179,20 @@ export function reserveSessionSlot(store, maxSessions) {
|
|
|
144
179
|
store.incrementInFlight();
|
|
145
180
|
return true;
|
|
146
181
|
}
|
|
182
|
+
/* -------------------------------------------------------------------------------------------------
|
|
183
|
+
* Capacity policy
|
|
184
|
+
* ------------------------------------------------------------------------------------------------- */
|
|
185
|
+
function isAtCapacity(store, maxSessions) {
|
|
186
|
+
return store.size() + store.inFlight() >= maxSessions;
|
|
187
|
+
}
|
|
147
188
|
export function ensureSessionCapacity({ store, maxSessions, evictOldest, }) {
|
|
148
189
|
const currentSize = store.size();
|
|
149
|
-
const
|
|
150
|
-
if (
|
|
190
|
+
const inflight = store.inFlight();
|
|
191
|
+
if (currentSize + inflight < maxSessions)
|
|
151
192
|
return true;
|
|
152
|
-
|
|
153
|
-
const canFreeSlot = currentSize >= maxSessions &&
|
|
154
|
-
currentSize - 1 + store.inFlight() < maxSessions;
|
|
193
|
+
const canFreeSlot = currentSize >= maxSessions && currentSize - 1 + inflight < maxSessions;
|
|
155
194
|
if (canFreeSlot && evictOldest(store)) {
|
|
156
|
-
return
|
|
195
|
+
return !isAtCapacity(store, maxSessions);
|
|
157
196
|
}
|
|
158
197
|
return false;
|
|
159
198
|
}
|
package/dist/tasks.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type TaskStatus = 'working' | 'input_required' | 'completed' | 'failed' | 'cancelled';
|
|
2
|
+
export interface TaskState {
|
|
3
|
+
taskId: string;
|
|
4
|
+
status: TaskStatus;
|
|
5
|
+
statusMessage?: string;
|
|
6
|
+
createdAt: string;
|
|
7
|
+
lastUpdatedAt: string;
|
|
8
|
+
ttl: number;
|
|
9
|
+
pollInterval: number;
|
|
10
|
+
result?: unknown;
|
|
11
|
+
error?: unknown;
|
|
12
|
+
}
|
|
13
|
+
export interface CreateTaskOptions {
|
|
14
|
+
ttl?: number;
|
|
15
|
+
}
|
|
16
|
+
export interface CreateTaskResult {
|
|
17
|
+
task: {
|
|
18
|
+
taskId: string;
|
|
19
|
+
status: TaskStatus;
|
|
20
|
+
statusMessage?: string;
|
|
21
|
+
createdAt: string;
|
|
22
|
+
lastUpdatedAt: string;
|
|
23
|
+
ttl: number;
|
|
24
|
+
pollInterval: number;
|
|
25
|
+
};
|
|
26
|
+
_meta?: Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
export declare class TaskManager {
|
|
29
|
+
private tasks;
|
|
30
|
+
createTask(options?: CreateTaskOptions, statusMessage?: string): TaskState;
|
|
31
|
+
getTask(taskId: string): TaskState | undefined;
|
|
32
|
+
updateTask(taskId: string, updates: Partial<Omit<TaskState, 'taskId' | 'createdAt'>>): void;
|
|
33
|
+
cancelTask(taskId: string): TaskState | undefined;
|
|
34
|
+
listTasks(): TaskState[];
|
|
35
|
+
cleanupExpiredTasks(): number;
|
|
36
|
+
}
|
|
37
|
+
export declare const taskManager: TaskManager;
|
package/dist/tasks.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
const DEFAULT_TTL_MS = 60000;
|
|
3
|
+
const DEFAULT_POLL_INTERVAL_MS = 1000;
|
|
4
|
+
export class TaskManager {
|
|
5
|
+
tasks = new Map();
|
|
6
|
+
createTask(options, statusMessage = 'Task started') {
|
|
7
|
+
const taskId = randomUUID();
|
|
8
|
+
const now = new Date().toISOString();
|
|
9
|
+
const task = {
|
|
10
|
+
taskId,
|
|
11
|
+
status: 'working',
|
|
12
|
+
statusMessage,
|
|
13
|
+
createdAt: now,
|
|
14
|
+
lastUpdatedAt: now,
|
|
15
|
+
ttl: options?.ttl ?? DEFAULT_TTL_MS,
|
|
16
|
+
pollInterval: DEFAULT_POLL_INTERVAL_MS,
|
|
17
|
+
};
|
|
18
|
+
this.tasks.set(taskId, task);
|
|
19
|
+
return task;
|
|
20
|
+
}
|
|
21
|
+
getTask(taskId) {
|
|
22
|
+
return this.tasks.get(taskId);
|
|
23
|
+
}
|
|
24
|
+
updateTask(taskId, updates) {
|
|
25
|
+
const task = this.tasks.get(taskId);
|
|
26
|
+
if (!task)
|
|
27
|
+
return;
|
|
28
|
+
Object.assign(task, {
|
|
29
|
+
...updates,
|
|
30
|
+
lastUpdatedAt: new Date().toISOString(),
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
cancelTask(taskId) {
|
|
34
|
+
const task = this.tasks.get(taskId);
|
|
35
|
+
if (!task)
|
|
36
|
+
return undefined;
|
|
37
|
+
if (task.status === 'completed' ||
|
|
38
|
+
task.status === 'failed' ||
|
|
39
|
+
task.status === 'cancelled') {
|
|
40
|
+
throw new Error(`Cannot cancel task: already in terminal status '${task.status}'`);
|
|
41
|
+
}
|
|
42
|
+
this.updateTask(taskId, {
|
|
43
|
+
status: 'cancelled',
|
|
44
|
+
statusMessage: 'The task was cancelled by request.',
|
|
45
|
+
});
|
|
46
|
+
return this.tasks.get(taskId);
|
|
47
|
+
}
|
|
48
|
+
listTasks() {
|
|
49
|
+
return Array.from(this.tasks.values());
|
|
50
|
+
}
|
|
51
|
+
// Helper to check if task is expired and could be cleaned up
|
|
52
|
+
// In a real implementation, this would be called by a periodic job
|
|
53
|
+
cleanupExpiredTasks() {
|
|
54
|
+
const now = Date.now();
|
|
55
|
+
let count = 0;
|
|
56
|
+
for (const [id, task] of this.tasks.entries()) {
|
|
57
|
+
const created = new Date(task.createdAt).getTime();
|
|
58
|
+
if (now - created > task.ttl) {
|
|
59
|
+
this.tasks.delete(id);
|
|
60
|
+
count++;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return count;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export const taskManager = new TaskManager();
|
package/dist/tools.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import type { CallToolResult, ContentBlock } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
import * as cache from './cache.js';
|
|
3
4
|
import type { MarkdownTransformResult } from './transform-types.js';
|
|
4
5
|
export interface FetchUrlInput {
|
|
5
6
|
url: string;
|
|
@@ -34,19 +35,12 @@ export type ToolErrorResponse = CallToolResult & {
|
|
|
34
35
|
};
|
|
35
36
|
export type ToolResponseBase = CallToolResult;
|
|
36
37
|
export interface FetchPipelineOptions<T> {
|
|
37
|
-
/** URL to fetch */
|
|
38
38
|
url: string;
|
|
39
|
-
/** Cache namespace (e.g., 'markdown') */
|
|
40
39
|
cacheNamespace: string;
|
|
41
|
-
/** Optional: AbortSignal for request cancellation */
|
|
42
40
|
signal?: AbortSignal;
|
|
43
|
-
/** Optional: cache variation input for headers/flags */
|
|
44
41
|
cacheVary?: Record<string, unknown> | string;
|
|
45
|
-
/** Transform function to process HTML into desired format */
|
|
46
42
|
transform: (html: string, url: string) => T | Promise<T>;
|
|
47
|
-
/** Optional: serialize result for caching (defaults to JSON.stringify) */
|
|
48
43
|
serialize?: (result: T) => string;
|
|
49
|
-
/** Optional: deserialize cached content */
|
|
50
44
|
deserialize?: (cached: string) => T | undefined;
|
|
51
45
|
}
|
|
52
46
|
export interface PipelineResult<T> {
|
|
@@ -92,8 +86,12 @@ interface InlineContentResult {
|
|
|
92
86
|
error?: string;
|
|
93
87
|
truncated?: boolean;
|
|
94
88
|
}
|
|
95
|
-
|
|
96
|
-
|
|
89
|
+
export type InlineResult = ReturnType<InlineContentLimiter['apply']>;
|
|
90
|
+
declare class InlineContentLimiter {
|
|
91
|
+
apply(content: string, cacheKey: string | null): InlineContentResult;
|
|
92
|
+
private resolveResourceUri;
|
|
93
|
+
private buildTruncatedFallback;
|
|
94
|
+
}
|
|
97
95
|
export declare function executeFetchPipeline<T>(options: FetchPipelineOptions<T>): Promise<PipelineResult<T>>;
|
|
98
96
|
interface SharedFetchOptions<T extends {
|
|
99
97
|
content: string;
|
|
@@ -121,5 +119,5 @@ type MarkdownPipelineResult = MarkdownTransformResult & {
|
|
|
121
119
|
export declare function parseCachedMarkdownResult(cached: string): MarkdownPipelineResult | undefined;
|
|
122
120
|
export declare function fetchUrlToolHandler(input: FetchUrlInput, extra?: ToolHandlerExtra): Promise<ToolResponseBase>;
|
|
123
121
|
export declare function withRequestContextIfMissing<TParams, TResult, TExtra = unknown>(handler: (params: TParams, extra?: TExtra) => Promise<TResult>): (params: TParams, extra?: TExtra) => Promise<TResult>;
|
|
124
|
-
export declare function registerTools(server: McpServer,
|
|
122
|
+
export declare function registerTools(server: McpServer, serverIcons?: cache.McpIcon[]): void;
|
|
125
123
|
export {};
|