payloadcms / payloadcms/payload
plugin-mcp: create tool cannot be used on collections with a custom id field
@AlessioGr is already working on this.
Since Aug 6, 2026.
- Dominant language
- TypeScript
- Stars
- 44.8k
- Forks
- 4.2k
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 53
Description
Describe the Bug
sanitizeJsonSchema unconditionally deletes id from the collection's JSON Schema before it is converted to the Zod input schema of the generated MCP tools, and also strips id from the schema's required array.
This is correct for collections that use an auto-generated id, but it breaks collections that define id as a custom, user-supplied field (e.g. a slug or an external classifier code). For those, createXxx exposes no id parameter at all, so there is no way to supply the value, and the create call always fails validation on the Payload side.
updateXxx is unaffected, because the update tool re-adds id explicitly as a document selector.
Relevant code — packages/plugin-mcp/src/utils/schemaConversion/sanitizeJsonSchema.ts:
delete schema?.properties?.id
delete schema?.properties?.createdAt
delete schema?.properties?.updatedAt
if (Array.isArray(schema.required)) {
schema.required = schema.required.filter((field) => field !== 'id')
// ...
}
Link to the code that reproduces this issue
N/A — minimal reproduction steps below.
Reproduction Steps
- Define a collection with a custom text
id:
export const Directions: CollectionConfig = {
slug: 'directions',
fields: [
{ name: 'id', type: 'text', required: true, unique: true },
{ name: 'title', type: 'text', required: true },
],
}
- Enable it in the plugin with
create: true:
mcpPlugin({
collections: {
directions: {
enabled: { create: true, delete: true, find: true, update: true },
},
},
})
-
Inspect the generated
createDirectionstool — its input schema containstitle,depth,draft,locale,fallbackLocale,select, but noid. -
Call
createDirectionswithtitleset. The call fails:
Error creating resource in collection "directions": The following field is invalid: ID
- Passing
idexplicitly makes no difference — it is not part of the tool schema, so it never reachespayload.create(), and the same error is returned.
Expected Behaviour
When a collection declares id as a real, user-supplied field, the generated create tool should expose id as a parameter (and keep it required if the field is required), so such collections can be created through MCP.
Collections relying on an auto-generated id should keep the current behaviour.
A possible fix would be to strip id only when it is not explicitly declared in the collection's fields — the information is available from payload.config at the point where the schema is built in getMcpHandler. Alternatively, a per-collection opt-in flag would work as a narrower fix.
Which area(s) are affected?
plugin: mcp
Environment Info
Binaries:
Node: 26.5.0
npm: 11.17.0
Yarn: N/A
pnpm: 11.1.0
Relevant Packages:
payload: 3.85.0
next: 16.2.6
@payloadcms/db-postgres: 3.85.0
@payloadcms/drizzle: 3.85.0
@payloadcms/email-nodemailer: 3.85.0
@payloadcms/graphql: 3.85.0
@payloadcms/next/utilities: 3.85.0
@payloadcms/plugin-cloud-storage: 3.85.0
@payloadcms/plugin-import-export: 3.85.0
@payloadcms/plugin-mcp: 3.85.0
@payloadcms/richtext-lexical: 3.85.0
@payloadcms/storage-s3: 3.85.0
@payloadcms/translations: 3.85.0
@payloadcms/ui/shared: 3.85.0
react: 19.2.6
react-dom: 19.2.6
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 25.3.0: Wed Jan 28 20:53:15 PST 2026; root:xnu-12377.81.4~5/RELEASE_ARM64_T6000
Available memory (MB): 16384
Available CPU cores: 8
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.