Koskamo

Apexly MCP

A hosted MCP server that allows AI coding agents to manage SaaS custom domains, including creating, verifying, diagnosing, and deleting domains via API tools.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

Apexly MCP logo, by ApexlyVendor evidenceStreamable HTTPNo sign-inEndpoint checked 2026-11-01Operated by Apexly
You need:Auth: your normal Apexly API key, sent as Authorization: Bearer sk_live_… or sk_test_…Create one under Keys in the dashboard
MCP endpoint (Streamable HTTP)
https://mcp.apexly.dev/mcp
Vendor documentation

What you can do with it

  • Add a customer's custom domain hostname
  • Check domain status and DNS verification
  • Diagnose domain configuration issues
  • Remove a custom domain

Source and maintenance

Vendor evidenceRegistry 1.0.0

Protocol and capabilities

Server
apexly 1.0.0
MCP protocol
2025-06-18
Tools
8 advertised
Resources
Not advertised
Resource templates
Not advertised
Prompts
Not advertised
Server-advertised capabilities
{
  "tools": {
    "listChanged": true
  }
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

Apexly gives your SaaS customers custom domains with automatic TLS. Typical flow: create_domain with the customer's hostname → give the customer the DNS record (get_dns_instructions) or the connect page link (get_connect_url) → poll get_domain until status is active. When it is stuck, diagnose_domain explains why and what the customer must change. Test keys (sk_test_…) create sandbox domains that go active on their own.

Tools

8 advertised

create_domain — Add a custom domain
Advertised by the server during the last successful anonymous check.

Add a customer's hostname (e.g. careers.acme.com or acme.com) to the app this API key belongs to. Idempotent: adding a hostname the app already has returns the existing domain. The domain starts in pending_dns; the customer must then add the DNS record in status_explained / get_dns_instructions, or open the connect_url to be guided through it. Apexly checks DNS every 15 seconds and issues the TLS certificate itself. With a test key (sk_test_…) the domain is a sandbox one that goes active by itself in about 30 seconds. Never invent a hostname: ask the user which one.

create_domain input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "hostname"
  ],
  "properties": {
    "origin": {
      "type": "string",
      "maxLength": 2048,
      "description": "Per-domain origin override (paid plans); omit to use the app origin"
    },
    "hostname": {
      "type": "string",
      "maxLength": 1024,
      "description": "The customer's hostname, no scheme or path, e.g. careers.acme.com"
    },
    "metadata": {
      "type": "object",
      "description": "Any JSON object up to 4 KB, e.g. {\"customer\": \"Acme\", \"tenant_id\": \"42\"}",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "apex_redirect": {
      "enum": [
        "none",
        "www"
      ],
      "type": "string",
      "description": "Apex domains only: also serve www.<apex> and redirect it"
    }
  }
}
create_domain annotations
{
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_domain — Get a domain
Advertised by the server during the last successful anonymous check.
Advertised read-only

Current state of one domain: status (pending_dns → verifying → issuing → active; or dns_broken, cert_failed, held, expired), the DNS record the customer must add, the connect_url and the certificate. status_explained says in one sentence why it is in that status and what to do next. Use it to poll after create_domain or verify_domain.

get_domain input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "maxLength": 64,
      "minLength": 1,
      "description": "The domain id (dom_…), from create_domain or list_domains"
    }
  }
}
get_domain annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
list_domains — List domains
Advertised by the server during the last successful anonymous check.
Advertised read-only

The app's domains, newest first, one page at a time. Pass next_cursor back as cursor for the next page (null means there are no more). Filter by status or by hostname prefix to find a domain id.

list_domains input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "limit": {
      "type": "integer",
      "default": 20,
      "maximum": 100,
      "minimum": 1
    },
    "cursor": {
      "type": "string",
      "maxLength": 200,
      "description": "next_cursor of the previous page"
    },
    "status": {
      "enum": [
        "pending_dns",
        "verifying",
        "issuing",
        "active",
        "dns_broken",
        "cert_failed",
        "expired",
        "held",
        "deleted"
      ],
      "type": "string"
    },
    "hostname": {
      "type": "string",
      "maxLength": 253,
      "description": "Hostname prefix, e.g. careers."
    }
  }
}
list_domains annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
verify_domain — Check a domain now
Advertised by the server during the last successful anonymous check.

Queue a DNS check right away instead of waiting for the next scheduled one; use it after the customer says they added the record. On cert_failed it retries the certificate. At most one per 15 seconds per domain. The check runs in the background: call get_domain a few seconds later for the result.

verify_domain input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "maxLength": 64,
      "minLength": 1,
      "description": "The domain id (dom_…), from create_domain or list_domains"
    }
  }
}
verify_domain annotations
{
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": false,
  "destructiveHint": false
}
get_connect_url — Get the connect page link
Advertised by the server during the last successful anonymous check.
Advertised read-only

The link to send the customer (the domain owner): a page branded with the app that detects their DNS provider, shows the exact record with copy buttons and tells them when the domain is live. Prefer it when the customer is not technical. It is safe to share with the customer, not publicly.

get_connect_url input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "maxLength": 64,
      "minLength": 1,
      "description": "The domain id (dom_…), from create_domain or list_domains"
    }
  }
}
get_connect_url annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_dns_instructions — DNS instructions for the customer
Advertised by the server during the last successful anonymous check.
Advertised read-only

The exact DNS record(s) the customer must add for this domain, plus step-by-step instructions for their DNS provider (detected from the domain's nameservers: GoDaddy, Cloudflare, Namecheap, Route 53 and ~40 more; generic steps otherwise). Record names are relative to the registrable domain ("careers" in acme.com, "@" for the apex).

get_dns_instructions input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "maxLength": 64,
      "minLength": 1,
      "description": "The domain id (dom_…), from create_domain or list_domains"
    }
  }
}
get_dns_instructions annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
diagnose_domain — Diagnose a domain
Advertised by the server during the last successful anonymous check.
Advertised read-only

Why a domain is not live and what to change (the domain doctor, same as GET /v1/domains/{id}/diagnose): runs every check live (the record at 1.1.1.1, 8.8.8.8 and the domain's own nameservers, other A and stale AAAA records, the Cloudflare proxy, CAA, the certificate, the origin, the www pair). Each check is pass, fail, warn or skip with what we saw (detail) and what to change (fix); blocking_check_id is the one to fix first. status_explained says why the domain is in its status. Use it when a domain stays in pending_dns, dns_broken or cert_failed, then relay the fix to the customer. Results are reused for 20 seconds.

diagnose_domain input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "maxLength": 64,
      "minLength": 1,
      "description": "The domain id (dom_…), from create_domain or list_domains"
    }
  }
}
diagnose_domain annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
delete_domain — Delete a domain
Advertised by the server during the last successful anonymous check.
Advertised destructive

Remove a domain: it stops being served within 5 seconds and its certificate is dropped. Irreversible (adding the hostname again starts over with a new record). Only call it after the user explicitly confirmed deleting this hostname, and pass confirm: true.

delete_domain input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "maxLength": 64,
      "minLength": 1,
      "description": "The domain id (dom_…), from create_domain or list_domains"
    },
    "confirm": {
      "type": "boolean",
      "description": "Must be true: the user confirmed deleting this domain"
    }
  }
}
delete_domain annotations
{
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": false,
  "destructiveHint": true
}

Prompts

Not advertised

No prompt definitions available.

Resources

Not advertised

No resource definitions available.

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
2034 ms
95th percentile latency
2034 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 2034 ms · metadata changed · 8 tool(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http apexly-mcp https://mcp.apexly.dev/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add apexly-mcp --url https://mcp.apexly.dev/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable apexly-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "apexly-mcp": {
      "url": "https://mcp.apexly.dev/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "apexly-mcp": {
      "type": "streamableHttp",
      "url": "https://mcp.apexly.dev/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start apexly-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "apexly-mcp": {
      "type": "http",
      "url": "https://mcp.apexly.dev/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http apexly-mcp https://mcp.apexly.dev/mcp

Claude Desktop

Merge this into claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\), then restart Claude Desktop.
Claude Desktop configuration
{
  "mcpServers": {
    "apexly-mcp": {
      "url": "https://mcp.apexly.dev/mcp"
    }
  }
}

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "apexly-mcp": {
      "serverUrl": "https://mcp.apexly.dev/mcp"
    }
  }
}

Let your agent find its tools

Find servers like Apexly MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.

Do you run Apexly MCP?

Prove ownership with a DNS record, a well-known file, or your Official MCP Registry entry, and your edits publish immediately. Proofs are re-checked weekly; admins can still hide or remove a listing.

Claim this listing