Skip to main content
Glama

support-kb-server

A role-based knowledge-base MCP server for a support bot. It serves FAQ answers out of a local vector store and gates write operations behind an admin bearer token, while a read_only token can only ask questions.

Everything runs locally — no API keys, no hosted services:

Concern

Choice

MCP server

mcp Python SDK (FastMCP), over streamable HTTP

Vector store

ChromaDB, embedded persistent mode → ./chroma_data

Embeddings

sentence-transformers all-MiniLM-L6-v2 (fully local)

Auth

Two bearer tokens → two roles, in-memory token → role mapping

Tools & permissions

Tool

admin

read_only

Notes

answer_question(query)

✅

✅

Retrieves top FAQ match + source snippet

add_knowledge(question, answer)

✅

❌

Adds an FAQ entry (audit-logged)

delete_knowledge(doc_id)

✅

❌

Removes an FAQ entry by id (audit-logged)

list_knowledge()

✅

❌

Lists all entries with ids (for delete refs)

Every tool call reads the caller's Authorization: Bearer <token> header, looks up the role, and returns a clear "Permission denied" error if that role may not call the tool.

Related MCP server: KB-MCP Server

Setup

Requires Python 3.10+.

pip install -r requirements.txt

The first run downloads the all-MiniLM-L6-v2 model (~90 MB) from Hugging Face and caches it locally. Every run after that is fully offline.

Run the server

python server.py

On startup the server:

  1. Seeds the Chroma collection with 10 sample FAQ entries (first run only).

  2. Prints the two bearer tokens, clearly labeled, to the console — this is where you copy them from:

    ====================================================================
      support-kb-server - BEARER TOKENS (copy these now)
    ====================================================================
      ADMIN     (full access)     : admin-XXXXXXXXXXXXXXXXXXXX
      READ_ONLY (answer_question) : readonly-XXXXXXXXXXXXXXXXXXXX
    ====================================================================
      Endpoint: http://127.0.0.1:8000/mcp
    ====================================================================
  3. Starts the MCP endpoint at http://127.0.0.1:8000/mcp.

Fresh random tokens are generated on each startup. To pin them (useful for scripts/CI), set env vars before launching:

# PowerShell
$env:KB_ADMIN_TOKEN="admin-my-fixed-token"; $env:KB_READONLY_TOKEN="readonly-my-fixed-token"; python server.py

# bash
KB_ADMIN_TOKEN=admin-my-fixed-token KB_READONLY_TOKEN=readonly-my-fixed-token python server.py

Other env vars: KB_HOST (default 127.0.0.1), KB_PORT (default 8000).

The active tokens + endpoint are also written to .mcp_tokens.json so the test script can authenticate without copy-pasting.

Test it

With the server running in one terminal, run the test harness in another:

python test_local.py

It opens real MCP client sessions over HTTP with each token and verifies the full matrix — read_only is allowed only on answer_question and denied on the other three; admin succeeds on all four — printing clear PASS/FAIL per check:

--- read_only role ---
[PASS] read_only can call answer_question
[PASS] read_only is DENIED add_knowledge
[PASS] read_only is DENIED delete_knowledge
[PASS] read_only is DENIED list_knowledge
--- admin role ---
[PASS] admin can call answer_question
[PASS] admin can call add_knowledge
[PASS] admin can call list_knowledge (sees new entry)
[PASS] admin can call delete_knowledge

8/8 checks passed

Audit log

Every successful add_knowledge / delete_knowledge call appends one JSON line to audit_log.jsonl:

{"timestamp": "2026-09-06T16:05:37.458146+00:00", "role": "admin", "tool": "add_knowledge", "arguments": {"question": "...", "answer": "...", "doc_id": "faq-7ee3b2da05e3"}}

Denied calls and read-only queries are not logged.

Connect it to Claude Desktop / claude.ai as a custom connector

This server speaks streamable HTTP with bearer auth, so it plugs in as a custom connector.

claude.ai (and Claude Desktop) require an HTTPS URL for custom connectors, so a local http://127.0.0.1:8000 URL is rejected. Expose the server over HTTPS with a tunnel such as ngrok.

1. Start the server so it accepts the tunnel's hostname

The MCP server has built-in DNS-rebinding protection that, by default, only trusts localhost. A tunnel forwards requests under its own public hostname, so tell the server to accept it via KB_ALLOWED_HOSTS. Because every tool is already gated by a bearer token, * (accept any host) is fine here:

# PowerShell — pin tokens too so they survive restarts
$env:KB_ALLOWED_HOSTS="*"
$env:KB_ADMIN_TOKEN="admin-supportkb-8f3a2c17d9e4"
$env:KB_READONLY_TOKEN="readonly-supportkb-2b6d40af71c8"
python server.py
# bash
KB_ALLOWED_HOSTS='*' python server.py

(You can instead pin exact hosts: KB_ALLOWED_HOSTS="myname.ngrok-free.app".)

2. Open the tunnel

ngrok http 8000

ngrok prints a forwarding URL like https://eb41-49-238-50-150.ngrok-free.app. Your MCP endpoint is that URL with /mcp appended. (A free-tier ngrok subdomain changes each time you restart ngrok — that's the reason for KB_ALLOWED_HOSTS="*".)

3. Add it in Claude → Settings → Connectors → "Add custom connector"

  1. Give it a name, e.g. Support KB.

  2. URL: https://<your-ngrok-subdomain>.ngrok-free.app/mcp

  3. Authentication: choose the bearer / access-token option and paste one of the tokens the server printed:

    • the admin token to enable all four tools, or

    • the read_only token to expose only answer_question.

  4. Save. Claude runs the MCP handshake and lists the tools your token is allowed to use. Ask a support question and it will call answer_question.

Troubleshooting 421 Misdirected Request: the server didn't trust the tunnel hostname — start it with KB_ALLOWED_HOSTS="*" (or the exact ngrok host) as above. Keep both the server and ngrok processes running the whole time Claude is connected.

Project layout

kb_store.py       # Chroma + embeddings + seed data + query/add/delete/list helpers
server.py         # FastMCP server: tools, auth/roles, audit logging, token printing
test_local.py     # End-to-end role/permission test over HTTP
requirements.txt
chroma_data/      # persisted vector store (created on first run)
audit_log.jsonl   # append-only audit trail (created on first admin write)
.mcp_tokens.json  # active tokens+endpoint, written for the test script

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    Not graded
    maintenance
    A local-first knowledge base server that enables AI clients to store, retrieve, and manage documents using semantic search. Provides privacy-focused, offline-capable memory for AI assistants with tools for ingesting, querying, updating, and deleting knowledge.
    7
    191 npm
    -
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables ticket management through a REST API and support document search via a local vector database, powered by Ollama and LanceDB.
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    Standalone MCP server exposing agentic-RAG tools (hybrid search, article retrieval, category listing) over a pgvector-backed knowledge base with bearer-token auth, designed for deployment on Render.
    -