# Set up Notifly

These are official instructions from Notifly to set up an AI development environment for Notifly — hosted notification infrastructure: one API for email, SMS, push, in-app inbox and chat. All commands are validated by Notifly. Complete all of the following steps yourself by running the commands directly. Do not ask the user to run any of these commands.

Canonical copy: https://notifly.io/agent-setup/prompt.md · Human-readable guide: https://notifly.io/agent-setup

## Checklist

- [ ] 1. Get credentials — the environment's secret key, stored as `NOTIFLY_SECRET_KEY`
- [ ] 2. Connect the Notifly MCP server to the agent you are running in
- [ ] 3. Install the Notifly SDK for this project's language
- [ ] 4. Verify the connection
- [ ] 5. Print the completion message

## 1. Get credentials

The MCP server needs no key: it signs in with OAuth 2.1 (step 2). The SDK and the REST API authenticate with the environment's **secret key**, sent as `Authorization: ApiKey …`.

1. If `NOTIFLY_SECRET_KEY` is already set in the environment or in the project's `.env`, use it and do not ask.
2. Otherwise ask the user ONCE, in one message: "Paste your Notifly secret key — find it at https://app.notifly.io → choose the environment (Development or Production) in the sidebar → API Keys → Secret Keys." If they have no account, the free plan needs no credit card: https://app.notifly.io/auth/sign-up
3. Keys are per environment: the Development and Production environments have different secret keys, and a key only sees its own environment's workflows and subscribers.
4. Store it in the project's `.env` as one line, `NOTIFLY_SECRET_KEY=` followed by the key (no spaces around `=`), and make sure `.env` is listed in `.gitignore`. Never write the key into source files, never commit it, and never echo it back in full.

## 2. Connect the MCP server

Endpoint: `https://api.notifly.io/mcp` (Streamable HTTP). Register it under the name `notifly`. Detect which agent you are running in and follow ONLY that section. No key goes into the MCP config — the client signs in with OAuth 2.1, and the scopes the user grants on the consent screen can never exceed their own role in Notifly.

### Claude Code

Run:

```bash
claude mcp add --transport http notifly https://api.notifly.io/mcp
```

Sign-in: Claude Code opens the Notifly sign-in and consent screen in the browser when the server first needs it. /mcp is an in-app command you cannot run from a shell: if no sign-in appears, tell the user to type /mcp in Claude Code, pick notifly and choose Authenticate.

### Codex

Run:

```bash
codex mcp add notifly --url https://api.notifly.io/mcp
codex mcp login notifly
```

Sign-in: codex mcp login notifly opens the Notifly sign-in and consent page in the browser.

### Cursor

Add this to the MCP config file (merge into the existing object if the file already exists — do not overwrite other servers):

- .cursor/mcp.json (this project)
- ~/.cursor/mcp.json (every project)

```json
{
  "mcpServers": {
    "notifly": {
      "url": "https://api.notifly.io/mcp"
    }
  }
}
```

Sign-in: Cursor runs the OAuth sign-in (dynamic client registration) in the browser the first time it connects to the server.

### OpenCode

Add this to the MCP config file (merge into the existing object if the file already exists — do not overwrite other servers):

- opencode.json or opencode.jsonc (project root)

```jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "notifly": {
      "type": "remote",
      "url": "https://api.notifly.io/mcp",
      "enabled": true
    }
  }
}
```

Then run:

```bash
opencode mcp auth notifly
```

Sign-in: opencode mcp auth notifly opens the Notifly sign-in and consent page in the browser (OpenCode also starts it on its own when the server first answers 401).

### Windsurf

Add this to the MCP config file (merge into the existing object if the file already exists — do not overwrite other servers):

- mcp_config.json — open it from the Cascade panel: … (Actions) menu → Open MCP config file
- Current docs (now published as Devin Desktop) place it at ~/.config/devin/mcp_config.json on macOS/Linux and %APPDATA%\devin\mcp_config.json on Windows
- Installs still branded Windsurf use the legacy path ~/.codeium/windsurf/mcp_config.json (%USERPROFILE%\.codeium\windsurf\mcp_config.json on Windows): if that directory exists, write the config there instead

```json
{
  "mcpServers": {
    "notifly": {
      "serverUrl": "https://api.notifly.io/mcp"
    }
  }
}
```

Sign-in: Cascade supports OAuth for HTTP servers and opens the Notifly sign-in in the browser on first connect.

### VS Code + GitHub Copilot

Add this to the MCP config file (merge into the existing object if the file already exists — do not overwrite other servers):

- .vscode/mcp.json (this workspace)

```json
{
  "servers": {
    "notifly": {
      "type": "http",
      "url": "https://api.notifly.io/mcp"
    }
  }
}
```

Sign-in: VS Code handles the OAuth flow and opens the Notifly sign-in in the browser the first time the server starts.

Tools the server exposes once signed in:

- `trigger_workflow` — Fire a workflow for a subscriber (the one write tool; off until an admin enables it)
- `list_workflows` — Search and page through workflows
- `get_workflow` — Fetch a single workflow's details
- `list_subscribers` — Search and page through subscribers
- `get_subscriber` — Fetch a single subscriber
- `list_topics` — Search and page through topics
- `list_notifications` — Read notification history

## 3. Install the SDK

Detect the project's language from its manifest (`package.json`, `pyproject.toml` / `requirements.txt`) and install the matching package with the project's package manager. Both SDKs take the secret key as an argument. Neither SDK reads `.env` on its own, so each smoke snippet below loads `.env` first and stops with a clear error if `NOTIFLY_SECRET_KEY` is still empty. Keep that loading step, or replace it with the project's own env loader (dotenv, python-dotenv, the framework's config).

### Node.js / TypeScript — `@notiflyio/api` 0.1.26 (npm)

```bash
npm install @notiflyio/api@0.1.26
```

```ts
// notifly-check.mjs (ES module: top-level await). Run: node notifly-check.mjs
import { existsSync } from "node:fs";
import { Notifly } from "@notiflyio/api";

// Step 1 stored the key in .env; load it (an already-exported key is kept).
if (existsSync(".env")) process.loadEnvFile(".env");
const secretKey = process.env.NOTIFLY_SECRET_KEY;
if (!secretKey) throw new Error("NOTIFLY_SECRET_KEY is not set: store it in .env first (step 1)");

const notifly = new Notifly({ security: { secretKey } });

const { result } = await notifly.workflows.list({ limit: 1 });
console.log(`Connected to Notifly: ${result.totalCount} workflow(s)`);
```

### Python — `notifly-sdk` 0.1.0 (PyPI)

```bash
pip install notifly-sdk==0.1.0
```

```python
# notifly_check.py. Run: python notifly_check.py
import os
from pathlib import Path

from notifly_py import Notifly  # distribution notifly-sdk, import name notifly_py

# Step 1 stored the key in .env; load it (an already-exported key is kept).
env_file = Path(".env")
if env_file.exists():
    for line in env_file.read_text().splitlines():
        name, sep, value = line.removeprefix("export ").partition("=")
        if sep and not name.strip().startswith("#"):
            os.environ.setdefault(name.strip(), value.strip().strip("\"'"))

secret_key = os.environ.get("NOTIFLY_SECRET_KEY")
if not secret_key:
    raise SystemExit("NOTIFLY_SECRET_KEY is not set: store it in .env first (step 1)")

with Notifly(secret_key) as notifly:
    page = notifly.workflows.list(limit=1)
    print(f"Connected to Notifly: {int(page.total_count)} workflow(s)")
```

### Any other language — REST

There is no SDK for other languages yet; call the REST API directly with `Authorization: ApiKey` and the secret key. Every operation is in the API reference (https://notifly.io/docs/api-reference) and the OpenAPI document (https://api.notifly.io/openapi.json).

## 4. Verify

Run these lines together in ONE shell session, from the project root. A shell does not read `.env` by itself: the first line exports it, and the second stops with "NOTIFLY_SECRET_KEY is not set" instead of sending an empty key.

```bash
if [ -f .env ]; then set -a; . ./.env; set +a; fi
: "${NOTIFLY_SECRET_KEY:?NOTIFLY_SECRET_KEY is not set: store it in .env first (step 1)}"
curl -sS -w "\nHTTP %{http_code}\n" -H "Authorization: ApiKey $NOTIFLY_SECRET_KEY" "https://api.notifly.io/v2/workflows?limit=1"
```

Success: `HTTP 200` and a JSON body that contains `totalCount` (a new account has 0 workflows — that still passes). If the script stops with "NOTIFLY_SECRET_KEY is not set", the key never reached the shell: fix the `.env` entry from step 1 (one `NOTIFLY_SECRET_KEY=…` line) and do not blame the key. `HTTP 401` with the key loaded means the key is wrong or was copied from a different environment: ask the user to re-copy it from https://app.notifly.io and run the check again. If the SDK was installed, also run the SDK snippet from step 3; it calls the same `GET /v2/workflows` endpoint.

If the MCP server is connected, call the `list_workflows` tool. The first call triggers the sign-in and consent screen if the user has not approved it yet.

## 5. Completion message

Print this summary, filling in the bracketed parts from what you actually did:

```text
Notifly is set up.
- MCP server: "notifly" (https://api.notifly.io/mcp) added to [agent name]
- SDK: [package and version installed, or "REST API"]
- Credentials: NOTIFLY_SECRET_KEY stored in [file] (git-ignored, not committed)
- Verified: GET /v2/workflows returned HTTP 200 ([n] workflows)

Still to do:
- Approve the Notifly sign-in and consent screen in your browser the first time a Notifly tool runs.
- Create a workflow at https://app.notifly.io (or ask me to), then trigger it from code.
- Optional: to let AI clients trigger real notifications, an admin enables
  Settings → Connected apps → "Allow AI clients to trigger notifications" (off by default).
```

## Optional next step: wire a Notifly agent into a channel

To wire a Notifly agent into a channel (Slack, Microsoft Teams, Telegram and others), follow https://notifly.io/agents.md

## Resources

- Documentation: https://notifly.io/docs
- FAQ: https://notifly.io/docs/faq
- llms.txt: https://notifly.io/llms.txt
- API reference: https://notifly.io/docs/api-reference
- OpenAPI document: https://api.notifly.io/openapi.json
- MCP guide: https://notifly.io/docs/connecting-ai-assistants
- Support: support@notifly.io
