
# Context Sites — Agent guide

## 1. What Context Sites is

Context Sites (the Context Blog MCP) is the publishing extension of Context: it drafts and publishes blog posts, site pages and Instagram carousels for a tenant, renders previews, lints content, records checker verdicts, and reports traffic and AI visibility. It never tracks work or approves anything — every piece carries a `context_issue_id`, and the approval that unlocks `publish` lives in Context. Everything in the [Context Agent guide](https://agents.onecontext.me/) applies unchanged when this workflow writes to Context.

## 2. Start here

**Connect both servers** — Context first (`https://mcp.onecontext.me/mcp`, see its Guide), then Sites at `https://sites.onecontext.me/api/mcp` (contract `blog-1.3.0`; `blog.onecontext.me/api/mcp` answers `410 moved`).

- Claude Code: `claude mcp add --transport http context-blog https://sites.onecontext.me/api/mcp`
- claude.ai: Settings → Connectors → Add custom connector → name Context Sites, URL above
- ChatGPT: Settings → Connectors → Add → URL above
- Cursor / any MCP client: add an HTTP MCP server with the URL above
- Auth: Google sign-in on interactive hosts. Headless routines use a bearer by **name** (`CONTEXT_BLOG_MCP_TOKEN` in the host's secret store, expanded into the `Authorization` header by the MCP config). Tenant credentials (Postiz, analytics, search console) are named, never pasted.

**Call `setup` first, every session** — `setup {workflow: "blog" | "site" | "instagram", caller, host, skills_held, guide_held_sha256}`. It resolves the workflow skill (`blog-agent` / `site-builder` / `instagram-drafter`) plus `rules-blog`, the core `context` skill and their dependencies, and returns `guide` and `skills[]` with `status: current | update | install`, `drift`, `nextAction`, and `mode: "files"` (paths to write per host) or `mode: "chat"` (skill links + inline text). Idempotent. Do the `nextStep` / `nextAction`.

**Install what it returns, then read this Guide.** `usage_guide` and `get_capabilities` describe the server and the tools this contract serves; if a tool a skill names is absent, say "not available yet on this server" and attach the payload you would have sent to the Context Issue instead. `list_skill_catalog` / `get_skill {key}` read the same catalog as `https://agents.onecontext.me/skills`.

## 3. The loop

1. **Set up** — `setup {workflow}`; for a new tenant `tenant_create`, `brand_upsert`, `audiences_upsert`, `hubs_upsert`, `topics_upsert`. The workflow skill charts the tenant Epic in Context: one parent Issue per channel, every piece a child, one combined map + spec `request_review`.
2. **Draft** — claim the publish Issue in Context (`update_issues … in_progress`). Research with cited sources. `content_lint` first (read-only; same body as the upsert), fix every finding, then `article_upsert {tenant_slug, slug, locale, translation_group, title, description, sections, seo, hub_slug, context_issue_id}` — it lints again and refuses on failure. Two bounces, then escalate. Pages: `page_upsert`; carousels: `asset_upload` → PUT → `asset_complete`, then `instagram_post_upsert`.
3. **Attach for review** — on the Context Issue: the markdown deliverable (what the owner comments on) and ONE final preview from `preview_render {tenant_slug, kind, title, description, sections, …}` attached as `Preview — <title>`. Instagram: one Instagram-style viewer over the slide asset URLs, never one Artifact per slide.
4. **Check** — a separate session runs `blog-checker`: `content_lint`, `preview_render`, judgement and fact checks, then `check_record {tenant_slug, subject_kind: "article" | "page" | "instagram", subject_ref: <issue id>, round, verdict, findings, models}`. On `pass` it raises the Context `request_review`; on `bounce` the maker fixes and re-upserts with the same `id`; `escalate` goes to the owner.
5. **Approve** — the owner decides in Context; wait on `get_changes`. Locale variants are child Issues of the EN master and inherit its approval once their own verdict is attached.
6. **Publish** — only for an Issue whose Context state is `done`: `article_set_status {tenant_slug, id, status}` forward as needed, then `publish {tenant_slug, assert_context_done: true, context_issue_id, article_id | page_id | instagram_post_id}`. Publish at the slot (`due`), never early; a missed window is re-slotted, never silently published late. Post the live URL on the Issue, then `complete_issues` with `work_stats`.
7. **Measure** — `stats_summary`, `top_posts`, `post_stats`, `ai_referrals`, `search_queries`, `indexing_status`, `tracking_setup_status`; the weekly `blog-assessment` probes AI visibility (`visibility_queries_set` → probe → `visibility_results_ingest` → `visibility_report`) and posts one report Issue.

## 4. Rules that bite

- **Never publish without a Context approval.** `publish` requires `assert_context_done: true` and refuses when the Issue is not `done`. Never mark that Issue done yourself — it is a human gate.
- **Maker and checker are different sessions.** A checker run gets only the brief and the draft. No `request_review` before the verdict, deliverable, preview and models are on the Issue.
- **Status moves forward one step**: `draft → in_review → approved → published → retired`; any other jump is an error; `retired` is terminal.
- **`context_issue_id` on every upsert** — the server rejects content without it. `tenant_slug` on every content call.
- **No invented facts**, numbers, quotes or anecdotes; cite sources in draft notes. No medical, legal or financial claims the owner did not approve. Do not work around the lint.
- **Keys by name only.** Binary bytes never go through the model: use the upload plan (`asset_upload` on Sites, `attach_artifact` on Context) and finish before it expires.
- **Recurring workflows install `daily-brief` first** — one comment a day on the Daily Brief Issue; a missing brief is the outage alert. Routines refresh their skills from the channel before each run and record the versions in the run log.
- **Drift rule.** Call `setup` every session. If the Guide or a skill comes back `update` or `install`, fetch the URLs it gives and overwrite your copy before working; if you cannot, finish the unit, comment on the Issue, and tell the owner. Record the versions you ran with in `work_stats` (`skills[]` names such as `blog-drafter@7`).
- **Context calls follow the Context Guide**: `caller` on every call, `expected_version` on updates, one `request_review` per decision, `get_changes {cursor, wait_ms: 25000}` to wait, ≤ 2 Issues per `create_issues` today.
- **Rate.** One new EN piece per drafter run plus its locale variants; one new carousel per run; the publisher runs every 3 h and publishes only inside `[due, due + 3 h)`.

## 5. Skills you will use

`rules-blog` is always loaded with the core `context` skill — the label vocabulary, the checker and publish gates, which server does what. The workflow skills: `blog-agent` ("set up blog": interview the owner, chart the tenant Epic, install and verify the routines), `blog-drafter` (nightly maker, `article_upsert` honouring the lint, hand-off to the checker), `blog-checker` (independent gate: machine checks, judgement, fact-check, `check_record`, `request_review` on pass), `blog-publisher` (every 3 h, exactly the approved and due pieces), `instagram-drafter` / `instagram-publisher` (carousel maker and Postiz scheduler, `POSTIZ_API_KEY` by name), `site-builder` (one page, one gate), `blog-assessment` (weekly traffic and AI-visibility report). `daily-brief`, `grill-me` and `wayfinder` come from the Context Guide.

| Skill | latest | beta | What it is for | Raw |
|---|---|---|---|---|
| [blog-agent](https://agents.onecontext.me/extensions/context-sites/skills/blog-agent) | v8 | v8 | Set up blog" for any agent connected to Context + the Context Blog MCP: detect an existing tenant epic and reuse it (redo = re-interview + updated brand guides), or interview the owner (grill-me / wayfinder), fetch the facts, chart a tenant epic with brand, audience and design documents, one parent issue per channel with every piece as its child, one Backlog, the standing issues, then install and verify the routines on this machine (daily brief first) and raise one combined map + spec review. | [.md](https://agents.onecontext.me/extensions/context-sites/skills/blog-agent.md) |
| [blog-assessment](https://agents.onecontext.me/extensions/context-sites/skills/blog-assessment) | v2 | v2 | Weekly assessment for a Context Blog tenant: read the stats the Blog MCP holds (traffic, AI-referral share, Search Console, indexing), run the agent-side AI-visibility probe with the host's keys (OpenRouter, optional Perplexity / SerpApi — by NAME, cost-capped), ingest the results, and post one report sub-issue under the tenant's Performance Report lane with citations found / missing and topic actions for the Topic Lane. | [.md](https://agents.onecontext.me/extensions/context-sites/skills/blog-assessment.md) |
| [blog-checker](https://agents.onecontext.me/extensions/context-sites/skills/blog-checker) | v5 | v5 | Independent quality gate between the maker and the human for Context Blog content: run the MACHINE checks through the Blog MCP (content_lint, preview_render), do the JUDGEMENT checks and the fact-check yourself, record a pass / bounce / escalate verdict on the Context issue (review doc + rendered preview + models), and raise the request_review only on pass. | [.md](https://agents.onecontext.me/extensions/context-sites/skills/blog-checker.md) |
| [blog-drafter](https://agents.onecontext.me/extensions/context-sites/skills/blog-drafter) | v7 | v7 | Nightly maker for Context Blog: keep the tenant's draft buffer at or above the floor, take the next hub-bound topic from the slotted publish issues under the tenant's `Blog` parent or graduate one from the `Backlog`, research it with cited sources, draft through the Blog MCP `article_upsert` (lint-gated, fix and retry, two bounces then escalate), hand the draft to `blog-checker` in a separate call, spawn the locale variants as child issues of the EN master, and leave the publish issue carrying the markdown draft (for comments) + verdict + the final rendered preview (to click and see) + models behind one blocking request_review. | [.md](https://agents.onecontext.me/extensions/context-sites/skills/blog-drafter.md) |
| [blog-publisher](https://agents.onecontext.me/extensions/context-sites/skills/blog-publisher) | v4 | v4 | Every 3 hours, publish exactly the Context Blog pieces the owner approved: Context issue `done`, `due` ≤ now < `due` + 3 h, no live link yet — through the Blog MCP (`article_set_status` forward, then `publish {assert_context_done: true, context_issue_id}`), post the live link on the issue, cascade to the checked locale variants, re-slot missed windows, and stay idempotent. | [.md](https://agents.onecontext.me/extensions/context-sites/skills/blog-publisher.md) |
| [instagram-drafter](https://agents.onecontext.me/extensions/context-sites/skills/instagram-drafter) | v4 | v4 | Maker for Context Blog Instagram carousels and posters: take the next `channel:instagram` publish issue of the tenant epic, write the caption and the slide copy from its linked blog topic in the tenant's voice, render the slides from the paper-cards template with headless Chrome, upload them as tenant assets, `instagram_post_upsert`, attach ONE Instagram-style swipeable preview (templates/instagram-preview.html over the asset URLs) + caption + models to the Context issue, hand it to `blog-checker`, and leave one blocking request_review. | [.md](https://agents.onecontext.me/extensions/context-sites/skills/instagram-drafter.md) |
| [instagram-publisher](https://agents.onecontext.me/extensions/context-sites/skills/instagram-publisher) | v3 | v3 | Every 3 hours, post exactly the Instagram carousels the owner approved: Context issue `done`, `due` ≤ now < `due` + 3 h, no live link yet — upload the slides to Postiz with `POSTIZ_API_KEY` (by name, host only), schedule the post on the tenant's Instagram channel found by name, `publish` the instagram_post on the Blog MCP, and post the Postiz id, then the permalink, on the issue. | [.md](https://agents.onecontext.me/extensions/context-sites/skills/instagram-publisher.md) |
| [rules-blog](https://agents.onecontext.me/extensions/context-sites/skills/rules-blog) | v6 | v6 | Rules for every Context Blog workflow, layered on the Context harness: the three forks (what · how often · output tier), the label vocabulary, the checker and publish gates, key names only, daily brief first, and which server does what. | [.md](https://agents.onecontext.me/extensions/context-sites/skills/rules-blog.md) |
| [site-builder](https://agents.onecontext.me/extensions/context-sites/skills/site-builder) | v3 | v3 | One-time site / landing page for a Context Blog tenant: fix the page goal, audience, sections (hero, how it works, tiers, proof, CTA) and design tokens in a short interview, draft straight into the Blog MCP page shape, `page_upsert` honouring the lint (dry run first), `preview_render`, hand the draft to `blog-checker` in a separate call, leave the Context issue behind one `gate:artifact` review, and `publish` only after the owner approved it there. | [.md](https://agents.onecontext.me/extensions/context-sites/skills/site-builder.md) |

Raw skill text: `https://agents.onecontext.me/extensions/context-sites/skills/<key>.md`.

## 6. Tools map

Full schemas: `https://agents.onecontext.me/extensions/context-sites/tools/context-blog`. Groups: Skills & setup (all read-only; `setup` first), Tenant & brand (upserts replace by key/slug), Content (`publish` takes exactly one id), Checker (`content_lint` is side-effect free), Assets (signed PUT, then `asset_complete` with width/height/alt), Instagram (slides are asset ids; caption ≤ 2200 chars), Domain (hosted tier), Analytics (periods `7d | 28d | 90d`), AI visibility (the probe runs agent-side with the host's keys).

| Server | Endpoint | Contract | Tools | Published | Catalog |
|---|---|---|---|---|---|
| [Context Sites](https://agents.onecontext.me/extensions/context-sites/tools/context-blog) | `https://sites.onecontext.me/api/mcp` | blog-1.3.0 | 44 | 2026-11-06 · `b22a1da` | [tools.json](https://agents.onecontext.me/extensions/context-sites/tools/context-blog/tools.json) |

Errors: lint failures come back as findings with a `path` — fix them, do not retry blindly; `VALIDATION_FAILED` names the missing field (`tenant_slug`, `context_issue_id`, `translation_group`, `hub_slug` are the usual ones); HTTP 410 `{"error": "moved", "endpoint": …}` means switch to the endpoint in the body. Every Context error class (`PAIRING_REQUIRED`, `STALE_VERSION`, `OPERATION_PENDING`, `WORKER_RESOURCE_LIMIT`) applies unchanged on the Context side.

## 7. Extensions

This is the Context Sites extension of Context. Core Guide, skills and tools: `https://agents.onecontext.me/`.


## Live index

**Channels** — latest `v18` (2026-09-08), beta `main@2a78a3c` (2026-11-07). Resolve at session start via `setup`; [channels.json](https://agents.onecontext.me/channels.json).

---
_Guide for Context Sites: `extensions/context-sites/GUIDE.md` at `v18` ([raw](https://agents.onecontext.me/extensions/context-sites/GUIDE.md)) · built 2026-11-07T05:58:32.340Z · [llms.txt](https://agents.onecontext.me/extensions/context-sites/llms.txt) · [index.md](https://agents.onecontext.me/extensions/context-sites/index.md) · [Context](https://agents.onecontext.me/)_
