Parse an SSE-streamed MCP response and return the first result text.
(res: Response)
| 94 | |
| 95 | /** Parse an SSE-streamed MCP response and return the first result text. */ |
| 96 | private async parseSseResponse(res: Response): Promise<string> { |
| 97 | const reader = res.body!.getReader(); |
| 98 | const decoder = new TextDecoder(); |
| 99 | let buffer = ""; |
| 100 | let result = ""; |
| 101 | |
| 102 | try { |
| 103 | while (true) { |
| 104 | const { done, value } = await reader.read(); |
| 105 | if (done) break; |
| 106 | buffer += decoder.decode(value, { stream: true }); |
| 107 | const lines = buffer.split("\n"); |
| 108 | buffer = lines.pop() ?? ""; |
| 109 | |
| 110 | for (const line of lines) { |
| 111 | if (!line.startsWith("data: ")) continue; |
| 112 | try { |
| 113 | const json = JSON.parse(line.slice(6)) as McpResponse<McpToolResult>; |
| 114 | if (json.result?.content?.[0]?.text != null) { |
| 115 | result = json.result.content[0].text; |
| 116 | } |
| 117 | } catch { |
| 118 | // skip |
| 119 | } |
| 120 | } |
| 121 | } |
| 122 | } finally { |
| 123 | reader.releaseLock(); |
| 124 | } |
| 125 | |
| 126 | return result; |
| 127 | } |
| 128 | |
| 129 | async callTool(name: string, args: Record<string, unknown>): Promise<string> { |
| 130 | await this.initialize(); |