Skip to content

Commit 300960c

Browse files
authored
feat: implement support for windows file detection (#27)
1 parent bdd206c commit 300960c

File tree

2 files changed

+53
-8
lines changed

2 files changed

+53
-8
lines changed

src/main.ts

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import fs from 'node:fs/promises'
2+
import { platform } from 'node:os'
23
import { MCPConfigLinterService } from './services/mcp-config-linter-service.ts'
34
import { MCPServerManagerService } from './services/mcp-server-manager-service.ts'
45

@@ -39,22 +40,40 @@ interface MCPFileGroupsResult {
3940
type MCPFilePathGroupsRecord = Record<string, MCPFileGroups>
4041
type MCPFileGroupsResultRecord = Record<string, MCPFileGroupsResult>
4142

43+
const osSpecificPaths: { [key: string]: MCPFilePath[] } = {
44+
claude: [],
45+
cursor: []
46+
}
47+
48+
if (platform() === 'win32') {
49+
osSpecificPaths['claude'] = [
50+
{ filePath: `${process.env.APPDATA}\\Claude\\claude_desktop_config.json`, type: 'global' }
51+
]
52+
osSpecificPaths['cursor'] = [
53+
{ filePath: `${process.env.HOME}\\.cursor\\mcp.json`, type: 'global' },
54+
{ filePath: '.cursor\\mcp.json', type: 'local' }
55+
]
56+
} else {
57+
osSpecificPaths['claude'] = [
58+
{ filePath: '~/Library/Application Support/Claude/claude_desktop_config.json', type: 'global' }
59+
]
60+
osSpecificPaths['cursor'] = [
61+
{ filePath: '~/.cursor/mcp.json', type: 'global' },
62+
{ filePath: '.cursor/mcp.json', type: 'local' }
63+
]
64+
}
65+
4266
export class MCPFiles {
4367
private mcpFilePathGroups: MCPFilePathGroupsRecord = {
4468
claude: {
4569
name: 'claude-desktop',
4670
friendlyName: 'Claude Desktop',
47-
paths: [
48-
{ filePath: '~/Library/Application Support/Claude/claude_desktop_config.json', type: 'global' },
49-
]
71+
paths: osSpecificPaths['claude']
5072
},
5173
cursor: {
5274
name: 'cursor',
5375
friendlyName: 'Cursor',
54-
paths: [
55-
{ filePath: '~/.cursor/mcp.json', type: 'global' },
56-
{ filePath: '.cursor/mcp.json', type: 'local' },
57-
]
76+
paths: osSpecificPaths['cursor']
5877
}
5978
}
6079

src/services/mcp-server-manager-service.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,34 @@ export class MCPServerManagerService {
112112

113113
// Then iterate the map to check for matches
114114
let mcpServerDetection: MatchedProcess | undefined
115+
115116
for (const [pid, processData] of processMap) {
116-
if (this.isCommandMatch(processData.commandTokens, pid, processData.ppid)) {
117+
const commandMatchLinux = this.isCommandMatch(processData.commandTokens, pid, processData.ppid)
118+
let commandMatchWin32 = false
119+
if (platform() === 'win32') {
120+
// for Windows, we need to change commandTokens to also match another pattern
121+
// where the command starts with `cmd` then follows potentially several command-line
122+
// flags like /c /d and then the actual command.
123+
// This is because Claude Desktop on Windows automatically starts MCP Servers like that
124+
// even if the command specified in the MCP config is just `uvx` or `npx`.
125+
126+
let commandTokensOnWin32 = processData.commandTokens
127+
if (commandTokensOnWin32.length > 0 && commandTokensOnWin32[0].toLowerCase().startsWith('cmd')) {
128+
// If the first token is 'cmd', we need to skip it and check the next tokens
129+
commandTokensOnWin32 = commandTokensOnWin32.slice(1)
130+
131+
// Skip any additional flags like /c, /d, etc.
132+
while (commandTokensOnWin32.length > 0 && commandTokensOnWin32[0].startsWith('/')) {
133+
commandTokensOnWin32 = commandTokensOnWin32.slice(1)
134+
}
135+
}
136+
137+
commandMatchWin32 = this.isCommandMatch(commandTokensOnWin32, pid, processData.ppid)
138+
}
139+
140+
const commandMatch = commandMatchLinux || commandMatchWin32
141+
142+
if (commandMatch) {
117143
mcpServerDetection = {
118144
pid,
119145
commandLine: processData.commandTokens.join(' '),

0 commit comments

Comments
 (0)