mimo-api
v0.1.0
Published
SOTA TypeScript SDK for the Xiaomi MiMo API — chat completions, streaming, TTS, function calling, web search, and more. Unofficial, open-source, community-built.
Maintainers
Keywords
Readme
mimo-api
The state-of-the-art TypeScript SDK for the Xiaomi MiMo Platform API — unofficial, open-source, and community-built.
MiMo delivers state-of-the-art reasoning, multimodal understanding, speech synthesis, and tool-calling capabilities through both OpenAI-compatible and Anthropic-compatible API endpoints.
Features
| Feature | Supported | |---|---| | Chat completions (OpenAI-compatible) | ✅ | | Messages (Anthropic-compatible) | ✅ | | Streaming (SSE) | ✅ | | Thinking / Chain-of-thought | ✅ | | Function calling / Tool use | ✅ | | Web search | ✅ | | Image understanding | ✅ | | Video understanding | ✅ | | Audio understanding | ✅ | | Text-to-Speech (TTS) | ✅ | | Voice cloning | ✅ | | Voice design | ✅ | | Structured output (JSON mode) | ✅ | | Automatic retry with backoff | ✅ | | Full TypeScript types | ✅ | | Dual CJS / ESM build | ✅ |
Supported Models
| Model | Type | Context | Max Output |
|---|---|---|---|
| mimo-v2.5-pro | Text (reasoning) | 1M | 128K |
| mimo-v2.5 | Multimodal (text/image/video/audio) | 1M | 128K |
| mimo-v2-flash | Text (fast) | 256K | 64K |
| mimo-v2.5-tts | Speech synthesis | 8K | 8K |
| mimo-v2.5-tts-voiceclone | Voice cloning | 8K | 8K |
| mimo-v2.5-tts-voicedesign | Voice design | 8K | 8K |
| mimo-v2-tts | Speech synthesis (legacy) | 8K | 8K |
Quick Start
Install
npm install mimo-api
# or
pnpm add mimo-api
# or
yarn add mimo-apiBasic Usage
import { MiMo } from "mimo-api";
const mimo = new MiMo({
apiKey: process.env.MIMO_API_KEY, // or pass directly
});
// Simple chat — returns the assistant's reply as a string
const reply = await mimo.chat("What is the meaning of life?");
console.log(reply);Streaming
// Stream tokens as they arrive
for await (const token of mimo.chatStream("Tell me a story")) {
process.stdout.write(token);
}Streaming with Reasoning
// Get both thinking and content tokens
for await (const part of mimo.chatStreamWithReasoning("Solve: 2x + 5 = 15")) {
if (part.type === "reasoning") {
process.stdout.write(`💭 ${part.text}`);
} else {
process.stdout.write(part.text);
}
}Advanced Usage
OpenAI-Compatible API
For full control, use the OpenAI-compatible endpoint directly:
import { MiMo } from "mimo-api";
const mimo = new MiMo({ apiKey: process.env.MIMO_API_KEY });
// Non-streaming
const completion = await mimo.openai.create({
model: "mimo-v2.5-pro",
messages: [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "Explain quantum computing" },
],
temperature: 1.0,
max_completion_tokens: 2048,
thinking: { type: "enabled" },
});
console.log(completion.choices[0].message.content);
console.log(completion.choices[0].message.reasoning_content); // thinking trace
// Streaming
const stream = await mimo.openai.createStream({
model: "mimo-v2.5-pro",
messages: [{ role: "user", content: "Write a haiku" }],
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}Anthropic-Compatible API
import { MiMo } from "mimo-api";
const mimo = new MiMo({ apiKey: process.env.MIMO_API_KEY });
// Non-streaming
const message = await mimo.anthropic.create({
model: "mimo-v2.5-pro",
max_tokens: 1024,
system: "You are a helpful assistant.",
messages: [{ role: "user", content: "Hello!" }],
});
console.log(message.content[0].type === "text" ? message.content[0].text : "");
// Streaming
const stream = await mimo.anthropic.createStream({
model: "mimo-v2.5",
max_tokens: 1024,
messages: [{ role: "user", content: "Tell me a joke" }],
});
for await (const event of stream) {
if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
process.stdout.write(event.delta.text);
}
}Function Calling / Tool Use
const tools = [
{
type: "function" as const,
function: {
name: "get_weather",
description: "Get current weather for a city",
parameters: {
type: "object",
properties: {
city: { type: "string", description: "City name" },
},
required: ["city"],
},
},
},
];
// Automatic tool-calling loop
const result = await mimo.chatWithTools(
[{ role: "user", content: "What's the weather in Tokyo?" }],
tools,
async (call) => {
if (call.function.name === "get_weather") {
const { city } = JSON.parse(call.function.arguments);
return JSON.stringify({ city, temperature: "22°C", condition: "Sunny" });
}
throw new Error(`Unknown tool: ${call.function.name}`);
},
);
console.log(result); // The model's final answer incorporating tool resultsWeb Search
const completion = await mimo.openai.create({
model: "mimo-v2.5-pro",
messages: [{ role: "user", content: "What happened in the news today?" }],
tools: [{ type: "web_search", web_search: { enabled: true } }],
});
const message = completion.choices[0].message;
console.log(message.content);
// Check annotations for source URLs
if (message.annotations) {
for (const annotation of message.annotations) {
console.log(`Source: ${annotation.title} — ${annotation.url}`);
}
}Image Understanding
const completion = await mimo.openai.create({
model: "mimo-v2.5",
messages: [
{
role: "user",
content: [
{
type: "image_url",
image_url: { url: "https://example.com/photo.jpg" },
},
{ type: "text", text: "What's in this image?" },
],
},
],
});
console.log(completion.choices[0].message.content);Video Understanding
const completion = await mimo.openai.create({
model: "mimo-v2.5",
messages: [
{
role: "user",
content: [
{
type: "video_url",
video_url: { url: "https://example.com/clip.mp4" },
fps: 2,
media_resolution: "default",
},
{ type: "text", text: "Describe what happens in this video" },
],
},
],
});Audio Understanding
const completion = await mimo.openai.create({
model: "mimo-v2.5",
messages: [
{
role: "user",
content: [
{
type: "input_audio",
input_audio: {
data: "https://example.com/audio.wav",
format: "wav",
},
},
{ type: "text", text: "Transcribe and describe this audio" },
],
},
],
});Text-to-Speech (TTS)
// Built-in voice
const completion = await mimo.openai.create({
model: "mimo-v2.5-tts",
messages: [
{ role: "user", content: "Speak in a warm, friendly tone." },
{ role: "assistant", content: "Hello! Welcome to MiMo, your AI assistant." },
],
audio: { format: "wav", voice: "Chloe" },
});
// Decode the base64 audio
const audioData = completion.choices[0].message.audio?.data;
if (audioData) {
const buffer = Buffer.from(audioData, "base64");
// Save or play the audio...
}Voice Design
const completion = await mimo.openai.create({
model: "mimo-v2.5-tts-voicedesign",
messages: [
{ role: "user", content: "A warm, middle-aged female narrator with a gentle British accent." },
{ role: "assistant", content: "Once upon a time, in a land far away..." },
],
audio: { format: "wav", optimize_text_preview: true },
});Voice Cloning
const completion = await mimo.openai.create({
model: "mimo-v2.5-tts-voiceclone",
messages: [
{ role: "user", content: "" },
{ role: "assistant", content: "This is a test of voice cloning." },
],
audio: {
format: "wav",
voice: "data:audio/wav;base64,<BASE64_ENCODED_SAMPLE>",
},
});Structured Output (JSON Mode)
const completion = await mimo.openai.create({
model: "mimo-v2.5-pro",
messages: [
{ role: "user", content: "List 3 programming languages with their years of creation." },
],
response_format: { type: "json_object" },
});
const data = JSON.parse(completion.choices[0].message.content!);Error Handling
The SDK throws typed errors for every failure mode documented in the MiMo API:
import { MiMo, RateLimitError, AuthenticationError, ContentFilterError } from "mimo-api";
const mimo = new MiMo({ apiKey: process.env.MIMO_API_KEY });
try {
await mimo.chat("Hello");
} catch (error) {
if (error instanceof RateLimitError) {
console.error(`Rate limited. Retry after ${error.retryAfter}s`);
} else if (error instanceof AuthenticationError) {
console.error("Invalid API key");
} else if (error instanceof ContentFilterError) {
console.error("Content was filtered");
}
}| Error Class | Status | Description |
|---|---|---|
| BadRequestError | 400 | Invalid request format or parameters |
| AuthenticationError | 401 | Missing or invalid API key |
| InsufficientBalanceError | 402 | Account balance depleted |
| ForbiddenError | 403 | Region blocked or key restricted |
| NotFoundError | 404 | Endpoint or model not found |
| ContentFilterError | 421 | Content filtered by safety system |
| RateLimitError | 429 | Rate limit or quota exceeded |
| InternalServerError | 500 | Server error |
| ServiceUnavailableError | 503 | Server overloaded |
| NetworkError | 0 | Connection or timeout failure |
Configuration
const mimo = new MiMo({
// API key (falls back to MIMO_API_KEY env var)
apiKey: "your-api-key",
// Base URL (default: https://api.xiaomimimo.com)
baseURL: "https://api.xiaomimimo.com",
// Default model (default: "mimo-v2.5-pro")
model: "mimo-v2.5-pro",
// Default parameters
temperature: 1.0,
topP: 0.95,
maxCompletionTokens: 4096,
// Request settings
timeout: 300_000, // 5 minutes (default)
maxRetries: 3, // Retry on transient errors (default)
// Custom headers (e.g., for analytics)
defaultHeaders: {
"X-My-App": "my-app/v1.0",
},
// Custom fetch (for proxies or testing)
fetch: customFetch,
});Pricing
Pricing is per-token, with significant discounts for cached inputs. See the official pricing page for current rates.
API Reference
MiMo
The main client class. Entry point for all API interactions.
Methods
| Method | Returns | Description |
|---|---|---|
| chat(message, options?) | Promise<string> | Send a message, get a text reply |
| chatStream(message, options?) | AsyncGenerator<string> | Stream text tokens |
| chatStreamWithReasoning(message, options?) | AsyncGenerator<{type, text}> | Stream reasoning + content |
| chatWithTools(messages, tools, handler, options?) | Promise<string> | Automatic tool-calling loop |
| openai.create(request) | Promise<ChatCompletion> | OpenAI-compatible completion |
| openai.createStream(request) | Promise<AsyncIterable<ChatCompletionChunk>> | OpenAI-compatible streaming |
| openai.createStreamAndCollect(request) | Promise<ChatCompletion & {chunks}> | Stream + collect into one object |
| anthropic.create(request) | Promise<Anthropic.Message> | Anthropic-compatible message |
| anthropic.createStream(request) | Promise<AsyncIterable<Anthropic.StreamEvent>> | Anthropic-compatible streaming |
| anthropic.createStreamAndCollect(request) | Promise<Anthropic.Message & {events}> | Stream + collect into one object |
Requirements
- Node.js ≥ 18.0.0
- TypeScript ≥ 5.0 (for type imports)
License
MIT — community project, not affiliated with Xiaomi.
