Bookmarks MCP Server
by dgholamian
README.md
# Bookmarks MCP Server
A Postgres-backed bookmark manager, plus a generic REST API tool, exposed as
an [MCP](https://modelcontextprotocol.io) server so an LLM client (e.g.
Claude Desktop) can save, search, and manage bookmarks on your behalf.
## What it does
- Stores bookmarks (url, title, description, tags) in Postgres via `asyncpg`
- Exposes CRUD tools: `add_bookmark`, `list_bookmarks`, `get_bookmark`,
`search_bookmarks`, `update_bookmark`, `delete_bookmark`
- Exposes DB inspection tools: `list_tables`, `describe_table`, `run_query`
(SELECT-only, for safety)
- Exposes one generic REST tool, `api_request`, that calls whatever API you
configure via `API_BASE_URL` in `.env` (any method, path, query params,
JSON body) — by default this is set up to use
[Microlink](https://microlink.io) (free, no API key) for fetching link
previews (title/description/image) of a URL before saving it
## Setup
### 1. Database
Create a dedicated role and database (don't use the Postgres superuser for
the app itself):
```sql
CREATE ROLE bookmarks_app WITH LOGIN PASSWORD 'choose-a-password';
CREATE DATABASE bookmarks OWNER bookmarks_app;
```
Then create the table:
```
psql -U bookmarks_app -h localhost -d bookmarks -f schema.sql
```
### 2. Python environment
```
python -m venv venv
venv\Scripts\activate # Windows
# source venv/bin/activate # macOS/Linux
pip install -r requirements.txt
```
### 3. Configure `.env`
```
copy .env.example .env # Windows
# cp .env.example .env # macOS/Linux
```
Fill in:
- `DATABASE_URL` — the `bookmarks_app` connection string
- `API_BASE_URL` / `API_KEY` — the REST API you want `api_request` to call
(defaults to Microlink, which needs no key; leave `API_KEY` blank for any
API that doesn't require auth)
### 4. Run it
```
python src/server.py
```
## Connect to Claude Desktop
Add an entry to your `claude_desktop_config.json`:
```json
{
"mcpServers": {
"bookmarks": {
"command": "/absolute/path/to/bookmarks-server/venv/Scripts/python.exe",
"args": ["/absolute/path/to/bookmarks-server/src/server.py"]
}
}
}
```
Env vars are read from `.env` (via `python-dotenv`, resolved relative to the
project root regardless of the process's working directory), so nothing
sensitive needs to go in the Claude config itself.
**Windows Store (MSIX) installs of Claude Desktop:** the config file isn't
at the usual `%APPDATA%\Claude\` path — it's sandboxed under
`%LOCALAPPDATA%\Packages\<Claude package id>\LocalCache\Roaming\Claude\claude_desktop_config.json`.
Fully quit Claude Desktop from the system tray (not just closing the window)
before editing it, then relaunch.
## Security notes
- All queries use parameterized SQL (`$1`, `$2`, ...) — no string-built SQL,
so no injection risk from tool arguments.
- `run_query` only allows `SELECT` statements. Writes go through the
dedicated CRUD tools instead, which is a deliberate narrower surface for
an LLM-driven client.
- `bookmarks_app` is a non-superuser role scoped to the `bookmarks`
database — the server never connects as the Postgres superuser.
- `.env` is gitignored. Never commit real credentials — use `.env.example`
as the template.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues