{"record":{"id":"b30254e3e2363da5","repo":"alibaba/open-code-review","slug":"remote-mcp-server-q-returned-http-403-forbidden","errorCode":null,"errorMessage":"remote MCP server %q returned HTTP 403 Forbidden — your credentials may lack required permissions","messagePattern":"remote MCP server %q returned HTTP 403 Forbidden — your credentials may lack required permissions","errorType":"http","errorClass":null,"httpStatus":403,"severity":"error","filePath":"internal/mcp/client.go","lineNumber":149,"sourceCode":"\nfunc (t *headerTransport) RoundTrip(req *http.Request) (*http.Response, error) {\n\tcloned := req.Clone(req.Context())\n\tfor k, v := range t.headers {\n\t\tcloned.Header.Set(k, v)\n\t}\n\tresp, err := t.base.RoundTrip(cloned)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tswitch resp.StatusCode {\n\tcase http.StatusUnauthorized:\n\t\tio.Copy(io.Discard, resp.Body)\n\t\tresp.Body.Close()\n\t\treturn nil, fmt.Errorf(\"remote MCP server %q returned HTTP 401 Unauthorized — check your token/header configuration\", t.serverName)\n\tcase http.StatusForbidden:\n\t\tio.Copy(io.Discard, resp.Body)\n\t\tresp.Body.Close()\n\t\treturn nil, fmt.Errorf(\"remote MCP server %q returned HTTP 403 Forbidden — your credentials may lack required permissions\", t.serverName)\n\t}\n\treturn resp, nil\n}\n\nfunc (c *Client) Name() string       { return c.name }\nfunc (c *Client) Tools() []*mcp.Tool { return c.tools }\n\n// CallTool invokes a tool on the MCP server and returns the text result.\nfunc (c *Client) CallTool(ctx context.Context, name string, args map[string]any) (string, error) {\n\tparams := &mcp.CallToolParams{\n\t\tName:      name,\n\t\tArguments: args,\n\t}\n\n\tresult, err := c.session.CallTool(ctx, params)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"call MCP tool %q: %w\", name, err)\n\t}","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/mcp/client.go#L131-L167","documentation":"The headerTransport wrapping the remote MCP HTTP client converts HTTP 403 responses into this descriptive error (draining and closing the body). Unlike a generic status error, it signals that authentication itself worked but the credential is not permitted to access the MCP server. Raised in RoundTrip for every request routed through the transport.","triggerScenarios":"Calling a remote MCP server (ListTools during Connect, or any session request) whose server responds 403 Forbidden — e.g. the configured token/header authenticates but the account lacks scopes/permissions for that server or tool.","commonSituations":"MCP token issued without the required scopes; server-side allowlist denying the user or IP; expired/downgraded plan on the MCP provider; token for the wrong environment (staging token against prod server).","solutions":["Verify the credential has the scopes/permissions required by the MCP server (regenerate the token with the necessary scopes)","Confirm you are hitting the intended server/environment URL and the account is allowed to use it","Check server-side allowlists (IP allowlist, org membership, plan limits) with the MCP provider","If auth is via custom headers, confirm header names/values match what the server expects — a valid-but-wrong principal can yield 403 rather than 401"],"exampleFix":"// before\nheaders = {\"Authorization\": \"Bearer <staging-token>\"}\n// after — token regenerated with required scopes for this server\nheaders = {\"Authorization\": \"Bearer <prod-token-with-scopes>\"}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"_, err := client.CallTool(ctx, name, args)\nif err != nil {\n    var httpErr interface{ Error() string }\n    if strings.Contains(err.Error(), \"HTTP 403 Forbidden\") {\n        // credential authenticated but lacks permissions: prompt user to\n        // regenerate the MCP token with required scopes; do not retry blindly\n    }\n}","preventionTips":["Issue MCP tokens with the scopes/permissions required by the tools you call","Point at the correct server environment URL (prod vs staging)","Check provider-side allowlists/plans before rollout","Distinguish 401 (bad token/header config) from 403 (insufficient permissions) when debugging"],"tags":["mcp","http","authorization","permissions"],"backgroundTag":"http-403-forbidden","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}