mirror of
https://github.com/modelcontextprotocol/servers.git
synced 2026-04-18 16:13:22 +02:00
fix(sequential-thinking): use z.coerce for number and boolean params (#3533)
fix(sequential-thinking): use z.coerce for number and safe preprocess for boolean params
Uses z.coerce.number() for number fields and a z.preprocess() helper for boolean fields to handle string-typed parameters from LLM clients. The preprocess approach correctly handles "false" → false, avoiding the z.coerce.boolean() footgun where Boolean("false") === true.
Fixes #3428
This commit is contained in:
@@ -5,6 +5,16 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { SequentialThinkingServer } from './lib.js';
|
import { SequentialThinkingServer } from './lib.js';
|
||||||
|
|
||||||
|
/** Safe boolean coercion that correctly handles string "false" */
|
||||||
|
const coercedBoolean = z.preprocess((val) => {
|
||||||
|
if (typeof val === "boolean") return val;
|
||||||
|
if (typeof val === "string") {
|
||||||
|
if (val.toLowerCase() === "true") return true;
|
||||||
|
if (val.toLowerCase() === "false") return false;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}, z.boolean());
|
||||||
|
|
||||||
const server = new McpServer({
|
const server = new McpServer({
|
||||||
name: "sequential-thinking-server",
|
name: "sequential-thinking-server",
|
||||||
version: "0.2.0",
|
version: "0.2.0",
|
||||||
@@ -72,14 +82,14 @@ You should:
|
|||||||
11. Only set nextThoughtNeeded to false when truly done and a satisfactory answer is reached`,
|
11. Only set nextThoughtNeeded to false when truly done and a satisfactory answer is reached`,
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
thought: z.string().describe("Your current thinking step"),
|
thought: z.string().describe("Your current thinking step"),
|
||||||
nextThoughtNeeded: z.boolean().describe("Whether another thought step is needed"),
|
nextThoughtNeeded: coercedBoolean.describe("Whether another thought step is needed"),
|
||||||
thoughtNumber: z.number().int().min(1).describe("Current thought number (numeric value, e.g., 1, 2, 3)"),
|
thoughtNumber: z.coerce.number().int().min(1).describe("Current thought number (numeric value, e.g., 1, 2, 3)"),
|
||||||
totalThoughts: z.number().int().min(1).describe("Estimated total thoughts needed (numeric value, e.g., 5, 10)"),
|
totalThoughts: z.coerce.number().int().min(1).describe("Estimated total thoughts needed (numeric value, e.g., 5, 10)"),
|
||||||
isRevision: z.boolean().optional().describe("Whether this revises previous thinking"),
|
isRevision: coercedBoolean.optional().describe("Whether this revises previous thinking"),
|
||||||
revisesThought: z.number().int().min(1).optional().describe("Which thought is being reconsidered"),
|
revisesThought: z.coerce.number().int().min(1).optional().describe("Which thought is being reconsidered"),
|
||||||
branchFromThought: z.number().int().min(1).optional().describe("Branching point thought number"),
|
branchFromThought: z.coerce.number().int().min(1).optional().describe("Branching point thought number"),
|
||||||
branchId: z.string().optional().describe("Branch identifier"),
|
branchId: z.string().optional().describe("Branch identifier"),
|
||||||
needsMoreThoughts: z.boolean().optional().describe("If more thoughts are needed")
|
needsMoreThoughts: coercedBoolean.optional().describe("If more thoughts are needed")
|
||||||
},
|
},
|
||||||
annotations: {
|
annotations: {
|
||||||
readOnlyHint: true,
|
readOnlyHint: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user