Skip to main content
Glama
amar-tya

ishari-mcp-server

by amar-tya

ishari-mcp-server

MCP server exposing read-only ISHARI shalawat content (from Supabase) as a tool an AI agent can call. Built as a learning scaffold following the official MCP best-practice guidelines (tool naming, Zod validation, pagination, annotations, RLS-respecting auth).

Setup

npm install
cp .env.example .env   # then fill in SUPABASE_URL and SUPABASE_ANON_KEY
npm run build

Related MCP server: Quran Cloud MCP Server

Run locally (stdio)

npm start

It will sit waiting for an MCP client to connect over stdin/stdout - that's normal, it's not a web server.

Test with MCP Inspector

npx @modelcontextprotocol/inspector node dist/index.js

This opens a local UI where you can call ishari_search_shalawat directly and see the raw request/response, without needing a full AI client.

Connect to Claude Desktop / Claude Code

Add to your MCP client config (e.g. claude_desktop_config.json):

{
  "mcpServers": {
    "ishari": {
      "command": "node",
      "args": ["/absolute/path/to/ishari-mcp-server/dist/index.js"],
      "env": {
        "SUPABASE_URL": "https://your-project-ref.supabase.co",
        "SUPABASE_ANON_KEY": "your-anon-public-key"
      }
    }
  }
}

Restart the client, then ask it something like "cari sholawat tentang rezeki".

Run remotely over HTTP (e.g. a homelab box + Tailscale)

stdio only works when the client can spawn the server as a local child process. To run this on a separate machine (a homelab mini PC reachable over Tailscale) and keep it running continuously, use the HTTP entry point instead - same tools, same Supabase logic, just a different transport.

On the remote machine:

git clone <this-repo-url> ishari-mcp && cd ishari-mcp
npm install
cp .env.example .env   # fill in SUPABASE_URL, SUPABASE_ANON_KEY
npm run build

# Optional but recommended: a shared secret so not everyone on your
# tailnet can call these tools. Generate one and add it to .env:
echo "MCP_API_KEY=$(openssl rand -hex 32)" >> .env
echo "PORT=3000" >> .env
echo "HOST=0.0.0.0" >> .env   # 0.0.0.0 so Tailscale peers (not just localhost) can reach it

npm run start:http

Visit http://<tailscale-ip>:3000/mcp from another device on your tailnet to confirm it's reachable (a bare GET returns a 405 - that's expected, it means the server is up and only accepts MCP's POST requests).

Run it as a systemd service (so it survives reboots/SSH disconnects) - create /etc/systemd/system/ishari-mcp.service:

[Unit]
Description=ishari-mcp-server (HTTP)
After=network.target

[Service]
Type=simple
WorkingDirectory=/home/YOUR_USER/ishari-mcp
ExecStart=/usr/bin/node --env-file=.env dist/httpServer.js
Restart=on-failure
User=YOUR_USER

[Install]
WantedBy=multi-user.target

Then:

sudo systemctl daemon-reload
sudo systemctl enable --now ishari-mcp
journalctl -u ishari-mcp -f   # tail logs

On the client machine, point it at the URL instead of a local command. For Claude Code:

claude mcp add ishari-remote -s user --transport http \
  http://<tailscale-ip>:3000/mcp \
  --header "Authorization: Bearer <your MCP_API_KEY>"

For Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "ishari-remote": {
      "url": "http://<tailscale-ip>:3000/mcp",
      "headers": { "Authorization": "Bearer <your MCP_API_KEY>" }
    }
  }
}

Security notes specific to this mode:

  • Without MCP_API_KEY set, anyone who can reach the port (i.e. anyone on your tailnet, unless restricted by Tailscale ACLs) can call every tool. Since tools use the Supabase anon key (RLS-scoped, same as any anonymous app user could see), the blast radius is limited - but ishari_list_bookmarks still requires the caller's own access_token per-request regardless, so no amount of API-key bypass exposes another user's bookmarks.

  • This is a stateless HTTP server (sessionIdGenerator: undefined) - every request gets a fresh McpServer instance, so there's no session state that could leak between different callers.

  • Prefer Tailscale ACLs restricting which of your own devices can reach this port, on top of the MCP_API_KEY check - defense in depth.

Current tools

  • ishari_search_shalawat - search verse translations by keyword, paginated.

  • ishari_get_chapter(book_id, chapter_number) - fetch a full chapter with all verses.

  • ishari_list_bookmarks(access_token) - per-user bookmarks, scoped by the caller's own Supabase Auth token via RLS (see services/supabaseClient.ts for why a fresh client is created per call instead of a shared one).

  • ishari_get_verse_audio(book_id, chapter_number, verse_number?) - audio recitation links for a chapter (or one verse), with reciter name and style.

  • ishari_list_hadi(query?) - list reciters (qari), optionally filtered by name, each with a count of their audio recitations.

Evaluating tool-use quality

See evals/EVALS.md - 10 prompts to run against a real agent to check it picks the right tool, extracts arguments correctly, and knows when a request falls outside what these tools can do.

Next steps (left as exercises)

  • Add a way to search by chapter title, not just translation text (see eval #5 in evals/EVALS.md for why this gap matters).

  • ishari_search_shalawat currently only searches one language_code at a time - consider whether searching across all languages by default is better UX.

Security notes

  • Uses the Supabase anon key, so every query goes through RLS - this server can never see more than an anonymous app user legitimately can.

  • No secrets are hardcoded; both values come from environment variables.

  • Errors from Supabase are surfaced with a hint, not raw internals.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Provides AI assistants with comprehensive access to Islamic resources including Quran verses with translations, Tafsir commentary, Hadith collections, and audio recitations. Enables users to explore Islamic texts, get daily inspiration, and access scholarly interpretations through natural language queries.
    18
    9 npm
    10
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Connects LLMs to the Quran API (alquran.cloud) to retrieve accurate Quranic text on-demand, reducing hallucinations when working with sensitive religious content.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables fetching and searching canonical hadith texts (Arabic and English) with cross-references and citation-safe URLs for assistants, built on FastMCP.
    2
    GPL 3.0