api-server-mcp
GitHub提供基于Axum的REST API服务及MCP协议集成,支持文档提取、异步任务处理及缓存管理。涵盖路由定义、中间件配置、错误处理机制及MCP工具/资源接口实现。
Trigger Scenarios
Install
npx skills add xberg-io/xberg --skill api-server-mcp -g -y
SKILL.md
Frontmatter
{
"name": "api-server-mcp",
"priority": "critical",
"description": "REST API server and MCP protocol integration"
}
API Server & MCP Protocol
Axum server for document extraction, plus the rmcp Model Context Protocol surface
Locations: crates/xberg/src/api/ (router.rs, handlers.rs, startup.rs, types.rs,
error.rs, jobs.rs) and crates/xberg/src/mcp/. There is no api/server.rs.
REST routes
Registered in api/router.rs, all on one Router:
| Route | Handler |
|---|---|
POST /extract |
extract_handler — multipart files, URL fields, or JSON; builds ExtractInput |
POST /extract-async |
extract_async_handler — queues a job |
GET/DELETE /jobs/{job_id} |
job_status_handler / cancel_job_handler |
POST /detect |
detect_handler |
GET /formats |
formats_handler |
GET /health |
health_handler |
GET /info, GET /version |
info_handler, version_handler |
GET /cache/stats |
cache_stats_handler |
DELETE /cache/clear |
cache_clear_handler |
GET /cache/manifest, POST /cache/warm |
cache_manifest_handler, cache_warm_handler |
PUT /process, POST /v1/convert/file |
openweb_external_handler, openweb_docling_handler (api/openweb.rs) |
GET /openapi.json |
openapi_schema_handler (feature api) |
GET /metrics |
metrics_handler (feature prometheus) |
There is no POST /extract-url (URL ingestion is a field on ExtractInput passed to
/extract) and no POST /batch (batch is /extract-async + /jobs/{job_id}).
Middleware, in order: DefaultBodyLimit::max(limits.max_request_body_bytes) +
RequestBodyLimitLayer (default 100 MB), CORS, request-id, compression, catch-panic,
sensitive-header stripping, tracing. CORS is built explicitly as
CorsLayer::new().allow_origin(Any).allow_methods(Any).allow_headers(Any) and warns loudly;
restrict it with XBERG_CORS_ORIGINS.
Caching
crates/xberg/src/cache/ — GenericCache is a filesystem-backed store with LRU-style
eviction, not an in-memory map. Keys are BLAKE3 content hashes (blake3_hash_bytes /
blake3_hash_file, cache/utilities.rs). Eviction is bounded by max_age_days,
max_cache_size_mb and min_free_space_mb — there is no entry-count limit.
Error handling
ApiError is a struct, not an enum: { status: StatusCode, body: ErrorResponse }
(api/error.rs). Status comes from the constructor, not a variant:
validation()→ 400,unprocessable()→ 422,internal()→ 500,bad_gateway()→ 502From<XbergError>picks one viaerror.api_status_category()(Validation/Unprocessable/Internal)
There is no 404, 413 or 503 path with a named variant. Do not match on ApiError.
MCP
crates/xberg/src/mcp/. Transport is a single nested rmcp streamable-HTTP service —
Router::new().nest_service("/mcp", http_service) — not a set of /mcp/* REST paths.
Tools, resources and prompts are JSON-RPC methods on it. Stdio transport serves the same
router over stdin/stdout.
Tools (9)
extract, extract_batch, detect_mime_type, list_formats, cache_stats, cache_clear,
get_version, cache_manifest, cache_warm. The set is pinned by
test_all_tools_are_registered in mcp/server.rs. There is no get_capabilities.
extract, extract_batch and cache_warm are task-eligible (TASK_ELIGIBLE_TOOLS,
mcp/server.rs).
Resources
mcp/resources.rs: xberg://formats, xberg://models, xberg://languages/ocr, plus
xberg://presets/embeddings behind #[cfg(feature = "embeddings")].
Prompts (3)
mcp/prompts.rs: extract_document, extract_with_ocr, semantic_search.
Environment variables
There is no .env.example. Server-side vars are read in core/server_config/env.rs:
XBERG_HOST,XBERG_PORT(defaults127.0.0.1:8000)XBERG_MAX_REQUEST_BODY_BYTES,XBERG_MAX_MULTIPART_FIELD_BYTES(both default 100 MB)XBERG_CORS_ORIGINS(comma-separated)
Extraction-side vars are documented on ExtractionConfig::apply_env_overrides
(core/config/extraction/env.rs) — XBERG_OCR_BACKEND, XBERG_OCR_LANGUAGE,
XBERG_CHUNKING_MAX_CHARS, XBERG_CACHE_ENABLED, XBERG_LLM_*, and others. Read that doc
comment rather than guessing a name.
Critical Rules
REST
- Validate uploads — MIME type, size, magic bytes; never trust the filename.
- Size limits are configurable — always read
limits.max_request_body_bytes, never hardcode. - Errors must be actionable — include the operation and a remediation hint in
ErrorResponse. - CORS is permissive by default — production deployments must set
XBERG_CORS_ORIGINS. - Long work goes to
/extract-async— do not block a request thread on a multi-minute extraction.
MCP
- Register a new tool in
mcp/server.rsand extendtest_all_tools_are_registered— the test is the contract. - Feature-gate resources the same way
xberg://presets/embeddingsis — a missing feature must not breakresources/list. - Resources are static — no network or filesystem scans in a resource handler.
- Tools need timeouts — a hung tool blocks the agent.
Related Skills
- extraction-pipeline-patterns — the core extraction the handlers and tools call
- chunking-embeddings — optional chunking/embedding parameters
- config-loading-precedence — server-mode precedence and env overrides
Version History
-
d8e4815
Current 2026-08-28 18:30
修正了过时的API描述,移除了不存在的端点(如POST /extract-url, POST /batch),更新了MCP传输方式及工具列表,并清理了与实际代码不符的类型和规则。
- 531e0f7 2026-08-20 07:47


