🎃 Add an opt-in Prometheus /metrics endpoint for tool calls
Maintainer thường phản hồi trong vòng 1 ngày
@rangarajan19 đang làm issue này rồi.
Từ ngày 17/10/2026.
Đánh giá
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức phù hợp với người mới
- 56/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- grafana, nodejs, prometheus, typescript
- Lĩnh vực
- backend, observability
Hướng nghiên cứu
Start with logToolCall() in packages/backend/src/mcp-server/dynamic-mcp-tools.ts, where the metrics recording belongs, and with tracing.ts as the env-gated no-op pattern to copy. Then read processGauges.snapshot() in common/process-vitals.ts, app.listen in main.ts and isCloud() in common/deployment.service.ts. Done means the new src/common/metrics.spec.ts passes via npx jest src/common/metrics, /metrics returns the counters after a tool call, and the Cloud and token rules from the acceptance list hold.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Part of the October Challenge #997.
Why
Operators who self-host AnythingMCP want tool-call rates, error rates and latency in Grafana, next to the rest of their stack. Today they only have the Pino tool_call log lines, which they have to parse themselves, and the database (ToolInvocation). Our ROADMAP lists "per-tool latency histograms, error-rate dashboards". Most self-hosted gateways (Kong, Traefik, n8n) ship a Prometheus endpoint.
Self-hosted vs Cloud
- Self-hosted: off by default. When
METRICS_ENABLED=true, the backend starts a second, separate HTTP listener for/metrics(it does not use the main app port 4000). Available in Community; no licence gate. - Cloud (
DEPLOYMENT_MODE=cloud): the operator (us) uses the same code. Two extra rules: the listener refuses to start withoutMETRICS_TOKEN(it logs an error and metrics stay off), and per-tool/per-connector labels are always off. No series may carry an organization id, connector name, tool name or user. This prevents cross-tenant leaks and keeps cardinality bounded with thousands of workspaces. Per-org usage already exists in the database (AuditService.getBreakdowns). - Who can use it: whoever operates the instance (env vars). There are no app roles, no dashboard UI and no org scoping, because metrics are instance-wide by design. That is why they must never be reachable through the public port.
What to build
- Library: use
prom-client. Recommendation and reasons:@opentelemetry/exporter-prometheuswould hook into the existingNodeSDK(tracing.ts). But that SDK only starts whenOTEL_EXPORTER_OTLP_ENDPOINTis set, its 0.x packages must move in lockstep with@opentelemetry/sdk-node(^0.222.0), and Node runtime metrics need extra packages.prom-clientgivescollectDefaultMetrics()(event loop lag, heap, GC) for free and is trivial to unit-test (await register.metrics()returns a string). Wrap it in a small facade (src/common/metrics.ts:recordToolCall(...)), so a later switch to OTel metrics touches one file. - Env vars:
METRICS_ENABLED(defaultfalse),METRICS_PORT(default9464),METRICS_HOST(default0.0.0.0, because in Docker the Prometheus container must reach it over the compose network; the port is not published indocker-compose.yml),METRICS_TOKEN(optional on self-hosted, required on Cloud, compared withtimingSafeEqual),METRICS_TOOL_LABELS(defaultfalse, ignored on Cloud with a warning). - Listener: a plain
node:httpserver started frommain.tsafterapp.listen(), closed on shutdown. It serves onlyGET /metrics. Any other path returns 404, and a wrong or missing token returns 401. - Metrics (prefix
anythingmcp_):tool_calls_total{connector_type,status}counter (status =success|error)tool_call_duration_seconds{connector_type,status}histogram (buckets roughly 0.05 to 60 s; tool calls can take 20 s or more)tool_call_upstream_errors_total{connector_type,upstream_status_class}(4xx|5xx|none)- with
METRICS_TOOL_LABELS=true(self-hosted only), addconnector_idandtoollabels. Use the connector id (cuid), not the name. - gauges mirrored from the existing
processGauges(toolCallsInFlight,mcpRequestsInFlight,registeredTools…), using acollect()callback collectDefaultMetrics()
Where to look
packages/backend/src/mcp-server/dynamic-mcp-tools.ts:130:logToolCall()is called on both the success and the error path and already hasdurationMs,status,upstreamStatusandconnectorType. Record the metrics here.packages/backend/src/common/process-vitals.ts:246:ProcessGauges/processGauges.snapshot(), existing in-process gauges to expose.packages/backend/src/tracing.ts:26: the existing opt-in OTel setup (pattern for an env-gated, no-op-by-default module).packages/backend/src/main.ts:160:app.listen(port). Start the metrics listener after it.packages/backend/src/health/sentry-verify.controller.ts:27:sameSecret(), a constant-time token comparison to reuse.packages/backend/src/common/deployment.service.ts:10:isCloud().deploy/cloud/Caddyfile:91anddocs/deployment.md:221:/health*is proxied publicly on Cloud and self-hosted. That is why metrics must not live under/healthor on port 4000.
Acceptance criteria
- With
METRICS_ENABLEDunset, no listener starts andprom-clientdefault metrics are not collected. -
GET :9464/metricsreturns Prometheus text format, and the counters and histogram move after a tool call. - With
METRICS_TOKENset, a missing or wrongAuthorization: Bearerreturns 401. - With
DEPLOYMENT_MODE=cloudand no token, the listener does not start. WithMETRICS_TOOL_LABELS=trueon Cloud, notool/connector_idlabel appears. - Unit tests in
src/common/metrics.spec.ts(labels, Cloud rules, token check). Run withcd packages/backend && npx jest src/common/metrics. - Docs: new section "Prometheus metrics (opt-in)" in
docs/operations/observability.md, with a sample scrape config, plus the env vars in the table indocs/deployment.md(around line 338).
Out of scope
- Grafana dashboards or alert rules (a follow-up issue).
- Pushing metrics via OTLP.
- Per-organization metrics or any UI.
- Changing
docker-compose.cloud.ymlor the Cloud Caddyfile (maintainers wire scraping on Cloud).
Size
M (1–2 days)
How to claim
Comment "I'd like to work on this" and we'll assign you. Rules in #997.
- Ngôn ngữ chính
- TypeScript
- Star
- 856
- Fork
- 82
- Merge trung bình
- 5 giờ 18 phút
- Pull request đã merge (30 ngày)
- 162
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của HelpCode-ai/anythingmcp
-
Docs: document all SMTP_* and other undocumented env vars for self-hostingCó thể đã có người làm @notlakshitha đã nhận 4 ngày trước. Đang mởenhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
HelpCode-ai/anythingmcp#1049 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
good first issue hacktoberfest
Độ khó 2/5 Nửa ngày Mức phù hợp với người mới 70/100
HelpCode-ai/anythingmcp#996 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
good first issue hacktoberfest
Độ khó 2/5 Nửa ngày Mức phù hợp với người mới 72/100
HelpCode-ai/anythingmcp#995 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement good first issue hacktoberfest help wanted
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
HelpCode-ai/anythingmcp#982 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Upload the new social previewCó thể đã có người làm @helpcodeai đã nhận 4 ngày trước. Đang mở
HelpCode-ai/anythingmcp#1087 · 6 bình luận · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của HelpCode-ai/anythingmcp
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 86/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 90/100
chrisparsons83/flexspotff#215 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
vitest-dev/vitest#11633 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
Maintainer thường phản hồi trong vòng 1 ngày