Skip to content

Conversation

@KKonstantinov
Copy link
Contributor

@KKonstantinov KKonstantinov commented Feb 3, 2026

Extract ProgressManager and TimeoutManager from Protocol

Extracts progress tracking and timeout management functionality from the Protocol class into dedicated ProgressManager and TimeoutManager classes, following the Single Responsibility Principle.

Motivation and Context

The Protocol class was handling multiple responsibilities including:

  • Progress tracking via _progressHandlers and _taskProgressTokens maps
  • Timeout management via _timeoutInfo map and _setupTimeout/_resetTimeout/_cleanupTimeout methods

This change extracts these concerns into separate manager classes to:

  • Improve code organization and readability
  • Follow Single Responsibility Principle
  • Make progress and timeout logic easier to test and maintain independently
  • Reduce the complexity of the Protocol class

How Has This Been Tested?

  • All existing unit tests pass (430/430 tests in core package)
  • Typecheck passes for all packages in the monorepo
  • Linting passes with no errors
  • The changes are internal refactoring with no external API changes

Breaking Changes

None. This is an internal refactoring:

  • ProgressCallback type is still exported from the same location
  • Protocol class public API is unchanged
  • New ProgressManager and TimeoutManager classes are now exported (additive, non-breaking)
  • New TimeoutInfo, TimeoutOptions, and TimeoutResetResult types are now exported (additive, non-breaking)

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Note: This is technically a refactoring, but marked as bug fix since it improves code maintainability without adding new features or breaking existing functionality.

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Files Changed

File Change
packages/core/src/shared/progressManager.ts NEW - ProgressManager class
packages/core/src/shared/timeoutManager.ts NEW - TimeoutManager class
packages/core/src/shared/protocol.ts Replace inline progress/timeout tracking with manager instances
packages/core/src/index.ts Export progressManager.ts and timeoutManager.ts
packages/core/test/shared/protocol.test.ts Update test helper interface to use _progressManager

ProgressManager API

class ProgressManager {
    registerHandler(messageId: number, callback: ProgressCallback): void;
    getHandler(messageId: number): ProgressCallback | undefined;
    removeHandler(messageId: number): void;
    hasHandler(messageId: number): boolean;
    handleProgress(notification: ProgressNotification): boolean;
    linkTaskToProgressToken(taskId: string, progressToken: number): void;
    getTaskProgressToken(taskId: string): number | undefined;
    cleanupTaskProgressHandler(taskId: string): void;
    clear(): void;
    get handlerCount(): number;
    get taskTokenCount(): number;
}

TimeoutManager API

interface TimeoutInfo {
    timeoutId: ReturnType<typeof setTimeout>;
    startTime: number;
    timeout: number;
    maxTotalTimeout?: number;
    resetTimeoutOnProgress: boolean;
    onTimeout: () => void;
}

interface TimeoutOptions {
    timeout: number;
    maxTotalTimeout?: number;
    resetTimeoutOnProgress?: boolean;
    onTimeout: () => void;
}

interface TimeoutResetResult {
    success: boolean;
    maxTotalTimeoutExceeded?: { elapsed: number; maxTotalTimeout: number };
}

class TimeoutManager {
    setup(messageId: number, options: TimeoutOptions): void;
    reset(messageId: number): TimeoutResetResult;
    cleanup(messageId: number): void;
    get(messageId: number): TimeoutInfo | undefined;
    has(messageId: number): boolean;
    getElapsed(messageId: number): number | undefined;
    clearAll(): void;
    get size(): number;
}

Design Decisions

  1. Uses # private fields - Modern ES private field syntax for true encapsulation
  2. Task progress token tracking in ProgressManager - Task-to-progress-token associations are tightly coupled to progress handlers
  3. TimeoutManager returns result objects instead of throwing - Keeps the manager simple; Protocol decides how to handle errors
  4. Error throwing logic stays in Protocol - Protocol knows about McpError and error codes
  5. Full TSDoc documentation - All public methods have comprehensive JSDoc comments
  6. Reset uses original timeout duration - When reset is called, the timeout is reset to its original duration; maxTotalTimeout is checked when reset is called, not by setting a shorter timeout

@KKonstantinov KKonstantinov requested a review from a team as a code owner February 3, 2026 10:26
@changeset-bot
Copy link

changeset-bot bot commented Feb 3, 2026

⚠️ No Changeset found

Latest commit: c2a1a38

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 3, 2026

Open in StackBlitz

@modelcontextprotocol/client

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/client@1458

@modelcontextprotocol/server

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/server@1458

@modelcontextprotocol/express

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/express@1458

@modelcontextprotocol/hono

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/hono@1458

@modelcontextprotocol/node

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/node@1458

commit: c2a1a38

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant