---
name: showly-connect
description: >-
  Connect this agent to Showly so it can build and manage the user's
  website — create a site from a template, stage edits, build previews,
  and request a publish. Use when the user asks to connect to Showly, set
  up the Showly MCP server, or work on a site hosted on Showly. Connecting
  registers the remote Showly MCP server (https://mcp.showly.ai/mcp) in THIS
  agent's config and runs a one-time browser sign-in the human must approve.
license: Apache-2.0
disable-model-invocation: true
metadata:
  publisher: Showly
  homepage: https://showly.ai
  mcp-server: https://mcp.showly.ai/mcp
---

# Connect this agent to Showly

You are an AI coding agent (Claude Code, Codex, or similar). The human pasted
this document to connect you to **Showly** — agent-native website hosting. Once
connected you can scaffold a site, stage edits, and build live previews on the
user's behalf, all through Showly's MCP tools.

Work through the phases **in order**. Do not skip ahead: each phase depends on
the previous one succeeding. Stop and report if a phase fails — do not invent a
workaround.

> **One thing only a human can do:** the sign-in in Phase 3 happens in a browser
> tab and requires the person to click **Allow**. You cannot click it for them.
> When you reach that step, hand the URL to the human, keep the authorization
> attempt running, and monitor your host for the OAuth callback. Continue
> automatically when it succeeds; ask the human to reply only if your host
> cannot remain waiting or the authorization attempt times out.

---

## Phase 1 — Detect

Before changing anything, figure out where you're running and whether Showly is
already wired up.

1. **Identify your host.** Determine which agent you are — Claude Code, Codex,
   Cursor, VS Code / GitHub Copilot, opencode, Zed, Continue, Windsurf, Cline, or
   another MCP-capable agent. In Phase 2 you'll pick the **one branch that matches
   you** and ignore the rest.
2. **Check for an existing Showly MCP server.** Look for an MCP entry whose URL is
   `https://mcp.showly.ai/mcp`. If one already exists:
   - Skip Phase 2 (add server).
   - Go straight to Phase 4 (verify). If `list_sites` returns connected, you're
     done — tell the user and stop.
3. **Report what you found** in one line, e.g. "Detected Claude Code; no Showly
   server configured yet — I'll add it." Then continue.

---

## Phase 2 — Add the Showly MCP server to your agent

Showly is a **remote, Streamable-HTTP MCP server** at one endpoint:

```
https://mcp.showly.ai/mcp
```

You don't install a package — you register that URL in **your own** config.
**Pick the single branch below that matches the host you detected in Phase 1**
and run only that one. Every branch writes a server named `showly`. None of them
writes a token or makes a network call — authorization happens in Phase 3 the
first time you call a tool. None of them touches the user's project files or git.

After you've added the entry, reload your MCP servers (restart the session if
your host requires it) so the `showly` server is live, then go to Phase 3.

> **Do not stop after writing the config.** Reloading is the ONE thing you may
> need the human to do (some hosts pick the server up automatically; some need a
> manual reload/restart). The moment the `showly` server is loaded, immediately
> **make the Phase 3 tool call** — do not merely describe what will happen. The
> browser sign-in only appears _after_ you actually call a Showly tool; narrating
> the step instead of calling it is the #1 reason the auth page never shows.

> **Register it GLOBALLY, not per-project.** Most hosts default to a
> project/directory-scoped config, and several branches below offer both. Always
> take the **user/global** option unless the human explicitly asks to limit
> Showly to one repo. A directory-scoped entry connects fine and then seems to
> "disappear" the next time they open the agent somewhere else — the single most
> common way this setup looks broken when it actually worked.

> **Default = browser OAuth.** For every host except Cline, the first tool call
> opens a browser sign-in (OAuth 2.1 + PKCE). You do **not** put a token in these
> configs. **Cline is the one exception** — it has no browser OAuth, so its branch
> uses a manual connection key instead.

### Claude Code

```bash
claude mcp add --scope user --transport http showly https://mcp.showly.ai/mcp
```

> **`--scope user` is load-bearing — do not drop it.** `claude mcp add` defaults
> to `local` scope, which binds the server to the directory you happened to run
> it in (it lands under `projects.<cwd>.mcpServers` in `~/.claude.json`). The
> connection genuinely works, but the moment the human opens Claude Code in any
> other folder, `showly` is absent from their MCP list and it looks like the
> connection failed. `--scope user` registers it once for every project on the
> machine, which is what "connect my agent to Showly" is supposed to mean.

If you edit JSON instead of running the command, put the entry at the **top
level** of `~/.claude.json` — that top-level `mcpServers` object _is_ the user
scope. Do **not** use a project `.mcp.json`; it has the same per-directory
limitation as `local`. Merge into the existing file, never overwrite it —
`~/.claude.json` also holds unrelated Claude Code state:

```json
{
  "mcpServers": {
    "showly": { "type": "http", "url": "https://mcp.showly.ai/mcp" }
  }
}
```

### Codex

```bash
codex mcp add --url https://mcp.showly.ai/mcp showly
```

Or edit `~/.codex/config.toml`:

```toml
[mcp_servers.showly]
url = "https://mcp.showly.ai/mcp"
```

Then run `codex mcp login showly` to trigger the browser OAuth flow (see Phase
3).

#### Codex after login — refresh tools before asking for a restart

Codex can finish OAuth and save the credential while the current task's MCP tool
inventory still reflects the state from when that task started. After
`codex mcp login showly` prints
`Successfully logged in to MCP server 'showly'.`:

1. **Treat that message as OAuth success.** Do not treat `Auth: Unsupported` from
   `codex mcp list` as proof that Showly authentication failed. Some affected
   Codex builds misclassify the status even after a successful browser callback.
2. **Refresh or rediscover tools in the current task first.** If deferred tool
   search/discovery is available, search for `Showly list_sites`, load the
   matching Showly MCP tool, and continue to Phase 4. If your host exposes an MCP
   reload action, use that instead.
3. **Only if in-place discovery/reload is unavailable**, start a new Codex task
   or session and continue at Phase 4. A full app/extension restart is a fallback
   only when a new task still cannot see Showly. Do not repeat OAuth unless an
   actual Showly tool call returns an authentication error.
4. If a new task or restarted host still has no Showly tools, run the
   non-secret diagnostics below, update Codex through the same installation
   channel, and report the version plus the status output. Do not read or print
   stored credential files.

   ```bash
   codex --version
   command -v codex
   printf 'CODEX_HOME=%s\n' "${CODEX_HOME:-$HOME/.codex}"
   codex mcp list --json
   ```

#### Codex: login succeeded, but a fresh task says `Auth required`

If `codex mcp login showly` reported success, but a new task fails with:

```text
MCP startup failed
Auth required, when send initialize request
```

the new Codex MCP client sent `initialize` without a usable stored Bearer
credential. This is **not** an empty `list_sites` result, and repeating the
Showly consent screen without fixing credential loading will not help.

1. Use the diagnostics above to confirm the login command and the running app
   use the same Codex installation and `CODEX_HOME`. A separately installed CLI
   can save credentials somewhere the app does not read.
2. Update the affected Codex installation first. Then run the login again from
   that same installation and keep it active until the browser callback
   completes.
3. If the exact startup error persists, use Codex's file credential store as a
   targeted fallback. Add this **top-level** setting to the user-level
   `$CODEX_HOME/config.toml` (normally `~/.codex/config.toml`):

   ```toml
   mcp_oauth_credentials_store = "file"
   ```

   Then, using the same Codex binary:

   ```bash
   codex mcp logout showly
   codex mcp login showly
   ```

   If logout reports that no credential exists, continue with login. File mode
   stores the OAuth credential locally in `$CODEX_HOME/.credentials.json`;
   never print, share, or commit that file.

4. Start a fresh task (or fully reopen the app if it owns the MCP process) and
   call the real `list_sites` tool. If the same startup error remains, report
   the Codex version, binary path, effective `CODEX_HOME`, and sanitized error
   as a Codex client credential-loading bug. Do not describe it as a Showly
   OAuth or empty-sites result.

### Cursor

Add to `~/.cursor/mcp.json` (**global — prefer this**) or, only if the human
explicitly wants Showly limited to one repo, `.cursor/mcp.json` (project). Just
the URL, no `auth` block and no token:

```json
{ "mcpServers": { "showly": { "url": "https://mcp.showly.ai/mcp" } } }
```

Cursor runs the full spec flow on its own: it reads Showly's `401` +
protected-resource metadata, registers itself via Dynamic Client Registration,
and opens your browser to sign in (OAuth 2.1 + PKCE). You don't paste a
`CLIENT_ID` — Cursor obtains one automatically.

> **Cursor authorizes from a button, NOT from a tool call.** Unlike Claude Code
> and Codex, Cursor does **not** start OAuth when the agent first calls a tool.
> After you save the config, tell the human to open **Cursor Settings → Tools &
> MCP**, find the `showly` server, and click the blue **Connect** button (it sits
> next to a "Needs authentication" label). _That_ click opens the browser sign-in.
> Until they click it, `showly` stays disconnected and `list_sites` will just fail
> — so in Cursor, **Phase 3's trigger is the human clicking Connect**, not your
> `list_sites` call. Ask them to click Connect, wait, then run Phase 4 to verify.
>
> **If clicking Connect does nothing** (a known bug in some Cursor 2.4.x builds —
> no browser, no error): have the human click the **"Needs authentication"** text
> under the server name instead, or copy the authorization URL from Cursor's
> **Output** panel and open it manually. Upgrading to Cursor 2.5+ fixes it.

Go to Phase 3.

### VS Code / GitHub Copilot

Run the command palette action **MCP: Add Server** → choose **HTTP (remote)** →
enter `https://mcp.showly.ai/mcp` and name it `showly`. The first use opens a
browser OAuth authorization.

### opencode

Add to `opencode.json`:

```json
{
  "mcp": { "showly": { "type": "remote", "url": "https://mcp.showly.ai/mcp" } }
}
```

opencode authorizes automatically (Dynamic Client Registration + browser OAuth)
on first use. If it doesn't prompt, run `opencode mcp auth showly`.

### Zed

Add to Zed `settings.json` — and **do not set an `Authorization` header**; the
absence of one is what triggers the standard MCP OAuth browser flow:

```json
{ "context_servers": { "showly": { "url": "https://mcp.showly.ai/mcp" } } }
```

### Continue

Add to `config.yaml` (`.continue/`):

```yaml
mcpServers:
  - name: showly
    type: streamable-http
    url: https://mcp.showly.ai/mcp
```

Continue runs the OAuth 2.1 browser flow on first connect.

### Windsurf

Add to `~/.codeium/windsurf/mcp_config.json` — note the key is **`serverUrl`**,
not `url`:

```json
{ "mcpServers": { "showly": { "serverUrl": "https://mcp.showly.ai/mcp" } } }
```

The first call opens a browser OAuth sign-in.

### Hermes (Nous Research)

Hermes authorizes with a **dedicated `login` command**, not on the first tool
call. Do **not** rely on `hermes mcp add … --auth oauth` alone: on the very
first add there are no cached tokens yet, and if that command runs without an
interactive TTY it swallows the OAuth step, prints a misleading _"This server
may not support OAuth"_, and (if you accept its "Continue without
authentication?" default) saves the server with **no** `auth: oauth` — which then
401s forever. Instead, do this two-step flow:

1. **Write the config entry** (this is the reliable part of `add`). Either run
   `hermes mcp add showly --url https://mcp.showly.ai/mcp --auth oauth` and, if it
   drops to "Continue without authentication?", answer **n** so it doesn't save a
   broken entry — or just add it to `~/.hermes/config.yaml` directly:

   ```yaml
   mcp_servers:
     showly:
       url: https://mcp.showly.ai/mcp
       auth: oauth
   ```

2. **Authorize in a fresh terminal** — NOT from inside a running Hermes session
   (an in-session config reload only waits 30s, too short for OAuth):

   ```bash
   hermes mcp login showly
   ```

   Hermes opens your browser to `https://showly.ai/oauth/authorize?…` (loopback
   `127.0.0.1` callback, PKCE). The human signs in and clicks **Allow**; Hermes
   captures the redirect and caches the token at `~/.hermes/mcp-tokens/showly.json`.
   Verify with `hermes mcp test showly` — it should report **Connected** and
   discover the tool set. Because Hermes finishes auth here, **skip Phase 3** and
   go to Phase 4. _(Showly issues no refresh token, so when the token eventually
   expires just run `hermes mcp login showly` again.)_

### Cline (no browser OAuth — manual key)

Cline does **not** support browser OAuth, so you cannot use the Phase 3 flow.
Instead, ask the human to generate a **connection key** in Showly
(**Settings → Agent connections → Generate key**) and paste it into
`cline_mcp_settings.json` as a Bearer header:

```json
{
  "mcpServers": {
    "showly": {
      "type": "streamableHttp",
      "url": "https://mcp.showly.ai/mcp",
      "headers": { "Authorization": "Bearer <connection-key-from-showly>" }
    }
  }
}
```

With a valid key in place, **skip Phase 3** and go straight to Phase 4 (verify).

### Any other MCP agent

Any MCP-capable client can use Showly. Register the remote Streamable-HTTP server
`https://mcp.showly.ai/mcp` however your host adds remote servers (a config entry
with a `url` field, or an "add remote server" command). The first tool call
returns a `401` that triggers the OAuth browser flow (Phase 3). If your host
can't do browser OAuth, use the **manual connection key** path shown for Cline.

---

## Phase 3 — Authorize (a human clicks Allow)

On most hosts the first time you call any Showly tool, the server has no token
for this machine yet, so it returns a `401` that starts an **OAuth browser
sign-in**. This is the step you cannot finish alone. _(If you took the Cline
manual-key path in Phase 2, there is no browser step — skip to Phase 4.)_

> **How the sign-in is triggered depends on your host — check which case you're in:**
>
> - **Claude Code, Codex, VS Code, opencode, Zed, Continue, Windsurf, others:** the
>   sign-in starts when _you_ call a tool. Do step 1 below.
> - **Cursor:** the sign-in starts when the _human_ clicks **Connect** in
>   **Settings → Tools & MCP** (see the Cursor branch in Phase 2). Your `list_sites`
>   call does NOT trigger it. Ask them to click Connect, wait for them to sign in,
>   then skip straight to Phase 4 to verify.
> - **Hermes:** the sign-in starts when the human runs `hermes mcp login showly`
>   in a fresh terminal (see the Hermes branch in Phase 2), not on a tool call.
>   That command finishes auth, so skip to Phase 4.

1. **Actually call `list_sites` now — this is a real tool invocation, not
   something to announce.** As soon as the `showly` server is loaded, invoke
   `list_sites`. Do **not** write "I'll call `list_sites`" and then wait: an
   unspoken future-tense plan triggers nothing, so no `401` is returned and no
   sign-in URL is ever produced. Make the call; the OAuth flow starts on its own.
   _(Cursor users: your host won't trigger sign-in this way — use the Connect
   button per the callout above.)_
2. The server responds with an authorization URL on Showly's sign-in origin,
   `https://showly.ai/oauth/authorize`. Always use the exact URL your host
   surfaces — don't retype the host from this guide. Your host will surface it
   as a prompt like:

   ```
   Please open https://showly.ai/oauth/authorize?...
   to authorize this agent with Showly.
   ```

3. **Hand the URL to the human — do not try to open or complete it yourself.**
   Say something like:

   > I've started the Showly sign-in. **I can't log in for you** — please open
   > this URL in your browser, sign in with the email you registered with, review
   > the permissions, and click **Allow**:
   > `https://showly.ai/oauth/authorize?...`
   > I'll keep waiting for the OAuth callback and continue automatically when it
   > succeeds. If this authorization attempt times out, I'll let you know.

4. On the consent screen the human sees the requesting agent's name, a plain-
   English list of scopes, and **Allow / Deny**. Production access is explicitly
   limited to the confirm-publish flow: the agent cannot publish on its first
   call or bypass the user's confirmation.
5. **Keep the authorization attempt active and monitor it.** Do not end the task
   merely to wait for a separate reply. When the human clicks **Allow**, the
   OAuth callback mints a token and your host picks it up automatically. As soon
   as the host reports success, continue to Phase 4 without requiring the human
   to message you. Ask them to confirm only as a fallback when your host cannot
   remain waiting, the attempt times out, or the callback is not surfaced.

If nothing happens: confirm Phase 2 actually wrote the `showly` server (URL
`https://mcp.showly.ai/mcp`), that you reloaded/restarted, then call `list_sites`
once more to re-trigger the sign-in.

---

## Phase 4 — Verify

Confirm the connection is live before you offer to do anything.

1. Call `list_sites` again. If the tool is not in the current inventory, use
   your host's tool discovery or MCP reload mechanism before declaring failure;
   Codex must follow the after-login sequence in Phase 2.
2. A **connected** response returns the user's sites (an empty list is still a
   success — it means a brand-new workspace, not a failure). An auth error means
   the token didn't land — return to Phase 3. A CLI status label such as
   `Auth: Unsupported` is not an auth error; the real `list_sites` call is the
   source of truth.
3. **Tell the human, plainly:**

   > Connected to Showly. I can see _N_ site(s) on your workspace. Say
   > "list my sites" or "make me a coffee-shop site called Kuro Coffee" to start.

Once `list_sites` succeeds, you are connected.

---

## Phase 5 — What you can and can't do

You hold a **read + write** Showly token. You can build and stage everything
right up to production. A live publish still requires an explicit human decision:
the user confirms the agent's summary on Free/Pro, while Team/Enterprise routes
the request to a second reviewer in Showly.

**You can:**

| Intent                             | Tool                                                      | Scope                                     |
| ---------------------------------- | --------------------------------------------------------- | ----------------------------------------- |
| See the user's sites & content     | `list_sites`, `get_site_context`, `get_site_files`        | `site:read`                               |
| Spin up a new site from a template | `create_site_from_template`                               | `template:create`, `site:write`           |
| Host plain HTML — no template      | `create_site_from_html`                                   | `site:write`, `preview:create`            |
| Turn a request into a plan         | `create_change_plan`                                      | `site:read`                               |
| Stage file edits (not deployed)    | `apply_site_patch`                                        | `site:write`                              |
| Build a real preview               | `create_preview`                                          | `preview:create`                          |
| Read build / check status          | `run_checks`, `get_preview_status`, `get_deployment_logs` | `checks:run`, `preview:read`, `logs:read` |
| Publish after the user confirms    | `publish_site`                                            | `publish:confirm`                         |
| Request a Team/Enterprise reviewer | `request_publish`                                         | `publish:request`                         |

**Production rules:**

- **Never publish on the first call.** On Free and Pro, call `publish_site`
  without a confirmation token, show the returned summary, and ask the user to
  confirm. Only after they say yes may you call it again with the short-lived
  token. Poll `get_preview_status` with the returned production deployment ID
  until it is `ready`, then return its `productionUrl` to the user. On Team and
  Enterprise, use `request_publish` and hand the returned
  `webApprovalUrl` to the user for second-person approval. Neither flow requires
  OTP/MFA enrollment.
- Both publish paths require the human bound to the MCP token to have a
  verified Showly account email. If either tool returns
  `email_verification_required`, give the user its `webVerificationUrl`, ask
  them to resend/complete verification in the Web app, and retry only after
  they confirm verification. Do not claim the site is live while this gate is
  unresolved.
- **Roll back or hard-delete production runtime.** Those stay in the Showly web
  UI behind a human + MFA.

**The normal loop:** plan → `apply_site_patch` → `create_preview` → share the
private preview URL and its one-time password (or organization access) → if the
user is happy, run the correct publish flow for their plan. Previews live on
`*.showly.site`; the control plane (`mcp.showly.ai`, `api.showly.ai`) lives on
`showly.ai`.

---

### Notes

- **Privacy:** your code stays on your machine until `apply_site_patch`, when the
  changeset is uploaded to Showly storage and built there.
- **Auditing:** Showly logs every tool you invoke (invoke / succeed / fail +
  duration). The user can review exactly what you did in their **Agent activity**
  page.
- **Re-authorizing:** if calls start failing with `invalid_token`, just invoke a
  Showly tool again — that re-triggers the browser sign-in (and another human
  **Allow**). Don't try to refresh credentials yourself.
