npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@embd/mcp

v0.7.7

Published

Private collaborative Markdown/HTML workspaces and embeddable charts from AI agents via MCP

Readme

@embd/mcp

MCP server for embd — hosted, embeddable charts and docs.

Connect it to an AI agent and the agent can turn any tabular data it is working with — CSV files, query results, scraped tables, computed metrics — into a hosted chart on embd.sh and hand back a shareable link and a ready-to-paste <iframe> embed snippet, without the user ever opening a chart editor. It can also publish rendered documents — HTML pages or markdown write-ups it has generated — as hosted, embeddable pages (create_doc). Agents can list every embed owned by the account and delete ones that are no longer needed, so embed management can happen entirely inside a conversation.

Setup

You need an embd API key (starts with embd_sk_). Create one in your embd account settings at www.embd.sh. API access is free during the beta; after launch it will require a Pro plan.

The published package is bundled for plain Node.js (>= 18) with zero runtime dependencies — npx and bunx both work, no build step. Working from a checkout of this repo instead? Run the server directly: EMBD_API_KEY=embd_sk_... bun src/bin.ts.

Claude Code

claude mcp add embd -e EMBD_API_KEY=embd_sk_... -- npx @embd/mcp

Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "embd": {
      "command": "npx",
      "args": ["@embd/mcp"],
      "env": {
        "EMBD_API_KEY": "embd_sk_..."
      }
    }
  }
}

Environment variables

| Variable | Required | Description | | -------------- | -------- | -------------------------------------------------------- | | EMBD_API_KEY | yes | embd API key (embd_sk_...) | | EMBD_API_URL | no | Override the API base URL (useful for local development) |

Tools

| Tool | Input | Result | | -------------- | -------------------------------------------------------------- | ----------------------------------------------- | | create_chart | data (CSV text or array of row objects), plus optional kind, title, x, y, split, theme, publish | Hosted URL, iframe embed snippet, and chart id | | create_doc | content (HTML or markdown text, max 100,000 chars), format (html | markdown), plus optional title, publish | Hosted URL, iframe embed snippet, and doc id | | list_charts | — | Your embeds (charts and docs), newest first: id — kind — status — title — url | | delete_chart | id | Deletion confirmation (charts and docs alike) |

Use create_chart when tabular data should become a chart; use create_doc when the deliverable is the document itself — a report, write-up, or self-contained HTML page. Hosted HTML renders inside a sandboxed iframe with JavaScript disabled — scripts never run, handlers never fire, forms cannot submit; CSS, images, web fonts and inline SVG work normally, so send static HTML and pre-render anything interactive. create_doc warns when the content it is given needs features the sandbox drops. Markdown gets a clean default stylesheet. In list_charts output, a doc's kind is its format (html or markdown).

Published charts and docs are public: anyone with the URL can view them. Pass publish: false to create_chart or create_doc to save a private draft instead.

Chart kinds: line (default), area, bar, stacked-bar, stacked-area, bar-horizontal, scatter, pie, donut, heatmap, radar.

Themes: aurora, simple, vibrant, neon — each in -light and -dark (e.g. aurora-dark, the default).

Remote (HTTP) server — stateless, no key (WEB-MCP)

The tools above run over stdio and require an API key, because they persist hosted embeds through the embd API. That works for a locally-spawned server (Claude Desktop / Claude Code) but cannot back a remote connector: a ChatGPT app or a Claude.ai / Cowork custom connector needs an MCP server reachable over HTTP.

embd-mcp-http is that server, and it is deliberately stateless and key-free. Every tool is a pure function over @embd/core's URL builders: data in → a self-contained embd.sh/#… link out, with the content encoded directly in the URL fragment (ADR-0004/0008). Nothing is stored, no account is touched, and there is no privileged action — so the endpoint is safe to expose with no auth, which also means no demo account is needed for OpenAI's app review.

# from a checkout
EMBD_MCP_HOST=0.0.0.0 EMBD_MCP_PORT=8787 bun src/http-bin.ts
# or the built binary
node dist/http-bin.js

Then point a client at http://<host>:<port>/mcp (Streamable HTTP). A quick check:

curl -s -X POST http://127.0.0.1:8787/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

Stateless tools: create_chart, create_doc (markdown only), create_kpi, create_qr — each returns { url, kind } in structuredContent. All are declared read-only / non-destructive.

Token discipline: a stateless link carries its data inline, so the URL is the payload — kept bounded by the share-limit guard. Data too large to fit a link returns a typed error (use the hosted stdio server for that), so an oversized base64 blob never lands in the model's context.

HTTP environment variables

| Variable | Default | Description | | ------------------------ | ------------------- | --------------------------------------------------------------- | | PORT / EMBD_MCP_PORT | 8787 | Listen port | | EMBD_MCP_HOST | 127.0.0.1 | Bind address (0.0.0.0 in a container) | | EMBD_MCP_PATH | /mcp | MCP endpoint path | | EMBD_ORIGIN | https://embd.sh | Origin for the URLs the tools return | | EMBD_MCP_ALLOWED_HOSTS | — | Comma-separated Host allowlist; enables DNS-rebinding protection |

Deploy (owner)

Not deployed by CI. The endpoint needs an HTTPS host reachable by ChatGPT / Claude (any Node host, or a container). Once live: add it as a custom connector in Claude/Cowork, or load it in ChatGPT developer mode, pointed at https://<host>/mcp. Public ChatGPT-app submission additionally needs a CSP whitelisting the widget's fetch domains — deferred with the MCP Apps widget layer (see below).

Not yet built (follow-ups on the WEB-MCP ticket)

  • MCP Apps widget (@modelcontextprotocol/ext-apps) — an inline UI rendering the embed in ChatGPT/Claude. Deferred: it needs a real host client to verify and a CSP with CONNECTED-DATA disabled. The transport + tools here are the load-bearing half and work without it.
  • Hosted short-link mode over HTTP — for data too big for a stateless URL, an authenticated variant returning a short id (the stdio server already does this locally).

Development

bun test            # unit + HTTP integration tests (no network; stateless tools hit real @embd/core)
bun run typecheck
bun run lint
bun run build       # bundles src/{bin,documents-bin,http-bin,index}.ts -> dist/ (node target; the published bins)
EMBD_API_KEY=embd_sk_... bun src/bin.ts   # run the stdio (hosted) server directly
bun src/http-bin.ts                        # run the stateless HTTP server directly (no key)

Private collaborative documents (invited beta)

The separate embd-documents-mcp entry point works with private workspace Markdown/HTML, discussions and history. It does not publish public embeds and does not accept chart API keys.

A workspace owner opens Workspace → Agent access, chooses a name and read/comment/edit scope, and copies the credential once. Access is workspace-scoped, expires after 30 days and can be revoked there. Configure it as EMBD_DOCUMENT_TOKEN; optionally set EMBD_DOCUMENT_ORIGIN (default https://app.embd.sh). Never place the token in document source or a shared configuration file.

A guest invited to one document can also open Agent access from that document. That credential is capped to the named document and the guest's current role; listing, search, history, comments, images and selected-document sync respect the same boundary. The agent cannot create documents, import sets, change folders, upload workspace images, invite people or alter access. Revoking the guest or lowering their role immediately limits future server requests by their agent. An existing downloaded copy cannot be recalled; local replicas retain their bounded offline lease. Invitation acceptance and audience management stay in the human Share flow.

Install the published package with npm install --global @embd/mcp using Node.js 22.13 or later, then configure your MCP client to launch embd-documents-mcp with that environment and no arguments. The workspace setup panel supplies a version-pinned install command matching its release. If your desktop client cannot find the command, use its absolute path (command -v embd-documents-mcp on macOS/Linux).

A source build remains available for contributors: run bun install and bun run --filter @embd/mcp build from the repository, then launch node /absolute/path/to/embd/packages/mcp/dist/documents-bin.js. A source checkout is not required for the published client.

Tools list the authorized workspace's documents, read current source and discussions, create MD/HTML, submit version-checked revisions, comment/reply, and read older history/discussion pages. Read before editing and send both expectedRevision and expectedEditVersion. On 409, reread and reconcile rather than silently retrying a replacement. A human or another agent can then continue at the same document link. Agent-authored messages/revisions retain the authorizing person's identity and the agent identity. Tokens cannot invite members or manage access.

Document references inside Markdown use an embd fence:

```embd
{"kind":"document","documentId":"the-target-document-uuid","revision":"live"}
```

Use an integer revision to pin a saved version. References require current access in the same workspace, stop at three nested documents, and show errors rather than retaining content after an access failure. Live references refresh every ten seconds while the page is visible. Pinned source does not pin external state produced by arbitrary HTML scripts.

Guided private-document setup

In Workspace → Agent access, the owner can now generate a private Codex TOML or Claude Desktop JSON configuration. Install the published package, then use the default embd-documents-mcp command or enter its absolute path. Choose Local source build only when developing from a repository checkout; that option takes the built packages/mcp/dist/documents-bin.js path and Node executable. The configuration uses the current workspace application's origin, including preview origins. Protected Vercel previews may not be reachable by an external client; use an accessible deployment for the real client check.

Templates intentionally contain a placeholder, never the issued credential. Copy the credential separately and substitute it in the client’s private configuration; merge the server entry without replacing existing entries. Use a separate credential for each client so attribution and revocation stay clear. Never commit a configuration containing credentials.

Check credential read access sends a single getWorkspace request with the new agent credential, without the human browser session. It does not create or modify documents. It verifies current access, not that a desktop MCP client is configured. Copy the read-only prompt into each configured client to verify its actual workspace_documents / read_document tools. After testing, revocation is available inline in the workspace; hiding a credential is not revocation. Existing secrets cannot be redisplayed.

Private document MCP currently uses local stdio. The key-free HTTP server above is a different stateless product surface and cannot access private workspaces. Installing the published package provides the local stdio server; the guided setup does not create a hosted private-document MCP connector. Version-specific publication and deployed behavior are verified separately by the paired release checks.

Client configuration references (checked October 1, 2026): Codex MCP, local MCP servers in Claude Desktop.

Contract and paired releases

Private-document tools and embd workspace are generated from the same @embd/documents operation catalog. The internal package is bundled into both public packages; it is not an npm runtime dependency. Every SQL-authorized agent action must have a shared tool or an explicit protocol-only exclusion. Human-only account/membership operations are deliberately excluded.

CLI and MCP versions move together. client-release.json fingerprints the bundled sources and document API/migrations; CI rejects drift or a missing version bump, verifies actual installed CLI and stdio MCP calls, and publishes both packages from main using npm trusted publishing. A failed package publish is a failed paired release and can be retried; npm publication is not atomic across two packages. Existing installed clients are not silently upgraded.

Local knowledge-base replica

Keep personal QMD collections independent. These tools maintain a separate embd SQLite FTS5 index and perform no network request for search/read/link resolution. Local tools require Node.js 22.13+ (or Bun for source development); existing remote commands retain their previous runtime support. The server must have the local-KB sync migration/API deployed.

Set EMBD_DOCUMENT_TOKEN to a read-scoped workspace agent credential. Do not put it in request JSON, shell history or the database. EMBD_DOCUMENT_ORIGIN defaults to https://app.embd.sh; EMBD_KB_DIR can override the cache root (default ~/.cache/embd/kb). Data is isolated by origin, credential fingerprint and workspace. Explicit sync selection authorizes local storage. Offline access lasts at most one hour and never outlives credential expiry. Revocation is detected on sync; previously downloaded copies cannot be recalled remotely.

# selection.json: {"workspaceId":"<workspace UUID>","documentIds":["<document UUID>"]}
embd workspace kb_sync --input @selection.json
# Optional background catch-up: keep this process running; Ctrl-C stops it.
embd workspace kb_sync --input @selection.json --watch 60
embd workspace kb_search --input '{"workspaceId":"<workspace UUID>","query":"authentication decision"}'
embd workspace kb_read --input '{"workspaceId":"<workspace UUID>","documentId":"<document UUID>"}'
embd workspace kb_resolve_link --input '{"workspaceId":"<workspace UUID>","documentId":"<document UUID>","href":"../decisions/auth.md#tradeoffs"}'
embd workspace kb_status --input '{"workspaceId":"<workspace UUID>"}'
embd workspace kb_forget --input '{"workspaceId":"<workspace UUID>"}'

The same seven kb_* operations are available in embd-documents-mcp. Call kb_sync explicitly there or run the CLI watch process with the same token/origin/cache directory. MCP does not silently start a daemon. workspace tools and each command's --help expose shared schemas. Search requires all literal terms, with Unicode tokenization; it is lexical, not semantic. Results contain stable document URLs, exact source versions/hashes and freshness. kb_read returns bounded source slices; use nextOffset to continue. Reads can be stale: fetch the current server document before editing. Relative links resolve only within the synced selection using retained bases and rename aliases; unresolved targets are not automatically downloaded.

Paired client 0.7.4 makes local search format-aware: Markdown headings, prose, lists, tables, link/image labels and literal code are searchable, including angle-bracket code such as <Widget>. HTML is parsed inertly; actual script/style/template/iframe/object/SVG payloads and comments are excluded. Raw or malformed HTML inside Markdown follows the same HTML5 recovery rules, while fenced and inline code remains literal. Nothing is executed or fetched by text extraction. Search uses displayed text plus document title/path, not link destinations; it does not evaluate CSS visibility or index image pixels.

Upgrade both CLI and MCP together and restart the MCP process. Run kb_sync again after upgrading: older extractor indexes are marked incompatible until a complete rebuild succeeds. Interrupted downloads or failed writes preserve the previous stored replica for retry, but incompatible indexes cannot be read. Sync rejects backwards cursors and document versions instead of replacing a newer local copy. Exact source, hashes, revisions and citation URLs are unchanged.

Changing the selected IDs atomically replaces the local set after complete sync. Interrupted attempts retain the previous complete replica and its original expiry. A server cursor reset triggers a full reconciliation. A 401/403/404 clears the affected replica. kb_forget removes local content without deleting server documents. This is pull-only source sync: discussions, offline editing, automatic folder ingestion and embeddings are not included.

Portable document images

export_document returns the versioned embd.document.v2 JSON package: exact current source, authorized PNG/JPEG/WebP bytes, and a path manifest. It composes existing authorized reads, so it works with the managed-image API without a new server endpoint. CLI and MCP use the same collector and limits: at most 30 images and 30 MB. A missing/denied/corrupt image or document edit aborts collection. It does not contain comments, history, linked documents, or external resources. External image URLs stay in source and are listed in externalImages; they are never fetched. HTML base/srcset overrides and root-relative image paths require conversion to ordinary relative image paths first.

The CLI can write a ZIP without overwriting an existing file:

embd workspace export_document --input @document.json --archive-file document.zip

document.json contains { "documentId": "<document UUID>" }. Extract the ZIP and open the source at sourcePath from embd-export.json. A moved document uses its retained link base within files/, preserving exact relative image links; its current workspace path remains in the manifest. The JSON form has each file's encoding/content; the ZIP contains real source/image files instead of base64. MCP returns the same JSON package and does not write to the machine's filesystem.