| 425 | // client it holds: the same connection (and cached OAuth), the full tool |
| 426 | // definition. |
| 427 | const describeTools = () => |
| 428 | Effect.promise(async (): Promise<ReadonlyArray<McpToolDef>> => { |
| 429 | const rt = await runtime(); |
| 430 | if (!connected) { |
| 431 | await rt.listTools(serverName, callOptions); |
| 432 | connected = true; |
| 433 | } |
| 434 | const context = await rt.connect(serverName, { |
| 435 | allowCachedAuth: true, |
| 436 | oauthSessionOptions: callOptions.oauthSessionOptions, |
| 437 | }); |
| 438 | const out: McpToolDef[] = []; |
| 439 | let cursor: string | undefined; |
| 440 | do { |
| 441 | const page = await context.client.listTools(cursor ? { cursor } : undefined); |
| 442 | for (const tool of page.tools) { |
| 443 | out.push({ |
| 444 | name: tool.name, |
| 445 | description: tool.description ?? "", |
| 446 | ...(tool.annotations |
| 447 | ? { annotations: tool.annotations as Record<string, unknown> } |
| 448 | : {}), |
| 449 | inputSchema: tool.inputSchema, |
| 450 | }); |
| 451 | } |
| 452 | cursor = page.nextCursor ?? undefined; |
| 453 | } while (cursor); |
| 454 | return out; |
| 455 | }); |
| 456 | |
| 457 | const call = (name: string, args: Record<string, unknown> = {}) => |
| 458 | Effect.promise(async (): Promise<McpCallResult> => { |