Skip to content

Commit 3613bc0

Browse files
chipgptmattzcarey
authored andcommitted
use z.input type
1 parent 67988c2 commit 3613bc0

File tree

2 files changed

+43
-30
lines changed

2 files changed

+43
-30
lines changed

src/client/index.ts

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ import {
4444
CreateMessageRequestSchema,
4545
CreateMessageResultSchema
4646
ToolListChangedNotificationSchema,
47-
ToolListChangedOptions
47+
ToolListChangedOptions,
48+
ToolListChangedOptionsSchema
4849
} from '../types.js';
4950
import { AjvJsonSchemaValidator } from '../validation/ajv-provider.js';
5051
import type { JsonSchemaType, JsonSchemaValidator, jsonSchemaValidator } from '../validation/types.js';
@@ -169,11 +170,11 @@ export type ClientOptions = ProtocolOptions & {
169170
/**
170171
* Configure automatic refresh behavior for tool list changed notifications
171172
*
173+
* Here's an example of how to get the updated tool list when the tool list changed notification is received:
174+
*
172175
* @example
173-
* ```ts
176+
* ```typescript
174177
* {
175-
* autoRefresh: true,
176-
* debounceMs: 300,
177178
* onToolListChanged: (err, tools) => {
178179
* if (err) {
179180
* console.error('Failed to refresh tool list:', err);
@@ -185,10 +186,13 @@ export type ClientOptions = ProtocolOptions & {
185186
* }
186187
* ```
187188
*
189+
* Here is an example of how to manually refresh the tool list when the tool list changed notification is received:
190+
*
188191
* @example
189-
* ```ts
192+
* ```typescript
190193
* {
191194
* autoRefresh: false,
195+
* debounceMs: 0,
192196
* onToolListChanged: (err, tools) => {
193197
* // err is always null when autoRefresh is false
194198
*
@@ -807,36 +811,45 @@ export class Client<
807811
public setToolListChangedOptions(options: ToolListChangedOptions | null): void {
808812
// Set up tool list changed options and add notification handler
809813
if (options) {
810-
const toolListChangedOptions: ToolListChangedOptions = {
811-
autoRefresh: !!options.autoRefresh,
812-
debounceMs: options.debounceMs ?? 300,
813-
onToolListChanged: options.onToolListChanged
814-
};
814+
const parseResult = ToolListChangedOptionsSchema.safeParse(options);
815+
if (parseResult.error) {
816+
throw new Error(`Tool List Changed options are invalid: ${parseResult.error.message}`);
817+
}
818+
819+
const toolListChangedOptions = parseResult.data;
815820
this._toolListChangedOptions = toolListChangedOptions;
821+
822+
const refreshToolList = async () => {
823+
let tools: Tool[] | null = null;
824+
let error: Error | null = null;
825+
try {
826+
const result = await this.listTools();
827+
tools = result.tools;
828+
} catch (e) {
829+
error = e instanceof Error ? e : new Error(String(e));
830+
}
831+
toolListChangedOptions.onToolListChanged?.(error, tools);
832+
};
833+
816834
this.setNotificationHandler(ToolListChangedNotificationSchema, () => {
817835
// If autoRefresh is false, call the callback for the notification, but without tools data
818836
if (!toolListChangedOptions.autoRefresh) {
819837
toolListChangedOptions.onToolListChanged?.(null, null);
820838
return;
821839
}
822840

823-
// Clear any pending debounce timer
824-
if (this._toolListChangedDebounceTimer) {
825-
clearTimeout(this._toolListChangedDebounceTimer);
826-
}
827-
828-
// Set up debounced refresh
829-
this._toolListChangedDebounceTimer = setTimeout(async () => {
830-
let tools: Tool[] | null = null;
831-
let error: Error | null = null;
832-
try {
833-
const result = await this.listTools();
834-
tools = result.tools;
835-
} catch (e) {
836-
error = e instanceof Error ? e : new Error(String(e));
841+
if (toolListChangedOptions.debounceMs) {
842+
// Clear any pending debounce timer
843+
if (this._toolListChangedDebounceTimer) {
844+
clearTimeout(this._toolListChangedDebounceTimer);
837845
}
838-
toolListChangedOptions.onToolListChanged?.(error, tools);
839-
}, toolListChangedOptions.debounceMs);
846+
847+
// Set up debounced refresh
848+
this._toolListChangedDebounceTimer = setTimeout(refreshToolList, toolListChangedOptions.debounceMs);
849+
} else {
850+
// No debounce, refresh immediately
851+
refreshToolList();
852+
}
840853
});
841854
}
842855
// Reset tool list changed options and remove notification handler

src/types.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1390,17 +1390,17 @@ export const ToolListChangedOptionsSchema = z.object({
13901390
*
13911391
* If `onToolListChanged` is also provided, it will be called after the tool list is auto refreshed.
13921392
*
1393-
* @default false
1393+
* @default true
13941394
*/
1395-
autoRefresh: z.boolean().optional(),
1395+
autoRefresh: z.boolean().default(true),
13961396
/**
13971397
* Debounce time in milliseconds for tool list changed notification processing.
13981398
*
13991399
* Multiple notifications received within this timeframe will only trigger one refresh.
14001400
*
14011401
* @default 300
14021402
*/
1403-
debounceMs: z.number().int().optional(),
1403+
debounceMs: z.number().int().default(300),
14041404
/**
14051405
* This callback is always called when the server sends a tool list changed notification.
14061406
*
@@ -1409,7 +1409,7 @@ export const ToolListChangedOptionsSchema = z.object({
14091409
onToolListChanged: z.function(z.tuple([z.instanceof(Error).nullable(), z.array(ToolSchema).nullable()]), z.void())
14101410
});
14111411

1412-
export type ToolListChangedOptions = z.infer<typeof ToolListChangedOptionsSchema>;
1412+
export type ToolListChangedOptions = z.input<typeof ToolListChangedOptionsSchema>;
14131413

14141414
/* Logging */
14151415
/**

0 commit comments

Comments
 (0)