VOOZH about

URL: https://deepwiki.com/WordPress/mcp-adapter/3.3-security-and-permissions

⇱ Security and Permissions | WordPress/mcp-adapter | DeepWiki


Loading...
Menu

Security and Permissions

This document describes the security architecture of the MCP Adapter, focusing on the two-layer permission system that protects MCP servers and individual abilities. It covers transport-level permissions (server-wide access control), ability-level permissions (granular per-component access), permission callback implementations, authentication patterns, and error handling.

For information about transport implementation details, see HTTP Transport. For configuring custom transports, see Transport Permissions. For ability registration and execution, see Creating Abilities.

Two-Layer Security Model

The MCP Adapter implements a two-layer security architecture that evaluates permissions at both the transport level and the ability level.


Sources: docs/guides/transport-permissions.md138-178

Layer 1: Transport Permissions

Transport permissions act as a server-wide gatekeeper. They determine whether a client can access any resources on a specific MCP server. If a client is blocked at this layer, they cannot access any tools, resources, or prompts on that server.

Key characteristics:

  • Evaluated once per request before routing
  • Returns HTTP status codes (401 Unauthorized, 403 Forbidden)
  • Implemented as a callback function passed to McpAdapter::create_server()
  • Default behavior: is_user_logged_in()

Layer 2: Ability Permissions

Ability permissions provide granular access control for individual tools, resources, and prompts. They determine whether a client can execute a specific ability with specific arguments.

Key characteristics:

  • Evaluated per ability execution
  • Returns isError: true in MCP response format
  • Implemented as permission_callback in wp_register_ability()
  • Can inspect execution arguments for context-aware decisions

Transport-Level Permissions

Transport permissions are checked by the transport layer before any request processing occurs. They are defined when creating an MCP server.

Default Permission Callback

By default, all MCP servers require authenticated WordPress users:


Sources: docs/guides/transport-permissions.md7-24

Custom Permission Callbacks

Custom callbacks can implement any authentication logic:


Callback signature:


Return values:

  • true: Grant access
  • false: Deny with 401 Unauthorized
  • WP_Error: Deny with custom error message and status code

Sources: docs/guides/transport-permissions.md27-74

Authentication Patterns

Role-Based Access


API Key Authentication


Time-Based Access


Sources: docs/guides/transport-permissions.md82-136

Error Handling for Transport Permissions

When a transport permission callback denies access:

Return ValueHTTP StatusResponse Body
false401 UnauthorizedGeneric error message
WP_Error with status: 401401 UnauthorizedCustom error message from WP_Error
WP_Error with status: 403403 ForbiddenCustom error message from WP_Error

Exception handling:

  • If callback throws an exception, it falls back to is_user_logged_in()
  • Exception is logged via the server's error handler
  • Provides secure default behavior

Sources: docs/guides/transport-permissions.md75-80

Ability-Level Permissions

Ability permissions are checked after transport permissions pass and immediately before ability execution. They provide fine-grained control over individual operations.


Sources: includes/Handlers/Tools/ToolsHandler.php327-369

Permission Callback Implementation

Ability permissions are defined in wp_register_ability():


Callback signature:


Parameters:

  • $args: The unwrapped input arguments for the ability

Return values:

  • true: Grant permission
  • false: Deny permission with generic message
  • WP_Error: Deny permission with custom message and code

Permission Check Flow

The permission check occurs in ToolsHandler::handle_tool_call():


Sources: includes/Handlers/Tools/ToolsHandler.php327-369

Argument-Based Permissions

Ability permission callbacks receive the execution arguments, enabling context-aware access control:


Sources: docs/guides/transport-permissions.md149-178

Permission Error Responses

The system provides different error formats depending on which layer denies access.

Transport Permission Errors

Transport permission errors return HTTP error responses:


HTTP status codes:

  • 401 Unauthorized: Authentication required
  • 403 Forbidden: Authenticated but access denied

Sources: docs/guides/transport-permissions.md62-73

Ability Permission Errors

Ability permission errors follow the MCP specification and return isError: true format:


Sources: includes/Handlers/Tools/ToolsHandler.php340-348 tests/Unit/Handlers/ToolsHandlerTest.php283-305

WP_Error Integration

When permission callbacks return WP_Error, the system extracts detailed error information:

Before (generic error):


After (detailed error):


Response metadata:


Benefits:

  • Specific failure reasons in observability events
  • Easier to track and alert on specific permission failures
  • Error messages include full validation context
  • Can monitor specific error patterns (rate limits, quota exceeded, etc.)

Sources: docs/migration/v0.3.0.md162-186 includes/Handlers/Tools/ToolsHandler.php330-348

Permission Checking Implementation

The following code entities implement permission checking:

ComponentFileResponsibility
HttpTransport::check_permission()includes/Transport/HttpTransport.phpEvaluates transport permission callback
ToolsHandler::handle_tool_call()includes/Handlers/Tools/ToolsHandler.php:327-369Evaluates ability permission callback for tools
ResourcesHandler::handle_resource_read()includes/Handlers/Resources/ResourcesHandler.phpEvaluates ability permission callback for resources
PromptsHandler::handle_prompt_get()includes/Handlers/Prompts/PromptsHandler.phpEvaluates ability permission callback for prompts
WP_Ability::check_permissions()WordPress Abilities APIExecutes registered permission callback

Exception Handling

Both layers implement robust exception handling:

Transport layer:


Ability layer:


Sources: includes/Handlers/Tools/ToolsHandler.php327-369 tests/Unit/Handlers/ToolsHandlerTest.php160-206

Security Best Practices

1. Layer Separation

Transport permissions: Use the broadest capability needed by any ability on the server.


Ability permissions: Check specific context and arguments.


Sources: docs/guides/transport-permissions.md194-203

2. Performance Considerations

Keep permission callbacks fast:


Sources: docs/guides/transport-permissions.md183-193

3. Error Information

Provide detailed error messages for debugging:


4. Secure Defaults

  • Always require authentication unless explicitly configured otherwise
  • Deny access by default if permission callbacks fail
  • Log all permission failures for security monitoring

Sources: includes/Handlers/Tools/ToolsHandler.php327-369

Testing Permissions

Testing Transport Permissions

Test with different user roles using WP-CLI:


Testing Ability Permissions

Test ability-level permissions in unit tests:


Sources: tests/Unit/Handlers/ToolsHandlerTest.php283-305 docs/guides/transport-permissions.md206-215