Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAdapters.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { VSBuffer } from '../../../../../base/common/buffer.js';
7
import { Platform } from '../../../../../base/common/platform.js';
8
import { Mutable } from '../../../../../base/common/types.js';
9
import { URI } from '../../../../../base/common/uri.js';
10
import { INativeMcpDiscoveryData } from '../../../../../platform/mcp/common/nativeMcpDiscoveryHelper.js';
11
import { DiscoverySource } from '../mcpConfiguration.js';
12
import { McpCollectionSortOrder, McpServerDefinition, McpServerLaunch, McpServerTransportType } from '../mcpTypes.js';
13
14
export interface NativeMpcDiscoveryAdapter {
15
readonly remoteAuthority: string | null;
16
readonly id: string;
17
readonly order: number;
18
readonly discoverySource: DiscoverySource;
19
20
getFilePath(details: INativeMcpDiscoveryData): URI | undefined;
21
adaptFile(contents: VSBuffer, details: INativeMcpDiscoveryData): Promise<McpServerDefinition[] | undefined>;
22
}
23
24
export async function claudeConfigToServerDefinition(idPrefix: string, contents: VSBuffer, cwd?: URI) {
25
let parsed: {
26
mcpServers: Record<string, {
27
command: string;
28
args?: string[];
29
env?: Record<string, string>;
30
url?: string;
31
}>;
32
};
33
34
try {
35
parsed = JSON.parse(contents.toString());
36
} catch {
37
return;
38
}
39
40
return Promise.all(Object.entries(parsed.mcpServers).map(async ([name, server]): Promise<Mutable<McpServerDefinition>> => {
41
const launch: McpServerLaunch = server.url ? {
42
type: McpServerTransportType.HTTP,
43
uri: URI.parse(server.url),
44
headers: [],
45
} : {
46
type: McpServerTransportType.Stdio,
47
args: server.args || [],
48
command: server.command,
49
env: server.env || {},
50
envFile: undefined,
51
cwd: cwd?.fsPath,
52
};
53
54
return {
55
id: `${idPrefix}.${name}`,
56
label: name,
57
launch,
58
cacheNonce: await McpServerLaunch.hash(launch),
59
};
60
}));
61
}
62
63
export class ClaudeDesktopMpcDiscoveryAdapter implements NativeMpcDiscoveryAdapter {
64
public id: string;
65
public readonly order = McpCollectionSortOrder.Filesystem;
66
public readonly discoverySource: DiscoverySource = DiscoverySource.ClaudeDesktop;
67
68
constructor(public readonly remoteAuthority: string | null) {
69
this.id = `claude-desktop.${this.remoteAuthority}`;
70
}
71
72
getFilePath({ platform, winAppData, xdgHome, homedir }: INativeMcpDiscoveryData): URI | undefined {
73
if (platform === Platform.Windows) {
74
const appData = winAppData || URI.joinPath(homedir, 'AppData', 'Roaming');
75
return URI.joinPath(appData, 'Claude', 'claude_desktop_config.json');
76
} else if (platform === Platform.Mac) {
77
return URI.joinPath(homedir, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
78
} else {
79
const configDir = xdgHome || URI.joinPath(homedir, '.config');
80
return URI.joinPath(configDir, 'Claude', 'claude_desktop_config.json');
81
}
82
}
83
84
adaptFile(contents: VSBuffer, { homedir }: INativeMcpDiscoveryData): Promise<McpServerDefinition[] | undefined> {
85
return claudeConfigToServerDefinition(this.id, contents, homedir);
86
}
87
}
88
89
export class WindsurfDesktopMpcDiscoveryAdapter extends ClaudeDesktopMpcDiscoveryAdapter {
90
public override readonly discoverySource: DiscoverySource = DiscoverySource.Windsurf;
91
92
constructor(remoteAuthority: string | null) {
93
super(remoteAuthority);
94
this.id = `windsurf.${this.remoteAuthority}`;
95
}
96
97
override getFilePath({ homedir }: INativeMcpDiscoveryData): URI | undefined {
98
return URI.joinPath(homedir, '.codeium', 'windsurf', 'mcp_config.json');
99
}
100
}
101
102
export class CursorDesktopMpcDiscoveryAdapter extends ClaudeDesktopMpcDiscoveryAdapter {
103
public override readonly discoverySource: DiscoverySource = DiscoverySource.CursorGlobal;
104
105
constructor(remoteAuthority: string | null) {
106
super(remoteAuthority);
107
this.id = `cursor.${this.remoteAuthority}`;
108
}
109
110
override getFilePath({ homedir }: INativeMcpDiscoveryData): URI | undefined {
111
return URI.joinPath(homedir, '.cursor', 'mcp.json');
112
}
113
}
114
115