charmbracelet/crush · error

session ID is required for reading MCP resources

Error message

session ID is required for reading MCP resources

What it means

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.

Source

Thrown at internal/agent/tools/read_mcp_resource.go:49

var readMCPResourceDescription string

func NewReadMCPResourceTool(cfg *config.ConfigStore, permissions permission.Service) fantasy.AgentTool {
	return fantasy.NewParallelAgentTool(
		ReadMCPResourceToolName,
		readMCPResourceDescription,
		func(ctx context.Context, params ReadMCPResourceParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
			params.MCPName = strings.TrimSpace(params.MCPName)
			params.URI = strings.TrimSpace(params.URI)
			if params.MCPName == "" {
				return fantasy.NewTextErrorResponse("mcp_name parameter is required"), nil
			}
			if params.URI == "" {
				return fantasy.NewTextErrorResponse("uri parameter is required"), nil
			}

			sessionID := GetSessionFromContext(ctx)
			if sessionID == "" {
				return fantasy.ToolResponse{}, fmt.Errorf("session ID is required for reading MCP resources")
			}

			relPath := filepathext.SmartJoin(cfg.WorkingDir(), cmp.Or(params.URI, "mcp-resource"))
			p, err := permissions.Request(
				ctx,
				permission.CreatePermissionRequest{
					SessionID:   sessionID,
					Path:        relPath,
					ToolCallID:  call.ID,
					ToolName:    ReadMCPResourceToolName,
					Action:      "read",
					Description: fmt.Sprintf("Read MCP resource from %s", params.MCPName),
					Params:      ReadMCPResourcePermissionsParams(params),
				},
			)
			if err != nil {
				return fantasy.ToolResponse{}, err
			}

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Invoke the tool through the normal agent/session pipeline
  2. Inject the session ID into ctx before calling Run, mirroring the coordinator's context setup
  3. In tests, populate the session context key first
  4. Audit any code path that rebuilds the context and drops existing values

Example fix

// before
out, err := readRes.Run(context.Background(), params)
// after
ctx := session.NewContext(parentCtx, sess)
out, err := readRes.Run(ctx, params)
Defensive patterns

Strategy: validation

Validate before calling

if GetSessionFromContext(ctx) == "" {
    return fmt.Errorf("cannot read MCP resource without a session")
}
if params.URI == "" { return fmt.Errorf("uri is required") }

Try / catch

resp, err := tool.Run(ctx, params)
if err != nil && strings.Contains(err.Error(), "session ID is required") {
    ctx = session.NewContext(parent, sess)
    resp, err = tool.Run(ctx, params)
}

Prevention

When it happens

Trigger: 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.

Common situations: Custom automation calling tools directly; a refactor that changed how context is propagated; MCP tool bridging that creates a fresh bare context.Context.

Related errors


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/70516bfc65855ea2. Report an issue: GitHub.