plugin-host.md describes the Keygen settings and answers, log redaction and the new tests, and replaces the empty-account-id gaps with Reddit's and Instagram's. .env.example gains the KEYGEN_* settings and names the eight plugins in PLUGINS. |
||
|---|---|---|
| .. | ||
| bundles | ||
| registry | ||
| remote | ||
| README.md | ||
Plugins
A plugin is a remote MCP server that gives SurfSense's agent tools. You host the server; SurfSense lists it, asks the user before connecting, and calls it. Any MCP server that works in other MCP clients works here unchanged. The design is the plugins proposal.
| Folder | What it holds |
|---|---|
registry/ |
The list of third-party plugins, their icons, the check every entry passes, and the container that serves them |
remote/ |
SurfSense's own plugins and the plugin host that runs them. Maintainers only for remote/proprietary/ |
bundles/ |
Deferred. The earlier, local design's SDK and tooling, kept for plugins that run on the user's machine |
The rest of this page is for publishers: companies and developers listing their own MCP server.
1. Build a server
-
Remote, over Streamable HTTP, on HTTPS. SurfSense does not run servers started by a command (
npx,uvx), and does not speak the legacy SSE transport. Any official MCP SDK serves Streamable HTTP. -
Protocol
2025-11-25or newer. SurfSense also speaks2026-07-28. -
Stateless if you can. A server that keeps no session between requests survives restarts and scaling, and loses nothing when SurfSense reconnects it, as it does when a sign-in token is refreshed.
-
Annotate every tool.
readOnlyHintanddestructiveHintdecide whether SurfSense asks the user before a call. A tool that says neither may destroy, as MCP's defaults say, so it asks before every call; a read-only one, or one markeddestructiveHint: false, asks until the user chooses to always allow it. -
Describe tools for a model. Say what the tool does and when to use it, as briefly as that allows: every description reaches the model on every turn. Instructions aimed at the model, such as "always call this first", are rejected in review.
-
Sign-in, one of:
authThe user Your server receives noneDoes nothing No credentials tokenPastes a key you give them Authorization: Bearer <key>oauthSigns in on your page in their browser Authorization: Bearer <access token>OAuth follows MCP's authorization spec: serve protected resource metadata, and support Client ID Metadata Documents or dynamic client registration. SurfSense signs in as
https://plugins.surfsense.com/oauth/client.jsonand redirects tohttps://plugins.surfsense.com/oauth/callback. If you only accept clients registered in advance, register SurfSense with those values and put the client id in your entry'sauth.client_id. SurfSense is a public client: it never holds a client secret.
2. Try it in SurfSense
You need no listing to try your server:
- Settings → Plugins → turn on Allow third-party plugins.
- Add MCP server, with its URL and, if it needs one, a key.
- Allow the tools you want, then ask the agent to use them in an Agentic thread.
A server added this way is marked third-party, not reviewed by SurfSense, and stays on that one computer.
3. List it
Open a pull request into dev that adds your entry to registry/plugins.json and your icon to registry/icons/.
{
"id": "acme-docs",
"kind": "remote",
"publisher": "community",
"name": "Acme Docs",
"description": "Search and read Acme's public documentation.",
"author": "Acme Inc.",
"url": "https://mcp.acme.example/mcp",
"auth": { "type": "none" },
"hosts": ["mcp.acme.example"],
"access": "free",
"privacy_policy": "https://acme.example/privacy",
"homepage": "https://acme.example",
"icon": "acme-docs.svg"
}
id: lowercase letters, digits and hyphens, unique, never reused once listed.publisher:community.partner(shown as "Verified") needs evidence in the pull request that you speak for the company that runs the server.hosts: every host SurfSense contacts for your plugin: your server's, and for OAuth your authorization server's. The user consents to each.access:free, orexternalwith anaccess_notesaying what the user must buy or have.privacy_policy: required. The user's requests and credentials reach your server, so this is yours, not your API provider's.icon: SVG or PNG, square, at most 32 KB; PNG at least 64×64; SVG with no scripts, event handlers or external references. Without one, SurfSense shows your name's first letter.
The full rules are in the registry proposal.
What happens to your pull request
- CI checks the entry against the rules above, and your icon.
- A maintainer reviews it once: they connect your plugin, signing in if it needs it, and check who runs the server, what its tools do, that no description carries instructions aimed at the model, that
hostsis complete, and that the privacy policy is real. - Once merged into
dev, CI signs the list. It is published atplugins.surfsense.com/plugins.jsonwith SurfSense's next release fromdevtomain, and reaches every app that allows third-party plugins with no app update.
To run the same check yourself, from plugins/registry/check/:
uv sync
uv run python -m registry_check static # the entry rules and your icon
4. After it is listed
- Changing your server needs no pull request. Deploy when you like. A tool you add, or one whose description or annotations change, starts off in every app until the user turns it on.
- Changing your entry is another pull request and another review.
- Removing a plugin moves its entry to
removedwith a reason. Apps stop offering its tools and show the reason; users keep their connection in case it returns.