Skip to content

Commit 1545b97

Browse files
fix(mcp): prefer live server status in mcp list
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <[email protected]>
1 parent f1789de commit 1545b97

1 file changed

Lines changed: 42 additions & 7 deletions

File tree

  • packages/opencode/src/cli/cmd

packages/opencode/src/cli/cmd/mcp.ts

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { McpOAuthProvider } from "../../mcp/oauth-provider"
1010
import { Config } from "../../config"
1111
import { ConfigMCP } from "../../config/mcp"
1212
import { Instance } from "../../project/instance"
13-
import { Installation } from "../../installation"
1413
import { InstallationVersion } from "../../installation/version"
1514
import path from "path"
1615
import { Global } from "../../global"
@@ -68,14 +67,49 @@ async function listState() {
6867
return AppRuntime.runPromise(
6968
Effect.gen(function* () {
7069
const cfg = yield* Config.Service
71-
const mcp = yield* MCP.Service
70+
const auth = yield* McpAuth.Service
7271
const config = yield* cfg.get()
73-
const statuses = yield* mcp.status()
72+
const global = yield* cfg.getGlobal()
73+
74+
const serverStatuses = yield* Effect.promise(() => {
75+
const hostname = global.server?.hostname === "0.0.0.0" ? "127.0.0.1" : (global.server?.hostname ?? "127.0.0.1")
76+
const password = process.env.OPENCODE_SERVER_PASSWORD
77+
const username = process.env.OPENCODE_SERVER_USERNAME ?? "opencode"
78+
const headers = password
79+
? {
80+
Authorization: `Basic ${Buffer.from(`${username}:${password}`).toString("base64")}`,
81+
}
82+
: undefined
83+
84+
const ports = [...new Set([global.server?.port, 18790, 4096].filter((value): value is number => !!value))]
85+
if (ports.length === 0) return Promise.resolve(undefined)
86+
87+
return (async () => {
88+
for (const port of ports) {
89+
const response = await fetch(`http://${hostname}:${port}/mcp`, {
90+
headers,
91+
signal: AbortSignal.timeout(1_000),
92+
}).catch(() => undefined)
93+
94+
if (response?.ok) return (await response.json()) as Record<string, MCP.Status>
95+
}
96+
97+
return undefined
98+
})()
99+
})
100+
101+
const statuses =
102+
serverStatuses ??
103+
(yield* Effect.gen(function* () {
104+
const mcp = yield* MCP.Service
105+
return yield* mcp.status()
106+
}))
107+
74108
const stored = yield* Effect.all(
75-
Object.fromEntries(configuredServers(config).map(([name]) => [name, mcp.hasStoredTokens(name)])),
109+
Object.fromEntries(configuredServers(config).map(([name]) => [name, Effect.map(auth.get(name), (entry) => !!entry?.tokens)])),
76110
{ concurrency: "unbounded" },
77111
)
78-
return { config, statuses, stored }
112+
return { config, statuses, stored, source: serverStatuses ? ("server" as const) : ("local" as const) }
79113
}),
80114
)
81115
}
@@ -120,7 +154,7 @@ export const McpListCommand = cmd({
120154
UI.empty()
121155
prompts.intro("MCP Servers")
122156

123-
const { config, statuses, stored } = await listState()
157+
const { config, statuses, stored, source } = await listState()
124158
const servers = configuredServers(config)
125159

126160
if (servers.length === 0) {
@@ -169,7 +203,8 @@ export const McpListCommand = cmd({
169203
)
170204
}
171205

172-
prompts.outro(`${servers.length} server(s)`)
206+
const sourceText = source === "server" ? "live server state" : "local process state"
207+
prompts.outro(`${servers.length} server(s) · source: ${sourceText}`)
173208
},
174209
})
175210
},

0 commit comments

Comments
 (0)