{"record":{"id":"70516bfc65855ea2","repo":"charmbracelet/crush","slug":"session-id-is-required-for-reading-mcp-resources","errorCode":null,"errorMessage":"session ID is required for reading MCP resources","messagePattern":"session ID is required for reading MCP resources","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/agent/tools/read_mcp_resource.go","lineNumber":49,"sourceCode":"var readMCPResourceDescription string\n\nfunc NewReadMCPResourceTool(cfg *config.ConfigStore, permissions permission.Service) fantasy.AgentTool {\n\treturn fantasy.NewParallelAgentTool(\n\t\tReadMCPResourceToolName,\n\t\treadMCPResourceDescription,\n\t\tfunc(ctx context.Context, params ReadMCPResourceParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {\n\t\t\tparams.MCPName = strings.TrimSpace(params.MCPName)\n\t\t\tparams.URI = strings.TrimSpace(params.URI)\n\t\t\tif params.MCPName == \"\" {\n\t\t\t\treturn fantasy.NewTextErrorResponse(\"mcp_name parameter is required\"), nil\n\t\t\t}\n\t\t\tif params.URI == \"\" {\n\t\t\t\treturn fantasy.NewTextErrorResponse(\"uri parameter is required\"), nil\n\t\t\t}\n\n\t\t\tsessionID := GetSessionFromContext(ctx)\n\t\t\tif sessionID == \"\" {\n\t\t\t\treturn fantasy.ToolResponse{}, fmt.Errorf(\"session ID is required for reading MCP resources\")\n\t\t\t}\n\n\t\t\trelPath := filepathext.SmartJoin(cfg.WorkingDir(), cmp.Or(params.URI, \"mcp-resource\"))\n\t\t\tp, err := permissions.Request(\n\t\t\t\tctx,\n\t\t\t\tpermission.CreatePermissionRequest{\n\t\t\t\t\tSessionID:   sessionID,\n\t\t\t\t\tPath:        relPath,\n\t\t\t\t\tToolCallID:  call.ID,\n\t\t\t\t\tToolName:    ReadMCPResourceToolName,\n\t\t\t\t\tAction:      \"read\",\n\t\t\t\t\tDescription: fmt.Sprintf(\"Read MCP resource from %s\", params.MCPName),\n\t\t\t\t\tParams:      ReadMCPResourcePermissionsParams(params),\n\t\t\t\t},\n\t\t\t)\n\t\t\tif err != nil {\n\t\t\t\treturn fantasy.ToolResponse{}, err\n\t\t\t}","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/agent/tools/read_mcp_resource.go#L31-L67","documentation":"Reading an MCP resource requires a session ID from the context so the access can be permission-checked and attributed to a session. When GetSessionFromContext(ctx) returns empty, the tool returns this error before requesting permission or contacting the MCP server. Like error 181, it signals the tool ran outside a session-scoped context.","triggerScenarios":"The ReadMCPResource tool's Run function is invoked with a context lacking the session value — direct invocation in tests/scripts, context values dropped when spawning the tool, or infrastructure calling the tool outside the agent loop.","commonSituations":"Custom automation calling tools directly; a refactor that changed how context is propagated; MCP tool bridging that creates a fresh bare context.Context.","solutions":["Invoke the tool through the normal agent/session pipeline","Inject the session ID into ctx before calling Run, mirroring the coordinator's context setup","In tests, populate the session context key first","Audit any code path that rebuilds the context and drops existing values"],"exampleFix":"// before\nout, err := readRes.Run(context.Background(), params)\n// after\nctx := session.NewContext(parentCtx, sess)\nout, err := readRes.Run(ctx, params)","handlingStrategy":"validation","validationCode":"if GetSessionFromContext(ctx) == \"\" {\n    return fmt.Errorf(\"cannot read MCP resource without a session\")\n}\nif params.URI == \"\" { return fmt.Errorf(\"uri is required\") }","typeGuard":null,"tryCatchPattern":"resp, err := tool.Run(ctx, params)\nif err != nil && strings.Contains(err.Error(), \"session ID is required\") {\n    ctx = session.NewContext(parent, sess)\n    resp, err = tool.Run(ctx, params)\n}","preventionTips":["Wrap MCP tool execution with session-aware context builders","Never pass context.Background() to tool Run","Add session-presence assertions in integration tests","Keep ctx value propagation intact through goroutines"],"tags":["session","context","mcp"],"backgroundTag":"missing-session-id-in-context","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}