{"record":{"id":"1707795848641d83","repo":"AlistGo/alist","slug":"mcp-access-not-permitted","errorCode":null,"errorMessage":"MCP access not permitted","messagePattern":"MCP access not permitted","errorType":"http","errorClass":null,"httpStatus":403,"severity":"error","filePath":"server/mcp/auth.go","lineNumber":131,"sourceCode":"\treqPath, err := user.JoinPath(path)\n\tif err != nil {\n\t\treturn ctx, \"\", err\n\t}\n\tmeta, _ := op.GetNearestMeta(reqPath)\n\tctx = context.WithValue(ctx, \"meta\", meta)\n\tctx = context.WithValue(ctx, \"user\", user)\n\treturn ctx, reqPath, nil\n}\n\n// checkAccess checks if user can access the path (read).\nfunc checkAccess(user *model.User, reqPath string) error {\n\tmeta, _ := op.GetNearestMeta(reqPath)\n\tif !common.CanAccessWithRoles(user, meta, reqPath, \"\") {\n\t\treturn fmt.Errorf(\"permission denied\")\n\t}\n\tperm := common.MergeRolePermissions(user, reqPath)\n\tif !user.IsAdmin() && !common.HasPermission(perm, common.PermMCPAccess) {\n\t\treturn fmt.Errorf(\"MCP access not permitted\")\n\t}\n\treturn nil\n}\n\n// checkManage checks if user can perform write operations via MCP.\nfunc checkManage(user *model.User, reqPath string, permBit uint) error {\n\tif err := checkAccess(user, reqPath); err != nil {\n\t\treturn err\n\t}\n\tperm := common.MergeRolePermissions(user, reqPath)\n\tif !user.IsAdmin() && !common.HasPermission(perm, common.PermMCPManage) {\n\t\treturn fmt.Errorf(\"MCP manage not permitted\")\n\t}\n\tif !user.IsAdmin() && !common.HasPermission(perm, permBit) {\n\t\treturn fmt.Errorf(\"permission denied for this operation\")\n\t}\n\treturn nil\n}","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/server/mcp/auth.go#L113-L149","documentation":"Returned by checkAccess (server/mcp/auth.go:131) when the user passes the meta and role path check but is not an admin and the merged role permissions for reqPath lack the PermMCPAccess bit. This is the dedicated 'may use MCP at all (read-level)' permission, evaluated after path access succeeds.","triggerScenarios":"A non-admin user with otherwise valid path roles calls any MCP read tool without the 'mcp access' permission granted on their role.","commonSituations":"MCP introduced to an instance after roles were defined, so no existing role carries the bit; admins assuming path access implies MCP access.","solutions":["Grant the MCP access permission to the user's role in the admin panel","Or perform MCP calls as an admin account, which bypasses the bit","After enabling MCP, audit roles and add the permission where intended"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before non-admins use MCP, verify the role's permission list includes the 'mcp access' bit","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When enabling MCP on an existing instance, audit roles for the mcp access bit","Keep a dedicated MCP role with the bit documented"],"tags":["mcp","permissions","rbac"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}