Skip to main content
Glama

icon

stdout-mcp

A simple Chrome extension for console-logging other Chrome extensions

Why?

Seeing console log output can be crucial for debugging Chrome extensions, especially when they use a manifest V3 service worker to respond to user-generated events, like a tab opening, the focus changing, etc. Sure, you can inspect the service worker console, but leaving that devtools window open keeps the service worker active. So you'll never see your extension go through the transition from active to inactive and back again — which is often where bugs sneak in.

stdout-mcp provides an easy way to send console output from your service worker or other extension pages without keeping your background scripts active.

Related MCP server: chrome-devtools-mcp

Installation

npm install --save-dev stdout-mcp

After installing the package, you'll need to add the unpacked stdout extension to Chrome. To do so, drag the extension folder from node_modules/stdout-mcp/ into the Extensions window in Chrome (chrome://extensions).

Once stdout is running, click its service worker link to open the devtools window. This is where any console output from your extension will be displayed.

You can also let a coding agent read the output directly. See Reading logs from a coding agent.

Usage

To send logs from your extension, import stdout() from the package and call it with the stdout extension ID. The ID is fixed by the extension's manifest, so it's always lnkfeennpkaoelponfafleomlmgjfjok, which the package exports as STDOUT_ID. (Versions before 0.1.0 had no fixed ID, so if you upgrade, replace the ID you used before.)

// service-worker.js
import stdout, { STDOUT_ID } from "stdout-mcp";

stdout(STDOUT_ID);
console.log("my important message", { hello: "world" });

By default, the global console object will be wrapped with methods that forward all calls to the stdout extension, so anything passed to console.log(), console.error(), etc. in your extension will also be displayed in the stdout service worker's console. Calls to console.error() appear there as warnings labeled "error", so they aren't listed as errors in stdout itself on chrome://extensions.

Call stdout() once from each "page" in your extension from which you want to send console output: the service worker, the popup, content scripts, etc. If you pass an empty string or null for the ID, stdout() will silently do nothing, so you can use an environment variable or something similar to enable log forwarding in development mode but disable it in production.

Options

Instead of passing a plain string ID to stdout(), you can also pass an object that contains the id and other options.

wrapConsole

If you don't want to wrap the global console object, set wrapConsole to false. In that case, stdout() will return an object with the standard console methods that you can call when you want to send console output to the stdout extension:

const { log, error } = stdout({ id: "...", wrapConsole: false });

console.log("this message will not be sent to stdout");
log("this message will be logged locally *and* sent to stdout", { hello: "world" });
error("so will this error", new Error("something went wrong"));

filename

In the stdout devtools window, the filename of your extension page is prefixed to each line of output, since different parts of your extension can all send messages to that console. By default, this filename is extracted from location.pathname, but you can specify a custom name by passing a filename field in the options object:

// service-worker.js
stdout({ id: "...", filename: "background" });

// popup.html
stdout({ id: "...", filename: "toolbar" });

Reading logs from a coding agent

The package includes an MCP server, stdout-mcp, that lets a coding agent like Claude Code read your extension's console output. It needs no other changes to your extension.

The stdout extension stores the last 10,000 log messages it receives, whether or not an agent is connected. So when you notice something going wrong and start an agent session, the agent can see what was logged beforehand.

Setup

Add the server to your agent's MCP configuration. For Claude Code, run this in your extension's project:

claude mcp add stdout -- npx stdout-mcp

Or add it to the project's .mcp.json:

{
  "mcpServers": {
    "stdout": {
      "command": "npx",
      "args": ["stdout-mcp"]
    }
  }
}

The agent starts the server when it needs it. The server starts a small background process on port 47321 that holds the logs, runs the tools, and is shared by all agent sessions. Each session's server only passes messages to it. The background process exits after two hours without use. See docs/architecture.html for how these pieces fit together.

If the background process was started from an older version of the code, the next agent session to start replaces it. Sessions that are already open then use the new one. The stdout extension then resends its stored logs within about 30 seconds.

Agent mode

To let stdout send its logs to the server, click the stdout icon in Chrome's toolbar. (You may need to pin it from the Extensions menu first.) The icon shows an MCP badge while agent mode is on. The badge is green when the server has received the logs and gray while stdout is waiting for a server to start.

While agent mode is on, stdout sends new log messages to the server as they arrive. It also checks for the server every 30 seconds, or every 5 seconds for the first three minutes after you turn on agent mode or start Chrome, so a newly started agent session gets the stored logs quickly. While the server is running, the stdout service worker stays awake so it can receive commands such as reloading an extension. This only affects stdout's worker, not your extension's.

Click the icon again to turn agent mode off. The logs are still stored and shown in the stdout console, but nothing is sent to the server.

Tools

Tool

Description

get_logs

Returns the most recent log messages, the messages after a cursor from a previous call, or the messages around a given one. Can filter by level, extension, filename, a regular expression, or how recent the messages are, like 10m.

wait_for_log

Waits for a new log message that matches a regular expression, such as after the agent asks you to reproduce a problem.

mark

Adds a line to the log, such as before the agent asks you to reproduce a problem, so the messages that follow are easy to find.

reload_extension

Reloads an unpacked extension so it runs your latest code, even if its service worker failed to start. It only works on extensions that have called stdout(). With reloadManifest, it also reads manifest.json again and says whether the extension came back. That needs stdout() to be called when your service worker starts, and a service worker that can start.

list_sources

Lists the extensions and pages that have sent logs, and when stdout last connected.

Times are shown in your local time zone, like in the stdout console, and each message shows the time since the previous one, like +251ms. A loaded line marks the first message from each page load, so you can see when a service worker restarted or a popup was reopened. These lines need the version of stdout-mcp that sends a page-load ID.

License

MIT © John Dunning

Related MCP Connectors

Related MCP Servers