Community Edition

Looking for the SWIRL Enterprise MCP setup? The Enterprise MCP server has a different feature set and deployment model. See the MCP Server (Enterprise) guide.

MCP Server for SWIRL Community

swirl-mcp-server is the official open-source Model Context Protocol server for SWIRL Community Edition. It exposes SWIRL's federated search and RAG capabilities as MCP tools, so Claude Desktop, Claude Code, Cursor, and any other MCP-compatible client can answer questions against your private data sources — SharePoint, Confluence, GitHub, Jira, Elastic, BigQuery, Snowflake, MongoDB, Microsoft 365, and 100+ more — without moving any data.

Overview

The server is a thin async adapter over SWIRL's existing REST API. No changes to your SWIRL deployment are required — install the MCP server alongside an existing SWIRL instance and the relationship is one-directional REST.

  • Search where your data lives. SWIRL queries each connector in parallel, federates the results, and re-ranks them with cosine relevancy — no vector DB, no ETL, no data movement.
  • One tool call, one answer. search(query="...", rag=true) returns a generated answer with citations. The model never has to orchestrate per-source plumbing.
  • Permission-aware. SWIRL enforces per-user ACLs on every search and result. The MCP server forwards the user's credentials and never widens that scope.
  • Drop-in. Works with any current SWIRL Community 4.x deployment.

System Requirements

ComponentTested versions
Python3.10, 3.11, 3.12
SWIRL Community Edition4.x (against main of swirlai/swirl-search)
MCP Python SDK1.x
OSmacOS, Linux, Windows (WSL2)

For RAG (rag=true): SWIRL itself needs an OpenAI or Azure OpenAI key. Paste it into the matching AIProvider record at /admin/swirl/aiprovider/ — see Enabling RAG below. The MCP server itself never sees the key. Plain search works without one.

Installation

Until swirl-mcp-server v0.1 lands on PyPI, install from GitHub:

pipx install git+https://github.com/swirlai/swirl-mcp-server

That puts the swirl-mcp executable on your PATH. (Don't have pipx? python -m pip install --user pipx && pipx ensurepath.)

Once on PyPI, the zero-install one-liner will be uvx swirl-mcp-server.

Enabling RAG

RAG calls (the rag_answer tool, or search with rag=true) route through a SWIRL AIProvider record. SWIRL Community ships with OpenAI and Azure/OpenAI AIProvider records preloaded — you only need to drop your API key into the matching record.

  1. Open the Administration Console at http://localhost:8000/admin/swirl/aiprovider/ and sign in.
  2. You'll see the preloaded AIProvider records:

SWIRL Admin Console showing the AIProvider list with preloaded OpenAI and Azure/OpenAI records

  1. Click the AIProvider you want to use (OpenAI for most setups, Azure/OpenAI if you're routing through Azure), paste your API key into the api_key field, and save.

SWIRL Admin Console AIProvider edit form, showing the api_key field where the OpenAI or Azure OpenAI key is pasted

RAG calls succeed immediately — no SWIRL restart needed. To change models, route through Azure, or use a different OpenAI-compatible endpoint, edit the same record. See the RAG Guide for the full set of AIProvider options.

Configuration

Environment variables

All settings come from environment variables (prefixed SWIRL_). A .env file in the working directory is auto-loaded.

VariableRequiredDefaultNotes
SWIRL_BASE_URLyeshttp://localhost:8000Your SWIRL instance root.
SWIRL_USERNAMEyesBasic auth user.
SWIRL_PASSWORDyesBasic auth password.
SWIRL_VERIFY_SSLnotrueSet to false for self-signed certs.
SWIRL_TIMEOUT_SECONDSno30HTTP timeout for normal calls.
SWIRL_RAG_TIMEOUT_SECONDSno60Separate, larger timeout for the RAG endpoint.
SWIRL_MAX_RESULTSno50Upper bound on result_count (caps LLM token cost).
SWIRL_DEFAULT_PROVIDERSnoComma-separated provider ids/names/tags applied when a caller omits providers.

Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "swirl": {
      "command": "swirl-mcp",
      "env": {
        "SWIRL_BASE_URL": "http://localhost:8000",
        "SWIRL_USERNAME": "<your-swirl-username>",
        "SWIRL_PASSWORD": "<your-swirl-password>"
      }
    }
  }
}

Restart Claude Desktop. You should see swirl in the tools menu.

Claude Code

claude mcp add swirl swirl-mcp \
  -e SWIRL_BASE_URL=http://localhost:8000 \
  -e SWIRL_USERNAME=<your-swirl-username> \
  -e SWIRL_PASSWORD=<your-swirl-password>

Cursor and other MCP clients

See the examples/ directory in the GitHub repo for ready-to-paste configurations.

Tools

The server exposes six tools. search is the one you'll use most often; the rest are escape hatches for async, discovery, and reuse.

ToolPurposeSWIRL backend
searchOne-shot federated search. Set rag=true for a generated answer with citations.GET /api/swirl/search/?qs=…
create_searchKick off a search asynchronously and get back a search_id.POST /api/swirl/search/
get_resultsFetch (or re-mix) results for an existing search_id. Returns not_ready while running.GET /api/swirl/results/?search_id=…
rag_answerGenerate a RAG answer over an existing search's results.GET /api/swirl/sapi/detail-search-rag/
list_providersList the user's configured SearchProviders (credentials stripped).GET /api/swirl/searchproviders/
list_searchesList the user's recent searches.GET /api/swirl/search/

search — the headline tool

One call covers the 90% case. Input:

{
  "query": "what's new in RAG?",
  "providers": ["arxiv", "europe_pmc"],
  "result_count": 10,
  "rag": true,
  "explain": false
}

Output (trimmed for brevity):

{
  "structured": {
    "search_id": 42,
    "query": "what's new in RAG?",
    "answer": "Recent work on retrieval-augmented generation…",
    "results": [
      {
        "title": "GraphRAG: …",
        "snippet": "We introduce…",
        "url": "https://arxiv.org/abs/…",
        "source": "Arxiv",
        "relevancy_score": 0.91,
        "date_published": "2025-04-01"
      }
    ]
  },
  "markdown": "## Answer\n…\n## Sources\n1. [GraphRAG: …](https://…) — _Arxiv · score 0.91_\n   > We introduce…"
}

The dual structured + markdown shape is deliberate: clients that render rich content show the markdown; clients that pass tool output back to the model verbatim get the leaner structured form.

Resources and prompts

  • swirl://providers (resource) — JSON catalog of active SearchProviders. Useful as pinned context in clients that support resource pinning.
  • swirl_research(question) (prompt) — a reusable prompt template that instructs the model to call search with rag=true and cite every source.

Authentication

The server picks the right authentication method per SWIRL path:

  • Basic auth for /api/swirl/search/, /api/swirl/results/, /api/swirl/searchproviders/, etc.
  • DRF token for any path under /api/swirl/sapi/ (which includes the RAG endpoint). SWIRL's TokenMiddleware gates these endpoints behind a DRF Token, not Basic auth.

On the first call to a /sapi/ path, the server POSTs to /swirl/login/ with the configured username and password to obtain a token, then caches it for the lifetime of the process. You don't have to manage tokens yourself — but knowing the model helps when debugging HTTP traffic.

Credentials are never logged or returned in tool output. list_providers deliberately strips credentials, url, and query_template from its response.

Troubleshooting

SymptomCauseFix
rag_answer returns "check the OpenAI or Azure/OpenAI credentials in your environment"The active AIProvider in SWIRL has no API key setPaste your key into the AIProvider record at /admin/swirl/aiprovider/ (see Enabling RAG). The MCP server itself never sees the key — SWIRL does.
SWIRL denied access. The user lacks permission for this operation. on rag_answer or search(rag=true)Running an older build that used Basic auth for /sapi/ endpointsUpgrade to v0.1+; the client now obtains a DRF token automatically.
command not found: swirl-mcp after installpipx's bin dir isn't on PATHpipx ensurepath, then restart your shell or your MCP client.
Connection refused / timeoutsSWIRL isn't running, or SWIRL_BASE_URL points somewhere elsecurl http://localhost:8000/ should return a 302 redirect. If not, docker compose up first.
get_results returns {"status": "not_ready"}Search is still being mixed by SWIRLNot an error — wait ~1s and call again. The model can loop on this.
TLS errors against a self-signed SWIRL certDefault is to verify TLSSet SWIRL_VERIFY_SSL=false in the env block. Only do this for trusted internal hosts.

See it in action

The rag_answer tool running against a local SWIRL via the MCP Inspector — a federated query answered with sources, ready to be piped into any MCP client:

SWIRL MCP Server — rag_answer tool returning a federated search RAG answer in the MCP Inspector

See also