@payloadcms/plugin-mcp 4.0.0-internal.41055b1 → 4.0.0-internal.435b2d6

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.
Files changed (58) hide show
  1. package/bin.js +6 -8
  2. package/dist/defaultAccess.d.ts.map +1 -1
  3. package/dist/defineTool.d.ts +8 -8
  4. package/dist/defineTool.d.ts.map +1 -1
  5. package/dist/endpoint/access.d.ts.map +1 -1
  6. package/dist/mcp/buildMcpServer.d.ts.map +1 -1
  7. package/dist/mcp/builtin/collections/createTool.d.ts.map +1 -1
  8. package/dist/mcp/builtin/collections/createTool.js +11 -1
  9. package/dist/mcp/builtin/collections/createTool.js.map +1 -1
  10. package/dist/mcp/builtin/collections/fileInput.d.ts +20 -0
  11. package/dist/mcp/builtin/collections/fileInput.d.ts.map +1 -0
  12. package/dist/mcp/builtin/collections/fileInput.js +100 -0
  13. package/dist/mcp/builtin/collections/fileInput.js.map +1 -0
  14. package/dist/mcp/builtin/collections/fileInput.spec.js +72 -0
  15. package/dist/mcp/builtin/collections/fileInput.spec.js.map +1 -0
  16. package/dist/mcp/builtin/collections/formatCollectionError.d.ts +1 -1
  17. package/dist/mcp/builtin/collections/formatCollectionError.d.ts.map +1 -1
  18. package/dist/mcp/builtin/collections/getCollectionSchemaTool.d.ts.map +1 -1
  19. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js +23 -2
  20. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js.map +1 -1
  21. package/dist/mcp/builtin/collections/updateTool.d.ts.map +1 -1
  22. package/dist/mcp/builtin/collections/updateTool.js +12 -6
  23. package/dist/mcp/builtin/collections/updateTool.js.map +1 -1
  24. package/dist/mcp/builtin/validateEntityData.d.ts.map +1 -1
  25. package/dist/mcp/builtinTools.d.ts.map +1 -1
  26. package/dist/mcp/sanitizeMCPConfig.d.ts.map +1 -1
  27. package/dist/stdio.d.ts +1 -2
  28. package/dist/stdio.d.ts.map +1 -1
  29. package/dist/stdio.js +4 -6
  30. package/dist/stdio.js.map +1 -1
  31. package/dist/utils/camelCase.d.ts.map +1 -1
  32. package/dist/utils/resolveProjectRoot.d.ts.map +1 -1
  33. package/dist/utils/schemaConversion/filterFieldsByAccess.d.ts.map +1 -1
  34. package/dist/utils/schemaConversion/getEntityInputSchema.d.ts.map +1 -1
  35. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts.map +1 -1
  36. package/dist/utils/toStandardSchema.d.ts.map +1 -1
  37. package/package.json +5 -18
  38. package/src/mcp/builtin/collections/createTool.ts +5 -1
  39. package/src/mcp/builtin/collections/fileInput.spec.ts +79 -0
  40. package/src/mcp/builtin/collections/fileInput.ts +139 -0
  41. package/src/mcp/builtin/collections/getCollectionSchemaTool.ts +14 -1
  42. package/src/mcp/builtin/collections/updateTool.ts +6 -4
  43. package/src/stdio.ts +4 -6
  44. package/dist/bin/index.d.ts +0 -2
  45. package/dist/bin/index.d.ts.map +0 -1
  46. package/dist/bin/index.js +0 -12
  47. package/dist/bin/index.js.map +0 -1
  48. package/dist/bin/initializeViteHMR.d.ts +0 -8
  49. package/dist/bin/initializeViteHMR.d.ts.map +0 -1
  50. package/dist/bin/initializeViteHMR.js +0 -75
  51. package/dist/bin/initializeViteHMR.js.map +0 -1
  52. package/dist/bin/viteConfigBoundary.d.ts +0 -6
  53. package/dist/bin/viteConfigBoundary.d.ts.map +0 -1
  54. package/dist/bin/viteConfigBoundary.js +0 -25
  55. package/dist/bin/viteConfigBoundary.js.map +0 -1
  56. package/src/bin/index.ts +0 -16
  57. package/src/bin/initializeViteHMR.ts +0 -76
  58. package/src/bin/viteConfigBoundary.ts +0 -39
package/src/stdio.ts CHANGED
@@ -4,7 +4,7 @@ import type { Config, Plugin, SanitizedConfig } from 'payload'
4
4
  import { serveStdio } from '@modelcontextprotocol/server/stdio'
5
5
  import { fileURLToPath, pathToFileURL } from 'node:url'
6
6
  import { createLocalReq, getPayload } from 'payload'
7
- import { findConfig, loadEnv } from 'payload/node'
7
+ import { findConfig } from 'payload/node'
8
8
 
9
9
  import type { SanitizedMCPPluginConfig } from './types.js'
10
10
 
@@ -20,7 +20,7 @@ import { resolveProjectRoot } from './utils/resolveProjectRoot.js'
20
20
  * Set `PAYLOAD_MCP_AUTHORIZATION` to authenticate. In development,
21
21
  * `PAYLOAD_MCP_OVERRIDE_ACCESS=true` skips access checks.
22
22
  */
23
- export const runMcpStdio = async (configOverride?: SanitizedConfig): Promise<void> => {
23
+ export const runMcpStdio = async (): Promise<void> => {
24
24
  // MCP clients may start this command from another folder. Move to the Payload
25
25
  // project so findConfig() can find the config.
26
26
  const projectRoot = resolveProjectRoot(fileURLToPath(import.meta.url))
@@ -28,11 +28,9 @@ export const runMcpStdio = async (configOverride?: SanitizedConfig): Promise<voi
28
28
  process.chdir(projectRoot)
29
29
  }
30
30
 
31
- loadEnv()
32
31
  const configPath = findConfig()
33
- const configURL = pathToFileURL(configPath).href
34
- const configModule = configOverride ? undefined : await import(configURL)
35
- const config: SanitizedConfig = configOverride ?? (await (configModule?.default ?? configModule))
32
+ const configModule = await import(pathToFileURL(configPath).toString())
33
+ const config = (await (configModule.default ?? configModule)) as SanitizedConfig
36
34
 
37
35
  /**
38
36
  * stdout is only for MCP messages. The spec says the server must not write
@@ -1,2 +0,0 @@
1
- export declare const bin: () => Promise<void>;
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bin/index.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,GAAG,QAAa,OAAO,CAAC,IAAI,CAaxC,CAAA"}
package/dist/bin/index.js DELETED
@@ -1,12 +0,0 @@
1
- import { runMcpStdio } from '../stdio.js';
2
- export const bin = async ()=>{
3
- let viteHMR;
4
- if (process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test' && process.env.DISABLE_PAYLOAD_HMR !== 'true') {
5
- const { initializeViteHMR } = await import('./initializeViteHMR.js');
6
- viteHMR = await initializeViteHMR();
7
- }
8
- await runMcpStdio(viteHMR?.config);
9
- await viteHMR?.connect();
10
- };
11
-
12
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/bin/index.ts"],"sourcesContent":["import { runMcpStdio } from '../stdio.js'\n\nexport const bin = async (): Promise<void> => {\n let viteHMR\n if (\n process.env.NODE_ENV !== 'production' &&\n process.env.NODE_ENV !== 'test' &&\n process.env.DISABLE_PAYLOAD_HMR !== 'true'\n ) {\n const { initializeViteHMR } = await import('./initializeViteHMR.js')\n viteHMR = await initializeViteHMR()\n }\n\n await runMcpStdio(viteHMR?.config)\n await viteHMR?.connect()\n}\n"],"names":["runMcpStdio","bin","viteHMR","process","env","NODE_ENV","DISABLE_PAYLOAD_HMR","initializeViteHMR","config","connect"],"mappings":"AAAA,SAASA,WAAW,QAAQ,cAAa;AAEzC,OAAO,MAAMC,MAAM;IACjB,IAAIC;IACJ,IACEC,QAAQC,GAAG,CAACC,QAAQ,KAAK,gBACzBF,QAAQC,GAAG,CAACC,QAAQ,KAAK,UACzBF,QAAQC,GAAG,CAACE,mBAAmB,KAAK,QACpC;QACA,MAAM,EAAEC,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC;QAC3CL,UAAU,MAAMK;IAClB;IAEA,MAAMP,YAAYE,SAASM;IAC3B,MAAMN,SAASO;AACjB,EAAC"}
@@ -1,8 +0,0 @@
1
- import type { SanitizedConfig } from 'payload';
2
- type ViteHMR = {
3
- config: SanitizedConfig;
4
- connect: () => Promise<void>;
5
- };
6
- export declare const initializeViteHMR: () => Promise<undefined | ViteHMR>;
7
- export {};
8
- //# sourceMappingURL=initializeViteHMR.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"initializeViteHMR.d.ts","sourceRoot":"","sources":["../../src/bin/initializeViteHMR.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAW9C,KAAK,OAAO,GAAG;IACb,MAAM,EAAE,eAAe,CAAA;IACvB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7B,CAAA;AAED,eAAO,MAAM,iBAAiB,QAAa,OAAO,CAAC,SAAS,GAAG,OAAO,CA2DrE,CAAA"}
@@ -1,75 +0,0 @@
1
- /* eslint-disable no-console */ import { fileURLToPath } from 'node:url';
2
- import { getPayload, reload } from 'payload';
3
- import { findConfig, loadEnv } from 'payload/node';
4
- import { resolveProjectRoot } from '../utils/resolveProjectRoot.js';
5
- export const initializeViteHMR = async ()=>{
6
- try {
7
- import.meta.resolve('vite');
8
- } catch (error) {
9
- if (error.code !== 'ERR_MODULE_NOT_FOUND') {
10
- throw error;
11
- }
12
- if (process.env.NODE_ENV === 'development') {
13
- console.error('[payload-mcp] Vite is not installed, so Payload config changes will not hot reload. Install vite@~8.1.4 as a development dependency to enable HMR during local development.');
14
- }
15
- return;
16
- }
17
- const { createServer, createServerModuleRunner, normalizePath } = await import('vite');
18
- const projectRoot = resolveProjectRoot(fileURLToPath(import.meta.url));
19
- if (projectRoot) {
20
- process.chdir(projectRoot);
21
- }
22
- loadEnv();
23
- const vite = await createServer({
24
- clearScreen: false,
25
- configFile: false,
26
- envDir: false,
27
- logLevel: 'error',
28
- optimizeDeps: {
29
- noDiscovery: true
30
- },
31
- publicDir: false,
32
- resolve: {
33
- alias: {
34
- 'payload-mcp:config': normalizePath(findConfig())
35
- },
36
- tsconfigPaths: true
37
- },
38
- server: {
39
- middlewareMode: true,
40
- ws: false
41
- },
42
- ssr: {
43
- noExternal: [
44
- /^@payloadcms\//,
45
- /^payload$/
46
- ]
47
- }
48
- });
49
- const runner = createServerModuleRunner(vite.environments.ssr);
50
- const boundaryPath = fileURLToPath(new URL('./viteConfigBoundary.js', import.meta.url));
51
- const boundary = await runner.import(boundaryPath);
52
- const config = boundary.getConfig();
53
- return {
54
- config,
55
- connect: async ()=>{
56
- const payload = await getPayload({
57
- config,
58
- cron: false,
59
- disableOnInit: true
60
- });
61
- let payloadReloadQueue = Promise.resolve();
62
- const reloadPayload = (nextConfig)=>{
63
- payloadReloadQueue = payloadReloadQueue.then(()=>reload(nextConfig, payload, false)).catch((error)=>console.error('[payload-mcp] config reload failed:', error));
64
- return payloadReloadQueue;
65
- };
66
- boundary.subscribe(reloadPayload);
67
- const latestConfig = boundary.getConfig();
68
- if (config !== latestConfig) {
69
- await reloadPayload(latestConfig);
70
- }
71
- }
72
- };
73
- };
74
-
75
- //# sourceMappingURL=initializeViteHMR.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/bin/initializeViteHMR.ts"],"sourcesContent":["import type { SanitizedConfig } from 'payload'\n\n/* eslint-disable no-console */\nimport { fileURLToPath } from 'node:url'\nimport { getPayload, reload } from 'payload'\nimport { findConfig, loadEnv } from 'payload/node'\n\nimport type * as ConfigBoundary from './viteConfigBoundary.js'\n\nimport { resolveProjectRoot } from '../utils/resolveProjectRoot.js'\n\ntype ViteHMR = {\n config: SanitizedConfig\n connect: () => Promise<void>\n}\n\nexport const initializeViteHMR = async (): Promise<undefined | ViteHMR> => {\n try {\n import.meta.resolve('vite')\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ERR_MODULE_NOT_FOUND') {\n throw error\n }\n\n if (process.env.NODE_ENV === 'development') {\n console.error(\n '[payload-mcp] Vite is not installed, so Payload config changes will not hot reload. Install vite@~8.1.4 as a development dependency to enable HMR during local development.',\n )\n }\n return\n }\n\n const { createServer, createServerModuleRunner, normalizePath } = await import('vite')\n const projectRoot = resolveProjectRoot(fileURLToPath(import.meta.url))\n if (projectRoot) {\n process.chdir(projectRoot)\n }\n\n loadEnv()\n const vite = await createServer({\n clearScreen: false,\n configFile: false,\n envDir: false,\n logLevel: 'error',\n optimizeDeps: { noDiscovery: true },\n publicDir: false,\n resolve: { alias: { 'payload-mcp:config': normalizePath(findConfig()) }, tsconfigPaths: true },\n server: { middlewareMode: true, ws: false },\n ssr: { noExternal: [/^@payloadcms\\//, /^payload$/] },\n })\n const runner = createServerModuleRunner(vite.environments.ssr)\n const boundaryPath = fileURLToPath(new URL('./viteConfigBoundary.js', import.meta.url))\n const boundary = await runner.import<typeof ConfigBoundary>(boundaryPath)\n const config = boundary.getConfig()\n\n return {\n config,\n connect: async () => {\n const payload = await getPayload({ config, cron: false, disableOnInit: true })\n let payloadReloadQueue = Promise.resolve()\n const reloadPayload = (nextConfig: SanitizedConfig): Promise<void> => {\n payloadReloadQueue = payloadReloadQueue\n .then(() => reload(nextConfig, payload, false))\n .catch((error) => console.error('[payload-mcp] config reload failed:', error))\n return payloadReloadQueue\n }\n\n boundary.subscribe(reloadPayload)\n\n const latestConfig = boundary.getConfig()\n if (config !== latestConfig) {\n await reloadPayload(latestConfig)\n }\n },\n }\n}\n"],"names":["fileURLToPath","getPayload","reload","findConfig","loadEnv","resolveProjectRoot","initializeViteHMR","resolve","error","code","process","env","NODE_ENV","console","createServer","createServerModuleRunner","normalizePath","projectRoot","url","chdir","vite","clearScreen","configFile","envDir","logLevel","optimizeDeps","noDiscovery","publicDir","alias","tsconfigPaths","server","middlewareMode","ws","ssr","noExternal","runner","environments","boundaryPath","URL","boundary","import","config","getConfig","connect","payload","cron","disableOnInit","payloadReloadQueue","Promise","reloadPayload","nextConfig","then","catch","subscribe","latestConfig"],"mappings":"AAEA,6BAA6B,GAC7B,SAASA,aAAa,QAAQ,WAAU;AACxC,SAASC,UAAU,EAAEC,MAAM,QAAQ,UAAS;AAC5C,SAASC,UAAU,EAAEC,OAAO,QAAQ,eAAc;AAIlD,SAASC,kBAAkB,QAAQ,iCAAgC;AAOnE,OAAO,MAAMC,oBAAoB;IAC/B,IAAI;QACF,YAAYC,OAAO,CAAC;IACtB,EAAE,OAAOC,OAAO;QACd,IAAI,AAACA,MAAgCC,IAAI,KAAK,wBAAwB;YACpE,MAAMD;QACR;QAEA,IAAIE,QAAQC,GAAG,CAACC,QAAQ,KAAK,eAAe;YAC1CC,QAAQL,KAAK,CACX;QAEJ;QACA;IACF;IAEA,MAAM,EAAEM,YAAY,EAAEC,wBAAwB,EAAEC,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC;IAC/E,MAAMC,cAAcZ,mBAAmBL,cAAc,YAAYkB,GAAG;IACpE,IAAID,aAAa;QACfP,QAAQS,KAAK,CAACF;IAChB;IAEAb;IACA,MAAMgB,OAAO,MAAMN,aAAa;QAC9BO,aAAa;QACbC,YAAY;QACZC,QAAQ;QACRC,UAAU;QACVC,cAAc;YAAEC,aAAa;QAAK;QAClCC,WAAW;QACXpB,SAAS;YAAEqB,OAAO;gBAAE,sBAAsBZ,cAAcb;YAAc;YAAG0B,eAAe;QAAK;QAC7FC,QAAQ;YAAEC,gBAAgB;YAAMC,IAAI;QAAM;QAC1CC,KAAK;YAAEC,YAAY;gBAAC;gBAAkB;aAAY;QAAC;IACrD;IACA,MAAMC,SAASpB,yBAAyBK,KAAKgB,YAAY,CAACH,GAAG;IAC7D,MAAMI,eAAerC,cAAc,IAAIsC,IAAI,2BAA2B,YAAYpB,GAAG;IACrF,MAAMqB,WAAW,MAAMJ,OAAOK,MAAM,CAAwBH;IAC5D,MAAMI,SAASF,SAASG,SAAS;IAEjC,OAAO;QACLD;QACAE,SAAS;YACP,MAAMC,UAAU,MAAM3C,WAAW;gBAAEwC;gBAAQI,MAAM;gBAAOC,eAAe;YAAK;YAC5E,IAAIC,qBAAqBC,QAAQzC,OAAO;YACxC,MAAM0C,gBAAgB,CAACC;gBACrBH,qBAAqBA,mBAClBI,IAAI,CAAC,IAAMjD,OAAOgD,YAAYN,SAAS,QACvCQ,KAAK,CAAC,CAAC5C,QAAUK,QAAQL,KAAK,CAAC,uCAAuCA;gBACzE,OAAOuC;YACT;YAEAR,SAASc,SAAS,CAACJ;YAEnB,MAAMK,eAAef,SAASG,SAAS;YACvC,IAAID,WAAWa,cAAc;gBAC3B,MAAML,cAAcK;YACtB;QACF;IACF;AACF,EAAC"}
@@ -1,6 +0,0 @@
1
- import type { SanitizedConfig } from 'payload';
2
- type ConfigListener = (config: SanitizedConfig) => Promise<void> | void;
3
- export declare const getConfig: () => SanitizedConfig;
4
- export declare const subscribe: (nextListener: ConfigListener) => void;
5
- export {};
6
- //# sourceMappingURL=viteConfigBoundary.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"viteConfigBoundary.d.ts","sourceRoot":"","sources":["../../src/bin/viteConfigBoundary.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAM9C,KAAK,cAAc,GAAG,CAAC,MAAM,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;AAavE,eAAO,MAAM,SAAS,QAAO,eAAyB,CAAA;AAEtD,eAAO,MAAM,SAAS,GAAI,cAAc,cAAc,KAAG,IAExD,CAAA"}
@@ -1,25 +0,0 @@
1
- /// <reference types="vite/client" />
2
- /* eslint-disable no-console */ // @ts-expect-error - The Vite initializer resolves this ID to the Payload config.
3
- import * as configModule from 'payload-mcp:config';
4
- let listener;
5
- let configQueue = Promise.resolve();
6
- const resolveConfig = async (module)=>{
7
- const config = module;
8
- return await (config.default ?? module);
9
- };
10
- let config = await resolveConfig(configModule);
11
- export const getConfig = ()=>config;
12
- export const subscribe = (nextListener)=>{
13
- listener = nextListener;
14
- };
15
- import.meta.hot?.accept('payload-mcp:config', (nextModule)=>{
16
- if (!nextModule) {
17
- return;
18
- }
19
- configQueue = configQueue.then(async ()=>{
20
- config = await resolveConfig(nextModule);
21
- await listener?.(config);
22
- }).catch((error)=>console.error('[payload-mcp] config reload failed:', error));
23
- });
24
-
25
- //# sourceMappingURL=viteConfigBoundary.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/bin/viteConfigBoundary.ts"],"sourcesContent":["/// <reference types=\"vite/client\" />\n\nimport type { SanitizedConfig } from 'payload'\n\n/* eslint-disable no-console */\n// @ts-expect-error - The Vite initializer resolves this ID to the Payload config.\nimport * as configModule from 'payload-mcp:config'\n\ntype ConfigListener = (config: SanitizedConfig) => Promise<void> | void\n\nlet listener: ConfigListener | undefined\nlet configQueue = Promise.resolve()\n\nconst resolveConfig = async (module: unknown): Promise<SanitizedConfig> => {\n const config = module as { default?: unknown }\n\n return (await (config.default ?? module)) as SanitizedConfig\n}\n\nlet config = await resolveConfig(configModule)\n\nexport const getConfig = (): SanitizedConfig => config\n\nexport const subscribe = (nextListener: ConfigListener): void => {\n listener = nextListener\n}\n\nimport.meta.hot?.accept('payload-mcp:config', (nextModule) => {\n if (!nextModule) {\n return\n }\n\n configQueue = configQueue\n .then(async () => {\n config = await resolveConfig(nextModule)\n await listener?.(config)\n })\n .catch((error) => console.error('[payload-mcp] config reload failed:', error))\n})\n"],"names":["configModule","listener","configQueue","Promise","resolve","resolveConfig","module","config","default","getConfig","subscribe","nextListener","hot","accept","nextModule","then","catch","error","console"],"mappings":"AAAA,qCAAqC;AAIrC,6BAA6B,GAC7B,kFAAkF;AAClF,YAAYA,kBAAkB,qBAAoB;AAIlD,IAAIC;AACJ,IAAIC,cAAcC,QAAQC,OAAO;AAEjC,MAAMC,gBAAgB,OAAOC;IAC3B,MAAMC,SAASD;IAEf,OAAQ,MAAOC,CAAAA,OAAOC,OAAO,IAAIF,MAAK;AACxC;AAEA,IAAIC,SAAS,MAAMF,cAAcL;AAEjC,OAAO,MAAMS,YAAY,IAAuBF,OAAM;AAEtD,OAAO,MAAMG,YAAY,CAACC;IACxBV,WAAWU;AACb,EAAC;AAED,YAAYC,GAAG,EAAEC,OAAO,sBAAsB,CAACC;IAC7C,IAAI,CAACA,YAAY;QACf;IACF;IAEAZ,cAAcA,YACXa,IAAI,CAAC;QACJR,SAAS,MAAMF,cAAcS;QAC7B,MAAMb,WAAWM;IACnB,GACCS,KAAK,CAAC,CAACC,QAAUC,QAAQD,KAAK,CAAC,uCAAuCA;AAC3E"}
package/src/bin/index.ts DELETED
@@ -1,16 +0,0 @@
1
- import { runMcpStdio } from '../stdio.js'
2
-
3
- export const bin = async (): Promise<void> => {
4
- let viteHMR
5
- if (
6
- process.env.NODE_ENV !== 'production' &&
7
- process.env.NODE_ENV !== 'test' &&
8
- process.env.DISABLE_PAYLOAD_HMR !== 'true'
9
- ) {
10
- const { initializeViteHMR } = await import('./initializeViteHMR.js')
11
- viteHMR = await initializeViteHMR()
12
- }
13
-
14
- await runMcpStdio(viteHMR?.config)
15
- await viteHMR?.connect()
16
- }
@@ -1,76 +0,0 @@
1
- import type { SanitizedConfig } from 'payload'
2
-
3
- /* eslint-disable no-console */
4
- import { fileURLToPath } from 'node:url'
5
- import { getPayload, reload } from 'payload'
6
- import { findConfig, loadEnv } from 'payload/node'
7
-
8
- import type * as ConfigBoundary from './viteConfigBoundary.js'
9
-
10
- import { resolveProjectRoot } from '../utils/resolveProjectRoot.js'
11
-
12
- type ViteHMR = {
13
- config: SanitizedConfig
14
- connect: () => Promise<void>
15
- }
16
-
17
- export const initializeViteHMR = async (): Promise<undefined | ViteHMR> => {
18
- try {
19
- import.meta.resolve('vite')
20
- } catch (error) {
21
- if ((error as NodeJS.ErrnoException).code !== 'ERR_MODULE_NOT_FOUND') {
22
- throw error
23
- }
24
-
25
- if (process.env.NODE_ENV === 'development') {
26
- console.error(
27
- '[payload-mcp] Vite is not installed, so Payload config changes will not hot reload. Install vite@~8.1.4 as a development dependency to enable HMR during local development.',
28
- )
29
- }
30
- return
31
- }
32
-
33
- const { createServer, createServerModuleRunner, normalizePath } = await import('vite')
34
- const projectRoot = resolveProjectRoot(fileURLToPath(import.meta.url))
35
- if (projectRoot) {
36
- process.chdir(projectRoot)
37
- }
38
-
39
- loadEnv()
40
- const vite = await createServer({
41
- clearScreen: false,
42
- configFile: false,
43
- envDir: false,
44
- logLevel: 'error',
45
- optimizeDeps: { noDiscovery: true },
46
- publicDir: false,
47
- resolve: { alias: { 'payload-mcp:config': normalizePath(findConfig()) }, tsconfigPaths: true },
48
- server: { middlewareMode: true, ws: false },
49
- ssr: { noExternal: [/^@payloadcms\//, /^payload$/] },
50
- })
51
- const runner = createServerModuleRunner(vite.environments.ssr)
52
- const boundaryPath = fileURLToPath(new URL('./viteConfigBoundary.js', import.meta.url))
53
- const boundary = await runner.import<typeof ConfigBoundary>(boundaryPath)
54
- const config = boundary.getConfig()
55
-
56
- return {
57
- config,
58
- connect: async () => {
59
- const payload = await getPayload({ config, cron: false, disableOnInit: true })
60
- let payloadReloadQueue = Promise.resolve()
61
- const reloadPayload = (nextConfig: SanitizedConfig): Promise<void> => {
62
- payloadReloadQueue = payloadReloadQueue
63
- .then(() => reload(nextConfig, payload, false))
64
- .catch((error) => console.error('[payload-mcp] config reload failed:', error))
65
- return payloadReloadQueue
66
- }
67
-
68
- boundary.subscribe(reloadPayload)
69
-
70
- const latestConfig = boundary.getConfig()
71
- if (config !== latestConfig) {
72
- await reloadPayload(latestConfig)
73
- }
74
- },
75
- }
76
- }
@@ -1,39 +0,0 @@
1
- /// <reference types="vite/client" />
2
-
3
- import type { SanitizedConfig } from 'payload'
4
-
5
- /* eslint-disable no-console */
6
- // @ts-expect-error - The Vite initializer resolves this ID to the Payload config.
7
- import * as configModule from 'payload-mcp:config'
8
-
9
- type ConfigListener = (config: SanitizedConfig) => Promise<void> | void
10
-
11
- let listener: ConfigListener | undefined
12
- let configQueue = Promise.resolve()
13
-
14
- const resolveConfig = async (module: unknown): Promise<SanitizedConfig> => {
15
- const config = module as { default?: unknown }
16
-
17
- return (await (config.default ?? module)) as SanitizedConfig
18
- }
19
-
20
- let config = await resolveConfig(configModule)
21
-
22
- export const getConfig = (): SanitizedConfig => config
23
-
24
- export const subscribe = (nextListener: ConfigListener): void => {
25
- listener = nextListener
26
- }
27
-
28
- import.meta.hot?.accept('payload-mcp:config', (nextModule) => {
29
- if (!nextModule) {
30
- return
31
- }
32
-
33
- configQueue = configQueue
34
- .then(async () => {
35
- config = await resolveConfig(nextModule)
36
- await listener?.(config)
37
- })
38
- .catch((error) => console.error('[payload-mcp] config reload failed:', error))
39
- })