# Error Handling Strategy for MCP Tool Execution in Chrome DevTools MCP

> Learn the error handling strategy for MCP tool execution in Chrome DevTools MCP. Discover how unhandled exceptions are captured logged and returned to the client.

- Repository: [ChromeDevTools/chrome-devtools-mcp](https://github.com/chromedevtools/chrome-devtools-mcp)
- Tags: how-to-guide
- Published: 2026-02-16

---

**The Chrome DevTools MCP server implements a centralized try/catch wrapper in [`src/main.ts`](https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/main/src/main.ts) that captures all unhandled exceptions during tool execution, logs them via the internal logger, and returns structured error responses with `isError: true` to the MCP client.**

The ChromeDevTools/chrome-devtools-mcp repository provides a Model Context Protocol (MCP) server that exposes Chrome DevTools functionality to AI assistants. Understanding the error handling strategy for MCP tool execution is critical for developers building robust integrations, as it determines how failures are communicated back to the client and logged for debugging.

## Centralized Error Handling Architecture

The server centralizes all error handling logic in [`src/main.ts`](https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/main/src/main.ts) within the tool registration phase. When `server.registerTool` is called, the registration code creates an async wrapper function that executes the tool's `handler` inside a protective try/catch block.

This wrapper performs several operations before and after handler execution:

- Acquires a mutual-exclusion lock (`toolMutex`) to prevent concurrent tool execution
- Logs the incoming request via the internal logging system
- Resolves a fresh `McpContext` for the invocation
- Calls the tool's `handler` with the request parameters
- Formats the output via `McpResponse.handle`

## How Errors Are Captured and Processed

Any exception that bubbles out of the tool handler is caught by the centralized wrapper in [`src/main.ts`](https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/main/src/main.ts) (lines 92-124). The error handling logic follows a specific sequence to ensure proper logging and client communication:

```typescript
try {
  // … tool invocation …
} catch (err) {
  logger(`${tool.name} error:`, err, err?.stack);
  const errorText = err && 'message' in err ? err.message : String(err);
  if ('cause' in err && err.cause) {
    errorText += `\nCause: ${err.cause.message}`;
  }
  return {
    content: [{type: 'text', text: errorText}],
    isError: true,
  };
} finally {
  void clearcutLogger?.logToolInvocation({
    toolName: tool.name,
    success,
    latencyMs: bucketizeLatency(Date.now() - startTime),
  });
  guard.dispose();
}

```

The error processing strategy includes:

1. **Logging**: The error and its stack trace are immediately logged using the `logger` utility from [`src/logger.ts`](https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/main/src/logger.ts)
2. **Message extraction**: The handler extracts the error message, checking for nested `cause` properties to capture wrapped exceptions
3. **Structured response**: The error is converted into a valid MCP response object with `isError: true` and the error text in the content array
4. **Telemetry**: Regardless of success or failure, the `finally` block reports the invocation outcome to the Clearcut telemetry logger

## Tool-Level Error Handling Patterns

While the centralized wrapper catches all unhandled exceptions, individual tools can implement their own error handling for anticipated failure modes. This pattern allows tools to provide richer error messages or perform cleanup before the global handler takes over.

For example, in [`src/tools/pages.ts`](https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/main/src/tools/pages.ts), the `close_page` tool implements specific handling for the `CLOSE_PAGE_ERROR`:

```typescript
handler: async (request, response, context) => {
  try {
    await context.closePage(request.params.pageId);
  } catch (err) {
    // Known safe error – show message, otherwise re‑throw
    if (err.message === CLOSE_PAGE_ERROR) {
      response.appendResponseLine(err.message);
    } else {
      throw err; // falls back to the global error handler
    }
  }
  response.setIncludePages(true);
},

```

This approach allows the tool to handle expected errors gracefully while ensuring unexpected exceptions still trigger the centralized error handling strategy.

## Error Response Structure

When a tool execution fails, the MCP client receives a standardized error response rather than a connection drop or raw exception. The response structure follows the MCP protocol specification:

```json
{
  "content": [
    {
      "type": "text",
      "text": "Failed to navigate: TimeoutError: Navigation timeout of 30000 ms exceeded"
    }
  ],
  "isError": true
}

```

Key characteristics of the error response:

- The `isError` boolean flag is set to `true`, signaling to the client that the tool execution failed
- Error content is delivered as a text content block within the `content` array
- Nested error causes are appended to the message text when available
- The response maintains valid MCP protocol structure even during failure conditions

## Summary

- The Chrome DevTools MCP server implements a **centralized try/catch wrapper** in [`src/main.ts`](https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/main/src/main.ts) that surrounds every tool execution
- Errors are **logged with full stack traces** via the internal logger before being converted to client responses
- The server returns **structured error responses** with `isError: true` and descriptive text content, preventing connection drops
- Individual tools can implement **localized error handling** for anticipated failures while delegating unexpected errors to the global handler
- **Telemetry logging** occurs in the `finally` block regardless of execution success or failure

## Frequently Asked Questions

### How does the Chrome DevTools MCP server prevent tool crashes from breaking the client connection?

The server wraps every tool handler in a centralized try/catch block located in [`src/main.ts`](https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/main/src/main.ts). When an exception occurs, the catch block converts the error into a valid MCP response object with `isError: true` rather than allowing the exception to propagate and terminate the connection.

### Can individual tools customize their error messages before the global handler processes them?

Yes, tools can implement their own try/catch logic within their handlers to catch anticipated errors and append custom messages to the response. If a tool re-throws the error or encounters an unexpected exception, the centralized wrapper in [`src/main.ts`](https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/main/src/main.ts) catches it and applies the standard error formatting and logging.

### What information is included in the error response sent back to the MCP client?

The error response includes a `content` array containing a text block with the error message. If the error object contains a nested `cause` property, that cause message is appended to the primary error text. The response also includes the boolean flag `isError: true` to signal the failure state to the client.

### Where are tool execution errors logged for debugging purposes?

Errors are logged using the internal logger utility defined in [`src/logger.ts`](https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/main/src/logger.ts). When the centralized catch block captures an exception, it immediately calls `logger()` with the tool name, error object, and stack trace before formatting the response for the client.