feat(mcp): enable Payload MCP plugin
Register mcpPlugin on the Payload config. Auth now also accepts payload-mcp-api-keys, so the generated types carry the new collection and the user union widens accordingly. Follow-up commits guard user auth paths against these API-key sessions. Also apply incidental prettier formatting to generatePlainText().
This commit is contained in:
parent
83790a629b
commit
b70ff4dff8
3 changed files with 89 additions and 14 deletions
|
|
@ -35,6 +35,7 @@
|
||||||
"@payloadcms/email-nodemailer": "3.88.0",
|
"@payloadcms/email-nodemailer": "3.88.0",
|
||||||
"@payloadcms/next": "3.88.0",
|
"@payloadcms/next": "3.88.0",
|
||||||
"@payloadcms/payload-cloud": "3.88.0",
|
"@payloadcms/payload-cloud": "3.88.0",
|
||||||
|
"@payloadcms/plugin-mcp": "^3.88.0",
|
||||||
"@payloadcms/richtext-lexical": "3.88.0",
|
"@payloadcms/richtext-lexical": "3.88.0",
|
||||||
"@payloadcms/ui": "3.88.0",
|
"@payloadcms/ui": "3.88.0",
|
||||||
"@radix-ui/react-avatar": "^1.2.6",
|
"@radix-ui/react-avatar": "^1.2.6",
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ export type SupportedTimezones =
|
||||||
export interface Config {
|
export interface Config {
|
||||||
auth: {
|
auth: {
|
||||||
users: UserAuthOperations;
|
users: UserAuthOperations;
|
||||||
|
'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations;
|
||||||
};
|
};
|
||||||
blocks: {};
|
blocks: {};
|
||||||
collections: {
|
collections: {
|
||||||
|
|
@ -112,6 +113,7 @@ export interface Config {
|
||||||
'arma-sync-events': ArmaSyncEvent;
|
'arma-sync-events': ArmaSyncEvent;
|
||||||
'arma-commands': ArmaCommand;
|
'arma-commands': ArmaCommand;
|
||||||
'plugin-ai-instructions': PluginAiInstruction;
|
'plugin-ai-instructions': PluginAiInstruction;
|
||||||
|
'payload-mcp-api-keys': PayloadMcpApiKey;
|
||||||
'payload-kv': PayloadKv;
|
'payload-kv': PayloadKv;
|
||||||
'payload-locked-documents': PayloadLockedDocument;
|
'payload-locked-documents': PayloadLockedDocument;
|
||||||
'payload-preferences': PayloadPreference;
|
'payload-preferences': PayloadPreference;
|
||||||
|
|
@ -171,6 +173,7 @@ export interface Config {
|
||||||
'arma-sync-events': ArmaSyncEventsSelect<false> | ArmaSyncEventsSelect<true>;
|
'arma-sync-events': ArmaSyncEventsSelect<false> | ArmaSyncEventsSelect<true>;
|
||||||
'arma-commands': ArmaCommandsSelect<false> | ArmaCommandsSelect<true>;
|
'arma-commands': ArmaCommandsSelect<false> | ArmaCommandsSelect<true>;
|
||||||
'plugin-ai-instructions': PluginAiInstructionsSelect<false> | PluginAiInstructionsSelect<true>;
|
'plugin-ai-instructions': PluginAiInstructionsSelect<false> | PluginAiInstructionsSelect<true>;
|
||||||
|
'payload-mcp-api-keys': PayloadMcpApiKeysSelect<false> | PayloadMcpApiKeysSelect<true>;
|
||||||
'payload-kv': PayloadKvSelect<false> | PayloadKvSelect<true>;
|
'payload-kv': PayloadKvSelect<false> | PayloadKvSelect<true>;
|
||||||
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
|
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
|
||||||
'payload-preferences': PayloadPreferencesSelect<false> | PayloadPreferencesSelect<true>;
|
'payload-preferences': PayloadPreferencesSelect<false> | PayloadPreferencesSelect<true>;
|
||||||
|
|
@ -192,7 +195,7 @@ export interface Config {
|
||||||
widgets: {
|
widgets: {
|
||||||
collections: CollectionsWidget;
|
collections: CollectionsWidget;
|
||||||
};
|
};
|
||||||
user: User;
|
user: User | PayloadMcpApiKey;
|
||||||
jobs: {
|
jobs: {
|
||||||
tasks: unknown;
|
tasks: unknown;
|
||||||
workflows: unknown;
|
workflows: unknown;
|
||||||
|
|
@ -214,6 +217,24 @@ export interface UserAuthOperations {
|
||||||
username: string;
|
username: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
export interface PayloadMcpApiKeyAuthOperations {
|
||||||
|
forgotPassword: {
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
};
|
||||||
|
login: {
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
};
|
||||||
|
registerFirstUser: {
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
};
|
||||||
|
unlock: {
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "media".
|
* via the `definition` "media".
|
||||||
|
|
@ -2872,6 +2893,33 @@ export interface PluginAiInstruction {
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* API keys control which collections, resources, tools, and prompts MCP clients can access
|
||||||
|
*
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "payload-mcp-api-keys".
|
||||||
|
*/
|
||||||
|
export interface PayloadMcpApiKey {
|
||||||
|
id: number;
|
||||||
|
/**
|
||||||
|
* The user that the API key is associated with.
|
||||||
|
*/
|
||||||
|
user: number | User;
|
||||||
|
/**
|
||||||
|
* A useful label for the API key.
|
||||||
|
*/
|
||||||
|
label?: string | null;
|
||||||
|
/**
|
||||||
|
* The purpose of the API key.
|
||||||
|
*/
|
||||||
|
description?: string | null;
|
||||||
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
enableAPIKey?: boolean | null;
|
||||||
|
apiKey?: string | null;
|
||||||
|
apiKeyIndex?: string | null;
|
||||||
|
collection: 'payload-mcp-api-keys';
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "payload-kv".
|
* via the `definition` "payload-kv".
|
||||||
|
|
@ -3075,12 +3123,21 @@ export interface PayloadLockedDocument {
|
||||||
| ({
|
| ({
|
||||||
relationTo: 'plugin-ai-instructions';
|
relationTo: 'plugin-ai-instructions';
|
||||||
value: number | PluginAiInstruction;
|
value: number | PluginAiInstruction;
|
||||||
|
} | null)
|
||||||
|
| ({
|
||||||
|
relationTo: 'payload-mcp-api-keys';
|
||||||
|
value: number | PayloadMcpApiKey;
|
||||||
} | null);
|
} | null);
|
||||||
globalSlug?: string | null;
|
globalSlug?: string | null;
|
||||||
user: {
|
user:
|
||||||
relationTo: 'users';
|
| {
|
||||||
value: number | User;
|
relationTo: 'users';
|
||||||
};
|
value: number | User;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
relationTo: 'payload-mcp-api-keys';
|
||||||
|
value: number | PayloadMcpApiKey;
|
||||||
|
};
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
|
@ -3090,10 +3147,15 @@ export interface PayloadLockedDocument {
|
||||||
*/
|
*/
|
||||||
export interface PayloadPreference {
|
export interface PayloadPreference {
|
||||||
id: number;
|
id: number;
|
||||||
user: {
|
user:
|
||||||
relationTo: 'users';
|
| {
|
||||||
value: number | User;
|
relationTo: 'users';
|
||||||
};
|
value: number | User;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
relationTo: 'payload-mcp-api-keys';
|
||||||
|
value: number | PayloadMcpApiKey;
|
||||||
|
};
|
||||||
key?: string | null;
|
key?: string | null;
|
||||||
value?:
|
value?:
|
||||||
| {
|
| {
|
||||||
|
|
@ -4364,6 +4426,20 @@ export interface PluginAiInstructionsSelect<T extends boolean = true> {
|
||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "payload-mcp-api-keys_select".
|
||||||
|
*/
|
||||||
|
export interface PayloadMcpApiKeysSelect<T extends boolean = true> {
|
||||||
|
user?: T;
|
||||||
|
label?: T;
|
||||||
|
description?: T;
|
||||||
|
updatedAt?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
enableAPIKey?: T;
|
||||||
|
apiKey?: T;
|
||||||
|
apiKeyIndex?: T;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "payload-kv_select".
|
* via the `definition` "payload-kv_select".
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ import { nodemailerAdapter } from "@payloadcms/email-nodemailer";
|
||||||
import nodemailer from "nodemailer";
|
import nodemailer from "nodemailer";
|
||||||
import { Shims } from "@/collections/Shims";
|
import { Shims } from "@/collections/Shims";
|
||||||
import { payloadAiPlugin, PayloadAiPluginLexicalEditorFeature } from "@ai-stack/payloadcms";
|
import { payloadAiPlugin, PayloadAiPluginLexicalEditorFeature } from "@ai-stack/payloadcms";
|
||||||
|
import { mcpPlugin } from "@payloadcms/plugin-mcp";
|
||||||
import { createOpenAI } from "@ai-sdk/openai";
|
import { createOpenAI } from "@ai-sdk/openai";
|
||||||
import { createTextStreamResponse, jsonSchema, streamObject } from "ai";
|
import { createTextStreamResponse, jsonSchema, streamObject } from "ai";
|
||||||
|
|
||||||
|
|
@ -104,11 +105,7 @@ function plainTextToLexicalJson(text: string): Record<string, unknown> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generatePlainText(
|
async function generatePlainText(prompt: string, system: string, model: string): Promise<string> {
|
||||||
prompt: string,
|
|
||||||
system: string,
|
|
||||||
model: string,
|
|
||||||
): Promise<string> {
|
|
||||||
const baseUrl = process.env.UNSLOTH_URL || "https://uns.onyxsimple.com/v1";
|
const baseUrl = process.env.UNSLOTH_URL || "https://uns.onyxsimple.com/v1";
|
||||||
const response = await fetch(`${baseUrl}/chat/completions`, {
|
const response = await fetch(`${baseUrl}/chat/completions`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
|
@ -288,6 +285,7 @@ export default buildConfig({
|
||||||
plugins: [
|
plugins: [
|
||||||
// payloadCloudPlugin(),
|
// payloadCloudPlugin(),
|
||||||
// storage-adapter-placeholder
|
// storage-adapter-placeholder
|
||||||
|
mcpPlugin({}),
|
||||||
payloadAiPlugin({
|
payloadAiPlugin({
|
||||||
collections: {
|
collections: {
|
||||||
[GameHardResources.slug]: true,
|
[GameHardResources.slug]: true,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue