Skip to content

feat(server): add Anthropic-style /v1/messages API endpoint - #74

Merged
inureyes merged 1 commit into
mainfrom
feat/73-anthropic-messages-api
May 24, 2026
Merged

inureyes merged 1 commit into
mainfrom
feat/73-anthropic-messages-api

Conversation

@inureyes

Copy link
Copy Markdown
Member

Closes #73

Adds an Anthropic Messages-compatible API surface to mlxcel-server so clients written against the Anthropic schema can use the server without a translation shim. Ported from upstream mlx-vlm server/anthropic.py (PR #1196) plus the tool-result image-handling fix (PR #1200).

New endpoints

  • POST /v1/messages (and /messages alias): create a message, synchronous or SSE streaming.
  • POST /v1/messages/count_tokens (and /messages/count_tokens alias): prompt token count.

What it covers

  • Request schema: top-level system (string or text-block array), messages, max_tokens, stop_sequences, temperature/top_p/top_k, function tools + tool_choice, and thinking.
  • Content blocks: text, image (base64 and url), tool_use, and tool_result, including image content nested inside tool_result blocks so vision models consume tool-produced images.
  • Streaming: the Anthropic SSE event sequence (message_start, content_block_start/delta/stop, message_delta, message_stop, error) with usage populated on both the non-streaming response and the streaming message_delta.
  • Reuses the existing generation, chat-template, media, tool-call, and thinking-budget plumbing rather than duplicating the generation loop, structured like the existing Responses API endpoint.
  • Both the message and count_tokens routes reject oversized tool arrays via the shared MAX_TOOLS bound to prevent template-rendering DoS.

Files

  • types/anthropic_request.rs, anthropic_response.rs, anthropic_stream.rs: inbound/outbound types + typed SSE event enum.
  • anthropic_translator.rs: request translation, outbound content-block assembly, stop-reason mapping, stop-sequence truncation.
  • streaming_anthropic.rs: SSE channel + content-block index state machine.
  • routes/anthropic.rs: thin handlers; route registration in app.rs; module wiring in types/mod.rs, mod.rs, routes/mod.rs.

Notes

User-facing API documentation is deferred to a follow-up; this PR is the functional endpoint plus tests.

Verification

  • cargo fmt --check clean.
  • cargo clippy --features metal,accelerate --all-targets -- -D warnings clean.
  • 44 new unit tests pass, covering request translation, content-block assembly, stop-reason mapping, the tools DoS guard, and the streaming state machine.

Add an Anthropic Messages-compatible API surface to mlxcel-server so clients written against the Anthropic schema can use the server without a translation shim. Ported from upstream mlx-vlm `server/anthropic.py` (PR #1196) plus the tool-result image-handling fix (PR #1200).

New endpoints:

- `POST /v1/messages` (and `/messages` alias): create a message, synchronous or SSE streaming.
- `POST /v1/messages/count_tokens` (and `/messages/count_tokens` alias): prompt token count.

The request schema covers the Anthropic surface: top-level `system` (string or text-block array), `messages`, `max_tokens`, `stop_sequences`, `temperature`/`top_p`/`top_k`, function `tools` + `tool_choice`, and `thinking`. Content blocks support `text`, `image` (base64 and url), `tool_use`, and `tool_result`, including image content nested inside `tool_result` blocks so vision models consume tool-produced images. Streaming emits the Anthropic SSE sequence (`message_start`, `content_block_start`/`delta`/`stop`, `message_delta`, `message_stop`, `error`) with `usage` populated on both the non-streaming response and the streaming `message_delta`.

The implementation reuses the existing generation, chat-template, media, tool-call, and thinking-budget plumbing rather than duplicating the generation loop:

- `types/anthropic_request.rs`, `anthropic_response.rs`, `anthropic_stream.rs`: inbound/outbound Anthropic types and the typed SSE event enum.
- `anthropic_translator.rs`: Anthropic request to internal `ChatCompletionRequest` (system/messages/tools/tool_choice, image-in-tool-result), plus outbound content-block assembly, stop-reason mapping, and stop-sequence truncation, mirroring the Responses API translator.
- `streaming_anthropic.rs`: the SSE channel and the content-block index state machine.
- `routes/anthropic.rs`: thin handlers that call `prepare_chat_request_with_cache`, `build_generate_options`, the model provider, and the shared tool-call helpers. Both the message and count_tokens routes reject oversized tool arrays via the shared `MAX_TOOLS` bound to prevent template-rendering DoS.
- Route registration in `app.rs`; module wiring in `types/mod.rs`, `mod.rs`, `routes/mod.rs`.

User-facing API documentation is deferred to a follow-up; this change is the functional endpoint plus its unit tests. Verified with cargo fmt, cargo clippy (metal,accelerate, all-targets, -D warnings), and 44 new unit tests covering request translation, content-block assembly, stop-reason mapping, the tools DoS guard, and the streaming state machine.
@inureyes inureyes added type:enhancement New features, capabilities, or significant additions priority:medium Medium priority area:inference Generation, sampling, decoding (incl. speculative, DRY) labels May 24, 2026
@inureyes
inureyes merged commit 49ff6dd into main May 24, 2026
4 checks passed
@inureyes
inureyes deleted the feat/73-anthropic-messages-api branch May 24, 2026 14:02
@inureyes inureyes self-assigned this May 25, 2026
inureyes added a commit that referenced this pull request May 26, 2026
Bump version to 0.0.31. Highlights: MiniCPM-V 4.6 and RT-DETRv2 model support plus an Anthropic-style /v1/messages API endpoint (#82, #80, #74); fixes for missing or null chat-message content, Gemma 3n VLM per_layer_inputs, Qwen3.5 MTP verify attention, and batched quantized KV cache mask offsets (#91, #86, #78, #76); and a pinned 1.93.1 Rust toolchain (#87, #90).
@inureyes inureyes added this to the 0.1 milestone Jun 21, 2026
@inureyes inureyes added the status:done Completed label Sep 6, 2026
be-free-snowboy pushed a commit to freestylejs/snowbrain-mlxcel that referenced this pull request Oct 27, 2026
Add an Anthropic Messages-compatible API surface to mlxcel-server so clients written against the Anthropic schema can use the server without a translation shim. Ported from upstream mlx-vlm `server/anthropic.py` (PR lablup#1196) plus the tool-result image-handling fix (PR lablup#1200).

New endpoints:

- `POST /v1/messages` (and `/messages` alias): create a message, synchronous or SSE streaming.
- `POST /v1/messages/count_tokens` (and `/messages/count_tokens` alias): prompt token count.

The request schema covers the Anthropic surface: top-level `system` (string or text-block array), `messages`, `max_tokens`, `stop_sequences`, `temperature`/`top_p`/`top_k`, function `tools` + `tool_choice`, and `thinking`. Content blocks support `text`, `image` (base64 and url), `tool_use`, and `tool_result`, including image content nested inside `tool_result` blocks so vision models consume tool-produced images. Streaming emits the Anthropic SSE sequence (`message_start`, `content_block_start`/`delta`/`stop`, `message_delta`, `message_stop`, `error`) with `usage` populated on both the non-streaming response and the streaming `message_delta`.

The implementation reuses the existing generation, chat-template, media, tool-call, and thinking-budget plumbing rather than duplicating the generation loop:

- `types/anthropic_request.rs`, `anthropic_response.rs`, `anthropic_stream.rs`: inbound/outbound Anthropic types and the typed SSE event enum.
- `anthropic_translator.rs`: Anthropic request to internal `ChatCompletionRequest` (system/messages/tools/tool_choice, image-in-tool-result), plus outbound content-block assembly, stop-reason mapping, and stop-sequence truncation, mirroring the Responses API translator.
- `streaming_anthropic.rs`: the SSE channel and the content-block index state machine.
- `routes/anthropic.rs`: thin handlers that call `prepare_chat_request_with_cache`, `build_generate_options`, the model provider, and the shared tool-call helpers. Both the message and count_tokens routes reject oversized tool arrays via the shared `MAX_TOOLS` bound to prevent template-rendering DoS.
- Route registration in `app.rs`; module wiring in `types/mod.rs`, `mod.rs`, `routes/mod.rs`.

User-facing API documentation is deferred to a follow-up; this change is the functional endpoint plus its unit tests. Verified with cargo fmt, cargo clippy (metal,accelerate, all-targets, -D warnings), and 44 new unit tests covering request translation, content-block assembly, stop-reason mapping, the tools DoS guard, and the streaming state machine.
be-free-snowboy pushed a commit to freestylejs/snowbrain-mlxcel that referenced this pull request Oct 27, 2026
Bump version to 0.0.31. Highlights: MiniCPM-V 4.6 and RT-DETRv2 model support plus an Anthropic-style /v1/messages API endpoint (lablup#82, lablup#80, lablup#74); fixes for missing or null chat-message content, Gemma 3n VLM per_layer_inputs, Qwen3.5 MTP verify attention, and batched quantized KV cache mask offsets (lablup#91, lablup#86, lablup#78, lablup#76); and a pinned 1.93.1 Rust toolchain (lablup#87, lablup#90).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:inference Generation, sampling, decoding (incl. speculative, DRY) priority:medium Medium priority status:done Completed type:enhancement New features, capabilities, or significant additions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(server): add Anthropic-style /v1/messages API endpoint

1 participant