{"record":{"id":"e481b2ce81ff0b47","repo":"AlistGo/alist","slug":"permission-denied-for-this-operation","errorCode":null,"errorMessage":"permission denied for this operation","messagePattern":"permission denied for this operation","errorType":"http","errorClass":null,"httpStatus":403,"severity":"error","filePath":"server/mcp/auth.go","lineNumber":146,"sourceCode":"\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}\n\n// UserContextFunc returns an HTTPContextFunc that injects a specific user (for STDIO mode).\nfunc userContextMiddleware(user *model.User) func(ctx context.Context) context.Context {\n\treturn func(ctx context.Context) context.Context {\n\t\treturn context.WithValue(ctx, userKey, user)\n\t}\n}\n\n// resolveUserForStdio resolves a user by username for STDIO mode.\nfunc resolveUserForStdio(username string) (*model.User, error) {\n\tusername = strings.TrimSpace(username)\n\tif username == \"\" || username == \"admin\" {\n\t\tadmin, err := op.GetAdmin()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to get admin user: %w\", err)","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/server/mcp/auth.go#L128-L164","documentation":"Returned by checkManage (server/mcp/auth.go:146) when the user has both PermMCPAccess and PermMCPManage but the merged permissions still lack the specific permBit passed for this operation (e.g. the write, rename, or delete bit). It is the finest-grained check: generic MCP grants are present, the individual operation is not.","triggerScenarios":"A role with mcp manage but without, say, the delete permission invokes the MCP delete tool; permission sets selectively omitting one operation bit.","commonSituations":"Least-privilege roles that intentionally omit an operation, hit by a script assuming full write rights; permission templates where a single bit was overlooked.","solutions":["Identify which operation failed and grant exactly that permission bit to the role","Audit the role's permission checklist against the operations the tooling performs","Prefer explicit per-operation grants over broad write access"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// map each planned operation to its permission bit and verify the role grants it before running","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Design least-privilege roles per operation and test each tool once after setup","Audit permission checklists when tooling changes operations","Grant the exact missing bit named by the failing operation"],"tags":["mcp","permissions","rbac","least-privilege"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}