Skip to content

MCP should return empty instead of error if tools / prompts / resources are not defined #181

Closed

Description

@theodormarcu

Describe the bug
Currently, if you set up a server with the tools defined, but no prompts / resources, attempting to get tools/resources will throw an error instead of returning empty.

To Reproduce
Steps to reproduce the behavior:

  1. Set up an MCP server + client
  2. Define a test tool
  3. Try calling listPrompts or listResources

Expected behavior

All list* methods (that return collections) should return empty arrays when there is nothing to return.

get* should throw an error.

Logs

Additional context

Returning an empty array is a idiomatic pattern when a collection of items is empty.

Express.js

When you query routes that don't match anything, Express returns a 404 rather than crashing
app.get('/api/items') will return an empty array [] when no items exist, not an error

React

When mapping over an empty array of items, React doesn't throw errors - it renders nothing
{items.map(item => <Component key={item.id} {...item} />)} works fine when items is empty

PostgreSQL / Sequelize

User.findAll() returns an empty array if no users exist
It only throws if the table itself doesn't exist (which would be a structural issue)

Next.js

getStaticPaths() can return an empty array if there are no dynamic routes
It doesn't error out because an empty set of paths is valid

Redux

Selectors return empty arrays or default values when querying state that doesn't exist
const todos = useSelector(state => state.todos || []) handles missing state gracefully

Activity

  1. TheHogginator commented on Mar 22, 2025

    @TheHogginator

    The problem here is the McpServer only enables the capabilities once you register the first prompt/resource etc. So the behaviour is correct I'd say.

    If you want to advertise the capability without necessarily registering a handler you can pass capabilities in the constructor

    const server = new McpServer({
      name: "Demo",
      version: "1.0.0"
    }, {
      capabilities: {
        prompts: {},
        resources: {}
      }
    });
  2. rikhuijzer commented on Apr 11, 2025

    @rikhuijzer

    Relatedly, a dynamic resource (note the ResourceTemplate) like

    server.resource(
      "user-profile",
      new ResourceTemplate("users://{userId}/profile", { list: undefined }),
      async (uri, { userId }) => ({
        contents: [{
          uri: uri.href,
          text: `Profile data for user ${userId}`
        }]
      })
    );

    will not be listed when for example requesting the resources with npx @modelcontextprotocol/inspector. But a static one will:

    server.resource(
      "greeting",
      "test://greeting",
      async (uri, { name }) => ({
        contents: [{
          uri: uri.href,
          text: `Hello, ${name}`
        }]
      })
    );
  3. Toavina23 commented on Apr 15, 2025

    @Toavina23

    Relatedly, a dynamic resource (note the ResourceTemplate) like

    server.resource(
    "user-profile",
    new ResourceTemplate("users://{userId}/profile", { list: undefined }),
    async (uri, { userId }) => ({
    contents: [{
    uri: uri.href,
    text: Profile data for user ${userId}
    }]
    })
    );
    will not be listed when for example requesting the resources with npx @modelcontextprotocol/inspector. But a static one will:

    server.resource(
    "greeting",
    "test://greeting",
    async (uri, { name }) => ({
    contents: [{
    uri: uri.href,
    text: Hello, ${name}
    }]
    })
    );

    I was confused by this behavior today while trying to create a dymanic resource, and did not see it in the inspector. Can I have a indication of how to test my dynamic resources with the inspector please ?

  4. lamemind commented on May 26, 2025

    @lamemind

    The problem here is the McpServer only enables the capabilities once you register the first prompt/resource etc. So the behaviour is correct I'd say.

    If you want to advertise the capability without necessarily registering a handler you can pass capabilities in the constructor

    const server = new McpServer({
    name: "Demo",
    version: "1.0.0"
    }, {
    capabilities: {
    prompts: {},
    resources: {}
    }
    });

    Hello,
    Claude Desktop floods log file with "Method not found" errors.
    This should not be considered the correct behavior IMO

    Thanks

  5. added
    needs confirmationNeeds confirmation that the PR is actually required or needed.
    needs reproneeds additional information to be able to reproduce bug
    on Sep 29, 2025
  6. felixweinberger commented on Sep 29, 2025

    @felixweinberger
    Contributor

    Hi @theodormarcu if this is still affecting you could you provide a minimal working example that reproduces the issue you're seeing? Something we could ideally run directly to debug.

  7. lf-novelt commented on Oct 31, 2025

    @lf-novelt

    @rikhuijzer I've finally found out why the dynamic resources would not appear in the "resources/list".

    it's because of the { list: undefined} template. You have to provide concrete examples to be listed:

    //Add a dynamic greeting resource that appears in  "resources/list"
    server.registerResource(
      'greeting3',
      new ResourceTemplate('greeting://test3/{name}', {
        list: async () => ({ // list template is needed to appear in the "resources/list"
          resources: [
            {
              name: 'Alice',
              uri: 'greeting://test3/Alice',
              description: 'Greeting for Alice'
            },
          ]
        })
      }),
      {
        title: 'Greeting Resource',
        description: 'Dynamic greeting generator'
      },
      async (uri, { name }) => ({
        contents: [
          {
            uri: uri.href,
            text: `Hello, ${name}!`
          }
        ]
      })
    );
    
  8. sstklen commented on Feb 24, 2026

    @sstklen

    Hey! I ran into a similar pattern in our bug knowledge base and thought this might help.

    What's happening: McpServer only calls server.setRequestHandler for prompts/list, resources/list etc. when the first prompt/resource is registered via .prompt()/.resource(). Without registration, no handler exists, so the low-level Server throws a MethodNotFound JSON-RPC error on list requests.

    What worked for us:

    In McpServer constructor (or a lazy init), always register fallback handlers for all list methods (prompts/list, resources/list, resources/templates/list) that return empty arrays. Only the get/read/call handlers should error when the capability is unused. Also declare the capabilities in the server init so they are advertised.

    // In src/server/mcp.ts — McpServer constructor, after creating this._server:
    
    // Register default empty-list handlers for all collection endpoints
    this._server.setRequestHandler(ListPromptsRequestSchema, async () => ({
      prompts: []
    }));
    this._server.setRequestHandler(ListResourcesRequestSchema, async () => ({
      resources: []
    }));
    this._server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => ({
      resourceTemplates: []
    }));
    this._server.setRequestHandler(ListToolsRequestSchema, async () => ({
      tools: []
    }));
    
    // When .tool()/.prompt()/.resource() is called, they already overwrite these
    // handlers via setRequestHandler, so real handlers replace the empty defaults.
    
    // Also ensure capabilities always include all three:
    // In the Server constructor options, merge:
    capabilities: {
      prompts: { listChanged: true },
      resources: { listChanged: true },
      tools: { listChanged: true },
      ...options?.capabilities
    }
    

    Hope this helps! Let me know if it doesn't match your case — happy to dig deeper. 🦞

    Disclosure: This analysis is from Confucius Debug, an AI-powered community KB for agent bugs. Please verify before applying.


    🦞 Confucius Debug — community knowledge base for AI agent bugs. Free to search via MCP.

  9. ghost added
    potentially closeBot recommends closing — needs maintainer review
    on Apr 17, 2026
  10. tonny008 commented on May 15, 2026

    @tonny008
    	//** hack to prevent error when list resources & list prompts
    	server.registerResource('dummy', '', {}, () => ({}) as any).remove();
    	server.registerPrompt('dummy', {}, () => ({}) as any).remove();
    	//** end hack

    until updates

  11. felixweinberger commented on Oct 5, 2026

    @felixweinberger
    Contributor

    On v2 the client returns an empty list when the server has no prompts, resources or tools (#1386, in 2.0.0). On v1, declaring the capability in the McpServer options gives an empty list from the next patch release (#2958). Closing.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingneeds confirmationNeeds confirmation that the PR is actually required or needed.needs reproneeds additional information to be able to reproduce bugpotentially closeBot recommends closing — needs maintainer review

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions