{"record":{"id":"f1c6e8eb8e44bfe3","repo":"koala73/worldmonitor","slug":"list-mission-presets-accepts-only-available","errorCode":null,"errorMessage":"list_mission_presets accepts only available.","messagePattern":"list_mission_presets accepts only available\\.","errorType":"exception","errorClass":"SafeWebMcpError","httpStatus":null,"severity":"error","filePath":"src/services/webmcp.ts","lineNumber":2939,"sourceCode":"    {\n      name: WEBMCP_SPA_TOOL.listMissionPresets,\n      title: 'List Mission Presets',\n      description:\n        'List every bundled mission preset for the current monitor. Each item uses a stable preset ID and panel/layer counts without premium payloads. Available rows include intended view and time range. Includes active, monitorCompatible, entitled, and available flags with a stable unavailableReason when gated.',\n      inputSchema: {\n        type: 'object',\n        properties: {\n          available: {\n            type: 'boolean',\n            description: 'If set, keep only presets the current session can apply.',\n          },\n        },\n        additionalProperties: false,\n      },\n      annotations: { readOnlyHint: true },\n      execute: withBindings(WEBMCP_SPA_TOOL.listMissionPresets, async (args, extra) => {\n        if (!hasOnlyOwnKeys(args, ['available'])) {\n          throw new SafeWebMcpError(\n            'list_mission_presets accepts only available.',\n            'validation',\n          );\n        }\n        const query: MissionPresetCatalogQuery = {};\n        if (args.available !== undefined) query.available = args.available as boolean;\n        return boundMissionPresetCatalog(await app.listMissionPresets(query, extra));\n      }, trackEvent, {\n        successMetadata: (_args, value) => {\n          const result = value as MissionPresetCatalogResult;\n          return { resultCount: result.presets.length };\n        },\n      }),\n    },\n    {\n      name: WEBMCP_SPA_TOOL.applyMissionPreset,\n      title: 'Apply Mission Preset',\n      description:","sourceCodeStart":2921,"sourceCodeEnd":2957,"githubUrl":"https://github.com/koala73/worldmonitor/blob/7d06c8633d256c18e38133030bc3613976a96ec9/src/services/webmcp.ts#L2921-L2957","documentation":"The WebMCP tool list_mission_presets accepts at most a single optional boolean argument, available. The handler enforces this with hasOnlyOwnKeys(args, ['available']) and throws SafeWebMcpError('validation') for any other key set, including extra keys or an empty object with unexpected properties.","triggerScenarios":"Calling list_mission_presets with arguments like { category }, { limit }, { available: true, limit: 10 }, or any misspelling such as { availabe: true }.","commonSituations":"Developers assuming all list_* tools share a pagination schema; passing filters copied from list_dashboard_panels; client-side schema caches that predate the narrowing of the tool's parameters.","solutions":["Call the tool with only { available: true|false } or with no arguments at all.","Remove any additional filter/pagination keys — this tool has none.","Re-fetch tool metadata from the server to confirm the current single-parameter schema."],"exampleFix":"// before\nconst res = await mcp.callTool('list_mission_presets', { available: true, limit: 5 });\n// after\nconst res = await mcp.callTool('list_mission_presets', { available: true });","handlingStrategy":"validation","validationCode":"const keys = Object.keys(args ?? {});\nif (keys.some(k => k !== 'available')) throw new Error('list_mission_presets accepts only available.');\nif (args?.available !== undefined && typeof args.available !== 'boolean') throw new Error('available must be boolean');","typeGuard":"const isPresetQuery = (a: unknown): a is { available?: boolean } =>\n  a !== null && typeof a === 'object' &&\n  Object.keys(a).every(k => k === 'available') &&\n  ((a as any).available === undefined || typeof (a as any).available === 'boolean');","tryCatchPattern":"try {\n  const res = await mcp.callTool('list_mission_presets', { available: true });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('accepts only available')) {\n    console.error('Strip all args except available', e.message);\n  } else throw e;\n}","preventionTips":["Pass at most the single boolean available flag.","Do not copy filter objects between list_* tools.","Check the tool schema before first use.","Add a unit test asserting the exact argument object shape."],"tags":["mcp","validation","strict-schema"],"backgroundTag":"invalid-query-parameter","analyzedSha":"7d06c8633d256c18e38133030bc3613976a96ec9","analyzedAt":"2026-09-15T16:44:39.439Z","contentChangedAt":"2026-09-15T16:44:39.439Z","schemaVersion":2},"datasetVersion":"2026-09-15T18:17:12.389Z"}