Skip to main content
Modelship

Modelship

CI License: Apache 2.0 Python 3.12+ Docs Discord

Your agents already speak OpenAI. Give them a /v1/responses backend you own.

Modelship serves the whole agentic surface — reasoning, tool calling, server-side conversation state, and MCP servers the gateway calls for you — and scores 17/17 on the independent Open Responses conformance suite. Embeddings, speech, and image generation ride the same /v1. Change the base URL and your agent runs unchanged, on hardware you control.

Quick Start

One command, one model. Pick your hardware:

CPU — Linux, Windows, or macOS via Docker (images are multi-arch: amd64 + arm64):

docker run --rm --shm-size=8g -p 8000:8000 -v modelship-cache:/.cache \
  ghcr.io/modelship-ai/modelship:latest-cpu start \
  --model "Qwen/Qwen3-8B-GGUF:*Q4_K_M.gguf" --loader llama_server \
  --usecase generate --num-cpus 4

NVIDIA GPU — needs the NVIDIA Container Toolkit:

docker run --rm --shm-size=8g --gpus all -p 8000:8000 -v modelship-cache:/.cache \
  ghcr.io/modelship-ai/modelship:latest-cuda start \
  --model "Qwen/Qwen3-8B-GGUF:*Q4_K_M.gguf" --loader llama_server \
  --usecase generate --num-gpus 1

Apple Silicon — native, with Metal offload:

uv tool install mship && mship bootstrap --metal
mship start --model "Qwen/Qwen3-8B-GGUF:*Q4_K_M.gguf" --loader llama_server \
  --usecase generate --num-gpus 1

Wait for the Deploy … succeeded log line, then talk to it — this hits the Responses API and streams the model's reasoning as it thinks:

uvx --with httpx llm openai endpoint http://localhost:8000/modelship/v1 \
  -m qwen3-8b --responses "Which is larger, 9.11 or 9.9?"

Add --chat for an interactive session, -T to hand it a tool, or --models to list what's deployed.

The model serves as qwen3-8b, inferred from the reference. It pulls ~5 GB and wants ~10 GB of free RAM; --num-cpus 4 reserves four cores for it, so lower it if the container has fewer (the deploy waits for resources it can't get). On a small box, swap in lmstudio-community/Qwen3-0.6B-GGUF:*Q4_K_M.gguf.

Deploying several models at once uses a models.yaml instead; one model's tuning blocks have flags too (--llama-server-config.n-ctx 8192) — see Model Configuration. Hitting an error? Check Troubleshooting.

Prefer curl?
curl http://localhost:8000/modelship/v1/responses \
  -H "Content-Type: application/json" \
  -d '{"model": "qwen3-8b", "input": "Which is larger, 9.11 or 9.9?"}'

The response carries both output_text and a first-class reasoning output item. /modelship/v1/chat/completions is there too, if that's what your client speaks.

Open Responses conformance

/v1/responses is tested against the independent Open Responses compliance suite (bun run test:compliance), which drives the endpoint over real HTTP against a live deployment rather than mocks.

Latest result: 17/17 — every core, compaction, vision, and WebSocket test (Qwen3-VL-8B-Instruct AWQ 4-bit, vLLM, 2026-10-04).

Loader parity: the vllm and llama_server loaders return the same result on all 17 tests.

Full test breakdown
Test Category Status
Basic Text Response Core ✅ Pass
Assistant Message Phase Core ✅ Pass
Response Output Phase Schema Core ✅ Pass
Streaming Response Core ✅ Pass
System Prompt Core ✅ Pass
Multi-turn Conversation Core ✅ Pass
Tool Calling Core ✅ Pass
Compaction Endpoint /v1/responses/compact ✅ Pass
Compaction Missing Required Model /v1/responses/compact ✅ Pass
Image Input Vision ✅ Pass
WebSocket Response WebSocket ✅ Pass
WebSocket Sequential Responses WebSocket ✅ Pass
WebSocket Continuation WebSocket ✅ Pass
WebSocket Store False Reconnect Recovery WebSocket ✅ Pass
WebSocket Missing Previous Response WebSocket ✅ Pass
WebSocket Failed Continuation Evicts Cache WebSocket ✅ Pass
WebSocket Compact New Chain WebSocket ✅ Pass

Fourteen cluster guarantees — zero-downtime model cutover, load-driven autoscaling, engine crash recovery, fractional-GPU multi-tenancy, server-side MCP tool loops — are likewise asserted end-to-end against a live cluster with real models over real HTTP. See Verified cluster behaviour.

Why Modelship

  • Conversations that survive the replica that started them. previous_response_id, reasoning, and tool state live in one store every gateway replica shares — a Ray actor by default, Redis when you want it to outlive the cluster. Scale the gateway out without sharding your users onto specific replicas.
  • One endpoint for the whole app. Chat, embeddings for RAG, speech-to-text, text-to-speech, and image generation on a single OpenAI-compatible /v1 — instead of a service per modality.
  • A stack that fits the hardware you have. Allocate GPU fractions per model (70% for the LLM, 5% for TTS), or run the same model CPU-only. vLLM, llama.cpp, Diffusers, sherpa-onnx, and whisper.cpp coexist in one deployment.
  • Changes you can ship on a Tuesday. Edit the model set and reconcile: models are added, replaced, or dropped incrementally, with a blue-green cutover per model and no gateway restart.
Full feature list
  • Multi-model, multi-GPU — chat, embedding, STT, TTS, and image models running at once across one or more GPUs, with tunable per-model GPU memory allocation
  • CPU-only support — vLLM or llama.cpp (llama_server) without a GPU (chat, embeddings, transcription, vision)
  • Multiple inference backends — vLLM, llama.cpp, Diffusers, sherpa-onnx, whisper.cpp, stable-diffusion.cpp
  • Zero-downtime hot-reloads — reconcile a changed model set incrementally, without interrupting the gateway or unchanged models
  • Reasoning and tool calling — <think>-style reasoning parsed into first-class output, and universal tool/function calling across the vLLM and GGUF (llama_server) backends
  • Server-side MCP tool execution — point /v1/responses at any self-hosted MCP server (tools: [{"type": "mcp", ...}]) and the gateway discovers its tools, calls them, and loops — with an approval flow (require_approval) client-driven tool calling doesn't have
  • Multiple gateways per cluster — --gateway-name mounts each gateway at its own route prefix on the same port, with its own model set
  • Per-model isolated deployments — independent lifecycle, health checks, failure isolation, and replica count per model
  • Streaming — SSE for chat completions, responses, and TTS audio
  • Client disconnect detection — cancels in-flight inference when the client goes away, freeing the GPU immediately
  • Security — Ray cluster token auth (--enable-ray-auth), caller identity from your auth layer (MSHIP_TRUSTED_IDENTITY_HEADER), payload and concurrency limits
  • Built-in observability — Prometheus metrics, custom modelship:* metrics, vLLM engine stats, structured JSON logging, OpenTelemetry export, plus a pre-built Grafana dashboard and alerting rules

Supported OpenAI endpoints

Endpoint Usecase
POST /v1/chat/completions Chat / text generation (streaming and non-streaming)
POST /v1/responses Responses API — text, reasoning, client-driven tool calls, server-side MCP tool execution, and stored conversations (streaming and non-streaming)
GET/DELETE /v1/responses/{id} Fetch or drop a stored response (/input_items lists its input); background: true on create + POST .../cancel for queued/pollable runs
POST /v1/embeddings Text embeddings
POST /v1/audio/transcriptions Speech-to-text
POST /v1/audio/translations Audio translation
POST /v1/audio/speech Text-to-speech (SSE streaming or single-response)
POST /v1/images/generations Image generation
GET /v1/models List available models

Architecture

Modelship architecture: an agent app calls Modelship over HTTP; one Ray Serve HTTP proxy on port 8000 fronts any number of replicated gateways, each at its own route prefix with its own model set, sharing one conversation-state store and routing each request by model name to Ray Serve deployments across GPU and CPU cluster nodes.

Each model runs as an isolated Ray Serve deployment with its own lifecycle, health checks, and resource budget. Several inference backends are available:

Backend Best for GPU required
vLLM High-throughput chat, embeddings, transcription No — installs on GPU or CPU
llama.cpp (llama_server) High-efficiency quantized GGUF models (chat, embeddings, vision) No
Diffusers Image generation Yes
sherpa-onnx TTS (Kokoro) No
whisper.cpp STT No

A model name maps to exactly one deployment — swapping GPU/CPU or backend replaces it with a blue-green cutover rather than adding a second one alongside it. Each deployment scales horizontally with num_replicas, load-balanced by Ray Serve. Multiple gateways can share one cluster and one port (--gateway-name), each mounted at /<name>/v1 with its own model set.

More ways to run

Several models at once — a models.yaml replaces the flags and unlocks the nested tuning blocks (vllm_engine_kwargs, llama_server_config, autoscaling_config):

docker run --rm --shm-size=8g -p 8000:8000 -v modelship-cache:/.cache \
  -v ./models.yaml:/models.yaml \
  ghcr.io/modelship-ai/modelship:latest-cpu start --config /models.yaml

See Model Configuration for the full reference, and config/examples/ for working files per backend.

Native install, any node role — one install command everywhere; pick the role once, at bootstrap:

uv tool install mship      # or: pipx install mship / pip install mship

mship bootstrap --cuda     # NVIDIA GPU node
mship bootstrap --cpu      # CPU node (includes vLLM CPU)
mship bootstrap --metal    # Apple Silicon
mship bootstrap --thin     # coordinator/head only, no capacity

mship start --config models.yaml

mship bootstrap installs a pinned Python 3.12.10 environment for that role and records it, so deploy afterwards needs no variant flag and installs nothing. A new node joins the cluster by running the same two commands. Platform prerequisites apply — see Native install.

High-throughput GPU serving — use --loader vllm with safetensors or AWQ/GPTQ/FP8 weights instead of GGUF, and set HF_TOKEN for gated models. Multi-node — join hosts into one Ray cluster with plain docker run, or deploy on Kubernetes with the Helm chart.

Documentation

Full docs are hosted at docs.model-ship.ai. The same source files are browsable in this repo:

Contributing

See CONTRIBUTING.md for guidelines on setting up the dev environment, code style, and submitting pull requests.

Metadata

Release files for mship-engine 0.9.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mship-engine 0.9.0
File Size Uploaded Provenance
mship_engine-0.9.0.tar.gz 240.2 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for mship-engine 0.9.0
File Interpreter ABI Platform
mship_engine-0.9.0-py3-none-any.whl Python 3 none any Details

Total release size: 530.0 kB

Release files / mship_engine-0.9.0.tar.gz

Download URL mship_engine-0.9.0.tar.gz
Size 240.2 kB
Tags Source
SHA-256 checksum
How to use checksums
0adb423d1dce7fb563e48e916a3b09e944a9b42825724487ebca55e5a94f9fd9
BLAKE2b-256 checksum
How to use checksums
ca7b7115353763fa10c478f3489cf807493ae8daf92a05ffe00d3befa970ccb7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / mship_engine-0.9.0-py3-none-any.whl

Download URL mship_engine-0.9.0-py3-none-any.whl
Size 289.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
91d614a68c911da8cfce9ca1c96bbf973e00ba18cd1aa7a21200406029d03a44
BLAKE2b-256 checksum
How to use checksums
5d631271dee1ff32ca72cffb2e91f9a236094a8a140ac1ea6e53bc2eb2fa3848
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for mship-engine 0.9.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page