Files
LLeMbas-CLI/tests/mcp-oauth.test.ts
T
HomerandClaude Opus 5.5 f9bad01ed7
ci / check (push) Waiting to run
LLeMbas CLI 1.0.0
The first public release of LLeMbas CLI: a terminal coding agent and project manager for any LLM
API, with permission modes, git snapshots, memory and skills, knowledge bases, MCP, voice, and a
link to a LLeMbas instance whose web UI can work its sessions too. Signed Linux binaries for x64
and arm64.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 21:59:03 +00:00

84 lines
3.9 KiB
TypeScript

// OAuth against a real authorisation server: the SDK's own example server with --oauth (discovery,
// dynamic client registration, PKCE, tokens), which approves every sign-in at once — so fetching
// the authorisation page and following its redirect plays the browser.
import { afterAll, beforeAll, expect, test } from "bun:test"
import { readFileSync, statSync } from "node:fs"
import { join } from "node:path"
import { paths } from "../src/config/paths.ts"
import { McpManager } from "../src/mcp/index.ts"
import { codeFrom } from "../src/mcp/oauth.ts"
const node = Bun.which("node")
const example = join(import.meta.dir, "..", "node_modules/@modelcontextprotocol/sdk/dist/esm/examples/server/simpleStreamableHttp.js")
const free = () => {
const s = Bun.serve({ port: 0, fetch: () => new Response() })
const p = s.port
s.stop(true)
return p
}
const [MCP, AUTH, CB] = [free(), free(), free()]
let server: ReturnType<typeof Bun.spawn> | undefined
beforeAll(async () => {
if (!node) return
server = Bun.spawn([node, example, "--oauth"], { env: { ...process.env, MCP_PORT: String(MCP), MCP_AUTH_PORT: String(AUTH) }, stdout: "pipe", stderr: "pipe" })
const until = Date.now() + 15_000
while (Date.now() < until) {
if (await fetch(`http://localhost:${MCP}/mcp`, { method: "POST" }).then(() => true, () => false)) break
await Bun.sleep(100)
}
})
afterAll(() => server?.kill())
test.skipIf(!node)("sign in: needs_auth first, then the redirect is caught, tokens stored (0600) and reused", async () => {
const cfg = { demo: { url: `http://localhost:${MCP}/mcp`, source: "global" as const, oauth: { callback_port: CB } } }
const m = new McpManager(cfg, { root: "/tmp", version: "t" })
await m.start()
expect(m.servers.get("demo")!.status).toBe("needs_auth")
let shown = ""
const s = await m.auth("demo", async (url) => {
shown = url
const r = await fetch(url, { redirect: "manual" })
await fetch(r.headers.get("location")!)
})
expect(new URL(shown).searchParams.get("code_challenge_method")).toBe("S256")
expect(s.status).toBe("connected")
expect((await m.tools().find((t) => t.name === "mcp__demo__greet")!.run({ name: "Jaro" }, { signal: new AbortController().signal } as any)).output).toBe("Hello, Jaro!")
await m.close()
const file = join(paths.data, "mcp-auth.json")
expect(statSync(file).mode & 0o777).toBe(0o600)
// Stored under the name and the URL together (a project's "demo" elsewhere cannot replace it).
const stored = JSON.parse(readFileSync(file, "utf8")) as Record<string, { url: string; tokens?: { access_token?: string } }>
const key = Object.keys(stored).find((k) => k.startsWith("demo "))!
expect(stored[key]!.tokens?.access_token).toBeTruthy()
const again = new McpManager(cfg, { root: "/tmp", version: "t" })
await again.start()
expect(again.servers.get("demo")!.status).toBe("connected")
again.logout("demo")
expect(JSON.parse(readFileSync(file, "utf8")).demo).toBeUndefined()
await again.close()
})
test.skipIf(!node)("a pasted redirect address works when the browser cannot reach this machine", async () => {
const cfg = { paste: { url: `http://localhost:${MCP}/mcp`, source: "global" as const, oauth: { callback_port: free() } } }
const m = new McpManager(cfg, { root: "/tmp", version: "t" })
let give: (s: string) => void = () => {}
const pasted = new Promise<string>((r) => (give = r))
const s = await m.auth(
"paste",
async (url) => {
// the browser ends on the redirect address; it never reaches our listener
const r = await fetch(url, { redirect: "manual" })
give(r.headers.get("location")!)
},
pasted,
)
expect(s.status).toBe("connected")
await m.close()
})
test("the code from a pasted address or a bare code", () => {
expect(codeFrom("http://127.0.0.1:19876/mcp/oauth/callback?code=abc&state=xyz")).toEqual({ code: "abc", state: "xyz", fromUrl: true })
expect(codeFrom(" abc ")).toEqual({ code: "abc" })
})