Skip to content

Commit a4de0df

Browse files
committed
fix: keep related request id zero from debouncing
1 parent 4f226c1 commit a4de0df

3 files changed

Lines changed: 21 additions & 1 deletion

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@modelcontextprotocol/core': patch
3+
---
4+
5+
Treat numeric related request ID `0` as present when deciding whether a notification can be debounced.

packages/core/src/shared/protocol.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1009,8 +1009,9 @@ export abstract class Protocol<ContextT extends BaseContext> {
10091009
const debouncedMethods = this._options?.debouncedNotificationMethods ?? [];
10101010
// A notification can only be debounced if it's in the list AND it's "simple"
10111011
// (i.e., has no parameters and no related request ID or related task that could be lost).
1012+
const hasRelatedRequestId = options?.relatedRequestId !== undefined;
10121013
const canDebounce =
1013-
debouncedMethods.includes(notification.method) && !notification.params && !options?.relatedRequestId && !options?.relatedTask;
1014+
debouncedMethods.includes(notification.method) && !notification.params && !hasRelatedRequestId && !options?.relatedTask;
10141015

10151016
if (canDebounce) {
10161017
// If a notification of this type is already scheduled, do nothing.

packages/core/test/shared/protocol.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,20 @@ describe('protocol tests', () => {
768768
expect(sendSpy).toHaveBeenCalledWith(expect.any(Object), { relatedRequestId: 'req-2' });
769769
});
770770

771+
it('should NOT debounce a notification that has relatedRequestId 0', async () => {
772+
// ARRANGE
773+
protocol = new TestProtocolImpl({ debouncedNotificationMethods: ['test/debounced_with_zero_id'] });
774+
await protocol.connect(transport);
775+
776+
// ACT
777+
await protocol.notification({ method: 'test/debounced_with_zero_id' }, { relatedRequestId: 0 });
778+
await protocol.notification({ method: 'test/debounced_with_zero_id' }, { relatedRequestId: 0 });
779+
780+
// ASSERT
781+
expect(sendSpy).toHaveBeenCalledTimes(2);
782+
expect(sendSpy).toHaveBeenCalledWith(expect.any(Object), { relatedRequestId: 0 });
783+
});
784+
771785
it('should clear pending debounced notifications on connection close', async () => {
772786
// ARRANGE
773787
protocol = new TestProtocolImpl({ debouncedNotificationMethods: ['test/debounced'] });

0 commit comments

Comments
 (0)