Skip to main content
Glama

@arizeai/phoenix-mcp

Official
by Arize-ai
converters.ts5.03 kB
import invariant from "tiny-invariant"; import { assertUnreachable } from "../../../utils/assertUnreachable"; import { OpenAIChatPart, OpenAIChatPartText, OpenAIChatPartImage, } from "../openai/messagePartSchemas"; import { OpenAIMessage, openAIMessageRoleSchema, } from "../openai/messageSchemas"; import { AnthropicMessagePart, AnthropicToolUseBlock, anthropicMessagePartSchema, } from "./messagePartSchemas"; import { anthropicMessageSchema } from "./messageSchemas"; import { anthropicToolCallSchema } from "./toolCallSchemas"; import { OpenAIToolCall } from "../openai/toolCallSchemas"; import { safelyStringifyJSON } from "../../../utils/safelyStringifyJSON"; import { anthropicToolChoiceSchema } from "./toolChoiceSchemas"; import { OpenaiToolChoice } from "../openai/toolChoiceSchemas"; import { OpenAIToolDefinition } from "../openai/toolSchemas"; import { anthropicToolDefinitionSchema } from "./toolSchemas"; /* * 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 anthropicMessagePartToOpenAI = anthropicMessagePartSchema.transform((anthropic): OpenAIChatPart | null => { const type = anthropic.type; switch (type) { case "text": return { type: "text", text: anthropic.text, } satisfies OpenAIChatPartText; case "image": return { type: "image_url", image_url: { url: anthropic.source.data }, } satisfies OpenAIChatPartImage; case "tool_use": return null; case "tool_result": return null; default: return assertUnreachable(type); } }); /** * Spoke → Hub: Convert an Anthropic message to OpenAI format */ export const anthropicMessageToOpenAI = anthropicMessageSchema.transform( (anthropic): OpenAIMessage => { let role = openAIMessageRoleSchema.parse(anthropic.role); if ( Array.isArray(anthropic.content) && anthropic.content.some((part) => part.type === "tool_result") ) { role = "tool"; } const initialContentArray: AnthropicMessagePart[] = typeof anthropic.content === "string" ? [{ type: "text", text: anthropic.content }] : anthropic.content; const toolCallParts = initialContentArray.filter( (part): part is AnthropicToolUseBlock => part.type === "tool_use" ); const nonToolCallParts = initialContentArray.filter( (part) => part.type !== "tool_use" ); invariant( role === "user" || role === "assistant", `Unexpected anthropic role: ${role}` ); switch (role) { case "assistant": { const content = nonToolCallParts .map((part) => anthropicMessagePartToOpenAI.parse(part)) .filter( (part): part is OpenAIChatPartText => part !== null && part.type === "text" ); return { role: "assistant", tool_calls: toolCallParts.length > 0 ? toolCallParts.map((tc) => anthropicToolCallToOpenAI.parse(tc)) : undefined, content, }; } case "user": { const content = nonToolCallParts .map((part) => anthropicMessagePartToOpenAI.parse(part)) .filter((part): part is OpenAIChatPart => part !== null); return { role: "user", content, }; } default: return assertUnreachable(role); } } ); /** * Parse incoming object as an Anthropic tool call and immediately convert to OpenAI format */ export const anthropicToolCallToOpenAI = anthropicToolCallSchema.transform( (anthropic): OpenAIToolCall => ({ type: "function", id: anthropic.id, function: { name: anthropic.name, arguments: typeof anthropic.input === "string" ? anthropic.input : (safelyStringifyJSON(anthropic.input).json ?? ""), }, }) ); /** * Parse incoming object as an Anthropic tool choice and immediately convert to OpenAI format */ export const anthropicToolChoiceToOpenAI = anthropicToolChoiceSchema.transform( (anthropic): OpenaiToolChoice => { switch (anthropic.type) { case "any": return "required"; case "auto": return "auto"; case "tool": if (!anthropic.name) { return "auto"; } return { type: "function", function: { name: anthropic.name }, }; default: return "auto"; } } ); /** * Parse incoming object as an Anthropic tool call and immediately convert to OpenAI format */ export const anthropicToolDefinitionToOpenAI = anthropicToolDefinitionSchema.transform( (anthropic): OpenAIToolDefinition => ({ type: "function", function: { name: anthropic.name, description: anthropic.description, parameters: anthropic.input_schema, }, }) );

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