-
Notifications
You must be signed in to change notification settings - Fork 32
Integrations
How other extensions, scripts, and AI agents drive Save in. It listens on browser.runtime.onMessageExternal (any extension) and onMessage (same extension), and — experimentally — registers WebMCP tools.
Extension IDs are platform-specific:
- Firefox:
{72d92df5-2aa0-4b06-b807-aa21767545cd} - Chrome Web Store:
jpblofcpgfjikaapfedldfeilmpgkedf
The options page shows the ID of the installed build. Other extensions must send to the ID for the browser they are running in.
Not officially supported beyond what's documented here. Use at your own risk.
Push a URL into the routing/rename pipeline. PING first to negotiate the version.
const ID = "{72d92df5-2aa0-4b06-b807-aa21767545cd}"; // Firefox; use the Chrome ID on Chrome
// Discover the version and capabilities
await browser.runtime.sendMessage(ID, { type: "PING" });
// -> { type: "PONG", body: { version: 1, capabilities: [...] } }
// Save a URL
await browser.runtime.sendMessage(ID, {
type: "DOWNLOAD",
body: {
url: "https://example.com/pic.jpg", // required
comment: "foo", // optional; matched by `comment:` rules
info: {
// all optional
pageUrl: "https://example.com/",
srcUrl: "https://example.com/pic.jpg",
selectionText: "…",
},
},
});
// -> { status: "OK", version, url }
// | { status: "ERROR", error, message, version }-
errorisBAD_REQUEST,INVALID_URL, orUNKNOWN_TYPE. - Only
http(s),ftp,data, andblobURLs are accepted. - The download runs through the same routing rules,
:variables:, Referer feature, auto-retry, history, and notifications as a context-menu save.status: "OK"means accepted, not finished.

-
Foxy Gestures → options →
User Scripts→ new gesture. -
Use this script (the ID is Save in's Mozilla Addons ID):
const source = data.element.mediaInfo && data.element.mediaInfo.source; if (source) { browser.runtime.sendMessage("{72d92df5-2aa0-4b06-b807-aa21767545cd}", { type: "DOWNLOAD", body: { url: source, info: { pageUrl: `${window.location}`, srcUrl: source }, comment: "foo", }, }); }
-
Assign a gesture to the script.
comment is targetable in routing rules:
comment: foo
into: ./from-foxy/:filename:
Read the schema, validate paths/rules, and apply config — the basis for scripted and AI-assisted setup.
-
GET_SCHEMA→{ version, options: [{ name, type, default, description }] }. Read-only. -
VALIDATE{ paths?, filenamePatterns? }→{ pathErrors, ruleErrors, menuPreview }. Dry-run, read-only. -
GET_KEYWORDS→{ variables, matchers }— the:variables:(paths/filenames) and clause matchers (fileext,into,capture, … for Dynamic Downloads rules). -
APPLY_CONFIG{ config: { name: value } }→{ applied, rejected }. Validated against the schema (unknown keys and type mismatches rejected). Same-extension only — not reachable viaonMessageExternal.
In a WebMCP-capable Chrome, the options page registers five tools an in-browser agent can call.
| Tool | Purpose | Input |
|---|---|---|
save_in_get_schema |
List every option with its type, default, and description | {} |
save_in_list_vocabulary |
List :variables: and Dynamic Downloads matchers |
{} |
save_in_validate_config |
Dry-run paths/rules and optionally trace a sample download | { paths?, filenamePatterns?, info? } |
save_in_apply_config |
Validate and store a partial configuration | { config: { optionName: value } } |
save_in_download |
Save a URL through the normal routing/rename pipeline | { url, pageUrl?, comment? } |
- In Chrome, enable
chrome://flags/#enable-webmcp-testingand relaunch. Origin-trial builds can use their trial enrollment instead. - Open Save In's options page and keep the tab open.
- Under Advanced → External integrations → WebMCP, confirm
Active — 5 tools registered. - Point your in-browser agent at the tab.
Ask in plain language — e.g. "sort my downloads into folders by website and date, number each file, and notify me only on failures." The recommended flow is:
save_in_get_schemasave_in_list_vocabularysave_in_validate_config- Fix any
pathErrorsorruleErrors save_in_apply_config
Example validation input for a positive fileext trace:
{
"filenamePatterns": "fileext: jpg\ninto: gallery/:sourcedomain:/:filename:",
"info": {
"srcUrl": "https://example.test/photo.jpg",
"filename": "photo.jpg",
"pageUrl": "https://example.test/gallery"
}
}Use srcUrl for fileext matching. If the sample only has url, use the urlfileext matcher. A successful trace reports the selected rule and the expanded, sanitized final path.
save_in_apply_config is partial: omitted options stay unchanged; omission does not delete a stored key. To restore an option, apply the default returned by save_in_get_schema. Unknown options, malformed tool arguments, and type mismatches are rejected.
For manual debugging, document.modelContext.executeTool(tool, args) expects args as a JSON string. Chrome may also return structured results as JSON text, so debugging clients should decode either form. Normal agents handle this transport detail themselves.
The tools are annotated so agents can distinguish read-only operations from config/download mutations and inputs that may contain untrusted page data. The API is still subject to change and the tools remain available only while the options tab is open.
-
onMessageExternalaccepts from any installed extension and triggers downloads. The URL scheme is validated but senders aren't allowlisted — treat "can install an extension" as the trust boundary. -
APPLY_CONFIGis deliberately internal-only. - No
externally_connectableblock, so web pages can't message Save in directly — only extensions can.