Repository navigation
fix(mcp): default inputSchema to {type:"object"} for registered tools in tools/list - #529
Merged
jpr5 merged 3 commits intoOct 12, 2026
Conversation
… in tools/list
inputSchema is required on every Tool in a tools/list result. A tool
registered with addTool() and no schema (the docs Quick Start) or only
via onToolCall() was listed without one, and the official Python and
TypeScript SDK clients rejected the whole list. Fake tools already list
{ type: "object" } in this case.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
commit: |
tools/list only defaulted a missing inputSchema. A schema present without
a root type ({} or properties only) was listed as is, and the official MCP
SDK client rejected the whole list (inputSchema.type: expected "object").
Such a schema now lists with type "object" added and its other keys kept;
an explicit type is left unchanged.
Add the changelog entry for the tools/list inputSchema default and update
the MCP mock docs: registered tools without an inputSchema (addTool without
one, or onToolCall only) list { "type": "object" }, and a schema without a
type gets type "object" added.
jpr5
approved these changes
Oct 12, 2026
Merged
jpr5
added a commit
that referenced
this pull request
Oct 12, 2026
Patch release npm/plugin **1.45.1** from `main` at a23779e (#529 merged). aimock-pytest stays at 0.7.0 (its `pyproject.toml` version is unchanged); only its default aimock pin moves to 1.45.1. > **Prepared, not merged.** `publish-release.yml` runs on every push to `main`. Merging this PR publishes npm `@copilotkit/aimock@1.45.1`, the `v1.45.1` tag, the `v1` major-tag move, the GitHub Release, the Docker images and the Slack announcement. Merge only when the release is authorized. ## What's in 1.45.1 ### Changed - **OpenRouter Video: `openai/sora-2` returns the real removal rejection** ([#520](#520)). OpenRouter removed the model; a live submit returns `400 {"error":{"message":"Model openai/sora-2 does not exist","code":400}}`. `POST /api/v1/videos` with `model: "openai/sora-2"` now returns that 400 even when a fixture matches, and never reaches a record-mode upstream. The default `GET /api/v1/videos/models` listing no longer includes `openai/sora-2`, and a fixture for it no longer adds it. Move fixtures to a model OpenRouter still serves (for example `bytedance/seedance-2.0`). The daily drift check now confirms the model stays absent. ### Fixed - **MCP `tools/list` gives every registered tool an `inputSchema`** ([#529](#529)). A tool registered with `addTool()` without an `inputSchema`, or only via `onToolCall()`, was listed with no `inputSchema`, and the official MCP SDK client rejected the whole `tools/list` response. These tools are now listed with `inputSchema: { "type": "object" }`, as fake-only tools already were. Tools registered with an `inputSchema` are unchanged. - **MCP `tools/list` adds `"type": "object"` to a typeless registered schema** ([#529](#529)). A schema such as `{}` or `{ "properties": { ... } }` was listed as is, and the SDK client rejected it (`inputSchema.type: expected "object"`). It is now listed with `"type": "object"` added and its other keys kept. A schema with an explicit `type` is unchanged. Everything else merged since v1.45.0 is test-only. ## Versions | Surface | Before | After | |---|---|---| | `package.json` `version` | 1.45.0 | 1.45.1 | | `.claude-plugin/plugin.json` `version` | 1.45.0 | 1.45.1 | | `.claude-plugin/marketplace.json` `plugins[0].source.version` | ^1.45.0 | ^1.45.1 | | `charts/aimock/Chart.yaml` `appVersion` (chart `version` stays 0.1.0) | 1.45.0 | 1.45.1 | | `docs/index.html` CLI banner | aimock v1.45.0 | aimock v1.45.1 | | `packages/aimock-pytest/src/aimock_pytest/_version.py` `AIMOCK_VERSION` | 1.45.0 | 1.45.1 | | `packages/aimock-pytest/README.md` `--aimock-version` default | 1.45.0 | 1.45.1 | Left at 1.45.0 on purpose: CHANGELOG history, and "requires 1.45.0 or later" minimum-version notes in `README.md`, `docs/*`, `packages/aimock-pytest/README.md` and `skills/write-fixtures/SKILL.md`, plus the illustrative `aimockVersion` in the `docs/mcp-mock` recorded-file example. `pnpm-lock.yaml` does not carry the root version. `CHANGELOG.md`: `[Unreleased]` became `[1.45.1] - 2026-10-11` with an empty `[Unreleased]` kept above it, as in prior releases. ## Local gates - `pnpm install --frozen-lockfile`: pass - `pnpm format:check`: pass - `pnpm lint`: pass - `pnpm typecheck`: pass - `pnpm build`: pass - `vitest run` on `npm-publish-verify-workflow`, `unreleased-check-workflow`, `drift-scripts`, `openrouter-video-record`: 4 files, 165 tests pass
Contributor
|
Thank you @vishalhabib99! 🙏 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
MCPMocklists a registered tool exactly as it was registered. A tool added withoutinputSchemais therefore listed without one, but the MCP schema requiresinputSchemaon everyTool. The official clients reject the wholetools/listresult, not just that tool.Two documented paths produce such a tool:
mcp.addTool({ name: "search", description: "Search the web" })mcp.onToolCall("name", handler)for a name that was never added. That stores{ name }.Repro (
@copilotkit/aimock1.45.0; currentmainhas the same handler):list_tools():ValidationError: ... ListToolsResult tools.1.inputSchema Field requiredclient.listTools():Invalid input: expected object, received undefinedattools[1].inputSchemaSo a test that points a real MCP client at the mock fails at
listTools, before it reaches the tool it's testing.Fix: in
tools/list, a registered tool with noinputSchemais listed with{ type: "object" }. This is the defaultMcpFakes.listTools()already uses ("A tool with noinputSchemalists{ type: "object" }"), so registered tools and fake tools now behave the same. A tool that has a schema is listed unchanged. The recorded-list path also gets the default, because it reuses the sametoolsarray.Tests:
mcp-mock.test.ts.calcis listed withoutinputSchema. I updated it to expect{ type: "object" }.addToolandonToolCallpaths. Both fail onmainand pass here.prettier --check,eslintandpnpm typecheckpass.pnpm testrun on macOS shows the same 36 failures with and without this change, all invalidate-cli*,mcp-fakes-report-route,mcp-fakes-doc-samplesandmcp-fakes-redgreen. They look like they need a built CLI or other local setup.I left out one related gap:
resources/readfor a resource registered without content returns notextorblob. That would be a separate PR if you want it.