jagypus

signal-mcp

Community jagypus
Updated

MCP server for read-only access to Signal Desktop's encrypted SQLite database.

signal-mcp

A Node/TypeScript MCP server that readsSignal Desktop's encrypted SQLite database directly and exposes richer querytools than the original Python signal-mcp-server.

Read-only. The database is opened with readonly: true andquery_only=ON. The server cannot modify Signal's data.

Requirements

  • macOS, with Signal Desktop installed and at least signed in once.
  • Node.js 20+.
  • On first run you'll see one macOS Keychain prompt — approve it (and checkAlways Allow if you don't want to be asked again). The server reads theSignal safeStorage password from your login keychain to decrypt theSQLCipher key.

Install

Step 1 — clone and install deps

git clone https://github.com/jagypus/signal-mcp.git
cd signal-mcp
npm install

The repo ships a pre-built dist/ so no compile step is needed; npm installjust pulls runtime deps.

Step 2 — register with your Claude client

The two clients share the same MCP server JSON shape but read it fromdifferent files. Pick whichever you use.

Claude Code

One-liner via the CLI:

claude mcp add signal --scope user -- node "$(pwd)/dist/index.js"

Or edit ~/.claude.json (or a project .mcp.json) and add:

{
  "mcpServers": {
    "signal": {
      "command": "node",
      "args": ["/Users/you/signal-mcp/dist/index.js"]
    }
  }
}
Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)or %APPDATA%\Claude\claude_desktop_config.json (Windows) and add:

{
  "mcpServers": {
    "signal": {
      "command": "node",
      "args": ["/Users/you/signal-mcp/dist/index.js"]
    }
  }
}

Then fully quit and relaunch Claude Desktop — it only reads this file atstartup. (Claude Code picks up claude mcp add immediately, but you'll needto restart any active sessions.)

Step 3 — verify

  • Claude Code: claude mcp list should include signal.
  • Claude Desktop: check the connectors / tools panel; the five signaltools should be listed.

Then ask: "List my Signal chats."

Updating

cd /path/to/signal-mcp
git pull
npm install

Restart Claude Desktop, or restart your Claude Code session, to pick upchanges.

Removing

# Claude Code:
claude mcp remove signal

# Claude Desktop: delete the "signal" entry from claude_desktop_config.json,
# then relaunch the app.

rm -rf /path/to/signal-mcp

Why not npm install -g git+https://...?

It looks attractive but currently fails on npm 11.x: the global-install pathmishandles native-dep install scripts (better-sqlite3-multiple-ciphers) andpartially-extracts the package tarball, leaving a broken install. Theclone-and-register flow above sidesteps the issue entirely.

Tools

Tool Purpose
list_chats List conversations with last-message metadata, filterable by group/DM, message count, and recency.
get_recent_messages Cross-chat message query with date range, sender, and chat filters.
get_chat_messages Same filter set, scoped to a single chat (by id or name).
search_messages Full-text-ish search across all message bodies. Falls back to LIKE.
query_sql Read-only SQL passthrough (SELECT/WITH/EXPLAIN/PRAGMA).

All inputs are validated with Zod. Timestamps are ISO 8601 in/out.

Filtering rules

  • exclude_system (default true) keeps only type IN ('incoming','outgoing'),filtering out keychange, profile-change, group-v2-change,timer-notification, etc.
  • only_with_body (default true) excludes attachment-only / reaction /sticker rows where body IS NULL.
  • sender: me (outgoing), them (incoming), any (both).

Development

git clone https://github.com/jagypus/signal-mcp.git
cd signal-mcp
npm install
npm run build               # compile to dist/
npm run dev                 # tsx, stdio (no build step)
npm run probe               # dump schema/FTS/types against the live DB
npx tsx scripts/smoke.ts    # exercise every tool against the live DB

How it opens the DB

Signal Desktop on macOS stores the SQLCipher v4 database at~/Library/Application Support/Signal/sql/db.sqlite. Modern Signal versionsstore the SQLCipher key encrypted in config.json under encryptedKey usingElectron's safeStorage:

  • Strip v10/v11 prefix → AES-128-CBC ciphertext.
  • Encryption key = PBKDF2-HMAC-SHA1(password, "saltysalt", 1003 iters, 16 bytes).
  • On macOS, password is fetched via security find-generic-password -s "Signal Safe Storage" -a "Signal" -w (one keychain prompt the first time).
  • IV is 16 bytes of 0x20.

The plaintext is the 64-char hex SQLCipher key. Older Signal builds with aplaintext key in config.json are also supported.

The DB is opened with better-sqlite3-multiple-ciphers in readonly: truemode and query_only=ON is set as a belt-and-braces guard. Opening whileSignal Desktop is running works fine because SQLCipher uses WAL.

Search caveat

messages_fts exists but uses Signal's custom signal_tokenizer which isregistered only by Signal Desktop's native code. Third-party readers can't runMATCH queries against it, so search_messages probes once and silentlyfalls back to body LIKE '%query%'.

Environment

Var Effect
SIGNAL_DIR Override default Signal data directory (useful for fixtures).
SIGNAL_KEY 64-char hex SQLCipher key, bypassing config.json/Keychain.

Cross-platform notes

  • macOS: handled.
  • Linux: safeStorage v10 uses the literal password peanuts. v11 (libsecret/KWallet) is not implemented — set SIGNAL_KEY explicitly.
  • Windows: not implemented — set SIGNAL_KEY explicitly.

Project layout

src/
  index.ts             # MCP server bootstrap
  db.ts                # connection + safeStorage key decryption
  schema.ts            # zod input shapes
  util/
    time.ts            # iso <-> ms
    messages.ts        # row shaping, display name resolution
    sql.ts             # shared filter SQL
  tools/
    listChats.ts
    getRecentMessages.ts
    getChatMessages.ts
    searchMessages.ts
    querySql.ts
scripts/
  probe.ts             # live-DB schema dump
  smoke.ts             # live-DB end-to-end check

License

MIT — see LICENSE.

This project is not affiliated with or endorsed by Signal Messenger LLC.Signal Desktop itself is licensed under AGPL-3.0; this project does notredistribute or modify any Signal code, it only reads the local SQLitedatabase that Signal Desktop creates on your own machine.

MCP Server · Populars

MCP Server · New