PasarGuard MCP
The PasarGuard MCP server manages one or more PasarGuard panels via REST APIs with a two-step plan/apply workflow. It supports:
Panel Management: List panels, test connections, and load credentials from local files (.env, .md, etc.) securely.
Reading & Inspection: Fetch panel inventory (nodes, cores, hosts, groups, users, system status), list resources with filters, get single resources by ID, real-time node stats, and overall panel system status.
Write Planning: Plan creation, partial updates, and deletion for nodes, cores, hosts, groups, and users. For nodes, also plan actions like reconnect, sync, reset usage, or core update. All plans generate a confirmation token; changes are applied only after explicit confirmation.
Execution & Recovery: Apply changes with the token, inspect pending plans safely, and plan rollbacks to previous states.
Security & Limitations: Operations are local and confined to panel APIs; local state directories have restricted permissions; TLS verification is enabled. It does NOT manage cloud servers, SSH, or CDN/DNS providers.
Click on "Deploy 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., "@PasarGuard MCP Show me the current nodes on the main panel"
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.
PasarGuard MCP
PasarGuard MCP is a local Model Context Protocol server for managing one or more PasarGuard panels through their REST APIs. It is intentionally limited to panel operations. It does not install servers, manage Vultr, SSH into nodes, manage Cloudflare/Fastly, or change provider infrastructure.
The server supports both reading and writing. Writes use a two-step plan/apply workflow: the MCP reads the current object, creates a short-lived confirmation token, and only applies the saved change after the user confirms it. Update plans preserve fields that were not changed, which is important because PasarGuard core and host updates expect complete valid objects.
Install
cd projects/pasarguard-mcp
python3 -m venv .venv
.venv/bin/python -m pip install -e '.[dev]'Python 3.11 or newer is required.
Related MCP server: Caddy MCP
Configure panels
Static configuration is optional. The MCP can also load a credential file from a chat-driven tool call; see the next section.
Copy config/panels.example.json to a file outside Git, for example
~/.config/pasarguard-mcp/panels.json, and set the password in an environment
variable:
export PASARGUARD_MCP_CONFIG="$HOME/.config/pasarguard-mcp/panels.json"
export PASARGUARD_EXAMPLE_PASSWORD='your-panel-password'The configuration accepts multiple named panels:
{
"panels": {
"main": {
"base_url": "https://panel.example.com",
"username": "admin",
"password_env": "PASARGUARD_MAIN_PASSWORD",
"verify_tls": true,
"timeout": 30
},
"staging": {
"base_url": "https://staging-panel.example.com",
"username_env": "PASARGUARD_STAGING_USERNAME",
"password_env": "PASARGUARD_STAGING_PASSWORD"
}
}
}An existing bearer token can be configured with token_env instead of
username/password. Do not commit panel URLs, credentials, tokens, node API
keys, certificates, or exported panel objects to this repository.
The local state directory stores confirmation plans and before-snapshots with
mode 0700/0600. Override it with PASARGUARD_MCP_STATE_DIR when needed.
MCP client configuration
For a stdio MCP client, use the installed executable:
{
"mcpServers": {
"pasarguard": {
"command": "/absolute/path/to/projects/pasarguard-mcp/.venv/bin/pasarguard-mcp",
"env": {
"PASARGUARD_MCP_CONFIG": "/absolute/path/to/panels.json",
"PASARGUARD_MAIN_PASSWORD": "set-this-in-your-local-client-config"
}
}
}
}Prefer the client's secret/environment mechanism where it provides one. The MCP server never prints passwords or bearer tokens to stdout.
Chat-based credential files
You can tell Codex where an existing local credential file is instead of
putting it in the MCP setup. Ask it to use the load_panel_credentials tool,
for example:
Use the PasarGuard credentials in
/Users/me/workspace/memory/30-clients/example/credentials.local.md for the
panel named example. Keep them session-only and test the connection.The tool reads the file locally and extracts only recognized fields. Supported
formats are .env, .md, and .markdown; common keys include PANEL_URL,
PASARGUARD_BASE_URL, username, password, and token. The password is
never returned by the tool and is kept only in the MCP process by default.
If a Markdown file contains multiple named accounts, select the intended
credential block explicitly. For example, a file with a
flowship_super_admin block should be loaded with
credential_name=flowship_super_admin. The parser strips one matching pair of
Markdown backticks or quote characters around values. This matters for entries
such as Password: \...`; sending the backticks as part of the password causes PasarGuard to return HTTP 401. When multiple complete credential blocks exist, omitting credential_name` now fails safely instead of merging the
username from one account with the password or URL from another.
The tool accepts persist=true only when you explicitly want the profile
written to the protected local JSON config. The default is persist=false.
Use absolute local paths and keep credential files outside Git repositories.
URL, credential, filtering, and output normalization
Dashboard URLs are normalized to the PasarGuard site root. For example,
https://flowshipnet.com/dashboard/becomeshttps://flowshipnet.combefore API paths are appended.Markdown
##through######headings are selectable credential blocks in addition to named list blocks. This supports files where a section such as## PasarGuard Panel (production)directly contains URL, username, and password fields.List query keys that correspond to returned item fields are also enforced locally with exact matching. This protects callers when a panel silently ignores a filter such as
inbound_tag. Pagination/control keys that are not item fields remain upstream-only.PasarGuard's
/api/hostsendpoint returns a bare top-level JSON list, unlike the wrapped node/core/group/user endpoints. The MCP normalizes bare lists to an object keyed by the resource, such as{"hosts": [...], "total": N}. FastMCP otherwise emits one text content block per list item, which makes a large host inventory easy for downstream tool renderers to split or truncate. The normalized object produces one coherent structured block.Apply responses are compact receipts. Full updated core objects are not returned, and recursive redaction covers Reality
privateKey/shortIdsin read results. Verification should use the read tools after apply.
Tool groups
Read operations:
list_panels,load_panel_credentials,test_panelget_panel_inventorylist_panel_resource,get_panel_resourceget_node_realtime_stats,get_panel_system_status
Write planning operations:
Nodes: create, update, delete, reconnect, sync, reset usage, update core
Cores: create and update, with explicit optional node restart on updates
Hosts: create and update
Groups: create and update
Users: create and update by numeric ID
All supported resources can be planned for deletion
Write execution and recovery:
apply_changeapplies one still-valid confirmation token.inspect_changeshows a safe summary without the stored payload.plan_rollbackcreates a new confirmation plan from an applied update's before-snapshot.
The normal sequence is:
Inspect the panel or resource.
Call the relevant
plan_*tool.Show the returned summary and ask the user for confirmation.
Call
apply_changewith the returned token.Verify the resulting resource and node status.
API compatibility
The implementation follows the current public PasarGuard panel API layout,
including POST /api/admin/token, /api/nodes, /api/cores, /api/hosts,
/api/groups, /api/users, node action endpoints, and ID-based user routes
under /api/user/by-id/{user_id}. The panel API can evolve, so endpoint
changes should be updated in src/pasarguard_mcp/server.py and covered by
tests before release.
Development
.venv/bin/python -m pytest
.venv/bin/python -m compileall -q src tests
.venv/bin/ruff check src testsTests use an in-memory HTTP transport and never contact a real panel.
Scoped direct-API fallback
When the hosted MCP approval gateway is unavailable, the repository includes
scripts/apply_reality_expansion.py. It uses the same PasarGuardClient,
loads session credentials from the Lexo, Flowship, and VSL247 credential files,
checks every requested port/tag for collisions, saves each core once with
restart_nodes=false so its inbound tags exist, updates the groups, then
saves each core once with restart_nodes=true. Without --apply it only
reads and validates the live state; --verify-only reads back the current
core/group/node state; --restart-cores panel:id,... performs targeted
restart-enabled saves when a previous request timed out. It never creates
hosts.
The hosted connector and local elevated execution were both blocked by an external HTTP 403 approval-gateway response on 2026-08-18; until that gate is available, do not report the planned ports as live.
For a targeted Microsoft REALITY target/SNI repair across the same four panel
cores, use scripts/repair_reality_sni.py. It validates the exact inbound tag,
port, transport, and old/new SNI before changing only target and
serverNames, then sends one complete-core PUT with restart_nodes=true per
target and verifies the read-back. Run without --apply for a dry-run,
--verify-only for current state, or --apply for the authorized repair.
Security boundary
This is an operations tool with write access. Run it locally over stdio, use a least-privileged PasarGuard administrator when possible, keep TLS verification enabled, and review every plan before applying it. Credential-file loading extracts only known fields and does not return passwords. The MCP deliberately does not provide a generic arbitrary-URL request tool.
Available Tools
22 toolsapply_changeA
Apply one previously planned change after explicit user confirmation.
Inputs: change_id (required), confirmation_token (required). Returns: object
get_node_realtime_statsC
Get current realtime statistics for a PasarGuard node.
Inputs: panel (required), node_id (required).
get_panel_inventoryB
Fetch a compact panel inventory: nodes, cores, hosts, groups, users, and system status.
Inputs: panel (required). Returns: object
get_panel_resourceC
Get a node, core, host, group, or user by numeric ID.
Inputs: panel (required), resource (required), resource_id (required), include_sensitive.
get_panel_system_statusC
Get panel system statistics and worker health.
Inputs: panel (required). Returns: object
inspect_changeA
Inspect a local plan summary without exposing its stored credentials or full payload.
Inputs: change_id (required). Returns: object
list_panel_resourceC
List one PasarGuard panel resource. Query supports the panel's normal filters/pagination.
Inputs: panel (required), resource (required), query.
list_panelsA
List configured PasarGuard panel profiles without exposing credentials.
Inputs: no named parameters. Returns: result
plan_create_coreC
Plan creating a core configuration using the panel's CoreCreate body.
Inputs: core (required), panel (required). Returns: object
plan_create_groupC
Plan creating a group using the panel's GroupCreate body.
Inputs: group (required), panel (required). Returns: object
plan_create_hostC
Plan creating a subscription host using the panel's CreateHost body.
Inputs: host (required), panel (required). Returns: object
plan_create_nodeB
Plan adding a node. Apply only after asking the user to confirm the returned token.
Inputs: node (required), panel (required). Returns: object
plan_create_userC
Plan creating a PasarGuard user. The body follows the panel's UserCreate model.
Inputs: user (required), panel (required). Returns: object
plan_delete_resourceB
Plan deleting a panel resource. This is intentionally separate from update tools.
Inputs: panel (required), resource (required), resource_id (required). Returns: object
plan_node_actionC
Plan a node action that may reconnect, sync, reset usage, or update its core.
Inputs: panel (required), action (required), node_id (required), flush_users. Returns: object
plan_rollbackB
Plan restoring a previously applied update from its local before-snapshot.
Inputs: change_id (required). Returns: object
plan_update_coreC
Plan a core update. The full current core is merged with patch and restart_nodes is explicit.
Inputs: panel (required), patch (required), core_id (required), restart_nodes. Returns: object
plan_update_groupC
Plan a partial group update.
Inputs: panel (required), patch (required), group_id (required). Returns: object
plan_update_hostA
Plan a partial host update while preserving required fields from the current host.
Inputs: panel (required), patch (required), host_id (required). Returns: object
plan_update_nodeA
Plan a partial node update; the MCP fetches and preserves the complete current object.
Inputs: panel (required), patch (required), node_id (required). Returns: object
plan_update_userC
Plan a user update through the current ID-based PasarGuard route.
Inputs: panel (required), patch (required), user_id (required). Returns: object
test_panelC
Authenticate to a panel and return the current admin identity.
Inputs: panel (required). Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 22 tools
Most tools target distinct resource-action pairs (e.g., plan_create_node vs. plan_update_core), and read tools are clearly separated from planning tools. Some ambiguity exists between plan_node_action and plan_update_core since plan_node_action can also update a core, and plan_delete_resource is generic, but descriptions mitigate this.
The naming follows a consistent verb_noun pattern (e.g., plan_create_node, get_panel_inventory, apply_change). Minor inconsistencies include 'list_panel_resource' (singular generic) and 'plan_rollback' not matching the plan_create/update pattern, but overall the convention is predictable.
With 22 tools, the server is on the heavier side, which can be overwhelming but is justified by the breadth of PasarGuard management. The count is within the 'heavy' range (16-25) rather than extreme, so it earns a middle score.
The tool surface covers create, read, update, delete, planning, applying, rollback, and monitoring for core PasarGuard resources. Minor gaps exist, such as no explicit tool to list planned changes or cancel a plan, but these are workarounds via inspect_change and apply_change.
Related MCP Connectors
MCP server for mandates, delegation, policy-gated execution, credential grants, and audit.
An MCP server that provides an API to LLMs to manage their JumpCloud resources.
Governed MCP gateway: one endpoint for your tools, with credential custody and audit log.
Hosted remote MCP for protected account access, permissions, activity history and supported undo.
Related MCP Servers
- AlicenseAqualityCmaintenanceMCP server for Proxmox VE and Proxmox Datacenter Manager, covering every API endpoint via six consolidated tools for list, describe, and call operations with a read-only safety gate.66 npm2AGPL 3.0
- AlicenseAqualityCmaintenanceMCP server for safely inspecting and operating a local Caddy admin API. Provides read-only tools and dry-run mutations for config management.7MIT
- AlicenseBqualityCmaintenanceLocal MCP server for inspecting and managing an allowlisted Discord server via Discord's REST API, with safety modes, idempotent JSON blueprints, and destructive-operation safeguards.271MIT
- AlicenseBqualityDmaintenanceMCP server for interacting with a self-hosted Appsmith instance via its REST API, enabling read/update/create of pages, queries, JS objects, widgets, datasources, and applications with lazy session management and destructive-operation gating.30MIT