Kagi MCP: the official Model Context Protocol server for Kagi Search
The Official Model Context Protocol (MCP) server for Kagi Search & other tools.
At a glance
- What is it?
- kagimcp is the official MCP server for the Kagi API, exposing two tools, a search tool covering web, news, video, podcast and image results with optional page extracts and Kagi lenses, and an extraction tool that returns a page as markdown. It runs locally over stdio, in streamable HTTP mode, or on Kagi's hosted server, and it is a small Python package built on FastMCP with a deliberately narrow tool surface.
- Who is it for?
- kagimcp fits anyone who wants an assistant to search and read pages through Kagi's index rather than a general web search, and it fits a team that wants the server to run as a shared multi-tenant HTTP service with per-request keys. It does not fit a user without a Kagi API key, since the key is the only credential the server has, and it does not fit a workflow that depends on the summarization and FastGPT tools that were removed and are only planned to return.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 108 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Two tools, and what the removal of the old ones tells you
kagimcp is an MCP server backed by the Kagi API, and it exposes search and extraction tools to MCP-compatible clients. The tool surface is deliberately small.
The first tool is `kagi_search_fetch`, covering web, news, videos, podcasts and image search, with optional page extracts, filters and Kagi lenses. The second is `kagi_extract`, which fetches a page's full content as markdown.
The split between them is the design decision worth noting. A search that returns a snippet and a separate tool that returns the whole page as markdown gives the model a cheap way to decide whether a full read is worth doing, and markdown rather than HTML is the right output format for a language model because it strips the navigation, the scripts and the layout that would otherwise eat the context window.
Then there is the note about what is gone. The previous `kagi_fastgpt` and `kagi_summarizer` tools have been removed, and both are planned to return in a future release. So at some point this server exposed a summarization tool, it was withdrawn, and it is coming back. If you are integrating against it, that is a change you need to plan for rather than discover, because a client that calls a tool which no longer exists gets an error at call time rather than a deprecation warning at connect time.
The removal also hints at the reasoning behind the current design. A summarizer tool inside the search server duplicates what a capable client model can do itself, and a tool that summarises for the model removes the model's ability to check the summary against the source. Keeping the tool set to search and extract keeps the model in charge of the reasoning.
The package is MIT licensed, the last push was on 2026-07-07, and the repository publishes no GitHub releases, though the package version in the project metadata is 1.0.2.
Three ways to run it, and how the credential travels
There are three deployment shapes, and the difference between them is mostly about who holds the API key.
The first is the hosted server at `https://mcp.kagi.com/mcp`, which needs no install. You point any HTTP-capable MCP client at it and authenticate with your Kagi API key. The example given for Claude Code is:
claude mcp add kagi https://mcp.kagi.com/mcp --transport http --header "Authorization: Bearer $(read -sp 'API key: ' k; echo $k)" --scope userNote how the key is handled there. The `read -sp` form prompts for the key with the input suppressed, and the command substitution pipes it into the Authorization header, so the key is not left in your shell history as a literal argument. It is still in the process argument list while the command runs, which is a smaller exposure than a history entry but not the same as passing it on standard input.
The second shape is local, over stdio, which is what the `uvx kagimcp` invocation in every local client configuration uses. The third is self-hosted HTTP, which the project describes as multi-tenant: each request supplies its API key via the `Authorization: Bearer <key>` header instead of a server-wide environment variable, so one instance can serve multiple users. That is the property that matters for a shared deployment, and it is why the hosted endpoint works without any per-user configuration on the server side.
The client configuration for Claude Desktop makes the local shape concrete, with the command as `uvx`, the args as `kagimcp`, and the key in the env block:
{
"mcpServers": {
"kagi": {
"command": "uvx",
"args": ["kagimcp"],
"env": {
"KAGI_API_KEY": "YOUR_API_KEY_HERE"
}
}
}
}Codex CLI takes the same idea on the command line, writing MCP configuration to `~/.codex/config.toml`:
codex mcp add kagi --env KAGI_API_KEY=<YOUR_API_KEY_HERE> -- uvx kagimcpClaude Code has its own form, and Smithery has a one-liner:
npx -y @smithery/cli install kagimcp --client claudeKiro uses the same `mcpServers` JSON as Claude Desktop, in `~/.kiro/settings/mcp.json` for global use or `.kiro/settings/mcp.json` for a project scope, and OpenCode has its own configuration shape with a `type` of local, a command array and an `enabled` flag.
One gap is worth naming. OAuth2 is not supported yet, it is on the roadmap, and for now the key has to be fetched from the Kagi dashboard and passed as Bearer authentication.
The environment variables, and hiding search parameters from the model
The configuration surface is a short list of environment variables, and one of them is unusual enough to deserve its own paragraph.
`KAGI_API_KEY` is the required Kagi API key. `FASTMCP_LOG_LEVEL` sets the logging level, for example `ERROR`. `KAGI_SEARCH_TIMEOUT` and `KAGI_EXTRACT_TIMEOUT` set the timeouts in seconds, defaulting to `10` and `30` respectively, which reflects the different cost of a search and a full page fetch. `KAGI_MAX_RETRIES` sets the maximum retry attempts after the first request, defaulting to `2`, and `0` disables retries entirely.
Then there is `KAGI_HIDDEN_PARAMS`, a comma-separated list of search params to hide from the LLM-facing schema. The hideable params are `workflow, extract_count, limit, include_domains, exclude_domains, time_relative, after, before, file_type, lens_id`.
This is the most thoughtful thing in the server, and it deserves an explanation because it is easy to miss. A search API has a lot of parameters, and every one of them that appears in the tool schema is a knob the model can turn, whether or not turning it is a good idea. `limit` and `extract_count` change how much context a call consumes, `include_domains` and `exclude_domains` change which sources are trusted, and `time_relative`, `after` and `before` change the date window in ways that can silently return nothing.
Hiding a parameter removes it from the schema the model sees, so the client can no longer pass it, while the server still accepts it. That gives you a way to fix the behaviour of the tool for a specific deployment without patching the code, and it is a way of saying that some of these knobs are for humans rather than for a model that is guessing.
The documented example is:
KAGI_HIDDEN_PARAMS="extract_count,after,before,time_relative,include_domains,exclude_domains"Hiding the date and domain parameters is the obvious starting point, because those are the ones that change what a search means rather than how much of it comes back.
Self-hosting the HTTP server and the version pin in the Dockerfile
The self-hosting instructions are the ones to read if you intend to run a shared instance, and the version pin in the container file is the detail that decides how often you have to redeploy.
The repository ships a Dockerfile that installs a pinned `kagimcp` from PyPI and runs it in HTTP mode, and the container respects `$PORT` so it works on any platform that injects one, with Railway, Render, Cloud Run and Fly.io named as examples. Building and running it locally is two commands:
docker build -t kagimcp-hosted .
docker run --rm -p 8000:8000 kagimcp-hostedThe smoke test that follows is a raw JSON-RPC call to the endpoint, which is worth looking at because it shows the protocol shape the server speaks:
curl -sL http://127.0.0.1:8000/mcp -X POST \
-H "authorization: Bearer $KAGI_API_KEY" \
-H "content-type: application/json" \
-H "accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'The accept header asking for both `application/json` and `text/event-stream` is the detail that trips people up when they write their own client. MCP over HTTP uses the streamable HTTP transport, where the server may answer with a single JSON response or with a server-sent event stream, and a client that only accepts one of the two will fail intermittently depending on how the server chooses to respond.
The Dockerfile itself is a python:3.12-slim base with the usual no-bytecode and no-cache environment settings, a working directory of /app, a `pip install kagimcp==1.0.0` line, an exposed port of 8000, and a command that starts the server in HTTP mode bound to all interfaces on that port.
Note the version mismatch worth flagging: the container pins 1.0.0 while the project metadata lists 1.0.2. The instruction for production is to bump the pin in the Dockerfile and redeploy, so the pinned version is a deliberate choice you make rather than an oversight, and it means the image does not pick up upstream fixes until you change it.
For local development, the checkout path is a clone, a sync and a run:
git clone https://github.com/kagisearch/kagimcp.git
cd kagimcp
uv syncKAGI_API_KEY=<YOUR_API_KEY_HERE> uv run kagimcpwith the HTTP variant adding the transport flag, a host and a port.
How the package is built, and how to inspect it
The packaging is small enough to read in one sitting, and it explains the runtime footprint.
The package name is `kagimcp`, the version is 1.0.2, and it requires Python exactly, with the constraint written as `==3.12.*`. That is a hard pin on a single minor series rather than a range, which is unusual for a library and reasonable for an application package that ships a container image.
The dependencies are fastmcp for the MCP server framework, pydantic for the data model, urllib3 for the HTTP client, python-dateutil for date handling, and typing-extensions. There is no HTTP framework of your own and no async client library, so the network layer is urllib3 with fastmcp handling the transport.
The build backend is hatchling, and the wheel packages two directories, `src/kagimcp` and `src/openapi_client`. The presence of an `openapi_client` package tells you the server generates a client from the Kagi API's OpenAPI description, which is a good way to keep up with an API that changes, and it explains why the wheel has two packages rather than one.
The console script is `kagimcp = "kagimcp:main"`, which is the entry point that `uvx kagimcp` invokes.
The debugging instructions use the official MCP inspector, which runs the server and gives you a UI to call tools and inspect their schemas. Against the published package it is one command:
npx @modelcontextprotocol/inspector uvx kagimcpand against a local checkout it points the inspector at the directory instead:
npx @modelcontextprotocol/inspector uv --directory /ABSOLUTE/PATH/TO/kagimcp run kagimcpThe inspector is usually available at `http://localhost:5173`. The distinction matters because the two commands test different things, the first the published package as a user would install it and the second your working copy, and the gap between those two is where version and dependency problems hide.
There is also a documented path for prerelease builds, which uses `uvx --prerelease allow --from kagimcp==1.0.0rc2 kagimcp` in place of the plain `uvx kagimcp` invocation, with the version swapped for whichever prerelease you want.
Where kagimcp is the wrong choice
The first limit is that a Kagi API key is the price of admission. The server has no other credential and no free tier of its own, so if you do not have a Kagi account with API access, none of this works. A general web search tool that your client can call for nothing is a different product, and for occasional lookups the convenience difference is large.
The second limit is the tool surface as it stands. Search and extract is enough for a model that can read and reason, and not enough for a model that expects a summariser or a FastGPT-style answer. Both were removed and both are planned to return, which means the current shape is not the final one, and a client integrating today may need a change later. Pin your version and check the changelog before upgrading.
The third is the authentication model. No OAuth2 yet, so the key travels as a Bearer token in every request. In a multi-tenant HTTP deployment that is workable, and it is the reason one instance can serve many users, but it means the key is in a request header on every call, and a client that logs headers logs keys.
The fourth is the dependency on Python 3.12 exactly, and on uv for the recommended install path. That is a low bar for a Python shop, but it does mean the tool does not fit a workstation pinned to an older interpreter, and the uvx-based client configurations assume uv is installed.
Compare that with the Kagi search API used directly through a plain HTTP client. The difference in approach is that this server is a thin, well-shaped adapter that lets an MCP client call Kagi without knowing anything about the API's parameters, filters or lenses, and it adds the schema-shaping and timeout and retry configuration that make an API usable by a model. What it cannot do is give you anything the API does not have, and it removes the option of writing your own request logic, which is sometimes what you want when the built-in search modes do not fit a particular question.
Editorial conclusion
kagimcp fits anyone who wants an assistant to search and read pages through Kagi's index rather than a general web search, and it fits a team that wants the server to run as a shared multi-tenant HTTP service with per-request keys. It does not fit a user without a Kagi API key, since the key is the only credential the server has, and it does not fit a workflow that depends on the summarization and FastGPT tools that were removed and are only planned to return. Before you configure it, decide between the hosted endpoint and a local process, set KAGI_API_KEY in the environment rather than inline in a shell history, and consider using KAGI_HIDDEN_PARAMS to trim the search parameters the model sees before you expose the tool to a client that will act on it.
Frequently asked questions
What tools does the Kagi MCP server expose?
Two. `kagi_search_fetch` covers web, news, videos, podcasts and image search with optional page extracts, filters and Kagi lenses, and `kagi_extract` fetches a page's full content as markdown. The earlier `kagi_fastgpt` and `kagi_summarizer` tools have been removed and are planned to return in a future release.
How do I run kagimcp with Claude Desktop?
Install uv first, then add the server to your Claude Desktop config using the command `uvx` with the args `kagimcp` and the `KAGI_API_KEY` set in the env block of the `mcpServers` entry. The config file is reached through Settings, then Developer, then Edit Config.
Can I use the hosted Kagi MCP server instead of installing anything?
Yes. A hosted server runs at https://mcp.kagi.com/mcp, and you point any HTTP-capable MCP client at it and authenticate with your Kagi API key as a Bearer token. OAuth2 is not supported yet, so you get the key from the Kagi dashboard and pass it via HTTP authentication.
What does KAGI_HIDDEN_PARAMS do?
It takes a comma-separated list of search parameters to hide from the LLM-facing schema, so the model cannot set them. The hideable params are workflow, extract_count, limit, include_domains, exclude_domains, time_relative, after, before, file_type and lens_id.
How do I self-host the kagimcp HTTP server?
The repository ships a Dockerfile that installs a pinned kagimcp from PyPI and runs it in HTTP mode, and the container respects `$PORT`. You can build and run it with `docker build -t kagimcp-hosted .` and `docker run --rm -p 8000:8000 kagimcp-hosted`, and to bump the version in production you edit the pin in the Dockerfile and redeploy.
What licence is kagimcp released under?
The project is released under the MIT licence, with the licence text in the LICENSE file at the repository root. The package version in the project metadata is 1.0.2, the repository publishes no GitHub releases, and the last push was on 2026-07-07.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/kagisearch-kagimcp)Was this useful?