Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions docs/user/expert/third-party-agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ The same three steps, written out:

2. **Sign in.** FlowFuse uses OAuth, so your agent sends you to a FlowFuse login page. If your client asks for an OAuth client ID or secret, leave them blank; FlowFuse registers your client for you.

3. **Choose what the agent may do.** Signing in takes you to a FlowFuse authorization page. There you pick read-only or full access, scope it to all your teams or specific teams, and set an expiration date for the grant.
3. **Select teams and permissions.** Signing in takes you to a FlowFuse authorization page. There you choose which teams the agent can reach and the permissions it has in each, and set an expiration date for the grant.

Your agent is now connected. If your client does not support OAuth, use a token instead, see [clients without a sign-in flow](#clients-without-a-sign-in-flow).

Expand Down Expand Up @@ -70,13 +70,17 @@ Custom connectors live behind developer mode. Turn it on under **Settings**, the

### Claude

Where custom connectors are available on your plan, add one and enter the FlowFuse MCP address.
[Connect FlowFuse to Claude](https://claude.ai/directory/flowfuse) from the FlowFuse connector in Claude's directory, choose **Connect to Claude** and sign in.

For a self-hosted platform, where custom connectors are available on your plan, add one and enter your platform's MCP address.

On Team and Enterprise plans an owner adds the connector for the organisation first, then each person connects and signs in individually.

### Coding agents

A coding agent can add the connector to itself. Ask it, rather than editing its configuration by hand:
In Claude Code signed in with a Claude account, FlowFuse Cloud is already available as a connector. Run `/mcp`, open **Show unused connectors**, select FlowFuse and choose **Authenticate**.

With an API key, on self-hosted, or in another coding agent, ask the agent to add the connector to itself, 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.
Expand Down Expand Up @@ -110,13 +114,13 @@ The config format is the client's, not FlowFuse's. Two JSON shapes are common, o

Each FlowFuse tool carries its recommended usage and permissions, so a connected agent knows what it is for before calling it. Most MCP clients then ask you to confirm before running a tool. That prompt is the client's, not FlowFuse's, so its look and whether you can turn it off vary. FlowFuse Expert's own approval cards do not apply here.

What FlowFuse enforces on every call is your grant: the teams, and read-only or full access. Each tool carries the access it needs, and FlowFuse rejects a call whose tool reaches past your grant, whether the grant came from signing in or from a token's scope.
What FlowFuse enforces on every call is your grant: the teams and permissions you selected. Each tool carries the access it needs, and FlowFuse rejects a call whose tool reaches past your grant, whether the grant came from signing in or from a token's scope.

Actions an agent takes appear in the [audit log](/docs/user/logs/#ai-agents-and-api-activity), attributed to your account and marked as having come from a connected agent.

## If something is not working

**A change was refused.** The agent has read-only access. Re-connect it and grant full access.
**A change was refused.** The agent was not granted that permission. Re-connect it and select the permission it needs.

**The agent cannot reach a team.** That team was not included when you signed in. Re-connect and include it.

Expand Down
2 changes: 1 addition & 1 deletion docs/user/mcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,4 @@ Access comes at one of two levels:

With **FlowFuse Expert**, an agent acts with the same access you have on the team you are working in.

With **your own agent**, you choose the access when you connect. Signing in over OAuth takes you to a FlowFuse page where you pick read-only or full access, scope it to all your teams or specific teams, and set an expiration date. A personal access token, for clients without a sign-in flow, carries the same read-only or full-access choice.
With **your own agent**, you choose the access when you connect. Signing in over OAuth takes you to a FlowFuse page where you choose which teams the agent can reach and the permissions it has in each, and set an expiration date. A personal access token, for clients without a sign-in flow, carries the same choice of teams and permissions.
48 changes: 41 additions & 7 deletions frontend/src/components/dialogs/AiConnectorModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,19 @@
<p class="ff-agent-step__num">01</p>
<p class="ff-agent-step__title">{{ client.step1Title || 'Copy the FlowFuse connector URL' }}</p>
<p class="ff-agent-step__body">{{ client.step1Body || 'Paste it into your agent in the next step.' }}</p>
<div class="ff-agent-step__cta">
<div v-if="client.step1Url" class="ff-agent-step__cta">
<a
:href="client.step1Url"
class="ff-agent-step__link"
target="_blank"
rel="noopener"
@click="capture('cta-ai-open-client', { position: client.id })"
>
<span>{{ client.step1Label }}</span>
<ArrowTopRightOnSquareIcon class="ff-icon" />
</a>
</div>
<div v-else class="ff-agent-step__cta">
<div class="ai-connector__command">
<code class="ai-connector__endpoint" :class="{ 'ai-connector__endpoint--wrap': client.step1Command }">{{ stepOneText(client) }}</code>
<ff-button kind="primary" size="small" @click="copyStepOne(client)">
Expand All @@ -50,7 +62,7 @@
<p class="ff-agent-step__num">02</p>
<p class="ff-agent-step__title">{{ client.step2Title }}</p>
<p class="ff-agent-step__body">{{ client.step2Body }}</p>
<div class="ff-agent-step__cta">
<div v-if="client.step2Url" class="ff-agent-step__cta">
<a
:href="client.step2Url"
class="ff-agent-step__link"
Expand All @@ -66,8 +78,7 @@

<div class="ff-agent-step">
<p class="ff-agent-step__num">03</p>
<p class="ff-agent-step__title">Sign in and choose what it reaches</p>
<p class="ff-agent-step__body">Pick which teams it acts on, and whether it can edit or only read.</p>
<p class="ff-agent-step__title">Select teams and permissions</p>
</div>
</div>
</div>
Expand Down Expand Up @@ -106,6 +117,8 @@ import chatgptLogo from '../icons/ai-agents/chatgpt.svg'
import claudeLogo from '../icons/ai-agents/claude.svg'
import copilotLogo from '../icons/ai-agents/microsoft-copilot.svg'

const CLOUD_ENDPOINT = 'https://app.flowfuse.com/mcp'

const CLIENTS = [
{
id: 'claude',
Expand All @@ -114,7 +127,16 @@ const CLIENTS = [
step2Title: 'Add a custom connector',
step2Body: 'Paste the URL.',
step2Label: 'Open Claude',
step2Url: 'https://claude.ai/'
step2Url: 'https://claude.ai/',
cloud: {
step1Title: 'Open the FlowFuse connector',
step1Body: 'The official FlowFuse MCP connector is available in Claude.',
step1Label: 'Connect to Claude',
step1Url: 'https://claude.ai/directory/flowfuse',
step2Title: 'Choose Connect to Claude',
step2Body: 'Claude opens FlowFuse.',
step2Url: null
}
},
{
id: 'copilot',
Expand Down Expand Up @@ -148,7 +170,14 @@ const CLIENTS = [
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/'
step2Url: 'https://flowfuse.com/docs/user/expert/third-party-agents/',
cloud: {
step1Title: 'Open the MCP list',
step1Body: 'Run this in Claude Code.',
step1Command: () => '/mcp',
step2Title: 'Select FlowFuse and choose Authenticate',
step2Body: 'Find it under Show unused connectors.'
}
},
{
id: 'codex',
Expand Down Expand Up @@ -179,13 +208,18 @@ export default {
mixins: [clipboardMixin],
data () {
return {
clients: CLIENTS,
activeClient: CLIENTS[0].id
}
},
computed: {
endpoint () {
return `${window.location.origin}/mcp`
},
isCloud () {
return this.endpoint === CLOUD_ENDPOINT
},
clients () {
return CLIENTS.map(client => (this.isCloud && client.cloud) ? { ...client, ...client.cloud } : client)
}
},
methods: {
Expand Down
Loading