# GeeFans MCP

GeeFans is a marketing department for indie creators (games, apps, books,
music, film, courses, and more). Give it a project — a repo, a site, some
docs — and it researches who the fans actually are, finds where they gather
online, and generates a marketing plan, campaign copy, key art, and video
content from that research.

This document is the reference for an agent (or the developer wiring one up)
connecting to the hosted MCP server. It does not assume you have ever visited
geefans.com.

## Connect

```json
{
  "mcpServers": {
    "geefans": {
      "url": "https://www.geefans.com/api/mcp",
      "headers": {
        "Authorization": "Bearer gf_live_your_personal_agent_key"
      }
    }
  }
}
```

That's the whole setup. No local process, no repo checkout, no SDK to
install — it's a remote MCP server over HTTPS supporting `initialize`,
`tools/list`, and `tools/call`.

## Getting an Agent API key

You need a `gf_live_…` key before the generation tools are usable. There are
two ways to get one:

**Already have a GeeFans account** — sign in at geefans.com, go to
**Settings → Agent keys**, and create one. It is shown once; store it in your
credential vault. It can be revoked at any time from the same page.

**No account yet** — connect to `https://www.geefans.com/api/mcp` with no
`Authorization` header at all. Without a key, only six bootstrap tools are
visible (below); everything else is hidden. Use them to create an account and
issue a key without ever visiting the website:

1. `get_service_info` — confirm you're talking to GeeFans and see what's required.
2. `get_onboarding_requirements` — see what you'll need to collect from the user.
3. Get explicit approval from your human before creating anything. **Never**
   create an account, store a provider key, or spend money on their behalf
   without this.
4. `begin_account_registration` — starts a short-lived registration and
   returns an `onboarding_token`. Creates nothing yet.
5. `complete_account_registration` — creates the account. GeeFans then sends
   a verification email; the account cannot be used until that link is
   clicked.
6. `configure_provider_key` (optional) — if the user wants to use their own
   Anthropic/OpenAI/etc. key (BYOK) instead of GeeFans' shared quota, store it
   now. Requires the same explicit approval. The value is never returned by
   any later call.
7. `finish_account_onboarding` — after the verification email is confirmed,
   this issues the one and only `gf_live_…` key for this account. Store it in
   your credential vault immediately; GeeFans will not show it again.
8. Reconnect with `Authorization: Bearer gf_live_…`. The bootstrap tools
   disappear and the full tool surface (below) becomes visible.

Every request after this point is scoped to that key's owning account. There
is no way to pass or override which user you're acting as — the key decides.

## Tool surface (authenticated)

### Research and planning

| Tool | What it does |
| --- | --- |
| `scan_project` | Reads a GitHub repo, up to 10 URLs (site, storefront, devlog, trailer page, socials), and up to 20 files you provide, and returns a structured brief (title, genre, USPs, art style, platforms, themes, dev stage). Nothing is saved — this is research only. |
| `create_marketing_plan` | Creates a project and runs the full pipeline: Persona DNA synthesis → fan-destination discovery → validation → scoring → plan. The plan's `target_channels` are always real, scored destinations discovered in this run — never invented. Returns a job; poll `get_job`. |
| `build_audience_dna` | Re-synthesizes Persona DNA for an existing project. `create_marketing_plan` already does this — call this only to refresh after the brief changes. |
| `find_audiences` | Re-runs fan-destination discovery against existing Persona DNA. Also refresh-only. |

`create_marketing_plan` always does the research first; there is no way to
skip straight to a plan. A plan written before anyone knows who the fans are
or where they gather is a guess, not a plan — GeeFans won't produce one.

Required fields for `create_marketing_plan`: `one_liner`, `target_persona`,
`creator_motivation`, `game_stage`, `marketing_budget`. Optional:
`product_category` (`game` | `app` | `book` | `music` | `film` | `course` |
`other`, default `game`), `scan_result` (paste the output of `scan_project`
here to seed the research with real project detail), `github_url`,
`game_urls`.

### Generation (requires a `marketing_plan_id` from a completed plan)

| Tool | What it does |
| --- | --- |
| `create_campaign_content` | Campaign content for social media and email, plus press-kit and sales-page copy. `kind`: `content` (social threads), `email_campaign`, `press_kit`, or `sales_page`. |
| `create_key_art` | Generates key art images for the project. |
| `create_showreel` | Cuts a highlight reel from a source video URL. |
| `create_video_influencer` | Generates a scripted video-influencer piece. |

### Utility

| Tool | What it does |
| --- | --- |
| `get_job` | Poll a job by `job_id` for stage progress and, once `completed`, its result artifacts. |
| `list_project_assets` | List existing video assets on the account. |

## Async jobs

`create_marketing_plan`, `build_audience_dna`, `find_audiences`,
`create_showreel`, and `create_video_influencer` are long-running. Calling
them returns a `job_id` and `status_url` in under a second — the work
continues after the call returns.

```text
create_marketing_plan → job_id  →  get_job(job_id) → status: "running", stage: "audience_dna"
                                 →  get_job(job_id) → status: "running", stage: "candidates"
                                 →  ...
                                 →  get_job(job_id) → status: "completed", result: {...}
```

Poll `get_job` until `status` is `completed`. **Never report a `queued` or
`running` job as a delivered result** — the artifacts (`marketing_plan_id`,
`persona_dna_id`, generated content, etc.) only exist once it's `completed`.

Typical durations: `create_marketing_plan` takes several minutes across six
stages (it also runs the audience research); `create_key_art` and
`create_campaign_content` typically finish in well under a minute but are still
synchronous calls, so use a generous client timeout on those.

If a job fails, `get_job` reports `error.stage` and `error.retryable`.
`retryable: false` means a required input is missing or invalid — fix the
request rather than retrying as-is.

## Idempotent retries

Every generation tool accepts an optional `request_id`. Reuse the same value
when retrying the same logical request; it's sent as an `Idempotency-Key` so
a retry (e.g. after a client-side timeout) can't create duplicate paid work.
For the async tools, the job itself is also the retry boundary: calling the
same job again resumes at the first incomplete stage rather than repeating
finished work.

## Recommended flow

```text
scan_project(urls, github_url, files, notes)
        → structured brief

create_marketing_plan(one_liner, target_persona, creator_motivation,
                       game_stage, marketing_budget, scan_result=<brief>)
        → job_id
poll get_job(job_id) until completed
        → marketing_plan_id, persona_dna_id, scored fan destinations, plan

create_campaign_content(kind, marketing_plan_id) / create_key_art(marketing_plan_id) /
create_showreel(marketing_plan_id) / create_video_influencer(marketing_plan_id)
        → campaign assets, using the same evidence-backed plan
```
