openpencil/tests/helpers/mcp/acp-session.ts
Danila Poyarkov 39bc4d2eb1
feat(acp): add reusable MCP connections (#516)
* feat(acp): add reusable MCP connections

- Store named Streamable HTTP connections separately from model providers
- Keep bearer tokens in the credential manager and resolve them per ACP session
- Add localized settings, validation, documentation, and focused coverage

* test(acp): harden MCP connection workflow

- Label credential inputs and confirm destructive connection removal
- Exercise MCP server delivery through an in-memory ACP session
- Extend the browser smoke test to cover accessible input and confirmation flows

* fix(acp): validate MCP connection lifecycle

- Keep non-browser storage initialization in memory and restore the German model copy
- Reject persisted name collisions and invalid draft IDs
- Preserve connections on credential failures and require credentials before enablement
2026-08-14 20:08:45 +03:00

54 lines
1.7 KiB
TypeScript

import {
AgentSideConnection,
ClientSideConnection,
PROTOCOL_VERSION,
type Agent,
type Client,
type McpServer,
type NewSessionRequest
} from '@agentclientprotocol/sdk'
import { buildACPMCPServers } from '@/app/integrations/mcp'
function pairedStreams() {
const clientToAgent = new TransformStream()
const agentToClient = new TransformStream()
return {
client: { writable: clientToAgent.writable, readable: agentToClient.readable },
agent: { writable: agentToClient.writable, readable: clientToAgent.readable }
}
}
export async function captureACPSessionMCPServers(): Promise<McpServer[]> {
const streams = pairedStreams()
let received: NewSessionRequest | null = null
const client: Client = {
requestPermission: async () => ({ outcome: { outcome: 'cancelled' } }),
sessionUpdate: async () => undefined
}
const agent: Agent = {
initialize: async () => ({
protocolVersion: PROTOCOL_VERSION,
agentCapabilities: { loadSession: false }
}),
newSession: async (params) => {
received = params
return { sessionId: 'smoke-session' }
},
authenticate: async () => ({}),
prompt: async () => ({ stopReason: 'end_turn' }),
cancel: async () => undefined
}
const agentConnection = new AgentSideConnection(() => agent, streams.agent)
const connection = new ClientSideConnection(() => client, streams.client)
await connection.initialize({ protocolVersion: PROTOCOL_VERSION, clientCapabilities: {} })
await connection.newSession({
cwd: '/tmp',
mcpServers: await buildACPMCPServers({ authorizationToken: 'built-in-token' })
})
if (!received) throw new Error('ACP agent did not receive session configuration')
void agentConnection
return received.mcpServers
}