Impiseo MCP Server
Expose all of Impiseo’s organic-search data — Search Console metrics, crawled page content, content ideas and AI recommendations — to any AI agent over the Model Context Protocol. Read-only and authenticated with your personal API key.
How it works
- The server connects directly to your database and Google Search Console — it does not need the dashboard up.
- Every tool call is authorized with your
imp_…personal API key. - It is strictly read-only: the AI can see and analyze everything but cannot change or delete data.
- It runs standalone at
http://localhost:3777/mcpby default.
Response format
Every tool returns the same stable envelope, so you never need to sniff the shape of a response. Success carries ok: true plus the tool’s payload; failures carry ok: false and a human-readable error. The real object is delivered in structuredContent (no JSON-in-JSON); content[0].text holds a pretty-printed copy for debugging.
{ "ok": true, "activeProperty": "sc-domain:example.com", "count": 3, "queries": [ … ] }
{ "ok": false, "error": "Invalid params: …" }1. Get a personal API key
Create and revoke keys from the dashboard under Dashboard → API Keys, or mint one from the server directly. Keys resolve to your own data only:
# from the dashboard: Dashboard → API Keys → Create API key # key: imp_ab12cd_XYZabc123 (shown once, stored hashed) # or from the impiseo-mcp repo: pnpm tsx src/keygen.ts "you@example.com" "my-agent" # hand that key to any MCP client as the Authorization: Bearer token
2. Run the server
Clone impiseo-mcp, set three env vars, start:
# .env MONGO_URI=mongodb+srv://… # same cluster the app uses GOOGLE_CLIENT_ID=…apps.googleusercontent.com # same creds the app was authorized with GOOGLE_CLIENT_SECRET=… pnpm install pnpm dev # listens on http://localhost:3777/mcp
The Google client id/secret are only used to refresh the access token for live Search Console queries. Everything else is read from the database.
3. Connect your client
Add it as a Streamable HTTP MCP server with a bearer token header:
# Claude Desktop / claude code: ~/.claude.json → mcpServers
"impiseo": {
"type": "http",
"url": "http://localhost:3777/mcp",
"headers": { "Authorization": "Bearer imp_ab12cd_XYZabc123" }
}# raw HTTP (Streamable HTTP protocol)
curl -N -X POST http://localhost:3777/mcp \
-H "Authorization: Bearer imp_ab12cd_XYZabc123" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'4. Tools
All parameters are optional unless marked Required. Without a site, each tool uses your active property.
get_profile
read-onlyAccount identity, plan context, connected properties and the active Search Console property.
returns { ok, userId, email, onboarded, product, properties[], activeProperty, createdAt }
No parameters — reads your active property.
list_sites
read-onlyAll Search Console properties on the account with permission level, plus the active one.
returns { ok, activeProperty, properties: [{ url, permissionLevel, addedAt }] }
No parameters — reads your active property.
get_overview
read-onlyDashboard-style totals, previous-period totals, daily series, top 25 queries and top 25 pages.
returns { ok, range: { start, end, prevStart, prevEnd }, totals, prevTotals, series: [{ date, clicks, impressions }], queries[], pages[] }
| param | type | description |
|---|---|---|
| site | string | GSC property URL. Defaults to active property. |
| days | number | Window in days, 1–90 (default 28). |
get_queries
read-onlyTop organic queries sorted by clicks, with impressions, CTR and position.
returns { ok, site, range, offset, limit, count, queries: [{ key, clicks, impressions, ctr, position }] }
| param | type | description |
|---|---|---|
| site | string | GSC property URL. Defaults to active property. |
| days | number | Window in days, 1–90 (default 28). |
| offset | number | Row offset for paging, 0–25000 (default 0). |
| limit | number | Max rows, 1–300 (default 100). |
get_pages
read-onlyTop organic pages sorted by clicks, joined with each page's crawled title, meta description and word count when available.
returns { ok, site, range, offset, limit, count, pages: [{ path, clicks, impressions, ctr, position, title, metaDescription, wordCount, httpStatus }] }
| param | type | description |
|---|---|---|
| site | string | GSC property URL. Defaults to active property. |
| days | number | Window in days, 1–90 (default 28). |
| offset | number | Row offset for paging, 0–25000 (default 0). |
| limit | number | Max rows, 1–300 (default 100). |
get_page_queries
read-onlyThe queries sending traffic to one page — live from Search Console.
returns { ok, page, normalizedPath, count, queries: [{ page, query, clicks, impressions, ctr, position }] }
| param | type | description |
|---|---|---|
| site | string | GSC property URL. Defaults to active property. |
| page | string | Required. The page path (e.g. /blog/post-1). |
| days | number | Window in days, 1–90 (default 28). |
| limit | number | Max rows, 1–300 (default 50). |
get_query_pages
read-onlyWhich pages rank for one query — live from Search Console.
returns { ok, query, count, pages: [{ query, page, clicks, impressions, ctr, position }] }
| param | type | description |
|---|---|---|
| site | string | GSC property URL. Defaults to active property. |
| query | string | Required. The exact query to filter by. |
| days | number | Window in days, 1–90 (default 28). |
| limit | number | Max rows, 1–100 (default 20). |
get_query_opportunities
read-onlyRuns the opportunities math across every query: the best-ranking page, the words that page misses vs the query, projected clicks at top 3 and top 1, clicks left on the table (headroom), intent, cluster, and a deterministic fixing suggestion. Live GSC + stored crawl content; paged with offset + limit.
returns { ok, site, range, offset, limit, count, total, queries: [{ query, clicks, impressions, ctr, position, intent, topPagePath, pageTitle, matchScore, missingTerms[], clusterId, clusterTopic, clusterSize, projectedTop3, headroomTop3, projectedTop1, headroomTop1, fixing }] }
| param | type | description |
|---|---|---|
| site | string | GSC property URL. Defaults to active property. |
| days | number | Window in days, 1–90 (default 28). |
| offset | number | Row offset for paging, 0–25000 (default 0). |
| limit | number | Max rows, 1–500 (default 100). |
| minImpressions | number | Only queries with at least this many impressions (default 0 = all). |
| queryContains | string | Only queries containing this substring (case-insensitive). |
| excludeBranded | boolean | Drop queries containing the brand token (default true). |
get_ideas
read-onlyLatest content-ideas run (gap, striking-distance, intent-mismatch, winner-expansion, new-topic) with stats and every idea's summary.
returns { ok, hasRun, generatedAt, stats: { queriesAnalyzed, ideasReturned, … }, ideas: [{ id, type, topic, queriesCount, impressions90d, … }] }
| param | type | description |
|---|---|---|
| site | string | GSC property URL. Defaults to active property. |
get_idea_detail
read-onlyFull detail for one idea: evidence, top queries, covering pages, autocomplete phrasings, AI angle and outline.
returns { ok, found, idea: { id, type, topic, evidence, angle?, outline? } }
| param | type | description |
|---|---|---|
| site | string | GSC property URL. Defaults to active property. |
| ideaId | string | Required. The idea id from get_ideas. |
list_idea_runs
read-onlyHistory of idea-generation runs with their stats (without the full idea payload).
returns { ok, count, runs: [{ userId, siteUrl, generatedAt, stats }] }
| param | type | description |
|---|---|---|
| site | string | GSC property URL. Defaults to active property. |
get_recommendations
read-onlyRunnable recs engine output: meta/title/thin-content/striking-distance fixes with impact scores. Grouped recs include per-page evidence — each affected path with its title, meta description and word count.
returns { ok, count, recommendations: [{ id, type, severity, path, title, detail, action, impact, paths?: [{ path, impressions, title, metaDescription, wordCount }] }] }
| param | type | description |
|---|---|---|
| site | string | GSC property URL. Defaults to active property. |
get_rec_enhancements
read-onlyStored AI fix plans for recommendations: why, steps, draft title/meta, agent prompt.
returns { ok, count, enhancements: [{ recId, fingerprint, why, steps[], draftTitle, draftMeta, agentPrompt }] }
| param | type | description |
|---|---|---|
| site | string | GSC property URL. Defaults to active property. |
| recId | string | Optional. A specific rec id to fetch, e.g. /blog/post::missing-meta. |
get_page_content
read-onlyCrawled on-page data we stored: title, meta description, headings, word count, structured data, http status. Not a live fetch.
returns { ok, count, pages: [{ path, httpStatus, title, metaDescription, canonical, headings[], wordCount, textSample, structuredData[], fetchedAt }] }
| param | type | description |
|---|---|---|
| site | string | GSC property URL. Defaults to active property. |
| path | string | Exact normalized path to look up. |
| prefix | string | Path prefix to filter, e.g. /blog. |
| limit | number | Max rows, 1–500 (default 200). |
get_page_html
read-onlyLive-fetches one of your own pages right now and parses its DOM: title, meta description, canonical, word count, every heading with its level and on-page order, plus the raw HTML (optional). Best for DOM/structure auditing.
returns { ok, origin, url, finalUrl, httpStatus, contentType, fetchedAt, sizeBytes, title, metaDescription, canonical, wordCount, headings: [{ level, text, position }], html }
| param | type | description |
|---|---|---|
| site | string | GSC property URL. Defaults to active property. |
| page | string | Required. Page path (e.g. /blog/post-1) or full URL on the same origin. |
| includeHtml | boolean | Include the raw HTML in the response (default false). |
get_crawl_status
read-onlyHow many pages have metrics, how many have been content-crawled, and the last sync time.
returns { ok, site, pagesWithMetrics, pagesWithContent, lastSyncedAt }
| param | type | description |
|---|---|---|
| site | string | GSC property URL. Defaults to active property. |
Notes
- GSC numbers reflect a ~3-day publishing lag — the server queries fully-settled days.
- Out-of-range parameters are rejected with a clear message; limits come from the tool’s JSON schema (e.g.
days1–90,limitup to 300,offsetup to 25000). - Page through
get_queries/get_pageswithoffset + limitto export everything. get_query_opportunitiesanalyzes every query (not just the top 25); its headroom figures are projections from an industry CTR curve, so treat them as estimates. Exports are capped at 25,000 GSC rows.- Live tools (overview, queries, pages, page_queries, query_pages, page_html) hit Google or the live site on every call; cached crawl, idea and recommendation tools read stored data instantly.
- Manage keys in the dashboard under
Dashboard → API Keys— revoking a key stops it working immediately.