{"record":{"id":"fe9b78ff5fc39dfc","repo":"charmbracelet/crush","slug":"session-id-is-required-for-listing-mcp-resources","errorCode":null,"errorMessage":"session ID is required for listing MCP resources","messagePattern":"session ID is required for listing MCP resources","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/agent/tools/list_mcp_resources.go","lineNumber":43,"sourceCode":"\nconst ListMCPResourcesToolName = \"list_mcp_resources\"\n\n//go:embed list_mcp_resources.md\nvar listMCPResourcesDescription string\n\nfunc NewListMCPResourcesTool(cfg *config.ConfigStore, permissions permission.Service) fantasy.AgentTool {\n\treturn fantasy.NewParallelAgentTool(\n\t\tListMCPResourcesToolName,\n\t\tlistMCPResourcesDescription,\n\t\tfunc(ctx context.Context, params ListMCPResourcesParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {\n\t\t\tparams.MCPName = strings.TrimSpace(params.MCPName)\n\t\t\tif params.MCPName == \"\" {\n\t\t\t\treturn fantasy.NewTextErrorResponse(\"mcp_name 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 listing MCP resources\")\n\t\t\t}\n\n\t\t\trelPath := filepathext.SmartJoin(cfg.WorkingDir(), params.MCPName)\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:    ListMCPResourcesToolName,\n\t\t\t\t\tAction:      \"list\",\n\t\t\t\t\tDescription: fmt.Sprintf(\"List MCP resources from %s\", params.MCPName),\n\t\t\t\t\tParams:      ListMCPResourcesPermissionsParams(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":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/agent/tools/list_mcp_resources.go#L25-L61","documentation":"The list_mcp_resources tool needs a session ID to associate the permission request with a conversation. GetSessionFromContext returns empty when the tool runs outside an agent session, so the tool aborts with this error instead of requesting permissions it cannot attribute.","triggerScenarios":"Invoking the ListMcpResources tool (with mcp_name set) from a context that lacks a session, e.g. calling the tool's Execute function directly in tests or from a non-session code path.","commonSituations":"Unit tests calling the tool handler without seeding the context, MCP resource listing attempted during startup or from background jobs that bypass the agent session.","solutions":["Ensure the tool is executed through the normal agent pipeline, which injects the session ID into the context.","In tests, set the session ID explicitly via the context helper (GetSessionFromContext counterpart) before invoking the tool.","If embedding the tool elsewhere, attach a valid session ID to the context first."],"exampleFix":"// before\nresp, _ := tool.Execute(ctx, params) // ctx has no session\n// after\nctx = WithSession(ctx, sessionID)\nresp, _ := tool.Execute(ctx, params)","handlingStrategy":"validation","validationCode":"if GetSessionFromContext(ctx) == \"\" {\n    return errors.New(\"cannot list MCP resources without a session\")\n}","typeGuard":"null","tryCatchPattern":"if err := run(); err != nil {\n    if strings.Contains(err.Error(), \"session ID is required\") { /* attach session and retry */ }\n}","preventionTips":["Always invoke tools through the agent pipeline","Seed the context with a session ID in tests","Never reuse bare contexts for tool execution"],"tags":["mcp","session","permissions"],"backgroundTag":"missing-session-context","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}