mcp-silverbullet
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-silverbulletsearch my notes for action items from the last team meeting"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-silverbullet
An MCP server that exposes a remote SilverBullet space
to an MCP client, over SilverBullet's /.fs HTTP API.
Reads are unrestricted across the space; writes are confined to a configurable page prefix.
Requirements
Python 3.11+ (
tomllib)A SilverBullet instance and an API token (admin UI > Users > API tokens)
Related MCP server: Obsidian MCP Server
Install
python3 -m venv .venv
.venv/bin/pip install -r requirements.txtConfiguration
Settings live in a TOML file, config.toml by default:
cp config.toml.example config.tomlKey | Required | Default | Description |
| yes | — | Space URL including its prefix, e.g. |
| yes | — | API token used for every request |
| no |
| Page prefix under which writing is allowed |
| no |
| Page prefixes hidden from listing and search |
| no |
| Interface the HTTP transport binds to |
| no |
| Port the HTTP transport listens on |
The file holds a token, so it is gitignored. An unknown key is an error rather than a silent fallback to the default.
Run
.venv/bin/python sb_mcp_http.py # reads ./config.toml
.venv/bin/python sb_mcp_http.py other.toml # or a path of your ownThe server speaks MCP over the streamable-http transport, on /mcp. It binds
to 127.0.0.1 by default, so a client on the same machine reaches it at
http://127.0.0.1:8000/mcp.
To reach it from anywhere else, put a reverse proxy in front of it rather than
changing host — see Deployment.
Tools
Tool | Description |
| Pages in the space, most recently modified first, minus |
| Markdown body of one page, named without the |
| Case-insensitive search over page names and bodies |
| Create a page, failing if it already exists |
| Append text to an existing page without overwriting the rest |
| Replace a page's whole content, to correct a note already written |
| Delete a page |
Every write tool rejects any page outside write_prefix, and they use HTTP
conditional requests — If-None-Match on create, If-Match on append,
replace and delete — so a page that changed underneath the server is neither
clobbered nor erased. A space that sends no ETag gets no write at all.
Filing notes outside the write prefix
Writes are confined to write_prefix, but most notes belong somewhere else —
a journal page, a project page. create_note and replace_note take a
destination for that: the note is still written under the prefix, with a
frontmatter key and a File button that files it on one click.
create_note(name="Inbox/client-sync", content="2:30pm client sync, nothing to report",
destination="Journal/2026-09-10")produces
---
destination: Journal/2026-09-10
---
${inbox.button()}
2:30pm client sync, nothing to reportClicking File appends the body to Journal/2026-09-10 and deletes the
note; the frontmatter and the button line are stripped on the way. The
destination is re-read after the write, and the source is deleted only once the
body is confirmed there — a write that did not land never costs the note.
The client never writes that frontmatter itself: it passes destination, the
server renders it, and the server's MCP instructions say so. Omit destination
and the content is written verbatim, for a note that genuinely lives under the
prefix.
The button and the command are not part of this server — they live in the
SilverBullet space, as space-lua/Inbox.md, a SilverBullet
library. Install it with the Library: Install command and this URI:
https://github.com/jgurhem/MCP-Silverbullet/blob/main/space-lua/Inbox.mdIt lands at Library/jgurhem/Inbox, and Library: Update pulls later versions —
no copying by hand. Reading a public repo needs no GitHub token.
Installing overwrites that page, so the pending-notes list lives in a page of
your own — your index, a Meta/Inbox, wherever you will actually see it. One
line in its body is enough:
${inbox.pending()}Each row carries a note's name, its destination and its own File button, so filing several notes does not mean opening each one.
Deployment
The server has no authentication of its own. Any request that reaches it
gets read access to the entire space, plus write access under
write_prefix, using the configured token. That is why it binds to the
loopback interface: authentication and TLS belong to a reverse proxy in front
of it.
Caddyfile.example is a working starting point. The one
non-obvious setting is flush_interval -1: MCP streams its responses as
server-sent events, and a proxy that buffers them leaves the client waiting
forever.
Setting host = "0.0.0.0" publishes an unauthenticated server on every interface.
Only do it where something else restricts access — a container published as
-p 127.0.0.1:8000:8000, or a private network you control.
Note that MCP's own HTTP auth is OAuth bearer-based, so a given client may not
support HTTP Basic. If yours does not, either use a proxy that accepts a bearer
token, or move authentication into the server itself: the SDK takes a
token_verifier on MCPServer(...) for exactly this.
Tests
.venv/bin/pip install -r requirements-dev.txt
.venv/bin/python -m pytestThe suite needs no network and no SilverBullet: tests/fake_space.py is an
ASGI stand-in for the /.fs API that keeps real ETag state, so the
conditional requests the write tools depend on are exercised against stored
state rather than against canned responses.
Known limitations
search_pages fetches every page in the space on each call, so search cost
grows linearly with space size.
License
Apache License 2.0 — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Notes, files, GitHub, and Drive through one MCP connection.
Notes, files, GitHub, and Drive through one MCP connection.
Notes, files, GitHub, and Drive through one MCP connection.
Search your Glasp web and Kindle highlights, notes, and AI memories from any MCP client. Read-only.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables LLMs to interact with SilverBullet notes and data through a bridge server. Provides secure access to read and manipulate your SilverBullet space via standardized MCP tools and resources.36MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to search, read, and append content to notes in an Obsidian vault via the MCP protocol.6,222 npmBSD Zero Clause
- AlicenseNot gradedqualityCmaintenanceAn MCP server that connects a SilverBullet space over its HTTP filesystem API, exposing a scoped prefix of notes to AI agents with read/write/delete capabilities.MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to list, read, search, create, update, rename, and delete markdown notes in a local Obsidian vault via an HTTP MCP endpoint.8 npmMIT