Skip to content

Commit 0e2488a

Browse files
fix: mcp server should use workspace persona first (#1530)
1 parent 60f255f commit 0e2488a

File tree

3 files changed

+29
-39
lines changed

3 files changed

+29
-39
lines changed

server/aws-lsp-codewhisperer/src/language-server/agenticChat/tools/mcp/mcpEventHandler.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1102,7 +1102,12 @@ export class McpEventHandler {
11021102
* @returns The persona path to use (workspace if exists, otherwise global)
11031103
*/
11041104
async #getPersonaPath(): Promise<string> {
1105-
// Get the global path as fallback
1105+
const allPermissions = McpManager.instance.getAllPermissions()
1106+
for (const [, permission] of allPermissions) {
1107+
if (permission.__configPath__) {
1108+
return permission.__configPath__
1109+
}
1110+
}
11061111
const globalPersonaPath = getGlobalPersonaConfigPath(this.#features.workspace.fs.getUserHomeDir())
11071112

11081113
// Get workspace folders and check for workspace persona path

server/aws-lsp-codewhisperer/src/language-server/agenticChat/tools/mcp/mcpManager.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,10 @@ export class McpManager {
344344
return new Map(this.mcpServers)
345345
}
346346

347+
public getAllPermissions(): Map<string, MCPServerPermission> {
348+
return new Map(this.mcpServerPermissions)
349+
}
350+
347351
/**
348352
* Map server names to their available tool names.
349353
*/

server/aws-lsp-codewhisperer/src/language-server/agenticChat/tools/mcp/mcpUtils.ts

Lines changed: 19 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -198,49 +198,43 @@ export async function loadPersonaPermissions(
198198
.filter(p => p !== globalPath)
199199

200200
const globalExists = await workspace.fs.exists(globalPath).catch(() => false)
201-
202-
// global first, then workspace
203-
const files = [...(globalExists ? [globalPath] : []), ...wsFiles]
204-
205-
const result = new Map<string, MCPServerPermission>()
206-
207-
// if none found, write default global persona and use it
208-
if (files.length === 0) {
201+
// use workspace files if they exist, otherwise fall back to global
202+
let selectedFile: string | undefined
203+
if (wsFiles.length > 0) {
204+
selectedFile = wsFiles[0]
205+
logging.info(`Using workspace persona file: ${selectedFile}`)
206+
} else if (globalExists) {
207+
selectedFile = globalPath
208+
logging.info(`Using global persona file: ${selectedFile}`)
209+
} else {
209210
await workspace.fs.mkdir(path.dirname(globalPath), { recursive: true })
210211
await workspace.fs
211212
.writeFile(globalPath, DEFAULT_PERSONA_RAW)
212213
.then(() => logging.info(`Created default persona file at ${globalPath}`))
213214
.catch(e => {
214215
logging.error(`Failed to create default persona file: ${e.message}`)
215216
})
216-
files.push(globalPath)
217-
logging.info(`Created default persona file at ${globalPath}`)
217+
selectedFile = globalPath
218+
logging.info(`Using newly created default persona file: ${selectedFile}`)
218219
}
219220

220-
// merge configs: later files override earlier ones
221-
let wsHasStar = false
222-
const wsEnabled = new Set<string>()
221+
// read all persona files, including global and workspace
222+
const result = new Map<string, MCPServerPermission>()
223223

224-
for (const file of files) {
225-
const isWorkspace = wsFiles.includes(file)
226-
logging.info(`Reading persona file ${file}`)
224+
if (selectedFile) {
227225
let cfg: PersonaConfig
228226
try {
229-
const raw = (await workspace.fs.readFile(file)).toString().trim()
227+
const raw = (await workspace.fs.readFile(selectedFile)).toString().trim()
230228
cfg = raw ? (JSON.parse(raw) as PersonaConfig) : { mcpServers: [], toolPerms: {} }
231229
} catch (err: any) {
232-
logging.warn(`Invalid Persona config in ${file}: ${err.message}`)
233-
continue
230+
logging.warn(`Invalid Persona config in ${selectedFile}: ${err.message}`)
231+
return result
234232
}
235233

236234
// enable servers listed under mcpServers
237235
const enabled = new Set(cfg['mcpServers'] ?? [])
238-
if (wsFiles.includes(file)) {
239-
if (enabled.has('*')) wsHasStar = true
240-
enabled.forEach(s => wsEnabled.add(s))
241-
}
242236
for (const name of enabled) {
243-
result.set(name, { enabled: true, toolPerms: {}, __configPath__: file })
237+
result.set(name, { enabled: true, toolPerms: {}, __configPath__: selectedFile })
244238
}
245239

246240
// Check if wildcard is present in mcpServers
@@ -252,27 +246,14 @@ export async function loadPersonaPermissions(
252246
if (hasWildcard || enabled.has(name)) {
253247
// Create entry for this server if it doesn't exist yet
254248
if (!result.has(name)) {
255-
result.set(name, { enabled: true, toolPerms: {}, __configPath__: file })
249+
result.set(name, { enabled: true, toolPerms: {}, __configPath__: selectedFile })
256250
}
257251

258252
const rec = result.get(name)!
259253
rec.toolPerms = perms as Record<string, McpPermissionType>
260-
} else if (isWorkspace && result.has(name)) {
261-
// server dropped from workspace mcpServers → remove it entirely
262-
result.delete(name)
263254
}
264255
}
265256
}
266-
267-
// workspace overrides global: global has '*' but workspace does not
268-
if (wsFiles.length > 0 && !wsHasStar) {
269-
// remove the global-level wildcard
270-
result.delete('*')
271-
// drop servers that were enabled only by the global '*'
272-
for (const [srv] of result) {
273-
if (srv !== '*' && !wsEnabled.has(srv)) result.delete(srv)
274-
}
275-
}
276257
const summary = [...result.entries()]
277258
.map(([srv, perm]) => {
278259
const tools = Object.keys(perm.toolPerms).length > 0 ? JSON.stringify(perm.toolPerms) : '{}'

0 commit comments

Comments
 (0)