Skip to content

Conversation

meiraleal
Copy link

@meiraleal meiraleal commented Sep 30, 2025

This PR resolves issue #929 by implementing a default fallback handler that automatically returns empty arrays for standard MCP list methods when no specific handlers are registered, preventing "Method not found" errors.

Fixes #929

Problem

When a server advertises a capability (prompts, resources, tools) but doesn't register handlers for the corresponding list methods, clients receive -32601: Method not found errors instead of empty arrays.

Reproduction scenario:

const server = new McpServer({
  name: "example",
  version: "0.0.0",
});

// Server advertises prompts capability but registers no prompts
// No call to server.registerPrompt()

await client.listPrompts(); 
// ❌ Throws: MCP error -32601: Method not found
// ✅ Expected: { prompts: [] }

This affects all four list methods:

  • prompts/list → should return { prompts: [] }
  • resources/list → should return { resources: [] }
  • resources/templates/list → should return { resourceTemplates: [] }
  • tools/list → should return { tools: [] }

Root cause: The protocol layer had no default handling for list methods, so servers with capabilities but no registered items would fail with "Method not found" instead of gracefully returning empty collections.

Solution

Added a _defaultFallbackRequestHandler method to the Protocol class that:

  1. Recognizes standard MCP list method patterns
  2. Automatically returns appropriate empty arrays for known list methods
  3. Falls through to "Method not found" only for truly unhandled methods
  4. Respects user-defined fallbackRequestHandler when provided

Implementation approach:

private _defaultFallbackRequestHandler(request: JSONRPCRequest): SendResultT | null {
  const listMethodResponses: Record<string, string> = {
    "prompts/list": "prompts",
    "resources/list": "resources",
    "resources/templates/list": "resourceTemplates",
    "tools/list": "tools",
  };
  
  const responseKey = listMethodResponses[request.method];
  return responseKey ? { [responseKey]: [] } as SendResultT : null;
}

Handler resolution order:

  1. Specific registered handler (if exists)
  2. User-defined fallbackRequestHandler (if set)
  3. Default list method handler (new)
  4. "Method not found" error (only if none of the above match)

Changes

Core Protocol Changes:

  • src/shared/protocol.ts:
    • Added _defaultFallbackRequestHandler method for automatic empty array responses
    • Refactored _onrequest to use layered fallback logic
    • Sends responses directly from default handler to avoid unnecessary handler wrapping

Test Coverage:

  • src/client/index.test.ts:
    • Test for explicit empty handler registration (backward compatibility)
    • Test for servers with actual registered items (regression)
    • new tests covering all four list methods simultaneously
    • Test validating consistent behavior across all capabilities

Testing

Unit Tests (6 new tests):

  1. prompts/list returns empty array when no handler registered
  2. resources/list returns empty array when no handler registered
  3. resources/templates/list returns empty array when no handler registered
  4. tools/list returns empty array when no handler registered
  5. All list methods work with explicit empty handlers (backward compatibility)
  6. All list methods return empty arrays simultaneously without any handlers

Test Results:

npm test  # All tests pass including new ones
npm run build  # Clean build with TypeScript compilation
npm run lint  # Code style compliance verified

Validation scenarios:

  • ✅ Server with capability but no registered items → returns []
  • ✅ Server with explicit empty handler → returns [] (unchanged)
  • ✅ Server with registered items → returns items (unchanged)
  • ✅ Server with custom fallbackRequestHandler → uses custom logic (unchanged)
  • ✅ Unknown methods still return "Method not found" error

Breaking Changes

None. This is a backward-compatible enhancement that:

  • Maintains all existing handler registration patterns
  • Respects user-defined fallbackRequestHandler when present
  • Only adds default behavior for previously failing scenarios
  • All existing tests pass without modification
  • Servers with explicit handlers continue working identically

Types of Changes

  • ✅ Bug fix (non-breaking change which fixes an issue)
  • ✅ New tests added with comprehensive coverage
  • ✅ Documentation via inline comments

Checklist

  • ✅ Code follows repository's style guidelines (ESLint passing)
  • ✅ New and existing tests pass locally
  • ✅ Appropriate error handling maintained
  • ✅ Comprehensive test coverage for all four list methods
  • ✅ Backward compatibility preserved
  • ✅ Clear separation between default behavior and custom handlers

Impact

This fix resolves a critical UX issue affecting MCP server development. Developers can now:

  • Create minimal servers that advertise capabilities without immediately implementing handlers
  • Avoid boilerplate empty handler registration for unused capabilities
  • Get intuitive empty array responses instead of confusing "Method not found" errors
  • Build servers incrementally, adding handlers only when needed

Before (Broken):

// ❌ Throws "Method not found" even though server advertises capability
await client.listPrompts();

After (Fixed):

// ✅ Returns empty array gracefully
const result = await client.listPrompts(); // { prompts: [] }

@meiraleal meiraleal requested review from a team and ihrpr September 30, 2025 22:27
@meiraleal meiraleal force-pushed the issue-929_listPrompts-methodNotFound branch from 88f9723 to 3cf1c07 Compare September 30, 2025 22:31
@meiraleal meiraleal force-pushed the issue-929_listPrompts-methodNotFound branch from 3cf1c07 to 46181b8 Compare September 30, 2025 22:55
@meiraleal meiraleal force-pushed the issue-929_listPrompts-methodNotFound branch from 46181b8 to 2732797 Compare September 30, 2025 23:36
@meiraleal meiraleal changed the title Fix: Return Empty Arrays for List Methods When No Handlers Registered (#929) Fix: Return empty Arrays for List methods when no handlers registered (#929) Oct 1, 2025
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.

Client#listPrompts results in MCP error -32601: Method not found
1 participant