Skip to main content
Glama

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.2 is 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-failover skill 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-0600 local providers.local.yaml overlay 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 preserve mode does not delete old Provider connections after a switch, so an active Codex or ChatGPT WebSocket can finish naturally; optional replacement_only cleanup 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

openai

reviewed OpenAI/ChatGPT roots

Enabled

workbuddy-cn

workbuddy.cn

Disabled

kimi

kimi.com

Disabled

minimax

minimaxi.com

Disabled

mavis

mavislabs.ai

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 --yes

If 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 --yes

The 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-preview

Apply the persistent Clash Verge enhancements and install the user LaunchAgent:

mihomo-ai-failover install \
  --confirm INSTALL_MIHOMO_AI_FAILOVER

If restart_required is true, restart Clash Verge, then:

mihomo-ai-failover check
mihomo-ai-failover inventory
mihomo-ai-failover service-start

The 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-failover

Claude Code plugin

claude plugin marketplace add doublebearoliver-cyber/mihomo-ai-failover
claude plugin install mihomo-ai-failover@mihomo-ai-failover

Both 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-start

Use 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 20

Known 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>' \
  --enable

If 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_AGENT

Restart 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 build

License

MIT. See LICENSE.

Available Tools

20 tools
apply_provider_overlayWrite private Provider overlayA
Idempotent

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.

NameRequiredDescriptionDefault
enabledNo
config_pathNo
provider_idYes
confirmationNo
exact_domainsYes
critical_domainsNo

Output Schema

NameRequiredDescription

No output parameters

check_provider_pathsCompare Provider network pathsA
Read-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.

NameRequiredDescriptionDefault
config_pathNo
provider_idYes

Output Schema

NameRequiredDescription

No output parameters

diagnose_environmentDiagnose local Mihomo environmentA
Read-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.

NameRequiredDescriptionDefault
config_pathNo

Output Schema

NameRequiredDescription

No output parameters

discover_provider_domainsObserve local Provider domainsA
Read-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.

NameRequiredDescriptionDefault
config_pathNo
provider_idYes
duration_secondsNo
include_temporal_candidatesNo

Output Schema

NameRequiredDescription

No output parameters

get_recent_eventsRead recent sanitized failover eventsB
Read-onlyIdempotent

Read up to 100 local sanitized events. Credentials, subscriptions, server addresses, and exit IPs are never returned.

NameRequiredDescriptionDefault
limitNo
config_pathNo
provider_idNo
include_node_namesNo

Output Schema

NameRequiredDescription

No output parameters

get_service_statusGet LaunchAgent statusA
Read-onlyIdempotent

Return whether the per-user failover LaunchAgent is installed and running.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription

No output parameters

get_statusGet failover statusA
Read-onlyIdempotent

Return controller, dedicated Provider group, health state, and pool counts. Node names remain hidden unless include_node_names is true.

NameRequiredDescriptionDefault
config_pathNo
provider_idNo
include_node_namesNo

Output Schema

NameRequiredDescription

No output parameters

initialize_configWrite local failover configA
Idempotent

Write an auto-discovered local config. Requires mutation opt-in and confirmation=WRITE_LOCAL_CONFIG.

NameRequiredDescriptionDefault
config_pathNo
confirmationNo

Output Schema

NameRequiredDescription

No output parameters

install_failoverInstall local failoverA
Idempotent

Back up and integrate the persistent AI group/rules, then install the LaunchAgent. Requires mutation opt-in and confirmation=INSTALL_MIHOMO_AI_FAILOVER.

NameRequiredDescriptionDefault
config_pathNo
confirmationNo
start_when_readyNo

Output Schema

NameRequiredDescription

No output parameters

list_poolsList failover poolsB
Read-onlyIdempotent

Return active, warm, and cold pool counts plus independent-exit statistics. Node names are opt-in; exit IPs are never returned.

NameRequiredDescriptionDefault
config_pathNo
provider_idNo
include_node_namesNo

Output Schema

NameRequiredDescription

No output parameters

list_provider_profilesList AI Provider profilesA
Read-onlyIdempotent

List public Provider templates and local enablement state without returning observed hostnames, node names, exit IPs, or credentials.

NameRequiredDescriptionDefault
config_pathNo

Output Schema

NameRequiredDescription

No output parameters

preview_installPreview local installationA
Read-onlyIdempotent

Preview persistent Clash Verge group/rule changes and report the environment without writing files.

NameRequiredDescriptionDefault
config_pathNo

Output Schema

NameRequiredDescription

No output parameters

preview_provider_overlayPreview private Provider overlayA
Read-onlyIdempotent

Preview exact-domain additions and optional Provider enablement in the local private overlay. This does not write files or change Clash Verge.

NameRequiredDescriptionDefault
enabledNo
config_pathNo
provider_idYes
exact_domainsYes
critical_domainsNo

Output Schema

NameRequiredDescription

No output parameters

record_web_feedbackRecord real-browser Provider web feedbackA
Idempotent

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.

NameRequiredDescriptionDefault
nodeYes
reasonYes
statusYes
config_pathNo
provider_idNo
ttl_secondsNo
confirmationNo

Output Schema

NameRequiredDescription

No output parameters

rollback_profileRoll back persistent profile integrationB
DestructiveIdempotent

Restore the latest backed-up Clash Verge enhancement files. Requires mutation opt-in and confirmation=ROLLBACK_PROFILE_INTEGRATION.

NameRequiredDescriptionDefault
backup_pathNo
config_pathNo
confirmationNo

Output Schema

NameRequiredDescription

No output parameters

run_health_checkRun read-only Provider health checkA
Read-onlyIdempotent

Probe direct connectivity and the configured Provider path through its selected AI group. Defaults to OpenAI and never switches nodes.

NameRequiredDescriptionDefault
config_pathNo
provider_idNo
include_node_nameNo

Output Schema

NameRequiredDescription

No output parameters

simulate_failoverSimulate failover invariantsA
Read-onlyIdempotent

Run an isolated deterministic simulation of adaptive failure gates, prepared-route timing, connection preservation, and distinct-exit ranking. No live proxy is changed.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription

No output parameters

start_monitorStart failover LaunchAgentA
Idempotent

Start or restart the installed monitor. Requires mutation opt-in and confirmation=START_LAUNCH_AGENT.

NameRequiredDescriptionDefault
config_pathNo
confirmationNo

Output Schema

NameRequiredDescription

No output parameters

stop_monitorStop failover LaunchAgentA
Idempotent

Stop the monitor without changing Clash Verge. Requires mutation opt-in and confirmation=STOP_LAUNCH_AGENT.

NameRequiredDescriptionDefault
config_pathNo
confirmationNo

Output Schema

NameRequiredDescription

No output parameters

uninstall_monitorUninstall failover LaunchAgentA
DestructiveIdempotent

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.

NameRequiredDescriptionDefault
config_pathNo
confirmationNo

Output Schema

NameRequiredDescription

No output parameters

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 10 tool updatesv0.2.2
    • Addedapply_provider_overlay
    • Addedcheck_provider_paths
    • Addeddiscover_provider_domains
    • Changedget_recent_events1 field changed
      • addedInput schema / properties / provider_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Provider Id"
        +}
    • Changedget_status1 field changed
      • addedInput schema / properties / provider_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Provider Id"
        +}
    • Changedlist_pools1 field changed
      • addedInput schema / properties / provider_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Provider Id"
        +}
    • Addedlist_provider_profiles
    • Addedpreview_provider_overlay
    • Addedrecord_web_feedback
    • Changedrun_health_check1 field changed
      • addedInput schema / properties / provider_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Provider Id"
        +}
  2. 14 tool updatesv0.1.0
    • First observeddiagnose_environment
    • First observedget_recent_events
    • First observedget_service_status
    • First observedget_status
    • First observedinitialize_config
    • First observedinstall_failover
    • First observedlist_pools
    • First observedpreview_install
    • First observedrollback_profile
    • First observedrun_health_check
    • First observedsimulate_failover
    • First observedstart_monitor
    • First observedstop_monitor
    • First observeduninstall_monitor

TDQS

A3.8/5.0

Scored across 20 tools

Disambiguation4/5

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.

Naming Consistency5/5

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.

Tool Count4/5

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.

Completeness4/5

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

ActivityInactive
ResponsivenessNo recent community issues

Related MCP Connectors

Related MCP Servers