diff --git a/docs/my-website/docs/providers/miromind.md b/docs/my-website/docs/providers/miromind.md
new file mode 100644
index 00000000000..c2741ca57d3
--- /dev/null
+++ b/docs/my-website/docs/providers/miromind.md
@@ -0,0 +1,130 @@
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+# MiroMind
+
+## Overview
+
+| Property | Details |
+|-------|-------|
+| Description | MiroMind operates the [MiroThinker](https://miromind.ai) deep research model family — agent models that iteratively plan, search the web, fetch pages, and synthesize a final report. Exposed through an OpenAI-compatible Responses API. |
+| Provider Route on LiteLLM | `miromind/` |
+| Link to Provider Doc | [MiroMind API Documentation ↗](https://platform.miromind.ai/docs/responses-api) |
+| Base URL | `https://api.miromind.ai/v1` |
+| Supported Operations | [`/v1/responses`](#sample-usage), `/v1/chat/completions` |
+
+
+
+
+MiroThinker models are **deep research agents** — they always run an internal planning loop with built-in `google_search` and URL-fetch tools. The Responses API is the recommended endpoint because it surfaces the full lifecycle (reasoning items, `web_search_call` events, final message) as typed SSE events. Chat Completions is supported as a thinner fallback that exposes only the final answer plus token usage.
+
+## Available Models
+
+| Model | Description | Context Window |
+|-------|-------------|----------------|
+| `miromind/mirothinker-1-7-deepresearch` | MiroThinker 1.7 flagship deep research agent | 262,144 tokens |
+| `miromind/mirothinker-1-7-deepresearch-mini` | Smaller / faster variant | 262,144 tokens |
+
+## Required Variables
+
+```python showLineNumbers title="Environment Variables"
+os.environ["MIROMIND_API_KEY"] = "" # your MiroMind API key
+```
+
+## Usage - LiteLLM Python SDK
+
+### Streaming Responses (recommended)
+
+```python showLineNumbers title="MiroMind Deep Research — streaming"
+import os
+import asyncio
+import litellm
+
+os.environ["MIROMIND_API_KEY"] = ""
+
+async def main():
+ stream = await litellm.aresponses(
+ model="miromind/mirothinker-1-7-deepresearch-mini",
+ input="Find the latest news about LiteLLM and summarize in 3 bullets with sources.",
+ stream=True,
+ )
+ async for event in stream:
+ print(event.type, getattr(event, "delta", ""))
+
+asyncio.run(main())
+```
+
+### Non-streaming Responses
+
+```python showLineNumbers title="MiroMind Deep Research — non-streaming"
+import os
+import litellm
+
+os.environ["MIROMIND_API_KEY"] = ""
+
+resp = litellm.responses(
+ model="miromind/mirothinker-1-7-deepresearch-mini",
+ input="What were the most-cited papers on alignment in 2025?",
+)
+print(resp)
+```
+
+### Chat Completions (fallback)
+
+```python showLineNumbers title="MiroMind via /v1/chat/completions"
+import os
+from litellm import completion
+
+os.environ["MIROMIND_API_KEY"] = ""
+
+response = completion(
+ model="miromind/mirothinker-1-7-deepresearch-mini",
+ messages=[{"role": "user", "content": "Summarize recent advances in retrieval-augmented generation."}],
+)
+print(response)
+```
+
+## Usage - LiteLLM Proxy Server
+
+```yaml showLineNumbers title="config.yaml"
+model_list:
+ - model_name: mirothinker
+ litellm_params:
+ model: miromind/mirothinker-1-7-deepresearch
+ api_key: os.environ/MIROMIND_API_KEY
+ - model_name: mirothinker-mini
+ litellm_params:
+ model: miromind/mirothinker-1-7-deepresearch-mini
+ api_key: os.environ/MIROMIND_API_KEY
+```
+
+## Custom API Base
+
+```python showLineNumbers title="Custom API Base"
+import os
+os.environ["MIROMIND_API_BASE"] = "https://api.miromind.ai/v1"
+os.environ["MIROMIND_API_KEY"] = ""
+```
+
+Or pass `api_base=` directly on the call.
+
+## Responses API event shape
+
+MiroThinker emits OpenAI Responses-shaped SSE events. Key things to know when integrating:
+
+- **Reasoning** is emitted as raw chain-of-thought via `response.reasoning_text.delta` / `.done` (GPT-OSS-style), not `response.reasoning_summary_text.*`.
+- **Built-in tools** surface as `web_search_call` output items with `action.type`:
+ - `google_search` → `action.type = "search"` (with `action.query`)
+ - URL fetch / page extraction → `action.type = "open_page"` (with `action.url`)
+- **Custom events** (`response.agent_summary.*`) carry the model's planning-phase scratch text and can be safely ignored — clients listening only to `response.output_text.*` will see the final answer correctly.
+
+See [MiroMind Responses API docs](https://platform.miromind.ai/docs/responses-api) for the full event catalog.
+
+## Supported OpenAI Parameters
+
+- `temperature`
+- `top_p`
+- `max_output_tokens`
+- `stream`
+- `tools` (built-in tools are managed server-side; client-supplied tool definitions are accepted but executed by MiroMind's agent loop)
+- `instructions`
diff --git a/litellm/llms/openai_like/providers.json b/litellm/llms/openai_like/providers.json
index b5e5aa4ea28..4d3792a1bb5 100644
--- a/litellm/llms/openai_like/providers.json
+++ b/litellm/llms/openai_like/providers.json
@@ -114,5 +114,11 @@
"param_mappings": {
"max_completion_tokens": "max_tokens"
}
+ },
+ "miromind": {
+ "base_url": "https://api.miromind.ai/v1",
+ "api_key_env": "MIROMIND_API_KEY",
+ "api_base_env": "MIROMIND_API_BASE",
+ "supported_endpoints": ["/v1/responses", "/v1/chat/completions"]
}
}
diff --git a/litellm/types/utils.py b/litellm/types/utils.py
index 400edcac889..a6ae91978c6 100644
--- a/litellm/types/utils.py
+++ b/litellm/types/utils.py
@@ -3325,6 +3325,7 @@ class LlmProviders(str, Enum):
A2A_AGENT = "a2a_agent"
LANGGRAPH = "langgraph"
MINIMAX = "minimax"
+ MIROMIND = "miromind"
SYNTHETIC = "synthetic"
APERTIS = "apertis"
NANOGPT = "nano-gpt"
diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json
index 269e7daecc1..5cef8aba609 100644
--- a/model_prices_and_context_window.json
+++ b/model_prices_and_context_window.json
@@ -23044,6 +23044,44 @@
"max_input_tokens": 200000,
"max_output_tokens": 8192
},
+ "miromind/mirothinker-1-7-deepresearch": {
+ "input_cost_per_token": 4e-06,
+ "output_cost_per_token": 2.5e-05,
+ "litellm_provider": "miromind",
+ "mode": "responses",
+ "max_input_tokens": 262144,
+ "max_output_tokens": 16384,
+ "max_tokens": 16384,
+ "supported_endpoints": ["/v1/responses", "/v1/chat/completions"],
+ "search_context_cost_per_query": {
+ "search_context_size_low": 0.05,
+ "search_context_size_medium": 0.05,
+ "search_context_size_high": 0.05
+ },
+ "supports_native_streaming": true,
+ "supports_reasoning": true,
+ "supports_web_search": true,
+ "supports_system_messages": true
+ },
+ "miromind/mirothinker-1-7-deepresearch-mini": {
+ "input_cost_per_token": 1.25e-06,
+ "output_cost_per_token": 1e-05,
+ "litellm_provider": "miromind",
+ "mode": "responses",
+ "max_input_tokens": 262144,
+ "max_output_tokens": 16384,
+ "max_tokens": 16384,
+ "supported_endpoints": ["/v1/responses", "/v1/chat/completions"],
+ "search_context_cost_per_query": {
+ "search_context_size_low": 0.05,
+ "search_context_size_medium": 0.05,
+ "search_context_size_high": 0.05
+ },
+ "supports_native_streaming": true,
+ "supports_reasoning": true,
+ "supports_web_search": true,
+ "supports_system_messages": true
+ },
"mistral.devstral-2-123b": {
"input_cost_per_token": 4e-07,
"litellm_provider": "bedrock_converse",
diff --git a/provider_endpoints_support.json b/provider_endpoints_support.json
index 1d577213a1b..06aa17c54d5 100644
--- a/provider_endpoints_support.json
+++ b/provider_endpoints_support.json
@@ -2491,6 +2491,22 @@
"responses": true
}
},
+ "miromind": {
+ "display_name": "MiroMind (`miromind`)",
+ "url": "https://docs.litellm.ai/docs/providers/miromind",
+ "endpoints": {
+ "chat_completions": true,
+ "messages": false,
+ "responses": true,
+ "embeddings": false,
+ "image_generations": false,
+ "audio_transcriptions": false,
+ "audio_speech": false,
+ "moderations": false,
+ "batches": false,
+ "rerank": false
+ }
+ },
"pg_vector": {
"display_name": "PG Vector (`pg_vector`)",
"url": "https://docs.litellm.ai/docs/providers/pg_vector",
diff --git a/tests/test_litellm/llms/miromind/__init__.py b/tests/test_litellm/llms/miromind/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/test_litellm/llms/miromind/test_miromind.py b/tests/test_litellm/llms/miromind/test_miromind.py
new file mode 100644
index 00000000000..704ad39eb40
--- /dev/null
+++ b/tests/test_litellm/llms/miromind/test_miromind.py
@@ -0,0 +1,130 @@
+"""
+Tests for the MiroMind JSON-driven provider.
+
+MiroMind is registered via litellm/llms/openai_like/providers.json plus an
+entry in the LlmProviders enum. There is no per-provider Python module —
+everything routes through the OpenAI-like dynamic config machinery (see
+tests/test_litellm/llms/openai_like/responses/test_openai_like_responses.py
+for the generic mechanics). The tests here only assert that the miromind-
+specific entries are wired into the registry and resolve to the documented
+shape (responses endpoint, MiroMind base URL, `MIROMIND_API_KEY` env var).
+"""
+
+import os
+import sys
+
+import pytest
+
+sys.path.insert(0, os.path.abspath("../../.."))
+
+
+class TestMiroMindProviderRegistration:
+ def test_provider_loaded_from_providers_json(self):
+ from litellm.llms.openai_like.json_loader import JSONProviderRegistry
+
+ assert JSONProviderRegistry.exists("miromind")
+
+ def test_provider_supports_responses_api(self):
+ from litellm.llms.openai_like.json_loader import JSONProviderRegistry
+
+ assert JSONProviderRegistry.supports_responses_api("miromind") is True
+
+ def test_provider_in_llm_providers_enum(self):
+ from litellm.types.utils import LlmProviders
+
+ assert LlmProviders("miromind") == LlmProviders.MIROMIND
+
+
+class TestMiroMindResponsesConfig:
+ def _make_config(self):
+ from litellm.llms.openai_like.dynamic_config import (
+ create_responses_config_class,
+ )
+ from litellm.llms.openai_like.json_loader import JSONProviderRegistry
+
+ provider = JSONProviderRegistry.get("miromind")
+ return create_responses_config_class(provider)()
+
+ def test_custom_llm_provider(self):
+ assert self._make_config().custom_llm_provider == "miromind"
+
+ def test_complete_url_default_base(self):
+ """
+ With no api_base override and no MIROMIND_API_BASE env var, the
+ URL is built from providers.json `base_url`.
+ """
+ from unittest.mock import patch
+
+ with patch(
+ "litellm.llms.openai_like.dynamic_config.get_secret_str",
+ return_value=None,
+ ):
+ url = self._make_config().get_complete_url(
+ api_base=None, litellm_params={}
+ )
+ assert url == "https://api.miromind.ai/v1/responses"
+
+ def test_complete_url_api_base_override(self):
+ url = self._make_config().get_complete_url(
+ api_base="https://api-test.miromind.example/v1",
+ litellm_params={},
+ )
+ assert url == "https://api-test.miromind.example/v1/responses"
+
+ def test_validate_environment_sets_bearer_from_env(self):
+ from unittest.mock import patch
+
+ with patch(
+ "litellm.llms.openai_like.dynamic_config.get_secret_str",
+ return_value="sk-miromind-test",
+ ):
+ headers = self._make_config().validate_environment(
+ headers={}, model="mirothinker-1-7-deepresearch-mini", litellm_params=None
+ )
+ assert headers["Authorization"] == "Bearer sk-miromind-test"
+
+
+@pytest.mark.parametrize(
+ "model",
+ [
+ "miromind/mirothinker-1-7-deepresearch",
+ "miromind/mirothinker-1-7-deepresearch-mini",
+ ],
+)
+class TestMiroMindModelRegistration:
+ """Both flagship models must be declared in the source-of-truth
+ model_prices_and_context_window.json with mode=responses and
+ supports_native_streaming=true. We read the file directly (rather
+ than via litellm.model_cost) because the runtime fetches the cost
+ map from a remote URL at import time, which doesn't reflect the
+ in-PR edits until merge."""
+
+ @staticmethod
+ def _load_local_cost_map():
+ import json
+ import pathlib
+
+ # tests/test_litellm/llms/miromind/test_miromind.py → repo root → JSON
+ repo_root = pathlib.Path(__file__).resolve().parents[4]
+ path = repo_root / "model_prices_and_context_window.json"
+ with open(path, encoding="utf-8") as f:
+ return json.load(f)
+
+ def test_model_present(self, model):
+ assert model in self._load_local_cost_map()
+
+ def test_provider_and_mode(self, model):
+ entry = self._load_local_cost_map()[model]
+ assert entry["litellm_provider"] == "miromind"
+ assert entry["mode"] == "responses"
+
+ def test_supports_native_streaming(self, model):
+ """Without this flag, LiteLLM falls back to fake_stream — which
+ tries to parse the SSE response as JSON and breaks every Responses
+ streaming call. See PR description for the failure mode."""
+ entry = self._load_local_cost_map()[model]
+ assert entry.get("supports_native_streaming") is True
+
+ def test_advertises_responses_endpoint(self, model):
+ entry = self._load_local_cost_map()[model]
+ assert "/v1/responses" in entry.get("supported_endpoints", [])