mirror of
https://gitea.toothfairyai.com/ToothFairyAI/tf_code.git
synced 2026-04-03 07:33:45 +00:00
feat: add per-project MCP config overrides (#5406)
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
This commit is contained in:
@@ -135,6 +135,11 @@ export namespace MCP {
|
||||
// Prompt cache types
|
||||
type PromptInfo = Awaited<ReturnType<MCPClient["listPrompts"]>>["prompts"][number]
|
||||
|
||||
type McpEntry = NonNullable<Config.Info["mcp"]>[string]
|
||||
function isMcpConfigured(entry: McpEntry): entry is Config.Mcp {
|
||||
return typeof entry === "object" && entry !== null && "type" in entry
|
||||
}
|
||||
|
||||
const state = Instance.state(
|
||||
async () => {
|
||||
const cfg = await Config.get()
|
||||
@@ -144,6 +149,11 @@ export namespace MCP {
|
||||
|
||||
await Promise.all(
|
||||
Object.entries(config).map(async ([key, mcp]) => {
|
||||
if (!isMcpConfigured(mcp)) {
|
||||
log.error("Ignoring MCP config entry without type", { key })
|
||||
return
|
||||
}
|
||||
|
||||
// If disabled by config, mark as disabled without trying to connect
|
||||
if (mcp.enabled === false) {
|
||||
status[key] = { status: "disabled" }
|
||||
@@ -237,6 +247,7 @@ export namespace MCP {
|
||||
status: { status: "disabled" as const },
|
||||
}
|
||||
}
|
||||
|
||||
log.info("found", { key, type: mcp.type })
|
||||
let mcpClient: MCPClient | undefined
|
||||
let status: Status | undefined = undefined
|
||||
@@ -434,8 +445,9 @@ export namespace MCP {
|
||||
const config = cfg.mcp ?? {}
|
||||
const result: Record<string, Status> = {}
|
||||
|
||||
// Include all MCPs from config, not just connected ones
|
||||
for (const key of Object.keys(config)) {
|
||||
// Include all configured MCPs from config, not just connected ones
|
||||
for (const [key, mcp] of Object.entries(config)) {
|
||||
if (!isMcpConfigured(mcp)) continue
|
||||
result[key] = s.status[key] ?? { status: "disabled" }
|
||||
}
|
||||
|
||||
@@ -455,6 +467,11 @@ export namespace MCP {
|
||||
return
|
||||
}
|
||||
|
||||
if (!isMcpConfigured(mcp)) {
|
||||
log.error("Ignoring MCP connect request for config without type", { name })
|
||||
return
|
||||
}
|
||||
|
||||
const result = await create(name, { ...mcp, enabled: true })
|
||||
|
||||
if (!result) {
|
||||
@@ -579,6 +596,10 @@ export namespace MCP {
|
||||
throw new Error(`MCP server not found: ${mcpName}`)
|
||||
}
|
||||
|
||||
if (!isMcpConfigured(mcpConfig)) {
|
||||
throw new Error(`MCP server ${mcpName} is disabled or missing configuration`)
|
||||
}
|
||||
|
||||
if (mcpConfig.type !== "remote") {
|
||||
throw new Error(`MCP server ${mcpName} is not a remote server`)
|
||||
}
|
||||
@@ -705,6 +726,10 @@ export namespace MCP {
|
||||
throw new Error(`MCP server not found: ${mcpName}`)
|
||||
}
|
||||
|
||||
if (!isMcpConfigured(mcpConfig)) {
|
||||
throw new Error(`MCP server ${mcpName} is disabled or missing configuration`)
|
||||
}
|
||||
|
||||
// Re-add the MCP server to establish connection
|
||||
pendingOAuthTransports.delete(mcpName)
|
||||
const result = await add(mcpName, mcpConfig)
|
||||
@@ -737,7 +762,9 @@ export namespace MCP {
|
||||
export async function supportsOAuth(mcpName: string): Promise<boolean> {
|
||||
const cfg = await Config.get()
|
||||
const mcpConfig = cfg.mcp?.[mcpName]
|
||||
return mcpConfig?.type === "remote" && mcpConfig.oauth !== false
|
||||
if (!mcpConfig) return false
|
||||
if (!isMcpConfigured(mcpConfig)) return false
|
||||
return mcpConfig.type === "remote" && mcpConfig.oauth !== false
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user