@n8n/frontend-module-mcp 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE_EE.md +27 -0
- package/package.json +23 -14
- package/src/assets/client-icons/antigravity.svg +1 -0
- package/src/assets/client-icons/devin.svg +1 -0
- package/src/components/MCPWorkflowsSelect.test.ts +13 -8
- package/src/components/McpConnectClientDialog.test.ts +44 -0
- package/src/components/McpConnectClientDialog.vue +11 -1
- package/src/mcp.clients.catalog.test.ts +18 -1
- package/src/mcp.clients.catalog.ts +26 -9
- package/src/mcp.module.ts +1 -0
package/LICENSE_EE.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# The n8n Enterprise License (the “Enterprise License”)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022-present n8n GmbH.
|
|
4
|
+
|
|
5
|
+
With regard to the n8n Software:
|
|
6
|
+
|
|
7
|
+
This software and associated documentation files (the "Software") may only be used in production, if
|
|
8
|
+
you (and any entity that you represent) hold a valid n8n Enterprise license corresponding to your
|
|
9
|
+
usage. Subject to the foregoing sentence, you are free to modify this Software and publish patches
|
|
10
|
+
to the Software. You agree that n8n and/or its licensors (as applicable) retain all right, title and
|
|
11
|
+
interest in and to all such modifications and/or patches, and all such modifications and/or patches
|
|
12
|
+
may only be used, copied, modified, displayed, distributed, or otherwise exploited with a valid n8n
|
|
13
|
+
Enterprise license for the corresponding usage. Notwithstanding the foregoing, you may copy and
|
|
14
|
+
modify the Software for development and testing purposes, without requiring a subscription. You
|
|
15
|
+
agree that n8n and/or its licensors (as applicable) retain all right, title and interest in and to
|
|
16
|
+
all such modifications. You are not granted any other rights beyond what is expressly stated herein.
|
|
17
|
+
Subject to the foregoing, it is forbidden to copy, merge, publish, distribute, sublicense, and/or
|
|
18
|
+
sell the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
|
21
|
+
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
22
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
|
23
|
+
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
24
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
25
|
+
|
|
26
|
+
For all third party components incorporated into the n8n Software, those components are licensed
|
|
27
|
+
under the original license provided by the owner of the applicable component.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@n8n/frontend-module-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"exports": {
|
|
@@ -8,20 +8,20 @@
|
|
|
8
8
|
"./mcp.module": "./src/mcp.module.ts"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@n8n/api-types": "1.
|
|
12
|
-
"@n8n/composables": "1.
|
|
13
|
-
"@n8n/design-system": "2.
|
|
14
|
-
"@n8n/frontend-constants": "0.
|
|
15
|
-
"@n8n/frontend-module-sdk": "0.
|
|
16
|
-
"@n8n/i18n": "2.
|
|
17
|
-
"@n8n/permissions": "0.
|
|
18
|
-
"@n8n/rest-api-client": "2.
|
|
19
|
-
"@n8n/stores": "2.
|
|
20
|
-
"@n8n/telemetry": "1.
|
|
21
|
-
"@n8n/utils": "1.
|
|
11
|
+
"@n8n/api-types": "1.44.0",
|
|
12
|
+
"@n8n/composables": "1.34.0",
|
|
13
|
+
"@n8n/design-system": "2.43.0",
|
|
14
|
+
"@n8n/frontend-constants": "0.10.0",
|
|
15
|
+
"@n8n/frontend-module-sdk": "0.14.0",
|
|
16
|
+
"@n8n/i18n": "2.44.0",
|
|
17
|
+
"@n8n/permissions": "0.81.0",
|
|
18
|
+
"@n8n/rest-api-client": "2.44.0",
|
|
19
|
+
"@n8n/stores": "2.44.0",
|
|
20
|
+
"@n8n/telemetry": "1.12.0",
|
|
21
|
+
"@n8n/utils": "1.51.0",
|
|
22
22
|
"element-plus": "2.4.3",
|
|
23
23
|
"lodash": "4.18.1",
|
|
24
|
-
"n8n-workflow": "2.
|
|
24
|
+
"n8n-workflow": "2.44.0",
|
|
25
25
|
"pinia": "^2.2.4",
|
|
26
26
|
"reka-ui": "^2.5.0",
|
|
27
27
|
"vue": "^3.5.13",
|
|
@@ -55,7 +55,16 @@
|
|
|
55
55
|
"vitest-mock-extended": "^3.1.0",
|
|
56
56
|
"vue-tsc": "^2.2.8"
|
|
57
57
|
},
|
|
58
|
-
"license": "
|
|
58
|
+
"license": "SEE LICENSE IN LICENSE.md",
|
|
59
|
+
"homepage": "https://n8n.io",
|
|
60
|
+
"author": {
|
|
61
|
+
"name": "Jan Oberhauser",
|
|
62
|
+
"email": "jan@n8n.io"
|
|
63
|
+
},
|
|
64
|
+
"repository": {
|
|
65
|
+
"type": "git",
|
|
66
|
+
"url": "git+https://github.com/n8n-io/n8n.git"
|
|
67
|
+
},
|
|
59
68
|
"scripts": {
|
|
60
69
|
"clean": "rimraf .turbo",
|
|
61
70
|
"typecheck": "vue-tsc --noEmit",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Antigravity</title><mask height="23" id="antigravity-mask" maskUnits="userSpaceOnUse" width="24" x="0" y="1"><path d="M21.751 22.607c1.34 1.005 3.35.335 1.508-1.508C17.73 15.74 18.904 1 12.037 1 5.17 1 6.342 15.74.815 21.1c-2.01 2.009.167 2.511 1.507 1.506 5.192-3.517 4.857-9.714 9.715-9.714 4.857 0 4.522 6.197 9.714 9.715z" fill="#fff"/></mask><g mask="url(#antigravity-mask)"><g filter="url(#antigravity-blur-1)"><path d="M-1.018-3.992c-.408 3.591 2.686 6.89 6.91 7.37 4.225.48 7.98-2.043 8.387-5.633.408-3.59-2.686-6.89-6.91-7.37-4.225-.479-7.98 2.043-8.387 5.633z" fill="#FFE432"/></g><g filter="url(#antigravity-blur-2)"><path d="M15.269 7.747c1.058 4.557 5.691 7.374 10.348 6.293 4.657-1.082 7.575-5.653 6.516-10.21-1.058-4.556-5.691-7.374-10.348-6.292-4.657 1.082-7.575 5.653-6.516 10.21z" fill="#FC413D"/></g><g filter="url(#antigravity-blur-3)"><path d="M-12.443 10.804c1.338 4.703 7.36 7.11 13.453 5.378 6.092-1.733 9.947-6.95 8.61-11.652C8.282-.173 2.26-2.58-3.833-.848-9.925.884-13.78 6.1-12.443 10.804z" fill="#00B95C"/></g><g filter="url(#antigravity-blur-4)"><path d="M-12.443 10.804c1.338 4.703 7.36 7.11 13.453 5.378 6.092-1.733 9.947-6.95 8.61-11.652C8.282-.173 2.26-2.58-3.833-.848-9.925.884-13.78 6.1-12.443 10.804z" fill="#00B95C"/></g><g filter="url(#antigravity-blur-5)"><path d="M-7.608 14.703c3.352 3.424 9.126 3.208 12.896-.483 3.77-3.69 4.108-9.459.756-12.883C2.69-2.087-3.083-1.871-6.853 1.82c-3.77 3.69-4.108 9.458-.755 12.883z" fill="#00B95C"/></g><g filter="url(#antigravity-blur-6)"><path d="M9.932 27.617c1.04 4.482 5.384 7.303 9.7 6.3 4.316-1.002 6.971-5.448 5.93-9.93-1.04-4.483-5.384-7.304-9.7-6.301-4.316 1.002-6.971 5.448-5.93 9.93z" fill="#3186FF"/></g><g filter="url(#antigravity-blur-7)"><path d="M2.572-8.185C.392-3.329 2.778 2.472 7.9 4.771c5.122 2.3 11.042.227 13.222-4.63 2.18-4.855-.205-10.656-5.327-12.955-5.122-2.3-11.042-.227-13.222 4.63z" fill="#FBBC04"/></g><g filter="url(#antigravity-blur-8)"><path d="M-3.267 38.686c-5.277-2.072 3.742-19.117 5.984-24.83 2.243-5.712 8.34-8.664 13.616-6.592 5.278 2.071 11.533 13.482 9.29 19.195-2.242 5.713-23.613 14.298-28.89 12.227z" fill="#3186FF"/></g><g filter="url(#antigravity-blur-9)"><path d="M28.71 17.471c-1.413 1.649-5.1.808-8.236-1.878-3.135-2.687-4.531-6.201-3.118-7.85 1.412-1.649 5.1-.808 8.235 1.878s4.532 6.2 3.119 7.85z" fill="#749BFF"/></g><g filter="url(#antigravity-blur-10)"><path d="M18.163 9.077c5.81 3.93 12.502 4.19 14.946.577 2.443-3.612-.287-9.727-6.098-13.658-5.81-3.931-12.502-4.19-14.946-.577-2.443 3.612.287 9.727 6.098 13.658z" fill="#FC413D"/></g><g filter="url(#antigravity-blur-11)"><path d="M-.915 2.684c-1.44 3.473-.97 6.967 1.05 7.804 2.02.837 4.824-1.3 6.264-4.772 1.44-3.473.97-6.967-1.05-7.804-2.02-.837-4.824 1.3-6.264 4.772z" fill="#FFEE48"/></g></g><defs><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="17.587" id="antigravity-blur-1" width="19.838" x="-3.288" y="-11.917"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="1.117"/></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="38.565" id="antigravity-blur-2" width="38.9" x="4.251" y="-13.493"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="5.4"/></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="36.517" id="antigravity-blur-3" width="40.955" x="-21.889" y="-10.592"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="4.591"/></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="36.517" id="antigravity-blur-4" width="40.955" x="-21.889" y="-10.592"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="4.591"/></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="36.595" id="antigravity-blur-5" width="36.632" x="-19.099" y="-10.278"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="4.591"/></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="34.087" id="antigravity-blur-6" width="33.533" x=".981" y="8.758"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="4.363"/></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="35.276" id="antigravity-blur-7" width="35.978" x="-6.143" y="-21.659"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="3.954"/></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="46.523" id="antigravity-blur-8" width="45.114" x="-11.96" y="-.46"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="3.531"/></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="24.054" id="antigravity-blur-9" width="25.094" x="10.485" y=".58"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="3.159"/></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="30.007" id="antigravity-blur-10" width="33.508" x="5.833" y="-12.467"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="2.669"/></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="26.151" id="antigravity-blur-11" width="22.194" x="-8.355" y="-8.876"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="3.303"/></filter></defs></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="#000000" role="img" viewBox="49 48 329 329" xmlns="http://www.w3.org/2000/svg"><title>Devin</title><path d="M70 159.333V91.3471C70 88.3592 71.594 85.5983 74.1816 84.1044L133.043 50.1205C135.631 48.6265 138.819 48.6265 141.407 50.1205L200.269 84.1044C202.856 85.5983 204.45 88.3592 204.45 91.3471V126.068C204.708 137.606 210.806 148.734 221.531 154.926C232.256 161.117 244.942 160.834 255.063 155.289L285.132 137.929C287.719 136.435 290.907 136.435 293.495 137.929L352.357 171.913C354.944 173.406 356.538 176.167 356.538 179.155V247.123C356.538 250.111 354.944 252.872 352.357 254.366L293.495 288.35C290.907 289.844 287.719 289.844 285.132 288.35L255.306 271.13C245.146 265.456 232.344 265.117 221.534 271.358C210.809 277.55 204.711 288.678 204.453 300.215V334.926C204.453 337.914 202.859 340.675 200.271 342.169L141.41 376.153C138.822 377.647 135.634 377.647 133.046 376.153L74.1845 342.169C71.5969 340.675 70.0028 337.914 70.0028 334.926V266.959C70.0029 263.971 71.5969 261.21 74.1845 259.716L133.046 225.732C135.634 224.238 138.822 224.238 141.41 225.732L171.547 243.132C181.656 248.638 194.306 248.906 205.005 242.729C215.815 236.488 221.922 225.231 222.088 213.595C221.83 202.057 215.732 189.737 205.008 183.545C194.283 177.353 181.597 177.636 171.476 183.181L141.269 200.72C138.67 202.229 135.461 202.228 132.864 200.716L74.1576 166.562C71.5835 165.065 70 162.311 70 159.333Z"/></svg>
|
|
@@ -155,21 +155,26 @@ describe('MCPWorkflowsSelect', () => {
|
|
|
155
155
|
data: [],
|
|
156
156
|
});
|
|
157
157
|
|
|
158
|
-
const {
|
|
159
|
-
await nextTick();
|
|
158
|
+
const { getAllByRole, findByRole, emitted } = createComponent({ pinia });
|
|
160
159
|
|
|
161
|
-
//
|
|
160
|
+
// The ready event follows the loading indicator delay.
|
|
162
161
|
await waitFor(() => {
|
|
163
|
-
expect(
|
|
162
|
+
expect(emitted('ready')).toHaveLength(1);
|
|
164
163
|
});
|
|
165
164
|
|
|
166
|
-
const
|
|
167
|
-
|
|
165
|
+
const [input] = getAllByRole('combobox').filter(
|
|
166
|
+
(combobox) => !combobox.hasAttribute('readonly'),
|
|
167
|
+
);
|
|
168
|
+
expect(input).toHaveAttribute('aria-expanded', 'false');
|
|
169
|
+
await userEvent.click(input);
|
|
168
170
|
|
|
169
171
|
await waitFor(() => {
|
|
170
|
-
|
|
171
|
-
expect(emptyText).toBeInTheDocument();
|
|
172
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
172
173
|
});
|
|
174
|
+
|
|
175
|
+
const emptyOption = await findByRole('option', { name: 'No available workflows' });
|
|
176
|
+
expect(emptyOption).toBeVisible();
|
|
177
|
+
expect(emptyOption).toHaveAttribute('aria-disabled', 'true');
|
|
173
178
|
});
|
|
174
179
|
});
|
|
175
180
|
|
|
@@ -69,6 +69,50 @@ describe('McpConnectClientDialog', () => {
|
|
|
69
69
|
expect(body().queryByText('Authenticate')).not.toBeInTheDocument();
|
|
70
70
|
});
|
|
71
71
|
|
|
72
|
+
it('should show the shared Antigravity config file and entry', async () => {
|
|
73
|
+
renderComponent({ pinia });
|
|
74
|
+
|
|
75
|
+
await waitFor(() => {
|
|
76
|
+
expect(body().getByTestId('mcp-connect-client-picker-trigger')).toBeInTheDocument();
|
|
77
|
+
});
|
|
78
|
+
await userEvent.click(body().getByTestId('mcp-connect-client-picker-trigger'));
|
|
79
|
+
const menuLabel = await body().findByText('Antigravity');
|
|
80
|
+
expect(
|
|
81
|
+
menuLabel.closest('[role="menuitem"]')?.querySelector('svg.brand-icon'),
|
|
82
|
+
).toBeInTheDocument();
|
|
83
|
+
await userEvent.click(menuLabel);
|
|
84
|
+
|
|
85
|
+
expect(
|
|
86
|
+
body().getByTestId('mcp-connect-client-picker-trigger').querySelector('svg.brand-icon'),
|
|
87
|
+
).toBeInTheDocument();
|
|
88
|
+
expect(body().getByText(/~\/\.gemini\/config\/mcp_config\.json/)).toHaveTextContent(
|
|
89
|
+
'IDE, desktop app, and CLI (agy) share this file',
|
|
90
|
+
);
|
|
91
|
+
expect(body().getByTestId('mcp-config-snippet')).toHaveTextContent('mcpServers');
|
|
92
|
+
expect(body().getByTestId('mcp-config-snippet')).toHaveTextContent('serverUrl');
|
|
93
|
+
expect(body().queryByTestId('mcp-connect-one-click')).not.toBeInTheDocument();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should show the shared Devin config file and entry', async () => {
|
|
97
|
+
renderComponent({ pinia });
|
|
98
|
+
|
|
99
|
+
await waitFor(() => {
|
|
100
|
+
expect(body().getByTestId('mcp-connect-client-picker-trigger')).toBeInTheDocument();
|
|
101
|
+
});
|
|
102
|
+
await userEvent.click(body().getByTestId('mcp-connect-client-picker-trigger'));
|
|
103
|
+
const menuLabel = await body().findByText('Devin');
|
|
104
|
+
expect(
|
|
105
|
+
menuLabel.closest('[role="menuitem"]')?.querySelector('svg.brand-icon'),
|
|
106
|
+
).toBeInTheDocument();
|
|
107
|
+
await userEvent.click(menuLabel);
|
|
108
|
+
|
|
109
|
+
expect(body().getByText(/~\/\.config\/devin\/mcp_config\.json/)).toHaveTextContent(
|
|
110
|
+
'Devin desktop app and CLI share this file',
|
|
111
|
+
);
|
|
112
|
+
expect(body().getByTestId('mcp-config-snippet')).toHaveTextContent('"transport": "http"');
|
|
113
|
+
expect(body().queryByTestId('mcp-connect-one-click')).not.toBeInTheDocument();
|
|
114
|
+
});
|
|
115
|
+
|
|
72
116
|
it('should show only the server URL (no one-click) for web clients without a connector URL', async () => {
|
|
73
117
|
renderComponent({ pinia });
|
|
74
118
|
|
|
@@ -134,6 +134,16 @@ const addButtonLabel = computed(() =>
|
|
|
134
134
|
interpolate: { client: activeClient.value?.name ?? '' },
|
|
135
135
|
}),
|
|
136
136
|
);
|
|
137
|
+
const sharedConfigFileDescriptionKeys: Partial<Record<string, BaseTextKey>> = {
|
|
138
|
+
antigravity: 'settings.mcp.connectDialog.configure.antigravity.description',
|
|
139
|
+
devin: 'settings.mcp.connectDialog.configure.devin.description',
|
|
140
|
+
};
|
|
141
|
+
const configureDescription = computed(() =>
|
|
142
|
+
i18n.baseText(
|
|
143
|
+
sharedConfigFileDescriptionKeys[activeClient.value?.id ?? ''] ??
|
|
144
|
+
'settings.mcp.connectDialog.configure.description',
|
|
145
|
+
),
|
|
146
|
+
);
|
|
137
147
|
const serverUrlDescription = computed(() =>
|
|
138
148
|
i18n.baseText('settings.mcp.connectDialog.serverUrl.description', {
|
|
139
149
|
interpolate: { client: activeClient.value?.name ?? '' },
|
|
@@ -354,7 +364,7 @@ const serverUrlDescription = computed(() =>
|
|
|
354
364
|
layout="vertical"
|
|
355
365
|
:show-divider="false"
|
|
356
366
|
:title="i18n.baseText('settings.mcp.connectDialog.configure.title')"
|
|
357
|
-
:description="
|
|
367
|
+
:description="configureDescription"
|
|
358
368
|
>
|
|
359
369
|
<template #action>
|
|
360
370
|
<McpConfigSnippet
|
|
@@ -11,10 +11,27 @@ describe('getMcpClientCatalog', () => {
|
|
|
11
11
|
expect(catalog.map((group) => group.clients.map((client) => client.id))).toEqual([
|
|
12
12
|
['claude-code', 'codex', 'gemini-cli'],
|
|
13
13
|
['claude-ai', 'chatgpt', 'mistral-vibe'],
|
|
14
|
-
['cursor', '
|
|
14
|
+
['antigravity', 'cursor', 'devin', 'vscode'],
|
|
15
15
|
]);
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
+
it('should give Antigravity an HTTP server entry and keep Gemini CLI available', () => {
|
|
19
|
+
const antigravity = clients.find((client) => client.id === 'antigravity');
|
|
20
|
+
expect(JSON.parse(antigravity!.configSnippet!)).toEqual({
|
|
21
|
+
mcpServers: { n8n: { serverUrl: SERVER_URL } },
|
|
22
|
+
});
|
|
23
|
+
expect(clients.find((client) => client.id === 'gemini-cli')?.installCommand).toContain(
|
|
24
|
+
'gemini mcp add',
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should give Devin a streamable HTTP server entry', () => {
|
|
29
|
+
const devin = clients.find((client) => client.id === 'devin');
|
|
30
|
+
expect(JSON.parse(devin!.configSnippet!)).toEqual({
|
|
31
|
+
mcpServers: { n8n: { url: SERVER_URL, transport: 'http' } },
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
18
35
|
it('should embed the server URL in every install command and config snippet', () => {
|
|
19
36
|
for (const client of clients) {
|
|
20
37
|
if (client.installCommand) expect(client.installCommand).toContain(SERVER_URL);
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { Component } from 'vue';
|
|
2
2
|
|
|
3
|
+
import AntigravityIcon from './assets/client-icons/antigravity.svg?component';
|
|
3
4
|
import ClaudeIcon from './assets/client-icons/claude.svg?component';
|
|
4
5
|
import CodexIcon from './assets/client-icons/codex.svg?component';
|
|
5
6
|
import CursorIcon from './assets/client-icons/cursor.svg?component';
|
|
7
|
+
import DevinIcon from './assets/client-icons/devin.svg?component';
|
|
6
8
|
import GeminiIcon from './assets/client-icons/gemini.svg?component';
|
|
7
9
|
import MistralIcon from './assets/client-icons/mistral.svg?component';
|
|
8
10
|
import OpenAiIcon from './assets/client-icons/openai.svg?component';
|
|
@@ -15,7 +17,7 @@ export interface McpClientSetup {
|
|
|
15
17
|
/** Brand name, not translatable. */
|
|
16
18
|
name: string;
|
|
17
19
|
category: McpSetupCategory;
|
|
18
|
-
/** Brand mark; null falls back to the neutral MCP icon
|
|
20
|
+
/** Brand mark; null falls back to the neutral MCP icon. */
|
|
19
21
|
icon: Component | null;
|
|
20
22
|
installCommand?: string;
|
|
21
23
|
/** Snippet for the client's MCP config file (JSON, or TOML for Codex). */
|
|
@@ -80,7 +82,15 @@ url = "${serverUrl}"`;
|
|
|
80
82
|
}
|
|
81
83
|
}
|
|
82
84
|
}`;
|
|
83
|
-
const
|
|
85
|
+
const serverUrlSnippet = `{\n "mcpServers": {\n "n8n": {\n "serverUrl": "${serverUrl}"\n }\n }\n}`;
|
|
86
|
+
const devinSnippet = `{
|
|
87
|
+
"mcpServers": {
|
|
88
|
+
"n8n": {
|
|
89
|
+
"url": "${serverUrl}",
|
|
90
|
+
"transport": "http"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}`;
|
|
84
94
|
|
|
85
95
|
// One-click deep links, exactly as each editor expects: Cursor takes base64 of
|
|
86
96
|
// `{"url": …}` in a `config` query param, VS Code a URL-encoded JSON object.
|
|
@@ -154,6 +164,13 @@ url = "${serverUrl}"`;
|
|
|
154
164
|
{
|
|
155
165
|
id: 'ide',
|
|
156
166
|
clients: [
|
|
167
|
+
{
|
|
168
|
+
id: 'antigravity',
|
|
169
|
+
name: 'Antigravity',
|
|
170
|
+
category: 'ide',
|
|
171
|
+
icon: AntigravityIcon,
|
|
172
|
+
configSnippet: serverUrlSnippet,
|
|
173
|
+
},
|
|
157
174
|
{
|
|
158
175
|
id: 'cursor',
|
|
159
176
|
name: 'Cursor',
|
|
@@ -162,6 +179,13 @@ url = "${serverUrl}"`;
|
|
|
162
179
|
deepLink: cursorDeepLink,
|
|
163
180
|
configSnippet: cursorSnippet,
|
|
164
181
|
},
|
|
182
|
+
{
|
|
183
|
+
id: 'devin',
|
|
184
|
+
name: 'Devin',
|
|
185
|
+
category: 'ide',
|
|
186
|
+
icon: DevinIcon,
|
|
187
|
+
configSnippet: devinSnippet,
|
|
188
|
+
},
|
|
165
189
|
{
|
|
166
190
|
id: 'vscode',
|
|
167
191
|
name: 'VS Code',
|
|
@@ -170,13 +194,6 @@ url = "${serverUrl}"`;
|
|
|
170
194
|
deepLink: vscodeDeepLink,
|
|
171
195
|
configSnippet: vscodeSnippet,
|
|
172
196
|
},
|
|
173
|
-
{
|
|
174
|
-
id: 'windsurf',
|
|
175
|
-
name: 'Windsurf',
|
|
176
|
-
category: 'ide',
|
|
177
|
-
icon: null,
|
|
178
|
-
configSnippet: windsurfSnippet,
|
|
179
|
-
},
|
|
180
197
|
],
|
|
181
198
|
},
|
|
182
199
|
];
|