Unified LLM protocol abstraction for MoonBit — multi-provider support with streaming, tool calling, and protocol translation
Dependencies
AI Tool / Client MoonBit LLM Gateway LLM Backend
================== ============================== =======================
Claude Code / SDK ----\
POST /v1/messages |
| +----------------------------+
OpenAI Agents SDK -----| | GatewaySurface |
POST /v1/responses |--->| (Anthropic|OpenAI|Gemini |
| | |Codex) |
Codex CLI / VS Code ----| +------------+---------------+
JSON-RPC stdio | |
| +------------v---------------+
MCP Client -----------/ | Dialect Transforms |
MCP stdio | Anthropic <-> OpenAI |
| Gemini <-> OpenAI |
| Responses -> Completions |
| (harmony pipeline) |
+------------+---------------+
|
+------------v---------------+
| Model Aliasing + Routing |
| claude-sonnet-4-6 -> llama3 |
+------------+---------------+
|
+-----------+-----------+
| | |
v v v
OpenAI Anthropic Ollama
Gemini Bedrock Codex
Copilot claude mcp ...| Concept | Description |
|---|---|
| Dialect | A GatewaySurface (OpenAI, Anthropic, Gemini, Codex) that determines which inbound API the gateway exposes. Each surface routes incoming requests to the appropriate transform pipeline. The DialectSpec struct binds a ModelApi to its endpoint paths, auth headers, and surface type. |
| Harmony pipeline | The Responses API compatibility layer. Converts OpenAI Responses API requests (POST /v1/responses) into Chat Completions calls, then maps the response back -- enabling any Chat Completions backend to serve Responses API clients (e.g. OpenAI Agents SDK). |
| Model aliasing | Per-provider model_aliases map that rewrites incoming model names before forwarding. Lets Claude Code send claude-sonnet-4-6 while the gateway routes it to llama3 on Ollama, or any other backend model. Configured in gateway-config.json. |
| SSE streaming | Server-Sent Events parser and serializer for streaming LLM responses. Each dialect has its own stream accumulator that incrementally builds the final response from SSE chunks, handling protocol-specific delta formats (Anthropic content_block_delta, OpenAI choices[].delta, etc.). |
llm_interop/
├── src/ Library packages
│ ├── gateway/ Core gateway: config, types, dialect dispatch, routing
│ ├── dialects/ Protocol transform implementations
│ │ ├── anthropic/ Anthropic Messages API transforms and accumulator
│ │ ├── openai/ OpenAI Chat Completions + Responses API transforms
│ │ ├── gemini/ Google Gemini GenerativeAI transforms
│ │ ├── harmony/ Harmony (gpt-oss) Chat Completions accumulator
│ │ ├── codex/ Codex app-server JSON-RPC transforms
│ │ └── claude_mcp/ `claude mcp serve` subprocess transforms
│ ├── types/ Shared message types (ToolCallRequest, etc.)
│ ├── client/ HTTP client with multi-provider integration tests
│ ├── sse/ SSE parser (JSONL) and serializer
│ ├── jsonrpc/ JSON-RPC 2.0 pure protocol layer
│ ├── mcp/ MCP (Model Context Protocol) pure protocol layer
│ ├── spawn/ Shell-safe command builder for subprocess execution
│ ├── interop/ Fixture-based protocol interop tests
│ │ └── util/ Test utilities
│ ├── utils/ JSON manipulation and string helpers
│ └── wasm-gc/ WebAssembly (wasm-gc) build artifacts
│ └── release/ Release binaries
├── cmd/ Executable entry points
│ ├── gateway-native/ HTTP gateway server (native target)
│ ├── app-server/ Codex app-server frontend (JSON-RPC over stdio)
│ ├── claude-mcp-server/ MCP server frontend (emulates `claude mcp serve`)
│ └── js-test-demo/ JS target test/demo runner
└── examples/ Usage examples and integration guidesollama pull llama3cd cmd/gateway-native
moon build --target nativecd cmd/gateway-native
moon run --target native . -- \
--dialect anthropic \
--config ../../examples/claude-agent-sdk/gateway-config.jsonANTHROPIC_BASE_URL=http://localhost:18080 \
ANTHROPIC_AUTH_TOKEN=dummy \
claude --model sonnet --print "What is 2+2?"| Dialect | Incoming API | Typical client | Description |
|---|---|---|---|
| anthropic | Anthropic Messages (POST /v1/messages) | Claude Code, Claude Agent SDK | Translates Anthropic Messages API to OpenAI Chat Completions for the backend |
| openai | OpenAI Responses (POST /v1/responses) | OpenAI Agents SDK, Codex CLI | Harmony pipeline: Responses API to Chat Completions |
| gemini | Gemini-compatible | Gemini SDK clients | Translates Gemini requests to Chat Completions |
| codex | OpenAI Responses (POST /v1/responses) | Codex CLI | Responses API proxy optimized for Codex CLI tool-call flows |
{
"providers": {
"ollama": {
"baseUrl": "http://localhost:11434/v1",
"api": "openai-completions",
"modelsFromEndpoint": false,
"modelPatterns": ["llama", "claude-"],
"modelAliases": {
"claude-sonnet-4-6": "llama3"
},
"models": [
{
"id": "llama3",
"name": "Llama 3",
"reasoning": false,
"input": ["text"],
"contextWindow": 8192,
"maxTokens": 4096
}
]
}
},
"server": {
"port": 18080,
"host": "0.0.0.0"
}
}| Field | Type | Description |
|---|---|---|
| baseUrl | string | Backend API base URL (must expose /v1/chat/completions) |
| api | string | Backend API type (e.g. "openai-completions") |
| modelsFromEndpoint | bool | Whether to fetch available models from the backend's /v1/models endpoint |
| modelPatterns | string[] | Glob patterns for model names this provider handles |
| modelAliases | object | Rewrites incoming model names before forwarding (e.g. map Claude model names to local model names) |
| models | object[] | Explicit model definitions with id, name, reasoning, input, contextWindow, maxTokens |
| Field | Type | Description |
|---|---|---|
| port | number | Port the gateway listens on |
| host | string | Bind address (e.g. "0.0.0.0" for all interfaces, "127.0.0.1" for localhost only) |
# 1. Pull a model
ollama pull llama3
# 2. Start the gateway with anthropic dialect
cd cmd/gateway-native
moon run --target native . -- \
--dialect anthropic \
--config ../../examples/claude-agent-sdk/gateway-config.json
# 3. Run Claude Code against the local gateway
ANTHROPIC_BASE_URL=http://localhost:18080 \
ANTHROPIC_AUTH_TOKEN=dummy \
claude --model sonnet --print "What is 2+2?"# 1. Pull a model
ollama pull llama3
# 2. Start the gateway
cmd/gateway-native/_build/native/debug/build/llm_interop-gateway-native.exe \
-c examples/codex/gateway-config.json
# 3. Run Codex CLI against the gateway
codex -m "llama3" \
-c 'model_providers.gw.name="Gateway"' \
-c 'model_providers.gw.base_url="http://localhost:18080/v1"' \
-c 'model_provider="gw"' \
exec "List the files in the current directory"| Surface | Dialect | Endpoint | Direction |
|---|---|---|---|
| Anthropic Messages | src/dialects/anthropic/ | POST /v1/messages | Inbound & Outbound |
| Chat Completions (OpenAI-compatible) | src/dialects/openai/ | POST /v1/chat/completions | Inbound & Outbound |
| Responses API (OpenAI Harmony) | src/dialects/harmony/ | POST /v1/responses | Inbound & Outbound |
| Gemini | src/dialects/gemini/ | POST /v1beta/models/{model}:generateContent | Inbound & Outbound |
| Codex | src/dialects/codex/ | App server protocol | Inbound |
| Claude MCP | src/dialects/claude_mcp/ | MCP tool serving | Inbound |
| Package | Purpose |
|---|---|
| src/types/ | Shared type definitions across dialects |
| src/interop/ | Cross-dialect conversion logic |
| src/gateway/ | Request routing and dispatch |
| src/client/ | HTTP client for outbound requests |
| src/sse/ | Server-Sent Events streaming |
| src/jsonrpc/ | JSON-RPC protocol support |
| src/mcp/ | Model Context Protocol primitives |
| src/spawn/ | Process spawning utilities |
| src/utils/ | Shared utilities |
| src/wasm-gc/ | Wasm-GC target support |
| Target | Path | Purpose |
|---|---|---|
| App Server | cmd/app-server/ | Codex app server |
| Claude MCP Server | cmd/claude-mcp-server/ | Claude Code MCP server |
| Native Gateway | cmd/gateway-native/ | HTTP gateway (separate module) |
| JS Test Demo | cmd/js-test-demo/ | JS target demo/test |
make check # Type-check for native and js targets
make test # Run unit tests for native and js targets
make info # Generate .mbti interface files
make verify # Run check + test + info (full local verification)make check-native # Type-check native only
make check-js # Type-check js only
make test-native # Test native only
make test-js # Test js onlymake test-integration PROVIDER=anthropic # Requires ANTHROPIC_API_KEY
make test-integration PROVIDER=openai # Requires OPENAI_API_KEY
make test-integration PROVIDER=groq # Requires GROQ_API_KEYmake gateway # Run the native gateway with gateway-config.jsonmake demo-js # moon run --target js cmd/js-test-demo
make test-js-demo # moon test --target js cmd/js-test-demoUnified LLM protocol abstraction for MoonBit — multi-provider support with streaming, tool calling, and protocol translation
Dependencies