@payloadcms/plugin-mcp 4.0.0-canary.35 → 4.0.0-canary.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@payloadcms/plugin-mcp",
|
|
3
|
-
"version": "4.0.0-canary.
|
|
3
|
+
"version": "4.0.0-canary.37",
|
|
4
4
|
"description": "MCP (Model Context Protocol) capabilities with Payload",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"plugin",
|
|
@@ -60,10 +60,10 @@
|
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@payloadcms/eslint-config": "3.28.0",
|
|
63
|
-
"payload": "4.0.0-canary.
|
|
63
|
+
"payload": "4.0.0-canary.37"
|
|
64
64
|
},
|
|
65
65
|
"peerDependencies": {
|
|
66
|
-
"payload": "4.0.0-canary.
|
|
66
|
+
"payload": "4.0.0-canary.37"
|
|
67
67
|
},
|
|
68
68
|
"//deps_notes": {
|
|
69
69
|
"tsx": "Required by the `bin.js` stdio mcp. Keep the version pinned to whatever `payload` ships to avoid duplicate installs."
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
|
|
76
76
|
"build:types": "tsc --emitDeclarationOnly --outDir dist",
|
|
77
77
|
"clean": "rimraf {dist,*.tsbuildinfo}",
|
|
78
|
-
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png,json}\" dist/",
|
|
78
|
+
"copyfiles": "copyfiles -u 1 -e \"**/*.spec.*\" \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png,json}\" dist/",
|
|
79
79
|
"lint": "eslint .",
|
|
80
80
|
"lint:fix": "eslint . --fix",
|
|
81
81
|
"pack:plugin": "pnpm build && pnpm pack"
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { fileInputSchema, resolveFile } from './fileInput.js';
|
|
3
|
-
describe('MCP file input', ()=>{
|
|
4
|
-
it('should reject malformed MIME types', ()=>{
|
|
5
|
-
const result = fileInputSchema.safeParse({
|
|
6
|
-
data: 'aGVsbG8=',
|
|
7
|
-
mimeType: 'text/plain\r\nx-test: value',
|
|
8
|
-
name: 'hello.txt',
|
|
9
|
-
source: 'base64'
|
|
10
|
-
});
|
|
11
|
-
expect(result.success).toBe(false);
|
|
12
|
-
});
|
|
13
|
-
it('should accept a prepared upload', ()=>{
|
|
14
|
-
const result = fileInputSchema.safeParse({
|
|
15
|
-
file: {
|
|
16
|
-
filename: 'image.png',
|
|
17
|
-
mimeType: 'image/png',
|
|
18
|
-
size: 123,
|
|
19
|
-
uploadReference: {
|
|
20
|
-
uploadId: 'upload-id'
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
source: 'uploadReference'
|
|
24
|
-
});
|
|
25
|
-
expect(result.success).toBe(true);
|
|
26
|
-
});
|
|
27
|
-
it('should reject oversized base64 files', async ()=>{
|
|
28
|
-
const req = createRequest({
|
|
29
|
-
maxFileSize: 4
|
|
30
|
-
});
|
|
31
|
-
await expect(resolveFile({
|
|
32
|
-
slug: 'media',
|
|
33
|
-
input: {
|
|
34
|
-
data: Buffer.from('hello').toString('base64'),
|
|
35
|
-
mimeType: 'text/plain',
|
|
36
|
-
name: 'hello.txt',
|
|
37
|
-
source: 'base64'
|
|
38
|
-
},
|
|
39
|
-
req
|
|
40
|
-
})).rejects.toThrow('File exceeds the 4 byte upload limit.');
|
|
41
|
-
});
|
|
42
|
-
it('should reject URLs outside the collection allowlist', async ()=>{
|
|
43
|
-
const req = createRequest({
|
|
44
|
-
allowList: [
|
|
45
|
-
{
|
|
46
|
-
hostname: 'assets.example.com',
|
|
47
|
-
protocol: 'https'
|
|
48
|
-
}
|
|
49
|
-
]
|
|
50
|
-
});
|
|
51
|
-
await expect(resolveFile({
|
|
52
|
-
slug: 'media',
|
|
53
|
-
input: {
|
|
54
|
-
source: 'externalURL',
|
|
55
|
-
url: 'https://example.com/image.png'
|
|
56
|
-
},
|
|
57
|
-
req
|
|
58
|
-
})).rejects.toThrow('The provided file URL is not allowed.');
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
function createRequest({ allowList, maxFileSize }) {
|
|
62
|
-
return {
|
|
63
|
-
payload: {
|
|
64
|
-
collections: {
|
|
65
|
-
media: {
|
|
66
|
-
config: {
|
|
67
|
-
upload: allowList ? {
|
|
68
|
-
pasteURL: {
|
|
69
|
-
allowList
|
|
70
|
-
}
|
|
71
|
-
} : {}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
config: {
|
|
76
|
-
upload: {
|
|
77
|
-
limits: {
|
|
78
|
-
fileSize: maxFileSize
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
//# sourceMappingURL=fileInput.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/mcp/builtin/collections/fileInput.spec.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload'\n\nimport { describe, expect, it } from 'vitest'\n\nimport { fileInputSchema, resolveFile } from './fileInput.js'\n\ndescribe('MCP file input', () => {\n it('should reject malformed MIME types', () => {\n const result = fileInputSchema.safeParse({\n data: 'aGVsbG8=',\n mimeType: 'text/plain\\r\\nx-test: value',\n name: 'hello.txt',\n source: 'base64',\n })\n\n expect(result.success).toBe(false)\n })\n\n it('should accept a prepared upload', () => {\n const result = fileInputSchema.safeParse({\n file: {\n filename: 'image.png',\n mimeType: 'image/png',\n size: 123,\n uploadReference: { uploadId: 'upload-id' },\n },\n source: 'uploadReference',\n })\n\n expect(result.success).toBe(true)\n })\n\n it('should reject oversized base64 files', async () => {\n const req = createRequest({ maxFileSize: 4 })\n\n await expect(\n resolveFile({\n slug: 'media',\n input: {\n data: Buffer.from('hello').toString('base64'),\n mimeType: 'text/plain',\n name: 'hello.txt',\n source: 'base64',\n },\n req,\n }),\n ).rejects.toThrow('File exceeds the 4 byte upload limit.')\n })\n\n it('should reject URLs outside the collection allowlist', async () => {\n const req = createRequest({\n allowList: [{ hostname: 'assets.example.com', protocol: 'https' }],\n })\n\n await expect(\n resolveFile({\n slug: 'media',\n input: {\n source: 'externalURL',\n url: 'https://example.com/image.png',\n },\n req,\n }),\n ).rejects.toThrow('The provided file URL is not allowed.')\n })\n})\n\nfunction createRequest({\n allowList,\n maxFileSize,\n}: {\n allowList?: Array<{ hostname: string; protocol: 'http' | 'https' }>\n maxFileSize?: number\n}): PayloadRequest {\n return {\n payload: {\n collections: {\n media: {\n config: {\n upload: allowList ? { pasteURL: { allowList } } : {},\n },\n },\n },\n config: {\n upload: {\n limits: {\n fileSize: maxFileSize,\n },\n },\n },\n },\n } as unknown as PayloadRequest\n}\n"],"names":["describe","expect","it","fileInputSchema","resolveFile","result","safeParse","data","mimeType","name","source","success","toBe","file","filename","size","uploadReference","uploadId","req","createRequest","maxFileSize","slug","input","Buffer","from","toString","rejects","toThrow","allowList","hostname","protocol","url","payload","collections","media","config","upload","pasteURL","limits","fileSize"],"mappings":"AAEA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAE7C,SAASC,eAAe,EAAEC,WAAW,QAAQ,iBAAgB;AAE7DJ,SAAS,kBAAkB;IACzBE,GAAG,sCAAsC;QACvC,MAAMG,SAASF,gBAAgBG,SAAS,CAAC;YACvCC,MAAM;YACNC,UAAU;YACVC,MAAM;YACNC,QAAQ;QACV;QAEAT,OAAOI,OAAOM,OAAO,EAAEC,IAAI,CAAC;IAC9B;IAEAV,GAAG,mCAAmC;QACpC,MAAMG,SAASF,gBAAgBG,SAAS,CAAC;YACvCO,MAAM;gBACJC,UAAU;gBACVN,UAAU;gBACVO,MAAM;gBACNC,iBAAiB;oBAAEC,UAAU;gBAAY;YAC3C;YACAP,QAAQ;QACV;QAEAT,OAAOI,OAAOM,OAAO,EAAEC,IAAI,CAAC;IAC9B;IAEAV,GAAG,wCAAwC;QACzC,MAAMgB,MAAMC,cAAc;YAAEC,aAAa;QAAE;QAE3C,MAAMnB,OACJG,YAAY;YACViB,MAAM;YACNC,OAAO;gBACLf,MAAMgB,OAAOC,IAAI,CAAC,SAASC,QAAQ,CAAC;gBACpCjB,UAAU;gBACVC,MAAM;gBACNC,QAAQ;YACV;YACAQ;QACF,IACAQ,OAAO,CAACC,OAAO,CAAC;IACpB;IAEAzB,GAAG,uDAAuD;QACxD,MAAMgB,MAAMC,cAAc;YACxBS,WAAW;gBAAC;oBAAEC,UAAU;oBAAsBC,UAAU;gBAAQ;aAAE;QACpE;QAEA,MAAM7B,OACJG,YAAY;YACViB,MAAM;YACNC,OAAO;gBACLZ,QAAQ;gBACRqB,KAAK;YACP;YACAb;QACF,IACAQ,OAAO,CAACC,OAAO,CAAC;IACpB;AACF;AAEA,SAASR,cAAc,EACrBS,SAAS,EACTR,WAAW,EAIZ;IACC,OAAO;QACLY,SAAS;YACPC,aAAa;gBACXC,OAAO;oBACLC,QAAQ;wBACNC,QAAQR,YAAY;4BAAES,UAAU;gCAAET;4BAAU;wBAAE,IAAI,CAAC;oBACrD;gBACF;YACF;YACAO,QAAQ;gBACNC,QAAQ;oBACNE,QAAQ;wBACNC,UAAUnB;oBACZ;gBACF;YACF;QACF;IACF;AACF"}
|