Skip to content

About

CodePen MCP

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

CodePen MCP

CodePen MCP is a Model Context Protocol server for CodePen that uses a Chrome extension bridge instead of browser automation. The MCP server runs locally over stdio, the bridge exposes a lightweight HTTP hub on http://127.0.0.1:3456, and the extension executes commands directly against the live CodePen DOM.

This approach is built for reliable editor automation against the modern CodePen UI: file trees, editor tabs, share links, assets, settings panels, project metadata, and local folder mirroring.

What It Does

  • Exposes CodePen as an MCP server for tools and agents.
  • Connects to a Chrome extension through a local SignalR-style long-polling bridge.
  • Automates the current CodePen editor surface without Playwright.
  • Supports classic pen CRUD flows and modern file-aware editor workflows.
  • Adds local-to-CodePen mirroring so a folder on disk can push and pull against a pen.

Architecture

MCP Client
    <-> stdio
Node.js MCP Server (src/)
    <-> local bridge on http://127.0.0.1:3456
Chrome Extension (extension/)
    <-> content script on codepen.io
CodePen Editor DOM

Core pieces:

  • src/index.ts: MCP server entry point.
  • src/bridge.ts: local bridge server plus proxy reuse mode when port 3456 is already occupied by another compatible bridge instance.
  • src/tools/: MCP tool registration grouped by domain.
  • src/mirror/: local folder mapping, hashing, watch mode, lock handling, and console helpers.
  • extension/background.js: extension-side bridge client and message router.
  • extension/content.js: CodePen DOM operations.
  • extension/popup.*: extension status UI, toggle, and logs.

Current Tool Surface

The server currently registers 70 MCP tools.

Connection and Diagnostics

  • status
  • close
  • get_log

Browser Tab Routing

  • list_tabs
  • switch_tab

File-Aware Editor Controls

  • list_files
  • list_open_tabs
  • get_active_file
  • set_active_file
  • open_file_tab
  • read_file
  • update_file
  • toggle_panel
  • get_preview_url
  • copy_share_links

Expanded Editor Surface

  • close_file_tab
  • create_file
  • delete_file
  • rename_file
  • create_folder
  • move_file
  • search_files
  • list_assets
  • upload_asset
  • delete_asset
  • copy_asset_url
  • list_blocks
  • search_blocks
  • insert_block
  • list_templates
  • use_template
  • get_privacy_settings
  • set_privacy_settings
  • list_collaborators
  • invite_collaborator
  • remove_collaborator
  • get_pen_details
  • set_pen_details
  • list_comments
  • add_comment
  • reply_to_comment
  • get_deployment_status
  • deploy_project
  • search_workspace
  • run_editor_command

Pen CRUD

  • create_pen
  • open_pen
  • read_pen
  • update_pen
  • save_pen
  • get_url

Pen Actions

  • run
  • fork_pen
  • export_pen
  • screenshot
  • console_output

Settings and Layout

  • set_preprocessors
  • add_external_resources
  • set_pen_settings
  • change_layout

CodePen HTTP/API Helpers

  • oembed
  • prefill
  • search_pens

Local Mirror Workflow

  • mirror_init
  • mirror_push
  • mirror_pull
  • mirror_start
  • mirror_stop
  • mirror_status
  • mirror_config

Why the Extension Bridge Exists

This repo does not drive CodePen through generic browser automation. Instead, it uses an unpacked Chrome extension that runs on CodePen pages and interacts with the editor directly.

Benefits:

  • Better access to the live editor DOM.
  • Less fragile than remote-control browser scripting for this use case.
  • Cleaner routing between MCP tools and the active CodePen tab.
  • Easier support for UI-only workflows like file trees, asset panels, and share links.

Tradeoffs:

  • The extension must be installed and enabled.
  • DOM selectors still depend on CodePen's current UI.
  • Some actions are gated by account tier or the currently visible editor state.

Requirements

  • Node.js 18+
  • npm
  • Google Chrome or a Chromium browser that supports unpacked extensions
  • A CodePen tab open at https://codepen.io/editor/pen or another editor/details page

Installation

1. Install dependencies

npm install

2. Build the server and extension assets

npm run build:all

This does two things:

  • Compiles the TypeScript server into dist/
  • Copies the browser SignalR client into extension/lib/signalr.min.js

If you only want the server build:

npm run build

If you only want the extension-side asset refresh:

npm run build:ext

The extension manifest metadata is synced from package.json during that build step.

If you want a distributable extension archive:

npm run pack:ext

That command refreshes the extension assets and writes a zip archive to artifacts/codepen-mcp-bridge-<version>.zip with manifest.json at the archive root.

If you want both the server build and the extension package in one step:

npm run pack:all

If you want to bump versions cleanly, use npm's version command:

npm version patch

That updates package.json and package-lock.json, then automatically syncs the Chrome extension version in extension/manifest.json through the version script.

Load the Extension

  1. Open chrome://extensions/
  2. Enable Developer mode
  3. Click Load unpacked
  4. Select the extension/ folder from this repo
  5. Pin the extension if you want easier access to its popup

The popup provides:

  • An ON/OFF connection toggle
  • Connection state feedback
  • A scrolling event log for bridge activity

Pack the Extension

Run:

npm run pack:ext

This produces a zip archive under artifacts/ that can be unpacked for distribution or uploaded where a Chrome extension zip is required. The archive excludes the local icon-generation helper page and includes the built SignalR client plus build.json metadata.

Release Artifacts

The repo now includes a GitHub Actions workflow at .github/workflows/release-artifacts.yml.

  • workflow_dispatch increments the version, commits it, creates a tag, and starts the tagged release flow
  • pushing a v* tag builds artifacts and attaches them to a GitHub release

When you dispatch the workflow, choose patch, minor, or major. The workflow runs npm version, which updates:

  • package.json
  • package-lock.json
  • extension/manifest.json through the existing sync hook

The workflow publishes:

  • the extension zip from artifacts/
  • the npm package tarball from npm pack

Running the MCP Server

Start the compiled server:

npm start

Expected behavior:

  • The MCP server starts on stdio for your MCP client.
  • The local bridge listens on http://127.0.0.1:3456/codepen-hub.
  • If another compatible bridge is already listening on 3456, the server reuses it in proxy mode instead of failing.

MCP Client Configuration

For VS Code workspace usage, this repo now includes .vscode/mcp.json. After dependencies are installed, VS Code can start the server directly from the workspace configuration.

That workspace config runs the TypeScript entrypoint through npx tsx, so it does not depend on a prebuilt dist/ folder.

Example MCP configuration:

{
  "mcpServers": {
    "codepen": {
      "command": "node",
      "args": ["d:/CodePenMCP/dist/index.js"]
    }
  }
}

If you publish or install the package globally, you can also use the package binary:

{
  "mcpServers": {
    "codepen": {
      "command": "codepen-mcp"
    }
  }
}

Basic Workflow

  1. Build the repo with npm run build:all.
  2. Load the unpacked extension from extension/.
  3. Start the MCP server with npm start.
  4. Open a CodePen editor tab in Chrome.
  5. Turn the extension ON in the popup.
  6. Call status to confirm the bridge is connected.

Common next calls:

  • list_tabs to see which browser tab will be targeted.
  • switch_tab if multiple CodePen tabs are open.
  • list_files and get_active_file for file-aware editing.
  • read_pen or update_pen for classic panel workflows. These work on both classic pens at /pen/<id> and modern Project Pens at /editor/<user>/pen/<uuid> — for the latter, panel content is read and written via a chrome.scripting.executeScript({ world: "MAIN" }) round-trip into the page-world CodeMirror 6 instances, since those JS objects are not visible from the content script's isolated world.

Local Folder Mirror Workflow

The mirror subsystem lets you bind a local folder to a CodePen pen and keep HTML, CSS, and JS synchronized.

Typical flow:

  1. Initialize a folder and mapping with mirror_init.
  2. Start continuous sync with mirror_start — it performs an initial push of the current local files before it begins watching, so the pen reflects disk from the moment watching begins.
  3. (Optional) Push or pull on demand with mirror_push / mirror_pull for one-shot syncs outside the watch loop.
  4. Inspect state with mirror_status.
  5. Stop watch mode with mirror_stop.

What mirror_init creates

mirror_init writes a .codepenmcp.json file into the target folder. That config stores:

  • The CodePen URL and pen id, if known
  • The HTML/CSS/JS file mapping
  • Detected preprocessors based on file extensions
  • Last sync timestamps and content hashes

Mirror modes

  • Existing pen to local folder: initialize with penUrl, then pull the pen into files on disk.
  • Local folder to new pen: initialize without penUrl, optionally use a template, push local content, save, and persist the resulting pen URL.
  • Continuous sync: watch local files and auto-push on save.

Notes about mirror behavior

  • mirror_start runs an initial best-effort push before the watcher begins, so the pen is in sync from t=0. If that push fails (no pen yet, bridge offline, empty folder), watching still starts and the failure reason is included in the response.
  • Watch mode uses a lock file to prevent duplicate watchers.
  • The watcher observes the parent directories of mapped files (not individual files), which keeps it reliable across editor save modes that write a temp file then rename — including VS Code's atomic save on Windows.
  • Concatenated mappings are supported for panels that should be assembled from multiple files. The JS/CSS panel content is delimited by /* === filename === */ boundary comments, which mirror_pull uses to round-trip the panel back into separate files.
  • HTML content pulled from CodePen is wrapped into a fuller local-file form when needed.

Development Commands

npm run build
npm run build:ext
npm run build:all
npm run dev
npm start
npm run test:list
npm run test:client
npm run test:call -- status

Command summary:

  • build: compile TypeScript into dist/
  • build:ext: refresh extension-side build metadata and bundled SignalR client
  • build:all: run both builds
  • dev: TypeScript watch mode
  • start: run the compiled MCP server
  • test:list: list registered MCP tools through the included test client
  • test:client: interactive REPL client for manual testing
  • test:call -- <tool> [json]: invoke one tool from the command line

Testing and Debugging

The repo includes test/client.ts, an interactive MCP client for local validation.

Useful checks:

  • npm run test:list confirms tool registration.
  • npm run test:call -- status verifies the bridge and extension connection.
  • get_log returns timestamped bridge and extension logs for reconnect issues.
  • The extension popup log helps track command flow and UI-side failures.
  • In the REPL (npm run test:client), if you mistype a tool's JSON arguments the client prints the expected schema (required/optional fields, types, descriptions) plus a paste-ready example call, so you don't have to re-run list to remember the shape.

There are also VS Code tasks for build:all and build:ext in this workspace, and a Build Extension launch entry that runs npm run build:ext in the integrated terminal without launching a browser.

Project Structure

.
├── extension/
│   ├── background.js
│   ├── content.js
│   ├── manifest.json
│   ├── popup.css
│   ├── popup.html
│   ├── popup.js
│   ├── lib/
│   └── icons/
├── src/
│   ├── bridge.ts
│   ├── index.ts
│   ├── types.ts
│   ├── mirror/
│   └── tools/
├── test/
├── test-output/
├── FEATURE_ROADMAP.md
├── REQUIREMENTS.md
├── package.json
└── tsconfig.json

Known Constraints

  • The extension must be connected to the same bridge instance the MCP server is using.
  • If multiple CodePen tabs are open, explicit tab routing may be required.
  • Several tools depend on whatever controls CodePen currently exposes in the active UI.
  • Asset upload, privacy changes, deployment, and collaborator actions may be limited by account tier or editor state.
  • Settings-oriented tools are partly assistive: some open a dialog and rely on CodePen's current DOM rather than fully deterministic structured APIs.
  • Screenshot capture is browser-tab based, not a semantic export of the preview frame.

Troubleshooting

status says the extension is not connected

  • Confirm npm start is running.
  • Open the extension popup and toggle it OFF, then ON.
  • Make sure the active page is a supported CodePen page.
  • Use get_log to inspect bridge and extension event history.

Commands go to the wrong CodePen tab

  • Run list_tabs.
  • Use switch_tab with the returned Chrome tab id.

The server cannot bind to port 3456

This is expected if another compatible bridge is already running. The server will switch into proxy mode and reuse the existing bridge if its health endpoint responds correctly.

A UI action works manually but fails through MCP

That usually means the relevant control is hidden, renamed, gated by account state, or no longer matches the selector assumptions in the content script. Re-check the current CodePen UI before changing server-side logic.

Contributing

See CONTRIBUTING.md for local setup, contribution guidelines, and how to raise issues and pull requests.

License

This project is licensed under the MIT License. See LICENSE.

An attribution request is also included in NOTICE. The notice does not change the license terms.

About

CodePen MCP

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages