MCP Integration

Run your entire content pipeline from VS Code, Cursor, or Claude Code.

EditorInChief exposes a Model Context Protocol server that gives any MCP-capable IDE direct access to the pipeline. Create sites, configure beats, ingest articles, and queue approvals — all without opening the dashboard.


Connection

The MCP server uses Streamable HTTP transport (JSON-RPC 2.0 over HTTP POST).

Endpoint:  https://api.editorinchief.io/mcp/
Protocol:  Streamable HTTP (JSON-RPC 2.0)
Version:   0.7.0

Every request requires an Authorization: Bearer <token> header. Use an API key — easier to configure once and never expires.

VS Code (GitHub Copilot)

Add to your workspace’s .vscode/mcp.json:

{
  "servers": {
    "editorinchief": {
      "type": "http",
      "url": "https://api.editorinchief.io/mcp/",
      "headers": {
        "Authorization": "Bearer eic_YOUR_API_KEY"
      }
    }
  }
}

Cursor

In Cursor’s MCP settings:

{
  "mcpServers": {
    "editorinchief": {
      "type": "http",
      "url": "https://api.editorinchief.io/mcp/",
      "headers": {
        "Authorization": "Bearer eic_YOUR_API_KEY"
      }
    }
  }
}

Claude Code

In ~/.claude/claude_desktop_config.json:

{
  "mcpServers": {
    "editorinchief": {
      "type": "http",
      "url": "https://api.editorinchief.io/mcp/",
      "headers": {
        "Authorization": "Bearer eic_YOUR_API_KEY"
      }
    }
  }
}

Quickstart

Typical first-time setup from inside your IDE:

1. list_sites          — confirm you start fresh
2. create_site         — define your publication
3. create_beat         — add at least one beat
4. ingest_content      — push your first article
5. list_queue          — see what's pending approval
6. preview_article     — read the draft

Setup tools

create_site

Creates a new publication. Returns a site_id to use in subsequent calls.

ParameterTypeRequiredDescription
namestringHuman-readable publication name
domainstringDomain without scheme, e.g. blog.example.com
editorial_voiceobjectSee Editorial voice
approval_modestringper_article (default), digest, or auto
target_frequency_per_weeknumberTarget publication rate per week
omnivocal_api_keystringOmnivocal API key for publishing
financial_ack_atnumberUnix timestamp — required when financial_content_regulated is true

editorial_voice sub-fields:

FieldTypeRequiredDescription
missionstringOne-sentence mission statement (max 500 chars)
tone_guardrailsstringTone rules appended to every prompt (max 500 chars)
site_typestringstandard, satire, or financial
image_tonestringImage generation style hint (max 200 chars)
financial_content_regulatedbooleanSet true for regulated financial content

Example request

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "create_site",
  "params": {
    "name": "TypeScript Weekly",
    "domain": "tsweekly.dev",
    "editorial_voice": {
      "mission": "Weekly roundup of TypeScript news for working developers.",
      "tone_guardrails": "Plain language, no marketing fluff. Short paragraphs.",
      "site_type": "standard"
    },
    "approval_mode": "per_article"
  }
}

Response

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "site_id": "site_abc123",
    "name": "TypeScript Weekly",
    "domain": "tsweekly.dev"
  }
}

list_sites

Returns all sites for the authenticated user. No parameters required.

Response

{
  "result": {
    "sites": [
      {
        "site_id": "site_abc123",
        "name": "TypeScript Weekly",
        "domain": "tsweekly.dev",
        "status": "active"
      }
    ]
  }
}

create_beat

Adds an editorial beat to a site. A beat defines a coverage area and which content types to generate when a matching item arrives.

ParameterTypeRequiredDescription
site_idstringSite to add the beat to
namestringSlug-style, e.g. "releases", "vc-deals"
content_typesstring[]One or more: short_social, status_message, long_form, github_content
descriptionstringOne-sentence description of what this beat covers
coveragestringselective, balanced (default), or broad
generation_guidancestringExtra prompt guidance for this beat
synthesis_modestringauto (default), review, or off

Example

{
  "method": "create_beat",
  "params": {
    "site_id": "site_abc123",
    "name": "releases",
    "description": "TypeScript and tooling release notes.",
    "content_types": ["short_social", "long_form"],
    "coverage": "selective"
  }
}

Response

{
  "result": {
    "beat_id": "beat_xyz789",
    "name": "releases",
    "site_id": "site_abc123"
  }
}

list_beats

Returns all beats for a site.

ParameterTypeRequiredDescription
site_idstringSite ID

Content tools

ingest_content

Pushes content into the pipeline and triggers the evaluator. High-scoring items are automatically queued for article generation. At least one of url, text, or repo is required.

ParameterTypeRequiredDescription
site_idstringTarget site
urlstring*Source URL to ingest
textstring*Raw text body
titlestringTitle hint (derived from URL if omitted)
repostring*GitHub repo in owner/repo format
beat_hintstringBeat name to prefer when routing

Example — push a GitHub release

{
  "method": "ingest_content",
  "params": {
    "site_id": "site_abc123",
    "repo": "microsoft/TypeScript",
    "beat_hint": "releases"
  }
}

Response

{
  "result": {
    "item_id": "ci_def456",
    "stage": "evaluating"
  }
}

Returns { "status": "duplicate" } if the content was already ingested.


generate_content

Forces article generation for an already-ingested item, bypassing the evaluator score threshold.

ParameterTypeRequiredDescription
item_idstringContentItem ID (from ingest_content)
content_typesstring[]Override the beat’s content types
persona_idstringOverride the default persona

list_queue

Returns all articles in the pending_approval stage — your review queue.

ParameterTypeRequiredDescription
site_idstringSite ID

Response

{
  "result": {
    "articles": [
      {
        "article_id": "art_ghi",
        "title": "TypeScript 5.8 ships strict config defaults",
        "content_type": "long_form",
        "beat_name": "releases",
        "created_at": 1713456789
      }
    ]
  }
}

preview_article

Returns the full generated body and all per-channel variants.

ParameterTypeRequiredDescription
article_idstringArticle ID

Response

{
  "result": {
    "article_id": "art_ghi",
    "title": "TypeScript 5.8 ships strict config defaults",
    "body": "The TypeScript team released 5.8 today, bringing...",
    "stage": "pending_approval",
    "content_type": "long_form",
    "targets": [
      { "channel": "bluesky", "body": "TypeScript 5.8 is out..." },
      { "channel": "mastodon", "body": "TypeScript 5.8 is out..." }
    ]
  }
}

get_clusters

Returns story clusters for a site. EIC groups related ingested items using vector similarity.

ParameterTypeRequiredDescription
site_idstringSite ID
statusstringFilter: detected, queued_for_synthesis, synthesized, dismissed

synthesize_cluster

Queues a cluster for synthesis — EIC generates a dedicated article drawing from all items in the cluster.

ParameterTypeRequiredDescription
cluster_idstringStoryCluster ID (from get_clusters)

Error handling

All errors follow JSON-RPC 2.0 error object format:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32000,
    "message": "editorial_voice.mission is required"
  }
}
CodeMeaning
-32700Parse error — malformed JSON
-32600Invalid request — not valid JSON-RPC 2.0
-32601Method not found
-32000Tool error — descriptive message in error.message

Plan limit errors, validation errors, and access-denied errors all use code -32000 with a human-readable message your IDE will surface directly.