Skip to main content
Glama

@arizeai/phoenix-mcp

Official
by Arize-ai
converters.ts5.68 kB
import { assertUnreachable } from "../../../utils/assertUnreachable"; import { OpenAIToolDefinition } from "../openai/toolSchemas"; import { OpenAIMessage } from "../openai/messageSchemas"; import { OpenAIToolCall } from "../openai/toolCallSchemas"; import { OpenaiToolChoice } from "../openai/toolChoiceSchemas"; import { phoenixMessageSchema } from "./messageSchemas"; import { ToolCallPart, ToolResultPart, asToolResultPart, phoenixContentPartSchema, } from "./messagePartSchemas"; import { phoenixToolCallSchema } from "./toolCallSchemas"; import { safelyStringifyJSON } from "../../../utils/safelyStringifyJSON"; import { OpenAIChatPartText } from "../openai/messagePartSchemas"; import { phoenixResponseFormatSchema } from "./responseFormatSchema"; import { OpenAIResponseFormat } from "../openai/responseFormatSchema"; import { phoenixToolDefinitionSchema } from "./toolSchemas"; import { phoenixToolChoiceSchema } from "./toolChoiceSchemas"; import { jsonSchemaZodSchema } from "../../jsonSchema"; /* * Conversion Functions * * These follow a hub-and-spoke model where OpenAI is the hub format. * All conversions between different formats go through OpenAI as an intermediate step. */ export const phoenixMessagePartToOpenAI = phoenixContentPartSchema.transform( (part) => { const type = part.type; switch (type) { case "text": return { type: "text", text: part.text, } satisfies OpenAIChatPartText; case "tool_call": return null; case "tool_result": return null; default: return assertUnreachable(type); } } ); /** * Spoke → Hub: Convert a Prompt message to OpenAI format */ export const phoenixMessageToOpenAI = phoenixMessageSchema.transform( (prompt) => { const content = typeof prompt.content == "string" ? [{ type: "text", text: prompt.content }] : prompt.content; // Special handling for TOOL role messages if (prompt.role === "tool") { const toolResult = content .map((part) => asToolResultPart(part)) .find((part): part is ToolResultPart => !!part); if (!toolResult) { throw new Error("TOOL role message must have a ToolResultContentPart"); } return { role: "tool", content: typeof toolResult.tool_result === "string" ? toolResult.tool_result : safelyStringifyJSON(toolResult.tool_result).json || "", tool_call_id: toolResult.tool_call_id, } satisfies OpenAIMessage; } // Handle other roles const role = prompt.role; switch (role) { case "system": case "developer": return { role: "system", content: content .map((part) => phoenixMessagePartToOpenAI.parse(part)) .filter( (part): part is OpenAIChatPartText => part !== null && part.type === "text" ), } satisfies OpenAIMessage; case "user": return { role: "user", content: content .map((part) => phoenixMessagePartToOpenAI.parse(part)) .filter( (part): part is OpenAIChatPartText => part !== null && part.type === "text" ), } satisfies OpenAIMessage; case "assistant": case "ai": case "model": return { role: "assistant", content: content .map((part) => phoenixMessagePartToOpenAI.parse(part)) .filter( (part): part is OpenAIChatPartText => part !== null && part.type === "text" ), tool_calls: content.some((part) => part.type === "tool_call") ? content .filter( (part): part is ToolCallPart => part.type === "tool_call" ) .map((part) => phoenixToolCallToOpenAI.parse(part)) .filter((part): part is OpenAIToolCall => part !== null) : undefined, } satisfies OpenAIMessage; default: return assertUnreachable(role); } } ); export const phoenixResponseFormatToOpenAI = phoenixResponseFormatSchema.transform( (phoenix): OpenAIResponseFormat => ({ type: "json_schema", json_schema: { name: phoenix.json_schema.name, description: phoenix.json_schema.description, schema: jsonSchemaZodSchema.parse(phoenix.json_schema.schema), }, }) ); export const phoenixToolCallToOpenAI = phoenixToolCallSchema.transform( (prompt): OpenAIToolCall => ({ type: "function", id: prompt.tool_call_id, function: { ...prompt.tool_call, arguments: typeof prompt.tool_call.arguments === "string" ? prompt.tool_call.arguments : (safelyStringifyJSON(prompt.tool_call.arguments).json ?? ""), }, }) ); export const phoenixToolDefinitionToOpenAI = phoenixToolDefinitionSchema.transform( (phoenix): OpenAIToolDefinition => ({ type: "function", function: { name: phoenix.function.name, description: phoenix.function.description, parameters: jsonSchemaZodSchema.parse(phoenix.function.parameters), }, }) ); export const phoenixToolChoiceToOpenAI = phoenixToolChoiceSchema.transform( (phoenix): OpenaiToolChoice => { switch (phoenix.type) { case "none": return "none"; case "zero_or_more": return "auto"; case "one_or_more": return "required"; case "specific_function": return { type: "function", function: { name: phoenix.function_name } }; } } );

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