tao.chenandClaude 2537976722 rm: list_applications 加 limit/queue + 日志 fallback 链补 NM 直连
P0 (Python parity 缺口):
  - rm.Client.ListApps 新增 queue + limit 查询参数
  - list_applications MCP tool schema 暴露 queue (string) 和 limit
    (number, default 100), handler 透传给 RM client
  - 限流原因: 生产 RM 上无 limit 会拉回 N MB JSON 撞 MaxResponseBytes
  - limit <= 0 不发送 query 参数, 跟 RM 默认行为一致; 老的调用方
    (TestListApplications_EndToEnd 等) 不传参时行为不变
  - 4 个旧 ListApps 测试调用点跟着更新, 加 3 个新测试:
    TestListApps_WithLimit, TestListApps_WithQueue,
    TestListApps_LimitZeroNoParam

P1.3 (Python fallback 行为补全):
  - rm.Client.GetLogs 加第 4 步 fallback: 当前 3 步
    (amContainerLogs/aggregated-logs/logs) 全失败时, 调 GetApp
    解析 app.amContainerLogs 字段, GET 该 URL 直连 NodeManager
  - 新 source 名 'amContainerLogs-direct' 区分 RM-level endpoint
  - 提取 doBytesWithHosts(extraHosts...) 支持 per-call host 白名单,
    NM host 动态加进 allowedHosts, SSRF 保护不破 (URL 是 RM 响应里
    回来的, 不是 LLM 任意填的)
  - 新增 TestGetLogs_FallbackToAMDirect (成功路径) 和
    TestGetLogs_FallbackFailsWhenAMFieldMissing (amContainerLogs
    字段为空时正常返回 error)

P1.4 (零代码改动 + 文档化):
  - get_application_logs / get_application_status 工具 description
    更新, 提示 LLM raw RM JSON 里包含 amContainerLogs 字段, 可在
    aggregated-logs 全部失败时自己用 fetch_url 直连 NM
  - get_application_status 函数体不变 (本就是透传 raw JSON)

验证:
  - go build / go vet / go test 全部通过
  - 5 个新测试全 PASS, 老的 TestListApplications_EndToEnd 仍 PASS
  - 单 ListApps 调用点 (list_applications.go:81) 编译过

未提交: spark-mcp-linux-amd64 (本地 build 产物, 当前 .gitignore
没拦, 需另行决定)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-13 15:15:21 +08:00
2026-07-10 10:19:28 +08:00

spark-mcp-go

MCP (Model Context Protocol) server for Apache Spark on YARN. Lets an LLM agent discover Spark/YARN endpoints, submit jobs, fetch logs, and analyze them via 11 typed Tools. Streamable HTTP transport, SQLite-backed configuration, and log/slog structured logging with per-Tool call files.

What it does

  • Exposes 11 MCP Tools over Streamable HTTP at /mcp
  • Admin API at /admin/* for cluster and audit configuration
  • HTTP Basic and YARN SimpleAuth for Spark/YARN endpoints
  • SSRF protection with cluster URL allowlist plus DNS rebinding guard
  • Per-Tool independent audit log (file mode 0600)
  • spark-submit via local exec.Command (no shell, no injection)

Quick start (3 steps)

  1. Copy and edit the environment file:

    cp .env.example .env
    # Edit ADMIN_TOKENS and AGENT_TOKEN
    
  2. Build and start the server:

    go build ./...
    ./spark-mcp-go
    # Or use the helper:
    # ./scripts/dev.sh
    
  3. Initialize an MCP session, then call list_clusters to discover endpoints.

11 Tools

Tool Type Purpose
list_clusters discovery Return all active clusters (LLM entry point)
spark_submit exec Local spark-submit process, extracts app_id
list_applications RM GET /ws/v1/cluster/apps[?state=&user=]
get_application_status RM GET /ws/v1/cluster/apps/{id}
get_application_logs RM Fallback chain: amContainerLogs -> aggregated-logs -> logs
kill_application RM PUT state KILLED
fetch_spark_metrics SHS Executor metrics + summary mode triggers analyzer
fetch_cluster_env RM Aggregate /cluster/info and /cluster/metrics
analyze_spark_log analyzer RM logs + heuristic rules + LLM-ready prompt
fetch_url HTTP Generic primitive, uses cluster allowlist and auth
upload_file FS Write to ./data/uploads/, reference from spark_submit

Environment variables

Variable Default Required Description
LISTEN_ADDR :8080 no HTTP listen address
DATA_DIR ./data no SQLite, uploads, and log root
ADMIN_TOKENS yes Comma-separated tokens for /admin/*
AGENT_TOKEN yes Token for /mcp requests
HTTP_CLIENT_TIMEOUT 30s no Timeout for fetch_url/RM Tool HTTP calls
MAX_RESPONSE_BYTES 1048576 (1 MiB) no HTTP response truncation limit
SPARK_SUBMIT_TIMEOUT 60s no spark-submit process timeout
LOG_DIR ./data/logs no Log root directory
LOG_LEVEL info no debug, info, warn, or error
LOG_FORMAT text no text for terminal, json for log files
ANALYZER_DATA_SKEW_RATIO 3.0 no Data-skew rule threshold (max/min ratio)
ANALYZER_GC_PRESSURE_RATIO 0.1 no GC-pressure rule threshold (GC/CPU ratio)
ANALYZER_BOTTLENECK_SHUFFLE_GB 50 no Bottleneck rule threshold (shuffle GB)

Admin API

All endpoints require Authorization: Bearer <admin_token>.

Method Path Description
GET /admin/clusters List all clusters
POST /admin/clusters Create a cluster
GET /admin/clusters/:id Get one cluster
PUT /admin/clusters/:id Update a cluster
DELETE /admin/clusters/:id Delete a cluster
GET /admin/audit?limit=100 Query audit log

Create a cluster:

curl -sS -X POST \\
  -H "Authorization: Bearer ${ADMIN_TOKEN}" \\
  -H "Content-Type: application/json" \\
  -d '{
    "id": "prod",
    "name": "prod",
    "rm_url": "http://rm.example.com:8088",
    "shs_url": "http://shs.example.com:18080",
    "spark_submit_execute_bin": "/opt/spark/bin/spark-submit",
    "is_active": true,
    "auth_type": "simple",
    "auth_username": "yarn",
    "rate_limit_per_min": 10,
    "url_allowlist": ["rm.example.com:8088", "shs.example.com:18080"]
  }' \\
  "http://127.0.0.1:${LISTEN_ADDR:-:8080}/admin/clusters"

Note: auth_password is not accepted via JSON (json:"-"). Set it through a dedicated password endpoint or seed the database directly.

Security model

Three lines of defense:

  1. Token auth - ADMIN_TOKENS protects /admin/*; AGENT_TOKEN protects /mcp.
  2. SSRF guard - Every outbound URL must match the cluster's url_allowlist, with private-IP CIDR blacklist (incl. 169.254.0.0/16 AWS/GCP metadata).
  3. Path allowlist - upload_file writes only to ./data/uploads/, rejects absolute paths, .., and non-[a-zA-Z0-9._-] filenames.

Additional guarantees:

  • spark_submit runs the cluster's binary via exec.Command(name, args...) — slice form, never sh -c. No shell metacharacter interpretation.
  • auth_password is tagged json:"-"; never serialized in responses, never accepted from JSON request bodies.
  • Cross-host redirects (RM → NM 307) preserve the Authorization header through DoWithRedirect only when the destination host is in url_allowlist.
  • Per-Tool log files are created with mode 0600 and live under ./data/logs/tools/.

Development

go build ./...
go test ./...
go vet ./...

More docs

S
Description
No description provided
Readme
268 KiB
2026-07-15 16:37:20 +08:00
Languages
Go 86.5%
HTML 12.6%
Shell 0.9%