Skip to content

Commit 89ab526

Browse files
perf(plugin-mcp)!: removes 'override' config (#14598)
- Removes `override` from the plugin config - Updates documentation #14595 makes it so we support MCP context in hooks, so the config no longer needs an `override` as a way of modifying model data.
1 parent 7a31c02 commit 89ab526

File tree

6 files changed

+111
-134
lines changed

6 files changed

+111
-134
lines changed

docs/plugins/mcp.mdx

Lines changed: 106 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -71,76 +71,46 @@ export default config
7171

7272
### Options
7373

74-
| Option | Type | Description |
75-
| -------------------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------- |
76-
| `collections` | `object` | An object of collection slugs to use for MCP capabilities. |
77-
| `collections[slug]` | `object` | An object of collection slugs to use for MCP capabilities. |
78-
| `collections[slug].description` | `string` | A description for the collection. |
79-
| `collections[slug].override` | `function` | A function that allows you to override the data generated by the LLM before it is used in an operation. |
80-
| `collections[slug].overrideResponse` | `function` | A function that allows you to override the response from the operation tool call |
81-
| `collections[slug].enabled` | `object or boolean` | Determines whether the LLM can find, create, update, and delete documents in the collection. |
82-
| `collections[slug].enabled.find` | `boolean` | Whether to allow the LLM to find documents in the collection. |
83-
| `collections[slug].enabled.create` | `boolean` | Whether to allow the LLM to create documents in the collection. |
84-
| `collections[slug].enabled.update` | `boolean` | Whether to allow the LLM to update documents in the collection. |
85-
| `collections[slug].enabled.delete` | `boolean` | Whether to allow the LLM to delete documents in the collection. |
86-
| `disabled` | `boolean` | Disable the MCP plugin while keeping database schema consistent. |
87-
| `overrideApiKeyCollection` | `function` | A function that allows you to override the automatically generated API Keys collection. |
88-
| `mcp` | `object` | MCP options that allow you to customize the MCP server. |
89-
| `mcp.tools` | `array` | An array of tools to add to the MCP server. |
90-
| `mcp.tools.name` | `string` | The name of the tool. |
91-
| `mcp.tools.description` | `string` | The description of the tool. |
92-
| `mcp.tools.handler` | `function` | The handler function for the tool. |
93-
| `mcp.tools.parameters` | `object` | The parameters for the tool (Zod schema). |
94-
| `mcp.prompts` | `array` | An array of prompts to add to the MCP server. |
95-
| `mcp.prompts.name` | `string` | The name of the prompt. |
96-
| `mcp.prompts.title` | `string` | The title of the prompt (used by LLMs to determine when to use it). |
97-
| `mcp.prompts.description` | `string` | The description of the prompt. |
98-
| `mcp.prompts.handler` | `function` | The handler function for the prompt. |
99-
| `mcp.prompts.argsSchema` | `object` | The arguments schema for the prompt (Zod schema). |
100-
| `mcp.resources` | `array` | An array of resources to add to the MCP server. |
101-
| `mcp.resources.name` | `string` | The name of the resource. |
102-
| `mcp.resources.title` | `string` | The title of the resource (used by LLMs to determine when to use it). |
103-
| `mcp.resources.description` | `string` | The description of the resource. |
104-
| `mcp.resources.handler` | `function` | The handler function for the resource. |
105-
| `mcp.resources.uri` | `string or object` | The URI of the resource (can be a string or ResourceTemplate for dynamic URIs). |
106-
| `mcp.resources.mimeType` | `string` | The MIME type of the resource. |
107-
| `mcp.handlerOptions` | `object` | The handler options for the MCP server. |
108-
| `mcp.handlerOptions.basePath` | `string` | The base path for the MCP server (default: '/api'). |
109-
| `mcp.handlerOptions.verboseLogs` | `boolean` | Whether to log verbose logs to the console (default: false). |
110-
| `mcp.handlerOptions.maxDuration` | `number` | The maximum duration for the MCP server requests (default: 60). |
111-
| `mcp.serverOptions` | `object` | The server options for the MCP server. |
112-
| `mcp.serverOptions.serverInfo` | `object` | The server info for the MCP server. |
113-
| `mcp.serverOptions.serverInfo.name` | `string` | The name of the MCP server (default: 'Payload MCP Server'). |
114-
| `mcp.serverOptions.serverInfo.version` | `string` | The version of the MCP server (default: '1.0.0'). |
115-
116-
## Override API Keys Collection
117-
118-
The plugin automatically creates an **API Keys** collection that provides high-resolution control over MCP capabilities. This collection allows admins to:
119-
120-
- Create API keys for MCP clients
121-
- Allow or disallow specific MCP capabilities in real-time
122-
- Control which collections can be accessed via MCP
123-
- Enable or disable tools
124-
125-
You can customize this collection using the `overrideApiKeyCollection` option:
126-
127-
```ts
128-
mcpPlugin({
129-
overrideApiKeyCollection: (collection) => {
130-
// Add fields to the API Keys collection
131-
collection.fields.push({
132-
name: 'department',
133-
type: 'select',
134-
options: [
135-
{ label: 'Development', value: 'dev' },
136-
{ label: 'Marketing', value: 'marketing' },
137-
],
138-
})
139-
return collection
140-
},
141-
// ... other options
142-
})
143-
```
74+
| Option | Type | Description |
75+
| -------------------------------------- | ------------------- | -------------------------------------------------------------------------------------------- |
76+
| `collections` | `object` | An object of collection slugs to use for MCP capabilities. |
77+
| `collections[slug]` | `object` | An object of collection slugs to use for MCP capabilities. |
78+
| `collections[slug].description` | `string` | A description for the collection. |
79+
| `collections[slug].overrideResponse` | `function` | A function that allows you to override the response from the operation tool call |
80+
| `collections[slug].enabled` | `object or boolean` | Determines whether the LLM can find, create, update, and delete documents in the collection. |
81+
| `collections[slug].enabled.find` | `boolean` | Whether to allow the LLM to find documents in the collection. |
82+
| `collections[slug].enabled.create` | `boolean` | Whether to allow the LLM to create documents in the collection. |
83+
| `collections[slug].enabled.update` | `boolean` | Whether to allow the LLM to update documents in the collection. |
84+
| `collections[slug].enabled.delete` | `boolean` | Whether to allow the LLM to delete documents in the collection. |
85+
| `disabled` | `boolean` | Disable the MCP plugin while keeping database schema consistent. |
86+
| `overrideApiKeyCollection` | `function` | A function that allows you to override the automatically generated API Keys collection. |
87+
| `mcp` | `object` | MCP options that allow you to customize the MCP server. |
88+
| `mcp.tools` | `array` | An array of tools to add to the MCP server. |
89+
| `mcp.tools.name` | `string` | The name of the tool. |
90+
| `mcp.tools.description` | `string` | The description of the tool. |
91+
| `mcp.tools.handler` | `function` | The handler function for the tool. |
92+
| `mcp.tools.parameters` | `object` | The parameters for the tool (Zod schema). |
93+
| `mcp.prompts` | `array` | An array of prompts to add to the MCP server. |
94+
| `mcp.prompts.name` | `string` | The name of the prompt. |
95+
| `mcp.prompts.title` | `string` | The title of the prompt (used by LLMs to determine when to use it). |
96+
| `mcp.prompts.description` | `string` | The description of the prompt. |
97+
| `mcp.prompts.handler` | `function` | The handler function for the prompt. |
98+
| `mcp.prompts.argsSchema` | `object` | The arguments schema for the prompt (Zod schema). |
99+
| `mcp.resources` | `array` | An array of resources to add to the MCP server. |
100+
| `mcp.resources.name` | `string` | The name of the resource. |
101+
| `mcp.resources.title` | `string` | The title of the resource (used by LLMs to determine when to use it). |
102+
| `mcp.resources.description` | `string` | The description of the resource. |
103+
| `mcp.resources.handler` | `function` | The handler function for the resource. |
104+
| `mcp.resources.uri` | `string or object` | The URI of the resource (can be a string or ResourceTemplate for dynamic URIs). |
105+
| `mcp.resources.mimeType` | `string` | The MIME type of the resource. |
106+
| `mcp.handlerOptions` | `object` | The handler options for the MCP server. |
107+
| `mcp.handlerOptions.basePath` | `string` | The base path for the MCP server (default: '/api'). |
108+
| `mcp.handlerOptions.verboseLogs` | `boolean` | Whether to log verbose logs to the console (default: false). |
109+
| `mcp.handlerOptions.maxDuration` | `number` | The maximum duration for the MCP server requests (default: 60). |
110+
| `mcp.serverOptions` | `object` | The server options for the MCP server. |
111+
| `mcp.serverOptions.serverInfo` | `object` | The server info for the MCP server. |
112+
| `mcp.serverOptions.serverInfo.name` | `string` | The name of the MCP server (default: 'Payload MCP Server'). |
113+
| `mcp.serverOptions.serverInfo.version` | `string` | The version of the MCP server (default: '1.0.0'). |
144114

145115
## Prompts
146116

@@ -217,49 +187,7 @@ resources: [
217187
]
218188
```
219189

220-
### Data Override Example
221-
222-
Use override functions to modify data before it's processed:
223-
224-
```ts
225-
collections: {
226-
posts: {
227-
enabled: true,
228-
override: (original, req) => {
229-
// Log the operation
230-
req.payload.logger.info('MCP operation on posts:', original)
231-
232-
// Sanitize or validate data
233-
const sanitized = {
234-
...original,
235-
title: sanitizeTitle(original.title),
236-
publishedAt: original.publishedAt || new Date().toISOString(),
237-
}
238-
239-
return sanitized
240-
},
241-
},
242-
}
243-
```
244-
245-
Use overrideResponse to modify response data:
246-
247-
```ts
248-
collections: {
249-
posts: {
250-
enabled: true,
251-
overrideResponse: (response, doc, req) => {
252-
response.content.push({
253-
type: 'text',
254-
text: 'Additional response for Posts!',
255-
})
256-
return response
257-
},
258-
},
259-
}
260-
```
261-
262-
### Example Tool with Database Access
190+
## Tools
263191

264192
Tools allow you to extend MCP capabilities beyond basic CRUD operations. Use them when you need to perform complex queries, aggregations, or business logic that isn't covered by the standard collection operations.
265193

@@ -294,6 +222,71 @@ tools: [
294222
]
295223
```
296224

225+
## Override API Keys Collection
226+
227+
The plugin automatically creates an **API Keys** collection that provides high-resolution control over MCP capabilities. This collection allows admins to:
228+
229+
- Create API keys for MCP clients
230+
- Allow or disallow specific MCP capabilities in real-time
231+
- Control which collections can be accessed via MCP
232+
- Enable or disable tools
233+
234+
You can customize this collection using the `overrideApiKeyCollection` option:
235+
236+
```ts
237+
mcpPlugin({
238+
overrideApiKeyCollection: (collection) => {
239+
// Add fields to the API Keys collection
240+
collection.fields.push({
241+
name: 'department',
242+
type: 'select',
243+
options: [
244+
{ label: 'Development', value: 'dev' },
245+
{ label: 'Marketing', value: 'marketing' },
246+
],
247+
})
248+
return collection
249+
},
250+
// ... other options
251+
})
252+
```
253+
254+
## Hooks
255+
256+
To understand or modify data returned by models at runtime use a collection [Hook](https://payloadcms.com/docs/hooks/collections). Within a hook you can look up the API context. If the context is `MCP` that collection was triggered by the MCP Plugin. This does not apply to custom tools or resources that have their own context, and can make unrelated database calls.
257+
258+
In this example, Post titles are modified to include '(MCP Hook Override)' when they are read using MCP.
259+
260+
```ts
261+
import type { CollectionConfig } from 'payload'
262+
263+
export const Posts: CollectionConfig = {
264+
slug: 'posts',
265+
fields: [
266+
{
267+
name: 'title',
268+
type: 'text',
269+
admin: {
270+
description: 'The title of the post',
271+
},
272+
required: true,
273+
},
274+
275+
// ... other fields
276+
],
277+
hooks: {
278+
beforeRead: [
279+
({ doc, req }) => {
280+
if (req.payloadAPI === 'MCP') {
281+
doc.title = `${doc.title} (MCP Hook Override)`
282+
}
283+
return doc
284+
},
285+
],
286+
},
287+
}
288+
```
289+
297290
## Performance
298291

299292
The description you choose to use for your collection greatly impacts the way a model will decide to use it.

packages/plugin-mcp/src/mcp/tools/resource/create.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,9 @@ export const createResourceTool = (
5050
// Create the resource
5151
const result = await payload.create({
5252
collection: collectionSlug,
53-
req,
54-
// TODO: Move the override to a `beforeChange` hook and extend the payloadAPI context req to include MCP request info.
55-
data: collections?.[collectionSlug]?.override?.(parsedData, req) || parsedData,
53+
data: parsedData,
5654
overrideAccess: false,
55+
req,
5756
user,
5857
})
5958

packages/plugin-mcp/src/mcp/tools/resource/update.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ export const updateResourceTool = (
127127
}
128128
const result = await payload.update({
129129
...updateOptions,
130-
data: collections?.[collectionSlug]?.override?.(parsedData, req) || parsedData,
130+
data: parsedData,
131131
} as any)
132132

133133
if (verboseLogs) {
@@ -175,7 +175,7 @@ ${JSON.stringify(result, null, 2)}
175175
}
176176
const result = await payload.update({
177177
...updateOptions,
178-
data: collections?.[collectionSlug]?.override?.(parsedData, req) || parsedData,
178+
data: parsedData,
179179
} as any)
180180

181181
const bulkResult = result as { docs?: unknown[]; errors?: unknown[] }

packages/plugin-mcp/src/types.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,6 @@ export type PluginMCPServerConfig = {
2626
update?: boolean
2727
}
2828
| boolean
29-
/**
30-
* Override the data generated by the MCP client. This allows you to modify the data that is sent to the MCP client. This is useful for adding additional data to the response, data normalization, or verifying data.
31-
*/
32-
override?: (
33-
original: Record<string, unknown>,
34-
req: PayloadRequest,
35-
) => Record<string, unknown>
3629

3730
/**
3831
* Override the response generated by the MCP client. This allows you to modify the response that is sent to the MCP client. This is useful for adding additional data to the response, data normalization, or verifying data.

test/plugin-mcp/config.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,6 @@ export default buildConfigWithDefaults({
7676
create: true,
7777
},
7878
description: 'This is a Payload collection with Post documents.',
79-
override: (original: Record<string, unknown>, req) => {
80-
const updatedOriginal = {
81-
...original,
82-
title: `Title Override: ${original?.title as string}`,
83-
}
84-
req.payload.logger.info('[Override MCP call for Posts]:')
85-
return updatedOriginal
86-
},
8779
overrideResponse: (response, doc, req) => {
8880
req.payload.logger.info('[Override MCP response for Posts]:')
8981
response.content.push({

0 commit comments

Comments
 (0)