@frogbotai/plugin-mcp 0.29.0 → 0.30.0
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/dist/access.js +55 -29
- package/dist/access.js.map +1 -1
- package/dist/index.js +16 -17
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/access.js
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import { executeAuthStrategy } from 'frogbot/internal';
|
|
2
2
|
import { UnauthorizedError } from 'payload';
|
|
3
|
-
const toCamelCase = (value) =>
|
|
4
|
-
.replace(/[-_\s]+(.)?/g, (_, character) => character?.toUpperCase() ?? '')
|
|
5
|
-
.replace(/^(.)/, (_, character) => character.toLowerCase());
|
|
3
|
+
const toCamelCase = (value)=>value.replace(/[-_\s]+(.)?/g, (_, character)=>character?.toUpperCase() ?? '').replace(/^(.)/, (_, character)=>character.toLowerCase());
|
|
6
4
|
export function validateMcpCapabilities(pluginOptions) {
|
|
7
|
-
const reserved = new Set([
|
|
5
|
+
const reserved = new Set([
|
|
6
|
+
'auth',
|
|
7
|
+
'config',
|
|
8
|
+
'jobs'
|
|
9
|
+
]);
|
|
8
10
|
for (const [type, entities] of [
|
|
9
|
-
[
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
[
|
|
12
|
+
'Collection',
|
|
13
|
+
pluginOptions.collections
|
|
14
|
+
],
|
|
15
|
+
[
|
|
16
|
+
'Global',
|
|
17
|
+
pluginOptions.globals
|
|
18
|
+
]
|
|
19
|
+
]){
|
|
20
|
+
for (const slug of Object.keys(entities ?? {})){
|
|
13
21
|
const capability = toCamelCase(slug);
|
|
14
22
|
if (reserved.has(capability)) {
|
|
15
23
|
throw new Error(`[plugin-mcp] ${type} slug '${slug}' maps to reserved MCP capability '${capability}'.`);
|
|
@@ -18,23 +26,32 @@ export function validateMcpCapabilities(pluginOptions) {
|
|
|
18
26
|
}
|
|
19
27
|
}
|
|
20
28
|
function collectionGrants(options) {
|
|
21
|
-
return Object.fromEntries(Object.entries(options ?? {}).map(([slug, config])
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
return Object.fromEntries(Object.entries(options ?? {}).map(([slug, config])=>[
|
|
30
|
+
toCamelCase(slug),
|
|
31
|
+
config?.enabled === true ? {
|
|
32
|
+
create: true,
|
|
33
|
+
delete: true,
|
|
34
|
+
find: true,
|
|
35
|
+
update: true
|
|
36
|
+
} : config?.enabled
|
|
37
|
+
]));
|
|
27
38
|
}
|
|
28
39
|
function globalGrants(options) {
|
|
29
|
-
return Object.fromEntries(Object.entries(options ?? {}).map(([slug, config])
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
40
|
+
return Object.fromEntries(Object.entries(options ?? {}).map(([slug, config])=>[
|
|
41
|
+
toCamelCase(slug),
|
|
42
|
+
config?.enabled === true ? {
|
|
43
|
+
find: true,
|
|
44
|
+
update: true
|
|
45
|
+
} : config?.enabled
|
|
46
|
+
]));
|
|
33
47
|
}
|
|
34
48
|
function namedGrants(items) {
|
|
35
|
-
return Object.fromEntries((items ?? []).map(({ name })
|
|
49
|
+
return Object.fromEntries((items ?? []).map(({ name })=>[
|
|
50
|
+
toCamelCase(name),
|
|
51
|
+
true
|
|
52
|
+
]));
|
|
36
53
|
}
|
|
37
|
-
export async function resolveMcpAccess({ collection, strategy, pluginOptions, req
|
|
54
|
+
export async function resolveMcpAccess({ collection, strategy, pluginOptions, req }) {
|
|
38
55
|
const frogbotReq = req;
|
|
39
56
|
const frogbot = frogbotReq.frogbot;
|
|
40
57
|
let result;
|
|
@@ -45,16 +62,17 @@ export async function resolveMcpAccess({ collection, strategy, pluginOptions, re
|
|
|
45
62
|
frogbot,
|
|
46
63
|
headers: req.headers,
|
|
47
64
|
req: frogbotReq,
|
|
48
|
-
strategyName: strategy.name
|
|
65
|
+
strategyName: strategy.name
|
|
49
66
|
});
|
|
50
|
-
}
|
|
51
|
-
catch {
|
|
67
|
+
} catch {
|
|
52
68
|
throw new UnauthorizedError();
|
|
53
69
|
}
|
|
54
|
-
if (!result.user)
|
|
55
|
-
throw new UnauthorizedError();
|
|
70
|
+
if (!result.user) throw new UnauthorizedError();
|
|
56
71
|
return {
|
|
57
|
-
user: {
|
|
72
|
+
user: {
|
|
73
|
+
...result.user,
|
|
74
|
+
collection: result.user.collection ?? collection
|
|
75
|
+
},
|
|
58
76
|
...collectionGrants(pluginOptions.collections),
|
|
59
77
|
...globalGrants(pluginOptions.globals),
|
|
60
78
|
'payload-mcp-tool': namedGrants(pluginOptions.mcp?.tools),
|
|
@@ -66,10 +84,18 @@ export async function resolveMcpAccess({ collection, strategy, pluginOptions, re
|
|
|
66
84
|
login: false,
|
|
67
85
|
resetPassword: false,
|
|
68
86
|
unlock: false,
|
|
69
|
-
verify: false
|
|
87
|
+
verify: false
|
|
70
88
|
},
|
|
71
|
-
config: {
|
|
72
|
-
|
|
89
|
+
config: {
|
|
90
|
+
find: false,
|
|
91
|
+
update: false
|
|
92
|
+
},
|
|
93
|
+
jobs: {
|
|
94
|
+
create: false,
|
|
95
|
+
run: false,
|
|
96
|
+
update: false
|
|
97
|
+
}
|
|
73
98
|
};
|
|
74
99
|
}
|
|
100
|
+
|
|
75
101
|
//# sourceMappingURL=access.js.map
|
package/dist/access.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"sources":["../src/access.ts"],"names":["executeAuthStrategy","UnauthorizedError","toCamelCase","value","replace","_","character","toUpperCase","toLowerCase","validateMcpCapabilities","pluginOptions","reserved","Set","type","entities","collections","globals","slug","Object","keys","capability","has","Error","collectionGrants","options","fromEntries","entries","map","config","enabled","create","delete","find","update","globalGrants","namedGrants","items","name","resolveMcpAccess","collection","strategy","req","frogbotReq","frogbot","result","headers","strategyName","user","mcp","tools","prompts","resources","auth","forgotPassword","login","resetPassword","unlock","verify","jobs","run"],"mappings":"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","file":"access.js"}
|
package/dist/index.js
CHANGED
|
@@ -3,29 +3,28 @@ import { mcpPlugin as payloadMcpPlugin } from '@payloadcms/plugin-mcp';
|
|
|
3
3
|
import { resolveMcpAccess, validateMcpCapabilities } from './access.js';
|
|
4
4
|
export function mcpPlugin(pluginOptions = {}) {
|
|
5
5
|
validateMcpCapabilities(pluginOptions);
|
|
6
|
-
return async (config)
|
|
7
|
-
const apiKeyStrategy = config.collections
|
|
8
|
-
.flatMap((collection) => {
|
|
6
|
+
return async (config)=>{
|
|
7
|
+
const apiKeyStrategy = config.collections.flatMap((collection)=>{
|
|
9
8
|
const auth = typeof collection.auth === 'object' ? collection.auth : undefined;
|
|
10
|
-
return (auth?.strategies ?? []).map((strategy)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
})
|
|
15
|
-
.find(({ strategy }) => isApiKeyStrategy(strategy));
|
|
9
|
+
return (auth?.strategies ?? []).map((strategy)=>({
|
|
10
|
+
collection: collection.slug,
|
|
11
|
+
strategy
|
|
12
|
+
}));
|
|
13
|
+
}).find(({ strategy })=>isApiKeyStrategy(strategy));
|
|
16
14
|
if (!apiKeyStrategy) {
|
|
17
15
|
throw new Error('[plugin-mcp] apiKeysPlugin must be configured before mcpPlugin.');
|
|
18
16
|
}
|
|
19
17
|
const { experimental: _experimental, overrideAuth: _overrideAuth, ...options } = pluginOptions;
|
|
20
|
-
return
|
|
18
|
+
return await payloadMcpPlugin({
|
|
21
19
|
...options,
|
|
22
|
-
overrideAuth: (req)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
})(config)
|
|
20
|
+
overrideAuth: (req)=>resolveMcpAccess({
|
|
21
|
+
collection: apiKeyStrategy.collection,
|
|
22
|
+
strategy: apiKeyStrategy.strategy,
|
|
23
|
+
pluginOptions: options,
|
|
24
|
+
req
|
|
25
|
+
})
|
|
26
|
+
})(config);
|
|
29
27
|
};
|
|
30
28
|
}
|
|
29
|
+
|
|
31
30
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["isApiKeyStrategy","mcpPlugin","payloadMcpPlugin","resolveMcpAccess","validateMcpCapabilities","pluginOptions","config","apiKeyStrategy","collections","flatMap","collection","auth","undefined","strategies","map","strategy","slug","find","Error","experimental","_experimental","overrideAuth","_overrideAuth","options","req"],"mappings":"AAAA,SAASA,gBAAgB,QAAQ,6BAA6B;AAE9D,SAASC,aAAaC,gBAAgB,QAAQ,yBAAyB;AAGvE,SAASC,gBAAgB,EAAEC,uBAAuB,QAAQ,cAAc;AAIxE,OAAO,SAASH,UAAUI,gBAAkC,CAAC,CAAC;IAC5DD,wBAAwBC;IAExB,OAAO,OAAOC;QACZ,MAAMC,iBAAiBD,OAAOE,WAAW,CACtCC,OAAO,CAAC,CAACC;YACR,MAAMC,OAAO,OAAOD,WAAWC,IAAI,KAAK,WAAWD,WAAWC,IAAI,GAAGC;YAErE,OAAO,AAACD,CAAAA,MAAME,cAAc,EAAE,AAAD,EAAGC,GAAG,CAAC,CAACC,WAAc,CAAA;oBACjDL,YAAYA,WAAWM,IAAI;oBAC3BD;gBACF,CAAA;QACF,GACCE,IAAI,CAAC,CAAC,EAAEF,QAAQ,EAAE,GAAKf,iBAAiBe;QAE3C,IAAI,CAACR,gBAAgB;YACnB,MAAM,IAAIW,MAAM;QAClB;QAEA,MAAM,EACJC,cAAcC,aAAa,EAC3BC,cAAcC,aAAa,EAC3B,GAAGC,SACJ,GAAGlB;QAEJ,OAAQ,MAAMH,iBAAiB;YAC7B,GAAGqB,OAAO;YACVF,cAAc,CAACG,MACbrB,iBAAiB;oBACfO,YAAYH,eAAeG,UAAU;oBACrCK,UAAUR,eAAeQ,QAAQ;oBACjCV,eAAekB;oBACfC;gBACF;QACJ,GAAGlB;IACL;AACF","file":"index.js"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frogbotai/plugin-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.0",
|
|
4
4
|
"description": "Payload MCP integration for FrogBot.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Colby Gilbert",
|
|
@@ -31,21 +31,21 @@
|
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"payload": "3.90.1",
|
|
34
|
-
"@frogbotai/plugin-api-keys": "0.
|
|
35
|
-
"frogbot": "0.
|
|
34
|
+
"@frogbotai/plugin-api-keys": "0.30.0",
|
|
35
|
+
"frogbot": "0.30.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"payload": "3.90.1",
|
|
39
39
|
"typescript": "5.6.2",
|
|
40
|
-
"@frogbotai/plugin-roles": "0.
|
|
41
|
-
"@frogbotai/plugin-api-keys": "0.
|
|
42
|
-
"frogbot": "0.
|
|
40
|
+
"@frogbotai/plugin-roles": "0.30.0",
|
|
41
|
+
"@frogbotai/plugin-api-keys": "0.30.0",
|
|
42
|
+
"frogbot": "0.30.0"
|
|
43
43
|
},
|
|
44
44
|
"publishConfig": {
|
|
45
45
|
"access": "public"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
|
-
"build": "
|
|
48
|
+
"build": "node ../../../scripts/build-package.mjs",
|
|
49
49
|
"clean": "rm -rf dist",
|
|
50
50
|
"typecheck": "tsc --noEmit"
|
|
51
51
|
}
|