npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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.

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-api

Basic 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 results

Web 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.