VictoriaTraces MCP Server
The implementation of Model Context Protocol (MCP) server for VictoriaTraces.
This provides access to your VictoriaTraces instance and seamless integration with VictoriaTraces APIs and documentation. It can give you a comprehensive interface for traces, observability, and debugging tasks related to your VictoriaTraces instances, enable advanced automation and interaction capabilities for engineers and tools.
Features
This MCP server allows you to use almost all read-only APIs of VictoriaTraces:
- Get services and operations (span names)
- Query traces, explore and analyze traces data
In addition, the MCP server contains embedded up-to-date documentation and is able to search it without online access.
More details about the exact available tools and prompts can be found in the Usage section.
You can combine functionality of tools, docs search in your prompts and invent great usage scenarios for your VictoriaTraces instance. And please note the fact that the quality of the MCP Server and its responses depends very much on the capabilities of your client and the quality of the model you are using.
You can also combine the MCP server with other observability or doc search MCP Servers and get even more powerful results.
Requirements
- VictoriaTraces instance: (single-node or cluster)
- Go 1.25 or higher (if you want to build from source)
Installation
Go
go install github.com/VictoriaMetrics-Community/mcp-victoriatraces/cmd/mcp-victoriatraces@latest
Binaries
Just download the latest release from Releases page and put it to your PATH.
Example for Linux x86_64 (note that other architectures and platforms are also available):
latest=$(curl -s https://api.github.com/repos/VictoriaMetrics-Community/mcp-victoriatraces/releases/latest | grep 'tag_name' | cut -d\" -f4)
wget https://github.com/VictoriaMetrics-Community/mcp-victoriatraces/releases/download/$latest/mcp-victoriatraces_Linux_x86_64.tar.gz
tar axvf mcp-victoriatraces_Linux_x86_64.tar.gz
Docker
You can run VictoriaTraces MCP Server using Docker.
This is the easiest way to get started without needing to install Go or build from source.
docker run -d --name mcp-victoriatraces \
-e VT_INSTANCE_ENTRYPOINT=https://localhost:10428 \
-e MCP_SERVER_MODE=http \
-e MCP_LISTEN_ADDR=:8081 \
-p 8081:8081 \
ghcr.io/victoriametrics-community/mcp-victoriatraces
You should replace environment variables with your own parameters.
Note that the MCP_SERVER_MODE=http flag is used to enable Streamable HTTP mode.
More details about server modes can be found in the Configuration section.
See available docker images in github registry.
Also see Using Docker instead of binary section for more details about using Docker with MCP server with clients in stdio mode.
Source Code
For building binary from source code you can use the following approach:
- Clone repo:
bash
git clone https://github.com/VictoriaMetrics-Community/mcp-victoriatraces.git
cd mcp-victoriatraces
- Build binary from cloned source code:
bash
make build
# after that you can find binary mcp-victoriatraces and copy this file to your PATH or run inplace
- Build image from cloned source code:
bash
docker build -t mcp-victoriatraces .
# after that you can use docker image mcp-victoriatraces for running or pushing
Configuration
MCP Server for VictoriaTraces is configured via environment variables:
| Variable | Description | Required | Default | Allowed values |
|---|---|---|---|---|
VT_INSTANCE_ENTRYPOINT |
URL to VictoriaTraces instance | Yes | - | - |
VT_INSTANCE_BEARER_TOKEN |
Authentication token for VictoriaTraces API | No | - | - |
VT_INSTANCE_HEADERS |
Custom HTTP headers to send with requests (comma-separated key=value pairs) | No | - | - |
VT_DEFAULT_TENANT_ID |
Default tenant ID used when tenant is not specified in requests (format: AccountID:ProjectID or AccountID) |
No | 0:0 |
- |
MCP_SERVER_MODE |
Server operation mode. See Modes for details. | No | stdio |
stdio, sse, http |
MCP_LISTEN_ADDR |
Address for SSE or HTTP server to listen on | No | localhost:8081 |
- |
MCP_DISABLED_TOOLS |
Comma-separated list of tools to disable | No | - | - |
MCP_HEARTBEAT_INTERVAL |
Defines the heartbeat interval for the streamable-http protocol. It means the MCP server will send a heartbeat to the client through the GET connection, to keep the connection alive from being closed by the network infrastructure (e.g. gateways) |
No | 30s |
- |
MCP_LOG_FORMAT |
Log output format | No | text |
text, json |
MCP_LOG_LEVEL |
Minimum log level | No | info |
debug, info, warn, error |
Modes
MCP Server supports the following modes of operation (transports):
stdio- Standard input/output mode, where the server reads commands from standard input and writes responses to standard output. This is the default mode and is suitable for local servers.sse- Server-Sent Events. Server will expose the/sseand/messageendpoints for SSE connections.http- Streamable HTTP. Server will expose the/mcpendpoint for HTTP connections.
More info about traqnsports you can find in MCP docs:
Π‘onfiguration examples
export VT_INSTANCE_ENTRYPOINT="https://localhost:10428"
# Custom headers for authentication (e.g., behind a reverse proxy)
# Expected syntax is key=value separated by commas
export VT_INSTANCE_HEADERS="<HEADER>=<HEADER_VALUE>,<HEADER>=<HEADER_VALUE>"
# Server mode
export MCP_SERVER_MODE="sse"
export MCP_SSE_ADDR="0.0.0.0:8082"
Endpoints
In SSE and HTTP modes the MCP server provides the following endpoints:
| Endpoint | Description |
|---|---|
/sse + /message |
Endpoints for messages in SSE mode (for MCP clients that support SSE) |
/mcp |
HTTP endpoint for streaming messages in HTTP mode (for MCP clients that support Streamable HTTP) |
/metrics |
Metrics in Prometheus format for monitoring the MCP server |
/health/liveness |
Liveness check endpoint to ensure the server is running |
/health/readiness |
Readiness check endpoint to ensure the server is ready to accept requests |
Setup in clients
Cursor
Go to: Settings -> Cursor Settings -> MCP -> Add new global MCP server and paste the following configuration into your Cursor ~/.cursor/mcp.json file:
{
"mcpServers": {
"victoriatraces": {
"command": "/path/to/mcp-victoriatraces",
"env": {
"VT_INSTANCE_ENTRYPOINT": "<YOUR_VT_INSTANCE>",
"VT_INSTANCE_BEARER_TOKEN": "<YOUR_VT_BEARER_TOKEN>",
"VT_INSTANCE_HEADERS": "<HEADER>=<HEADER_VALUE>,<HEADER>=<HEADER_VALUE>"
}
}
}
}
See Cursor MCP docs for more info.
Claude Desktop
Add this to your Claude Desktop claude_desktop_config.json file (you can find it if open Settings -> Developer -> Edit config):
{
"mcpServers": {
"victoriatraces": {
"command": "/path/to/mcp-victoriatraces",
"env": {
"VT_INSTANCE_ENTRYPOINT": "<YOUR_VT_INSTANCE>",
"VT_INSTANCE_BEARER_TOKEN": "<YOUR_VT_BEARER_TOKEN>",
"VT_INSTANCE_HEADERS": "<HEADER>=<HEADER_VALUE>,<HEADER>=<HEADER_VALUE>"
}
}
}
}
See Claude Desktop MCP docs for more info.
Claude Code
Run the command:
claude mcp add victoriatraces -- /path/to/mcp-victoriatraces \
-e VT_INSTANCE_ENTRYPOINT=<YOUR_VT_INSTANCE> \
-e VT_INSTANCE_BEARER_TOKEN=<YOUR_VT_BEARER_TOKEN> \
-e VT_INSTANCE_HEADERS="<HEADER>=<HEADER_VALUE>,<HEADER>=<HEADER_VALUE>"
See Claude Code MCP docs for more info.
Visual Studio Code
Add this to your VS Code MCP config file:
{
"servers": {
"victoriatraces": {
"type": "stdio",
"command": "/path/to/mcp-victoriatraces",
"env": {
"VT_INSTANCE_ENTRYPOINT": "<YOUR_VT_INSTANCE>",
"VT_INSTANCE_BEARER_TOKEN": "<YOUR_VT_BEARER_TOKEN>",
"VT_INSTANCE_HEADERS": "<HEADER>=<HEADER_VALUE>,<HEADER>=<HEADER_VALUE>"
}
}
}
}
See VS Code MCP docs for more info.
Zed
Add the following to your Zed config file:
"context_servers": {
"victoriatraces": {
"command": {
"path": "/path/to/mcp-victoriatraces",
"args": [],
"env": {
"VT_INSTANCE_ENTRYPOINT": "<YOUR_VT_INSTANCE>",
"VT_INSTANCE_BEARER_TOKEN": "<YOUR_VT_BEARER_TOKEN>",
"VT_INSTANCE_HEADERS": "<HEADER>=<HEADER_VALUE>,<HEADER>=<HEADER_VALUE>"
}
},
"settings": {}
}
}
}
See Zed MCP docs for more info.
JetBrains IDEs
- Open
Settings->Tools->AI Assistant->Model Context Protocol (MCP). - Click
Add (+) - Select
As JSON - Put the following to the input field:
{
"mcpServers": {
"victoriatraces": {
"command": "/path/to/mcp-victoriatraces",
"env": {
"VT_INSTANCE_ENTRYPOINT": "<YOUR_VT_INSTANCE>",
"VT_INSTANCE_BEARER_TOKEN": "<YOUR_VT_BEARER_TOKEN>",
"VT_INSTANCE_HEADERS": "<HEADER>=<HEADER_VALUE>,<HEADER>=<HEADER_VALUE>"
}
}
}
}
Windsurf
Add the following to your Windsurf MCP config file.
{
"mcpServers": {
"victoriatraces": {
"command": "/path/to/mcp-victoriatraces",
"env": {
"VT_INSTANCE_ENTRYPOINT": "<YOUR_VT_INSTANCE>",
"VT_INSTANCE_BEARER_TOKEN": "<YOUR_VT_BEARER_TOKEN>",
"VT_INSTANCE_HEADERS": "<HEADER>=<HEADER_VALUE>,<HEADER>=<HEADER_VALUE>"
}
}
}
}
See Windsurf MCP docs for more info.
Using Docker instead of binary
You can run VictoriaTraces MCP Server using Docker instead of local binary.
You should replace run command in configuration examples above in the following way:
{
"mcpServers": {
"victoriatraces": {
"command": "docker",
"args": [
"run",
"-i", "--rm",
"-e", "VT_INSTANCE_ENTRYPOINT",
"-e", "VT_INSTANCE_BEARER_TOKEN",
"-e", "VT_INSTANCE_HEADERS",
"ghcr.io/victoriametrics-community/mcp-victoriatraces",
],
"env": {
"VT_INSTANCE_ENTRYPOINT": "<YOUR_VT_INSTANCE>",
"VT_INSTANCE_BEARER_TOKEN": "<YOUR_VT_BEARER_TOKEN>",
"VT_INSTANCE_HEADERS": "<HEADER>=<HEADER_VALUE>,<HEADER>=<HEADER_VALUE>"
}
}
}
}
Usage
After installing and configuring the MCP server, you can start using it with your favorite MCP client.
You can start dialog with AI assistant from the phrase:
Use MCP VictoriaTraces in the following answers
But it's not required, you can just start asking questions and the assistant will automatically use the tools and documentation to provide you with the best answers.
Toolset
MCP VictoriaTraces provides numerous tools for interacting with your VictoriaTraces instance.
Here's a list of available tools:
| Tool | Description |
|---|---|
documentation |
Search in embedded VictoriaTraces documentation |
services |
List of all traced services |
service_names |
Get all the span names (operations) of a service |
traces |
Query traces |
trace |
Get trace info by trace ID |
dependencies |
Query the service dependency graph |
Prompts
The server includes pre-defined prompts for common tasks.
These are just examples at the moment, the prompt library will be added to in the future:
| Prompt | Description |
|---|---|
documentation |
Search VictoriaTraces documentation for specific topics |
Roadmap
- [ ] Implement multitenant version of MCP (that will support several deployments)
- [x] Add service graph tool after release of this feature (see the PR)
Disclaimer
AI services and agents along with MCP servers like this cannot guarantee the accuracy, completeness and reliability of results. You should double check the results obtained with AI.
The quality of the MCP Server and its responses depend very much on the capabilities of your client and the quality of the model you are using.
Contributing
Contributions to the MCP VictoriaTraces project are welcome!
Please feel free to submit issues, feature requests, or pull requests.
Parameters
endTs
The end timestamp in unix milliseconds. Current timestamp will be used if empty.
lookback
the lookbehind window duration in milliseconds (i.e. start-time + lookback = endTs). Default to 1h if empty.
tenant
Name of the tenant for which the data will be displayed (format AccountID:ProjectID)
Parameters
limit
Maximum number of results to return
query
Query for search (for example, list of keywords)
required
Parameters
service_name
Service name
required
tenant
Name of the tenant for which the data will be displayed (format AccountID:ProjectID)
Parameters
tenant
Name of the tenant for which the data will be displayed (format AccountID:ProjectID)
Parameters
tenant
Name of the tenant for which the data will be displayed (format AccountID:ProjectID)
trace_id
Trace ID
required
Parameters
end
End timestamp in unix milliseconds.
limit
The maximum number of traces in query results, default 20.
required
maxDuration
The maximum duration of the span, with units: ns, us, ms, s, m, or h.
minDuration
The minimum duration of the span, with units: ns, us, ms, s, m, or h.
operation
The span name (also known as the operation name in Jaeger)
service
Service name
required
start
Start timestamp in unix milliseconds.
tenant
Name of the tenant for which the data will be displayed (format AccountID:ProjectID)
out of 100
Security Review
Integration: VictoriaTraces
Repository: https://github.com/VictoriaMetrics-Community/mcp-victoriatraces
Commit: latest
Scan Date: 2026-03-14 12:17 UTC
Security Score
80 / 100
Tier Classification
Silver
OWASP Alignment
OWASP Rubric
- Standard: OWASP Top 10 (2021) aligned review
- Core methodology: architecture context, trust boundaries, data-flow tracing, threat modeling, control verification, and evidence-backed validation
- Key characteristics considered: exploitability, impact, likelihood, attacker preconditions, and business context
OWASP Security Category Mapping
- A01 Broken Access Control: none
- A02 Cryptographic Failures: none
- A03 Injection: none
- A04 Insecure Design: none
- A05 Security Misconfiguration: none
- A06 Vulnerable and Outdated Components: none
- A07 Identification and Authentication Failures: none
- A08 Software and Data Integrity Failures: none
- A09 Security Logging and Monitoring Failures: none
- A10 Server-Side Request Forgery: none
Static Analysis Findings (Bandit)
High Severity
None
Medium Severity
None
Low Severity
None
Build Status
SKIPPED
Build step was skipped to avoid running untrusted build commands by default.
Tests
Not detected
Documentation
README: Present
Dependency file: Present
AI Security Review
OWASP-Aligned Security Review of VictoriaTraces (mcp-victoriatraces)
Summary
Repository reviewed: VictoriaTraces (cmd/mcp-victoriatraces)
Primary language: Go
Scope: MCP server integration that exposes tools which call a configured VictoriaTraces API endpoint (VT instance) and serves embedded documentation resources.
NOTE: I reviewed the main entrypoint (cmd/mcp-victoriatraces/main.go), configuration (cmd/mcp-victoriatraces/config/config.go), tool handlers and HTTP request builders (cmd/mcp-victoriatraces/tools/.go), request execution (cmd/mcp-victoriatraces/tools/utils.go), resource indexing and serving (cmd/mcp-victoriatraces/resources/), and logging/hooks (cmd/mcp-victoriatraces/hooks/hooks.go, logging/*). I also inspected relevant vendor types for MCP message shapes (vendor/github.com/mark3labs/mcp-go). No static analysis findings were present.
1) OWASP Review Methodology Applied
- Orientation: Reviewed repository layout and static analysis summary; focused on cmd/mcp-victoriatraces.
- Entry points: Read cmd/mcp-victoriatraces/main.go to see how server is configured and which tools/resources are registered.
- Trust boundaries & entry points: Identified MCP client requests (tools/prompts/resources) as untrusted input, and the configured EntryPoint (VT_INSTANCE_ENTRYPOINT) as a privileged configuration parameter. Network boundary is between this service and the VictoriaTraces API (entrypoint).
- Data flows: Traced flow of CallToolRequest -> GetToolReqParam/GetToolReqTenant -> CreateSelectRequest/CreateAdminRequest -> http.NewRequestWithContext -> http.DefaultClient.Do -> io.ReadAll -> result returned to MCP client. Also traced env-config parsing (VT_INSTANCE_ENTRYPOINT, VT_INSTANCE_BEARER_TOKEN, VT_INSTANCE_HEADERS).
- Threat modelling: Considered attacker capabilities when controlling an MCP client (invoke tools, provide arguments), and when misconfiguring environment variables. Focused on SSRF, credential exposure, DoS/resource exhaustion, logging sensitive data, and insecure defaults.
- Verification: Verified concrete code locations and lines (see Findings below) and produced concrete remediation suggestions.
2) OWASP Top 10 (2021) Mapping
Findings mapped to OWASP Top10 2021 IDs where applicable:
- SSRF / Unrestricted network access leading to sensitive backend access -> A10: Server-Side Request Forgery (SSRF)
- Credentials sent to arbitrary endpoints / sensitive data exposure -> A02: Cryptographic Failures (Sensitive Data Exposure)
- No network timeouts and full-body reads -> A05: Security Misconfiguration (resource exhaustion) and A04: Insecure Design (denial-of-service vectors)
- Logging potentially leaking secrets -> A09: Security Logging and Monitoring Failures / A02 (sensitive data exposure)
- Insecure default / no scheme enforcement -> A05 Security Misconfiguration
- Vendor/dependency usage (embedded Bleve, langchaingo, big vendor tree) -> A06 Vulnerable and Outdated Components (advisory: review pinned versions)
3) Critical Vulnerabilities
No direct RCE, SQL injection, unsafe deserialization, or auth bypass were found in the reviewed files. However, there is a critical risk classed as SSRF leading to credential exfiltration (high/critical impact) because the server will make requests to the configured entrypoint and will attach the Bearer token and any custom headers to those requests. If an attacker-controlled MCP client can cause requests to a malicious host (or the entrypoint is attacker-controlled), secrets may leak and internal network services can be probed.
Concrete evidence (code references):
- Entry point parsed from env and accepted without scheme/host validation:
- cmd/mcp-victoriatraces/config/config.go:92 (entrypoint := os.Getenv("VT_INSTANCE_ENTRYPOINT"))
- cmd/mcp-victoriatraces/config/config.go:130 (result.entryPointURL, err = url.Parse(result.entrypoint))
- Request building which sets Authorization and custom headers and AccountID/ProjectID headers, then issues the HTTP request:
- cmd/mcp-victoriatraces/tools/utils.go:16 CreateSelectRequest builds URL and headers; sets Authorization header from cfg.BearerToken() (utils.go:29-34)
- cmd/mcp-victoriatraces/tools/utils.go:37-41 Adds custom headers from config (VT_INSTANCE_HEADERS)
- cmd/mcp-victoriatraces/tools/utils.go:86-99 GetTextBodyForRequest issues request via http.DefaultClient.Do and io.ReadAll (no timeout and no response size limit)
Risk: An MCP client that can call tools (e.g. 'trace', 'traces', 'services', etc.) can trigger HTTP requests to arbitrary destinations under the server's control (depending on configured EntryPoint). If EntryPoint is attacker-controlled or resolves to internal IPs, server may be induced to request internal metadata (e.g., cloud provider metadata 169.254.169.254) while including a Bearer token or other sensitive headers β resulting in critical credential exposure and SSRF.
Severity: Critical / High depending on deployment context.
4) High Severity Issues
Issue A: SSRF + Credential Exfiltration
- Files & lines:
- config: cmd/mcp-victoriatraces/config/config.go:92, 130 (entrypoint read/parsed without restrictions)
- request creation: cmd/mcp-victoriatraces/tools/utils.go:16-36 (CreateSelectRequest sets Authorization: Bearer
- request execution: cmd/mcp-victoriatraces/tools/utils.go:86-99 (http.DefaultClient.Do + io.ReadAll)
- Why: The server attaches sensitive headers and sends them to whatever URL results from joining the configured entrypoint and path. No allowlist or scheme checks, no hostname restriction, and the server will perform the network call on behalf of the client. Attackers controlling an MCP client or the entrypoint environment can abuse this.
- Remediation (concrete):
1. Validate/normalize EntryPoint URL early and enforce allowed schemes (only "https") and optionally an allowlist of hostnames/subnets. Fail fast if VT_INSTANCE_ENTRYPOINT uses non-HTTPS or untrusted host. (config/config.go: after url.Parse -> verify u.Scheme == "https" and u.Host not empty; provide allowlist option.)
2. Add an allowlist/denylist mechanism for outbound hosts (e.g. ENV or config file) and enforce it before making requests (tools/utils.go:getSelectURL or CreateSelectRequest).
3. Avoid sending the global Bearer token or any sensitive headers to arbitrary redirects/destinations. Only attach Authorization when the request host is in the trusted allowlist.
4. Consider not attaching secret-bearing headers by default; instead allow per-host credentials configured explicitly.
- OWASP mappings: A10 (SSRF), A02 (sensitive data exposure)
Issue B: No http client timeout and no limit on response body size -> Denial-of-Service/Resource exhaustion
- Files & lines:
- cmd/mcp-victoriatraces/tools/utils.go:86-99 (GetTextBodyForRequest uses http.DefaultClient.Do and io.ReadAll; DefaultClient has no timeout set by default).
- Why: An attacker-controlled or slow upstream can cause requests to hang (no timeout) or return very large payloads which the server will fully read into memory via io.ReadAll causing high memory usage/OOM.
- Remediation:
1. Use a custom http.Client with a sensible Timeout and Transport that restricts Dial and TLS handshake timeouts. For example, create an http.Client with Timeout: 10s (configurable via env). Replace http.DefaultClient.Do with client.Do.
- File: cmd/mcp-victoriatraces/tools/utils.go: create and use a client with timeout.
2. Limit maximum response body read size: replace io.ReadAll(resp.Body) with io.LimitReader and a controlled buffer, or read incrementally and enforce a maximum number of bytes (e.g., 5-10MB) before returning an error.
3. Consider adding server-side rate limiting and concurrency limits on tool calls that trigger network I/O.
- OWASP mappings: A05 Security Misconfiguration, A04 Insecure Design
Issue C: Credentials sent over non-HTTPS endpoints (no enforcement)
- Files & lines: cmd/mcp-victoriatraces/config/config.go:130 (url.Parse only), cmd/mcp-victoriatraces/tools/utils.go:29-34 (Authorization header set)
- Why: The code will happily send Authorization header over http if entrypoint scheme is http. This can expose bearer tokens in transit.
- Remediation: Enforce HTTPS for EntryPoint (reject non-https unless explicitly configured), or at minimum warn / provide a config flag to allow insecure transport.
- OWASP mapping: A02 (Cryptographic Failures / sensitive data exposure)
5) Medium Severity Issues
Issue D: Custom headers from environment are applied without validation (possible header injection or misuse)
- Files & lines: cmd/mcp-victoriatraces/config/config.go:42-53 (parsing VT_INSTANCE_HEADERS), cmd/mcp-victoriatraces/tools/utils.go:37-41 (applying headers)
- Why: If misconfigured, custom headers could include hop-by-hop or other headers that change request semantics. While environment variables are considered administrative, they can be misused. Also header names/values are not validated; malformed header names could cause unexpected behavior or be used to set headers like "Host".
- Remediation:
1. Validate header names (allow only RFC7230 token characters) and disallow dangerous headers (Host, Connection, Transfer-Encoding, Proxy-*, Upgrade, Content-Length, etc.).
2. Provide explicit configuration for per-host headers and disallow globally sending custom headers to untrusted hosts.
- OWASP mapping: A05 Security Misconfiguration
Issue E: Logging of full MCP messages may leak secrets
- Files & lines: cmd/mcp-victoriatraces/hooks/hooks.go: AddBeforeAny logs "message" using toJSON(message) (hooks.go:~72-96) and AddOnError/AddOnSuccess also log message/result.
- Why: Message and result objects may contain sensitive data from clients (e.g., tokens in arguments or resource content). Logs are written to stderr (logging.New sets os.Stderr) and are not redacted.
- Remediation:
1. Redact sensitive fields before logging. Implement a configurable redact list and remove/hide known sensitive keys (e.g., tokens, passwords, secrets, AccountID?), or avoid logging entire message payloads.
2. Make logging level configurable and default to not logging full message content in production (limit to metadata such as tool name, session id, and whether result was success/failure).
- OWASP mapping: A09 Security Logging and Monitoring Failures, A02 Sensitive Data Exposure
Issue F: No per-tool authorization or access control
- Files & lines: tools are registered unconditionally when not disabled by env (tools/.go RegisterTool use c.IsToolDisabled(name)). There is no code that authenticates or authorizes MCP clients calling tools.
- Why: Any connected MCP client that is allowed to call tools can trigger backend requests. If MCP clients are not trusted or authenticated strongly, an unauthorized client could call tools to probe internal resources.
- Remediation:
1. Require and validate client authentication/authorization before allowing tool calls. Use MCP hooks to enforce session/user-level allowlists for tool usage.
2. At minimum, document that only trusted MCP clients should be connected and advise operators to run in private networks or behind an access gateway.
- OWASP mapping: A01 Broken Access Control
6) Low Severity Issues / Best-practice gaps
Issue G: No maximum search index size enforcement / Bleve in-memory index
- Files & lines: cmd/mcp-victoriatraces/resources/docs.go (searchIndex created with bleve.NewMemOnly(mapping))
- Why: In-memory index can grow and consume memory; if the embedded docs are large (unlikely in normal deployments), indexing could be heavy.
- Remediation: Monitor memory usage; consider persistent index or limit indexing behavior. Not a direct security vulnerability for typical doc sizes.
- OWASP mapping: A04 Insecure Design (resource consumption)
Issue H: Logs include JSON marshaling of arbitrary structures via toJSON which swallows errors -> missing logging error visibility is minor.
- Files & lines: cmd/mcp-victoriatraces/hooks/hooks.go toJSON (hooks.go:~184)
- Remediation: Consider redaction and safe stringification with size limits.
7) Key Risk Characteristics (for top findings)
Finding: SSRF leading to credential exposure (CreateSelectRequest + GetTextBodyForRequest)
- Exploitability: Moderate to high if an attacker can either: (a) control the MCP client interface (call tools) or (b) cause the server to be pointed to a malicious entrypoint value (misconfiguration or supply of env variables). In practice, the MCP server is a service that accepts client connections; if clients are untrusted this is high risk.
- Impact: High/Critical β exposure of bearer token and other headers to internal endpoints or attacker-controlled endpoints; potential leakage of cloud metadata, internal service data, or lateral movement.
- Likelihood: In multi-tenant or public deployments where clients are untrusted, likelihood is high. In single-tenant deployments where the MCP server only accepts trusted clients, likelihood is lower.
- Preconditions: Attacker must be able to connect as MCP client and call registered tools, or operator must misconfigure the entrypoint to an untrusted host.
- Business impact: Exfiltration of credentials and internal data; potential service account compromise.
Finding: No timeouts + full-body read
- Exploitability: High β remote servers can cause long-running requests or very large responses.
- Impact: Medium-High β DoS by consuming CPU/memory or blocking server threads.
- Preconditions: Attacker can cause server to call a slow/large endpoint (via MCP client). Same as SSRF preconditions.
Finding: Logging of potentially sensitive payloads
- Exploitability: Medium β leaks are passive and may be read by log consumers.
- Impact: Medium β tokens or secrets in logged messages can be retrieved by attackers with log access.
- Preconditions: Secrets are included in MCP messages or payloads and logs are accessible.
8) Positive Security Practices Observed
- Use of embed.FS for documentation prevents reading arbitrary filesystem paths (docs are embedded at build time) β cmd/mcp-victoriatraces/resources/docs.go.
- Use of default listen address and server shutdown logic with context/timeouts in main.go to avoid abrupt termination β cmd/mcp-victoriatraces/main.go.
- Config validation for many env vars (log format/level, heartbeatInterval parsing, tenant parsing). config.InitConfig does early validation and errors on missing VT_INSTANCE_ENTRYPOINT.
- Tools define input parameter patterns (e.g., tenant pattern regex) and mcp input schema usage reduces malformed input.
- Use of metrics hooks to monitor calls, errors and resource access helps observability.
9) Recommendations (concrete fixes with file:line references)
High/Immediate actions (must do before exposing to untrusted clients or public networks):
1. Prevent SSRF and credential leakage by validating EntryPoint and restricting which hosts the server can call.
- Where: cmd/mcp-victoriatraces/config/config.go
- What: After parsing result.entryPointURL (config.go:~130), validate scheme and host. Example checks:
- require scheme == "https" unless operator explicitly sets an ALLOW_INSECURE_ENTRYPOINT flag
- require host is in an allowlist (e.g., VT_ALLOWED_HOSTS env or CIDR allowlist) or at least disallow local/internal IPs (169.254.169.254, 127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, ::1, fe80::/10, etc.)
- Rationale: avoid accidental exposure of bearer token and internal endpoints.
- OWASP: A10, A02
- Do not attach Authorization or custom headers to requests to arbitrary destinations.
- Where: cmd/mcp-victoriatraces/tools/utils.go: lines 27-41
- What: Before setting req.Header.Set("Authorization", ... ) and adding cfg.CustomHeaders(), verify the host of req.URL is trusted (see allowlist). If not trusted, omit Authorization/custom headers or return an error.
- Also provide a configuration to explicitly map credentials to allowed host(s).
-
OWASP: A02, A10
-
Use a dedicated http.Client with timeouts and safe Transport, and limit response body size.
- Where: cmd/mcp-victoriatraces/tools/utils.go:86-99
- What: Replace http.DefaultClient.Do(req) with a client created once (e.g., in package init or passed from main) with fields: Timeout (configurable, e.g., 10s), Transport with DialContext timeouts, TLSHandshakeTimeout, and DisableKeepAlives=false. Read response bodies using io.LimitReader(resp.Body, maxBytes) (e.g., 10MB) and handle overflow errors gracefully.
- Example: var httpClient = &http.Client{Timeout: 10 * time.Second, Transport: &http.Transport{...}}
-
OWASP: A05, A04
-
Implement header validation and disallow specific hop-by-hop headers or dangerous headers from VT_INSTANCE_HEADERS.
- Where: cmd/mcp-victoriatraces/config/config.go (parsing of VT_INSTANCE_HEADERS) and cmd/mcp-victoriatraces/tools/utils.go (applying headers)
- What: Validate header names against RFC tokens, and skip/return error if header is in blacklist (Host, Connection, Content-Length, Transfer-Encoding, Upgrade, Proxy-Authorization, Proxy-Connection, TE, Expect).
-
OWASP: A05
-
Redact sensitive data from logs.
- Where: cmd/mcp-victoriatraces/hooks/hooks.go AddBeforeAny/AddOnSuccess/AddOnError calls to toJSON(message)/toJSON(result) (hooks.go:~72-116) and logging middleware in cmd/mcp-victoriatraces/logging/middleware.go
- What: Implement a redaction function that sanitizes known sensitive fields in MCP messages (e.g., arguments that match names like token, password, secret, authorization) before logging. Alternatively, log only metadata (tool name, session id) and not full payload by default. Add a configurable log redaction allowlist.
- OWASP: A09, A02
Medium-term actions:
6. Add per-tool authorization policies.
- Where: server hooks (cmd/mcp-victoriatraces/hooks/hooks.go) or in the mcp-go middleware
- What: Use on-before-call hooks to restrict which sessions (or authenticated clients) can call which tools. Deny requests coming from unknown/untrusted clients. Document recommended deployment topology (private networks or auth gateways).
- OWASP: A01
- Add unit tests that assert hostile input won't cause unsafe behavior: large responses, redirects to internal addresses, invalid header injection, etc. Add integration tests for network timeouts and header redaction.
-
Where: cmd/mcp-victoriatraces/tools/utils_test.go and new tests.
-
Make outbound host allowlist and timeouts configurable via environment variables and document secure defaults (deny by default; require explicit allowlist entries for remote hosts).
-
Where: config/config.go and main.go for initialization.
-
Sanitize/customize logging of embedded docs and search functionality to avoid exposing system paths in logs.
- Where: cmd/mcp-victoriatraces/resources/docs.go and resources/hooks.
Low priority / housekeeping:
- Monitor vendor dependency versions (Bleve, langchaingo etc.) and keep them maintained (A06). The vendor directory is large; ensure security CVE scans are part of CI.
10) Next Tier Upgrade Plan (Bronze -> Silver -> Gold)
Current tier assessment (per typical MCP integration security maturity): Bronze
- Rationale: The integration has solid structure, clear config parsing and some validation, uses embedded docs and metrics, but lacks critical runtime protections (SSRF allowlist, timeouts, header validation, logging redaction, per-tool auth). These gaps make it unsafe for deployment where MCP clients are untrusted or in public-facing contexts.
Target next tier: Silver
- Goals for Silver: eliminate SSRF/credential-exfil risks, enforce TLS and host allowlist, add timeouts and response size limits, redact sensitive logs, and add basic per-tool authorization.
Prioritized action plan to reach Silver (ordered):
1. Enforce entrypoint validation and host allowlist (config/config.go) β HIGH priority
2. Stop sending Authorization/custom headers to non-allowlisted hosts (tools/utils.go) β HIGH
3. Introduce configurable http.Client with timeouts and response size limits (tools/utils.go) β HIGH
4. Implement logging redaction of sensitive message fields (hooks/hooks.go + logging/*) β HIGH
5. Add server-side per-tool authorization and document expected trust boundaries (hooks or mcp-go hooks) β MEDIUM
6. Add rate limits and concurrency controls for tool calls that produce network I/O β MEDIUM
7. Add unit/integration tests covering SSRF, large responses, header injection, and logging redaction β MEDIUM
8. Add CI scans for vendor dependencies (CVE scanning) and update vendor as needed β LOW
After Silver -> Gold (optional):
- Implement dynamic credential mapping (per-host credentials) and rotateable secrets integrations (vault/K8s secrets), stronger telemetry and alerting on unexpected host access, and hardened Transport layer checks (mutual TLS for backend).
Detailed Findings with file:line, severity and remediation
(Note: line numbers refer to file search results and in-file logical regions.)
Finding 1 (Critical): SSRF and credential leakage via EntryPoint + CreateSelectRequest/ CreateAdminRequest
- Files: cmd/mcp-victoriatraces/config/config.go (VT_INSTANCE_ENTRYPOINT parsing, ~lines 92,130), cmd/mcp-victoriatraces/tools/utils.go (CreateSelectRequest: ~lines 16-36; CreateAdminRequest: ~lines 46-71)
- Concrete lines:
- config.go: result.entryPointURL, err = url.Parse(result.entrypoint) (config.go:130)
- tools/utils.go: req, err := http.NewRequestWithContext(ctx, http.MethodGet, selectURL, nil) (utils.go:27)
- tools/utils.go: bearerToken := cfg.BearerToken(); if bearerToken != "" { req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", bearerToken)) } (utils.go:29-34)
- tools/utils.go: for key, value := range cfg.CustomHeaders() { req.Header.Set(key, value) } (utils.go:37-41)
- Severity: Critical
- Impact: Bearer token and custom headers can be sent to arbitrary hosts derived from the entrypoint. If entrypoint is attacker-controlled or contains internal IPs, attacker can exfiltrate secrets and access internal services.
- Remediation (concrete):
1. In config.InitConfig, after url.Parse(result.entrypoint), validate scheme and host. Example addition:
- if result.entryPointURL.Scheme != "https" { if os.Getenv("ALLOW_INSECURE_ENTRYPOINT") != "1" { return nil, fmt.Errorf("VT_INSTANCE_ENTRYPOINT must use https") } }
- Add optional VT_ALLOWED_HOSTS or VT_ALLOWED_NETWORKS env that is checked later.
2. Enforce an allowlist in CreateSelectRequest and CreateAdminRequest: do not set Authorization/custom headers unless req.URL.Host is in the allowlist (or matches the configured entrypoint host).
3. Consider disallowing entrypoints that resolve to private IP ranges by performing DNS resolution (with timeouts) and checking IP ranges before use.
Finding 2 (High): No timeout and unlimited response body read
- Files: cmd/mcp-victoriatraces/tools/utils.go (GetTextBodyForRequest ~lines 86-99)
- Concrete lines:
- resp, err := http.DefaultClient.Do(req) (utils.go:87)
- body, err := io.ReadAll(resp.Body) (utils.go:88)
- Severity: High
- Impact: Remote server can cause long-running requests (hang) or return extremely large responses leading to resource exhaustion and potential crash.
- Remediation (concrete):
1. Replace http.DefaultClient with a configured http.Client with Timeout and custom Transport. Create the client during initialization (main.go or a package-level var).
- Example: client := &http.Client{ Timeout: 10 * time.Second, Transport: &http.Transport{ / configure DialContext, TLSHandshakeTimeout, MaxIdleConns, IdleConnTimeout / }}
- Use client.Do(req)
2. Replace io.ReadAll with reading through io.LimitReader(resp.Body, maxBytes) and error if response is larger than maxBytes (e.g., 5-20 MB configurable).
Finding 3 (High/Medium): Credentials transmitted over non-TLS
- Files: cmd/mcp-victoriatraces/config/config.go (url parse happening at ~line 130), cmd/mcp-victoriatraces/tools/utils.go (setting Authorization header ~lines 29-34)
- Severity: High (sensitive data exposure)
- Impact: Bearer token can be sent in cleartext across the network if entrypoint uses http.
- Remediation: Require https for EntryPoint by default; if operator needs to use http for testing, require explicit opt-in flag.
Finding 4 (Medium): Custom headers not validated and potentially dangerous
- Files: cmd/mcp-victoriatraces/config/config.go:42-53 parsing VT_INSTANCE_HEADERS; cmd/mcp-victoriatraces/tools/utils.go:37-41 applying headers
- Severity: Medium
- Impact: Unvalidated header names can override Host or other hop-by-hop headers and cause unexpected behavior.
- Remediation: Validate header names and strip blacklisted headers; document and require safe header names.
Finding 5 (Medium): Logging may leak secrets
- Files: cmd/mcp-victoriatraces/hooks/hooks.go: AddBeforeAny/AddOnError/AddOnSuccess use toJSON(message) and toJSON(result) (hooks.go:~72-116), toJSON function at hooks.go:~184
- Severity: Medium
- Impact: Any secret present in message/result may be written to logs; log files may be accessible to attackers.
- Remediation: Implement redaction of sensitive keys before logging. Limit logged payload size and content.
Finding 6 (Low): Bleve index in-memory may consume resources for large docs (design)
- Files: cmd/mcp-victoriatraces/resources/docs.go: searchIndex created with bleve.NewMemOnly(mapping)
- Severity: Low
- Remediation: Monitor memory and consider persistent index or size limits if docs become large.
Implementation notes / example code snippets
- Create a trusted http client once and reuse it (example in main.go):
var outboundClient = &http.Client{
Timeout: time.Second * 10,
Transport: &http.Transport{
DialContext: (&net.Dialer{ Timeout: 5 * time.Second, KeepAlive: 30 * time.Second }).DialContext,
TLSHandshakeTimeout: 5 * time.Second,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
},
} -
Safe body read snippet to limit size:
maxBody := int64(5 * 1024 * 1024) // 5 MB
bodyReader := io.LimitReader(resp.Body, maxBody+1)
bodyBytes, err := io.ReadAll(bodyReader)
if err != nil { ... }
if int64(len(bodyBytes)) > maxBody { return mcp.NewToolResultError("response too large") } -
Host allowlist enforcement pseudo:
func isHostTrusted(u url.URL, cfg Config) bool {
host := u.Hostname()
if host == cfg.EntryPointURL().Hostname() { return true }
// check VT_ALLOWED_HOSTS or CIDR deny private IP ranges
return false
}
Positive practices summary
- Good configuration validation for many settings.
- Tools expose typed parameters and JSON schemas (mcp.NewTool with patterns) which reduces malformed input.
- Embedded docs and in-memory search provides self-contained documentation resources.
- Graceful shutdown logic and metrics/hooks for observability.
Final Risk Assessment and Recommendation
- The most serious issue is the SSRF/credential exfiltration vector due to: permissive EntryPoint URL handling, unconditional attachment of Authorization and custom headers, and unbounded outgoing HTTP execution. In environments where MCP clients might be untrusted, this creates a critical risk. Mitigations recommended above (host allowlist, https enforcement, per-host credentials, timeouts, response limits, logging redaction) are required before exposing this service to any untrusted network or public-facing client.
If you want, I can:
- Provide concrete patch diffs (go code snippets) implementing an http.Client with timeout, response size limit, and host allowlist checks.
- Draft a secure-configuration checklist and example env configuration for safe operation.
Reviewed-by: AI Security Reviewer
Date: 2026-03-14
Summary
Security Score: 80/100 (Silver)
Static analysis found 0 high, 0 medium, and 0 low severity issues.
Build step skipped for safety.
No automated tests detected.
Sign in to leave a review
No reviews yet β be the first!
Configuration
VT_INSTANCE_BEARER_TOKEN
required
π password
Configure the connection to VictoriaTraces MCP Server
VT_INSTANCE_ENTRYPOINT
required
string
URL of VictoriaTraces instance (it should be root URL of vtsingle or vtselect)
VT_INSTANCE_HEADERS
string
Optional custom headers to include in requests to VictoriaTraces instance, formatted as 'header1=value1,header2=value2'
MCP_SERVER_MODE
string
Mode in which the MCP server operates (possible values: stdio, http, sse)
MCP_LISTEN_ADDR
string
Address and port on which the MCP server listens for incoming connections (e.g., ':8081')
MCP_DISABLED_TOOLS
string
Comma-separated list of tools to disable (possible values: export, metric_statistics, test_rules)
MCP_HEARTBEAT_INTERVAL
string
Defines the heartbeat interval for the streamable-http protocol. It means the MCP server will send a heartbeat to the client through the GET connection, to keep the connection alive from being closed by the network infrastructure (e.g. gateways)
Docker Image
Docker HubPublished by github.com/VictoriaMetrics-Community