mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-13 03:13:47 +00:00
e29a019376
The MCP endpoint was the only route accepting a body without validation. Its JSON Schema tool declarations were advertisement only: the low-level SDK Server validates the JSON-RPC envelope but never the arguments of a tool call, and every handler cast them with `args as SomeType`. Tools are now declared with `defineTool(name, config, handler)`, the argument shape `registerTool` takes, and the JSON Schema advertised in tools/list is generated from the same zod schema that parses incoming arguments, so the two cannot drift. Handlers receive inferred arguments and pass them to the existing services, whose argument types are derived from ontime-types — which means a schema that drifts from the domain model now fails typecheck. mcp.registry.ts is the only module aware of the SDK internals. Migrating to the SDK v2 registerTool API means replacing its two functions with a registration loop, leaving the tool declarations untouched. Malformed calls are now protocol errors, matching what the SDK does on the registerTool path and what v2 will do. Failures raised by the services are still returned as tool errors so agents can read them and recover. Fixes three bugs the missing validation allowed: - Project filenames reached `join(projectsDir, name)` unsanitised, so `../canary.json` resolved outside the projects directory. They are now confined with the same sanitize-filename + ensureJsonExtension pair the HTTP routes use in db.validation.ts. - ontime_update_project_info forwarded its whole argument object into setProjectData, which spreads it into the stored project; an undeclared `logo` key also caused the current logo file to be deleted. Only declared fields reach it now. - Batch creation declared nested entries as a bare object. They are modelled two levels deep, which encodes that groups cannot be nested and keeps the generated schema free of $ref/$defs. Unknown keys are rejected rather than stripped, so an agent gets an actionable error instead of a write that silently does less than it reported. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MZioYpY8NR8UM5tAQ7BkfN