diff --git a/docs/user/expert/third-party-agents.md b/docs/user/expert/third-party-agents.md
index c214ac141a..65235030dc 100644
--- a/docs/user/expert/third-party-agents.md
+++ b/docs/user/expert/third-party-agents.md
@@ -89,16 +89,32 @@ Where custom connectors are available on your plan, add one and enter the FlowFu
On Team and Enterprise plans an owner adds the connector for the organisation first, and then each person connects and signs in individually.
-### Command-line and editor agents
+### Gemini
-Claude Code, Cursor, Visual Studio Code and Gemini CLI all connect to the same address. Where a client supports OAuth, sign in; otherwise use a token, see [clients without a sign-in flow](#clients-without-a-sign-in-flow).
+In the Gemini web app, open **Settings & help**, then **Connected Apps**, then add a custom app and enter the FlowFuse MCP address. FlowFuse supports Dynamic Client Registration, so there is no client ID or secret to fill in.
-For Claude Code:
+Custom apps run in Gemini Spark, which Google currently limits to personal accounts in the US, so this is not available to everyone yet.
+
+### Coding agents
+
+A coding agent can add the connector to itself. Ask it, rather than editing its configuration by hand:
+
+```
+Add the FlowFuse MCP tool at https://app.flowfuse.com/mcp. Then ask me to complete the sign-in in the browser that opens.
+```
+
+This works in Claude Code and Codex, and in any other agent that can change its own MCP configuration. It also survives those clients changing how a remote server is added, which they do at different times and in different ways.
+
+If you would rather add it yourself, Claude Code takes:
```bash
claude mcp add --transport http flowfuse https://app.flowfuse.com/mcp
```
+### Other command-line and editor agents
+
+Cursor, Visual Studio Code and Gemini CLI all connect to the same address. Where a client supports OAuth, sign in; otherwise use a token, see [clients without a sign-in flow](#clients-without-a-sign-in-flow).
+
### Local and self-hosted models
Use any HTTP-capable MCP client, such as LM Studio, LibreChat or Open WebUI, pointed at your own model, and add the FlowFuse address as a server in that client's configuration. Note that Ollama is a model runtime rather than an agent, so it needs an MCP client in front of it.
diff --git a/frontend/src/components/dialogs/AiConnectorModal.vue b/frontend/src/components/dialogs/AiConnectorModal.vue
index 31a4dc4063..e699577164 100644
--- a/frontend/src/components/dialogs/AiConnectorModal.vue
+++ b/frontend/src/components/dialogs/AiConnectorModal.vue
@@ -33,12 +33,12 @@
>
01
-
Copy the FlowFuse connector URL
-
Paste it into your agent in the next step.
+
{{ client.step1Title || 'Copy the FlowFuse connector URL' }}
+
{{ client.step1Body || 'Paste it into your agent in the next step.' }}
- {{ endpoint }}
-
+ {{ stepOneText(client) }}
+
Copy
@@ -104,6 +104,7 @@ import product from '../../services/product.js'
import chatgptLogo from '../icons/ai-agents/chatgpt.svg'
import claudeLogo from '../icons/ai-agents/claude.svg'
+import geminiLogo from '../icons/ai-agents/gemini.svg'
import copilotLogo from '../icons/ai-agents/microsoft-copilot.svg'
const CLIENTS = [
@@ -134,6 +135,43 @@ const CLIENTS = [
step2Label: 'Open ChatGPT',
step2Url: 'https://chatgpt.com/'
},
+ {
+ id: 'gemini',
+ logo: geminiLogo,
+ name: 'Gemini',
+ step2Title: 'Settings & help, Connected Apps, Add a custom app',
+ step2Body: 'Paste the URL. Gemini Spark only, US personal accounts.',
+ step2Label: 'Open Gemini',
+ step2Url: 'https://gemini.google.com/'
+ },
+ // A coding agent installs the connector into itself, so its tab is the prompt
+ // and nothing else. Nothing here to go stale when a client changes how remote
+ // servers are added, and the prompt carries this platform's own address, so it
+ // is correct on Cloud and self-hosted without the reader editing it.
+ {
+ id: 'claude-code',
+ logo: claudeLogo,
+ name: 'Claude Code',
+ step1Title: 'Copy the prompt',
+ step1Body: 'This is the whole setup.',
+ step1Command: url => `Add the FlowFuse MCP tool at ${url}. Then ask me to complete the sign-in in the browser that opens.`,
+ step2Title: 'Paste it into Claude Code',
+ step2Body: 'It adds the connector itself, then asks you to finish signing in.',
+ step2Label: 'See the documentation',
+ step2Url: 'https://flowfuse.com/docs/user/expert/third-party-agents/'
+ },
+ {
+ id: 'codex',
+ logo: chatgptLogo,
+ name: 'Codex',
+ step1Title: 'Copy the prompt',
+ step1Body: 'This is the whole setup.',
+ step1Command: url => `Add the FlowFuse MCP tool at ${url}. Then ask me to complete the sign-in in the browser that opens.`,
+ step2Title: 'Paste it into Codex',
+ step2Body: 'It adds the connector itself, then asks you to finish signing in.',
+ step2Label: 'See the documentation',
+ step2Url: 'https://flowfuse.com/docs/user/expert/third-party-agents/'
+ },
{
id: 'local',
icon: true,
@@ -168,8 +206,14 @@ export default {
this.activeClient = id
this.capture('cta-ai-agent-tab', { position: id })
},
- copyEndpoint () {
- this.copyToClipboard(this.endpoint)
+ // Most tabs show the bare address. A coding-agent tab shows a prompt built
+ // around it, so step one is whatever that client asks for rather than a
+ // fixed string. Both go through the same copy path and the same event.
+ stepOneText (client) {
+ return client.step1Command ? client.step1Command(this.endpoint) : this.endpoint
+ },
+ copyStepOne (client) {
+ this.copyToClipboard(this.stepOneText(client))
.then(() => {
this.capture('cta-copy-mcp-endpoint', { position: this.activeClient })
alerts.emit('Copied to Clipboard.', 'confirmation')
@@ -330,6 +374,15 @@ export default {
color: var(--ff-color-text-default);
}
+// A sentence, not an address. Holding one line is right for something you read
+// left to right and paste, but a prompt sized to its whole length pushes out of
+// the modal, and the half you cannot see is the half saying what it does.
+.ai-connector__endpoint--wrap {
+ white-space: pre-wrap;
+ overflow-x: visible;
+ overflow-wrap: anywhere;
+}
+
@container (min-width: 640px) {
.ff-agent-panel {
grid-template-columns: repeat(3, minmax(0, 1fr));
diff --git a/frontend/src/components/icons/ai-agents/gemini.svg b/frontend/src/components/icons/ai-agents/gemini.svg
new file mode 100644
index 0000000000..4545c8331f
--- /dev/null
+++ b/frontend/src/components/icons/ai-agents/gemini.svg
@@ -0,0 +1,10 @@
+