MCP server
Connect Claude Code, Cursor or any MCP client to your published FAQ. Read-only, scoped to one organization by your API key.
Updated 2026-10-11
Every organization has a Model Context Protocol endpoint. An AI assistant connected to it can search your FAQ, read it as markdown and answer questions from it. It only reads: there is no tool that creates, edits or deletes content.
https://api.thefaq.app/api/v1/{organizationSlug}/mcp
The endpoint speaks Streamable HTTP, protocol version 2025-06-18 (2025-03-26 and 2024-11-05 are also accepted). Each request is one JSON-RPC message sent with POST, and each response is plain JSON. There is no server-sent event stream, so GET returns 405.
Which key to use
Send your API key as Authorization: Bearer <key>. The key decides which organization the assistant sees and what it may do. A key from another organization is refused when the client connects.
- A publishable key (
publicscope) is enough forsearch_faqsandlist_faqs. Use it unless you needanswer_question. answer_questionneeds a key with thereadscope. That is a server key: anyone holding it can read your drafts through the REST API, so keep it out of shared configs and repositories.
The MCP tools themselves return published content only, whichever key you use. Create keys under API Keys in the dashboard.
Connect a client
Claude Code
claude mcp add --transport http thefaq https://api.thefaq.app/api/v1/acme/mcp \
--header "Authorization: Bearer $VITE_FAQAPP_PUBLISHABLE_KEY"
Cursor
Open Cursor Settings → MCP → Add new MCP server, or add this to Cursor’s global or project mcp.json:
{
"mcpServers": {
"thefaq": {
"url": "https://api.thefaq.app/api/v1/acme/mcp",
"headers": { "Authorization": "Bearer <your publishable key>" }
}
}
}
VS Code
Add to .vscode/mcp.json:
{
"servers": {
"thefaq": {
"type": "http",
"url": "https://api.thefaq.app/api/v1/acme/mcp",
"headers": { "Authorization": "Bearer <your publishable key>" }
}
}
}
Replace acme with your organization slug.
Tools
| Tool | Arguments | Same as |
|---|---|---|
search_faqs |
query (1–500 characters), optional limit (1–100), offset, lang, category |
GET /api/v1/{organizationSlug}/search |
list_faqs |
optional lang, category, limit (1–200) |
GET /api/v1/{organizationSlug}/faqs?format=markdown |
answer_question |
question (1–2000 characters), optional lang |
POST /api/v1/{organizationSlug}/answers |
answer_question returns status: "answered" with the answer and its source, or status: "not_covered" when nothing published answers the question. An assistant should never present not_covered as an answer.
Arguments the schema does not list are refused before anything is read. tools/list returns the exact JSON Schema of each tool.
Limits and errors
Each tool call counts as one request to the REST endpoint it mirrors: the same per-key rate limit and the same monthly request quota. Connecting, listing tools and ping are not counted. See Rate limits.
When the API refuses a call, the tool result has isError: true and its structuredContent carries the API error code, for example forbidden, validation_error or rate_limit_exceeded. A rate-limited result also includes details.retryAfterSeconds. See Errors.
Try it with curl
curl https://api.thefaq.app/api/v1/acme/mcp \
-H "Authorization: Bearer $VITE_FAQAPP_PUBLISHABLE_KEY" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_faqs","arguments":{"query":"refunds"}}}'