charmbracelet/crush · error

session ID is required for creating a new file

Error message

session ID is required for creating a new file

What it means

The MCP tool wrapper requires a session ID in the context because MCP tool executions are tracked per session and gated by permissions scoped to that session. If GetSessionFromContext(ctx) returns an empty string, Run immediately fails with this error before checking permissions or invoking the MCP server.

Source

Thrown at internal/agent/tools/mcp-tools.go:102

			}
		} else if reqStr, ok := input["required"].([]string); ok {
			// Handle case where it's already []string
			required = reqStr
		}
	}

	return fantasy.ToolInfo{
		Name:        m.Name(),
		Description: m.tool.Description,
		Parameters:  parameters,
		Required:    required,
	}
}

func (m *Tool) Run(ctx context.Context, params fantasy.ToolCall) (fantasy.ToolResponse, error) {
	sessionID := GetSessionFromContext(ctx)
	if sessionID == "" {
		return fantasy.ToolResponse{}, fmt.Errorf("session ID is required for creating a new file")
	}

	// Skip permission for whitelisted Docker MCP tools.
	if !slices.Contains(whitelistDockerTools, params.Name) {
		permissionDescription := fmt.Sprintf("execute %s with the following parameters:", m.Info().Name)
		p, err := m.permissions.Request(
			ctx,
			permission.CreatePermissionRequest{
				SessionID:   sessionID,
				ToolCallID:  params.ID,
				Path:        m.workingDir,
				ToolName:    m.Info().Name,
				Action:      "execute",
				Description: permissionDescription,
				Params:      params.Input,
			},
		)
		if err != nil {

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Build the tool context with the session ID injected via the package's WithSession/GetSessionFromContext helper.
  2. Run the tool through the normal agent/coordinator flow which always attaches a session.
  3. In tests, use the same context helper the other tests use to set a session ID.
  4. Guard callers to skip MCP tools when no session is available instead of invoking Run.

Example fix

// before
resp, err := mcpTool.Run(context.Background(), call)
// after
ctx := tools.WithSessionContext(context.Background(), "session-123")
resp, err := mcpTool.Run(ctx, call)
Defensive patterns

Strategy: validation

Validate before calling

if tools.GetSessionFromContext(ctx) == "" {
	return errors.New("MCP tools require a session-scoped context")
}

Try / catch

resp, err := tool.Run(ctx, call)
if err != nil && strings.Contains(err.Error(), "session ID is required") {
	ctx = tools.WithSessionContext(ctx, sessionID)
	resp, err = tool.Run(ctx, call)
}

Prevention

When it happens

Trigger: Calling the MCP Tool's Run with a context built without the session value — e.g. invoking the tool directly in tests or from code paths that bypass the normal agent session setup (runBashTool-style harnesses).

Common situations: Custom scripts or tests invoking MCP tools with context.Background(); refactoring removed the session injection; running a tool outside the agent's execution loop.

Related errors


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