Which way should your app connect?
It depends on what your app’s MCP settings support. Use your Zyflow link with sign-in if you can, an API key if your app can send a fixed header but can’t sign in, and the bridge if it can only start local (stdio) servers. The bridge needs an API key too.
| Your app can... | Use | You need |
|---|---|---|
| Add a remote MCP server by URL and sign in with OAuth | Your Zyflow link | Nothing else |
| Send a fixed Authorization header, but not sign in with OAuth | An API key as a Bearer token | A key from the Connect page |
| Only start local (stdio) servers | The bridge | Node 18 or newer, the bridge file and an API key |
Prefer your Zyflow link with sign-in when your app supports it, because there’s no secret to store. Each app also gets its own line under Connected apps and puts its registered name on every change, so you can disconnect one without touching the others.
Connect with the server URL and sign in (OAuth)
Paste your Zyflow link into your app. Zyflow answers the app’s first request with a 401 that points to its sign-in details. An app that supports MCP authorization then registers itself and opens your browser, where you sign in and approve one workspace. Zyflow accepts dynamic client registration and client ID metadata documents, and requires PKCE (S256).
Steps
-
Paste https://app.zyflowcrm.com/mcp where your app adds a remote MCP server. Field names vary by app.
-
Your browser opens. Sign in to Zyflow, or create a free account. No account yet? Get your Zyflow link first, then paste it.
-
Choose one workspace, then press Approve.
-
Your app appears under Connected apps on the Connect page.
What your app needs
- The authorization code flow with PKCE, method S256.
- Dynamic client registration (RFC 7591), or a client ID metadata document served over https.
- A redirect URI on https, on http at a loopback address (any port), or on the app’s own scheme. Zyflow refuses fragments and the javascript:, data: and file: schemes.
- Discovery from the WWW-Authenticate header, which points to /.well-known/oauth-protected-resource/mcp, then /.well-known/oauth-authorization-server, on your Zyflow link’s host.
- A resource indicator (RFC 8707) is optional. If your app sends one, it must be your Zyflow link.
- Token endpoint auth: none, client_secret_post or client_secret_basic.
What you’ll see when you approve
The approval screen shows the app’s name and logo, the host you’ll return to, and a workspace picker. Apps with a client ID metadata document also show “Verified app from <domain>”. That names the domain that published the app’s details; Zyflow hasn’t reviewed the app.
The scopes are crm:read and crm:write. There’s no read-only switch on the sign-in screen yet; an app that asks only for crm:read gets read-only access. Access tokens last 60 minutes. Refresh tokens last 90 days and rotate on every use. If an app reuses a replaced refresh token more than 30 seconds later, Zyflow ends the connection.
Your app’s changes show the name it registered, as in “Added by <App> via MCP”, and each one can be undone.1 An app that registers no name shows as “An AI app”.
Disconnect an app
On the Connect page, press Disconnect next to the app under Connected apps. Every token it holds stops working at once. Your records stay as they are.
Use an API key as a Bearer token
If your app can’t sign in with OAuth but can send a header, create an API key on the Connect page and send it as a Bearer token in the Authorization header. Keys start with zf_live_. Choose Read only if the app only needs to look things up, and keep that key just as private: a read-only key can still export the workspace. Keys don’t expire, so revoke any key you stop using.
Steps
-
On the Connect page, go to API keys and press New key.
-
Name the key after the app or script that will use it, such as “Office agent”. History shows this name on every change the key makes.
-
Under Access, choose Read and write, or Read only. Press Create key.
-
Copy the key. This is the only time it’s shown.
{
"mcpServers": {
"zyflow": {
"url": "https://app.zyflowcrm.com/mcp",
"headers": { "Authorization": "Bearer zf_live_…" }
}
}
} Field names vary by app, so check your app’s MCP docs. If your app can read the key from an environment variable, keep it there instead of in the file.
Before you hand a key to an app:
- A key acts with its creator’s role. Its changes show its name, such as “Added by Office agent via MCP”, and can be undone.1
- Any member can create a key, or list and revoke anyone’s, from the web app. AI apps can’t manage keys.
- Every member, and every member’s AI, can see and edit every customer. There are no per-person permissions yet.
- Keys work on your Zyflow link and the REST API, never on account, team or billing endpoints.
- On the REST API, a key can permanently delete files already in the trash. Treat it like a password, and never put it in browser code or a shared repo.
- Zyflow keeps only a hash of each key, so a lost key can’t be shown again. Revoke it and create a new one.
- Key counts by plan are on the Zyflow limits page.
For scripts that don’t speak MCP: Read the REST API docs
Use the local stdio bridge if your app only runs local servers
The Zyflow bridge is a local stdio bridge for AI apps that can only start local MCP servers: one JavaScript file that your app runs with Node 18 or newer. It reads your API key from ZYFLOW_API_KEY and relays each message to your Zyflow link over HTTPS. Set ZYFLOW_URL as well. It defaults to a local address, so without it the bridge can’t reach Zyflow.
Steps
-
Create an API key on the Connect page.
-
Download the bridge, and save the file somewhere it will stay, such as your home folder.
-
Add the config below to your app’s MCP settings, with the full path to the file.
-
Restart your app.
One file, MIT-licensed, for AI apps that can only start local MCP servers.
{
"mcpServers": {
"zyflow": {
"command": "node",
"args": ["/path/to/zyflow-mcp.mjs"],
"env": {
"ZYFLOW_URL": "https://app.zyflowcrm.com/mcp",
"ZYFLOW_API_KEY": "zf_live_…"
}
}
}
} | Variable | Default | Notes |
|---|---|---|
| ZYFLOW_API_KEY | None (required) | Your API key. Without it, every call gets a 401 |
| ZYFLOW_URL | http://localhost:5900/mcp | Set it to your Zyflow link. Leave it out and the bridge can’t reach Zyflow |
| ZYFLOW_TIMEOUT_MS | 60000 | How long one request may take, in milliseconds |
What the bridge does
- Relays each JSON-RPC line with the protocol version your app negotiated, and writes each answer back to your app.
- Reads plain JSON and SSE answers, and splits JSON-RPC batches into single requests.
- Warns at startup when ZYFLOW_URL isn’t https.
- Turns 401, 403 and 429 answers into plain hints.
- Keeps stdout for protocol messages. Logs go to stderr with the prefix [zyflow-mcp], starting with “ready · <your URL>”.
Before you run it
The bridge is one file of about 160 lines, with no dependencies and an MIT license, so you can read all of it before your app runs it. Because you download it once from your Zyflow app, nothing is fetched from a package registry when your app starts it. It reads your key from the environment, as the MCP authorization spec says stdio servers should (“retrieve credentials from the environment”, MCP specification, 2025-11-25), and sends the key only to the address in ZYFLOW_URL. Changes made through it carry the key’s name in History.
The bridge uses API keys only; it doesn’t do OAuth sign-in. Zyflow tests it with an app on protocol version 2025-06-18. Stdio apps on 2026-07-28 aren’t tested yet.
If your app can’t start it
- On Windows, write the path in JSON with forward slashes (“C:/Users/you/zyflow-mcp.mjs”) or doubled backslashes.
- If your app can’t find node, put the full path to Node in command. Run “which node” on macOS or Linux, or “where node” on Windows, to find it.
Which MCP protocol versions does Zyflow support?
Zyflow’s MCP server speaks the 2026-07-28 specification natively and accepts clients on 2025-11-25, 2025-06-18, 2025-03-26 and 2024-11-05. It uses Streamable HTTP at one URL, answers each POST with plain JSON, and takes one JSON-RPC message per request.
| Version | How Zyflow handles it |
|---|---|
| 2026-07-28 | Native |
| 2025-11-25 | Stateless legacy fallback |
| 2025-06-18 | Stateless legacy fallback |
| 2025-03-26 | Stateless legacy fallback. Batches are refused; the bridge splits them |
| 2024-11-05 | Stateless legacy fallback |
- Requests can be up to 16 MB.
- There’s no SSE endpoint; every answer is plain JSON.
- JSON-RPC batches get a 400. The bridge splits them for you.
- Not supported: sampling, elicitation, progress notifications and resource subscriptions.
- Zyflow checks the token or key before the protocol layer runs, and never accepts cookies on your Zyflow link.
Troubleshooting 401, 403 and 429 errors
Common causes are a missing or revoked credential, a read-only key asked to write, and ZYFLOW_URL left unset. Find the message your app shows in the table for its cause and fix. Through the bridge, an error starts with “Zyflow answered” and the status code, followed by a hint.
First, check the connection. Ask your app:
- What’s on my plate today?
If it answers with today’s list from Zyflow, or says nothing is due, you’re connected.
| What you see | Why | Fix |
|---|---|---|
| 401 “Authentication required. Connect Zyflow to this app first.” | No token or key was sent | Sign in from your app, add the Bearer header, or set ZYFLOW_API_KEY for the bridge |
| 401 “The access token is invalid, expired or revoked. Reconnect Zyflow.” The bridge adds “Check ZYFLOW_API_KEY (it may have been revoked).” | A mistyped or revoked key, a disconnected app, or a person who left the workspace | Reconnect, or create a new key |
| 403 insufficient_scope “This connection is read-only. Reconnect with write access to change records.” The bridge adds “This key is read-only; create a read-and-write key to make changes.” | A read-only key or connection tried to write | Create a Read and write key, or reconnect with write access |
| 429 “Too many requests. Slow down and retry shortly.” | Short burst limits stop runaway scripts | Wait for the number of seconds in the Retry-After header, then retry. Add a pause between calls in scripts |
| “Couldn’t reach Zyflow at http://localhost:5900/mcp: …” | ZYFLOW_URL isn’t set, so the bridge uses its local default | Set it to your Zyflow link |
| “Couldn’t reach Zyflow at <another address>: …” | A typo in ZYFLOW_URL, no network, or a call that ran past ZYFLOW_TIMEOUT_MS | Copy your Zyflow link again, check your connection, or raise ZYFLOW_TIMEOUT_MS |
| “[zyflow-mcp] ZYFLOW_API_KEY is not set; create one in Zyflow under Connect your AI → API keys.” | The bridge’s env block has no ZYFLOW_API_KEY | Add ZYFLOW_API_KEY |
| “[zyflow-mcp] warning: … is not https; your key would travel unencrypted.” | ZYFLOW_URL starts with http | Use the https link, your Zyflow link |
| 400 “JSON-RPC batches are not supported; send one request per POST.” | The app sends batches | Run the bridge, which splits them |
| “PKCE with code_challenge_method=S256 is required.” | The app doesn’t support PKCE S256 | Use an API key instead |
| “This server issues tokens for https://app.zyflowcrm.com/mcp only.” (invalid_target) | The app sent a different resource indicator | Paste your Zyflow link exactly, ending in /mcp |
| “This connection request has expired” | The approval page was left open for more than 10 minutes | Start again from your app |
| “Unknown app” or “Unknown client. Register again.” | The app’s registration is stale | Remove Zyflow from the app and add it again |
| Your app sees the wrong customers | The connection was approved for a different workspace | Disconnect, connect again and approve the right workspace. For a key, create a new one inside the right workspace |
Still stuck? Contact us. Spot an error? Tell us. Size limits and key counts are on the Zyflow limits page.
Questions about connecting other MCP apps
My app isn’t listed. Will it work?
Yes, if it can add a remote MCP server by URL with OAuth, send an Authorization header, or start a local server (with Node 18 or newer installed). We name only the apps we’ve tested.
Should I use OAuth or an API key?
Use OAuth when your app supports it: there’s no secret to store, and you can disconnect that app without touching the others. Use a key for scripts, and for apps that can only send a header.
Can I give an app read-only access?
Yes, with a read-only API key, or an app that asks only for crm:read. Writes get a 403 before they run. A read-only key can still export the workspace.
Is the bridge on npm? Is it open source?
No, you download it from your Zyflow app. The file is MIT-licensed. Zyflow itself is a hosted service and isn’t open source.
Do calls from these apps cost extra?
No. Calls through your Zyflow link, a key or the bridge are never billed, and there are no AI credits.3
Are changes from my app labeled and undoable?
Yes. Apps that sign in show under their registered name, and keys and the bridge under the key’s name. Each change can be undone from History.1
Can one connection reach two workspaces?
No. Connect again and approve the other workspace, or create a key inside it.
Does Zyflow have an SSE endpoint?
No. Zyflow answers over Streamable HTTP with plain JSON.
An app we haven’t tested gets the same rules as the guided ones. It reaches one workspace, it can move things to the 30-day trash but can’t empty it, and every change it makes is labeled.
One workspace per connection
You sign in and approve, like “Sign in with Google”. Your AI app never gets your password, and it can’t touch billing, members or keys.
Every AI change labeled
Export any time