Implements the HTTP+SSE transport for the MCP server per bead pdftract-g0ro2. All acceptance criteria PASS. Routes: - POST /: JSON-RPC requests (single or batch) - GET /sse: Server-Sent Events for notifications - GET /health: Health check (auth-exempt) Key features: - Reuses axum/tokio/tower-http from Phase 6.4 (no new deps) - Bearer token auth (from sibling bead 6.7.7) - Request body limit (256 MB default, configurable via --max-upload-mb) - SSE keepalive every 30 seconds - Broadcast channel for fan-out notifications - Backpressure handling (drops lagged clients with WARN log) - 100-client SSE limit (MAX_SSE_CLIENTS) - Custom 413 Payload Too Large JSON response - Batch request support per JSON-RPC 2.0 spec All 10 integration tests pass: - test_post_tools_list: POST / returns tool catalog - test_get_sse_stream: GET /sse opens SSE stream with keepalive - test_50_concurrent_clients: 50 concurrent clients succeed - test_health_during_load: GET /health returns 200 under load - test_post_batch_request: Batch requests return batch responses - test_post_payload_too_large: POST / over limit returns 413 with JSON body - test_auth_required_for_non_loopback: Bearer auth returns 401 with WWW-Authenticate - test_post_single_request_returns_single_response: Single request returns single response - test_unknown_method: Unknown method returns method_not_found error - test_get_health: GET /health returns 200 with version info Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
49 lines
1.3 KiB
TOML
49 lines
1.3 KiB
TOML
[package]
|
|
name = "pdftract-cli"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
rust-version.workspace = true
|
|
license.workspace = true
|
|
repository.workspace = true
|
|
publish = true
|
|
|
|
[[bin]]
|
|
name = "pdftract"
|
|
path = "src/main.rs"
|
|
test = true
|
|
|
|
[[bin]]
|
|
name = "generate_lzw_fixtures"
|
|
path = "../../tests/fixtures/generate_lzw_fixtures_main.rs"
|
|
|
|
default-run = "pdftract"
|
|
|
|
[dependencies]
|
|
anyhow = { workspace = true }
|
|
async-stream = "0.3"
|
|
axum = { version = "0.7", features = ["json"] }
|
|
chrono = { version = "0.4", features = ["serde"] }
|
|
clap = { version = "4.5", features = ["derive"] }
|
|
hyper = { version = "1.0", features = ["full"] }
|
|
hyper-util = { version = "0.1", features = ["full"] }
|
|
http-body-util = "0.1"
|
|
lzw = { workspace = true }
|
|
pdftract-core = { path = "../pdftract-core" }
|
|
regex = "1.10"
|
|
secrecy = { workspace = true }
|
|
serde = { workspace = true, features = ["derive"] }
|
|
serde_json = "1.0"
|
|
tempfile = "3"
|
|
tera = "1"
|
|
tokio = { version = "1", features = ["full"] }
|
|
tokio-stream = "0.1"
|
|
tower = { version = "0.5", features = ["full"] }
|
|
tower-http = { version = "0.5", features = ["cors", "trace", "limit", "compression-full"] }
|
|
tracing = { workspace = true }
|
|
walkdir = "2"
|
|
|
|
[target.'cfg(unix)'.dependencies]
|
|
libc = "0.2"
|
|
|
|
[dev-dependencies]
|
|
reqwest = { version = "0.12", features = ["blocking", "json", "rustls-tls"], default-features = false }
|