Skip to content

The Nexafon MCP server (@nexafon/mcp) lets an AI coding agent read these docs and the example apps while it writes your integration, and, with a test secret key, send a test message and look at your webhook deliveries and recent errors. It speaks the Model Context Protocol over stdio, so it works in Claude Code and any other MCP client that starts local servers.

It pairs with the Nexafon agent skill, which teaches the agent the integration steps and rules, and the CLI, which scaffolds the integration and checks it with nexafon doctor.

Tool Needs What it does
search_docs(query, limit?) Searches these docs; each result has the page title, its URL and a snippet
get_page(path) Returns a page as Markdown, the same text as its .md twin (/v1/quickstart/ or /v1/quickstart.md)
get_example(name, file?) Lists the files of an example app (react, next, partner, …) with its README, or returns one file
send_test_message(to, text) test key Sends a text to a customer through sendMessage in test mode
list_webhook_deliveries(limit?, endpointId?, status?) test key The latest delivery attempts across your webhook endpoints, the newest first
recent_errors(limit?) test key Failed webhook deliveries, failing or turned-off endpoints, and outbound messages WhatsApp did not accept

The docs and the examples are bundled into the package when it is built, so the first three tools work offline and match the version you installed. Links in their answers point at NEXAFON_DOCS_URL.

  • There is no separate test-send operation. send_test_message calls the documented send-message operation with your test key, so test mode applies: a real WhatsApp number answers test_mode_live unless the workspace has a WhatsApp test number. The customer must have written within the last 24 hours; a new conversation starts with a template.
  • recent_errors reports what the public API exposes. The API keeps no log of failed requests: those come back to your own code as Problem Details.
  • get_example serves only the files committed under examples/<name>, and never a .env file (the .env.example templates are included).

The server reads its settings from its environment:

Variable
NEXAFON_DOCS_URL Required. The docs site, https://docs.nexafone.so, for the links in results
NEXAFON_API_URL The API, https://api.nexafone.so; needed by the test-key tools. https, or http only to localhost, 127.0.0.1 or a *.localhost name, since the key is sent there. Against a local Nexafon stack use its API_URL unchanged: the server sends *.localhost names to 127.0.0.1 itself (macOS does not resolve them for Node), with the Host header the stack routes by
NEXAFON_SECRET_KEY A test secret key (sk_test_…) with the inbox:reply and developers:manage scopes; needed by the test-key tools
NEXAFON_WORKSPACE_ID The key’s workspace id: the {workspaceId} in API paths, also sent as workspaceId in every webhook delivery
NEXAFON_APP_URL, NEXAFON_EMBED_CDN_URL Optional: fill in the dashboard and SDK loader URLs in the pages the server returns

@nexafon/mcp is not on npm yet, so npx -y @nexafon/[email protected] fails for now. Until it is published, build it in a checkout of the repo (pnpm install, then pnpm --filter @nexafon/mcp build) and start it with node. Add the server to a project, so everyone working on it gets the tools, with the key and workspace id read from each developer’s own environment:

Terminal window
claude mcp add nexafon --scope project \
--env NEXAFON_DOCS_URL=https://docs.nexafone.so \
--env NEXAFON_API_URL=https://api.nexafone.so \
--env 'NEXAFON_WORKSPACE_ID=${NEXAFON_WORKSPACE_ID:-}' \
--env 'NEXAFON_SECRET_KEY=${NEXAFON_SECRET_KEY:-}' \
-- node /path/to/nexafon/mcp/dist/bin.js

That writes .mcp.json at the project root. Claude Code fills in ${…} from the environment it starts in; a variable that is not set becomes empty (:-), which leaves the test-key tools off and the docs tools working:

{
"mcpServers": {
"nexafon": {
"command": "node",
"args": ["/path/to/nexafon/mcp/dist/bin.js"],
"env": {
"NEXAFON_DOCS_URL": "https://docs.nexafone.so",
"NEXAFON_API_URL": "https://api.nexafone.so",
"NEXAFON_WORKSPACE_ID": "${NEXAFON_WORKSPACE_ID:-}",
"NEXAFON_SECRET_KEY": "${NEXAFON_SECRET_KEY:-}"
}
}
}
}

After the release, replace node /path/to/nexafon/mcp/dist/bin.js with npx -y @nexafon/[email protected] (in the JSON, "command": "npx" and "args": ["-y", "@nexafon/[email protected]"]). Run /mcp in Claude Code to see the server and its tools.

Any client that starts stdio servers runs it the same way: the command node /path/to/nexafon/mcp/dist/bin.js (after the release, npx -y @nexafon/[email protected]) with the variables above in its environment. Cursor reads the same mcpServers object from .cursor/mcp.json, and Claude Desktop from its claude_desktop_config.json. Where a client cannot read a variable from your environment, put the test key in its user-level config, never in a file you commit.