Skip to main content
Glama

@arizeai/phoenix-mcp

Official
by Arize-ai
converters.ts14.4 kB
import z from "zod"; import { assertUnreachable } from "../../utils/assertUnreachable"; import { safelyParseJSON } from "../../utils/safelyParseJSON"; import { JSONLiteral } from "../jsonLiteralSchema"; import { OpenAIChatPart } from "./openai/messagePartSchemas"; import { OpenAIMessage } from "./openai/messageSchemas"; import { OpenAIToolCall } from "./openai/toolCallSchemas"; import { OpenaiToolChoice } from "./openai/toolChoiceSchemas"; import { OpenAIToolDefinition } from "./openai/toolSchemas"; import { toolCallHeuristicSchema } from "./schemas"; import { SDKProviderConverterMap } from "./constants"; import { LLMMessagePart, PromptSDKFormat } from "./types"; import { detectMessagePartProvider, detectMessageProvider, detectToolCallProvider, detectToolChoiceProvider, detectToolDefinitionProvider, } from "./utils"; import invariant from "tiny-invariant"; export const safelyConvertMessageToProvider = < TargetProviderSDK extends NonNullable<PromptSDKFormat>, >({ message, targetProvider, }: { message: unknown; targetProvider: TargetProviderSDK; }) => { try { // convert incoming message to OpenAI format const openAIMessage = toOpenAIMessage(message); invariant( openAIMessage != null, `Could not convert message to ${targetProvider} format` ); // convert the OpenAI format to the target provider format return fromOpenAIMessage({ message: openAIMessage, targetProvider }); } catch { return null; } }; export const safelyConvertToolCallToProvider = < TargetProviderSDK extends NonNullable<PromptSDKFormat>, >({ toolCall, targetProvider, }: { toolCall: unknown; targetProvider: TargetProviderSDK; }) => { try { // convert incoming tool call to OpenAI format const openAIToolCall = toOpenAIToolCall(toolCall); invariant( openAIToolCall != null, `Could not convert tool call to ${targetProvider} format` ); // convert the OpenAI format to the target provider format return fromOpenAIToolCall({ toolCall: openAIToolCall, targetProvider, }); } catch { return null; } }; export const safelyConvertToolDefinitionToProvider = < TargetProviderSDK extends NonNullable<PromptSDKFormat>, >({ toolDefinition, targetProvider, }: { toolDefinition: unknown; targetProvider: TargetProviderSDK; }) => { try { // convert incoming tool definition to OpenAI format const openAIToolDefinition = toOpenAIToolDefinition(toolDefinition); invariant( openAIToolDefinition != null, `Could not convert tool definition to ${targetProvider} format` ); // convert the OpenAI format to the target provider format return fromOpenAIToolDefinition({ toolDefinition: openAIToolDefinition, targetProvider, }); } catch { return null; } }; export const safelyConvertToolChoiceToProvider = < TargetProviderSDK extends NonNullable<PromptSDKFormat>, >({ toolChoice, targetProvider, }: { toolChoice: unknown; targetProvider: TargetProviderSDK; }) => { try { // convert incoming tool choice to OpenAI format const openAIToolChoice = toOpenAIToolChoice(toolChoice); invariant( openAIToolChoice != null, `Could not convert tool choice to ${targetProvider} format` ); // convert the OpenAI format to the target provider format return fromOpenAIToolChoice({ toolChoice: openAIToolChoice, targetProvider, }); } catch { return null; } }; export const toOpenAIChatPart = ( part: LLMMessagePart ): OpenAIChatPart | null => { const { provider, validatedMessage } = detectMessagePartProvider(part); switch (provider) { case "AZURE_OPENAI": case "OPENAI": return validatedMessage; case "ANTHROPIC": return SDKProviderConverterMap.ANTHROPIC.messageParts.toOpenAI.parse( validatedMessage ); case "PHOENIX": return SDKProviderConverterMap.PHOENIX.messageParts.toOpenAI.parse( validatedMessage ); case "VERCEL_AI": return SDKProviderConverterMap.VERCEL_AI.messageParts.toOpenAI.parse( validatedMessage ); case null: return null; default: return assertUnreachable(provider); } }; /** * Convert from any message format to OpenAI format if possible */ export const toOpenAIMessage = (message: unknown): OpenAIMessage | null => { const { provider, validatedMessage } = detectMessageProvider(message); switch (provider) { case "AZURE_OPENAI": case "OPENAI": return validatedMessage as OpenAIMessage; case "ANTHROPIC": return SDKProviderConverterMap.ANTHROPIC.messages.toOpenAI.parse( validatedMessage ); case "PHOENIX": return SDKProviderConverterMap.PHOENIX.messages.toOpenAI.parse( validatedMessage ); case "VERCEL_AI": return SDKProviderConverterMap.VERCEL_AI.messages.toOpenAI.parse( validatedMessage ); case null: return null; default: return assertUnreachable(provider); } }; /** * Convert from OpenAI message format to any other format */ export const fromOpenAIMessage = < TargetProviderSDK extends NonNullable<PromptSDKFormat>, >({ message, targetProvider, }: { message: OpenAIMessage; targetProvider: TargetProviderSDK; }): z.infer< (typeof SDKProviderConverterMap)[TargetProviderSDK]["messages"]["fromOpenAI"] > => { switch (targetProvider) { case "AZURE_OPENAI": case "OPENAI": return SDKProviderConverterMap.OPENAI.messages.fromOpenAI.parse(message); case "ANTHROPIC": return SDKProviderConverterMap.ANTHROPIC.messages.fromOpenAI.parse( message ); case "PHOENIX": return SDKProviderConverterMap.PHOENIX.messages.fromOpenAI.parse(message); case "VERCEL_AI": return SDKProviderConverterMap.VERCEL_AI.messages.fromOpenAI.parse( message ); default: return assertUnreachable(targetProvider); } }; /** * Converts a tool call to the OpenAI format if possible * @param maybeToolCall a tool call from an unknown LlmProvider * @returns the tool call parsed to the OpenAI format */ export const toOpenAIToolCall = ( maybeToolCall: unknown ): OpenAIToolCall | null => { const { provider, validatedToolCall } = detectToolCallProvider(maybeToolCall); switch (provider) { case "AZURE_OPENAI": case "OPENAI": return validatedToolCall; case "ANTHROPIC": return SDKProviderConverterMap.ANTHROPIC.toolCalls.toOpenAI.parse( validatedToolCall ); case "PHOENIX": return SDKProviderConverterMap.PHOENIX.toolCalls.toOpenAI.parse( validatedToolCall ); case "VERCEL_AI": return SDKProviderConverterMap.VERCEL_AI.toolCalls.toOpenAI.parse( validatedToolCall ); case null: return null; default: return assertUnreachable(provider); } }; /** * Converts a tool call to a target provider format * @param params the parameters object * @param params.toolCall the tool call to convert * @param params.targetProvider the provider to convert the tool call to * @returns the tool call in the target provider format */ export const fromOpenAIToolCall = < TargetProviderSDK extends NonNullable<PromptSDKFormat>, >({ toolCall, targetProvider, }: { toolCall: OpenAIToolCall; targetProvider: TargetProviderSDK; }): z.infer< (typeof SDKProviderConverterMap)[TargetProviderSDK]["toolCalls"]["fromOpenAI"] > => { switch (targetProvider) { case "AZURE_OPENAI": case "OPENAI": return SDKProviderConverterMap.OPENAI.toolCalls.fromOpenAI.parse( toolCall ); case "ANTHROPIC": return SDKProviderConverterMap.ANTHROPIC.toolCalls.fromOpenAI.parse( toolCall ); case "PHOENIX": return SDKProviderConverterMap.PHOENIX.toolCalls.fromOpenAI.parse( toolCall ); case "VERCEL_AI": return SDKProviderConverterMap.VERCEL_AI.toolCalls.fromOpenAI.parse( toolCall ); default: assertUnreachable(targetProvider); } }; /** * Converts a tool choice to the OpenAI format * @param toolChoice a tool choice from an unknown LlmProvider * @returns the tool choice parsed to the OpenAI format */ export const toOpenAIToolChoice = ( toolChoice: unknown ): OpenaiToolChoice | null => { const { provider, toolChoice: validatedToolChoice } = detectToolChoiceProvider(toolChoice); if (provider == null || validatedToolChoice == null) { throw new Error("Could not detect provider of tool choice"); } switch (provider) { case "AZURE_OPENAI": case "OPENAI": return validatedToolChoice; case "ANTHROPIC": return SDKProviderConverterMap.ANTHROPIC.toolChoices.toOpenAI.parse( validatedToolChoice ); case "PHOENIX": return SDKProviderConverterMap.PHOENIX.toolChoices.toOpenAI.parse( validatedToolChoice ); case "VERCEL_AI": return SDKProviderConverterMap.VERCEL_AI.toolChoices.toOpenAI.parse( validatedToolChoice ); default: assertUnreachable(provider); } }; /** * Converts a tool choice to a target provider format * @param params the parameters object * @param params.toolChoice the tool choice to convert * @param params.targetProvider the provider to convert the tool choice to * @returns the tool choice in the target provider format */ export const fromOpenAIToolChoice = < TargetProviderSDK extends NonNullable<PromptSDKFormat>, >({ toolChoice, targetProvider, }: { toolChoice: OpenaiToolChoice; targetProvider: TargetProviderSDK; }): z.infer< (typeof SDKProviderConverterMap)[TargetProviderSDK]["toolChoices"]["fromOpenAI"] > => { switch (targetProvider) { case "AZURE_OPENAI": case "OPENAI": return SDKProviderConverterMap.OPENAI.toolChoices.fromOpenAI.parse( toolChoice ); case "ANTHROPIC": return SDKProviderConverterMap.ANTHROPIC.toolChoices.fromOpenAI.parse( toolChoice ); case "PHOENIX": return SDKProviderConverterMap.PHOENIX.toolChoices.fromOpenAI.parse( toolChoice ); case "VERCEL_AI": return SDKProviderConverterMap.VERCEL_AI.toolChoices.fromOpenAI.parse( toolChoice ); default: assertUnreachable(targetProvider); } }; /** * Convert from any tool call format to OpenAI format if possible */ export const toOpenAIToolDefinition = ( toolDefinition: unknown ): OpenAIToolDefinition | null => { const { provider, validatedToolDefinition } = detectToolDefinitionProvider(toolDefinition); switch (provider) { case "AZURE_OPENAI": case "OPENAI": return SDKProviderConverterMap.OPENAI.toolDefinitions.toOpenAI.parse( validatedToolDefinition ); case "ANTHROPIC": return SDKProviderConverterMap.ANTHROPIC.toolDefinitions.toOpenAI.parse( validatedToolDefinition ); case "PHOENIX": return SDKProviderConverterMap.PHOENIX.toolDefinitions.toOpenAI.parse( validatedToolDefinition ); case "VERCEL_AI": return SDKProviderConverterMap.VERCEL_AI.toolDefinitions.toOpenAI.parse( validatedToolDefinition ); case null: return null; default: assertUnreachable(provider); } }; /** * Convert from OpenAI tool call format to any other format */ export const fromOpenAIToolDefinition = < TargetProviderSDK extends NonNullable<PromptSDKFormat>, >({ toolDefinition, targetProvider, }: { toolDefinition: OpenAIToolDefinition; targetProvider: TargetProviderSDK; }): z.infer< (typeof SDKProviderConverterMap)[TargetProviderSDK]["toolDefinitions"]["fromOpenAI"] > => { switch (targetProvider) { case "AZURE_OPENAI": case "OPENAI": return SDKProviderConverterMap.OPENAI.toolDefinitions.fromOpenAI.parse( toolDefinition ); case "ANTHROPIC": return SDKProviderConverterMap.ANTHROPIC.toolDefinitions.fromOpenAI.parse( toolDefinition ); case "PHOENIX": return SDKProviderConverterMap.PHOENIX.toolDefinitions.fromOpenAI.parse( toolDefinition ); case "VERCEL_AI": return SDKProviderConverterMap.VERCEL_AI.toolDefinitions.fromOpenAI.parse( toolDefinition ); default: assertUnreachable(targetProvider); } }; export function findToolCallId(maybeToolCall: unknown): string | null { let subject = maybeToolCall; if (typeof maybeToolCall === "string") { const parsed = safelyParseJSON(maybeToolCall); subject = parsed.json; } const toolCall = toOpenAIToolCall(subject); if (toolCall) { return toolCall.id; } // we don't have first class support for the incoming tool call // try some heuristics to find the id const heuristic = toolCallHeuristicSchema.safeParse(subject); if (heuristic.success) { return heuristic.data.id ?? heuristic.data.name ?? null; } return null; } export function findToolCallName(maybeToolCall: unknown): string | null { let subject = maybeToolCall; if (typeof maybeToolCall === "string") { const parsed = safelyParseJSON(maybeToolCall); subject = parsed.json; } const toolCall = toOpenAIToolCall(subject); if (toolCall) { return toolCall.function.name; } // we don't have first class support for the incoming tool call // try some heuristics to find the name const heuristic = toolCallHeuristicSchema.safeParse(subject); if (heuristic.success) { return ( heuristic.data.function?.name ?? heuristic.data.name ?? // fallback to id if we don't have a name heuristic.data.id ?? null ); } return null; } export function findToolCallArguments( maybeToolCall: unknown ): JSONLiteral | null { let subject = maybeToolCall; if (typeof maybeToolCall === "string") { const parsed = safelyParseJSON(maybeToolCall); subject = parsed.json; } const toolCall = toOpenAIToolCall(subject); if (toolCall) { return toolCall.function.arguments as JSONLiteral; } // we don't have first class support for the incoming tool call // try some heuristics to find the arguments const heuristic = toolCallHeuristicSchema.safeParse(subject); if (heuristic.success) { return ( ((heuristic.data.arguments ?? heuristic.data.function?.arguments) as JSONLiteral) ?? null ); } return null; }

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/Arize-ai/phoenix'

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