VISTA-MCP
Provides tools for Fortinet VISTA, including log analysis, visualization, and troubleshooting for FortiOS/FortiGate engineering and support.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@VISTA-MCPanalyze this firewall log"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
VISTA-MCP
An MCP (Model Context Protocol) server that exposes a growing catalog of Fortinet VISTA
tools to a partner team's agents, for FortiOS / FortiGate engineering and support. Log analysis
& visualization is the first tool; the catalog will grow to include things like config/script
generation, debug-command helpers, End-of-Support & lifecycle lookups, and more. The tools are
independent and varied — each has its own inputs and its own text output; not all take a log
file or return a visualization. The agent reads each tool's description in list_tools and calls
the one whose purpose matches the task.
Today's tool — Log_Analyzer_Visualizer, backed by the Log Visualizer "AgentAssist" API
(FortiGate SD-WAN event logs). The client still sends a source_url (+ optional question) and
gets back one text report — no client-visible change.
Architecture (current): each MCP tool is a thin entry point into a config-driven orchestrator. It discovers a set of standard analyzers, lets DeepSeek pick which optional ones fit the question, calls them in parallel, concatenates their reports, and appends ORB troubleshooting — with no per-analyzer code. Adding capability is a config edit. Full details:
docs/Architecture.md — the whole design and flow
docs/analyzer_api.md — the standard analyzer contract every analyzer follows
docs/how_to_add_analyzer.md — add an analyzer or a whole new tool (config, no code)
docs/testing.md — run & test locally, with commands
Flow GUI at
/gui— live n8n-style flow of every job + a TOOL_ENABLEMENT / routing-prompt editor(The older
analyzers/module anddocs/ADDING_ANALYZERS.mddescribe the superseded one-subclass-per-tool proxy pattern; the orchestrator replaced it.)
Production URL:
https://vista.fortinet.com/mcp/(the served MCP path is/mcp/).
1. How it works
Partner agent VISTA-MCP (this repo) Backend analyzer
───────────── ───────────────────── ────────────────
list_tools ───────────────────► return tool name/description/schema
(the model decides whether to call)
call Log_Analyzer_Visualizer
{ source_url:<signed URL>, 1. fetch_log(source_url) ── stream, ≤50MB ──► (partner's
question:"..." } 2. LogVAnalyzer.analyze(bytes, question) signed URL)
├─ question? POST .../filter_analyze_visualyze_logs ──► Log
└─ no q? POST .../analyze_visualise_logs ──► Visualizer
3. ask ORB for troubleshooting steps ──────────────────► ORB API
4. fold JSON + ORB → ONE text report ◄──── {filter, analysis, viz}
◄──────────────────────── return report textThe report the agent receives concatenates, in order:
Filter summary —
filter: matched 2495/29169 · queries 1+ how the logs were selected (the internal engine name is scrubbed).Open in Log Visualizer — a shareable link to the parsed logs.
Analysis — the AI report (written for a Fortinet TAC engineer).
ORB Suggestions — troubleshooting steps directly relevant to the analysis. This layer sends the analysis + a fixed troubleshoot instruction + the user's own question (when they asked one) to the ORB "ask" API, so the remediation targets what was actually asked, and inserts ORB's answer here (between analysis and the iframe). Fail-open: if ORB is disabled, unreachable, slow, or there's no real analysis, this section is simply omitted and the rest of the report is unaffected.
Interactive Visualization — an
iframeURL the agent is told to embed in its answer.
If a question is given, the filter block appears (filter → analyze → visualize). With no question, the Filter block is omitted (just analyze → visualize). ORB Suggestions appear whenever there's a real analysis to troubleshoot. If the uploaded log isn't a supported type, the tool returns a clear "not supported yet" message instead.
The one special input: the log URL
Per the partner contract, we never ask the user for the file — the platform injects a
short-lived signed URL into a field we declare (source_url). The tool fetches it
promptly (it expires in minutes), streams it (logs can be large; capped by
MAX_LOG_BYTES), and does not store it. The model fills only question.
Related MCP server: FortiOS 7.6.x MCP Server
2. Repository layout
VISTA-MCP/
├── server.py # FastMCP server: /mcp route, bearer auth, log fetch → orchestrator; mounts /gui
├── config/tool_enablement.json # TOOL_ENABLEMENT — per-tool: description, routing_system_prompt, orb, analyzers[]
├── orchestrator/ # the config-driven core (no per-analyzer code)
│ ├── models.py # the standard contract + ToolConfig/AnalyzerRef/Decision/Job
│ ├── tool_enablement.py # load/save the per-tool config (cached, hot-reload)
│ ├── vfr.py # VFR — passthrough today (real routing seam; see Architecture.md §9)
│ ├── discovery.py # GET /discover for all analyzers (concurrent, fail-soft)
│ ├── deepseek.py · decide.py # DeepSeek routing + skip-logic + per-tool prompt composition
│ ├── analyzer_client.py # the ONE generic call → AnalyzerResult
│ ├── orb.py · pipeline.py # ORB (fail-open) + the whole flow wired together
│ └── jobs.py · gui.py # job/flow registry (CLI logs) + the /gui routes
├── gui/index.html # the single-page n8n-style flow GUI (red/white)
├── fakes/fake_analyzer.py # a real analyzer following the contract, for local testing (+ run_fakes.sh)
├── client_test.py # end-to-end MCP client (serves a log, list_tools, call_tool)
├── test_data/ # sample SD-WAN logs
├── docs/ # Architecture.md · analyzer_api.md · how_to_add_analyzer.md · testing.md
├── analyzers/ # SUPERSEDED pre-orchestrator subclass pattern (kept for reference)
└── starter_kit/ # the partner team's original example (reference, untouched)3. Run it
python3 -m venv .venv && . .venv/bin/activate
pip install -r requirements.txt
# point at a running Log Visualizer AgentAssist backend (see the LogAssist repo)
export LOGV_API_BASE="http://127.0.0.1:8802/logVisualizer/api/agent_assist"
export LOGV_VIEW_BASE="https://vista.fortinet.com/logVisualizer" # link/iframe base
export MCP_AUTH_TOKEN="a-strong-shared-token" # partner sends this
# for LOCAL testing only, because the test client serves the log on 127.0.0.1:
export MCP_ALLOW_PRIVATE_FETCH=1
python server.py # → http://0.0.0.0:8100/mcp/Test it end-to-end (no partner infra needed)
In another shell (server running):
. .venv/bin/activate
export MCP_AUTH_TOKEN="a-strong-shared-token" # same token the server expects
python client_test.py --list-only # inspect the tool schema
python client_test.py --file test_data/sdwan-small.log --question "SLA failures for Austin"
python client_test.py --file test_data/sdwan-small.log --no-question # analyze + visualize
python client_test.py --file test_data/DEMO_LOG_VISUALIZER_SDWAN.log --question "packet loss over 50%"The client serves the log over a throwaway local HTTP server (standing in for the partner's
signed URL), connects over MCP with the bearer token, and prints the exact text report the
agent would receive. (If the MCP server runs on another host, pass --host-ip <ip the server can reach the client at>.)
4. Configuration (env)
Var | Default | Meaning |
|
| bind host |
|
| bind port (served path is |
|
| shared bearer token the partner must send. The server refuses to start with an empty/default token unless |
| (off) |
|
| (off) |
|
|
| streaming fetch cap for the injected log |
| (unset) | PEM bundle of extra CAs to trust on outbound calls (internal PKI). Bad path ⇒ the server refuses to start |
| (empty) | comma-separated hosts to skip TLS verification for — a scoped |
| (off) |
|
|
| terminal flow-log verbosity ( |
|
| Log Visualizer AgentAssist base |
|
| SPA base for the returned session links/iframe |
|
| set |
|
| ORB "ask" API queried after the analysis for troubleshooting steps |
|
|
|
|
| ORB request timeout (s) — ORB is deep-research and slow (~45–140 s); fail-open on timeout |
Every tool call logs the full flow to the terminal with a correlation id:
[110877fa] ▶ TOOL CALL Log_Analyzer_Visualizer question='SLA failures on Austin' source_url=http://…/sdwan.log
[110877fa] fetch: GET http://…/sdwan.log (streaming, cap 52,428,800B)
[110877fa] fetch: done — 577,618 bytes, filename='sdwan-small.log' in 0.02s
[110877fa] forward → LogV: POST …/filter_analyze_visualyze_logs (question=yes, file=577,618B, spa_base=…)
[110877fa] forward: LogV responded HTTP 200 in 17.32s
[110877fa] LogV result: log_type=System:sdwan filter.matched=50/948 analysis=4,316chars session_id=21b2ece7-… iframe=yes
[110877fa] ◀ TOOL CALL done — returning 5,177-char report in 17.34s5. Auth
The server uses FastMCP's StaticTokenVerifier — a pre-shared bearer token. The partner
agent must send Authorization: Bearer <MCP_AUTH_TOKEN>; anything else is 401 Unauthorized
(verified). Rotate by changing MCP_AUTH_TOKEN and re-sharing.
Fail-closed: the server refuses to start if MCP_AUTH_TOKEN is empty or the built-in
vista-dev-token, unless MCP_ALLOW_INSECURE=1 (local dev only) — so you can't accidentally
ship it open or with the public default.
SSRF guard: the injected source_url is fetched server-side, so before fetching (and on
every redirect hop) the host is resolved and rejected if it's a private / loopback /
link-local / reserved address (e.g. cloud metadata, the internal LogV backend). Production
signed URLs are public, so this is transparent; for the local test client (which serves the
log on 127.0.0.1) set MCP_ALLOW_PRIVATE_FETCH=1. Signed URLs are never logged (the query
string is redacted) and are never echoed back in error messages.
TLS trust on outbound calls
Every outbound call (log fetch, LogV forward, ORB ask) verifies TLS, exactly like curl
without -k. A rejected certificate fails as httpx.ConnectError in ~0.1 s — before any HTTP
request is sent — and the flow log names it:
✖ fetch failed (ConnectError, TLS certificate rejected) for https://sa-staging.corp.fortinet.com/…
↳ TLS certificate rejected by 'sa-staging.corp.fortinet.com' (same failure as `curl` without `-k`). Fix one of: …Two ways to accommodate an internal host, in order of preference:
Symptom ( | Fix |
|
|
|
|
MCP_FETCH_INSECURE_TLS_HOSTS is a scoped curl -k: verification is skipped for those exact
hostnames only, every other host stays fully verified, and each use logs a WARNING. A relaxed
request may also only be redirected to another relaxed host — so an unverified hop can't
hand the connection off to an arbitrary target. MCP_FETCH_INSECURE_TLS=1 relaxes everything
and should be a last resort.
6. Going live (what to send the partner)
Per the starter kit, once the server is reachable from their backend:
Server URL —
https://vista.fortinet.com/mcp/(include the/mcp/path).Auth token — the
MCP_AUTH_TOKENvalue (share securely).For each log-consuming tool — the tool name and the input field that receives the injected log URL:
Log_Analyzer_Visualizer→source_url
They register the server, wire source_url to their signed-URL injector, and enable the tool.
7. Design notes
Proxy, not a re-implementation. VISTA-MCP holds no analysis logic; it forwards to the analyzer's API and formats the reply. The Log Visualizer decides the log subtype (SD-WAN today) and how to handle it — VISTA-MCP just surfaces the result (including "not supported").
Pluggable analyzers.
analyzers/base.Analyzeris the contract:name,log_field,description(),analyze(log_bytes, filename, question) -> str. One subclass per backend, one tool per subclass. See docs/ADDING_ANALYZERS.md.Bounded output. The report is text; the analysis is already reduced by the backend.
Stateless per call. Fetch → forward → return; nothing is stored.
Framework. FastMCP (runs on an ASGI/Starlette app via uvicorn) implements the MCP protocol and the
/mcp/HTTP transport — the same framework the partner's starter kit uses.
8. Verified behavior (end-to-end)
Scenario | Result |
| 1 tool |
With question (SD-WAN) | filter block (matched N/total) + LogV link + analysis + ORB Suggestions + iframe URL |
No question (SD-WAN) | LogV link + analysis + ORB Suggestions + iframe URL (no filter block) |
ORB Suggestions section | troubleshooting steps directly relevant to the findings, added by this MCP layer between the analysis and the visualization (fail-open) |
Response time | ~1–2 min (full analysis + ORB troubleshooting research); within the 300 s read timeout |
Non-SD-WAN log | "classified as |
14 MB log | streamed + processed (29,169 logs) |
Internal engine name | scrubbed (0 mentions in output) |
Wrong/missing bearer token | 401 Unauthorized |
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityDmaintenanceMCP server for querying and analyzing logs from VMware Aria Operations for Logs, enabling log search, incident detection, and vROps correlation.Last updated64MIT
- AlicenseBqualityDmaintenanceA complete MCP server for Fortinet FortiOS 7.6.x that exposes the entire REST API as typed MCP tools for use with MCP-compatible clients like Claude Desktop.Last updated10010MIT
- Alicense-qualityCmaintenanceA production-ready MCP server for managing FortiGate firewalls, enabling AI assistants to manage firewall policies, network objects, routing, and device configurations.Last updated32MIT
- Alicense-qualityBmaintenanceMCP server for managing Fortinet FortiCNAPP via AI agents, enabling vulnerability scanning, agent management, and compliance monitoring.Last updatedMIT
Related MCP Connectors
Autopilot MCP server for GEO analyses, reports, content, audits, memories and agents.
MCP Server for agents to onboard, pay, and provision services autonomously with InFlow
The MCP server for Azure DevOps, bringing the power of Azure DevOps directly to your agents.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ProjectVISTA-Kashcode/vista-agent-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server