openpencil/tests/engine/cli/app-client.test.ts
Danila Poyarkov 2b32a8c7d3 feat(mcp): add local transport discovery
- Prefer private Unix sockets with TCP fallback for local MCP clients

- Unify HTTP and WebSocket lifecycle, authentication, and cleanup

- Discover transport details from an owner-only runtime file
2026-07-25 21:29:03 +03:00

55 lines
1.7 KiB
TypeScript

import { afterEach, describe, expect, test } from 'bun:test'
import { createServer, type Server } from 'node:http'
import type { AddressInfo } from 'node:net'
import { join } from 'node:path'
import { removeDiscoveryFile, writeDiscoveryFile } from '@open-pencil/mcp/discovery'
import { rpc } from '#cli/app-client'
let server: Server | null = null
afterEach(async () => {
await new Promise<void>((resolve) => {
if (!server) {
resolve()
return
}
server.close(() => resolve())
})
server = null
await removeDiscoveryFile()
})
describe('CLI app transport discovery', () => {
test('falls back to discovered TCP when the Unix socket is unavailable', async () => {
const token = 'cli-test-token'
server = createServer((request, response) => {
if (request.url !== '/rpc' || request.headers.authorization !== `Bearer ${token}`) {
response.writeHead(401, { 'Content-Type': 'application/json' })
response.end(JSON.stringify({ error: 'Unauthorized' }))
return
}
response.writeHead(200, { 'Content-Type': 'application/json' })
response.end(JSON.stringify({ ok: true, result: { source: 'tcp' } }))
})
await new Promise<void>((resolve) => {
server?.listen(0, '127.0.0.1', resolve)
})
const address = server.address() as AddressInfo
await writeDiscoveryFile({
pid: process.pid,
socketPath: join('/tmp', `missing-openpencil-${process.pid}.sock`),
httpPort: address.port,
authRequired: true,
authToken: token,
version: '0.0.0-test',
startedAt: new Date().toISOString()
})
const result = await rpc('list_documents')
expect(result).toEqual({ source: 'tcp' })
})
})