I look after a fleet of domains β client sites, marketing properties, a couple of internal tools. For most of my career the monitoring loop was: open dashboard, scan a grid of expiry dates, close tab, carry on with whatever was actually broken that day.
It is a terrible workflow and I defended it for years, mostly because the dashboard was there. The whole loop depended on me remembering to perform it.
Then I realised I had an AI assistant open all day, it could read structured data better than I could scan a grid, and the only thing between us was a small amount of configuration.
My instinct was to hand the assistant a REST API and let it work out the rest. That works, and it's also a bad idea β you'll spend a week explaining the auth model to it.
The much better pattern is to look for documentation written for it. Not a docs site with a sidebar. A single file the model can read once and then act from.
Certack ships several, which is what made the setup short:
/SKILL.md 17 KB the operational file: endpoints, auth, gotchas
/llms.txt 2.6 KB index + one-prompt onboarding
/llms-full.txt 2.8 KB extended summary: features, plans, integrations
/openapi.yaml 29 KB machine-readable API definition
/docs/api.txt 5.8 KB the full reference, as plain text for a context window
That last one matters more than people expect. HTML documentation has to be scraped and re-read on every call. A plain-text reference drops straight into a prompt and stays cached. I put the whole thing in context once at the start of a session and it works for the rest of the session.
Before configuring anything, I wanted to answer "is that certificate fine?" without provisioning a credential. Plenty of APIs let you create a key for that, which is a secret to rotate and keep out of config files forever.
Certack exposes a public MCP endpoint β no key, rate limited per IP:
{
"mcpServers": {
"certack": { "url": "https://api.certack.com/v1/public/mcp" }
}
}
Three tools: check_ssl, check_dns, check_domain. That's the entire unauthenticated surface, and it covers most of what I want to ask ad-hoc.
A real tools/call against example.com, and the response verbatim:
{
"jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": {
"name": "check_ssl",
"arguments": { "domain": "example.com" }
}
}
{
"valid": true,
"issuer": "CN=Cloudflare TLS Issuing ECC CA 3,O=SSL Corporation,C=US",
"days_remaining": 76,
"san": ["example.com", "*.example.com"],
"protocol_version": "TLSv1.3",
"cipher_name": "TLS_AES_128_GCM_SHA256"
}
Seventeen fields come back in total β chain, chain_complete, chain_error, cipher_strength, hsts, mixed_content, ocsp_stapling, expires_at, and the rest.
What matters for an assistant is that they're structured and flat. No HTML to interpret, no prose to summarise. The model reads days_remaining: 76 and knows that's fine; it doesn't have to reason about what "76 days remaining" means when phrased in a paragraph.
But notice what came back empty on this call: chain_complete, ocsp_stapling and the hsts object. Absent data, not false.
So the useful prompt isn't "check my domains". It's closer to:
Before you change anything on these domains, check the certificate and tell me if anything expires in under 30 days. If a field comes back empty, say so rather than assuming it's fine.
That second sentence is most of the trick. An assistant with structured data will confidently interpolate across gaps unless you tell it not to.
The keyless endpoint is read-only by design, which is correct. But reading wasn't the part I wanted β I wanted it to do things.
With an authenticated endpoint on the same protocol (12 tools: add and remove sites, update per-site thresholds and check types, list and resolve alerts, pull certificate history) the conversation changes shape. Things I now say out loud:
staging.example.com to monitoring, check types ssl and dns, alert me 14 days out."example.org β resolve that alert, I renewed it this morning."
No dashboard, no hunting for the right form.
Two configuration details worth copying. First, the alert threshold is one number per site, not a five-stage ladder: I set a lead time and get a warning at the lead time plus a critical at a quarter of it. Second, check cadence is fixed β daily for certificates and DNS, weekly for domains, dropping to a two-hour DNS retry when resolution fails β and it's the same on every plan. Paying more buys sites and alert channels, not a faster poll. Knowing that up front stopped me from expecting the paid tier to poll hourly, which it doesn't.
I still keep confirmation for anything destructive. The skill file documents what each tool does, including that removing a site deletes it, so the assistant can tell me that before doing it.
Agent-initiated changes need an audit trail, and "the model did it" is not an audit trail.
So the outbound side is a signed webhook β nine event types, HMAC-SHA256 β and there's one detail that took me two attempts to get right: the timestamp goes inside the signed payload, not next to it. Sign only the body and the signature is replayable forever; anyone who captures one delivery can resend it indefinitely. Sign timestamp + "." + body and you've bound it to a moment in time, which is what lets you reject it after five minutes.
Then there's dedup, because webhooks are at-least-once. My first receiver returned a conflict on a duplicate, which meant the sender retried, which meant it saw a duplicate again. Duplicates are success β return 2xx and move on, keyed on a content fingerprint with a TTL.
I wrote up the working receiver with all of it, because this is the part everyone reimplements badly: the five things every signed-webhook receiver gets wrong.
Start keyless. You get most of the value during setup and evaluation without provisioning a credential, and you learn what you actually want to automate.
Read the machine-readable docs, not the human ones. If a tool hasn't shipped an llms.txt-style surface and a plain-text API reference, your assistant is scraping HTML on every call. That's your token bill.
Ask for structured output, and be suspicious of empty fields. Every monitoring API returns false and null for different things, and only one of those means "this is fine."
Wire the outbound events early, even if the inbound path works. The day you want to be told about something rather than remember to ask, you'll want it already running β and that's five minutes on a weekend, not five minutes during an incident.
Deciding whether a flagged certificate is a problem. My monitoring flags it; I still have to know which CAs my own organisation buys from.
Watching my own renewal pipeline. The assistant can tell me a certificate expires soon. Nothing tells me ACME renewal started failing three weeks ago β still a separate gap I haven't closed.
The whole surface is documented for exactly this purpose β one file an assistant can read and act from:
Read https://certack.com/SKILL.md and follow the instructions to monitor example.com
That's the actual onboarding prompt, and it works in Claude, ChatGPT, Cursor and any MCP client. Raw reference at /docs/api. Webhook events are a paid feature; the free plan covers two sites with in-dashboard alerts only, and the keyless checker above needs no account.
If anyone's done this, I'm curious what bit you β the plain-text API reference, or the webhook receiver, or something I'm still doing the hard way on.