MCP server
Dropper ships a Model Context Protocol server, so Claude and any other MCP client can publish and manage drops as tools. One binary, two transports: add the hosted endpoint as a custom connector and sign in with your Dropper account, or spawn it locally over stdio with a personal API key.
The hosted server speaks Streamable HTTP at /mcp and authenticates with OAuth — nothing to copy, paste, or store. Dropper identifies the connector either from Anthropic's hosted client metadata document (the recommended default: the client id is an HTTPS URL Dropper fetches and validates) or from an automatic RFC 7591 registration — both work. You then sign in the same way you sign in to the dashboard, and you approve the connection once.
https://dropp.sh/mcp- In Claude, open Settings → Connectors → Add custom connector.
- Paste https://dropp.sh/mcp as the server URL and add it. Leave "Use Anthropic's hosted client metadata (Recommended)" selected — Dropper reads Anthropic's published client metadata document and identifies the connector from it. "No client ID — register one automatically" works too; that is the older RFC 7591 registration path, and Dropper still offers it.
- Click Connect. Dropper sends you to Authelia to sign in (locally, the dev login stands in), then shows a one-time consent screen naming the connector and the single "drops" scope it is asking for.
- Approve, and the eleven tools below show up in the client. Access is granted to your Dropper account, so every drop the connector makes lands in your own namespace.
- The dashboard’s API Keys page lists the connection afterwards under “Connected apps”. Disconnecting there ends the connector’s access — it must ask for your approval again — though an access token it already holds keeps working until it expires, within the hour. Your drops and API keys are untouched.
Access tokens are short-lived and audience-bound to this server's MCP resource; the client refreshes them silently. The REST drop routes accept them too, the account routes never do. Personal API keys are not accepted here — they stay the credential for the REST API, the local stdio server below, and the CLI in scripts and CI.
Remote callers have no filesystem, so content is sent inline: html for a single page, or files for a multi-file site (utf8 or base64 entries, zipped server-side). Images need no inline bytes at all: add_drop_asset hands the server a public https URL to download straight into an existing drop.
# Any MCP client that implements the OAuth flow points at the same URL — no header, no key.
claude mcp add --transport http dropper https://dropp.sh/mcp
# Then run /mcp in Claude Code and authenticate; the browser flow is the same
# sign-in + consent as the connector UI.The local server can read your filesystem, so tools accept a path input — drop an .html or .md file, or a whole directory, straight from disk. Configuration comes from the same env vars or ~/.config/dropper/config.json the CLI uses; the token slot holds a personal API key minted on the dashboard's API Keys page (sign in with Authelia to get there). It takes an API key only: a dropper login in that file does not sign the stdio server in, and never moves the "url" its key goes to.
git clone https://gitlab.tolbbox.com/tolbnet/dropper.git
cd dropper/mcp
npm ci && npm run build
# register with Claude Code (any MCP client works the same way)
# DROPPER_TOKEN holds your personal API key from the dashboard's API Keys page;
# the stdio server takes a key only, never a dropper login
claude mcp add dropper \
-e DROPPER_URL=https://dropp.sh \
-e DROPPER_TOKEN=your-api-key \
-- node /path/to/dropper/mcp/dist/index.jsOnce registered, the eleven tools below show up automatically — just ask for what you want:
> Publish this report as a page on my dropper and protect it with a generated password.
# Claude calls create_drop with html (or files) + generate_password,
# then replies with the public URL and the passphrase.
> Put the photo at https://example.com/canyon.jpg into my utah-trip drop and use it on the page.
# Claude calls add_drop_asset (the server downloads the file — no image bytes pass through
# the model), then read_drop_file + write_drop_file to reference images/canyon.jpg from index.html.Generated passphrases are returned in the tool result, and list_drops and get_drop read them back on your own drops later. Blank passwords are rejected rather than silently clearing protection — clearing is an explicit flag.
create_drop
Publish a static page or site and get its public URL.
Provide exactly one content source. Local paths work only when the server runs locally over stdio; remote (HTTP) callers use html, markdown or files.
| Name | Type | Required | Description |
|---|---|---|---|
html | string | optional | Inline HTML for a single-page drop |
markdown | string | optional | Inline Markdown for a single-page drop, rendered as a styled page at the drop URL; ?raw=1 serves the source |
files | array | optional | Inline multi-file site: { path, content, encoding? } entries; must include an index.html, index.md or README.md at the root — the page the drop URL serves |
path | string | optional | Local .html or .md file, or a directory (zipped automatically) — stdio only |
slug | string | optional | Custom slug; random 8 chars when omitted |
name | string | optional | Display name — shown in the drops list and used as the title of a rendered Markdown page (a trailing .md is dropped). Defaults to the uploaded filename |
password | string | optional | Protect the drop with this access code |
generate_password | boolean | optional | Protect with a generated passphrase, returned in the result |
public | boolean | optional | List the drop in the cross-user gallery (default private). Discoverability only — never affects URL access or passwords |
description | string | optional | Short summary, at most 200 characters — shown under the name, and on the gallery when the drop is public |
labels | array | optional | Label paths naming the project the drop belongs to, e.g. ["acme/website"]. Up to three lowercase names joined by "/" (project/area/topic); a sublabel implies its parents, a missing label is created on the spot, at most 20 per drop |
list_drops
List your drops, newest first, with public URLs plus protection and gallery flags.
Your own rows carry their label paths in labels, and any row its description when set.
| Name | Type | Required | Description |
|---|---|---|---|
public | boolean | optional | When true, list every user’s gallery-public drops instead of your own |
label | string | optional | A label path, e.g. "acme": only your drops carrying it or one of its sublabels. Not with public |
list_labels
List your labels in tree order, each with its path, colour and drop count (sublabels counted in).
Check it before labelling a drop and reuse the path a project already has. Labels come into being by labelling a drop; rename, move, recolour and delete them in the dashboard or with the CLI’s dropper labels.
get_drop
Look up a single drop by slug — name, description, labels, kind, size, protection, public URL.
| Name | Type | Required | Description |
|---|---|---|---|
slug | string | required | The drop slug |
list_drop_files
List the files inside a drop with sizes and content types.
Works on protected drops — owning them grants read-back without a viewer unlock.
| Name | Type | Required | Description |
|---|---|---|---|
slug | string | required | The drop slug |
read_drop_file
Read one file from a drop — fetch current content before editing it with write_drop_file (one file) or update_drop (the whole drop).
Text files return utf8 content; binaries return base64. This returns the stored source: the styled page a browser sees for a .md file exists only at the drop’s /d/ URL. Files over 1 MiB are refused (fetch them via the API instead). Works on protected drops.
| Name | Type | Required | Description |
|---|---|---|---|
slug | string | required | The drop slug |
path | string | optional | File path inside the drop; defaults to index.html — a Markdown drop keeps its page at index.md |
write_drop_file
Write one file into an existing drop from inline content — create it or replace it in place — leaving every other file untouched.
For small text and assets (HTML, CSS, JS, SVG, JSON, tiny icons): inline bytes travel through the model as tokens, so real images and photos belong to add_drop_asset. To edit text, read_drop_file first and write the whole file back. Nested paths create their directories; the drop’s name, description, labels, password and gallery visibility are unchanged, and a drop left holding more than one file becomes kind "zip". Base64 is checked (standard alphabet, padding) before a request is made; the API caps a file at 20 MB and the drop at 200 MB and 2000 files. A .md file written into a drop renders as a styled page at its own /d/ URL when a browser opens it — table of contents, highlighted code, Mermaid diagrams — while the same URL still returns the stored bytes to anything that does not ask for HTML, and to ?raw=1. To replace a whole drop at once, use update_drop with html or files instead.
| Name | Type | Required | Description |
|---|---|---|---|
slug | string | required | Slug of the drop to edit |
path | string | required | Relative path inside the drop, e.g. "index.html" or "images/logo.svg" |
content | string | required | File content: text, or base64 with encoding "base64" |
encoding | string | optional | How content is encoded: "utf8" (default) or "base64" |
add_drop_asset
Add an image or other binary to an existing drop by having the server download it from a public https URL — the token-free way to put real images in a drop.
The bytes go straight from the source into the drop and never pass through the model (no base64, no tokens). The URL must be a public https:// address that answers 200 with the file itself: redirects are not followed, so give the final asset URL rather than a page, a shortener or a signed-redirect link; 20 MB at most; private, loopback and internal hosts are refused. Creates or replaces exactly one file at path — the served content type comes from its extension — and the drop becomes kind "zip" once it holds more than one file. Reference it from the HTML by relative path, e.g. <img src="images/photo.jpg">; hotlinked images rot when their source changes, ingested copies do not. To replace the whole drop at once, use update_drop with files instead; this tool adds or replaces one file.
| Name | Type | Required | Description |
|---|---|---|---|
slug | string | required | Slug of the drop to add the asset to |
path | string | required | Where to store it inside the drop, e.g. "images/photo.jpg" — the extension sets the served type |
url | string | required | Public https:// URL of the file, served directly (200, no redirect), up to 20 MB |
delete_drop_file
Delete one file from an existing drop, pruning any directories it leaves empty; the rest of the drop is untouched.
The drop’s entry page — index.html, index.md or README.md, whichever the drop root serves — cannot be deleted; replace it with write_drop_file instead (a nested index.html is fine). To remove the whole drop, use delete_drop.
| Name | Type | Required | Description |
|---|---|---|---|
slug | string | required | Slug of the drop to edit |
path | string | required | Path of the file to delete, e.g. "images/old.jpg"; use list_drop_files for the available paths |
update_drop
Edit an existing drop: rename, change its description or labels, change protection, toggle gallery visibility, or replace content — combinable in one call.
Renaming changes the public URL; changing or clearing the password revokes every viewer unlock. Replacement content uses the same html / markdown / files / path rules as create_drop and replaces the whole drop — to touch one file, use write_drop_file, add_drop_asset or delete_drop_file.
| Name | Type | Required | Description |
|---|---|---|---|
slug | string | required | Slug of the drop to edit |
new_slug | string | optional | Rename the drop |
password | string | optional | Set this access code |
clear_password | boolean | optional | Remove protection |
generate_password | boolean | optional | Set a generated passphrase, returned in the result |
public | boolean | optional | true lists the drop in the cross-user gallery, false delists it; omitted leaves visibility unchanged |
name | string | optional | Set the display name — shown in the drops list and used as the title of a rendered Markdown page (a trailing .md is dropped) — on its own, or alongside replacement content, which never renames the drop by itself |
description | string | optional | New description, at most 200 characters; "" removes it, omitted keeps it |
labels | array | optional | The drop’s whole new label set, as paths (same rules as create_drop); [] removes them all, omitted keeps them |
html / markdown / files / path | content | optional | Replacement content — same rules as create_drop |
delete_drop
Delete a drop; its public URL stops working immediately and the slug frees up right away.
Recoverable: the drop goes to your trash and stays restorable for 30 days from the dashboard (Profile → Deleted drops) or POST /api/trash/<id>. Only the API’s permanent=1 deletes outright, and this tool never sends it.
| Name | Type | Required | Description |
|---|---|---|---|
slug | string | required | The drop slug |