Skip to main content
Glama
client.ts3.42 kB
import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'; import { z } from 'zod'; import { ToolName } from '../../src/tools/toolName.js'; import invariant from '../../src/utils/invariant.js'; import { getDefaultEnv } from '../testEnv.js'; /** * Lists the tools available in the MCP server. * * @returns {*} {Promise<Array<string>>} The names of the tools available in the MCP server */ export async function listTools(): Promise<Array<string>> { const client = await getClient(); const result = await client.listTools(); const names = result.tools.map((tool) => tool.name); return names; } /** * Calls the MCP tool with the provided arguments. * * @param {ToolName} toolName The name of the tool to call * @param {({ * schema: Z; * contentType?: 'text' | 'image'; * env?: Record<string, string>; * toolArgs?: Record<string, unknown>; * })} options Additional options * @param options.schema The expected shape of the tool result * @param options.contentType The expected content type of the tool result * @param options.env The environment to use when spawning the node process running the MCP server * @param options.toolArgs The arguments to pass to the tool * @returns {*} {Promise<z.infer<Z>>} The tool call result */ export async function callTool<Z extends z.ZodTypeAny = z.ZodNever>( toolName: ToolName, { schema, contentType, env, toolArgs, }: { schema: Z; contentType?: 'text' | 'image'; env?: Record<string, string>; toolArgs?: Record<string, unknown>; }, ): Promise<z.infer<Z>> { contentType = contentType ?? 'text'; toolArgs = toolArgs ?? {}; const client = await getClient(env); const result = await client.callTool({ name: toolName, arguments: toolArgs, }); if (!Array.isArray(result.content)) { console.error(result.content); throw new Error('result.content must be an array'); } expect(result.content).toHaveLength(1); expect(result.content[0].type).toBe(contentType); if (result.isError) { const content = result.content[0][contentType === 'text' ? 'text' : 'data']; console.error(content); throw new Error(content); } if (contentType === 'text') { const text = result.content[0].text; invariant(typeof text === 'string'); const response = schema.parse(JSON.parse(text)); return response; } else { const content = result.content[0].data; invariant(typeof content === 'string'); const response = schema.parse(content); return response; } } /** * Gets a new instance of an MCP client using stdio transport. * * @param {Record<string, string>} [env] The environment to use when spawning the node process running the MCP server * @returns {*} {Promise<Client>} The MCP client */ export async function getClient(env?: Record<string, string>): Promise<Client> { env = env ?? getDefaultEnv(); // https://github.com/nodejs/node/issues/55374 env.PATH = process.env.PATH ?? ''; const transport = new StdioClientTransport({ command: 'node', args: ['build/index.js'], env: env ?? {}, }); const client = new Client({ name: 'tableau-mcp-e2e-tests', version: '1.0.0', capabilities: { listTools: true, callTool: true, }, }); await client.connect(transport); return client; }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/datalabs89/tableau-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server