mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-17 13:39:44 +02:00
feat(editor): Add Mistral Vibe to the MCP connect-client picker (#39183)
This commit is contained in:
parent
2a710313ff
commit
183d769841
|
|
@ -39,7 +39,7 @@ export type McpScope = (typeof MCP_INSTANCE_SCOPES)[number];
|
|||
export type McpClientType = 'cli' | 'ide' | 'editor' | 'assistant';
|
||||
|
||||
/** Known client brands, used by the FE to pick the logo shown next to a client. */
|
||||
export type McpClientBrandName = 'claude' | 'cursor' | 'vscode' | 'openai';
|
||||
export type McpClientBrandName = 'claude' | 'cursor' | 'vscode' | 'openai' | 'mistral';
|
||||
|
||||
/**
|
||||
* Client names are free-form (self-reported at OAuth registration), so known
|
||||
|
|
@ -59,6 +59,7 @@ export const MCP_CLIENT_BRAND_MATCHERS: ReadonlyArray<{
|
|||
{ pattern: /(visual studio code|vs ?code)/i, brand: 'vscode', type: 'editor' },
|
||||
{ pattern: /codex/i, brand: 'openai', type: 'cli' },
|
||||
{ pattern: /chatgpt|openai/i, brand: 'openai', type: 'assistant' },
|
||||
{ pattern: /mistral|\bvibe\b/i, brand: 'mistral', type: 'assistant' },
|
||||
];
|
||||
|
||||
export function getMcpClientType(clientName: string): McpClientType | null {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { defineTelemetryEvents } from '../define';
|
|||
* dialog's client slug is. Null when the name matches no known brand.
|
||||
*/
|
||||
const clientBrand = z
|
||||
.enum(['claude', 'cursor', 'vscode', 'openai'])
|
||||
.enum(['claude', 'cursor', 'vscode', 'openai', 'mistral'])
|
||||
.nullable()
|
||||
.describe('Client brand, mirroring MCP_CLIENT_BRAND_MATCHERS in @n8n/api-types');
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Mistral AI</title><path fill="#FFD800" d="M3.429 3.429h3.428v3.428H3.429zM17.143 3.429h3.428v3.428h-3.428z"/><path fill="#FFAF00" d="M3.429 6.857h6.857v3.429H3.429zM13.714 6.857h6.857v3.429h-6.857z"/><path fill="#FF8205" d="M3.429 10.286h17.142v3.428H3.429z"/><path fill="#FA500F" d="M3.429 13.714h3.428v3.429H3.429zM10.286 13.714h3.428v3.429h-3.428zM17.143 13.714h3.428v3.429h-3.428z"/><path fill="#E10500" d="M0 17.143h6.857v3.428H0zM10.286 17.143h3.428v3.428h-3.428zM17.143 17.143H24v3.428h-6.857z"/></svg>
|
||||
|
After Width: | Height: | Size: 588 B |
|
|
@ -12,6 +12,8 @@ describe('getClientBrand', () => {
|
|||
['Visual Studio Code', 'editor'],
|
||||
['Codex CLI', 'cli'],
|
||||
['ChatGPT', 'assistant'],
|
||||
['Mistral Vibe', 'assistant'],
|
||||
['Vibe', 'assistant'],
|
||||
['Some Unknown Client', null],
|
||||
])('derives the type of %s as %s', (name, type) => {
|
||||
expect(getClientBrand(name).type).toBe(type);
|
||||
|
|
@ -20,6 +22,7 @@ describe('getClientBrand', () => {
|
|||
it('resolves a logo for recognized brands and none for unknown clients', () => {
|
||||
expect(getClientBrand('Claude Code').icon).not.toBeNull();
|
||||
expect(getClientBrand('Cursor').icon).not.toBeNull();
|
||||
expect(getClientBrand('Mistral Vibe').icon).not.toBeNull();
|
||||
expect(getClientBrand('Some Unknown Client').icon).toBeNull();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import type { BaseTextKey } from '@n8n/i18n';
|
|||
|
||||
import ClaudeIcon from './assets/client-icons/claude.svg?component';
|
||||
import CursorIcon from './assets/client-icons/cursor.svg?component';
|
||||
import MistralIcon from './assets/client-icons/mistral.svg?component';
|
||||
import OpenAiIcon from './assets/client-icons/openai.svg?component';
|
||||
import VsCodeIcon from './assets/client-icons/vscode.svg?component';
|
||||
|
||||
|
|
@ -25,6 +26,7 @@ const BRAND_ICONS: Record<McpClientBrandName, Component> = {
|
|||
cursor: CursorIcon,
|
||||
vscode: VsCodeIcon,
|
||||
openai: OpenAiIcon,
|
||||
mistral: MistralIcon,
|
||||
};
|
||||
|
||||
// Client names are bounded (a user's own registered clients), so memoizing the
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ describe('getMcpClientCatalog', () => {
|
|||
expect(catalog.map((group) => group.id)).toEqual(['cli', 'web', 'ide']);
|
||||
expect(catalog.map((group) => group.clients.map((client) => client.id))).toEqual([
|
||||
['claude-code', 'codex', 'gemini-cli'],
|
||||
['claude-ai', 'chatgpt'],
|
||||
['claude-ai', 'chatgpt', 'mistral-vibe'],
|
||||
['cursor', 'vscode', 'windsurf'],
|
||||
]);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import ClaudeIcon from './assets/client-icons/claude.svg?component';
|
|||
import CodexIcon from './assets/client-icons/codex.svg?component';
|
||||
import CursorIcon from './assets/client-icons/cursor.svg?component';
|
||||
import GeminiIcon from './assets/client-icons/gemini.svg?component';
|
||||
import MistralIcon from './assets/client-icons/mistral.svg?component';
|
||||
import OpenAiIcon from './assets/client-icons/openai.svg?component';
|
||||
import VsCodeIcon from './assets/client-icons/vscode.svg?component';
|
||||
|
||||
|
|
@ -141,6 +142,13 @@ url = "${serverUrl}"`;
|
|||
addUrl:
|
||||
'https://chatgpt.com/plugins#settings/Connectors?create-connector=true&redirectAfter=%2Fplugins',
|
||||
},
|
||||
{
|
||||
id: 'mistral-vibe',
|
||||
name: 'Mistral Vibe',
|
||||
category: 'web',
|
||||
icon: MistralIcon,
|
||||
addUrl: 'https://chat.mistral.ai/connections/marketplace?search=n8n&template=n8n',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user