Connect your AI agent to one Keygrip project's work orders: review, approve and publish each page.
Overview
Keygrip writes and improves pages for your site. Each page arrives as a work
order: the page body, its metadata and structured data, and step-by-step publishing
instructions. The client MCP server is how your own AI agent (Claude Code, Claude Desktop or any
MCP client) works through those work orders for one Keygrip project:
List the pages Keygrip has sent you, with the version to take for each and whether it is approved or awaiting approval.
Preview a page as it is served now and with Keygrip's edits applied, rendered in your site's own CSS.
Edit a page. Every edit saves a new version; an earlier version can be restored.
Approve a version for publishing, after ticking its "Before publishing" checks.
Publish it yourself, from the deploy document: a pull request in your own repository, or your CMS. Keygrip touches neither, and there is nothing to report afterwards: Keygrip's daily check of your site records when the page is live.
Feedback: pass on what your team said about a page or a tool, which Keygrip otherwise never sees.
Nothing on this server bills you or starts a content run, and it cannot reach any other project.
Every tool is listed with its parameters in the tool reference,
which is generated from the running server's own tool registry.
Authentication
The server takes one credential: a client key, starting
kg_client_. Your Keygrip contact mints it on the project's
Settings → Client MCP access → Create client key and sends it to you; it is
shown once. The key is pinned to that one project, so no tool takes a project id.
Send it on every request as a bearer token: Authorization: Bearer kg_client_…
There is no OAuth flow and no Keygrip login. A request without a valid key answers 401.
The key does not expire. To revoke it, Keygrip deletes it; the next call is refused. Ask for a new key per team or machine if you want to revoke them separately.
Treat it like a password: it can edit and approve the project's pages.
Connecting
The endpoint speaks MCP over Streamable HTTP:
https://app.keygrip.ai/client/mcp
Claude Code
One command, once per machine:
claude mcp add --transport http -s user keygrip-workorder https://app.keygrip.ai/client/mcp \
--header "Authorization: Bearer kg_client_…"
Claude Desktop and other MCP clients
Any client that supports remote Streamable HTTP servers with custom headers takes this
configuration (Claude Desktop: Settings → Developer → Edit config, or your client's
equivalent):
The Keygrip Claude Mod (workorder-pane) draws the deploy queue, each order's edits and checks,
and the page preview in a panel beside the chat, on the same key. Install it from
the setup page and type /workorders.
Workflows
Review and approve
kg_workorders lists the pages Keygrip has sent you, one row per page, with the version to take. A row with approved_at set is approved and is the one to build; a row without it is awaiting approval. A row with blocked: true is still being resolved by Keygrip.
kg_workorder_preview shows the page before (mode=live) and after (mode=proposed) the edits.
To change it: kg_fetch_body, edit the markdown, then kg_save_version. That makes a new version with a new id; use the new id from then on. kg_restore_version brings an older version back.
kg_workorder_approve stamps the version as approved. The stamp is per version: a later edit starts unapproved again, unless it changes only notes.
kg_fetch_workorder downloads the whole deploy
document (body, metadata, structured data and publishing steps) for the approved version.
Publish it yourself
Publishing is your agent's own work, and no tool here does it. The deploy document from
kg_fetch_workorder carries everything the
page needs — body, metadata, structured data, step-by-step instructions — so after approving,
your agent writes the page into your site: a branch and a pull request in your
repository, or an entry in your CMS. Keygrip has no access to either and keeps none. Once the
page is served on your site, Keygrip's daily check finds it, records the date it went live and
verifies it against the work order; the page's search performance is tracked from that date.
Session context
Using Keygrip's client tools means Keygrip records this session's context — from the agent's first Keygrip tool call on — about your site, CMS, templates and preferences, to improve the next page. The raw conversation is kept 90 days; the summary drawn from it is kept with the project. With the Keygrip Claude Mod installed this happens automatically: the
mod sends the conversation from the agent's first Keygrip tool call on. Without it, your agent
sends what it learned with kg_session_context
before approving and at the end of the session. Any change to what Keygrip knows about you that
it draws from a session waits for a person to accept it.
Send feedback
When your team says something Keygrip should
know (a deploy step that did not fit, a content correction, a tool that errored, a page you
decided not to publish), send it with kg_feedback,
one call per point. A rule every future page should follow ("never call them clinics") goes the
same way, as kind: request; Keygrip's team records it in the project's guidelines.
Reporting API
The same key reads the client reporting API: JSON for the project's
pages (search demand, traffic potential, live status) and its AI-visibility tracking, plus the
session capture route the Keygrip Claude Mod posts to. It is
documented, with a try-it console, at https://app.keygrip.ai/api/client/v1/docs.
Tool reference
10 tools, read from the server's registry on every page load.
Every result is JSON text, except kg_workorder_preview, which also returns an image.
The pages Keygrip has sent you to review and publish (and the versions you saved), one row per page, newest first: the version to take for each (older versions are superseded; include_superseded adds them). A row with blocked true is not publishable yet — Keygrip is resolving it. approved_at / approved_by is the approval stamp (kg_workorder_approve): a row with it is approved and is the one to build; a row without it is awaiting approval, not ready to build — build approved rows only. observed_at / deployed_at / deployed_url show what is already live.
Download one page's deploy document (markdown, tens of KB): the page body, its metadata, structured data and step-by-step publishing instructions. Follow the document, including its Version marker block: put the marker on the page as the block says, so Keygrip's daily check can tell which version is live. optimization_id is a row id from kg_workorders. Refused for a superseded version (take the newer one from kg_workorders) and for a page that is blocked. format="json" returns the same work order as data, for drawing it rather than following it: fields[], edits[], body, structured_data[], verify[], recommended[], checked[], context_changes[], report_back, version_marker {marker, carriers[]}, mode, prepared.
The canonical body of one page's work order, as MARKDOWN — the bytes a hand edit starts from (not the work order's BODY block: its hero image, deck and table of contents are added at render time). Edit it and hand it back with kg_save_version. version_marker identifies THIS version; the saved version gets its own, so do not paste it into the body. editable false names why this version cannot take an edit (superseded — take the newest from kg_workorders; still being prepared; no stored body).
Save an edited body as the page's NEXT version — a new work order, version+1, rendered through Keygrip's own packager (same checks and publish blockers), which SUPERSEDES the one you edited and starts UNAPPROVED (approve it again with kg_workorder_approve) — except a save that changes only page_note, section_notes or section_types, which keeps an approved page approved. approval_carried (true/false) and approval_note in the result say which happened and why not ("approval not carried: fields changed"). body_markdown REPLACES the whole body: start from kg_fetch_body, change what you mean to, send all of it back; keep headings that links point at. repair: propose (default) stores your body exactly as sent and lists what Keygrip's deterministic clean-up would change as proposed_edits, unapplied; skip runs no clean-up; apply adopts it (listed in engine_edits) — save the new version again with repair=apply and an empty body to accept a proposal. notices says what was stripped on the way in. field_lengths measures meta_title, meta_description, og_title and og_description as the new version ships them against their bands, with a note naming the band on any outside it (never clamped). fields sets metadata outright — {title (the on-page H1), meta_title, meta_description, og_title, og_description, deck (hero subhead, new pages only), canonical, og_image, jsonld (the whole graph as a JSON string), verify_steps (one per line), slug / page_url (move a new page to another path — SLUG, canonical, breadcrumb and JSON-LD follow)}; a save that changes only fields is still a version — leave body_markdown empty and the current body is kept. rerender=true saves again with nothing changed (body_markdown may be empty) so the page renders from the project's current settings. section_notes {section_id: text} and page_note are your own instructions to the deploying agent, kept on later edits ("" removes one); a page without its own page_note gets the project's, which Keygrip sets; section_types {section_id: type} sets a landing section's type (prose, card_list, value_cards, ...) over the derived one, kept the same way; toc true/false keeps or drops the table of contents. note is a one-line reason for the trail. Refuses (409) a superseded or unfinished version and (400) an empty body with nothing else to save, or an oversize or unchanged body. Returns the NEW version: it is the id to preview and approve from now on. RETRIES: pass idempotency_key (any opaque token, new per save) and a retry after a timeout returns the version the first call made, with replayed true, never a second version; with no key, a retry that resends the same body and choices is recognised the same way. prepublish_checks [{item, owner, status: open|done, id}] replaces the 'Before publishing' list at the top of the work order (omit to keep it, [] clears it); tick one later with kg_prepublish_check. hero_image {url | data_base64, alt} sets the page's hero image on the new version to a picture you supply: url is an absolute URL used as given; data_base64 is the file (JPEG/PNG/WebP/GIF/AVIF, ≤10 MB), stored by Keygrip exactly as sent; alt omitted keeps the current one. New pages only; body_markdown may be empty.
Make an EARLIER version of a page current again, as its next version: optimization_id is the version to bring back (kg_workorders include_superseded=true lists them). Its body, fields and notes come back byte for byte on a new version, which starts UNAPPROVED; the version it replaces is superseded. Refuses (409) the current version, one with no stored body, and a page whose current version is still being prepared. Returns the NEW version.
Record that this page may be published (approved=true, the default) or take that back (approved=false): stamps approved_at / approved_by on THIS version, under this key's label. The stamp is per version — an edit or a restore is a new version that starts unapproved, except a save that changes only notes, which keeps an approved page approved (kg_save_version's approval_carried / approval_note say which, e.g. "approval not carried: fields changed") — and approving stores the deploy document as it is now: kg_fetch_workorder serves those same bytes while the stamp stands, so an approved page cannot change under its approval. Approving refuses (409) a superseded version, a blocked page and a page with an open 'Before publishing' check (tick it with kg_prepublish_check); withdrawing always succeeds. When withdrawing, pass reason: why the page is not being published (it is kept with the work order for Keygrip's staff). Returns the row with the stamp. Publishing the approved page is yours to do, from the deploy document; Keygrip's daily check of the site records when it is live.
Tick (done=true, the default) or reopen (done=false) one item of a work order's 'Before publishing' list, in place: a tick is a sign-off, not an edit, so no new version is made and the stored work order re-renders with the tick. check_id is the item's id from prepublish_checks on the run (or the `id:` at the end of its line in the work order). A condensed testimonial adds a check of its own (owner client) that clears by itself once the approved wording is recorded as a quote datapoint. Approval is refused while any item is open; reopening one withdraws the approval. Refuses an unknown id (404) and a superseded version (409). Returns the run.
A screenshot of one work order's page as it is served now (mode=live) or with the work order's targeted edits applied in the browser (mode=proposed, the default), each removal marked with a dashed rule — what a correct deploy will look like, in the page's own CSS, fetched from the client's site on every render. width=1280 (desktop, the default) or width=390 (a phone, a mobile viewport). The page is cut into width×1600 px slices; slice indexes them top-down (0 first). The result is one image block plus a JSON text block: slices (how many), height, applied (per-edit status: applied / not_found, and box = where the change sits on the page in CSS px), view_url (the same preview as a web page: the page alone under a header, no instructions on it), missing_assets / missing_asset_count (requests to the client's own site that failed or answered 4xx/5xx while the page loaded — a missing stylesheet shows as an unstyled picture; third_party_failed counts other hosts' failures, mostly trackers). highlight=true also outlines each applied change on the picture. format=jpeg and scale<1 (e.g. 0.5) shrink the picture for a surface with a small image budget. max_bytes keeps a PNG under that many bytes as a PNG (palette, then scale) for a consumer whose transport re-encodes larger images. A NET-NEW page has no live URL yet, so it renders on a template — template_url (a live page on the same site, absolute or a /path; kept on the work order, so later previews of the page use it without passing it again), else the one kept earlier, else the template the page was generated from, else the inventory page whose role fits the page (product/solution for a head-term page, a blog post for an article) nearest the new URL's path: mode=live is the template as served, mode=proposed is the template with its article thrown out and the work order's body, H1 and hero in its place, i.e. the new page in the site's own layout; the metadata's template_url names the page used and template_reason why. Once the page is reported or seen live it renders at its own URL. When the client's own build of a net-new page already exists on their Webflow staging site (found by the daily watch or on this call: a page at the work order's path on <slug>.webflow.io, proven theirs by a matching data-wf-site, carrying this version's marker), that DRAFT is the page shown as built, in both modes, and the metadata's draft_url names it; a template_url passed on the call still renders that template. An edit that comes back not_found or error means the live page changed after the compile: the preview marks the work order stale (stale_reason on kg_workorders) for staff to recompile before the client deploys. Refused (409) for proposed on a page whose work order has no targeted edits — use mode=live — for a page that is not live when no template can be found (pass template_url), and for a template off the site. A render takes a few seconds; the result is cached for ten minutes, refresh=true re-renders. A superseded version is refused (404) with the id of the page's newest version to preview instead.
Send Keygrip one correction or remark from the client — Keygrip never sees this conversation, so without this call it is lost when the session ends. One call per correction. text: what the client said or changed, in a sentence or two (their words where possible; under 4000 characters — summarise, do not paste the session). optimization_id: the work order it is about. For a correction to the page, also send section (the heading it is under; "" for page-wide), said (what the page said, quoted) and changed_to (what it says now; "" for a removal). kind is optional — leave it out for a correction to the page, Keygrip classifies it; send it only for deploy_problem (a deploy step did not fit their CMS), tool_problem (a Keygrip tool errored), request (something new, or a rule every future page should follow, "never call them clinics"), praise or not_publishing (and why). Approving past a warning and restoring a version are recorded by those calls themselves. Returns the stored row.
Send Keygrip what this session taught you about the client, so the next page gets it right. Call it before kg_workorder_approve and at the natural end of the session; it is additive — a second call merges into the same record (lists de-duplicated, transcript appended), so send what is new. Every field is optional, but send at least one; each list field is a list of short strings: cms (their CMS, platform, repo, how pages are published), template_constraints (slots and blocks their templates have or lack), preferences (what they said they want or always / never do), decisions (what was decided and why), open_questions, people (who was involved, who signs off), tool_problems (a Keygrip tool or work order step that failed or misled). transcript: optionally the conversation itself, or an excerpt (up to 200,000 characters a call, appended). optimization_ids: the work orders the session touched. session_id: your own session id if you have one (1-200 of letters, digits, _ . : -); without one, a call within 30 minutes of the last joins the same record. Keygrip's team reviews what it draws from this before anything about the client changes; credentials are redacted. Returns the session's record. For a single complaint or correction, kg_feedback is still the call.