For AI assistants

CTDS Chrome Extensions

7 tools over the Model Context Protocol.

The domain logic of the Chimney Top Chrome extensions (Window Organizer, Tab Link Copier, Pixel Ruler) and their store listings, without a browser: the tools take the windows, tabs, text or rectangles the user describes and return what the extension would show or do. Nothing here reads the user's real browser, storage or license; evaluate_entitlement is the policy on a record the caller supplies and never contacts the license service. Tab and window ids are the caller's; sizes are CSS pixels; times are ISO 8601.

Connect

The server is at https://chimneytopdigital.com/api/mcp/extensions. It is free, asks for no sign-in and keeps nothing between calls. Rate limits apply per address.

ClientHow
Claude CodeOne command in a terminal:
claude mcp add --transport http ctds-extensions https://chimneytopdigital.com/api/mcp/extensions
Claude (web and desktop apps)Settings → Connectors → Add custom connector, with the URL https://chimneytopdigital.com/api/mcp/extensions. No sign-in is asked for.
Codex CLIOne command in a terminal:
codex mcp add ctds-extensions --url https://chimneytopdigital.com/api/mcp/extensions
Any other MCP clientUse the Streamable HTTP transport with the URL https://chimneytopdigital.com/api/mcp/extensions: one JSON-RPC message per POST, JSON answers, no session and no authentication.

To see the raw protocol, list the tools and call one from a terminal:

curl -s https://chimneytopdigital.com/api/mcp/extensions -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

curl -s https://chimneytopdigital.com/api/mcp/extensions -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"list_extensions","arguments":{}}}'

Tools

Every tool is read-only and idempotent, so a client may run it without asking you first. Arguments are checked before a tool runs; a wrong one comes back as a message naming the field.

list_extensions List extensions

The Chrome extensions this app builds, from each extension.config.ts: name, version, description, launch status, store listing (category, tagline, overview, features, what it replaces), permissions with their justifications, pricing and changelog. Use it to answer what an extension does, needs or costs.

  • set (all | launch | retired | demo, default "launch"): Which extensions: the launch set (default), the retired ones, the reference demo, or all
window_overview Window and tab overview

Window Organizer's view of a set of browser windows and tabs: windows focused first, tabs matching a search (title or address, case-insensitive), totals, the tabs it would close as duplicates (same address, fragment ignored; the active or pinned copy is kept) and, when asked, the tab order a sort by site or title would give. Pass the windows and tabs as the user describes them.

  • windows (array, required)
  • query (string, default ""): Search text; empty shows every tab
  • sort_by (domain | title): Also return each window's tab ids in this order (pinned tabs stay first)
parse_window_import Parse a saved-windows import file

Reads a JSON or CSV export from another window or tab manager the way Window Organizer's import does: the windows and tabs it would import (http and https pages only), or the errors that stop the import. Give the file text and, when known, its name (the extension decides JSON or CSV; otherwise the first character does).

  • text (string, required): The file contents
  • filename (string): The file name, for format detection

Tab Link Copier's output for a list of tabs: plain URLs, title and URL, Markdown links or HTML links, or a custom one-line template with $url, $title, $host and $index (a Pro feature in the extension). The copy options skip browser pages, repeated addresses and pinned tabs as the extension does.

  • tabs (array, required)
  • format (urls | titled | markdown | html, default "urls"): Built-in format: urls (Plain URLs), titled (Title and URL), markdown (Markdown links), html (HTML links); ignored when template is given
  • template (string): Custom format, one line per tab, with $url, $title, $host or $index; \t and \n insert a tab or a line break
  • skip_non_web (boolean, default true): Leave out chrome://, file: and other non-web addresses
  • dedupe (boolean, default true): Copy a repeated address once
  • include_pinned (boolean, default true)

Every http and https address in a piece of pasted text (a list, an email, Markdown, HTML or JSON), in order and de-duplicated, as Tab Link Copier's "open pasted links" does: trailing punctuation trimmed, at most 100 addresses, and never a javascript:, data: or file: address.

  • text (string, required)
evaluate_entitlement Evaluate a cached license record

The shared license policy of the extensions and the license-check service: given the last stored license answer and the time, whether the user has Pro right now, from which source (fresh, cache, offline grace, grace expired), until when the grace period runs, and whether the record is due for a re-check. Pure arithmetic on the record; it contacts no license service.

  • record (object): The last stored answer; omit for a user who never activated a key
  • now (string): The time to evaluate at (ISO 8601); defaults to the current time
  • policy (client | service, default "client"): client: the extension (refresh after 12 h, 7 days of grace); service: the license-check Lambda (6 h, 3 days)
  • just_verified (boolean, default false): True when the record came from the upstream in this same call
measure_rect Measure a ruler rectangle

Pixel Ruler's readout for a rectangle on a page: the rectangle kept whole-numbered, at least 8 px across and inside the viewport, and its width, height and position in px or rem (rem uses the page's root font size, default 16 px).

  • rect (object, required): The rectangle in viewport pixels
  • viewport (object, required): The viewport size in pixels
  • unit (px | rem, default "px")
  • root_font_px (number): The page's root font size in px, for rem

Limits

  • The tools compute from the values the assistant passes in. They reach no stored data.
  • Results carry the same notices the app shows. They are estimates and working aids, not professional advice; ask your assistant to show the notice with the figure.
  • Rate limits apply per address. A request over the limit gets a plain error the assistant can read.
  • The tool list may grow. This page is generated from the running server, so it shows the tools as they are today.

If something fails

"Couldn't reach the MCP server", or a 404
Check the address character by character: the server answers only at https://chimneytopdigital.com/api/mcp/extensions, over HTTPS. Nothing else on this host speaks MCP.
405 Method Not Allowed
The client sent a GET. The server speaks the Streamable HTTP transport without an event stream: one JSON-RPC message per POST, a JSON answer, no session. A notification gets an empty 202.
429 Too Many Requests
Your address passed the fair-use limit. The Retry-After header says how many seconds to wait; the limit resets on its own.
413 Payload Too Large
One request may carry 256 KiB. Send fewer rows per call, or summarize before you send.
A tool answers with an error naming a field
The argument did not match the tool's schema above: money is integer cents (or plain dollars where the tool says so), dates are YYYY-MM-DD, and lists are JSON arrays. Fix the named field and call again; nothing was stored.
Still stuck
Write to support@chimneytopdigital.com with the tool name, the arguments you sent (with nothing personal in them), the time in UTC and the exact message. We keep no record of calls, so what you send us is all we can look at.

How we built the servers, and the rules every one follows: our guide. Questions: hello@chimneytopdigital.com.