Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 15, 2025

Fix MCP Server Session Timing Out

Problem

Sessions were timing out prematurely due to two distinct bugs:

  1. Timestamp frequency mismatch (primary bug): IdleTimeout.Ticks (100-nanosecond intervals) was incorrectly used with TimeProvider.GetTimestamp() (platform-specific frequency). On macOS with ~1B ticks/second, a 10-hour timeout became ~6 minutes.

  2. Activity timestamp not updated: LastActivityTicks only updated when reference count dropped to 0, so POST requests during active GET connections didn't refresh the timeout.

Plan

  • Analyze the session lifecycle and identify root causes
  • Fix timestamp frequency conversion in StatefulSessionManager
  • Update LastActivityTicks when references are acquired
  • Add test to verify sessions with periodic requests don't timeout
  • Build and test the changes
  • Run full test suite
  • Run security scanning
  • Address code review feedback

Root Causes

Bug 1: Timestamp Frequency Mismatch
In StatefulSessionManager.cs line 21, _idleTimeoutTicks was set to IdleTimeout.Ticks, which uses TimeSpan.Ticks (100-nanosecond units, always 10,000,000 per second). But line 115 used this with TimeProvider.GetTimestamp(), which returns ticks based on TimeProvider.TimestampFrequency (varies by platform: ~1,000,000,000 on macOS, ~10,000,000 on Windows).

Bug 2: Activity Timestamp
In StreamableHttpSession.cs, LastActivityTicks was updated in UnreferenceDisposable.DisposeAsync() only when _referenceCount reached 0. This meant POST requests during active GET connections didn't update the timestamp.

Solutions

Bug 1 Fix: Added GetIdleTimeoutInTimestampTicks() helper that converts TimeSpan.Ticks to timestamp ticks: timeSpan.Ticks * timeProvider.TimestampFrequency / TimeSpan.TicksPerSecond

Bug 2 Fix: Updated AcquireReferenceAsync() to set LastActivityTicks whenever a reference is acquired in the Started state.

Testing

  • All 210 AspNetCore tests pass
  • All 1018 core tests pass
  • Existing tests with FakeTimeProvider validate the timestamp conversion
  • New test ActiveSession_WithPeriodicRequests_DoesNotTimeout verifies ongoing activity prevents timeout
  • No security issues detected

Security Summary

No vulnerabilities detected by CodeQL scanner.

Original prompt

This section details on the original issue you should resolve

<issue_title>MCP server session timing out</issue_title>
<issue_description>The MCP server session seems to be timing out. I am getting this error if my client doesnt interact with the server for a while.

{"error":{"message":"Streamable HTTP error: Error POSTing to endpoint: {"error":{"code":-32001,"message":"Session not │
│ found"},"id":"","jsonrpc":"2.0"}","isError":true}}</issue_description>

Comments on the Issue (you are @copilot in this section)

@mikekistler I have also observed this problem on MacOs but could not figure out why it was happening. Thanks for finding the root of the problem!

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 2 commits December 15, 2025 19:06
Update LastActivityTicks whenever a reference is acquired in the Started state,
not just when reference count drops to 0. This ensures sessions with ongoing
activity (POST requests) don't timeout even if a GET request is active.

Co-authored-by: stephentoub <[email protected]>
Updated comment to be more precise about when LastActivityTicks is updated.

Co-authored-by: stephentoub <[email protected]>
Copilot AI changed the title [WIP] Fix MCP server session timing out issue Fix session timeout for active sessions with periodic requests Dec 15, 2025
Copilot AI requested a review from stephentoub December 15, 2025 19:16
Copy link
Member

@eiriktsarpalis eiriktsarpalis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot the user comment from #1104 (comment) suggests that the root cause for the bug might be different. Could you check if that is the case?

Convert TimeSpan.Ticks to timestamp ticks using TimeProvider.TimestampFrequency.
TimeSpan.Ticks uses 100-nanosecond intervals (10,000,000 per second), but
TimeProvider.GetTimestamp() returns ticks based on TimeProvider.TimestampFrequency,
which varies by platform (e.g., ~1,000,000,000 on macOS, ~10,000,000 on Windows).

This was causing IdleTimeout to be incorrectly calculated, resulting in sessions
timing out much faster than configured on platforms with different frequencies.

Co-authored-by: eiriktsarpalis <[email protected]>
Copy link
Contributor Author

Copilot AI commented Dec 15, 2025

@copilot the user comment from #1104 (comment) suggests that the root cause for the bug might be different. Could you check if th...

You're absolutely right! The user identified the actual root cause: a timestamp frequency mismatch between TimeSpan.Ticks (100-nanosecond intervals, always 10,000,000 per second) and TimeProvider.GetTimestamp() (platform-specific frequency - ~1,000,000,000 on macOS, ~10,000,000 on Windows).

I've fixed this in commit 01982eb by converting TimeSpan.Ticks to timestamp ticks using the formula:

timeSpan.Ticks * timeProvider.TimestampFrequency / TimeSpan.TicksPerSecond

This explains why the IdleTimeout had no effect - on macOS, a 10-hour timeout was being treated as ~360 seconds (~6 minutes). All tests pass with the fix.

Copilot AI changed the title Fix session timeout for active sessions with periodic requests Fix session timeout due to timestamp frequency mismatch and activity tracking Dec 15, 2025
Copilot AI requested a review from eiriktsarpalis December 15, 2025 19:50
@stephentoub stephentoub marked this pull request as ready for review December 15, 2025 19:54
Moved the helper method to the end of the class per code review feedback.

Co-authored-by: eiriktsarpalis <[email protected]>
@stephentoub stephentoub merged commit aaffd71 into main Dec 15, 2025
16 of 17 checks passed
@stephentoub stephentoub deleted the copilot/fix-mcp-server-session-timeout branch December 15, 2025 21:21
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.

MCP server session timing out

3 participants