BorealHost
REMOTE · BOREALHOST.AI · 2 COMPONENTS · SCANNED SEP 20
Agent-native web hosting — deploy sites, manage DNS, register domains, scale infrastructure
Available components
How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score → Why this is hard to score →
Endpoint Security57
- The endpoint's TLS certificate is valid, in date, and uses a strong key. View diagnostics → Pass
- Authorisation not fully verified: no authorisation is required to call this server, and 184 tool(s) never declared a destructiveHint. The MCP spec treats an absent hint as destructive by default, so we cannot call this surface safe. See how to fix → View diagnostics → Unverified
- HTTPS is enforced; there's no plaintext access path. View diagnostics → Pass
- HSTS check failed: the Strict-Transport-Security header is absent. See how to fix → View diagnostics → Fail
- DNSSEC check failed: this domain isn't protected by DNSSEC. See how to fix → View diagnostics → Fail
Transport & Reachability100
- Verified streamable-http transport via a live MCP handshake. View diagnostics → Pass
Schema Quality & AI Usability79
- 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
- AI-judged instruction clarity (good).Pass
- Context-footprint check failed: tool/resource definitions use about 27636 tokens (~146/item across 189 items; 184 tools + 5 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management99
- Stability check failed: schema churn in the 30 days we've observed: 1 tool removals, 0 breaking changes, 0 auth/transport breaks, 41 additions. See how to fix → Fail
Tool Coverage67
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 0% of tool parameters carry a description.Fail
Tool Safety75
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- 0 of 27 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation; "delete_snapshot" implies "delete" and declares no destructiveHint at all, which the MCP spec reads as destructive by default. See how to fix → Fail
- An AI judge read all 186 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
How do I install the BorealHost MCP server?
BorealHost is a hosted endpoint at https://borealhost.ai/mcp/, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
remote · borealhost.ai
claude mcp add --transport http ai-borealhost-mcp 'https://borealhost.ai/mcp/'
{
"mcpServers": {
"ai-borealhost-mcp": {
"url": "https://borealhost.ai/mcp/"
}
}
} {
"servers": {
"ai-borealhost-mcp": {
"type": "http",
"url": "https://borealhost.ai/mcp/"
}
}
} [mcp_servers.ai-borealhost-mcp] url = "https://borealhost.ai/mcp/"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"ai-borealhost-mcp": {
"type": "remote",
"url": "https://borealhost.ai/mcp/",
"enabled": true
}
}
} openclaw mcp add ai-borealhost-mcp --url 'https://borealhost.ai/mcp/' --transport streamable-http
mcp_servers:
ai-borealhost-mcp:
url: "https://borealhost.ai/mcp/" {
"McpServers": {
"ai-borealhost-mcp": {
"Transport": "http",
"Url": "https://borealhost.ai/mcp/"
}
}
} assistant mcp add ai-borealhost-mcp -t streamable-http -u 'https://borealhost.ai/mcp/'
{
"mcpServers": {
"ai-borealhost-mcp": {
"type": "http",
"url": "https://borealhost.ai/mcp/"
}
}
} The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 20 Sept 26 0
- Stability: pass → fail ▼ security
- A breaking change shipped without a version bump: still 1.27.0 ▼ security
- Tool “register” was removed ▼ security
- The server rewrote its instructions, which are the text every model session reads security
- Tool “search_domain” rewrote its description, which is the text the model reads security
- Tool “add_domain_dns” rewrote its description, which is the text the model reads security
- Tool “create_api_key” rewrote its description, which is the text the model reads security
- Tool “decommission” rewrote its description, which is the text the model reads security
- Tool “domain_settings” rewrote its description, which is the text the model reads security
- Tool “execute_query” rewrote its description, which is the text the model reads security
- Tool “install_app” rewrote its description, which is the text the model reads security
- Tool “list_domain_dns” rewrote its description, which is the text the model reads security
- Tool “manage_dns” rewrote its description, which is the text the model reads security
- Tool “register_domain” rewrote its description, which is the text the model reads security
- Tool “rotate_key” rewrote its description, which is the text the model reads security
- Tool “set_api_key” rewrote its description, which is the text the model reads security
- Schema quality: 24346 → 27636 ▼ functional
- Schema quality: excellent → good functional
- New tool “add_mailbox_alias” functional
- New tool “add_port_forward” functional
- New tool “browse_backup” functional
- New tool “clear_mailbox_forwarding” functional
- New tool “configure_email_dns” functional
- New tool “create_mailbox_token” functional
- New tool “delete_email_mailbox” functional
- New tool “disable_email_domain” functional
- New tool “enable_email_domain” functional
- New tool “find_address” functional
- New tool “get_database_recovery” functional
- New tool “get_email_domain” functional
- New tool “get_email_webmail_url” functional
- New tool “get_file_recovery” functional
- New tool “get_mailbox” functional
- New tool “list_email_audit” functional
- New tool “list_email_domains” functional
- New tool “list_mailbox_aliases” functional
- New tool “list_mailboxes” functional
- New tool “list_port_forwards” functional
- New tool “logout_mailbox_sessions” functional
- New tool “recover_backup_database” functional
- New tool “recover_backup_files” functional
- New tool “remove_mailbox_alias” functional
- New tool “remove_port_forward” functional
- New tool “resend_registrant_verification” functional
- New tool “reset_email_mailbox_password” functional
- New tool “restore_mailbox” functional
- New tool “rotate_email_key” functional
- New tool “set_mailbox_aliases” functional
- New tool “update_email_domain” functional
- New tool “update_mailbox” functional
- New tool “create_email_mailbox” functional
- “create_api_key” added an optional parameter “email_domains” cosmetic
- “create_api_key” added an optional parameter “expires_at” cosmetic
- “create_api_key” added an optional parameter “ip_allowlist” cosmetic
- “register_domain” added an optional parameter “quote_only” cosmetic
- “register_domain” added an optional parameter “quote_token” cosmetic
- “register_domain” added an optional parameter “whois_privacy” cosmetic
- “rotate_key” added an optional parameter “grace_minutes” cosmetic
- “add_domain_dns” dropped the optional parameter “ttl” cosmetic
- “manage_dns” dropped the optional parameter “ttl” cosmetic
- 4 Sept 26 0
- Stability: fail → pass ▲ security
- 29 Aug 26 0
- Tool “complete_checkout” rewrote its description, which is the text the model reads security
- Tool “list_plans” rewrote its description, which is the text the model reads security
- Tool “request_api_key” rewrote its description, which is the text the model reads security
- Tool “update_checkout” rewrote its description, which is the text the model reads security
- Tool “claim_api_key” rewrote its description, which is the text the model reads security
- New tool “add_site” functional
- New tool “get_wallet” functional
- New tool “set_site_type” functional
- “update_checkout” added an optional parameter “site_type” cosmetic
- 26 Aug 26 −1
- We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
- 25 Aug 26 +1
- The server rewrote its instructions, which are the text every model session reads security
- Tool “create_checkout” rewrote its description, which is the text the model reads security
- Tool “get_checkout_status” rewrote its description, which is the text the model reads security
- Tool “complete_checkout” rewrote its description, which is the text the model reads security
- Tool “link_domain” rewrote its description, which is the text the model reads security
- New tool “cancel_checkout” functional
- New tool “delete_subdomain” functional
- New tool “list_checkouts” functional
- New tool “set_site_nginx_snippet” functional
- New tool “get_site_nginx_snippet” functional
- 23 Aug 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 89 to 92.
- 11 Aug 26 0
- We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
- 7 Aug 26 0
- The server no longer declares the “experimental” capability functional
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 20 Sept 2026 · Probed https://borealhost.ai/mcp/
TLS valid
Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .
| Subject | Issuer | Valid from | Valid until | Key | Signature | Serial |
|---|---|---|---|---|---|---|
| CN=borealhost.ai | CN=YE1,O=Let's Encrypt,C=US | 3 Sept 2026 | 2 Dec 2026 | ECDSA 256 | ECDSA-SHA384 | 5bc108d01b5e6db29a7f7c52e60fd4f2090 |
| SANs: *.borealhost.ai, borealhost.ai | ||||||
| CN=YE1,O=Let's Encrypt,C=US (CA) | CN=Root YE,O=ISRG,C=US | 3 Sept 2025 | 2 Sept 2028 | ECDSA 384 | ECDSA-SHA384 | 5ddd70dd31f801c85c186a7a04b80afe |
| CN=Root YE,O=ISRG,C=US (CA) | CN=ISRG Root X2,O=Internet Security Research Group,C=US | 13 May 2026 | 2 Sept 2032 | ECDSA 384 | ECDSA-SHA384 | 872165fc34b6e5fba8add5b3705fb53a |
| CN=ISRG Root X2,O=Internet Security Research Group,C=US (CA) | CN=ISRG Root X1,O=Internet Security Research Group,C=US | 13 May 2026 | 2 Sept 2032 | ECDSA 384 | SHA256-RSA | 6c8f1dc727c7117f7baf853ac980f9cd |
Background: What to check on a remote MCP endpoint →
DNSSEC insecure
Validation of borealhost.ai. — Not signed
| Zone | DS | Keys | Algorithms | Outcome |
|---|---|---|---|---|
| . | trust_anchor | 20326, 38696 | 8, 8 | Verified |
| ai. | present | 3799 | 8 | Verified |
| borealhost.ai. | absent | Unsigned (proven) parent-signed NSEC/NSEC3 proves an unsigned delegation |
Authentication No authorisation required
The endpoint answered without asking for a token. Anyone who knows the URL can reach it.
| Result | No authorisation required |
|---|---|
| HTTP status | 200 |
| Header | Value |
|---|---|
| content-security-policy | default-src 'self'; script-src 'self' https://challenges.cloudflare.com 'unsafe-inline' 'unsafe-eval' https://esm.sh https://js.stripe.com https://unpkg.com https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://www.googletagmanager.com https://connect.facebook.net https://static.cloudflareinsights.com https://www.googleadservices.com https://www.google.com https://googleads.g.doubleclick.net; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https://www.facebook.com https://www.googletagmanager.com https://pagead2.googlesyndication.com https://www.google.com https://googleads.g.doubleclick.net https://www.google.ca https://www.google-analytics.com; connect-src 'self' https://esm.sh https://www.google-analytics.com https://analytics.google.com https://www.googletagmanager.com https://googleads.g.doubleclick.net https://td.doubleclick.net https://www.facebook.com https://con |
Background: How OAuth 2.1 works in the 2026 MCP spec →
Transports 2 probes
| Transport | URL | Outcome | Status | Location |
|---|---|---|---|---|
| streamable-http | https://borealhost.ai/mcp/ | Verified | 200 | |
| http (plaintext) | http://borealhost.ai/mcp/ | HTTPS enforced | 301 | https://borealhost.ai/mcp/ |
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
add_cron ~99
Add a cron job to a site. Requires: API key with write scope. Args: slug: Site identifier schedule: Cron schedule (e.g. "*/5 * * * *", "0 2 * * *") command: Command to execute Returns: {"added": true, "result": {...}}
| Name | Type | Req | Description |
|---|---|---|---|
| command | string | yes | – |
| schedule | string | yes | – |
| slug | string | yes | – |
No output schema declared.
No examples provided.
add_domain_dns ~254
Add a DNS record to a domain. Requires: API key with write scope. Args: domain_name: Full domain name (e.g. "example.com") record_type: "A", "AAAA", "CNAME", "MX", "TXT", or "SRV" value: Record value (e.g. "1.2.3.4" for A, "mail.example.com" for MX) subdomain: Subdomain part (e.g. "www", "mail"). Empty for apex domain. priority: MX priority (required for MX records) The DNS provider manages the effective TTL and does not expose a per-record value through this service. Returns: {"success": true, "record": {"id": "...", "type": "A", "subdomain": "www", "value": "1.2.3.4"}} Errors: VALIDATION_ERROR: Missing value, invalid record type NOT_FOUND: Domain not found
| Name | Type | Req | Description |
|---|---|---|---|
| domain_name | string | yes | – |
| priority | integer | – | – |
| record_type | string | yes | – |
| subdomain | string | – | – |
| value | string | yes | – |
No output schema declared.
No examples provided.
add_firewall_rule ~186
Add an IP firewall rule (allow or deny) and reload Nginx. Supports IPv4, IPv6, and CIDR notation. Max 100 rules per site. If a rule already exists for the IP, the action is updated. Requires: API key with write scope. Args: slug: Site identifier ip: IP address or CIDR (e.g. "1.2.3.4", "10.0.0.0/8", "2001:db8::/32") action: "deny" (block) or "allow" (whitelist). Default: "deny" Returns: {"added": true, "ip": "1.2.3.4", "action": "deny"}
| Name | Type | Req | Description |
|---|---|---|---|
| action | string | – | – |
| ip | string | yes | – |
| slug | string | yes | – |
No output schema declared.
No examples provided.
add_mailbox_alias ~50
Add an alias on the same domain, preserving existing aliases.
| Name | Type | Req | Description |
|---|---|---|---|
| actor | string | – | – |
| alias | string | yes | – |
| string | yes | – | |
| reason | string | – | – |
No output schema declared.
No examples provided.
add_port_forward ~501
Publish a container port on the node's public IP (TCP or UDP). This is how inbound UDP reaches a container. There is no other way: the container's own address is private, and the IP allow/deny rules of add_firewall_rule cannot route anything. PORT PRESERVATION MATTERS. Leave external_port at 0 and a port is allocated from 10000-19999 — your service becomes reachable, but on a DIFFERENT number. That is fine for HTTP or ssh and broken for every protocol that carries its own port inside the payload: STUN, TURN, RTP/WebRTC, SIP, WireGuard, QUIC. For those, pass external_port equal to internal_port. A media server needs a contiguous span, not one port — pass internal_port_end. A span is always published unchanged and counts as ONE rule against your limit. Some ports are refused because the host or its neighbours already answer on them: 22, 80, 443, 2222, 9201, 51820, and the bands 9210-9250, 9310-9350 and 20000-20099. The last one is why the "forward UDP 20000-20999 for Janus" recipe printed in most Nextcloud Talk guides will not work here — pick a span above it, e.g. 20100-20599. Requires: API key with write scope. Args: slug: Site identifier internal_port: Port your service listens on inside the container protocol: "tcp" or "udp". Default: "tcp" label: Free-text note shown in the panel external_port: Publish on this exact port; 0 allocates one from the pool internal_port_end: End of a contiguous range (inclusive); 0 means one port Returns: {"id": "...", "external_port": 3478, "internal_port": 3478, "protocol": "udp", "status": "active", "public_address": "203.0.113.5:3478", "port_preserved": true}
| Name | Type | Req | Description |
|---|---|---|---|
| external_port | integer | – | – |
| internal_port | integer | yes | – |
| internal_port_end | integer | – | – |
| label | string | – | – |
| protocol | string | – | – |
| slug | string | yes | – |
No output schema declared.
No examples provided.
add_redirect ~127
Add an HTTP redirect rule to a site. Requires: API key with write scope. Args: slug: Site identifier source_path: Path to redirect, must start with "/" (e.g. "/old-page") target_url: Destination URL redirect_type: 301 (permanent, default) or 302 (temporary) Returns: {"id", "source_path", "target_url", "redirect_type"}
| Name | Type | Req | Description |
|---|---|---|---|
| redirect_type | integer | – | – |
| slug | string | yes | – |
| source_path | string | yes | – |
| target_url | string | yes | – |
No output schema declared.
No examples provided.
add_site ~457
Provision a site into a slot a plan you ALREADY PAY FOR includes. Two different things can be meant by "create a site". Buying one is the checkout flow (create_checkout → update → complete). This is the other: most plans include several sites, and this uses one of them at no extra cost. site_starter includes 5, site_plus 8, site_pro 12, and the agency plans more. `whoami` and `list_sites` show what the account already holds. ⚠ Prefer this over buying a second subscription when a slot is free. Sites under ONE subscription share one CPU pool, one disk quota and one rate-limit bucket — that shared budget is what the plan sells. Two subscriptions split it, so the customer pays twice for capacity they had. Requires: API key with write scope, on the account that owns the plan. Args: slug: Sub-domain for the new site (lowercase, digits, hyphens) subscription_id: The subscription whose slot to use client_name: Display name for the site (optional) domain: Custom domain; defaults to <slug>.borealhost.ai site_type: wordpress (default) | php | php-nodb | static-site. Choose here rather than provisioning WordPress and calling set_site_type afterwards — that installs a WordPress you then abandon in the docroot, and it costs a minute of provisioning. Returns: {"subscription_id": "uuid", "provisioning_job_id": "uuid", "slug": "my-second-site", "domain": "my-second-site.borealhost.ai", "status": "provisioning"} Poll get_site_status(slug) until it reports active. Errors: VALIDATION_ERROR: Plan includes a single site, slug taken, or every slot is in use (the message reports used/total) NOT_FOUND: Unknown subscription, or it belongs to another account
| Name | Type | Req | Description |
|---|---|---|---|
| client_name | string | – | – |
| domain | string | – | – |
| site_type | string | – | – |
| slug | string | yes | – |
| subscription_id | string | yes | – |
No output schema declared.
No examples provided.
add_ssh_key ~170
Inject your SSH public key into a site's container for direct SSH access. The key is appended to /home/admin/.ssh/authorized_keys. Only available for VPS/dedicated plans. Requires: API key with write scope. Args: slug: Site identifier public_key: SSH public key string. Supported types: ssh-ed25519, ssh-rsa, ecdsa-sha2-nistp256/384/521 Returns: {"success": true, "message": "SSH key added", "ssh_command": "ssh admin@184.107.x.x"} Errors: VALIDATION_ERROR: Invalid or unsupported key format FORBIDDEN: Plan does not support SSH
| Name | Type | Req | Description |
|---|---|---|---|
| public_key | string | yes | – |
| slug | string | yes | – |
No output schema declared.
No examples provided.
add_subdomain ~257
Create and route a subdomain of a site-linked domain. Creates the DNS A record (if absent) pointing at the site's server, then configures the nginx vhost and SSL certificate on that server. The domain must already be linked to a site (see link_domain). Idempotent: if the DNS record already exists and points at the site's server, the nginx/SSL steps are (re)applied — safe to re-call, e.g. to retry SSL after DNS propagation. May take up to 3 minutes when a certificate is issued. Requires: API key with write scope. Args: domain_name: Registrable domain linked to a site (e.g. "example.com") subdomain: Subdomain label only, no dots (e.g. "blog") Returns: {"fqdn": "blog.example.com", "domain": "example.com", "site": "my-site", "message": "..."} Errors: NOT_FOUND: Domain not found VALIDATION_ERROR: Domain not linked to a site, invalid label, or an existing record points at a different server
| Name | Type | Req | Description |
|---|---|---|---|
| domain_name | string | yes | – |
| subdomain | string | yes | – |
No output schema declared.
No examples provided.
adopt_compute_instance ~252
Turn an instance you are ALREADY running into a persistent volume. Use this when you launched something, set it up, and then decided you want to keep it. Nothing reboots and no data moves — the machine you have becomes the volume, and you can detach it afterwards to stop paying for compute while keeping the machine. Beats creating a volume and rebuilding. Only instances launched with an ssh_public_key qualify. One launched with your own user_data carries only your key, and a key cannot be added to a machine we cannot already log into — check "managed_ssh" on the instance. Requires: API key with write scope, and an active subscription. Args: instance_id: A running lsw.* instance you own name: Label for the volume (defaults to the instance name) Returns: Volume dict with state "attached", wrapping that same instance. No snapshot exists yet — the first one is taken on detach or snapshot. Errors: CONFLICT: Not running, already a volume, BorealHost Metal, or launched without BorealHost management access
| Name | Type | Req | Description |
|---|---|---|---|
| instance_id | string | yes | – |
| name | string | – | – |
No output schema declared.
No examples provided.
attach_compute_volume ~270
Restore a detached volume onto a fresh instance — optionally a new type. Pass a different instance_type to move the same machine to different hardware: this is the closest thing to changing instance type that the provider allows, since it has no resize API at all. The restore runs at first boot and the machine reboots into itself, so the instance answers SSH BEFORE it is ready. Poll get_compute_volume and give it a few minutes (measured: ~6 min for a 10 GB GPU machine end to end). The machine keeps its SSH host keys, so your client will not warn about a changed host identity. Requires: API key with write scope. Args: volume_id: A volume in state "detached" ssh_public_key: Required — installed via cloud-init at boot instance_type: Defaults to the type it last ran on root_disk_size: GB. May grow, never shrink below the volume's size. Returns: Volume dict with state "attached" and a new instance. Errors: CONFLICT: Volume is not detached, or has no snapshot yet
| Name | Type | Req | Description |
|---|---|---|---|
| instance_type | string | – | – |
| root_disk_size | integer | – | – |
| ssh_public_key | string | yes | – |
| volume_id | string | yes | – |
No output schema declared.
No examples provided.
browse_backup ~187
List one bounded page of immediate children in a backup directory. This returns names and metadata only, never file contents. Use ``next_cursor`` from the response as ``cursor`` to request the next page. Requires: API key with read scope. Args: slug: Site identifier backup_id: UUID of a completed backup path: Absolute directory path as it existed in the backup cursor: Resume after this entry name (optional) limit: Maximum entries, from 1 through 100 Errors: SNAPSHOT_SCOPE_CHANGED: The path is allowed by today's schedule but was not included when this backup was created; choose an included path or a newer backup.
| Name | Type | Req | Description |
|---|---|---|---|
| backup_id | string | yes | – |
| cursor | string | – | – |
| limit | integer | – | – |
| path | string | yes | – |
| slug | string | yes | – |
No output schema declared.
No examples provided.
cache_flush ~50
Flush all caches (Redis + WP object cache). Requires: API key with write scope. Args: slug: Site identifier Returns: {"flushed": true}
| Name | Type | Req | Description |
|---|---|---|---|
| slug | string | yes | – |
No output schema declared.
No examples provided.
cache_status ~78
Get cache status (Redis, WP object cache, hit rates). Requires: API key with read scope. Args: slug: Site identifier Returns: {"redis_running": true, "object_cache_enabled": true, "hit_rate": 0.95, "memory_used_mb": 12}
| Name | Type | Req | Description |
|---|---|---|---|
| slug | string | yes | – |
No output schema declared.
No examples provided.
cache_toggle ~66
Enable or disable the WordPress object cache. Requires: API key with write scope. Args: slug: Site identifier enable: true to enable, false to disable Returns: {"enabled": true}
| Name | Type | Req | Description |
|---|---|---|---|
| enable | boolean | yes | – |
| slug | string | yes | – |
No output schema declared.
No examples provided.
cancel_checkout ~120
Abandon an unpaid checkout and expire its Stripe payment link. Use this to clean up abandoned attempts rather than leaving them to sit. A completed checkout is never cancelled here — that would be a refund, and it is refused. Args: checkout_id: Checkout session ID Returns: The checkout, with status "canceled". Errors: VALIDATION_ERROR: Checkout was already paid — cancel the subscription from the panel instead FORBIDDEN: Missing checkout_secret and no owning API key
| Name | Type | Req | Description |
|---|---|---|---|
| checkout_id | string | yes | – |
No output schema declared.
No examples provided.
cancel_scheduled_snapshot ~87
Cancel a scheduled snapshot. Requires: API key with write scope. Args: slug: Site identifier schedule_id: UUID of the scheduled snapshot to cancel Returns: {"success": true, "message": "Scheduled snapshot cancelled"} Errors: NOT_FOUND: Schedule not found or already executed
| Name | Type | Req | Description |
|---|---|---|---|
| schedule_id | string | yes | – |
| slug | string | yes | – |
No output schema declared.
No examples provided.
claim_api_key ~170
Claim an API key using a claim token from the container. After calling request_api_key(), read the claim token from the path that call returned in `claim_path`, on that site's container, and pass it here. The token is single-use — once claimed, it cannot be used again. The API key is automatically activated for this MCP session. Args: claim_token: The claim token string read from the container file Returns: {"api_key": "bh_...", "key_prefix": "bh_...", "site_slug": "my-site", "scopes": ["read", "write"], "message": "API key created and activated..."} Errors: VALIDATION_ERROR: Invalid, expired, or already-claimed token
| Name | Type | Req | Description |
|---|---|---|---|
| claim_token | string | yes | – |
No output schema declared.
No examples provided.
clear_mailbox_forwarding ~56
Clear forwarding; when Sieve exists, requires explicit clear_all_filters=true.
| Name | Type | Req | Description |
|---|---|---|---|
| actor | string | – | – |
| clear_all_filters | boolean | – | – |
| string | yes | – | |
| reason | string | – | – |
No output schema declared.
No examples provided.
cloudflare_proxy_status ~112
Get Cloudflare proxy (CDN) status for a site. Shows whether traffic is routed through Cloudflare's CDN (orange cloud) or goes direct to origin (grey cloud / DNS-only). Requires: API key with read scope. Args: slug: Site identifier Returns: {"domain": "my-site.borealhost.ai", "has_record": true, "proxied": true, "ip": "1.2.3.4"}
| Name | Type | Req | Description |
|---|---|---|---|
| slug | string | yes | – |
No output schema declared.
No examples provided.
cloudflare_purge_cache ~137
Purge Cloudflare CDN cache for a site. Without urls: purges all cached content for the site's subdomain. With urls: purges only the specified URLs (max 30 per call). Requires: API key with write scope. Args: slug: Site identifier urls: Optional list of specific URLs to purge (e.g. ["https://my-site.borealhost.ai/style.css"]) Returns: {"purged": true, "scope": "host", "domain": "my-site.borealhost.ai"}
| Name | Type | Req | Description |
|---|---|---|---|
| slug | string | yes | – |
| urls | array | – | – |
No output schema declared.
No examples provided.
cloudflare_set_proxy ~141
Enable or disable Cloudflare CDN proxy for a site. When enabled (orange cloud): traffic goes through Cloudflare's CDN, gets caching, DDoS protection, and SSL termination at the edge. When disabled (grey cloud): traffic goes directly to origin server. Requires: API key with write scope. Args: slug: Site identifier proxied: true to enable CDN proxy, false to disable Returns: {"domain": "my-site.borealhost.ai", "proxied": true, "ip": "1.2.3.4"}
| Name | Type | Req | Description |
|---|---|---|---|
| proxied | boolean | yes | – |
| slug | string | yes | – |
No output schema declared.
No examples provided.
complete_checkout ~562
Complete checkout with payment and start site provisioning. The checkout must be in "ready" status. Two payment methods: - "stripe_checkout" (default): Returns a short, chat-safe payment URL. **Present `payment_url` to the human — NOT `stripe_checkout_url`.** The raw Stripe URL has a required `#fragment` that chat UIs routinely strip when rendering markdown links, which causes Stripe to show "page not found". `payment_url` is a short BorealHost redirect that preserves the fragment via HTTP 302. After paying, the human lands on a confirmation page (`confirmation_url`) — not on raw JSON. Then poll get_checkout_status() until status becomes "completed". The API key appears in the first poll after payment (shown once, then cleared). Payment provisions the site; nothing else has to be called to create it. - "stripe_payment_method": Charges a Stripe PaymentMethod directly. Requires payment_method_id. On success, returns the API key immediately. Args: checkout_id: Checkout session ID payment_method: "stripe_checkout" (returns a payment_url for a human), "stripe_payment_method" (card on file), or "wallet" — pay from the account's prepaid balance against THIS key's allowance. Check get_wallet() first: `spendable_cents` is what you may actually spend, and a wallet payment is refused for plans that order dedicated hardware, which are authorised against a verified card payment instead. payment_method_id: Stripe PaymentMethod ID (pm_...). Required only for "stripe_payment_method". Returns (stripe_checkout): {"id": "uuid", "status": "awaiting_payment", "payment_url": "https://borealhost.ai/pay/<id>/?s=<secret>", "confirmation_url": "https://borealhost.ai/pay/<id>/confirmation/?s=...", "stripe_checkout_url": "https://checkout.stripe.com/c/pay/...", "message": "Present payment_url to the human..."} Returns (stripe_payment_method): {"id": "uuid", "…
| Name | Type | Req | Description |
|---|---|---|---|
| checkout_id | string | yes | – |
| payment_method | string | – | – |
| payment_method_id | string | – | – |
No output schema declared.
No examples provided.
configure_email_dns ~60
Configure OpenSRS DKIM and merge email DNS, preserving other senders and subdomains.
| Name | Type | Req | Description |
|---|---|---|---|
| actor | string | – | – |
| dmarc_reporting_address | string | – | – |
| domain | string | yes | – |
| reason | string | – | – |
No output schema declared.
No examples provided.
container_action ~141
Start, stop, or restart a site's container. Only for plans with a dedicated container (VPS / split-VPS / dedicated). Shared-hosting sites share a container and cannot restart it. The response reports the observed container state after the action. Requires: API key with write scope. Args: slug: Site identifier action: "start", "stop", or "restart" Returns: {"site", "action", "status": "running|stopped", "observed": true} Errors: VALIDATION_ERROR: Shared-hosting plan or unknown action
| Name | Type | Req | Description |
|---|---|---|---|
| action | string | yes | – |
| slug | string | yes | – |
No output schema declared.
No examples provided.
create_alert_rule ~260
Create an alert rule to monitor CPU, memory, or disk usage. When the metric crosses the threshold, a notification is sent via email and/or webhook. Max 10 rules per site. Requires: API key with write scope. Args: slug: Site identifier metric: "cpu", "memory", or "disk" (percentage-based) threshold: Threshold value 0-100 (e.g. 90 for 90%) operator: "gt" (greater than) or "lt" (less than). Default: "gt" severity: "warning" or "critical". Default: "warning" cooldown_minutes: Min minutes between repeated alerts. Default: 30 notify_email: Send email notification. Default: true notify_webhook: Optional webhook URL for POST notifications Returns: {"id": "uuid", "metric": "disk", "threshold": 90, ...}
| Name | Type | Req | Description |
|---|---|---|---|
| cooldown_minutes | integer | – | – |
| metric | string | yes | – |
| notify_email | boolean | – | – |
| notify_webhook | string | – | – |
| operator | string | – | – |
| severity | string | – | – |
| slug | string | yes | – |
| threshold | number | yes | – |
No output schema declared.
No examples provided.
create_api_key ~305
Create a new API key with specified scopes. Cannot create keys with higher scopes than the current key. Site-scoped keys restrict access to a single site. email_domains restricts the key to email tools on the named domains; use email:read, email:write and optionally email:signon scopes. expires_at is an ISO timestamp; ip_allowlist accepts IP addresses and CIDR networks. Requires: API key with write scope. Args: name: Human-readable name for the key (1-100 chars) scopes: Comma-separated scopes. Options: "read", "read,write", "read,write,admin". Default: "read" site_slug: Optional — restrict the key to a single site. Omit for account-wide access. Returns: {"api_key": "bh_...", "key_id": "uuid", "prefix": "bh_...", "name": "My Key", "scopes": ["read", "write"], "message": "Store this API key securely — it will not be shown again."} Errors: VALIDATION_ERROR: Invalid name, scopes, or max 25 active keys FORBIDDEN: Cannot create keys with higher scopes than current key
| Name | Type | Req | Description |
|---|---|---|---|
| email_domains | – | – | – |
| expires_at | – | – | – |
| ip_allowlist | – | – | – |
| name | string | yes | – |
| scopes | string | – | – |
| site_slug | string | – | – |
No output schema declared.
No examples provided.
create_b2_snapshot ~184
Create a B2 cloud-backed snapshot (zero local disk, async). Streams container data directly to Backblaze B2 via restic. No local disk impact — billed separately at cost+5%. Runs in background — returns immediately with status "creating". Poll list_snapshots() to check when status becomes "completed". Only available for VPS plans. Requires: API key with write scope. Args: slug: Site identifier description: Optional description (max 200 chars) Returns: {"id": "uuid", "name": "...", "status": "creating", "storage_type": "b2", "message": "B2 cloud snapshot started. Poll list_snapshots()..."} Errors: VALIDATION_ERROR: Not a VPS plan or max snapshots reached
| Name | Type | Req | Description |
|---|---|---|---|
| description | string | – | – |
| slug | string | yes | – |
No output schema declared.
No examples provided.
create_backup ~88
Create a manual backup (runs asynchronously). The backup starts in the background. Poll list_backups() to check status. Requires: API key with write scope. Args: slug: Site identifier Returns: {"id": "uuid", "status": "pending", "message": "Backup started. Poll list_backups() to check status."}
| Name | Type | Req | Description |
|---|---|---|---|
| slug | string | yes | – |
No output schema declared.
No examples provided.
create_checkout ~298
Start a new checkout session to purchase a hosting plan. No authentication needed. After creating, call update_checkout to set buyer info, then complete_checkout to pay. The response carries a `checkout_secret`, returned ONCE, that every later step of this checkout requires. It is held in memory for this MCP session and sent automatically — but it is gone if the server restarts. If a session key is set, the checkout is owned by that account and the API key authorizes the later steps on its own, which is the durable path. Args: sku: Plan SKU in format bh_{plan_slug}_{monthly|annual}. Examples: "bh_site_starter_monthly", "bh_site_pro_annual", "bh_site_managed_monthly", "bh_site_business_annual". Call list_plans() to discover all available plan slugs. Returns: {"id": "uuid", "sku": "bh_site_starter_monthly", "plan_slug": "site_starter", "billing_period": "monthly", "status": "not_ready", "buyer_email": "", "requested_slug": "", "created_at": "iso8601", "checkout_secret": "base64-token"} Errors: VALIDATION_ERROR: Invalid SKU format or unknown plan RATE_LIMITED: Max 10 checkouts per IP per hour
| Name | Type | Req | Description |
|---|---|---|---|
| sku | string | yes | – |
No output schema declared.
No examples provided.
create_compute_volume ~342
Create a persistent machine and boot its first instance. Start here, then set the machine up however you like (install packages, drivers, models). Everything you do becomes part of the volume the first time you detach or snapshot it. While attached you pay hourly compute; while detached you pay only for stored bytes (CA$0.03/GB/month). Stopping an instance does NOT save money on this provider — detaching is what stops the compute charge. Requires: API key with write scope, and an active subscription. Args: name: Label for the volume, e.g. "trainer" image_id: From list_compute_images, e.g. "UBUNTU_24_04_64BIT". Cannot change later — restores must land on the same OS. instance_type: From list_compute_types, e.g. "lsw.g6.xlarge". CAN change on every later attach. ssh_public_key: Required. Volume instances always boot via cloud-init, so this is the only way in. root_disk_size: GB. Defaults to the type's minimum (or 25). Returns: Volume dict with state "attached". Poll get_compute_volume until instance.state is "running" (~1-3 min). Errors: PAYMENT_REQUIRED: No active subscription LIMIT_EXCEEDED: Volume cap reached NOT_AVAILABLE: Volumes not enabled on this deployment
| Name | Type | Req | Description |
|---|---|---|---|
| image_id | string | yes | – |
| instance_type | string | yes | – |
| name | string | yes | – |
| root_disk_size | integer | – | – |
| ssh_public_key | string | yes | – |
No output schema declared.
No examples provided.
create_directory ~107
Create a directory in a site's container. Creates parent directories if they don't exist. Requires: API key with write scope. Args: slug: Site identifier path: Relative path of the directory to create Returns: {"success": true, "path": "uploads/2024", "message": "Directory created"} Errors: NOT_FOUND: Unknown slug FORBIDDEN: Protected system path
| Name | Type | Req | Description |
|---|---|---|---|
| path | string | yes | – |
| slug | string | yes | – |
No output schema declared.
No examples provided.
create_email_mailbox ~104
Create a domain-addressed billable mailbox. Password returned once; retries omit it.
| Name | Type | Req | Description |
|---|---|---|---|
| actor | string | – | – |
| display_name | string | – | – |
| domain | string | yes | – |
| idempotency_key | string | – | – |
| label | string | – | – |
| local_part | string | yes | – |
| password | string | – | – |
| quota_gb | integer | – | – |
| reason | string | – | – |
| smtp_sent_limit | – | – | – |
No output schema declared.
No examples provided.
create_ftp_account ~182
Create an SFTP account on a site. The account is chrooted to /var/www and lands in home_dir. Password must be at least 8 characters. Username must be lowercase alphanumeric. Requires: API key with write scope. Args: slug: Site identifier username: SFTP username (lowercase, max 32 chars) password: Password (min 8 chars) home_dir: Landing directory inside /var/www. Leave empty to land at /var/www itself, which lists every site directory. Returns: {"success": true, "username": "sftpuser", "home_dir": "/wordpress", "protocol": "sftp"}
| Name | Type | Req | Description |
|---|---|---|---|
| home_dir | string | – | – |
| password | string | yes | – |
| slug | string | yes | – |
| username | string | yes | – |
No output schema declared.
No examples provided.
create_mailbox ~132
Create a mailbox on the site's email domain. Password is generated when omitted and returned ONCE — store it. Each mailbox adds to the subscription's email billing. Requires: API key with write scope. Args: slug: Site identifier local_part: Part before the @ (e.g. "info") display_name: Optional display name password: Optional password (generated if empty) Returns: {"email", "password", "message"}
| Name | Type | Req | Description |
|---|---|---|---|
| display_name | string | – | – |
| local_part | string | yes | – |
| password | string | – | – |
| slug | string | yes | – |
No output schema declared.
No examples provided.
create_mailbox_token ~81
Issue a temporary mail-services token with no OMA access. Requires email:signon. Use 60, 120, ... 1440 minutes. OpenSRS rejects fractional hours; no rounding up.
| Name | Type | Req | Description |
|---|---|---|---|
| actor | string | – | – |
| duration_minutes | integer | – | – |
| string | yes | – | |
| reason | string | – | – |
No output schema declared.
No examples provided.
create_snapshot ~182
Create a local container snapshot (async). Runs in background — returns immediately with status "creating". Poll list_snapshots() to check when status becomes "completed" or "failed". Available for VPS, dedicated, and cloud plans (any plan with max_snapshots > 0). Local snapshots are stored on the host disk and count against disk quota. Requires: API key with write scope. Args: slug: Site identifier description: Optional description (max 200 chars) Returns: {"id": "uuid", "name": "snap-...", "status": "creating", "storage_type": "local", "message": "Snapshot started. Poll list_snapshots() to check status."} Errors: VALIDATION_ERROR: Max snapshots reached or insufficient disk quota
| Name | Type | Req | Description |
|---|---|---|---|
| description | string | – | – |
| slug | string | yes | – |
No output schema declared.
No examples provided.
create_support_ticket ~163
Open a support ticket with the BorealHost team. Use this to escalate platform-side problems you cannot fix with the available tools (billing issues, infrastructure faults, API bugs). A human answers every ticket — poll get_support_ticket for updates. Requires: API key with write scope. Args: subject: Short summary (max 200 chars) message: Full description (max 20000 chars) category: Optional (e.g. "technical", "billing") site: Optional site slug the ticket concerns Returns: {"id", "subject", "status", "message": "Ticket created..."}
| Name | Type | Req | Description |
|---|---|---|---|
| category | string | – | – |
| message | string | yes | – |
| site | string | – | – |
| subject | string | yes | – |
No output schema declared.
No examples provided.
create_webhook ~131
Register a webhook endpoint for platform events. Events (backup failures, security notices, hosting incidents, billing) are POSTed as JSON, signed with X-BH-Signature (HMAC-SHA256 of the raw body). The signing secret is returned ONCE. Categories: billing, security, hosting, decommission, general — empty list means all. Endpoints auto-disable after 20 consecutive failures. Requires: API key with write scope. Returns: {"id", "url", "events", "secret", "message"}
| Name | Type | Req | Description |
|---|---|---|---|
| events | array | – | – |
| url | string | yes | – |
No output schema declared.
No examples provided.
database_search_replace ~154
Search and replace in WordPress database (e.g. URL migration). Handles serialized data safely. Use dry_run=true first to preview changes. Requires: API key with write scope. Args: slug: Site identifier old: String to search for (e.g. "http://old-domain.com") new: Replacement string (e.g. "https://new-domain.com") dry_run: Preview only without making changes (default: true) Returns: {"replacements": 42, "tables_affected": 5, "dry_run": true}
| Name | Type | Req | Description |
|---|---|---|---|
| dry_run | boolean | – | – |
| new | string | yes | – |
| old | string | yes | – |
| slug | string | yes | – |
No output schema declared.
No examples provided.
decommission ~141
Delete a site and schedule resource cleanup (7-day grace period). WARNING: This is destructive. The site will be inaccessible immediately. After the grace period, its active service data is deleted. A final backup remains recoverable for 30 days; immutable copies may remain until their retention locks expire. Best practice: create a snapshot before decommissioning. Requires: API key with admin scope. Args: slug: Site identifier Returns: {"success": true, "message": "Site scheduled for deletion", "grace_period_days": 7} Errors: NOT_FOUND: Unknown slug
| Name | Type | Req | Description |
|---|---|---|---|
| slug | string | yes | – |
No output schema declared.
No examples provided.
delete_account ~77
Permanently anonymize the account. Cancels subscriptions, deactivates keys. WARNING: This is irreversible. The account will be soft-deleted and all personal data anonymized. All sites will be decommissioned. Requires: API key with admin scope. Returns: {"success": true, "message": "Account anonymized"}
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
delete_alert_rule ~71
Delete an alert rule. Requires: API key with write scope. Args: slug: Site identifier rule_id: UUID of the alert rule to delete Returns: {"deleted": true, "id": "uuid"}
| Name | Type | Req | Description |
|---|---|---|---|
| rule_id | string | yes | – |
| slug | string | yes | – |
No output schema declared.
No examples provided.
delete_backup ~62
Permanently delete a single backup (metadata + stored snapshot). Irreversible. Requires: API key with admin scope. Returns: {"site", "backup_id", "deleted": true}
| Name | Type | Req | Description |
|---|---|---|---|
| backup_id | string | yes | – |
| slug | string | yes | – |
No output schema declared.
No examples provided.
delete_compute_volume ~107
Permanently delete a volume and everything stored in it. Irreversible: the instance is released AND the stored data is purged from object storage, so billing genuinely stops. Refuses while an instance is live unless force=True, so a running machine's only copy cannot be destroyed by reflex. Requires: API key with admin scope. Returns: {"id", "state": "deleted"}
| Name | Type | Req | Description |
|---|---|---|---|
| force | boolean | – | – |
| volume_id | string | yes | – |
No output schema declared.
No examples provided.
delete_cron ~78
Delete a cron job by line number. Get line numbers from list_cron(). Requires: API key with write scope. Args: slug: Site identifier line_number: Line number of the cron entry to delete Returns: {"deleted": true}
| Name | Type | Req | Description |
|---|---|---|---|
| line_number | integer | yes | – |
| slug | string | yes | – |
No output schema declared.
No examples provided.
delete_domain_dns ~103
Delete a DNS record from a domain. Requires: API key with write scope. Args: domain_name: Full domain name (e.g. "example.com") record_id: ID of the DNS record to delete (from list_domain_dns) Returns: {"success": true, "message": "DNS record deleted"} Errors: NOT_FOUND: Domain or record not found
| Name | Type | Req | Description |
|---|---|---|---|
| domain_name | string | yes | – |
| record_id | string | yes | – |
No output schema declared.
No examples provided.
delete_email_mailbox ~56
Soft-delete a mailbox. confirm must equal email. Provider recovery window: 30 days.
| Name | Type | Req | Description |
|---|---|---|---|
| actor | string | – | – |
| confirm | string | yes | – |
| string | yes | – | |
| reason | string | – | – |
No output schema declared.
No examples provided.
delete_file ~116
Delete a file or directory from a site's container. Directories are deleted recursively. Protected system paths (e.g. /etc, /usr) cannot be deleted. Requires: API key with write scope. Args: slug: Site identifier path: Relative path to delete Returns: {"success": true, "path": "...", "message": "Deleted"} Errors: NOT_FOUND: Path doesn't exist FORBIDDEN: Protected system path
| Name | Type | Req | Description |
|---|---|---|---|
| path | string | yes | – |
| slug | string | yes | – |
No output schema declared.
No examples provided.
delete_mailbox ~51
Delete a mailbox (its mail is destroyed). Requires: API key with write scope. Returns: {"email", "deleted": true}
| Name | Type | Req | Description |
|---|---|---|---|
| string | yes | – | |
| slug | string | yes | – |
No output schema declared.
No examples provided.
What is the BorealHost MCP server?
BorealHost is an MCP server listed in the public MCP registry as ai.borealhost/mcp. Agent-native web hosting, deploy sites, manage DNS, register domains, scale infrastructure. This page covers its hosted endpoint (https://borealhost.ai/mcp/).
Is the BorealHost MCP server safe to use?
BorealHost scores 75 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the BorealHost MCP server expose?
BorealHost exposes 184 tools: set_api_key, whoami, request_api_key, claim_api_key, list_plans, and 179 more. Their descriptions and schemas cost roughly 25,764 tokens of context every time the server is loaded.
Does the BorealHost MCP server require authentication?
No. We connected to BorealHost without credentials and it answered, so anything it exposes is reachable by anyone who knows the address.
Is the BorealHost MCP server still maintained?
BorealHost is still listed as active in the MCP registry. We last reached this channel on 20 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.