Skip to content

prompts/get rejects omitted arguments when all argsSchema fields are optional; tools fix (#1404) not in 1.x #1869

@dgon-jd

Description

@dgon-jd

Describe the bug

The same "missing arguments rejected when all schema fields are optional" pattern fixed for tools in #1404 still affects prompts, and #1404 itself is not in any 1.x release.

Two distinct gaps:

  1. Prompts handler is unfixed (all versions, including main). prompts/get calls safeParseAsync(argsObj, request.params.arguments) without the ?? {} defensive pattern that fix(server): handle undefined arguments for tools with all optional params #1404 introduced for tools. A prompt registered with argsSchema: { context: z.string().optional() } and called with arguments omitted returns MCP error -32602: Invalid arguments for prompt <name>: [{ "code": "invalid_type", "expected": "object", "received": "undefined" }].

  2. Tools fix (fix(server): handle undefined arguments for tools with all optional params #1404) is not in the 1.x line. The fix landed on main on 2026-01-23 but none of the v1.x backport releases (1.27.0, 1.27.1, 1.28.0, 1.29.0 — all tagged as "[v1.x backport]") include it. Users on @modelcontextprotocol/sdk@^1.27.0 still hit the tools-side bug.

To Reproduce

Server (using 1.27.0 or any 1.x):

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';

const server = new McpServer({ name: 'test', version: '1.0.0' }, {
  capabilities: { prompts: {}, tools: {} },
});

server.registerPrompt(
  'echo',
  {
    title: 'Echo',
    description: 'Echoes optional context',
    argsSchema: { context: z.string().optional() },
  },
  async (args) => ({
    messages: [{
      role: 'user',
      content: { type: 'text', text: `context: ${args.context ?? 'none'}` },
    }],
  }),
);

Client — any of these fail in the same way:

// Fails: arguments omitted
await client.getPrompt({ name: 'echo' });

// Fails: arguments explicitly undefined
await client.getPrompt({ name: 'echo', arguments: undefined });

Client workaround that succeeds:

await client.getPrompt({ name: 'echo', arguments: {} });

Expected behavior

Per the MCP spec, arguments on prompts/get is OPTIONAL at the request level. A registered prompt where every declared argument is optional should accept a request that omits arguments entirely. The same applies to tools/call (addressed upstream by #1404 on main).

Actual behavior

safeParseAsync(argsObj, undefined) fails because argsObj is the non-optional z.object(...) returned by objectFromShape(), which rejects undefined at the top level. The error propagates to the client as JSON-RPC -32602 "Invalid params".

Root cause is _createRegisteredPrompt in src/server/mcp.ts (around line 567):

argsSchema: argsSchema === undefined ? undefined : objectFromShape(argsSchema),

Wrapped once, the top-level object is never optional, and there's no ?? {} coercion at the parse site (unlike tools, where #1404 added it).

Proposed fix

Mirror #1404 in the prompts handler:

- const parseResult = await safeParseAsync(argsObj, request.params.arguments);
+ const parseResult = await safeParseAsync(argsObj, request.params.arguments ?? {});

Plus backport both the tools fix (#1404) and this prompts fix to the v1.x branch so users on @modelcontextprotocol/sdk@^1.x get consistent behavior.

Affected versions

Workaround we're using

Transport-layer normalization that sets req.body.params.arguments ??= {} before the request reaches the SDK, for both prompts/get and tools/call. Works across all 1.x versions but is obviously a wart we'd like to drop.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Moderate issues affecting some users, edge cases, potentially valuable featurebugSomething isn't workingfix proposedBot has a verified fix diff in the commentready for workEnough information for someone to start working on

    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