ai-protocol-mock
Unified mock server for AI-Protocol runtimes. Provides HTTP provider mock (OpenAI and Anthropic formats) and MCP JSON-RPC mock for testing ai-lib-python, ai-lib-rust, and other runtimes.
Features
- Manifest-driven HTTP mock: Generates responses in OpenAI or Anthropic format based on provider manifests
- STT / TTS / Rerank mock: Simulates speech-to-text, text-to-speech, and document reranking endpoints (OpenAI/Cohere compliant)
- MCP JSON-RPC mock: Implements
tools/list,tools/call,capabilities,initialize - Configurable: Response delay, error rate, mock content via environment variables
- Docker: One-command startup with
docker-compose up
Quick Start
# Install and run
pip install -e .
python scripts/sync_manifests.py --force # Sync manifests from ai-protocol
uvicorn ai_protocol_mock.main:app --host 0.0.0.0 --port 4010
Or with Docker:
docker-compose up -d
Configuration
| Variable | Default | Description |
|---|---|---|
| HTTP_PORT | 4010 | Port for HTTP and MCP (MCP at /mcp) |
| MANIFEST_DIR | manifests | Directory for synced manifests |
| MANIFEST_SYNC_URL | https://raw.githubusercontent.com/ailib-official/ai-protocol/d61b701…/ | Source for manifest sync (PROTO-PIN ai-protocol v1.2.0) |
| AI_PROTOCOL_TAG | (optional) | Convenience alias; docker-compose sets the same PROTO-PIN commit |
| RESPONSE_DELAY | 0 | Delay in seconds before responding |
| ERROR_RATE | 0 | Probability (0-1) of returning 429/500/503 |
| MOCK_CONTENT | Mock response from ai-protocol-mock | Default response content |
Test Control Headers (X-Mock-*)
For integration tests, requests can include these headers to control mock behavior:
| Header | Description | Example |
|---|---|---|
| X-Mock-Status | Force HTTP error status (400-599) | 429, 500, 503 |
| X-Mock-Content | Override response content for this request | Custom text |
| X-Mock-Tool-Calls | Return tool_calls instead of text; parallel or recursive for multi-tool scenarios |
1, parallel, recursive |
| X-Mock-Reasoning | Include reasoning/thinking blocks in chat response | true |
| X-Mock-Error | Inject standard errors (context_overflow, content_filter, rate_limit, stream_interrupt) |
rate_limit |
| X-Mock-Usage-Format | Enrich usage payload (openai or anthropic shape) |
openai |
| X-Mock-Tool-Depth | Max recursive tool-call rounds (with recursive) |
2 |
| X-Mock-Invalid-Content-Type | Inject text/plain payload for robustness tests |
1 |
| X-Mock-Video-Terminal | Force async video terminal state (succeeded/failed/cancelled) |
failed |
Endpoints
POST /v1/chat/completions- OpenAI-format chatPOST /v1/messages- Anthropic-format chatPOST /v1/audio/transcriptions- STT (OpenAI Whisper format), returns{"text": "..."}POST /v1/audio/speech- TTS (OpenAI format), returnsaudio/mpegbytesPOST /v2/rerank- Rerank (Cohere v2 format), request{query, documents, top_n}, returns{results, id, meta}POST /v1/video/generations- Video generation (sync + async polling)GET /v1/video/generations/{job_id}- Poll async video generation statusPOST /mcp- MCP JSON-RPC (tools/list,tools/call,capabilities,initialize)GET /health- Health checkGET /status- Status with manifest sync metadataGET /providers- Provider contracts from manifests (provider_id, api_style, chat_path, capability_profile summary)
Video Generation Lifecycle
Async video generation jobs follow a deterministic state machine:
queued -> running -> terminal
Terminal states:
succeeded(default): returnsoutputwith mock mp4 metadatafailed: returnserrorpayload (video_generation_failed)cancelled: returnscancellationpayload (mock_cancelled_for_test)
Controls:
- request body
terminal_stateor headerX-Mock-Video-Terminal - unknown values fall back to
succeeded
Using with ai-lib-python
import os
os.environ["MOCK_HTTP_URL"] = "http://localhost:4010"
from ai_lib_python.client import AiClient
from ai_lib_python.types.message import Message
client = await AiClient.create(
"openai/gpt-4o",
api_key="sk-test",
base_url="http://localhost:4010"
)
response = await client.chat().messages([Message.user("Hi")]).execute()
print(response.content)
Or run tests with mock:
MOCK_HTTP_URL=http://localhost:4010 MOCK_MCP_URL=http://localhost:4010/mcp pytest tests/ -v
Third-Party Integration (ZeroClaw, etc.)
ai-protocol-mock is designed for downstream runtimes and frameworks that need deterministic testing without real API calls:
- ZeroClaw / ZeroSpider: Set
MOCK_HTTP_URLandMOCK_MCP_URLto the mock server (e.g.http://192.168.2.13:4010) before running integration tests. UseNO_PROXYto bypass HTTP proxies when testing against a local or LAN mock. - CI pipelines: Start mock via
docker-compose up -doruvicorn ai_protocol_mock.main:app --host 0.0.0.0 --port 4010, then run tests with the env vars above. - Error injection: Set
ERROR_RATE=0.1to simulate 429/500/503 for resilience testing.
Remote / proxy environments: If your machine uses HTTP/HTTPS proxy, set NO_PROXY to include the mock server IP so Python's httpx can reach it directly:
NO_PROXY=192.168.2.13,localhost,127.0.0.1 MOCK_HTTP_URL=http://192.168.2.13:4010 MOCK_MCP_URL=http://192.168.2.13:4010/mcp pytest tests/ -v
Using with ai-lib-rust
export MOCK_HTTP_URL=http://localhost:4010
cargo run --example basic_usage
Or run mock integration tests:
MOCK_HTTP_URL=http://localhost:4010 MOCK_MCP_URL=http://localhost:4010/mcp cargo test -- --ignored --nocapture
Or in code:
let client = AiClientBuilder::new()
.base_url_override("http://localhost:4010")
.build("openai/gpt-4o")
.await?;
Manifest Sync
Sync manifests from the ai-protocol repository:
python scripts/sync_manifests.py [--force] [--url URL] [--tag REF]
--force- Overwrite existing files--tag REF- Pin to a specific ai-protocol ref (e.g.v1.2.0, commit SHA,main; default URL pins v1.2.0 tip)--url URL- Custom base URL (overrides default pinned release)
Run before starting the server to ensure manifests are up to date. CI and docker-compose should use the PROTO-PIN commit for ai-protocol v1.2.0 so integration tests match the post–GOV-007 release train.
v1.0 migration (from 0.1.x)
| 0.1.x | v1.0+ |
|---|---|
Path heuristics (/messages → Anthropic) |
ContractResolver + manifest streaming.decoder.strategy / ProviderContract |
| Hardcoded JSON shapes only | X-Mock-* generative branches (reasoning, tools, structured output) |
Floating main sync |
Pin a release tip (currently ai-protocol v1.2.0 / PROTO-PIN commit) in CI and sync_manifests.py |
Breaking changes are documented in CHANGELOG; PyPI 1.0.1 ships after four-runtime Mock Integration CI is green (MOCK-001-R4).
Development
pip install -e ".[dev]"
pytest tests/ -v
ruff check src tests scripts
License
MIT OR Apache-2.0
Metadata
Release files for ai-protocol-mock 1.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ai_protocol_mock-1.1.1.tar.gz | 24.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ai_protocol_mock-1.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 55.9 kB
Release files / ai_protocol_mock-1.1.1.tar.gz
| Download URL | ai_protocol_mock-1.1.1.tar.gz |
|---|---|
| Size | 24.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
51f042e20235061803e5d8a7b66df5d61e7a64141a1d249993cbed81ac365f48
|
|
BLAKE2b-256 checksum How to use checksums |
078548e221b835c843bac0aa718b8133845b60c66684f89d8fea1df37a8e0699
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / ai_protocol_mock-1.1.1-py3-none-any.whl
| Download URL | ai_protocol_mock-1.1.1-py3-none-any.whl |
|---|---|
| Size | 31.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b74b092accf7d64b36ad30213c0663776424f81c1298dc8d47c411226f7d4456
|
|
BLAKE2b-256 checksum How to use checksums |
eb459cdc16fc324f3712977c4cbc6cea41a17f2ef81f425d244f9a50ee04b652
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|