Skip to main content
Glama
NabuDesk MCP server

NabuDesk MCP server

Official
by NabuxAi

NabuDesk MCP server

Drives NabuDesk conversationally instead of through the Livewire panel: create a business, write its knowledge base, and check what the support bot would answer — without opening a browser or reaching for docker exec.

MCP client (Claude Code / Claude Desktop)
   │ stdio
   ▼
mcp-server/index.js                     ← runs locally
   │ HTTPS + X-Internal-Token
   ▼
NabuDesk  /api/internal/v1/*            ← app/Http/Controllers/Api/Internal
   │
   ▼
BusinessProvisioningService · KnowledgeSyncService · SupportDryRunService

The MCP server holds no business logic. It is a transport adapter over the operator API, so the panel and the API cannot drift apart.

Security

INTERNAL_API_TOKEN is a single shared secret that is not scoped to a business — it can read and write every business on the instance. It is for staff only. Never hand it to a customer, and never put it in a client-side app.

When the variable is unset the entire /api/internal/* surface returns 503, so a deploy that forgets the secret fails closed rather than serving the API unauthenticated.

Related MCP server: rbac-rag-assistant

Setup

On the NabuDesk instance, set the secret (in Coolify's environment variables, so it survives a redeploy — a value written only into the container's .env is lost on the next deploy):

openssl rand -hex 32
# → INTERNAL_API_TOKEN=<value>

Locally:

cd mcp-server
npm install
npm run build

Register it with your MCP client. For Claude Code:

claude mcp add nabudesk \
  --env NABUDESK_URL=https://desk.nabuxai.com \
  --env NABUDESK_TOKEN=<the same value> \
  -- node /absolute/path/to/NabuDesk/mcp-server/index.js

Or in claude_desktop_config.json:

{
  "mcpServers": {
    "nabudesk": {
      "command": "node",
      "args": ["/absolute/path/to/NabuDesk/mcp-server/index.js"],
      "env": {
        "NABUDESK_URL": "https://desk.nabuxai.com",
        "NABUDESK_TOKEN": "<the same value>"
      }
    }
  }
}

Variable

Required

Default

Purpose

NABUDESK_URL

yes

—

Base URL of the instance

NABUDESK_TOKEN

yes

—

Must equal INTERNAL_API_TOKEN there

NABUDESK_TIMEOUT_MS

no

60000

Raise if the AI gateway is slow

Tools

Businesses

Tool

Does

list_businesses

All businesses with AI settings, knowledge count, Telegram link state

get_business

One business including its full AI context text

upsert_business

Create or update. Idempotent by (owner, name) — safe to retry

get_link_status

Which of the two manual Telegram steps are still pending, with the exact instructions

Custom Domains & Zone Mapping

Tool

Does

list_domains

All custom domains mapped to a business with status and DNS records

add_domain

Connect custom domain / subdomain (forms, quizzes, bio-links, booking) and get DNS instructions

verify_domain

Live test of CNAME / A / TXT DNS records and instant activation

delete_domain

Remove a custom domain from the business

Knowledge

Tool

Does

list_knowledge

Every item with content and embedding state

upsert_knowledge

Add or replace by title. Embeds and indexes in one batch; returns embedded beside written

delete_knowledge

Removes the row and its Qdrant vector

reindex_knowledge

Re-embed everything — after a model change or a direct DB edit

Diagnostics

Tool

Does

ask

The answer the support agent would give — no contact, no conversation, no budget spend

test_retrieval

Cosine score per knowledge item, and which clear the threshold

list_unanswered

Questions the bot could not answer — the knowledge-gap queue

health

Database, Qdrant, embeddings and AI gateway reachability

Why test_retrieval exists

The failure it catches is silent. EmbeddingService::searchKnowledge() drops anything below a 0.2 minimum score. The embedding model is cross-lingual but weak: a non-English question can rank the correct document first and still score under the threshold, so nothing is retrieved and the bot answers from the context alone — confidently, and without the specifics.

Measured on the Zooey Support knowledge base before it was made trilingual:

Question

Top score

Retrieved

How do I connect WhatsApp?

0.689

yes

كيف أربط واتساب؟

0.430

yes

كم سعر الباقة الاحترافية؟

0.160

no

چطور واتساپ رو وصل کنم؟

0.298

yes

Writing the knowledge in the languages customers actually use raised the failing case to 0.297. test_retrieval is how you see that, since ask alone still returns a plausible-looking answer.

Why upsert_knowledge returns two counts

EmbeddingService::embedMany never throws. It returns null for any text it could not embed — including when the provider key is unset or the request failed. Without counting, every row is written with a null vector and reported as a success while being permanently unretrievable.

written is how many rows were stored; embedded is how many of them can actually be found. They should match. If nothing could be embedded the call returns 503 and writes nothing, because a business with knowledge it can never retrieve is worse than a failed call it can retry.

Notes

  • ask is a dry run. It shares production's retrieval, business context and model, but not the prompt-injection guard or the per-contact reply budget — those belong to the live ReplyComposer path.

  • upsert_business is idempotent by (owner, name), and upsert_knowledge by title. Both are safe for an AI caller that retries.

  • The Livewire create form still assembles its AI context inline. Until it is refactored onto BusinessProvisioningService, a change to the section list must be mirrored in resources/views/livewire/pages/businesses/create.blade.php.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables MCP clients to ask plain-language questions and receive answers grounded only in documents the configured role is cleared to read, with the same access-controlled tools available across any client.
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI assistants and agents to ask support questions, search knowledge articles, and list available articles from a configured support bot through MCP tools.
    6 npm
    MIT