mihomo-ai-failover
This server provides read-only diagnostics and controlled local operations for the Mihomo AI failover system on macOS.
Diagnose local environment:
diagnose_environment,preview_install,get_service_statusinspect Clash Verge, Mihomo controller, system proxy, profile integration, and LaunchAgent state.List and check Providers:
list_provider_profiles,check_provider_paths,run_health_checkinspect Provider templates, direct vs proxied paths, and health without switching nodes.Observe Provider traffic:
discover_provider_domainswatches sanitized connection hostnames while the user exercises a Provider.Preview/write private overlay:
preview_provider_overlayshows exact-domain and enablement changes;apply_provider_overlaywrites them only with confirmation.Read failover state and history:
get_status,list_pools, andget_recent_eventsreport groups, pools, and sanitized events without exposing exit IPs or credentials unless node names are explicitly allowed.Simulate failover behavior:
simulate_failoverruns deterministic invariant checks without changing live proxy state.Manage local install and service:
initialize_config,install_failover,start_monitor, andstop_monitorhandle config, persistent Clash enhancements, and LaunchAgent control with explicit confirmations.Roll back or uninstall:
rollback_profilerestores backed-up Clash profile changes;uninstall_monitorstops and trashes the LaunchAgent plist.Record real-browser feedback:
record_web_feedbackstores time-limited confirmed/rejected browser evidence for an observed exit fingerprint, requiring the monitor to be stopped and explicit confirmation.
All mutating operations require local mutation opt-in and exact server-enforced confirmations; read-only operations never switch proxies or expose secrets.
Enables automatic failover for OpenAI services by monitoring connectivity to OpenAI endpoints and switching the active proxy node when failures are detected, ensuring reliable access to ChatGPT and the OpenAI API.
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., "@mihomo-ai-failoverCheck the health of the AI proxy group and show current failover status."
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.
Mihomo AI Failover — automatic proxy failover for ChatGPT and Codex
Automatic, stability-first AI proxy failover for macOS with Clash Verge Rev and Mihomo. It diagnoses ChatGPT login/loading failures, Codex network errors, and stalled AI streams, keeps a working selected node, and switches only the affected Provider's dedicated proxy group after guarded, verified hard-failure evidence on that Provider's real path.
Version
0.2.2is an early public preview for macOS, Clash Verge Rev, and Mihomo. OpenAI is enabled by default. WorkBuddy (China), Kimi, MiniMax, and Mavis remain disabled until their real local traffic is observed and reviewed. The project never enables TUN automatically.
中文说明 · AI agent contract · Agent integration · Architecture · Validation
AI agents: read the
dbear-mihomo-ai-failoverskill before using any MCP tool. It is the canonical machine-facing contract for supported environments, safety boundaries, tool order, stop conditions, and result reporting. This README is not a substitute for that contract.
Public core and private adaptation
There are two layers, not two long-lived forks:
the public layer contains the engine, conservative Provider templates, CLI/MCP/Skill contracts, installer, rollback, and tests;
the personal layer is a mode-
0600localproviders.local.yamloverlay with only that Mac's approved Provider enablement, exact domains, and probes.
The public package contains no local nodes, exits, or observed hostnames. An agent must use local Mihomo evidence, preview the narrow overlay, and obtain authorization before writing it.
Related MCP server: Codex 2.0 MCP Gateway
Why
Generic url-test groups optimize latency. They do not prove that ChatGPT
login, the OpenAI API, streaming connections, or a particular exit region are
usable. This project validates each enabled Provider path and:
ignores small latency changes and isolated soft anomalies;
retries only the hard-failing probe once before a round can count as a verified hard failure;
switches after two guarded rounds only when at least two independent critical targets failed across those rounds; one repeatedly failing target requires at least three rounds and a 30-second observation window;
excludes local-network and controller failures from blind switching;
maintains active, warm, and cold pools deduplicated by observed exit IP;
confirms the selected route before starting isolated candidate validation, so an isolated first failure cannot launch a broad node scan; two independent candidates are prepared while at most two are live-selected, and each still needs two usable full-path samples with at least one retry-free result;
ranks health, success history, exit/ASN diversity, cooldown, and stability before latency;
verifies the selected candidate on the live route before committing; a retry-assisted pass requires a second, retry-free verification after three seconds, otherwise it rolls back, followed by a 60-second probation period;
reruns a just-in-time live-core preflight immediately before each candidate selection, so stale preparation evidence cannot cause a blind switch;
uses make-before-break connection draining: the default
preservemode does not delete old Provider connections after a switch, so an active Codex or ChatGPT WebSocket can finish naturally; optionalreplacement_onlycleanup requires a newer same-process replacement on the new route;notifies once per all-unavailable outage episode and backs off;
exposes the same behavior through a CLI, local stdio MCP, Codex plugin, and Claude Code plugin.
A silent or spinning AI client is only an auxiliary symptom. It never triggers a switch by itself. GitHub, Git, npm, Docker, shared infrastructure, and ordinary websites are outside every Provider failure trigger.
Each Provider has a separate select group, health history, active/warm/cold pools, cooldowns, switch episode, state file, and log. Providers share only the read-only subscription node catalog. Background deep scans are serialized and daemon starts are staggered to bound local load.
Provider ID | Conservative public root | Default |
| reviewed OpenAI/ChatGPT roots | Enabled |
|
| Disabled |
|
| Disabled |
|
| Disabled |
|
| Disabled |
These are bootstrap identities, not exhaustive API/auth/streaming/CDN lists. Non-OpenAI profiles must be adapted from evidence on the target Mac before automatic failover is enabled.
Each enabled Provider adds a bounded ten-second foreground check and its own health history. Enable only Providers the operator uses. Heavier isolated deep scans are serialized across Providers, so hundreds of subscription nodes are not all tested at high frequency.
An exact ChatGPT Cloudflare challenge is classified as browser_ambiguous, not
as a generic healthy response. It can remain candidate-eligible only when the
API, authentication, and WebSocket transport probes are healthy. Other soft
responses are soft_unstable and cannot become candidates. A user-confirmed
real-browser result can also be stored against the observed exit IP + ASN +
country fingerprint. Confirmed results last seven days by default; rejected
results exclude that exit for 24 hours. Feedback never triggers a switch by
itself and automatically becomes inapplicable when the exit fingerprint
changes.
Install
Install the Agent Skill with the official skills CLI:
npx --yes skills@latest add doublebearoliver-cyber/mihomo-ai-failover \
--skill dbear-mihomo-ai-failover --agent codex --global --yesIf a client cannot discover a nested Skill from the repository shorthand, use the canonical Skill directory directly:
npx --yes skills@latest add \
https://github.com/doublebearoliver-cyber/mihomo-ai-failover/tree/main/plugins/mihomo-ai-failover/skills/dbear-mihomo-ai-failover \
--skill dbear-mihomo-ai-failover --agent codex --global --yesThe Skill supplies instructions and safety boundaries; it does not install the local CLI/MCP runtime. To diagnose or operate a Mac, install the runtime too.
Install uv, then:
uv tool install \
'mihomo-ai-failover[mcp] @ git+https://github.com/doublebearoliver-cyber/mihomo-ai-failover@v0.2.2'Diagnose and preview before writing:
mihomo-ai-failover diagnose
mihomo-ai-failover check
mihomo-ai-failover profile-previewApply the persistent Clash Verge enhancements and install the user LaunchAgent:
mihomo-ai-failover install \
--confirm INSTALL_MIHOMO_AI_FAILOVERIf restart_required is true, restart Clash Verge, then:
mihomo-ai-failover check
mihomo-ai-failover inventory
mihomo-ai-failover service-startThe installer never edits generated clash-verge.yaml. It backs up and updates
the selected profile's persistent Groups and Rules enhancements.
Codex plugin
codex plugin marketplace add doublebearoliver-cyber/mihomo-ai-failover
codex plugin add mihomo-ai-failover@mihomo-ai-failoverClaude Code plugin
claude plugin marketplace add doublebearoliver-cyber/mihomo-ai-failover
claude plugin install mihomo-ai-failover@mihomo-ai-failoverBoth plugins bundle the same dbear-mihomo-ai-failover Skill and local MCP server.
MCP mutations are disabled by default and require both local opt-in and an
exact server-enforced confirmation.
Agents without native plugin support can use the generic stdio MCP definition
and load the same SKILL.md as instructions. The skill does not grant access to
the Mac: the agent still needs a trusted local MCP client. See
Agent integration.
To record an explicitly verified browser result, stop the monitor first so the state lock is uncontended:
mihomo-ai-failover service-stop
mihomo-ai-failover web-feedback \
--node 'local node display name' \
--status confirmed \
--reason browser_login_success \
--confirm RECORD_WEB_FEEDBACK
mihomo-ai-failover service-startUse rejected and browser_login_failed for a verified failure. The command
refuses to record feedback without an observed exit fingerprint.
Adapt another Provider
Ask the user to exercise one Provider while the read-only observer runs:
mihomo-ai-failover diagnose
mihomo-ai-failover providers-list
mihomo-ai-failover provider-check --provider kimi
mihomo-ai-failover provider-observe --provider kimi --duration-seconds 20Known roots confirm coverage. Process-correlated hosts may be proposed as
exact domains. Browser-only temporal_only hosts are never auto-added, and
shared infrastructure is never a critical failover trigger. Preview before
writing:
mihomo-ai-failover provider-overlay-preview \
--provider kimi \
--domain '<reviewed exact hostname>' \
--critical-domain '<reviewed critical hostname>' \
--enableIf direct access is already stable and proxying is unnecessary or worse, do not force that Provider into a failover group.
After explicit authorization, write with
--confirm APPLY_PROVIDER_OVERLAY, then separately preview/apply the
persistent profile integration and restart Clash Verge when requested. See the
Provider adaptation contract.
Disabling a Provider stops its state machine after the service restarts. To avoid deleting user-managed rules, previously installed persistent rules are removed only through an authorized rollback or explicit profile cleanup.
Roll back
mihomo-ai-failover service-stop
mihomo-ai-failover profile-rollback \
--confirm ROLLBACK_PROFILE_INTEGRATION
mihomo-ai-failover service-uninstall \
--confirm UNINSTALL_LAUNCH_AGENTRestart Clash Verge after restoring the enhancement backup. The LaunchAgent plist is moved to Trash rather than permanently deleted.
Safety and privacy
Controls only dedicated Provider groups; one Provider cannot trigger another.
Uses the local Unix-domain Mihomo controller by default.
Reads the controller secret at runtime and never returns it.
Does not store subscription URLs, proxy server addresses, or proxy credentials.
MCP never returns exit IPs and hides node names by default.
Does not expose a TCP control listener.
A hosted model cannot directly reach a user's localhost. An authenticated remote-to-local bridge is intentionally outside version 0.x. See PRIVACY.md for exact network destinations and local data.
Development
uv sync --all-extras --dev
uv run pytest
uv run ruff check .
uv run ruff format --check .
uv run python scripts/scan_sensitive.py
uv run python -m buildLicense
MIT. See LICENSE.
Available Tools
20 toolsapply_provider_overlayWrite private Provider overlayAIdempotent
Write user-approved exact domains and optional Provider enablement to the local private overlay. It does not modify Clash Verge by itself. Requires mutation opt-in and confirmation=APPLY_PROVIDER_OVERLAY.
| Name | Required | Description | Default |
|---|---|---|---|
| enabled | No | ||
| config_path | No | ||
| provider_id | Yes | ||
| confirmation | No | ||
| exact_domains | Yes | ||
| critical_domains | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
check_provider_pathsCompare Provider network pathsARead-onlyIdempotent
Run the configured Provider probes once over a direct connection and once through the current macOS system-proxy path. This is read-only, does not require the Provider group to exist, and never switches nodes.
| Name | Required | Description | Default |
|---|---|---|---|
| config_path | No | ||
| provider_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
diagnose_environmentDiagnose local Mihomo environmentARead-onlyIdempotent
Inspect macOS, Clash Verge paths, Unix controller reachability, system proxy state, AI group presence, and LaunchAgent status. Use before any installation or troubleshooting action.
| Name | Required | Description | Default |
|---|---|---|---|
| config_path | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
discover_provider_domainsObserve local Provider domainsARead-onlyIdempotent
Observe sanitized Mihomo connection hostnames for up to 60 seconds while the user exercises one Provider. Never returns URLs, paths, connection IDs, IPs, or chains. Temporal-only candidates are hidden by default and, when explicitly requested, are never auto-recommended.
| Name | Required | Description | Default |
|---|---|---|---|
| config_path | No | ||
| provider_id | Yes | ||
| duration_seconds | No | ||
| include_temporal_candidates | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
get_recent_eventsRead recent sanitized failover eventsBRead-onlyIdempotent
Read up to 100 local sanitized events. Credentials, subscriptions, server addresses, and exit IPs are never returned.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| config_path | No | ||
| provider_id | No | ||
| include_node_names | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
get_service_statusGet LaunchAgent statusARead-onlyIdempotent
Return whether the per-user failover LaunchAgent is installed and running.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
get_statusGet failover statusARead-onlyIdempotent
Return controller, dedicated Provider group, health state, and pool counts. Node names remain hidden unless include_node_names is true.
| Name | Required | Description | Default |
|---|---|---|---|
| config_path | No | ||
| provider_id | No | ||
| include_node_names | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
initialize_configWrite local failover configAIdempotent
Write an auto-discovered local config. Requires mutation opt-in and confirmation=WRITE_LOCAL_CONFIG.
| Name | Required | Description | Default |
|---|---|---|---|
| config_path | No | ||
| confirmation | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
install_failoverInstall local failoverAIdempotent
Back up and integrate the persistent AI group/rules, then install the LaunchAgent. Requires mutation opt-in and confirmation=INSTALL_MIHOMO_AI_FAILOVER.
| Name | Required | Description | Default |
|---|---|---|---|
| config_path | No | ||
| confirmation | No | ||
| start_when_ready | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
list_poolsList failover poolsBRead-onlyIdempotent
Return active, warm, and cold pool counts plus independent-exit statistics. Node names are opt-in; exit IPs are never returned.
| Name | Required | Description | Default |
|---|---|---|---|
| config_path | No | ||
| provider_id | No | ||
| include_node_names | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
list_provider_profilesList AI Provider profilesARead-onlyIdempotent
List public Provider templates and local enablement state without returning observed hostnames, node names, exit IPs, or credentials.
| Name | Required | Description | Default |
|---|---|---|---|
| config_path | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
preview_installPreview local installationARead-onlyIdempotent
Preview persistent Clash Verge group/rule changes and report the environment without writing files.
| Name | Required | Description | Default |
|---|---|---|---|
| config_path | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
preview_provider_overlayPreview private Provider overlayARead-onlyIdempotent
Preview exact-domain additions and optional Provider enablement in the local private overlay. This does not write files or change Clash Verge.
| Name | Required | Description | Default |
|---|---|---|---|
| enabled | No | ||
| config_path | No | ||
| provider_id | Yes | ||
| exact_domains | Yes | ||
| critical_domains | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
record_web_feedbackRecord real-browser Provider web feedbackAIdempotent
Record time-limited browser evidence for the Provider and node's current observed exit fingerprint. status must be confirmed or rejected. This never switches a proxy and requires the monitor to be stopped, mutation opt-in, and confirmation=RECORD_WEB_FEEDBACK.
| Name | Required | Description | Default |
|---|---|---|---|
| node | Yes | ||
| reason | Yes | ||
| status | Yes | ||
| config_path | No | ||
| provider_id | No | ||
| ttl_seconds | No | ||
| confirmation | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
rollback_profileRoll back persistent profile integrationBDestructiveIdempotent
Restore the latest backed-up Clash Verge enhancement files. Requires mutation opt-in and confirmation=ROLLBACK_PROFILE_INTEGRATION.
| Name | Required | Description | Default |
|---|---|---|---|
| backup_path | No | ||
| config_path | No | ||
| confirmation | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
run_health_checkRun read-only Provider health checkARead-onlyIdempotent
Probe direct connectivity and the configured Provider path through its selected AI group. Defaults to OpenAI and never switches nodes.
| Name | Required | Description | Default |
|---|---|---|---|
| config_path | No | ||
| provider_id | No | ||
| include_node_name | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
simulate_failoverSimulate failover invariantsARead-onlyIdempotent
Run an isolated deterministic simulation of adaptive failure gates, prepared-route timing, connection preservation, and distinct-exit ranking. No live proxy is changed.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
start_monitorStart failover LaunchAgentAIdempotent
Start or restart the installed monitor. Requires mutation opt-in and confirmation=START_LAUNCH_AGENT.
| Name | Required | Description | Default |
|---|---|---|---|
| config_path | No | ||
| confirmation | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
stop_monitorStop failover LaunchAgentAIdempotent
Stop the monitor without changing Clash Verge. Requires mutation opt-in and confirmation=STOP_LAUNCH_AGENT.
| Name | Required | Description | Default |
|---|---|---|---|
| config_path | No | ||
| confirmation | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
uninstall_monitorUninstall failover LaunchAgentADestructiveIdempotent
Stop the monitor and move its plist to Trash. Persistent Clash profile changes are not removed. Requires mutation opt-in and confirmation=UNINSTALL_LAUNCH_AGENT.
| Name | Required | Description | Default |
|---|---|---|---|
| config_path | No | ||
| confirmation | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
10 tool updates
v0.2.2- Added
apply_provider_overlay - Added
check_provider_paths - Added
discover_provider_domains - Changed
get_recent_events1 field changed- added
Input schema / properties / provider_idAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Provider Id" +}
- Changed
get_status1 field changed- added
Input schema / properties / provider_idAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Provider Id" +}
- Changed
list_pools1 field changed- added
Input schema / properties / provider_idAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Provider Id" +}
- Added
list_provider_profiles - Added
preview_provider_overlay - Added
record_web_feedback - Changed
run_health_check1 field changed- added
Input schema / properties / provider_idAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Provider Id" +}
14 tool updates
v0.1.0- First observed
diagnose_environment - First observed
get_recent_events - First observed
get_service_status - First observed
get_status - First observed
initialize_config - First observed
install_failover - First observed
list_pools - First observed
preview_install - First observed
rollback_profile - First observed
run_health_check - First observed
simulate_failover - First observed
start_monitor - First observed
stop_monitor - First observed
uninstall_monitor
TDQS
Scored across 20 tools
Most tools have clear, distinct purposes, but a few pairs like get_status/list_pools and check_provider_paths/run_health_check could be confused without careful reading. The detailed descriptions help differentiate them, so overall ambiguity is low.
All tool names follow a consistent verb_noun snake_case pattern (e.g., preview_install, run_health_check, uninstall_monitor). There are no mixed conventions, and the verb clearly indicates the action.
With 20 tools, the set is on the heavier side, but each tool addresses a distinct phase of the failover lifecycle (preview, install, monitor, rollback). Given the complexity of the domain, the count is justifiable, though some status tools could potentially be consolidated.
The tool surface covers the full lifecycle from environment diagnosis and provider overrides to installation, monitoring, and uninstallation. Minor gaps exist, such as no direct tool for updating failover settings after initial config, but users can work around this.
Maintenance
Related MCP Connectors
MCP server for Uptrack uptime monitoring. Manage monitors and incidents from AI agents.
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
Hosted OpenAI Ads MCP server for Claude, ChatGPT and Cursor, with each action switched per account.
Talk to your public-facing AI from any MCP client — Claude, ChatGPT, Cursor, Cline, Windsurf.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceAn MCP server that functions as an intelligent gateway for multiple LLM backends including OpenAI, Claude, and Ollama. It supports automatic provider fallback, streaming responses via Server-Sent Events, and real-time monitoring for robust AI integration.MIT
- FlicenseNot gradedqualityDmaintenanceTurns a Mac into an MCP host exposing terminal, filesystem, browser automation, and macOS controls to approved AI clients via OpenAI's Secure MCP Tunnel.-
- AlicenseNot gradedqualityCmaintenanceEnables macOS users to securely connect AI assistants such as Notion AI, Claude, and Cursor to their local files and terminal through an MCP server protected by a Bearer token and Cloudflare Tunnel.MIT
- AlicenseBqualityBmaintenanceGive any chat AI a real terminal. Local stdio MCP for Warp, Claude Desktop, and other hosts. macOS, Swift.4018MIT