Skip to main content
Glama

plopino

CLI: publish with one command

npx -y plopino publish ./index.html
npx -y plopino publish ./dist --json
npx -y plopino login
npx -y plopino publish ./dist --update https://plopino.com/b/YOUR_BOARD_ID/
npx -y plopino whoami
npx -y plopino logout

login prompts for an email and a hidden password. Create an account on the website first if needed. Login claims available anonymous uploads made with this CLI's saved identity, reports how many were claimed, and saves a session for future uploads. An existing PLOPINO_TOKEN overrides the saved session for publishing. For Google/GitHub-only accounts, use an API token for future uploads; CLI password login requires an account with a password.

Cookies are stored as unencrypted JSON per server origin under ~/.config/plopino/. The directory is created with mode 0700 and cookie files are written with 0600; this restricts access to your OS user but is not encryption. Override the directory with PLOPINO_CONFIG_DIR. Keep this directory to retain the ability to claim anonymous uploads. Passwords are never stored. Logging out revokes the saved account session but preserves the anonymous identity; log out before handing a shared OS account to someone else. Browser and MCP sessions are separate: logging in on the website alone does not claim CLI uploads.

For non-interactive login, use login --email you@example.com --password-stdin, supplying the password through standard input from your secret manager. Do not pass passwords as command-line arguments. --json gives structured results and errors; errors exit with status 1. Default publishing writes only the URL to stdout and status to stderr.

Both CLI and MCP directory uploads skip .git, .env*, node_modules, .ssh, .aws, and symbolic links. Other files are included; publish the output directory you intend to share. A single explicitly selected file is uploaded as requested, so never select credentials or other secrets. Symlink inputs are rejected. CLI commands for the same server cannot run concurrently; after a forcibly terminated process, the next command identifies any stale lock to remove once no command is running.

For development before the npm release, replace npx -y plopino with node /path/to/boards/mcp/index.js in the examples above.

Related MCP server: sitebox

MCP

MCP server for Plopino — lets an AI agent publish what it just built and hand back a public link, without the user touching a browser.

agent writes index.html — or has a report / spreadsheet / markdown on disk
   ↓  publish_page / publish_path
https://plopino.com/b/xxxxxxxx/

Documents are first-class: Word (doc/docx), Excel (xls/xlsx) and Markdown render as readable pages, code and data files get syntax-highlighted previews, and images and video display inline. The recipient opens a link; they never download a file.

Tools

Tool

Use it when

publish_page

You have the content as a string — generated HTML, or a Markdown / CSV / code document. The filename decides how it renders: leave it at index.html for a page, pass report.md and it renders as a document.

publish_path

The page needs sibling files (CSS, JS, images), or you are sharing something that is already on disk — including any document, and including binary formats (docx, xlsx, pdf) that cannot be sent as a string. Point it at a directory and the structure is preserved — no need to zip first.

publish_files

Remote endpoint only. Same job as publish_path for clients that cannot hand over a local path: you send the file contents inline (a relative path plus its content, per entry).

Both take an optional update_url: pass a link returned by an earlier publish and that page's content is replaced while the link stays the same. This needs a token (see below).

Publishing is anonymous by default: no account, no configuration, no API key. The returned link is public; without a token the page is kept for a month, with a token it is permanent and can be updated in place.

The stdio MCP server reuses the CLI's per-origin anonymous cookie in ~/.config/plopino/ (override with PLOPINO_CONFIG_DIR). Repeated publishes and MCP restarts therefore keep the same anonymous identity, and plopino login can claim those uploads. MCP does not use the saved CLI login session; account publishing and updates still require PLOPINO_TOKEN.

Anonymous creates also return claimUrl. It is a private browser link for the publisher: open it yourself, sign in, and confirm the claim to keep that page in your account. Do not append it to the public URL or share it with page viewers. JSON output includes it as claimUrl; human output prints it on stderr for CLI publishes and inside the MCP tool result for agent publishes.

Authentication (optional)

Set PLOPINO_TOKEN to publish to your account instead of anonymously. You get private boards, updates that keep the same link, and you are not subject to the anonymous rate limit.

Create a token at plopino.com/b — the panel hands you a ready-made command with the token already in it (the server keeps an encrypted copy, so you can come back for it any time), then:

claude mcp add plopino --env PLOPINO_TOKEN=plp_xxx -- npx -y plopino

Leaving it unset is a supported configuration, not a degraded one. Most users never need a token — the anonymous flow is the product.

Install

Also listed in the official MCP registry as io.github.plopino/plopino-mcp, and on Smithery as an installable bundle.

Claude Code plugin

This repository is also a Claude Code plugin marketplace:

claude plugin marketplace add plopino/plopino-mcp
claude plugin install plopino@plopino

The plugin connects to Plopino's remote MCP endpoint, so it works without a local Node process. A token is optional; leave it empty to publish anonymously.

OpenAI Codex / ChatGPT plugin

codex-plugin/ is the OpenAI-format package and .agents/plugins/marketplace.json is its Codex marketplace entry:

codex plugin marketplace add plopino/plopino-mcp
codex plugin add plopino@plopino

It uses the remote MCP endpoint with mixed authentication: anonymous by default, or Plopino OAuth 2.1 (DCR + PKCE) for account publishing and in-place updates. The same folder is the single-plugin-root package for the OpenAI directory ZIP submission.

Claude Desktop extension

Download the latest plopino.mcpb, then open it or drag it into Claude Desktop. This is the local stdio server, with an optional PLOPINO_TOKEN in the extension settings.

Anything that speaks stdio MCP works — the server is a plain stdio process, so the only difference between clients is how you register it. All of the below are the clients' own documented forms (verified 2026-09). Wherever you see plp_xxx, paste a token from plopino.com/b — the panel there fills it in for you and lets you pick your client. If your client would rather not run a local process at all, skip to Remote endpoint — same tools, one URL.

Claude Code

claude mcp add plopino -e PLOPINO_TOKEN=plp_xxx -- npx -y plopino

Codex (CLI and IDE extension share ~/.codex/config.toml)

codex mcp add plopino --env PLOPINO_TOKEN=plp_xxx -- npx -y plopino

Gemini CLI

gemini mcp add -e PLOPINO_TOKEN=plp_xxx plopino npx -y plopino

WorkBuddy — ~/.workbuddy/mcp.json (%USERPROFILE%\.workbuddy\mcp.json on Windows; needs WorkBuddy 5.3+), then restart WorkBuddy:

{
  "mcpServers": {
    "plopino": {
      "command": "npx",
      "args": ["-y", "plopino"],
      "env": { "PLOPINO_TOKEN": "plp_xxx" }
    }
  }
}

Cursor — the same JSON in .cursor/mcp.json (project) or ~/.cursor/mcp.json (global). Windsurf — the same JSON in ~/.codeium/windsurf/mcp_config.json. Claude Desktop — the same JSON in claude_desktop_config.json.

VS Code — same idea in .vscode/mcp.json, but the key is servers, not mcpServers:

{
  "servers": {
    "plopino": {
      "command": "npx",
      "args": ["-y", "plopino"],
      "env": { "PLOPINO_TOKEN": "plp_xxx" }
    }
  }
}

No npm? The server also ships as a single self-contained file on the site. Two lines instead of one, but nothing to install:

curl -fsSL https://plopino.com/plopino-mcp.mjs -o "$HOME/.plopino-mcp.mjs"
claude mcp add plopino -e PLOPINO_TOKEN=plp_xxx -- node "$HOME/.plopino-mcp.mjs"

"$HOME/…" is expanded by your shell as you paste, so the absolute path is what gets registered. That matters: MCP clients spawn the server from an arbitrary working directory, so a relative path would break.

Then just ask: "publish this to Plopino", or "give me a link for that page".

Remote endpoint — nothing to install

Everything above runs on your machine. There is also a hosted Streamable HTTP endpoint serving the same tools, for clients that support remote MCP servers and would rather not run a local process at all:

https://plopino.com/mcp
claude mcp add --transport http plopino https://plopino.com/mcp

Any client that accepts a remote server URL takes that same address. Authentication works the same way: send a token as Authorization: Bearer plp_xxx if you have one, and publish anonymously if you don't.

Two differences from the stdio build, both deliberate:

  • publish_path is not available remotely. It takes a path on the machine the server runs on — which, remotely, is not your machine. Use publish_files and send the contents.

  • The endpoint is stateless: each request is handled on its own, no session to keep alive.

Self-hosted / local

The instance the server publishes to defaults to https://plopino.com. Set PLOPINO_BASE_URL to point at another one — a staging host, or your own deployment:

PLOPINO_BASE_URL=https://plopino.com npx -y plopino

Requirements

  • Node 20 or newer (required by the MCP TypeScript SDK v2).

  • The only runtime dependency is the MCP SDK.

Development

npm install
npm test        # 路径展开的边界 + 协议握手/工具列表(不需要网络)

To exercise the full publish path, run a Plopino instance and drive the server over stdio against it:

PLOPINO_BASE_URL=https://plopino.com node index.js

stdout is the MCP protocol channel. Anything written there that is not a JSON-RPC message will break the client. All logging must go to stderr — hence console.error everywhere and never console.log.

Privacy Policy

Full policy: https://plopino.com/privacy

  • What is collected. Only what publishing requires: the file contents and file names you pass to a tool, the destination URL, and — for anonymous publishes — the requesting IP address (used for the daily rate limit). The MCP server itself collects nothing and sends no telemetry; it runs locally and logs only to stderr. Anonymous publishing writes the local identity cookie described above.

  • How it is used and stored. Uploaded content is stored on Plopino's servers and served from the returned public link. A PLOPINO_TOKEN is stored locally in your MCP client configuration; the server keeps only its SHA-256 hash.

  • Third parties. No content or usage data is sold, shared or sent to third parties for advertising. Plopino uses Cloudflare as its CDN/reverse proxy and self-hosted Umami for aggregate, cookieless visit counts.

  • Retention. Anonymous uploads are deleted after 30 days; a link can also be removed earlier from the account page. Uploads made with a token are kept until you delete them or the account is closed. Request deletion or report abuse at abuse@plopino.com.

  • Contact. abuse@plopino.com (abuse and privacy requests), or https://plopino.com/abuse.

Notes

  • publish_path walks directories recursively and skips symbolic links — following them could escape the directory tree and upload files from elsewhere on the machine.

  • Anonymous uploads are rate-limited per IP by the server side.

  • Nothing is uploaded until a tool is called; the server does no network I/O at startup.

Available Tools

2 tools
publish_pagePublish a page and get a linkA

Publish content you have in hand to a public URL. Use this whenever the user asks to share, send, publish, or "give me a link to" something you just produced — an HTML page (dashboard, report, chart, interactive page), a Markdown document, CSV, JSON, or a code/data file. Everything it publishes becomes a page the recipient opens in a browser: the filename decides how it renders, so pass "report.md" for Markdown instead of renaming it to .html. Returns a public link that opens on any device; no account or configuration needed. Anonymous pages are kept for a month — with a token, storage is permanent and the page can be updated in place. Prefer this over telling the user to save the file and upload it somewhere themselves.

NameRequiredDescriptionDefault
contentYesThe complete content of the file, as a string. With the default filename this is a self-contained HTML document including the <html> tag — relative references to local files will not resolve, so use publish_path when the page needs sibling files (CSS, JS, images).
filenameNoWhat to name the file — this decides how the content is rendered, so get it right rather than renaming Markdown to .html. Defaults to "index.html". Use "report.md", "data.csv", "query.sql" and so on; subdirectories work too ("reports/q3.md"). Only text can be sent as a string — binary formats (docx, xlsx, pdf) must go through publish_path.
update_urlNoA URL returned by an earlier publish. When given, the content of that page is replaced and the link stays the same. Requires the server to be configured with a Plopino token.

Output Schema

NameRequiredDescription
urlYesPublic link to the published page — give this to the user.
noteYesHuman-readable status: created vs updated, and how long the page is kept.
claimUrlNoPrivate browser claim link for the publisher only. Never give it to page viewers or append it to the public URL.

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, it discloses important behavior: public URL output, no account/configuration required, anonymous retention for a month, and token-based permanent storage with in-place updates. It does not cover limits or full public-visibility implications, but the added context is substantial.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with purpose and usage guidance, and every sentence contributes useful context. It is slightly long and duplicates some filename guidance already in the schema, but it is not padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema, annotations, and full parameter coverage, the description covers purpose, usage, return behavior, and retention well. The main omission is that the publish_path alternative/routing is left to the schema rather than the tool description.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description repeats the filename-rendering guidance already present in the schema and mentions content types, but it does not add parameter-specific detail beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: publishing in-hand content to a public URL. It clearly contrasts with telling the user to upload the file manually, but it does not explicitly distinguish this tool from the sibling publish_path in the main description.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear triggering conditions ('whenever the user asks to share, send, publish, or give me a link') and a preferred alternative over manual upload. It omits an explicit when-not/alternative case for publish_path, which is only mentioned in the parameter schema.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

publish_pathPublish a local file or folder and get a linkA

Publish a local file, a zip, or a whole directory to a public URL, preserving the directory structure. Use this when the page needs sibling files (CSS, JS, images) — write them into a directory first, then publish that directory. It is also the way to share any document: Word (doc/docx), Excel (xls/xlsx) and Markdown render as readable pages, code and data files get syntax-highlighted previews, and images and video display inline — the recipient opens a link instead of downloading a file. (PowerPoint files publish and download fine but have no rendered preview.)

NameRequiredDescriptionDefault
pathYesAbsolute path to a file or directory on this machine. A directory is uploaded recursively with its structure preserved; symbolic links and common private paths (.git, .env*, node_modules, .ssh, .aws) are skipped. An explicitly selected single file is uploaded as requested, so never select credentials or other secrets. A zip archive is unpacked server-side.
update_urlNoA URL returned by an earlier publish. When given, the content of that page is replaced and the link stays the same. Requires the server to be configured with a Plopino token.

Output Schema

NameRequiredDescription
urlYesPublic link to the published page — give this to the user.
noteYesHuman-readable status: created vs updated, and how long the page is kept.
claimUrlNoPrivate browser claim link for the publisher only. Never give it to page viewers or append it to the public URL.

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare openWorldHint=true, destructiveHint=false and idempotentHint=false, but the description adds meaningful context beyond them: the output is a public URL (exposure implied), PowerPoint files publish without a rendered preview, and zip archives are unpacked. It does not describe what happens on a failed upload or whether a previously published link persists, which keeps it below a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose and the primary usage rule are front-loaded in the first two sentences, with the file-type rendering details trailing as supporting context. The long enumerations of formats and the PowerPoint parenthetical are dense but each conveys a real capability, so little is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no explanation, and 100% schema coverage handles parameter details. The only substantive hole is the absence of any comparison to publish_page, leaving the sibling choice unresolved from the description alone.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters are already fully documented, and the baseline is 3. The description reinforces the directory-recursion behavior implied by 'path' but says nothing about the update_url parameter — the link-replacement workflow is only discoverable from the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb+resource ('Publish a local file, a zip, or a whole directory to a public URL') and enumerates supported content types, so the agent knows exactly what it does. However, it never mentions the sibling publish_page, so an agent choosing between the two gets no disambiguation from this text.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states a clear triggering condition — 'Use this when the page needs sibling files (CSS, JS, images) — write them into a directory first, then publish that directory' — plus the sharing use case for documents and media. What's missing is an explicit exclusion or pointer to publish_page for the single-page case.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv0.3.1
    • Changedpublish_page3 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / properties / claimUrl
        Added value: +{
        +  "description": "Private browser claim link for the publisher only. Never give it to page viewers or append it to the public URL.",
        +  "type": "string"
        +}
    • Changedpublish_path4 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedInput schema / properties / path / description
        Previous value: -"Absolute path to a file or directory on this machine. A directory is uploaded recursively with its structure preserved (symbolic links are skipped, so the upload cannot escape the directory); a zip archive is unpacked server-side."New value: +"Absolute path to a file or directory on this machine. A directory is uploaded recursively with its structure preserved; symbolic links and common private paths (.git, .env*, node_modules, .ssh, .aws) are skipped. An explicitly selected single file is uploaded as requested, so never select credentials or other secrets. A zip archive is unpacked server-side."
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / properties / claimUrl
        Added value: +{
        +  "description": "Private browser claim link for the publisher only. Never give it to page viewers or append it to the public URL.",
        +  "type": "string"
        +}
  2. 3 tool updatesv0.1.10
    • Removedpublish_html
    • Addedpublish_page
    • Changedpublish_path1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "note": {
        +      "description": "Human-readable status: created vs updated, and how long the page is kept.",
        +      "type": "string"
        +    },
        +    "url": {
        +      "description": "Public link to the published page — give this to the user.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "url",
        +    "note"
        +  ],
        +  "type": "object"
        +}
  3. 2 tool updates
    • Changedpublish_html1 field changed
      • changedInput schema / properties / html / description
        Previous value: -"The complete HTML document to publish, including the <html> tag."New value: +"The complete HTML document to publish, including the <html> tag. It must be self-contained: relative references to local files will not resolve — use publish_path when the page needs sibling files (CSS, JS, images)."
    • Changedpublish_path1 field changed
      • changedInput schema / properties / path / description
        Previous value: -"Absolute path to a file or directory on this machine."New value: +"Absolute path to a file or directory on this machine. A directory is uploaded recursively with its structure preserved (symbolic links are skipped, so the upload cannot escape the directory); a zip archive is unpacked server-side."
  4. 2 tool updatesv0.1.4
    • First observedpublish_html
    • First observedpublish_path

TDQS

A3.9/5.0

Scored across 2 tools

Disambiguation4/5

The split is clear in principle: publish_page takes in-hand content, publish_path takes a local file or directory. However, the descriptions overlap substantially — both claim to handle HTML, Markdown, code, and data files — which could make an agent hesitate over which to pick when content already exists as a local file.

Naming Consistency5/5

Both tools follow the same verb_noun pattern (publish_page, publish_path) with a shared prefix that signals a common action family. Fully predictable and readable.

Tool Count4/5

Two tools is on the thin side, but the server has a narrow, well-defined purpose (publishing artifacts to a public URL), and each tool covers a genuinely different input shape. Neither feels redundant.

Completeness3/5

The surface covers publishing but stops there: no update, list, or delete/unpublish operation, despite descriptions mentioning that token-backed pages can be updated in place and storage managed. An agent that wants to refresh or revoke a link has no tool for it.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables sharing artifacts (HTML, files, sites) with password protection and custom branding on your own domain, directly from any AI agent.
    8
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to upload, list, read, and delete static web pages via the Model Context Protocol, with REST API and optional authentication and TTL.
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to publish HTML or Markdown to a public URL with a single HTTP POST, automatically converting Markdown to a styled webpage, with no account or setup required.
    1 npm
    1
    MIT