MCP server: coder_list_tasks panics with nil client while coder_report_task succeeds
- Dominant language
- No language data
- Stars
- 3
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
*Problem*
When the MCP server starts without valid authentication, the `coder_list_tasks` tool panics with a nil pointer dereference, while `coder_report_task` continues to work.
*Stack Trace*
```
runtime error: invalid memory address or nil pointer dereference
at github.com/coder/coder/v2/codersdk.(*Client).Request(0x0, ...)
/home/runner/work/coder/coder/codersdk/client.go:214 +0x6f
at github.com/coder/coder/v2/codersdk.(*ExperimentalClient).Tasks
/home/runner/work/coder/coder/codersdk/aitasks.go:216 +0x1a5
```
*Root Cause*
The MCP server initializes two separate dependency sources:
1. `deps.coderClient` - Set from `srv.client` (requires successful authentication)
2. `deps.report` - Set from agent client task reporter callback (independent of user auth)
When MCP starts on dev.coder.com without valid authentication:
1. `TryInitClient()` returns a client with URL configured
2. Validation fails at `exp_mcp.go:487` because EITHER:
- `client.SessionToken()` returns empty string, OR
- `client.User(ctx, codersdk.Me)` fails (expired/invalid token)
3. `srv.client` remains `nil` (never assigned at line 493)
4. However, `srv.agentClient` is created successfully for task reporting
5. `toolsdk.NewDeps(nil, toolOpts...)` creates deps with:
- `coderClient = nil`
- `report = ` (set from agent client)
*Why coder_report_task Works*
`ReportTask` handler (`toolsdk/toolsdk.go:297`) checks for nil and uses `deps.report`:
```go
if deps.report == nil {
return codersdk.Response{}, xerrors.New("task reporting not available...")
}
err := deps.report(args) // Uses callback, not coderClient
```
*Why coder_list_tasks Panics*
`ListTasks` handler (`toolsdk/toolsdk.go:1990`) immediately dereferences nil client:
```go
expClient := codersdk.NewExperimentalClient(deps.coderClient) // deps.coderClient is nil!
tasks, err := expClient.Tasks(ctx, &codersdk.TasksFilter{...})
```
This calls `(*Client).Request(0x0, ...)` which panics at line 214 trying to access:
```go
opts = append([]RequestOption{c.SessionTokenProvider.AsRequestOption()}, opts...)
```
*Solution*
All tools marked `UserClientOptional: true` that use `deps.coderClient` must check for nil:
```go
Handler: func(ctx context.Context, deps Deps, args ListTasksArgs) (ListTasksResponse, error) {
if deps.coderClient == nil {
return ListTasksResponse{}, xerrors.New("authentication required to list tasks")
}
// ... rest of handler
}
```
*Affected Tools*
All `UserClientOptional: true` tools that use `deps.coderClient`:
- `ListTasks` (line 1990) - ✗ NO nil check
- `CreateTask` (line 1897) - ✗ NO nil check
- `DeleteTask` (line 1948) - ✗ NO nil check
- `GetTaskStatus` (line 2043) - ✗ NO nil check
- `SendTaskInput` (line 2086) - ✗ NO nil check
- `GetTaskLogs` (line 2134) - ✗ NO nil check
- `WorkspaceLS` (line 1460) - ✗ NO nil check (calls `newAgentConn`)
- `WorkspaceReadFile` (line 1525) - ✗ NO nil check (calls `newAgentConn`)
- `WorkspaceWriteFile` (line 1598) - ✗ NO nil check (calls `newAgentConn`)
- `WorkspaceEditFile` (line 1660) - ✗ NO nil check (calls `newAgentConn`)
- `WorkspaceEditFiles` (line 1737) - ✗ NO nil check (calls `newAgentConn`)
- `WorkspacePortForward` (line 1776) - ✗ NO nil check (calls `findWorkspaceAndAgent`)
- `WorkspaceListApps` (line 1829) - ✗ NO nil check (calls `findWorkspaceAndAgent`)
- `ReportTask` (line 297) - ✓ HAS nil check (but checks `deps.report`, not `deps.coderClient`)
*Action Items*
1. Add nil checks to all affected tool handlers
2. Consider whether `UserClientOptional: true` is the correct flag for these tools
3. Consider creating a helper function like `requireClient(deps) error` to reduce boilerplate
4. Add tests that verify tools behave correctly when `deps.coderClient` is nil
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.