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. On every call it discovers a set of standard analyzers, and an AI Controller decides which optional ones fit the question and how to call each one from the contract it just discovered; they run in parallel, their reports are concatenated, and ORB troubleshooting is appended — with no per-analyzer code. Adding capability is a config edit. Every job is stored in Postgres. 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/gui_guide.md — the operator console: Flow · Dashboard · History
docs/db_setup.md — durable job history (the prod
psqlcommands)docs/testing.md — run & test locally, with commands
Console at
/gui— live flow of every job, dashboard analytics, searchable history, and the TOOL_ENABLEMENT / routing-prompt editor. It also serves two standalone pages:/gui/user-guide(how to drive the console) and/gui/api-integration-guide(the API an analyzer must expose to plug in) — both also under/mcp/gui/…changes.md — what changed in the latest revision, and why
(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/CallPlan/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 §11)
│ ├── discovery.py # GET /discover for all analyzers (concurrent, fail-soft) + probe()
│ ├── ai_controller.py # the AI gateway client (fail-safe)
│ ├── decide.py · plan.py # ALWAYS-ON decision: pick optional analyzers + plan every call
│ │ # from live discovery, then validate the plan against it
│ ├── analyzer_client.py # the ONE generic call — executes a validated plan
│ ├── orb.py · pipeline.py # ORB (fail-open) + the whole flow wired together
│ ├── jobs.py · db.py # job/flow registry (CLI logs) + durable history in Postgres
│ └── gui.py # the /gui routes (state, history, analytics, config, probe)
├── gui/index.html # the operator console — Flow · Dashboard · History (red/white, dark mode)
├── gui/user_guide.html # served at /gui/user-guide (console walkthrough)
├── gui/api_guide.html # served at /gui/api-integration-guide (analyzer contract)
├── fakes/fake_analyzer.py # a reference analyzer following the contract (+ run_fakes.sh)
├── fakes/fake_analyzer_v2.py # the same contract with a DIFFERENT request shape (dynamic-discovery test)
├── 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 ·
│ # gui_guide.md · db_setup.md (+ .sql) · 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 |
|
|
|
|
| AI gateway used for the routing + invocation decision (legacy name |
|
| secondary gateway (legacy |
|
| gateway read timeout (s) (legacy |
| (unset) | Postgres for durable job history + console analytics, e.g. |
|
|
|
|
|
|
|
| how many recent jobs the live console keeps in memory |
Every tool call logs the full flow to the terminal with a correlation id:
[633d5f5b] ▶ TOOL CALL Log_Analyzer_Visualizer question='SLA failures for LO_C1_2 and High CPU' source_url=http://…/sdwan.log
[633d5f5b] fetch: done — 13,885,720 bytes, filename='DEMO_LOG_VISUALIZER_SDWAN.log' in 0.31s
[633d5f5b] ✔ [tool_enablement] ok mandatory=['logv'] optional=['perf'] orb=on
[633d5f5b] ✔ [discover] ok discovered=['logv', 'perf']
[633d5f5b] → [ai_controller] asking (4,068-char prompt · mode=select+plan · mandatory=['logv'] optional=['perf'])
[633d5f5b] ✔ [ai_controller] ok (21022ms) The user asks about 'High CPU', which is a performance concern…
[633d5f5b] → call[logv] POST …/agent_assist/run (file=13,885,720B → file, fields=['question'], plan=ai)
[633d5f5b] → call[perf] POST …/perf/run (file=13,885,720B → file, fields=['question'], plan=ai)
[633d5f5b] ✔ [concat] ok 2 section(s), 7,568 chars
[633d5f5b] ✔ [orb] ok (38214ms) 11,159 chars appended
[633d5f5b] ◀ JOB DONE report=18,749 chars in 86.2s5. 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, discovered live. The contract is docs/analyzer_api.md:
GET <base>/discover+POST <query.path>. The orchestrator holds one discover function, one call function and one read path, and learns each analyzer's request shape from its discovery on every call — so an analyzer can change its API without a change here. Adding one is a config edit in the console.The model can propose, never decide alone. The AI Controller's request plan is validated field-by-field against the analyzer's own discovery before anything is sent; anything not advertised is corrected or dropped, and the correction is recorded.
Fail-safe everywhere. No AI gateway ⇒ deterministic routing + discovery-built requests. No ORB ⇒ report without it. No database ⇒ live view only. One analyzer down ⇒ the others still answer.
Bounded output. The report is text; the analysis is already reduced by the backend.
Stateless per call for the log. Fetch → forward → return; the log itself is never stored. Job metadata and reports are persisted for the console's history and analytics.
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 |
| every configured 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 |
AI Controller | runs on every job — |
Analyzer with a different contract | called correctly with no code change (renamed file/question params, an extra required param, a different path) |
AI gateway unreachable | fail-safe: all optional analyzers run, requests built from discovery, client output unaffected |
Job history | every job + step + per-analyzer request/result + final report in Postgres, replayable in the console after a restart |
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.64MIT
- 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.10011MIT
- Alicense-qualityCmaintenanceA production-ready MCP server for managing FortiGate firewalls, enabling AI assistants to manage firewall policies, network objects, routing, and device configurations.33MIT
- Alicense-qualityBmaintenanceMCP server for managing Fortinet FortiCNAPP via AI agents, enabling vulnerability scanning, agent management, and compliance monitoring.MIT
Related MCP Connectors
Autopilot MCP server for GEO analyses, reports, content, audits, memories and agents.
Hosted MCP server for agent governance: MCP config audits, injection scans, scope-policy checks.
MCP Server for agents to onboard, pay, and provision services autonomously with InFlow
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