rasuvaeff/yii3-mcp-rbac-bridge 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

rasuvaeff/yii3-mcp-rbac-bridge

Composer 安装命令:

composer require rasuvaeff/yii3-mcp-rbac-bridge

包简介

Per-user RBAC for MCP servers: yiisoft/rbac permissions on yii3-mcp tool calls, visibility filtering and session-identity binding

README 文档

README

Stable Version Total Downloads Build Static analysis Psalm level PHP License

Per-user authorization for rasuvaeff/yii3-mcp servers over the Yii3 auth stack — the application-facing alternative to OAuth 2.1: RBAC permissions enforced on every tools/call, permission-aware tools/list filtering, and session-identity binding against session hijacking.

Using an AI coding assistant? llms.txt contains a compact API reference you can share with the model. Contributors: see AGENTS.md.

Requirements

Requirement Version
PHP 8.3 – 8.5
rasuvaeff/yii3-mcp ^1.1
yiisoft/access ^2.0 (bind AccessCheckerInterface to your RBAC manager)
yiisoft/user ^2.0 (identity of the current request)

Installation

composer require rasuvaeff/yii3-mcp-rbac-bridge

The model: two auth layers

SharedSecretMiddleware (yii3-mcp) stays — it is machine auth: may this MCP client talk to this endpoint at all. This bridge adds user auth: what may the authenticated user behind the call actually do. Both layers run; removing the shared secret does not follow from adding RBAC.

// config/routes.php — secret first (cheap fail-closed), then identity
Route::methods(['POST', 'GET', 'DELETE', 'OPTIONS'], '/mcp')
    ->middleware(SharedSecretMiddleware::class)
    ->middleware(Authentication::class)       // yiisoft/auth: token -> CurrentUser
    ->action(McpAction::class),

Usage

1. Declare permissions on tools

use Rasuvaeff\Yii3McpRbacBridge\RequiredPermission;

final readonly class OrderTools
{
    #[McpTool(name: 'order.status')]
    #[RequiredPermission('orders.view')]
    public function status(string $orderId): string { ... }

    #[McpTool(name: 'ping')]          // no attribute = unrestricted
    public function ping(): string { ... }
}

Restriction is explicit and per-tool: tools without a permission stay open (behind the shared secret). #[RequiredPermission] on a method without #[McpTool] fails the build — a permission that would never be enforced is a bug, not a default. One tool name mapped to two different permissions by attributes fails the build too (a silent last-one-wins would enforce an arbitrary one); explicit overrides win by design.

Tool names: what the map keys must be

PermissionMap keys are tool names, and the bridge derives each one exactly as yii3-mcp registers it — so list and call can never key off different names:

Tool declaration Registered name = map key
#[McpTool(name: 'order.status')] order.status — the explicit name wins
#[McpTool] on public function status() status — the method name
#[McpTool] on public function __invoke() the class short name (e.g. RefundTool), not __invoke

fromToolClasses() computes these keys for you. Only an explicit map (the $overrides argument, or new PermissionMap([...])) is yours to key correctly — for an invokable tool that key is the class short name:

new PermissionMap(['RefundTool' => 'orders.refund']);   // invokable RefundTool::__invoke

A key that matches no registered tool is inert (the tool stays unrestricted), so keep explicit keys in sync with the tool names above.

2. Wire the bridge

// config/common/di/mcp-rbac.php
use Rasuvaeff\Yii3McpRbacBridge\ {
    CurrentUserIdentitySource, IdentitySourceInterface, PermissionMap,
};

return [
    IdentitySourceInterface::class => CurrentUserIdentitySource::class,
    PermissionMap::class => static fn () => PermissionMap::fromToolClasses(
        [OrderTools::class],                       // same list as the `tools` params
        // ['order.status' => 'orders.admin'],     // optional explicit overrides
    ),
];
// config/params.php
'rasuvaeff/yii3-mcp' => [
    'tools' => [OrderTools::class],
    'interceptors' => [
        SessionIdentityInterceptor::class,   // outermost: binding before anything trusts the session
        RbacToolCallInterceptor::class,
    ],
    'tool_visibility' => RbacToolVisibility::class,
],

AccessCheckerInterface comes from your RBAC setup (yiisoft/rbac manager with rbac-php/rbac-db storage — see suggest).

What each piece does

Class Role
RbacToolCallInterceptor rejects tools/call without the mapped permission (regular MCP tool error, fail-closed for guests)
RbacToolVisibility hides the same tools from tools/list — list and call can never disagree (one PermissionMap)
SessionIdentityInterceptor binds the MCP session to its first identity; a leaked Mcp-Session-Id presented with another user's token is rejected
PermissionMap tool name → permission: #[RequiredPermission] scan + explicit overrides
CurrentUserIdentitySource identity id from yiisoft/user CurrentUser (null = guest); implement IdentitySourceInterface for stdio/custom setups

Security notes

  • Session binding happens on the first tools/call (the yii3-mcp interceptor chain does not see initialize). Between initialize and the first call the session carries no identity — nothing is authorized in that window, so nothing is exposed; the binding covers every actual operation.
  • Guests are first-class: a guest binds the session as a guest and is denied on every permission-mapped tool (AccessCheckerInterface receives null). The internal guest marker cannot be forged by a literal "guest" user id.
  • Permission revocation applies on the next call (fail-closed). Live notifications/tools/list_changed on revocation is not part of this version — the SDK exposes it only with an event dispatcher, which yii3-mcp's factory does not yet carry.
  • For stdio (mcp:serve) there is no HTTP request: bind IdentitySourceInterface to an env-/config-driven implementation, or leave the shared secret as the only (machine) identity.

Examples

See examples/ — runs offline.

Script Shows Needs server?
rbac.php Filtered listing, allowed/denied calls, session binding no

Development

No PHP/Composer on the host — run in Docker via the composer:2 image:

docker run --rm -v "$PWD":/app -w /app composer:2 composer build

Or with Make: make build, make cs-fix, make psalm, make test.

License

BSD-3-Clause. See LICENSE.md.

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: BSD-3-Clause
  • 更新时间: 2026-07-07

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固