79 lines · 2.4 KB · TypeScript
RawDownload
// ---------------------------------------------------------------------------// MCP tool discovery — connect to an MCP server and list its tools// --------------------------------------------------------------------------- import { Effect } from "effect"; import type { McpConnector } from "./connection";import { McpToolDiscoveryError } from "./errors";import {  extractManifestFromListToolsResult,  isListToolsResult,  type McpToolManifest,} from "./manifest"; // ---------------------------------------------------------------------------// Public API// --------------------------------------------------------------------------- /** * Connect to an MCP server and discover all available tools. * Returns the parsed manifest containing server metadata and tool entries. */export const discoverTools = (  connector: McpConnector,): Effect.Effect<McpToolManifest, McpToolDiscoveryError> =>  Effect.gen(function* () {    // Acquire connection    const connection = yield* connector.pipe(      Effect.mapError(        ({ message }) =>          new McpToolDiscoveryError({            stage: "connect",            message: `Failed connecting to MCP server: ${message}`,          }),      ),    );     // List tools    const listResult = yield* Effect.tryPromise({      try: () => connection.client.listTools(),      catch: () =>        new McpToolDiscoveryError({          stage: "list_tools",          message: "Failed listing MCP tools",        }),    });     if (!isListToolsResult(listResult)) {      yield* closeConnection(connection);      return yield* new McpToolDiscoveryError({        stage: "list_tools",        message: "MCP listTools response did not match the expected schema",      });    }     const manifest = extractManifestFromListToolsResult(listResult, {      serverInfo: connection.client.getServerVersion?.(),      instructions: connection.client.getInstructions?.(),    });     // Close the connection after discovery    yield* closeConnection(connection);     return manifest;  }); const closeConnection = (connection: {  readonly close: () => Promise<void>;}): Effect.Effect<void, never> =>  Effect.ignore(    Effect.tryPromise({      try: () => connection.close(),      catch: () =>        new McpToolDiscoveryError({          stage: "list_tools",          message: "Failed closing MCP connection",        }),    }),  );