← All MCP servers
MCP server

Lviv Public Transport

mcp:vbhjckfd/timetable-api-node

Lviv public transport MCP: stops, timetables, routes, and live vehicle positions. No API key.

Verdict
Suspicious

Risky behavior the analysis could not rule out.

Analyzed Oct 26, 2026, 13:12 UTC at b05ff72
2
findings
medium
highest severity
2
threat classes
111
files scanned
1,256/1,256
checks satisfied
0
package advisories

Why this verdict

  • suspicious: finding mcp-server:.:INTEGRATION.md:139:PRIVESC
  • suspicious: finding mcp-server:.:package.json:44:SUPPLY

Security findings 2

Privilege escalation

mediumContextual risklow confidence

The LangChain recipe enables allow_dangerous_requests=True, so the agent can make arbitrary HTTP requests beyond the declared read-only transit API.

allow_dangerous_requests=True
vector:instruction
Counter-argument considered

The recipe tells developers to enable allow_dangerous_requests=True, which gives the agent a general HTTP-request tool. Nothing in the artifact mitigates this, and the read-only claim covers only the MCP tools.

Supply chain

lowContextual risklow confidence

package.json declares open-ended dependency ranges (protobufjs and tar with '>=') that let any future major release be pulled in without review.

"protobufjs": ">=8.2.0",
vector:metadata
Counter-argument considered

The >= ranges for protobufjs and tar are open-ended, so future majors can be pulled in unreviewed. This is dependency hygiene with no concrete agent-facing chain, so severity is low, but nothing cited refutes it.

Refuted findings 7

Candidates the review stage examined and rejected, kept for transparency.

Supply chain

criticalRefutedlow confidence

The guide tells users to run the unpinned npm package via `npx -y`, a stdio proxy that forwards to a remote MCP endpoint whose tool metadata is controlled remotely and overridable through MCP_URL.

"args": ["-y", "timetable-api-node"]
Why it was refuted

The npx entry runs the artifact's own package as its declared stdio proxy to the live API, and MCP_URL is a documented override. Nothing here is concealed or undeclared.

Tool poisoning

criticalRefutedlow confidence

The stdio proxy forwards the remote upstream server's tool list, instructions and tool/resource/prompt calls verbatim, so a remote host (overridable via MCP_URL) controls the tool metadata and instructions presented to the local agent.

instructions: upstream.getInstructions(),
Why it was refuted

Forwarding the upstream server's tools and instructions is the declared purpose of this stdio-to-HTTP proxy. The code comment says it is deliberate, and MCP_URL is a documented user-set override.

Supply chain

criticalRefutedlow confidence

The stdio proxy relays the remote server's instructions, tool, prompt and resource metadata from a live upstream URL (overridable via MCP_URL) to the local agent without pinning or verification, so upstream changes silently change the agent's instructions.

instructions: upstream.getInstructions(),
Why it was refuted

Relaying the live upstream's metadata is exactly what the declared proxy does. The code comment states the pass-through is intentional, so it is neither concealed nor undeclared.

Data exfiltration

criticalRefutedlow confidence

Undeclared outbound telemetry: on each stop timetable request the service POSTs the stop's lat/lng/code with a bearer secret to an env-configured Worker URL (R7), which the MCP server's declared transit-lookup purpose does not need; the data is stop coordinates only, not user or workspace data, and it is inert unless the env vars are set.

const secret = process.env.PULSE_SIGNAL_SECRET ?? '';
Why it was refuted

The payload is only public stop coordinates and code, with no user or workspace data. The call is inert unless the operator sets both env vars, so this is operator-side telemetry rather than exfiltration of sensitive data.

Privilege escalation

highRefutedlow confidence

The integration guide's sample code sets the OpenAI MCP tool's require_approval to "never", disabling per-call approval prompts for a remote MCP server, justified only by a self-claim that every tool is read-only.

"require_approval": "never",
Why it was refuted

The sample is for the vendor's own server, and its inline comment and the docs both state that all tools are read-only. The tool table lists only lookup tools, so skipping approval is consistent with the declared read-only capability.

Privilege escalation

highRefutedlow confidence

The integration docs tell users to configure the MCP tool with approval prompts disabled (require_approval never), relying on the unverified assertion that every tool is read-only.

"require_approval": "never"
Why it was refuted

This is the same sample as F2. The setting is for a documented read-only transit lookup service, and the docs openly declare that no tool writes.

Supply chain

highRefutedlow confidence

The docs configure clients to run an unpinned npm package via `npx -y`, which fetches and executes whatever version is latest on every start.

"args": ["-y", "timetable-api-node"]
Why it was refuted

The unpinned npx run of the project's own package is its declared install path, and the docs say npm dependencies are installed on first run. This is the artifact's declared core capability, not a hidden fetch of third-party code.

Coverage gaps 6

Parts of the artifact the static analysis could not fully examine.

unanalyzable_binary binary content is only byte-scanned
favicon.ico
dynamic_metadata line 60: server instructions are computed: upstream.getInstructions()
mcp/stdio.ts
dynamic_metadata line 64: tools list returned by ListToolsRequestSchema handler is computed
mcp/stdio.ts
dynamic_metadata line 65: resources list returned by ListResourcesRequestSchema handler is computed
mcp/stdio.ts
dynamic_metadata line 66: resourceTemplates list returned by ListResourceTemplatesRequestSchema handler is computed
mcp/stdio.ts
dynamic_metadata line 67: prompts list returned by ListPromptsRequestSchema handler is computed
mcp/stdio.ts