IndexMachine MCP server
Official# IndexMachine MCP server
Check your own sites' pages on Google and request indexing, plus IndexNow, from your AI assistant.
This MCP server lets Claude Code, Cursor, VS Code, Claude Desktop and claude.ai work with the sites you
connected to [IndexMachine](https://indexmachine.co): list your sites and pages, check whether a URL is
on Google, queue a Request indexing click (also a re-index of a page that is already indexed) and notify
Bing and the other IndexNow engines. It calls the IndexMachine API with your key and does nothing the
API does not.
## How a request really travels
IndexMachine uses Request indexing in your own Google Search Console and IndexNow, no link farms. So a
request is not instant, and the server says so every time:
1. `request_indexing` queues the click. It does not reach Google by itself.
2. The IndexMachine Chrome extension, in your Chrome and signed in to the Google account that owns the
property, picks the request up when it next checks in: about every 5 minutes on extension 1.2.0 or
newer, every 30 minutes on older versions. Chrome has to be running. When the extension has not
checked in for 40 minutes there is no ETA, and the request waits in the queue.
3. The extension clicks **Request indexing** in your Search Console, the same button you would press.
4. Google takes about 10 of these requests per site per day, a day that resets at midnight Pacific. The
number is observed; Google does not publish it. Requests you queue go ahead of the extension's daily
work on your other pages and share the same 10. Once a site's day is used up, the ETA moves past
midnight Pacific.
5. Google then decides whether and when it indexes the page, often days later. The ETA is for the click,
never for indexing, and only `check_url` says a page is indexed.
A re-index of a page that is already on Google (`force: true`) needs extension 1.2.0 or newer. IndexNow
tells Bing, Yandex and the other IndexNow engines directly; it needs the site's IndexNow key file in place,
takes 20 submissions per site a day and does not reach Google.
## What you need
- An IndexMachine account with your sites connected: [app.indexmachine.co](https://app.indexmachine.co/sign-up).
Signing up is free and shows which of your pages Google has not indexed. Requesting indexing needs a
paid plan for the site ([pricing](https://indexmachine.co/pricing)).
- The IndexMachine Chrome extension, installed and signed in, for the Request indexing clicks.
- An API key (with claude.ai you can add it as a request header, see [Remote server](#remote-server)).
### Create an API key
1. Open the IndexMachine dashboard and choose **Settings** from your profile menu, or go straight to
[app.indexmachine.co/settings](https://app.indexmachine.co/settings).
2. Under **API keys** press **Create key** and give it a label, such as `Claude Code`.
3. Pick **Full** (it also queues and cancels requests and submits to IndexNow) or **Read only** (sites,
pages, checks and requests).
4. Copy the key. It starts with `im_live_` and is shown only once.
Roll or revoke a key on the same page at any time; an account holds up to 10 active keys.
## Install
The package runs on your machine with `npx` (Node.js 20 or newer). Keep the key in your user-level
config, never in a file that lives in a repository.
**Claude Code** (user scope, so the key stays out of the project's `.mcp.json`)
```sh
claude mcp add --scope user indexmachine --env INDEXMACHINE_API_KEY=im_live_... -- npx -y indexmachine-mcp
```
**Cursor** (`~/.cursor/mcp.json`, the user-level file)
```json
{
"mcpServers": {
"indexmachine": {
"command": "npx",
"args": ["-y", "indexmachine-mcp"],
"env": { "INDEXMACHINE_API_KEY": "im_live_..." }
}
}
}
```
**VS Code** (`.vscode/mcp.json`): VS Code asks for the key and keeps it out of the file.
```json
{
"inputs": [
{ "type": "promptString", "id": "indexmachine-key", "description": "IndexMachine API key", "password": true }
],
"servers": {
"indexmachine": {
"type": "stdio",
"command": "npx",
"args": ["-y", "indexmachine-mcp"],
"env": { "INDEXMACHINE_API_KEY": "${input:indexmachine-key}" }
}
}
}
```
**Claude Desktop** (`claude_desktop_config.json`): the same block as Cursor, under `mcpServers`.
**Other MCP clients**: run `npx -y indexmachine-mcp` with `INDEXMACHINE_API_KEY` in its environment, or
use the remote server below.
## Remote server
The remote server at `https://mcp.indexmachine.co/mcp` needs no install. Clients send the API key in a
header:
```
URL: https://mcp.indexmachine.co/mcp
Header: Authorization: Bearer <your key> (X-API-Key: <your key> works too)
```
**Claude Code**
```sh
claude mcp add --transport http indexmachine https://mcp.indexmachine.co/mcp \
--header "Authorization: Bearer $INDEXMACHINE_API_KEY"
```
**Cursor** (`~/.cursor/mcp.json`)
```json
{
"mcpServers": {
"indexmachine": {
"url": "https://mcp.indexmachine.co/mcp",
"headers": { "Authorization": "Bearer im_live_..." }
}
}
}
```
**VS Code** (`.vscode/mcp.json`)
```json
{
"inputs": [
{ "type": "promptString", "id": "indexmachine-key", "description": "IndexMachine API key", "password": true }
],
"servers": {
"indexmachine": {
"type": "http",
"url": "https://mcp.indexmachine.co/mcp",
"headers": { "Authorization": "Bearer ${input:indexmachine-key}" }
}
}
}
```
### claude.ai: a custom connector
1. In claude.ai, open **Customize > Connectors**, press **+ Add**, then **Add custom connector**.
2. Enter the name `IndexMachine` and the URL `https://mcp.indexmachine.co/mcp`.
3. Under **Request headers** add `Authorization` with the value `Bearer im_live_...`, then press **Add**.
4. In a chat, open **+**, then **Connectors**, and switch IndexMachine on.
IndexMachine and the Submitator connector can be on in the same chat: no tool name is shared.
Signing in with your IndexMachine account instead of a key (OAuth) is built into this server and stays off
until IndexMachine's API issues sign-in tokens. Until then the server advertises no sign-in, and every
client sends a key.
The remote server keeps nothing between requests: it passes the key on to the IndexMachine API and
forgets it.
## Tools
| Tool | What it does |
|---|---|
| `account_status` | Your plan, the key's permissions and hourly budget, whether the Chrome extension is online, and today's requests per site against Google's daily quota |
| `list_sites` | Your connected Search Console properties with page counts, whether Google indexing is on, whether a paid plan covers them and whether IndexNow is ready |
| `site_summary` | One site: today's Request indexing quota, the median days from a first request to indexing, and 30 days of counts |
| `list_pages` | A site's pages by status (`indexed`, `not_indexed`, `awaiting`, `requested`, `rejected`, `needs_fix`, `excluded`, `not_found`) or part of the URL, 50 at most per call |
| `check_url` | Whether a URL is indexed, and as of when, or that it is not known yet (never inspected); `live: true` asks Google now and uses 1 of 50 live checks per site a day |
| `request_indexing` | Queues a Request indexing click, also for a URL that is not a page of the site yet, and with `force: true` a re-index of an indexed page. Answers the queue position and an honest ETA |
| `get_indexing_request`, `list_indexing_requests` | Follow requests: open ones with their position and ETA, closed ones with what Search Console answered |
| `cancel_indexing_request` | Takes an open request out of the queue |
| `submit_indexnow` | Notifies Bing, Yandex and the other IndexNow engines of up to 100 URLs of one site |
Prompt: `index_url` checks a URL, queues a request when it is not indexed, and reports the ETA as it is.
## Keys and safety
- `request_indexing` previews before it queues. It asks you before a re-index of a page that is already
on Google, a URL that is not in your sitemap, or your site's last request of the day; declining queues
nothing. Clients that can ask their user (MCP elicitation) show the question themselves, and your answer
never passes through the model; a question that gets no answer queues nothing either. Clients that
cannot ask, and on the remote server clients on an MCP protocol before 2026-07-28, get a refusal first,
with the reasons and a `confirm` token: an HMAC under your API key that fits only that request, on that
day, while your site's quota stays as it was. The model cannot make one up, so a call always takes the
refusal first. Whether your assistant then shows you the reasons before it sends the token back is up
to the assistant and to your client's approval of tool calls; the server cannot see it.
`submit_indexnow` does the same above 10 URLs, with a token for those URLs on that Pacific day.
- `cancel_indexing_request` is marked destructive (`destructiveHint: true`), and no other tool is: it undoes a
request. The tools that only read are marked read-only, so clients can run them without asking.
- The `npx` package reads the key from its environment and sends it only to `https://api.indexmachine.co`.
`INDEXMACHINE_API_URL` may point it to a local development server, and nowhere else.
- A read-only key fits an assistant that only checks: sites, pages, URL checks and requests.
- Every call carries a request id that starts with `mcp-`. Revoke a key on the Settings page at any time.
- Report a vulnerability by email to vlad@indexmachine.co, not in a public issue
([SECURITY.md](https://github.com/indexmachine/indexmachine-mcp/blob/main/SECURITY.md)).
## Development
```sh
npm install
npm test # unit, contract and protocol tests (it builds dist/ first)
npm run build
npm run sync:openapi # refresh openapi/v1.json and src/v1.d.ts from https://api.indexmachine.co/v1/openapi.json
npm run check:pack # pack, install in an empty folder, run the stdio handshake
npm run release:check # what a release needs, then the publishing commands
```
`openapi/v1.json` is the `/v1` contract, and the API serves the same document at `/v1/openapi.json`. When
the API ships a new release, `npm run sync:openapi` and `npm test` show which new operations need a tool or
a line in `EXCLUDED` (`src/tools/index.ts`).
The remote server deploys to Vercel (`vercel.json`, `api/`) under the domain `mcp.indexmachine.co`.
OAuth turns on with `MCP_OAUTH=1` and `MCP_OAUTH_KEYS`, the keys IndexMachine's API encrypts its access
tokens with.
## License
MIT
TDQS
Scored across 10 tools
Most tools are clearly separated by resource and action: list_sites vs. site_summary differ in overview vs. detail, and list_pages vs. check_url differ in bulk page status vs. single-URL inspection. The overlap is manageable, but an agent could initially hesitate between the site-level and page-level read tools.
All names use consistent snake_case and are generally readable. The pattern is mostly verb_noun, but site_summary and account_status are noun phrases rather than action-first names, a minor deviation.
Ten tools is well-scoped for an indexing-management server. Each tool earns its place by covering a distinct part of the site, page, indexing-request, and IndexNow workflow.
The surface covers the core lifecycle: listing sites and pages, checking index status, requesting and canceling indexing, viewing request details, and submitting to IndexNow. Minor gaps include no tools for adding/removing sites or managing sitemaps/IndexNow key setup, but the main agent workflows are supported.