lokicms插件mcp身份验证
](https://badge.fury.io/js/lokicms-plugin-mcp-auth)  
基于角色的身份验证和工具过滤 MCP(模型上下文协议) 服务器。
特性
- 基于角色的访问控制(RBAC) -定义具有特定工具权限的角色
- 工具筛选 -根据代理角色自动筛选可用工具
- 灵活的身份验证 -支持环境变量和API密钥前缀
- TypeScript原生 -完全类型安全和IntelliSense支持
- 零依赖 -仅要求
zod用于模式验证 - 可扩展 -在运行时添加自定义角色和API密钥映射
- MCP SDK兼容 -与合作
@modelcontextprotocol/sdk
安装
npm install lokicms-plugin-mcp-authyarn add lokicms-plugin-mcp-authpnpm add lokicms-plugin-mcp-auth快速开始
import { createMCPAuth } from 'lokicms-plugin-mcp-auth';
// Create auth instance with default roles
const auth = createMCPAuth();
// Check if a tool is allowed for current role
if (auth.isToolAllowed('create_user')) {
// Execute the tool
}
// Get filtered tools for MCP ListTools response
const filteredTools = auth.filterTools(allTools);
// Get current agent info
const info = auth.getAgentInfo();
console.log(`Role: ${info.role}, Allowed: ${info.allowedToolCount} tools`);配置
环境变量
| 变量 | 描述 | 默认值 |
|---|---|---|
AGENT_ROLE | 直接角色规范 | viewer |
AGENT_API_KEY | 用于角色查找的API密钥 | - |
插件检查 AGENT_ROLE 首先,然后回落到 AGENT_API_KEY 前缀匹配。
自定义配置
import { createMCPAuth } from 'lokicms-plugin-mcp-auth';
const auth = createMCPAuth({
// Add or override roles
roles: {
custom_role: {
name: 'Custom Role',
description: 'A custom role with specific permissions',
accessLevel: 'limited',
tools: ['list_entries', 'get_entry', 'search'],
},
},
// Default role when no auth is provided
defaultRole: 'viewer',
// Map API key prefixes to roles
apiKeyMap: {
'myapp_admin_': 'admin',
'myapp_user_': 'editor',
},
// List of all known tools (for admin '*' access)
knownTools: ['list_entries', 'create_entry', 'delete_entry'],
// Custom environment variable names
roleEnvVar: 'MY_AGENT_ROLE',
apiKeyEnvVar: 'MY_API_KEY',
});默认角色
| 角色 | 访问级别 | 工具 | 描述 |
|---|---|---|---|
admin | full | 全部(\*) | 完全访问所有操作 |
editor | 有限 | 26 | 读/写内容,结构不变 |
author | 受限 | 15 | 创建和管理自己的内容 |
viewer | 受限 | 13 | 只读访问 |
编辑角色权限
Structure (read-only):
list_content_types, get_content_type, get_structure_summary
Entries (CRUD):
list_entries, get_entry, create_entry, update_entry, delete_entry
publish_entry, unpublish_entry
Taxonomies (read-only):
list_taxonomies, get_taxonomy, list_terms, get_term
assign_terms, get_entries_by_term
Search:
search, search_in_content_type, search_suggest
Scheduler:
scheduler_status, scheduler_upcoming, schedule_entry, cancel_schedule
Revisions:
revision_list, revision_compare, revision_statsapi参考
createMCPAuth(config?)
创建新的MCP Auth实例。
const auth = createMCPAuth({
roles?: Record,
defaultRole?: string,
apiKeyMap?: Record,
knownTools?: string[],
roleEnvVar?: string,
apiKeyEnvVar?: string,
});实例方法
auth.isToolAllowed(toolName, role?)
检查角色是否允许使用工具。
auth.isToolAllowed('create_user'); // Check for current role
auth.isToolAllowed('create_user', 'editor'); // Check for specific roleauth.filterTools(tools, role?)
过滤工具对象,只保留允许的工具。
const allTools = { tool1: {...}, tool2: {...}, tool3: {...} };
const filtered = auth.filterTools(allTools); // Only allowed toolsauth.getAllowedTools(role)
获取角色允许的工具名称数组。
const tools = auth.getAllowedTools('editor');
// ['list_entries', 'get_entry', ...]auth.getBlockedTools(role)
获取角色的被阻止工具名称数组。
const blocked = auth.getBlockedTools('editor');
// ['create_user', 'delete_user', ...]auth.getRoleFromEnv()
从环境中获取当前角色。
const role = auth.getRoleFromEnv(); // 'admin', 'editor', etc.auth.getAgentInfo()
获取当前代理信息。
const info = auth.getAgentInfo();
// {
// role: 'editor',
// name: 'Editor',
// description: 'Can read/write content but not modify structure',
// allowedToolCount: 26,
// blockedToolCount: 30
// }auth.getRoles()
获取所有可用角色。
const roles = auth.getRoles();
// [
// { key: 'admin', name: 'Admin', toolCount: 56, accessLevel: 'full' },
// { key: 'editor', name: 'Editor', toolCount: 26, accessLevel: 'limited' },
// ...
// ]auth.registerRole(key, config)
在运行时注册新角色。
auth.registerRole('moderator', {
name: 'Moderator',
description: 'Can moderate content',
accessLevel: 'limited',
tools: ['list_entries', 'update_entry', 'delete_entry'],
});auth.mapApiKey(prefix, role)
将API密钥前缀映射到角色。
auth.mapApiKey('mod_key_', 'moderator');MCP服务器集成
使用中间件
import { createMCPMiddleware } from 'lokicms-plugin-mcp-auth';
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
ListToolsRequestSchema,
CallToolRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
// Your tools
const tools = {
list_entries: { description: '...', inputSchema: z.object({}), handler: async () => {} },
create_entry: { description: '...', inputSchema: z.object({}), handler: async () => {} },
// ...
};
// Create middleware
const middleware = createMCPMiddleware(tools, {
onAccessDenied: (tool, role) => {
console.error(`[Auth] Blocked: ${tool} for role ${role}`);
},
onToolExecuted: (tool, role) => {
console.log(`[Auth] Executed: ${tool} by ${role}`);
},
});
// Create server
const server = new Server(
{ name: 'my-server', version: '1.0.0' },
{ capabilities: { tools: {} } }
);
// Use middleware in handlers
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: middleware.getToolsList(),
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
return middleware.executeTool(request.params.name, request.params.arguments);
});
// Start server
const transport = new StdioServerTransport();
await server.connect(transport);使用预构建的处理程序
import { createMCPHandlers } from 'lokicms-plugin-mcp-auth';
const { handleListTools, handleCallTool, middleware } = createMCPHandlers(tools);
server.setRequestHandler(ListToolsRequestSchema, handleListTools);
server.setRequestHandler(CallToolRequestSchema, handleCallTool);
console.log(`Running as: ${middleware.getRole()}`);MCP配置
在中配置具有不同角色的多个服务器实例 .mcp.json:
{
"mcpServers": {
"myapp-admin": {
"command": "node",
"args": ["./dist/server.js"],
"env": {
"AGENT_ROLE": "admin"
}
},
"myapp-client": {
"command": "node",
"args": ["./dist/server.js"],
"env": {
"AGENT_ROLE": "editor"
}
},
"myapp-readonly": {
"command": "node",
"args": ["./dist/server.js"],
"env": {
"AGENT_ROLE": "viewer"
}
}
}
}建筑
┌─────────────────────────────────────────────────────────┐
│ AI Agent (Claude) │
└────────────────────────┬────────────────────────────────┘
│
┌──────────┴──────────┐
│ MCP Connection │
│ (role: editor) │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ MCP Auth │
│ │
│ ├─ filterTools() │ ← Only 26 tools exposed
│ ├─ isToolAllowed() │ ← Block unauthorized calls
│ └─ getAgentInfo() │ ← Role information
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ MCP Server │
│ (your tools) │
└─────────────────────┘安全
- 工具过滤发生 服务器端,不是客户端
- 堵塞的工具 未暴露 在ListTools响应中
- 尝试执行被阻止的工具会返回拒绝访问错误
- API密钥通过前缀匹配进行验证
- 默认角色为
viewer(限制性最强) - 所有访问尝试都可以通过回调记录
TypeScript
完全支持TypeScript导出类型:
import type {
RoleConfig,
RoleInfo,
AgentInfo,
AuthResult,
ToolFilter,
MCPAuthConfig,
MCPAuthInstance,
MCPTool,
} from 'lokicms-plugin-mcp-auth';例子
自定义审核角色
const auth = createMCPAuth({
roles: {
moderator: {
name: 'Moderator',
description: 'Can review and moderate content',
accessLevel: 'limited',
tools: [
'list_entries',
'get_entry',
'update_entry', // Can edit
'unpublish_entry', // Can unpublish
'search',
],
},
},
});基于API密钥的身份验证
const auth = createMCPAuth({
apiKeyMap: {
'admin_': 'admin',
'editor_': 'editor',
'readonly_': 'viewer',
},
});
// Set via environment
// AGENT_API_KEY=admin_abc123xyz
// Result: role = 'admin'动态角色注册
const auth = createMCPAuth();
// Add roles at runtime
auth.registerRole('premium_user', {
name: 'Premium User',
description: 'Premium tier access',
accessLevel: 'limited',
tools: [...auth.getAllowedTools('editor'), 'export_data'],
});
// Map new API keys
auth.mapApiKey('premium_', 'premium_user');许可证
麻省理工学院
贡献
欢迎投稿!请阅读我们的投稿指南。
