ModelRunner
ModelRunner запускает более 100 AI-моделей — от изображений до видео и музыки — из одного подключения
Что умеет
- Искать модели по категории или типу входа и выхода
- Запускать инференс модели и получать результат по ссылке
- Загружать локальные файлы как входные данные модели
- Создавать и настраивать собственные обёртки над базовыми моделями
- Следить за статусом запроса и историей запусков
Какие данные видит
Авторизация через OAuth 2.1, оплата по фактическому использованию — доступ ограничен запросами и загрузками владельца аккаунта.
Нужен ли аккаунт
Не нужен: сервер работает без входа
ModelRunner — хостируемый MCP-сервер, объединяющий более 100 AI-моделей разных провайдеров под одним подключением: текст в изображение, изображение в видео, генерация музыки, распознавание речи и 3D из изображения, включая Kling, HiDream, Hunyuan Image, Stable Audio и Rodin. Ассистент может искать модель в каталоге, смотреть её схему входных данных, запускать инференс и получать результат ссылкой прямо в диалоге, а также собирать собственные упрощённые обёртки над базовыми моделями.
Как подключить
Как подключить ModelRunner к Claude
Адрес сервера, который нужно вставить в настройках Claude:
https://modelrunner-mcp--modelrunner.run.tools
- Откройте Claude (сайт claude.ai или приложение для компьютера).
- Перейдите в Настройки → Коннекторы (в английском интерфейсе: Settings → Connectors).
- Нажмите Добавить пользовательский коннектор (Add custom connector).
- Вставьте адрес сервера, скопированный ниже, в поле URL удалённого MCP-сервера и нажмите Добавить.
- В чате нажмите + → Коннекторы и включите новый коннектор.
Пользовательские коннекторы доступны на тарифах Free, Pro, Max, Team и Enterprise. На Free можно добавить только один. В Team и Enterprise коннектор сначала добавляет владелец организации в Настройки организации → Коннекторы.
Авторизация
После нажатия Добавить откроется окно входа в сервис. Войдите под своим аккаунтом и подтвердите доступ. Пароль Claude не видит.
Как подключить ModelRunner к ChatGPT
Адрес сервера, который нужно вставить в настройках ChatGPT:
https://modelrunner-mcp--modelrunner.run.tools
- Откройте ChatGPT в браузере (chatgpt.com). Нужен тариф Plus, Pro, Business, Enterprise или Edu.
- Один раз включите режим разработчика: Настройки → Приложения → Дополнительные настройки → Режим разработчика (Settings → Apps → Advanced settings → Developer mode).
- Откройте Настройки → Коннекторы и нажмите Создать (Create).
- Заполните форму: Название (любое), Описание (одна фраза, что делает сервис), URL MCP-сервера (скопируйте ниже).
- В поле Аутентификация выберите OAuth, если сервис требует вход, иначе Нет. Нажмите Создать.
- В новом чате откройте + → Приложения/Коннекторы и включите коннектор.
Название раздела у OpenAI менялось (Connectors → Apps/Plugins). Если пункт называется иначе, ищите «режим разработчика» в настройках. В рабочих пространствах Business/Enterprise администратор должен разрешить пользовательские коннекторы.
Авторизация
При первом использовании ChatGPT откроет окно входа в сервис. Войдите и подтвердите доступ.
Как подключить ModelRunner к Cursor
Адрес сервера, который нужно вставить в настройках Cursor:
https://modelrunner-mcp--modelrunner.run.tools
Быстрый способ: нажмите кнопку Открыть в Cursor ниже, Cursor сам предложит добавить сервер.
Вручную:
- В Cursor откройте Settings → Cursor Settings → MCP и нажмите Add new global MCP server.
- Вставьте JSON, скопированный ниже, в открывшийся файл
~/.cursor/mcp.json(для одного проекта:.cursor/mcp.jsonв корне проекта). - Сохраните файл. Сервер появится в списке MCP; при необходимости пройдите авторизацию по кнопке рядом с ним.
Авторизация
Если сервис требует вход, рядом с сервером в списке MCP появится кнопка авторизации.
Список инструментов сервера (23)
Технические названия из tools/list. Нужны только разработчикам.
| list_models | Lists publicly available models. Filter by category or input/output modality. Returns compact summaries — use `get_model` for full details. |
| recommended_models | Returns the admin-curated shortlist of models for a category. The fastest way for an AI assistant to pick a good model. |
| get_model | Returns a compact, readable description of a model: inputs, outputs, pricing, examples. For raw JSON Schema use `get_model_raw_schema`. |
| get_model_raw_schema | Returns the raw OpenAPI-style JSON Schema for a model. Prefer `get_model` for most use cases. |
| list_wrappers | Lists publicly available wrappers (curated combinations of base models with prompt templates). Returns compact summaries — use `get_wrapper` for full details. |
| list_my_wrappers | Lists the wrappers YOU own — scoped to your authenticated identity, including private and draft wrappers (which `list_wrappers` does not show). Returns each wrapper's `id`, `endpoint`, `visibility`, and `status`; pass that `id` to `patch_wrapper` or `delete_wrapper`. Requires authentication. |
| recommended_wrappers | Returns the admin-curated shortlist of wrappers for a category. |
| get_wrapper | Returns a compact, readable description of a wrapper: inputs, outputs, base models, and effective pricing (with markup). This readable view truncates long enum lists ("…N more") and omits the prompt template and field mappings. To edit a wrapper, fetch ONLY the part(s) you need with the focused tools — `get_wrapper_raw_schema` (full input schema + untruncated enums), `get_wrapper_prompt_template` (the Handlebars template + templateContext), `get_wrapper_field_mappings` (per-base-model mappings + defaultBaseModel). These are deliberately split so you pull just one slice into context; for a large wrapper, fan each part out to its own sub-agent rather than loading the whole definition at once. |
| get_wrapper_raw_schema | Returns ONLY the raw OpenAPI-style input `schema` for a wrapper, with the FULL, untruncated enum value lists that `get_wrapper` abbreviates ("…N more"). This is the authoritative source for allowed field values — do not reconstruct enums from a client app. Pair with `get_wrapper_prompt_template` and `get_wrapper_field_mappings` (separate calls) only when you actually need those parts. |
| get_wrapper_prompt_template | Returns ONLY the wrapper's Handlebars `promptTemplate` and its `templateContext` ({ maps, constants }) — nothing else. Use this when you intend to read or edit the template. Note it can be large (up to ~50k chars), which is exactly why it is a separate tool: fetch it in its own context/sub-agent rather than alongside the schema and mappings. |
| get_wrapper_field_mappings | Returns ONLY the wrapper's base-model wiring: the `defaultBaseModel` endpoint and each base model's `fieldMappings` (collectFields/staticValues/presets/renames/omit). Shaped to match `patch_wrapper`/`create_wrapper` input (`baseModels: [{ baseModel, fieldMappings }]`, defaultBaseModel as an "ownerName/alias" endpoint) so you can edit and submit it back. Fetch separately from the schema/template so each part stays in its own context. |
| wrapper_authoring_guide | Returns the full ModelRunner wrapper authoring guide: how to design the user-facing input schema, write the Handlebars prompt template + templateContext, choose base models, and derive per-base-model fieldMappings — with all constraints and worked examples. Read this BEFORE calling create_wrapper or patch_wrapper. |
| preview_wrapper | Dry-run a wrapper prompt template + field mappings against a sample input WITHOUT creating anything. Returns the transformed base-model input so you can validate template rendering, collectFields, presets, renames, and omit while authoring. Note: preview does not guarantee every produced key is accepted by the base model — create/update validation is stricter. |
| create_wrapper | Create a new wrapper you own (a curated base model + prompt template + user-facing input schema). It is created under YOUR account — `ownerName` is derived from your authenticated identity; do not pass it. Defaults to visibility=private, status=draft. BEFORE calling: (1) read `wrapper_authoring_guide`; (2) inspect each base model's app Input schema via `get_model` / `get_model_raw_schema` so your fieldMappings target valid keys; (3) dry-run with `preview_wrapper`. Constraints: `schema` is OpenAPI-style `{ components: { schemas: { Input: {...} } } }` and MUST NOT contain a `base_model` field. `promptTemplate` is Handlebars (helpers: lookup, eq, and, or, exists; no partials or raw blocks). Base models are referenced by their `ownerName/alias` endpoint (the same identifier you call a model with), not a UUID; `defaultBaseModel` must be one of `baseModels[].baseModel`. fieldMappings target each base model's APP schema and apply in order: collectFields → staticValues → presets → renames → omit. `alias` must be unique across your models and wrappers. Author a short "How to use" / orchestration passage INTO `description` — `get_wrapper` shows it to callers before they run. Especially when the wrapper is meant to produce a consistent SET across multiple runs, tell the caller to plan the set up front, generate the first item, then reuse that first output as the reference/anchor for the rest (not chain each run to its predecessor). |
| patch_wrapper | Update one of your existing wrappers by id. Provide only the fields you want to change; you can only modify wrappers you own. `ownerName` cannot be changed. Before editing, read the wrapper's current source with the focused tools — `get_wrapper_raw_schema`, `get_wrapper_prompt_template`, `get_wrapper_field_mappings` — fetching only the part you intend to change (`get_wrapper` truncates enums and omits the template/mappings). For a large or multi-part edit, fan each part out to its own sub-agent so no single context holds the whole definition. The same authoring constraints as `create_wrapper` apply to any changed field (schema shape, Handlebars helpers, fieldMappings target the base model app schema, base models referenced by `ownerName/alias` endpoint, defaultBaseModel ∈ baseModels). Re-run `preview_wrapper` after changing the template or mappings. |
| delete_wrapper | Delete one of your wrappers by id or "ownerName/alias" endpoint. You can only delete wrappers you own. |
| search | Relevance-ranked free-text search across the public catalog (models AND wrappers), designed for you to evaluate the results: - `score`: full-text rank, comparable across models and wrappers. - `matchedOn`: which fields matched (name/alias/tags/shortDescription/description/category/owner); 'fulltext' = only the stemmed query matched, no verbatim substring. - `pricing.averageCost`: average USD per run from curated examples. - `examplePrompts`: real prompts from example runs — proof of what the entry actually handles. - `collections`: published themed sets it belongs to. - `rootModel`: entries sharing it are variants (speed/price tiers) of one family — compare their pricing before picking. Recall-first (default 25 results) — YOU are the precision layer; filter and re-rank against the user's use case. Describe the use case in `q` with descriptive words ("remove background product photo"), not stopword sentences. Follow up with `get_model` / `get_wrapper` to see input schemas before running. |
| run_model | Starts an asynchronous inference request against the specified model or wrapper endpoint. Returns immediately with a requestId — poll with `get_request` or use `wait_for_request`. |
| get_request | Returns the current status, outputs (if completed), pricing snapshot, and error (if failed) for a request. |
| wait_for_request | Polls `get_request` server-side until the request reaches a terminal state or the timeout elapses. Returns the final status payload. |
| create_upload_url | PREFERRED way to turn a LOCAL file into a ModelRunner file-input URL. Returns two short-lived PUT URLs plus the final canonical `file_url`, so you stream the bytes straight to storage from your own environment — the bytes never pass through this MCP or your token output. Use this for any local file (especially images/audio/video over ~100 KB): (1) call this tool, (2) PUT the file with the returned headers using your shell, starting with `upload_url` (direct to storage) — e.g. `curl -X PUT -T <localPath> -H "Content-Type: <type>" "<upload_url>"`; if that PUT is blocked by a host/egress allowlist (HTTP 403 `host_not_allowed` / "not allowed host"), retry the SAME PUT to `relay_upload_url` (served on the ModelRunner API domain, which an allowlist is more likely to permit), (3) pass `file_url` as the model/wrapper input. ALWAYS prefer this over `upload_file` for local files — `upload_file` sends the bytes through the model as base64, which burns a large amount of tokens/compute and is unreliable above a few hundred KB. URLs are short-lived (PUT promptly). Requires a shell or other way to make an HTTP PUT; only if you have none, AND BOTH URLs are blocked by your network, fall back to `upload_file` (base64 — token-expensive, last resort). |
| upload_file | Uploads a file to ModelRunner storage and returns the canonical `file_url` for a `run_model` / wrapper file input. ⚠️ LAST RESORT for local files — almost always use `create_upload_url` instead. To upload LOCAL-file bytes this tool takes `base64`, which means the file is written into the MODEL'S TOKENS: that is slow and burns a large amount of tokens/compute, and it gets worse the bigger the file (and far worse in chunked mode — every chunk's base64 is emitted into the conversation). `create_upload_url` streams the bytes out-of-band via a shell PUT (direct-to-storage OR its relay URL on the ModelRunner domain) so NO base64 ever touches the model. Only fall back to base64 here when `create_upload_url` is genuinely impossible — i.e. you have no shell to PUT with AND it is a fully egress-locked sandbox where the MCP channel is the only way out. Re-hosting a remote `url` (no base64) is always fine. BASE64 MODES (last resort only). (1) SINGLE-SHOT: pass the whole file as `base64`; ALWAYS pass `expectedDecodedBytes` = the file's size in bytes so a silently-truncated base64 becomes a loud error instead of a corrupt upload. (2) CHUNKED (only when the file is too large to fit one base64 string in that locked sandbox — expensive, avoid otherwise): split into small base64 chunks (~32-48 KB each), one tool call per chunk; omit `uploadId` on the FIRST chunk (the response returns one), pass it back on every later chunk with an incrementing `partIndex`, set `isLastPart:true` on the final chunk. Each chunk carries its own `expectedDecodedBytes` and is validated on arrival — a truncated chunk errors alone and you resend just it (same `partIndex`). The response contains `file_url` once the last chunk assembles. Then pass `file_url` as the model/wrapper input. |
| list_my_requests | Returns the authenticated user's past requests, newest first. Filters by status, model endpoint, and date range. |