blnq MCP Server Spec

Model Context Protocol server for live browser editor integration. Version 1.0.0

Contents

Overview

The blnq MCP server connects AI assistants (Claude Code, etc.) to the blnq.studio browser-based code editors in real time. It exposes a set of tools via the Model Context Protocol that allow reading, writing, searching, and validating code across four editor panels: HTML, CSS, JS, and HEAD.

The server also exposes a REST API (the "bridge") and an SSE channel for the browser client. MCP tools and REST routes share the same bridge layer — edits from either path push live to the browser via SSE.

Connection

The MCP endpoint is at POST /mcp using the Streamable HTTP transport (MCP SDK).

MCP Tools

list_tabs
List open editor tabs with tabId, projectId, and projectName.

Parameters: None

Returns: Tab-separated table of tabId, name, projectId — or a message if no tabs are open.

get_project_info
Get project name, ID, and editor sizes with line counts. Use to plan which editors to read and whether to use line ranges.
ParamTypeDescription
tabIdstring optionalTab ID — auto-detected when only one tab is open.

Returns: Tab ID, project name/ID, and per-editor line + character counts.

read_editors
Read line-numbered editor content as plain text. Read one editor at a time with startLine/endLine for large files.
ParamTypeDescription
tabIdstring optionalTab ID (auto-detected if one tab open).
editorsstring[] optionalWhich editors to read: "html", "css", "js", "head". Default: all.
startLinenumber optional1-based start line (single editor only).
endLinenumber optional1-based end line, inclusive (single editor only).

Returns: Line-numbered content per editor, with range labels.

search_code
Search for text or regex across editors. Returns matching lines with line numbers.
ParamTypeDescription
tabIdstring optionalTab ID (auto-detected if one tab open).
querystring requiredText or regex pattern to search for.
editorsstring[] optionalEditors to search. Default: all.
regexboolean optionalTreat query as regex.

Returns: Matching lines in editor:line\tcontent format, with total count.

edit_code
Edit code by line range, find-and-replace, or batch. Preferred for all changes — always use over write_editors when possible.

Three modes:

ParamTypeDescription
tabIdstring optionalTab ID (auto-detected if one tab open).
editorenum optional"html" | "css" | "js" | "head". Required for single edits.
startLinenumber optionalFirst line to replace (1-based inclusive).
endLinenumber optionalLast line to replace (1-based inclusive).
oldTextstring optionalText to find (must be unique unless replaceAll).
newTextstring optionalReplacement text.
replaceAllboolean optionalReplace all occurrences of oldText.
editsobject[] optionalBatch edits: [{ editor, oldText, newText, replaceAll? }].

Returns: Confirmation with updated line count, context snippet around the edit, and syntax warnings (bracket balance) if any.

write_editors
Replace full editor content. Only for initial creation or when rewriting >80% of content. Use edit_code for smaller changes.
ParamTypeDescription
tabIdstring optionalTab ID (auto-detected if one tab open).
htmlstring optionalFull HTML content.
cssstring optionalFull CSS content.
jsstring optionalFull JS content.
headstring optionalFull HEAD content.

Returns: List of updated editors, plus syntax warnings if bracket imbalance detected.

write_html / write_css / write_js / write_head
Replace full content of a single editor. Use for initial creation or >80% rewrites. Each tool writes one editor and pushes the update live to the browser.
ParamTypeDescription
tabIdstring optionalTab ID (auto-detected if one tab open).
codestring requiredFull content for that editor.

Returns: Editor name, line count, and syntax warnings if bracket imbalance detected.

read_sketch
Read the current Excalidraw sketch elements. Returns the elements array with positions, types, styles, and bindings.
ParamTypeDescription
tabIdstring optionalTab ID (auto-detected if one tab open).

Returns: JSON array of Excalidraw element objects, or "Sketch is empty."

write_sketch
Write Excalidraw elements to the sketch canvas. Elements are normalized with defaults and labels are expanded into bound text elements.
ParamTypeDescription
tabIdstring optionalTab ID (auto-detected if one tab open).
elementsobject[] requiredArray of Excalidraw element objects (rectangle, ellipse, diamond, text, arrow, line).

Returns: Confirmation with element count.

check_preview
Check the preview for JavaScript errors and accessibility (WCAG) violations. Call after edits to catch issues.
ParamTypeDescription
tabIdstring optionalTab ID (auto-detected if one tab open).

Returns: JS console errors (with line numbers) and axe-core a11y violations/incomplete checks — or "Clean" if none found.

screenshot
Take a full-page screenshot of the preview. Returns a compressed JPEG image.
ParamTypeDescription
tabIdstring optionalTab ID (auto-detected if one tab open).
widthnumber optionalViewport width in pixels. Default: 1280.

Returns: JPEG image (base64) of the rendered preview.

refresh_preview
Force a full preview refresh in the browser. Use after updating a child blnq (web component) that the current tab imports — the preview needs to re-fetch the latest code.
ParamTypeDescription
tabIdstring optionalTab ID (auto-detected if one tab open).

Returns: Confirmation that the refresh was triggered.

set_project_name
Set the project name. Use when creating something new or renaming a project.
ParamTypeDescription
tabIdstring optionalTab ID (auto-detected if one tab open).
namestring requiredShort descriptive project name.

Returns: Confirmation that the project name was set.

undo
Undo the last edit. Reverts the most recent write or edit operation. Optionally target a specific editor.
ParamTypeDescription
tabIdstring optionalTab ID (auto-detected if one tab open).
editorstring optionalSpecific editor to undo: html, css, js, or head. Default: undo all editors from last edit.

Returns: Which editors were restored and how many undo steps remain.

get_cursor
Get the user's current cursor position in the editor. Returns which editor the cursor is in and the line/column number. Useful for making edits near what the user is looking at.
ParamTypeDescription
tabIdstring optionalTab ID (auto-detected if one tab open).

Returns: Editor name, line number, column number, and how recently the position was reported.

get_element_info
Inspect a live DOM element in the preview by CSS selector. Returns bounding box, computed styles, text content, and ARIA attributes. Useful for verifying layout and computed values without taking a screenshot.
ParamTypeDescription
tabIdstring optionalTab ID (auto-detected if one tab open).
selectorstring requiredCSS selector for the element to inspect.
stylesstring[] optionalComputed CSS properties to return (e.g. ["color", "font-size"]). Default: common layout properties.

Returns: Bounding rect, text content, computed styles, ARIA role/label.

run_js
Run JavaScript in the live preview iframe and return the result. Use to inspect live state, read variables, or measure things. Return values are JSON-serialised.
ParamTypeDescription
tabIdstring optionalTab ID (auto-detected if one tab open).
codestring requiredJavaScript to evaluate in the preview iframe. The return value is captured.

Returns: JSON-serialised result, or a runtime error message.

web_search
Search the web for current information — library docs, CDN links, CSS techniques, browser APIs. Requires a Serper API key (SERPER_API_KEY env var).
ParamTypeDescription
querystring requiredSearch query.
max_resultsnumber optionalNumber of results to return (1–10, default 5).

Returns: Formatted snippets with title, URL, and description. Graceful error messages for missing/invalid/exhausted API key.

set_todos
Show a task list in the chat UI. Call at the start of multi-step work with all planned steps, then call again after each step to update statuses.
ParamTypeDescription
todosobject[] requiredArray of { content: string, status: "pending" | "in_progress" | "done" }.

Returns: Confirmation string.

REST / Bridge API

These HTTP endpoints are used by the browser client and can also be called directly. All endpoints that operate on a tab require a tabId parameter.

GET/api/bridge/events?tabId=…

SSE stream for a browser tab. One connection per tab. Pushes editors:update and a11y:run events.

GET/api/bridge/tabs

List active (SSE-connected) tabs. Returns [{ tabId, projectId, projectName, updatedAt }].

GET/api/bridge/editors?tabId=…

Read all editor content for a tab. Returns { tabId, html, css, js, head, projectId, projectName }.

POST/api/bridge/sync

Browser syncs its content to the server. Body: { tabId, html?, css?, js?, head?, projectId?, projectName? }.

POST/api/bridge/editors

Write full editor content. Body: { tabId, html?, css?, js?, head? }. Pushes update via SSE.

POST/api/bridge/edit

Find-and-replace edit. Body: { tabId, editor, oldText, newText, replaceAll? } or batch: { tabId, edits: [...] }.

POST/api/bridge/search

Search across editors. Body: { tabId, query, editors?, regex? }.

POST/api/bridge/a11y/run

Trigger an accessibility check. Body: { tabId }. Query: ?timeout=15000. Waits for browser to return results via SSE round-trip.

POST/api/bridge/a11y/results

Browser posts axe-core results back. Body: { tabId, violations, incomplete }.

GET/api/bridge/a11y?tabId=…

Read the last cached a11y report for a tab.

GET/api/bridge/sketch?tabId=…

Read current sketch elements. Returns { tabId, elements, elementCount, projectId, projectName }.

POST/api/bridge/sketch

Write sketch elements. Body: { tabId, elements: [...] }. Pushes sketch:update via SSE.

POST/api/bridge/console/errors

Browser reports JS console errors. Body: { tabId, errors: [{ level, message, line?, col? }] }.

POST/api/bridge/console/clear

Clear stored console errors. Body: { tabId }.

GET/api/bridge/console/errors?tabId=…

Read stored console errors for a tab.

SSE Events

The SSE channel at /api/bridge/events sends the following events:

The _highlight field is a hint for the browser to scroll to/highlight the edited line.

Editor Model

Each tab holds state for four editors:

EditorContentNotes
htmlBody content onlyNo <!DOCTYPE>, <html>, <head>, or <body> tags.
cssFull CSS stylesheetInjected as a <style> block in the preview.
jsFull JavaScriptVanilla ES6+. Runs after HTML loads. ES modules supported via importmap in HEAD.
headHEAD contentCDN scripts, meta tags, importmaps, external stylesheets.

The preview composes a full HTML document: <head> content + CSS in a <style> block + HTML as <body> content + JS in a <script> block.

Validation

Every edit operation runs a bracket balance check on the affected editor (except HEAD). If unclosed or unmatched brackets are detected, a ⚠ SYNTAX warning is returned alongside the successful edit result. This catches broken {}, (), and [] pairs immediately rather than at preview time.

Tab state is held in memory (per-process). Tabs are cleaned up 5 minutes after their SSE connection drops. Max 50 console errors stored per tab.