Genie MCP
Native Cursor / Claude / Codex / ChatGPT support for GenieOS via the Model Context Protocol.
The Genie MCP lets AI editors read and write GenieOS safely on behalf of a logged-in user. It speaks the Model Context Protocol over stateless streamable HTTP, with bearer authentication and per-tool scopes. Supported today: Cursor, Claude Code, Claude Desktop, Codex, ChatGPT Developer Mode, Continue, Zed — plus any MCP 1.0 client.
The endpoint:
https://mcp.genieos.pro/v1Why MCP, not "an integration"
A plugin pattern is one editor at a time. MCP gives every editor that speaks the protocol the same surface — and gives GenieOS schema contracts as tool schemas, so the agent literally cannot propose a malformed template send.
The result for the user: "tell Cursor to ship a launch sequence" actually ships a launch sequence with the right variables, in the right state machine, with audit trail.
Install
The fastest way is the Developer Console in
app.genieos.pro → Developers
(Cursor deeplink + copy-paste snippets for every other client). Reveal
your gos_* key once, then pick the tab for your editor. If you\u2019d
rather wire it by hand:
~/.cursor/mcp.json (or Settings \u2192 Tools & MCP \u2192 Add server):
{
"mcpServers": {
"genieos": {
"url": "https://mcp.genieos.pro/v1",
"headers": {
"Authorization": "Bearer gos_…"
}
}
}
}Restart Cursor; you\u2019ll see genieos in Tools & MCP. Omit the
header to use OAuth on first tool call.
All flags go before the server name:
claude mcp add --transport http \
--header "Authorization: Bearer gos_…" \
genieos https://mcp.genieos.pro/v1
claude mcp listExpect genieos · http · ✓ connected. Omit --header to complete
OAuth on first use instead.
~/Library/Application Support/Claude/claude_desktop_config.json
(macOS) or %APPDATA%/Claude/claude_desktop_config.json (Windows):
{
"mcpServers": {
"genieos": {
"command": "npx",
"args": ["-y", "@genie-os/mcp"],
"env": {
"GENIEOS_API_KEY": "gos_…"
}
}
}
}Claude Desktop talks stdio; the @genie-os/mcp package is a tiny
launcher that bridges stdio to https://mcp.genieos.pro/v1. Restart
Claude Desktop after saving.
Codex stores the env-var name, not the secret. Export the key in the shell that launches Codex:
export GENIEOS_API_KEY='gos_…'
codex mcp add genieos \
--url https://mcp.genieos.pro/v1 \
--bearer-token-env-var GENIEOS_API_KEY
codex mcp listThis writes ~/.codex/config.toml. For long organic compose / publish
calls, set tool_timeout_sec = 300 on the genieos server table if
cold starts time out.
ChatGPT connects remote MCP servers in Developer mode (Pro / Plus / Business / Enterprise / Education on web):
- Settings → Apps & Connectors → Advanced → enable Developer mode.
- Create an app at chatgpt.com/apps.
- MCP server URL:
https://mcp.genieos.pro/v1. - Authentication: OAuth (GenieOS opens consent and binds a workspace).
- Start a Developer mode chat and ask Genie to list templates or social networks.
Compose / publish tools can take a few minutes on cold start — keep the chat open until the tool call settles.
In your ~/.continue/config.json, add to experimental.modelContextProtocolServers:
{
"name": "genieos",
"transport": {
"type": "streamable-http",
"url": "https://mcp.genieos.pro/v1",
"headers": {
"Authorization": "Bearer gos_…"
}
}
}In ~/.config/zed/settings.json:
{
"context_servers": {
"genieos": {
"command": {
"path": "npx",
"args": ["-y", "@genie-os/mcp"]
},
"settings": {
"env": {
"GENIEOS_API_KEY": "gos_…"
}
}
}
}
}For any client that speaks stdio MCP:
npx -y @genie-os/mcp
# stdin/stdout speaks JSON-RPC; Authorization read from GENIEOS_API_KEY.For any client that speaks HTTP MCP:
POST https://mcp.genieos.pro/v1
Authorization: Bearer gos_…
Content-Type: application/json
{ "jsonrpc": "2.0", "id": 1, "method": "tools/list" }Available tools
Every tool is a thin wrapper around the REST API with the same
auth and the same schema-contract enforcement. Live catalogue today:
64 tools (call tools/list for the authoritative JSON Schema).
Workspace & brand
| Tool | What it does |
|---|---|
read_workspace | Workspace settings, plan, send budget, identities |
read_brand | Brand voice, palette, fonts, logos — author on-brand |
recent_audit_entries | Last audited writes — for "what did the agent just do?" |
Email templates & sends
| Tool | What it does |
|---|---|
list_templates | Paginated list of templates with schema contract version |
create_template | Blank draft email (same seed as New email). Scope templates:write |
compose_template | Compose from a brief and persist as a draft (charges compose credits) |
read_template | Source + contract for a single template |
read_template_schema | Variables + schema contract only (cheaper than read_template) |
render_template | Preview a template against variables (no send) |
propose_template_change | Request a variable change on a template's schema |
send_transactional | Send via POST /v1/templates/{key}/send |
send_test | Send a test to a verified sandbox inbox (never charges / never hits real recipients) |
read_send | GET /v1/sends/{id} — SendPublic status + timeline |
list_sends | GET /v1/sends — recent sends with optional filters |
Pages
| Tool | What it does |
|---|---|
list_pages | List landing pages (id, slug, status, title) |
read_page | Read one page: metadata + section summary (by id or slug) |
compose_page | Compose landing-page block tree for an existing page (persists by default) |
publish_page | Publish a landing page |
Sequences
| Tool | What it does |
|---|---|
list_sequences | List published sequences (key, name, trigger, enrolled count) |
read_sequence | Read a sequence by key/id (trigger, status, node/edge counts) |
enroll_in_sequence | Enrol a contact in a named sequence |
read_sequence_run | Read one sequence run's state by run id |
cancel_sequence_run | Cancel an active sequence run (cannot resume) |
emit_event | Emit a custom event (can wake sequence edges) |
Transactional SMS
| Tool | What it does |
|---|---|
browse_sms_transactional_kit | Browse reserved SMS keys and variables |
list_sms_templates | List transactional SMS kit (body, variables, segments, consent) |
preview_sms_template | Preview transactional SMS copy and segment count |
send_transactional_sms | Send a transactional SMS through Messaging |
list_sms_deliveries | Inspect recent transactional SMS deliveries |
Transactional socials
| Tool | What it does |
|---|---|
browse_social_event_kit | Browse reserved Transactional Socials event keys |
list_social_event_templates | Installed transactional social templates / policies |
preview_social_event | Render a transactional social event without posting |
trigger_social_event | Trigger a transactional social event (preview / draft / publish) |
list_social_event_runs | Recent transactional social event runs |
Organic social
| Tool | What it does |
|---|---|
list_social_networks | Connected company social networks — call before create |
refresh_social_networks | Re-sync company networks from provider (Glow+ / publish scope) |
list_social_posts | List organic social posts (filter by status / channel / group) |
read_social_post | Read one organic post (caption, media, schedule, status) |
create_social_post | Create organic post(s); optional schedule/publish |
schedule_social_post | Schedule an existing organic post |
publish_social_post | Publish an organic post now — confirm with the operator first |
delete_social_post | Delete a draft; pass fromProvider to remove a live post |
get_social_post_analytics | Cached engagement metrics for a published organic post |
Marketing OS, campaigns & lists
| Tool | What it does |
|---|---|
read_marketing_strategy | Read live Marketing Strategy (detail=summary|full) |
patch_marketing_strategy | Sparse-merge patch of live Marketing Strategy |
list_icps | List Ideal Customer Profiles (primary/active first) |
read_icp | Read one ICP by id |
read_creation_defaults | Read workspace creation defaults (stored + factory-merged) |
set_creation_defaults | Merge-patch workspace creation defaults |
list_creations | List campaigns/creations with strategy status |
read_creation | Read one creation/campaign by id |
spawn_creation | Spawn a campaign from a brief |
approve_creation_strategy | Approve campaign strategy and start building planned channels |
list_lists | List contact lists (name, contact counts) |
read_list | Read one contact list by id |
create_list | Create a contact list |
add_list_members | Add workspace contacts to a list by contactId |
Approvals, links & webhooks
| Tool | What it does |
|---|---|
list_approval_policies | List approval policies by surface |
manage_approval_policy | Upsert approval policy for a surface |
list_pending_approvals | List pending approval requests awaiting decide |
decide_approval | Approve / request changes / reject a pending approval |
list_short_links | List existing tracked short links (newest first) |
get_short_link | Read one short link (password/schedule/route metadata) |
list_utm_suggestions | Frequency-ranked prior UTM values to reuse on new links |
create_short_link | Create a tracked short link (1 credit) — UTM, password, schedule, route rules, domain |
update_short_link | Patch destination, UTM, password, schedule, route rules |
read_link_analytics | Click analytics cards (workspace-wide or per link) |
create_qr_design | Create a brand-styled QR design (1 credit) |
update_qr_design | Update QR style / encodes / frame |
render_qr_design | Render SVG/PNG/WebP/hi-res/print PDF; optional saveToAssets |
list_webhooks | Subscriptions and their delivery state |
create_webhook | Create a webhook subscription (Glow+ for link.* events) |
list_utm_suggestions
Returns prior utm_source / utm_medium / utm_campaign /
utm_content / utm_term values used on workspace short links,
frequency-ranked (same history the Links designer autocomplete uses).
Requires links:read.
Agent habit: call this before create_short_link. Offer matching
prior values to the operator so taxonomy stays consistent
(newsletter not a new Newsletter spelling).
| Argument | Required | Notes |
|---|---|---|
field | no | Limit to one of source | medium | campaign | content | term |
includeCounts | no | Default true — include { value, count } per suggestion |
list_short_links
Lists existing tracked links (slug, redirectUrl, destination, utm,
clicks). Useful to avoid minting duplicates. Requires links:read.
| Argument | Required | Notes |
|---|---|---|
includeArchived | no | Default false |
limit | no | 1–500, default 100 |
create_short_link
Mints a tracked short link (1 credit). Requires links:write. Optional
utm is stamped onto the redirect destination at click time — so a
chatbot can take a list of sites and mint attributed links in one pass.
Prefer reusing values from list_utm_suggestions when the operator
agrees. Password, expiry, scheduled go-live, and route rules (country /
city / device / platform) are available on every tier.
| Argument | Required | Notes |
|---|---|---|
destinationUrl | yes | Full URL including scheme (https://…) |
slug | no | Custom short path (1–40 chars, alphanumeric + -/_). Omit to auto-generate |
label | no | Human nickname in the Links library |
campaignId | no | Campaign back-pointer for attribution |
tags | no | Free-form tags (max 20) |
domain | no | Short-link host; defaults to gogen.ie. Spark+ custom hosts accepted when active |
password | no | Gate the redirect behind a password |
expiresAt | no | ISO timestamp — link stops redirecting after |
scheduledGoLiveAt | no | ISO timestamp — link inactive until |
routeRules | no | Array of { match: { kind, values }, destinationUrl } |
utm | no | Object with source, medium, campaign, content, term → utm_* query params on redirect |
{
"destinationUrl": "https://acme.com/sale",
"slug": "summer",
"label": "Summer sale",
"password": "gate-phrase",
"utm": {
"source": "newsletter",
"medium": "email",
"campaign": "summer-2026",
"content": "hero-cta"
}
}Returns redirectUrl (https://gogen.ie/{slug}), linkId, and click
counters at zero. There is no bulk endpoint — call once per destination.
Slug collisions return an error; omit slug or retry with another value.
Use get_short_link / update_short_link to read or patch an existing
link (including clearPassword, clearExpiresAt,
clearScheduledGoLiveAt, clearRouteRules). Use read_link_analytics
for click cards. For QR: create_qr_design → render_qr_design with
format (svg | png | webp | png-print | pdf) and optional
saveToAssets. Print PDF (bleed) costs 5 credits; hi-res PNG 2; SVG /
PNG / WebP free.
Prefer compose_template when the operator gave a brief; use
create_template only for a blank canvas. Both need templates:write
(Full / custom keys). Hero image gen on compose is off unless
includeHeroImage: true.
Organic social tools require social:posts:read|write|publish (see
Authentication). Only company / workspace
networks are returned — never personal LinkedIn or personal X profiles.
create_social_post supports mode: "copy" (supply caption) and
mode: "compose" (Genie writes from a brief). Prefer
create_social_post with scheduleAt when the time is known; always
confirm before publish: true or publish_social_post. Native X with
a URL in the caption or linkUrl costs 4 credits
(social-post-publish-url) instead of 1. Pass refresh: true on
get_social_post_analytics to poll live metrics. Call
refresh_social_networks after the operator connects a new account.
Call read_marketing_strategy (and list_icps) before drafting
campaigns. Prefer spawn_creation + approve_creation_strategy over
hand-wiring every channel when the brief is campaign-shaped.
Tools that mutate require a key with the matching scope. The MCP
installer offers presets — Read, Send, Author, Full — so the
human in the loop chooses the agent\u2019s blast radius.
How the contract flows through
When tools/list is called, GenieOS returns each tool\u2019s JSON
Schema including the per-template variable schema for the templates
the key can see. So send_transactional\u2019s schema looks roughly like:
{
"name": "send_transactional",
"description": "Send a single transactional message via a published template.",
"inputSchema": {
"type": "object",
"properties": {
"to": { "type": "string", "format": "email" },
"template": {
"type": "string",
"enum": ["welcome", "order_confirm", "password_reset"]
},
"variables": {
"oneOf": [
{ "title": "welcome", "type": "object", "required": ["first_name", "plan"], "properties": { ... } },
{ "title": "order_confirm", "type": "object", "required": ["order_total"], "properties": { ... } },
{ "title": "password_reset", "type": "object", "required": ["reset_url"], "properties": { ... } }
]
}
},
"required": ["to", "template", "variables"]
}
}The agent gets red squiggles for missing variables, just like a TypeScript developer would. This is the killer feature.
Auditing
Every MCP call lands in the audit log with actor.kind = "mcp",
actor.client (e.g. cursor/0.42.0), and actor.user (the human who
installed the key). Replay it from the dashboard or:
genie logs tail --actor mcpRevoke
gos_mcp_* keys can be revoked from
app.genieos.pro → Developers → MCP at any
time; revocation is instant. The next agent call sees 401 invalid_api_key
and the editor shows a re-auth prompt.
What\u2019s next
- MCP Resources for static knowledge — your domain\u2019s style guide, brand voice, do-not-send list — coming in Q3 2026.
- MCP Prompts for canned workflows — "draft a launch sequence", "audit last week\u2019s sends" — coming in Q3 2026.
If you\u2019re building MCP-shaped tooling and want feedback on what the contract surface should look like for your domain, hello@genieos.pro.
The MCP is the API
We build GenieOS MCP-first. Anything in mcp.genieos.pro/v1 is
also in api.genieos.pro/v1 and vice versa — there\u2019s no MCP-only
surface, no API-only surface. The contract enforcement, the audit log,
the rate limits, the idempotency rules are all the same.