Skip to content

Feature Request: Add maxTimeMS Configuration Option for Query Timeout #829

@jahales

Description

@jahales

Feature Request: Add maxTimeMS Configuration Option for Query Timeout

Summary

Add a configuration option (MDB_MCP_MAX_TIME_MS / --maxTimeMs) that applies MongoDB's maxTimeMS parameter to all find() and aggregate() operations, automatically terminating long-running queries after a specified duration.

Motivation

When using the MCP server with AI assistants (e.g., GitHub Copilot, Claude), there's a risk of:

  1. Runaway queries - AI-generated queries may unintentionally cause collection scans or inefficient operations on large collections
  2. Resource exhaustion - Long-running queries can lock up connections and consume server resources
  3. Hanging sessions - Users have no way to recover from stuck queries without restarting the MCP server

The existing safeguards (--indexCheck, --maxDocumentsPerQuery, --maxBytesPerQuery) help but don't address execution time.

Proposed Solution

Add a new configuration option:

Config Default Description
MDB_MCP_MAX_TIME_MS / --maxTimeMs 30000 (30s) Maximum execution time in milliseconds for find and aggregate operations. Uses MongoDB's maxTimeMS cursor option.

Implementation Details

After analyzing the codebase, this would be a low-complexity change with well-defined modification points:

1. Add Config Option (src/common/config/userConfig.ts)

Add alongside existing timeout configs (idleTimeoutMs, exportTimeoutMs, etc.):

maxTimeMs: z4.coerce
    .number()
    .default(30_000)
    .describe(
        "Maximum execution time in milliseconds for find and aggregate operations. Set to 0 to disable."
    )
    .register(configRegistry, { overrideBehavior: onlyLowerThanBaseValueOverride() }),

2. Modify Find Tool (src/tools/mongodb/read/find.ts, ~line 66)

The find cursor is already created with options - just add maxTimeMS:

  findCursor = provider.find(database, collection, filter, {
      projection,
      limit: limitOnFindCursor.limit,
      sort,
+     maxTimeMS: this.config.maxTimeMs || undefined,
  });

3. Modify Aggregate Tool (src/tools/mongodb/read/aggregate.ts, ~line 115)

Same pattern:

- aggregationCursor = provider.aggregate(database, collection, cappedResultsPipeline);
+ aggregationCursor = provider.aggregate(database, collection, cappedResultsPipeline, {
+     maxTimeMS: this.config.maxTimeMs || undefined,
+ });

4. Modify Export Tool (src/tools/mongodb/read/export.ts, ~lines 70-82)

Add to both find and aggregate cursor creation:

  cursor = provider.find(database, collection, filter ?? {}, {
      projection,
      sort,
      limit,
      promoteValues: false,
      bsonRegExp: true,
+     maxTimeMS: this.config.maxTimeMs || undefined,
  });

  cursor = provider.aggregate(database, collection, pipeline, {
      promoteValues: false,
      bsonRegExp: true,
      allowDiskUse: true,
+     maxTimeMS: this.config.maxTimeMs || undefined,
  });

5. Update Constants (src/helpers/constants.ts)

Add documentation/reference:

export const DEFAULT_MAX_TIME_MS: number = 30_000;

Existing Patterns to Follow

The codebase already uses maxTimeMS in two places (hardcoded for count operations):

  • QUERY_COUNT_MAX_TIME_MS_CAP = 10_000 for countDocuments in find
  • AGG_COUNT_MAX_TIME_MS_CAP = 60_000 for aggregation count

This shows the pattern is already established and tested.

Estimated Effort

Task Complexity
Add config option Low - follows existing patterns in userConfig.ts
Update find.ts Trivial - add one option
Update aggregate.ts Trivial - add options object
Update export.ts Low - two small changes
Add tests Medium - follow existing test patterns
Update README Low - add to config table

Total estimate: 1-2 hours for implementation + tests

Benefits

  • Safety by default - Prevents runaway queries from blocking the MCP server
  • Configurable - Users can adjust or disable (0) based on their needs
  • Follows existing patterns - Aligns with other _MS configuration options like idleTimeoutMs, exportTimeoutMs
  • Native MongoDB support - Uses built-in MongoDB functionality, no custom timeout logic needed
  • Override behavior - Using onlyLowerThanBaseValueOverride() means client configs can only reduce the timeout, not increase it beyond server limits

Additional Context

This would complement the existing --indexCheck option which prevents collection scans. Together they provide comprehensive query protection:

  • --indexCheck prevents obviously inefficient queries (COLLSCAN)
  • --maxTimeMs catches queries that are slow for other reasons (complex aggregations, lock contention, large result sets, etc.)

Related

  • MongoDB documentation: cursor.maxTimeMS()
  • Existing option: MDB_MCP_INDEX_CHECK (related safety feature)
  • Existing timeout configs: idleTimeoutMs, notificationTimeoutMs, exportTimeoutMs

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions