VOOZH about

URL: https://deepwiki.com/WordPress/mcp-adapter/5.4-transport-permissions

⇱ Transport Permissions | WordPress/mcp-adapter | DeepWiki


Loading...
Menu

Transport Permissions

Transport permissions provide server-wide authentication and authorization controls for MCP servers. They act as the first layer of security, determining whether a request can access any abilities on a given server before individual ability permissions are checked.

This page covers transport-level permission configuration, callback implementation, and authentication patterns. For fine-grained per-ability permissions, see Ability Permissions. For session management after permission checks, see Session Management.

Overview

Transport permissions function as a server-wide gatekeeper. When an MCP request arrives, the transport layer checks the permission callback before processing the request. If the check fails, the request is immediately rejected with a 401 or 403 HTTP status code, and no abilities on that server are accessible.

Default Behavior

By default, all MCP servers use is_user_logged_in() as their permission check. This requires WordPress authentication via cookies, application passwords, or other WordPress authentication mechanisms.

Sources: docs/guides/transport-permissions.md7-25 README.md32

Request Flow with Permission Checks


Sources: includes/Transport/HttpTransport.php includes/Transport/Infrastructure/RequestRouter.php docs/guides/transport-permissions.md138-178

Configuration

Basic Server Creation

Permission callbacks are specified as the last parameter to McpAdapter::create_server():


If the permission callback parameter is omitted, the server uses is_user_logged_in() by default.

Sources: docs/guides/transport-permissions.md7-25 README.md452-470

Permission Callback Signatures

Permission callbacks receive a WP_REST_Request object and return either bool or WP_Error:

Return TypeMeaningHTTP Status
truePermission grantedRequest continues
falsePermission denied403 Forbidden
WP_Error with status 401Not authenticated401 Unauthorized
WP_Error with status 403Insufficient permissions403 Forbidden

Sources: docs/guides/transport-permissions.md52-74 docs/guides/transport-permissions.md219-228

Code Entity Flow


Sources: includes/Core/McpAdapter.php includes/Core/McpServer.php includes/Transport/HttpTransport.php includes/Transport/Infrastructure/McpTransportContext.php

Exception Handling and Fallback

If a permission callback throws an exception, the transport layer automatically falls back to is_user_logged_in() and logs the error:


This ensures that:

  • Broken callbacks don't crash the server
  • Failed authentication always defaults to secure behavior
  • Errors are logged for debugging

Sources: docs/guides/transport-permissions.md76-80 docs/guides/transport-permissions.md224-228

Common Authentication Patterns

Role-Based Access Control

Restrict access based on WordPress capabilities:


Sources: docs/guides/transport-permissions.md83-94

API Key Authentication

Validate custom API keys from request headers:


Sources: docs/guides/transport-permissions.md96-112

Time-Based Access Control

Restrict access based on time of day or user role:


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

Two-Layer Security Model


The MCP Adapter enforces security at two distinct layers:

Layer 1: Transport Permissions (Server-wide Gatekeeper)

  • Scope: Entire MCP server
  • Check: Before any request processing
  • Purpose: Broad authentication (who can access this server?)
  • Example: "Only logged-in users" or "Only administrators"
  • Implementation: Permission callback in create_server()

Layer 2: Ability Permissions (Fine-grained Control)

  • Scope: Individual abilities (tools, resources, prompts)
  • Check: When executing specific abilities
  • Purpose: Fine-grained authorization (can this user access this specific resource?)
  • Example: "Can user edit post ID 123?" or "Can user view unpublished content?"
  • Implementation: permission_callback in wp_register_ability()

Example: Content Management Server


When to Use Each Layer

Use CaseLayerImplementation
Require authenticationTransportis_user_logged_in()
Require specific roleTransportcurrent_user_can('capability')
API key validationTransportCustom validation against stored keys
Check resource ownershipAbilitycurrent_user_can('edit_post', $post_id)
Rate limiting per userTransportCustom rate limit check
Validate input parametersAbilitySchema validation + permission check

Sources: docs/guides/transport-permissions.md138-178 README.md32 Diagram 4 from high-level system architecture

Best Practices

Keep Callbacks Fast

Permission callbacks run on every request. Avoid expensive operations:


Use Broadest Capability

Set transport permissions to the broadest capability needed by any ability on the server. Let ability-level permissions handle specific restrictions:


Provide Detailed Error Messages

Use WP_Error to give clients useful feedback:


Sources: docs/guides/transport-permissions.md181-204

Testing Permission Callbacks

Test permission callbacks with different user roles using WP-CLI:


Expected responses:


Sources: docs/guides/transport-permissions.md206-216

Transport Context Structure


The McpTransportContext object encapsulates all configuration needed by a transport, including the permission callback. This context is created during server initialization and passed to transport instances.

Sources: includes/Transport/Infrastructure/McpTransportContext.php includes/Transport/HttpTransport.php includes/Core/McpServer.php

Related Capabilities

Transport permissions integrate with WordPress's capability system. Common capabilities used in MCP servers:

CapabilityUser RolesTypical Use Case
readAll authenticated usersPublic content access
edit_postsAuthor, Editor, AdminContent management servers
edit_published_postsEditor, AdminPublished content editing
publish_postsAuthor, Editor, AdminPublishing tools
delete_postsAuthor, Editor, AdminDeletion operations
manage_optionsAdmin onlyAdministrative servers
edit_usersAdmin onlyUser management
manage_categoriesEditor, AdminTaxonomy management

Custom capabilities can be registered and checked via current_user_can() for plugin-specific permissions.

Sources: docs/guides/transport-permissions.md83-94