Strapi插件AI SDK
Strapi v5插件在管理面板中添加了一个人工智能聊天助手,为前端应用程序(Next.js等)公开了人工智能端点,并为外部人工智能客户端提供了一个MCP服务器。建立在 Vercel AI 开发工具包 和 人物克劳德 作为默认提供者。
特性
- 管理员聊天界面 使用markdown渲染、工具调用可视化、对话历史和内存管理
- 内容工具 --人工智能可以列出内容类型、搜索内容、创建/更新文档和发送电子邮件
- API终点 --
/ask,/ask-stream,以及/chat用于前端消费(兼容useChat从@ai-sdk/react) - 公共聊天 --使用只读工具和单独的公共内存存储进行沙盒面向公众的聊天
- 可嵌入小部件 --放弃一个单一 `` 在任何网站上添加标签以添加AI聊天气泡
- MCP服务器 --通过模型上下文协议将工具暴露给外部AI客户端(Claude Desktop、Cursor等)
- 护栏 --基于正则表达式的输入安全中间件,可阻止提示注入、越狱和破坏性命令
- 可扩展 --在运行时注册自定义工具和AI提供商
快速开始
1.安装并启用
在你的Strapi项目中 config/plugins.ts:
export default ({ env }) => ({
'ai-sdk': {
enabled: true,
resolve: 'src/plugins/ai-sdk', // or the npm package path
config: {
anthropicApiKey: env('ANTHROPIC_API_KEY'),
chatModel: env('ANTHROPIC_MODEL', 'claude-sonnet-4-20250514'),
},
},
});2.设置环境变量
ANTHROPIC_API_KEY=sk-ant-your-api-key-here
ANTHROPIC_MODEL=claude-sonnet-4-20250514 # optional3.构建并启动
npm run build
npm run develop4.启用权限
在Strapi管理面板中:
- 首选 设置>用户和权限>角色
- 选择 公共 (或你想要的角色)
- 在...之下 Ai sdk,启用
ask,askStream,以及chat - 保存
可嵌入聊天小部件
添加一个浮动的AI聊天气泡 任何网站 使用单个脚本标签。无需安装npm,无需构建步骤,也不需要React。
1.启用公共聊天端点
在Strapi管理面板中:
- 首选 设置>用户和权限>角色>公共
- 在...之下 Ai sdk,启用
publicChat和serveWidget - 保存
2.添加脚本标签
就是这样。右下角出现了一个浮动聊天按钮。小部件会自动从脚本中检测其Strapi URL src.
通过数据属性进行配置
| 属性 | 描述 |
|---|---|
data-api-token | 用于已验证请求的可选API令牌 |
data-system-prompt | 覆盖默认系统提示 |
运作原理
- 该小部件在内部捆绑了React和AI SDK(约130KB gzip压缩)
- 它在Shadow DOM中呈现,因此样式永远不会与页面冲突
- 它使用
/api/ai-sdk/public-chat仅公开只读工具的端点
公共聊天vs管理员聊天
| 功能 | 管理员聊天(/chat) | 公共聊天(/public-chat) |
|---|---|---|
| 身份验证 | 需要管理员JWT | 无(公共端点) |
| 可用工具 | 所有工具(读+写) | 只读工具 |
| 内存存储 | 每个用户的私人内存 | 共享的公共内存 |
| 内容访问 | 所有内容类型 | 仅配置 allowedContentTypes |
配置公共聊天
在 config/plugins.ts,添加 publicChat 通过内容类型,访问者可以查询:
'ai-sdk': {
enabled: true,
config: {
anthropicApiKey: env('ANTHROPIC_API_KEY'),
publicChat: {
chatModel: 'claude-haiku-4-5-20251001', // optional: use a cheaper model for public chat
allowedContentTypes: [
'api::article.article',
'api::category.category',
'api::product.product',
],
},
},
},如果 allowedContentTypes 如果是空数组,公共聊天将无法访问内容。
管理公众记忆
公共记忆是人工智能在与访客交谈时知道的事实(例如,“我们的退货政策是30天”)。从Strapi管理面板管理它们:
- 去 AI SDK 插件页面
- 单击聊天工具栏中的地球图标
- 按类别添加、编辑或删除公共记忆:一般、常见问题、产品、政策
配置
所有插件设置都进入 config/plugins.ts 在...之下 ai-sdk 按键:
export default ({ env }) => ({
'ai-sdk': {
enabled: true,
config: {
// AI Provider (required)
anthropicApiKey: env('ANTHROPIC_API_KEY'),
provider: 'anthropic', // default
chatModel: 'claude-sonnet-4-20250514', // default
baseURL: undefined, // custom API base URL
// System Prompt (optional)
systemPrompt: 'You are a helpful CMS assistant.\n\n{tools}',
// MCP Session Tuning (optional)
mcp: {
sessionTimeoutMs: 4 * 60 * 60 * 1000, // 4 hours (default)
maxSessions: 100, // default
cleanupInterval: 100, // cleanup every N requests
},
// Public Chat (optional)
publicChat: {
chatModel: 'claude-haiku-4-5-20251001', // optional cheaper model
allowedContentTypes: ['api::article.article'],
},
// Guardrails (optional)
guardrails: {
enabled: true, // default
maxInputLength: 10000, // default
additionalPatterns: [], // extra regex patterns
disableDefaultPatterns: false, // use only your own patterns
blockedMessage: 'Custom blocked message.', // override default message
},
},
},
});支持的Claude模型
claude-sonnet-4-20250514(默认)claude-opus-4-20250514claude-haiku-4-5-20251001claude-3-5-sonnet-20241022claude-3-5-haiku-20241022
API终点
内容API(适用于前端应用程序)
| 方法 | 端点 | 描述 |
|---|---|---|
POST | /api/ai-sdk/ask | 非流式文本生成 |
POST | /api/ai-sdk/ask-stream | 通过服务器发送的事件流式传输文本 |
POST | /api/ai-sdk/chat | 使用AI SDK UI消息流协议聊天 |
POST | /api/ai-sdk/public-chat | 使用只读工具和公共记忆进行公共聊天 |
GET | /api/ai-sdk/widget.js | 可嵌入聊天小部件脚本 |
POST | /api/ai-sdk/mcp | MCP JSON-RPC请求 |
GET | /api/ai-sdk/mcp | MCP会话管理 |
DELETE | /api/ai-sdk/mcp | MCP会话清理 |
管理员API(仅限管理面板)
| 方法 | 端点 | 描述 |
|---|---|---|
POST | /ai-sdk/chat | 具有完整工具访问权限的管理员聊天 |
所有有用户输入的路线都受到护栏中间件的保护。
发布 /api/ai-sdk/ask
生成文本响应(非流式)。
请求:
{
"prompt": "What is the capital of France?",
"system": "You are a helpful geography assistant."
}| 字段 | 类型 | 必填 | 描述 |
|---|---|---|---|
prompt | string | 是 | 用户的问题或提示 |
system | string | 否 | 系统提示覆盖 |
答复:
{
"data": {
"text": "The capital of France is Paris."
}
}发布 /api/ai-sdk/ask-stream
通过服务器发送事件生成流式文本。
请求: 同 /ask
答复: SSE流
data: {"text":"The"}
data: {"text":" capital"}
data: {"text":" of France is Paris."}
data: [DONE]发布 /api/ai-sdk/chat
聊天端点使用AI SDK UI消息流协议。与兼容 useChat 钩子从 @ai-sdk/react支持通过工具调用进行多回合对话。
请求:
{
"messages": [
{ "role": "user", "content": "Hello!" },
{ "role": "assistant", "content": "Hi there! How can I help you?" },
{ "role": "user", "content": "List all my content types" }
],
"system": "You are a helpful assistant."
}| 字段 | 类型 | 必填 | 描述 |
|---|---|---|---|
messages | array | Yes | 消息对象数组 role 和 content |
system | string | 否 | 系统提示覆盖 |
答复: UI消息流(x-vercel-ai-ui-message-stream: v1 协议)与文本增量和工具调用事件。
内置工具
AI助手可以访问这些工具。标记为的工具 公共 也通过MCP暴露。
| 工具 | MCP名称 | 描述 |
|---|---|---|
listContentTypes | list_content_types | 列出所有Strapi内容类型和组件及其字段和关系 |
searchContent | search_content | 使用过滤器、排序和分页搜索和查询任何内容类型 |
aggregateContent | aggregate_content | 计数、分组和分析内容(比searchContent更快进行分析) |
writeContent | write_content | 创建或更新任何内容类型的文档 |
sendEmail | send_email | 通过配置的电子邮件提供商发送电子邮件(例如重新发送) |
此外,AI SDK会自动从其他已安装的插件中发现工具(请参阅 扩展插件).例如,安装了提及和嵌入插件后,AI还可以访问 searchMentions, semanticSearch, ragQuery以及更多。
工具详细信息
搜索内容 参数: contentType (必填), query, filters, fields, sort, page, pageSize (最多50个)
writeContent 参数: contentType (必填), action (create 或 update), documentId (需要更新), data (必填), status (draft 或 published)
send电子邮件 参数: to (必填), subject (必填), html (必填), text, cc, bcc, replyTo该工具在发送之前始终与用户确认收件人。看 文档/发送电子邮件-带-resend.md 用于设置。
MCP服务器
该插件公开了一个 主控程序 服务器在 /api/ai-sdk/mcp 它允许外部AI客户端(Claude Desktop、Claude Code、Cursor、Windsurf等)直接调用公共工具。
运作原理
- 使用低级MCP
Server类,用于完全控制JSON模式输出,确保与mcp-remote以及所有MCP客户端,无论Zod版本如何 - 使用 可流式HTTP传输 (MCP 2025-03-26规范)
- 会话在第一次请求时创建,并由
mcp-session-id头球 - 工具名称从camelCase转换为snake_case(
listContentTypes->list_content_types) - 每个工具包括
title(例如“Strapi:搜索内容”)和annotations(readOnlyHint,destructiveHint)实现更好的客户端集成 - 所有工具模式包括
additionalProperties: false以确保与mcp-remote和克劳德桌面 - 自定义Zod到JSON模式转换器,支持Zod 3和Zod 4,为每个参数生成完整的类型信息(类型、描述、默认值、枚举、约束)
- MCP参数在执行前通过Zod模式强制执行——字符串化的JSON值(例如。
fields: '["title"]')自动解析为预期类型,并对省略的可选参数应用默认值 - 服务器返回动态
instructions在初始化过程中,这样客户端就知道何时加载工具——提供getMeta()获取关键字驱动的条目(例如。/youtube,/octalens),其他人则获得自动生成的摘要 - 会话在配置的超时后过期(默认值:4小时)
- 可以配置最大并发会话数(默认值:100)
设置
1.启用权限
在Strapi管理面板中:
- 首选 设置>API令牌
- 创建新的API令牌(或使用现有令牌)
- 在...之下 权限,启用 Ai sdk 行动:
handle(涵盖MCP的POST、GET、DELETE) - 复制令牌
或者,对于没有令牌的公共访问:
- 首选 设置>用户和权限>角色>公共
- 在...之下 Ai sdk,启用
handle - 保存
2.连接您的AI客户端
MCP端点URL为:
http://localhost:1337/api/ai-sdk/mcp对于远程部署,请替换 localhost:1337 使用您的Strapi URL。
从克劳德桌面连接
添加 ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)或 %APPDATA%\Claude\claude_desktop_config.json (Windows):
无身份验证(启用公共权限):
{
"mcpServers": {
"strapi": {
"url": "http://localhost:1337/api/ai-sdk/mcp"
}
}
}使用API令牌:
{
"mcpServers": {
"strapi": {
"command": "npx",
"args": [
"mcp-remote",
"http://localhost:1337/api/ai-sdk/mcp",
"--header",
"Authorization: Bearer YOUR_STRAPI_API_TOKEN"
]
}
}
}保存配置后重新启动Claude Desktop。
从克劳德代码连接
添加 ~/.claude/settings.json:
{
"mcpServers": {
"strapi": {
"command": "npx",
"args": [
"mcp-remote",
"http://localhost:1337/api/ai-sdk/mcp",
"--header",
"Authorization: Bearer YOUR_STRAPI_API_TOKEN"
]
}
}
}或运行: claude mcp add strapi -- npx mcp-remote http://localhost:1337/api/ai-sdk/mcp --header "Authorization: Bearer YOUR_STRAPI_API_TOKEN"
从游标连接
添加到光标MCP设置(.cursor/mcp.json):
无身份验证:
{
"mcpServers": {
"strapi": {
"url": "http://localhost:1337/api/ai-sdk/mcp"
}
}
}使用API令牌:
{
"mcpServers": {
"strapi": {
"command": "npx",
"args": [
"mcp-remote",
"http://localhost:1337/api/ai-sdk/mcp",
"--header",
"Authorization: Bearer YOUR_STRAPI_API_TOKEN"
]
}
}
}使用cURL进行测试
# 1. Initialize a session
curl -s -X POST http://localhost:1337/api/ai-sdk/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer YOUR_STRAPI_API_TOKEN" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}'
# 2. Send initialized notification (use the mcp-session-id from step 1)
curl -s -X POST http://localhost:1337/api/ai-sdk/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_STRAPI_API_TOKEN" \
-H "mcp-session-id: SESSION_ID_FROM_STEP_1" \
-d '{"jsonrpc":"2.0","method":"notifications/initialized"}'
# 3. List available tools
curl -s -X POST http://localhost:1337/api/ai-sdk/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer YOUR_STRAPI_API_TOKEN" \
-H "mcp-session-id: SESSION_ID_FROM_STEP_1" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
# 4. Call a tool
curl -s -X POST http://localhost:1337/api/ai-sdk/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer YOUR_STRAPI_API_TOKEN" \
-H "mcp-session-id: SESSION_ID_FROM_STEP_1" \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"list_content_types","arguments":{}}}'MCP配置
// config/plugins.ts
config: {
mcp: {
sessionTimeoutMs: 4 * 60 * 60 * 1000, // 4 hours (default)
maxSessions: 100, // default
cleanupInterval: 100, // cleanup expired sessions every N requests
},
}护栏
该插件包含一个护栏中间件,在用户输入到达AI之前对其进行检查。它在每个AI端点上运行(/ask, /ask-stream, /chat, /mcp).
它捕获了什么
- 提示注入 --“忽略之前的所有指示”,“覆盖您的规则”
- 越狱企图 --“您现在处于开发人员模式”、“DAN模式”
- 系统提示提取 --“显示你的系统提示”,“你被告知了什么”
- 系统提示模仿 --假的
[SYSTEM]:在用户输入中注入分隔符 - 破坏性命令 --“删除所有内容”、“删除表”、“rm-rf”
运作原理
- 提取用户输入(适应请求形状:消息、提示或JSON-RPC参数)
- 运行可选
beforeProcess钩子(用于外部审核API等自定义逻辑) - 规范化文本(NFKC、条带零宽度字符、折叠空白)
- 与编译的正则表达式模式匹配
- 检查输入长度(默认最大值:10000个字符)
阻止的请求返回路由感知响应:聊天路由得到SSE消息(在UI中自然呈现),API路由得到403 JSON错误。
有关完整详细信息、模式列表和 beforeProcess 挂钩API,参见 docs/guardails.md.
前端集成(Next.js)
使用 useChat (推荐)
这 /chat 端点与完全兼容 useChat 钩子从 @ai-sdk/react:
npm install @ai-sdk/react'use client';
import { useChat } from '@ai-sdk/react';
export default function Chat() {
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({
api: 'http://localhost:1337/api/ai-sdk/chat',
});
return (
{messages.map((message) => (
{message.role}: {message.content}
))}
{isLoading ? 'Sending...' : 'Send'}
);
}非流媒体请求
const response = await fetch('http://localhost:1337/api/ai-sdk/ask', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
prompt: 'Explain quantum computing in simple terms',
}),
});
const { data } = await response.json();
console.log(data.text);流媒体请求
const response = await fetch('http://localhost:1337/api/ai-sdk/ask-stream', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt: 'Write a short story about a robot' }),
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value, { stream: true });
const lines = chunk.split('\n').filter(line => line.startsWith('data: '));
for (const line of lines) {
const data = line.replace('data: ', '');
if (data === '[DONE]') continue;
const { text } = JSON.parse(data);
process.stdout.write(text);
}
}cURL
# Non-streaming
curl -X POST http://localhost:1337/api/ai-sdk/ask \
-H "Content-Type: application/json" \
-d '{"prompt": "Hello, how are you?"}'
# Streaming
curl -N -X POST http://localhost:1337/api/ai-sdk/ask-stream \
-H "Content-Type: application/json" \
-d '{"prompt": "Count from 1 to 10"}'扩展插件
从其他插件添加工具(基于约定的发现)
任何Strapi插件都可以通过公开 ai-tools 服务与a getTools() 方法。AI SDK在启动时自动发现这些,无需配置。
flowchart LR
subgraph "AI SDK Bootstrap"
B[Scan all plugins]
end
subgraph "Plugin A"
A1[ai-tools service] --> A2["getTools()"]
end
subgraph "Plugin B"
B1[ai-tools service] --> B2["getTools()"]
end
B --> A1
B --> B1
A2 --> R[ToolRegistry]
B2 --> R
R --> Chat[Admin Chat]
R --> MCP[MCP Server]
R --> Public[Public Chat]运作原理
- 启动时,AI SDK会扫描每个加载的插件以查找
ai-tools服务 - 如果找到,它会调用
getTools()它返回一个数组ToolDefinition物体 - 每个工具的名称间隔为
pluginName__toolName(例如。,octalens_mentions__searchMentions)防止碰撞 - 发现的工具在共享中注册
ToolRegistry与内置工具一起 - 所有注册的工具都可以在管理员聊天、公共聊天(如果
publicSafe: true),以及MCP
创建一个 ai-tools 插件中的服务
1.定义规范工具 在 server/src/tools/:
// server/src/tools/my-tool.ts
import { z } from 'zod';
import type { Core } from '@strapi/strapi';
const schema = z.object({
query: z.string().describe('Search query'),
limit: z.number().min(1).max(50).optional().default(10).describe('Max results'),
});
export const mySearchTool = {
name: 'mySearch',
description: 'Search my plugin data with relevance ranking.',
schema,
execute: async (args: z.infer, strapi: Core.Strapi) => {
const validated = schema.parse(args);
const results = await strapi.documents('plugin::my-plugin.item' as any).findMany({
filters: { title: { $containsi: validated.query } },
limit: validated.limit,
});
return { results, total: results.length };
},
publicSafe: true, // available in public chat (read-only operations)
};2.创建 ai-tools 可选服务 getMeta():
// server/src/services/ai-tools.ts
import type { Core } from '@strapi/strapi';
import { tools } from '../tools';
export default ({ strapi }: { strapi: Core.Strapi }) => ({
getTools() {
return tools;
},
/**
* Optional: provide metadata so the MCP server instructions
* include your plugin's capabilities and trigger keywords.
* Without this, a summary is auto-generated from tool descriptions.
*/
getMeta() {
return {
label: 'My Plugin',
description: 'Search and manage my plugin data with relevance ranking',
keywords: ['/my-plugin', 'my data', 'search my stuff'],
};
},
});3.注册服务:
// server/src/services/index.ts
import myService from './my-service';
import aiTools from './ai-tools';
export default {
'my-service': myService,
'ai-tools': aiTools,
};就是这样。AI SDK将在下次Strapi重启时发现并注册您的工具。
工具定义界面
interface ToolDefinition {
name: string; // camelCase, unique within your plugin
description: string; // Clear description for the AI model
schema: z.ZodObject; // Zod schema for parameter validation
execute: (args: any, strapi: Core.Strapi, context?: ToolContext) => Promise;
internal?: boolean; // If true, hidden from MCP (AI chat only)
publicSafe?: boolean; // If true, available in public/widget chat
}ToolSourceMeta接口(可选 getMeta())
当你的插件提供 getMeta() 在其 ai-tools 服务,MCP服务器指令包括您的插件与触发器关键字的功能。这有助于Claude Desktop的“需要时加载工具”模式为插件的查询激活正确的服务器。
没有 getMeta(),AI SDK会根据您的工具描述自动生成摘要,因此这是可选的,但建议用于更好的可发现性。
interface ToolSourceMeta {
label: string; // Human-readable label, e.g. "YouTube Transcripts"
description: string; // One-line capability summary for MCP instructions
keywords?: string[]; // Trigger keywords/prefixes, e.g. ["/youtube", "/yt", "transcript"]
}以开头的关键字 / 在指令中呈现为斜线命令提示(例如。 /youtube or /yt — Fetch and search YouTube transcripts).其他关键字作为自然语言触发器包含在内。
规范架构模式
建议的模式是一次性定义工具 server/src/tools/ 并从AI SDK服务和MCP处理程序中使用它们:
flowchart TB
subgraph "Your Plugin"
T["server/src/tools/
Canonical tool definitions
(Zod schema + business logic)"]
subgraph "AI SDK Path"
S["services/ai-tools.ts
getTools() → tools array"]
end
subgraph "MCP Path"
M["mcp/tools/*.ts
Thin wrappers → MCP envelope"]
MS["mcp/server.ts"]
end
T --> S
T --> M
M --> MS
end
S -->|"Discovery"| SDK["AI SDK ToolRegistry"]
MS -->|"JSON-RPC"| Clients["Claude Desktop / Cursor"]这消除了重复——业务逻辑集中在一个地方,每个消费者(AI SDK、MCP)都使用一个瘦适配器。
真实世界的例子
两个插件已经使用了这种模式:
strapi octolens提到插件 --贡献4个工具: searchMentions (BM25相关性搜索), listMentions, getMention, updateMention
strapi内容嵌入 --贡献5个工具: semanticSearch (向量相似度), ragQuery (抹布), listEmbeddings, getEmbedding, createEmbedding
添加自定义工具(无插件)
选项A:插件内部 --在中创建文件 tools/definitions/ 和 tool-logic/,添加到 builtInTools 阵列。
选项B:在Strapi应用程序运行时:
// src/index.ts (your Strapi app)
import { z } from 'zod';
export default {
bootstrap({ strapi }) {
const plugin = strapi.plugin('ai-sdk');
plugin.toolRegistry.register({
name: 'analyzeContent',
description: 'Analyze content quality and suggest improvements',
schema: z.object({
contentType: z.string().describe('Content type UID'),
documentId: z.string().describe('Document ID to analyze'),
}),
execute: async (args, strapi) => {
const doc = await strapi.documents(args.contentType).findOne({
documentId: args.documentId,
});
return { score: 85, suggestions: ['Add more headings'] };
},
});
},
};该工具在AI聊天和MCP中自动可用(除非 internal: true).没有更改 tools/index.ts 或 mcp/server.ts 需要。
添加AI提供者
// src/index.ts (your Strapi app)
import { createOpenAI } from '@ai-sdk/openai';
export default {
register({ strapi }) {
const { AIProvider } = require('strapi-plugin-ai-sdk/server');
AIProvider.registerProvider('openai', ({ apiKey, baseURL }) => {
const provider = createOpenAI({ apiKey, baseURL });
return (modelId) => provider(modelId);
});
},
};然后设置 provider: 'openai' 和 chatModel: 'gpt-4o' 在配置中。
自定义系统提示
// config/plugins.ts
config: {
// Simple replacement (tool descriptions appended automatically)
systemPrompt: 'You are a friendly content editor for our blog platform.',
// Or use {tools} placeholder for precise placement
systemPrompt: `You are a blog assistant.
RULES:
- Always use friendly language
- Never create content without confirmation
{tools}
When listing content types, summarize them in a table.`,
}根据请求 system 请求正文中的覆盖优先于配置的 systemPrompt.
管理面板功能
该插件为Strapi管理面板添加了一个聊天界面,其中包括:
- 聊天界面 --带有markdown渲染、工具调用可视化和键入指示器的消息列表
- 对话历史 --每个用户存储的持久对话,可通过侧边栏访问
- 内存管理 --人工智能在对话中记住事实;从工具栏查看和管理内存
- 公共内存存储 --公共聊天访问者可以共享的事实(常见问题解答、政策等)
- 工具调用显示 --可折叠查看器,在聊天中内联显示工具输入和输出
- 小部件预览 --带有复制粘贴嵌入代码的可嵌入聊天小部件的实时预览
错误处理
| 错误 | 原因 | 解决方案 |
|---|---|---|
prompt is required | 请求中缺少提示 | 包含 prompt 在请求正文中 |
AI SDK not initialized | 缺少API密钥 | 检查 ANTHROPIC_API_KEY 在 .env |
403 Forbidden | 未启用权限 | 在Strapi管理员中启用权限 |
Request blocked by guardrails | 输入与安全模式匹配 | 重新表述提示 |
错误响应格式:
{
"error": {
"status": 400,
"name": "BadRequestError",
"message": "prompt is required and must be a string"
}
}项目结构
server/src/
index.ts # Server entry point
register.ts # Plugin register lifecycle
bootstrap.ts # Initialize providers, tools, MCP, plugin tool discovery
destroy.ts # Graceful shutdown
config/index.ts # Plugin config defaults
guardrails/ # Input safety middleware
lib/
ai-provider.ts # AIProvider with static provider registry
tool-registry.ts # ToolRegistry class
types.ts # Shared types
utils.ts # Controller helpers
controllers/
controller.ts # ask, askStream, chat, publicChat, serveWidget handlers
public-memory.ts # CRUD for public memories
mcp.ts # MCP session management
services/service.ts # AI service facade
routes/
content-api/index.ts # Public API routes
admin/index.ts # Admin routes
tools/
index.ts # Bridge: registry -> AI SDK ToolSet
definitions/ # Tool definitions (schema + execute wrapper)
tool-logic/ # Pure business logic (shared by AI SDK + MCP)
mcp/
server.ts # MCP server factory
utils/sanitize.ts # Content API sanitization
admin/src/
pages/ # App router, HomePage, WidgetPreviewPage, MemoryStorePage
components/
Chat.tsx # Chat orchestrator
MessageList.tsx # Message rendering with markdown
ChatInput.tsx # Input area
ToolCallDisplay.tsx # Tool call viewer
ConversationSidebar.tsx # Conversation history panel
MemoryPanel.tsx # Memory management panel
hooks/
useChat.ts # Chat state + SSE streaming
useConversations.ts # Conversation CRUD
useMemories.ts # Memory CRUD
widget/src/ # Embeddable chat widget (separate Vite build)
embed.tsx # Auto-mount entry (Shadow DOM)
react.tsx # React component export
auto-detect.ts # Script URL detection
styles.css # Scoped CSS (no Tailwind)
components/strapi-chat.tsx # Chat UI component
tests/ # E2E integration tests
docs/ # Architecture + guardrails + email guides测试
该插件对正在运行的Strapi实例使用端到端集成测试:
npm run test:guardrails # Guardrail safety tests (42 assertions)
npm run test:api # /ask and /ask-stream endpoint tests
npm run test:stream # Streaming visual test
npm run test:chat # Chat protocol test
npm run test:ts:back # Server TypeScript type checking (no Strapi needed)
npm run test:ts:front # Admin TypeScript type checking (no Strapi needed)通过身份验证:
STRAPI_TOKEN=your-api-token npm run test:guardrails文档
- 建筑 --完整的系统架构、数据流、扩展指南
- 插件工具发现 --跨插件工具发现架构与实现
- 工具标准化规范 --规范工具格式,Zod优先与MCP原生比较,可移植性
- 护栏 --护栏系统、图案列表,
beforeProcess挂钩API - 重新发送电子邮件 --重新发送设置、电子邮件工具、域验证
许可证
麻省理工学院
