npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

lokicms-plugin-mcp-auth

v1.1.0

Published

Role-based authentication and tool filtering plugin for LokiCMS MCP servers

Readme

lokicms-plugin-mcp-auth

npm version License: MIT TypeScript

Role-based authentication and tool filtering for MCP (Model Context Protocol) servers.

Features

  • Role-Based Access Control (RBAC) - Define roles with specific tool permissions
  • Tool Filtering - Automatically filter available tools based on agent role
  • Flexible Authentication - Support for environment variables and API key prefixes
  • TypeScript Native - Full type safety and IntelliSense support
  • Zero Dependencies - Only requires zod for schema validation
  • Extensible - Add custom roles and API key mappings at runtime
  • MCP SDK Compatible - Works with @modelcontextprotocol/sdk

Installation

npm install lokicms-plugin-mcp-auth
yarn add lokicms-plugin-mcp-auth
pnpm add lokicms-plugin-mcp-auth

Quick Start

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`);

Configuration

Environment Variables

| Variable | Description | Default | |----------|-------------|---------| | AGENT_ROLE | Direct role specification | viewer | | AGENT_API_KEY | API key for role lookup | - |

The plugin checks AGENT_ROLE first, then falls back to AGENT_API_KEY prefix matching.

Custom Configuration

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',
});

Default Roles

| Role | Access Level | Tools | Description | |------|--------------|-------|-------------| | admin | full | All (*) | Full access to all operations | | editor | limited | 26 | Read/write content, no structure changes | | author | limited | 15 | Create and manage own content | | viewer | limited | 13 | Read-only access |

Editor Role Permissions

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_stats

API Reference

createMCPAuth(config?)

Creates a new MCP Auth instance.

const auth = createMCPAuth({
  roles?: Record<string, RoleConfig>,
  defaultRole?: string,
  apiKeyMap?: Record<string, string>,
  knownTools?: string[],
  roleEnvVar?: string,
  apiKeyEnvVar?: string,
});

Instance Methods

auth.isToolAllowed(toolName, role?)

Check if a tool is allowed for a role.

auth.isToolAllowed('create_user');           // Check for current role
auth.isToolAllowed('create_user', 'editor'); // Check for specific role

auth.filterTools(tools, role?)

Filter a tools object, keeping only allowed tools.

const allTools = { tool1: {...}, tool2: {...}, tool3: {...} };
const filtered = auth.filterTools(allTools); // Only allowed tools

auth.getAllowedTools(role)

Get array of allowed tool names for a role.

const tools = auth.getAllowedTools('editor');
// ['list_entries', 'get_entry', ...]

auth.getBlockedTools(role)

Get array of blocked tool names for a role.

const blocked = auth.getBlockedTools('editor');
// ['create_user', 'delete_user', ...]

auth.getRoleFromEnv()

Get current role from environment.

const role = auth.getRoleFromEnv(); // 'admin', 'editor', etc.

auth.getAgentInfo()

Get current agent information.

const info = auth.getAgentInfo();
// {
//   role: 'editor',
//   name: 'Editor',
//   description: 'Can read/write content but not modify structure',
//   allowedToolCount: 26,
//   blockedToolCount: 30
// }

auth.getRoles()

Get all available roles.

const roles = auth.getRoles();
// [
//   { key: 'admin', name: 'Admin', toolCount: 56, accessLevel: 'full' },
//   { key: 'editor', name: 'Editor', toolCount: 26, accessLevel: 'limited' },
//   ...
// ]

auth.registerRole(key, config)

Register a new role at runtime.

auth.registerRole('moderator', {
  name: 'Moderator',
  description: 'Can moderate content',
  accessLevel: 'limited',
  tools: ['list_entries', 'update_entry', 'delete_entry'],
});

auth.mapApiKey(prefix, role)

Map an API key prefix to a role.

auth.mapApiKey('mod_key_', 'moderator');

MCP Server Integration

Using Middleware

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);

Using Pre-built Handlers

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 Configuration

Configure multiple server instances with different roles in .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"
      }
    }
  }
}

Architecture

┌─────────────────────────────────────────────────────────┐
│                    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)     │
              └─────────────────────┘

Security

  • Tool filtering happens server-side, not client-side
  • Blocked tools are not exposed in ListTools response
  • Attempting to execute blocked tools returns access denied error
  • API keys are validated by prefix matching
  • Default role is viewer (most restrictive)
  • All access attempts are loggable via callbacks

TypeScript

Full TypeScript support with exported types:

import type {
  RoleConfig,
  RoleInfo,
  AgentInfo,
  AuthResult,
  ToolFilter,
  MCPAuthConfig,
  MCPAuthInstance,
  MCPTool,
} from 'lokicms-plugin-mcp-auth';

Examples

Custom Role for Moderation

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 Key Based Authentication

const auth = createMCPAuth({
  apiKeyMap: {
    'admin_': 'admin',
    'editor_': 'editor',
    'readonly_': 'viewer',
  },
});

// Set via environment
// AGENT_API_KEY=admin_abc123xyz
// Result: role = 'admin'

Dynamic Role Registration

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');

License

MIT

Contributing

Contributions are welcome! Please read our contributing guidelines.

Related