Certificate automation with MCP
Agents can inspect ACME accounts, configure certificate templates, select DNS connections, request issuance and build deployment tasks. Issuance, deployment and verification are separate outcomes.
From account to a verified endpoint
- Choose the issuer account. Read saved accounts and confirm production or staging. A TenantAdmin can register an account without EAB through
Settings/AcmeAccounts/Register, using a server-generated key and explicit agreement to the issuer's terms. Account-key import and EAB setup use the secure application UI. See ACME providers. - Select DNS authorization.
Certs/DnsConnectionsreturns names, types and GUIDs without credentials. Select the template default and any SAN-specific overrides. WithfollowTemplateDns=true, a domain inherits the default. A DNS setting GUID is different from a zone ID or numeric integration ID. See DNS authorization. - Save the template. Confirm primary domain, SANs, account, DNS settings and renewal window. Saving does not request a certificate. Preserve unrelated settings and stored passwords.
- Build deployment. Reuse or create the template's linked
Certificatetask, configure targets, link custom inputs and validate it. Renewal is unattended, so required inputs need usable defaults or a verified runtime source. Publication is optional. - Request issuance when authorized. An accepted order returns an operation ID. Follow its status until terminal, then inspect the issued certificate's thumbprint and expiry. After an ambiguous response, check the active operation before retrying.
- Follow the deployment run. Check task and step outcomes, then verify the intended service serves the new certificate. Successful issuance does not prove the deployment task succeeded.
The worker creates DNS-01 challenge records, waits for propagation, validates with the issuer, cleans up challenge values and finalizes the order. A DNS step in a post-renewal task runs too late to satisfy that order's challenge. Preserve other TXT values when investigating cleanup. Wildcards and apex names may share a challenge record name while needing different values. See DNS-01 validation.
Write scripts against the certificate context
Use an explicit PowerShell Script step (stepType=PSScript, configType=script) after CertificateInstall for parameterized post-install checks or changes. Read the script's input contract, select its version and bind each parameter through scriptParameters. The legacy post-script fields on an install target do not establish normal Script-step execution.
| Script parameter | Task binding example | Purpose |
|---|---|---|
| Thumbprint | {{ CertificateThumbprint }} | Find the exact issued certificate. |
| PrimaryDomain | {{ CertificatePrimaryDomain }} | Identify the intended domain. |
| CertificateStorePath | Cert:\LocalMachine\My | Use the same store as the installation step. |
| ServiceName or SiteName | A verified literal or linked custom parameter | Target the requested service or binding without guessing. |
Other certificate metadata includes CertificateSubject, CertificateExpiration, CertificateCommonName and CertificateFriendlyName. Availability depends on runtime certificate context. These names do not contain PFX or private-key payloads. CertificatePassword is sensitive: never print it or return it to an agent. Avoid custom parameters that shadow system names.
This read-only Windows PowerShell example checks the local installation. It does not verify the service binding or a remote TLS endpoint:
[CmdletBinding()]
param(
[Parameter(Mandatory)][ValidatePattern('^[A-Fa-f0-9]{40}$')]
[string]$Thumbprint,
[ValidateSet('Cert:\LocalMachine\My', 'Cert:\CurrentUser\My')]
[string]$CertificateStorePath = 'Cert:\LocalMachine\My'
)
$ErrorActionPreference = 'Stop'
$certificate = Get-Item -LiteralPath "$CertificateStorePath\$Thumbprint"
if (-not $certificate.HasPrivateKey) { throw 'Certificate has no private key.' }
if ($certificate.NotBefore.ToUniversalTime() -gt [DateTime]::UtcNow) {
throw 'Certificate is not valid yet.'
}
if ($certificate.NotAfter.ToUniversalTime() -le [DateTime]::UtcNow) {
throw 'Certificate has expired.'
}
[pscustomobject]@{
Thumbprint = $certificate.Thumbprint
ExpiresUtc = $certificate.NotAfter.ToUniversalTime().ToString('o')
InstallationVerified = $true
}
Use terminating errors for required changes and verify the resulting state. Keep scripts repeatable, preserve old certificates until the replacement is verified, and restart services only when requested. Save a new script version after changing its source or parameters, then read back the task's version, bindings and defaults. Follow custom and integration parameter guidance for dynamic selectors.
What the agent must verify
| Reported result | Required evidence |
|---|---|
| Configuration saved | Read back the template, linked task, selected script version and bindings. |
| Task valid | Validation returns isValid with no blocking issues. This does not execute anything. |
| Certificate issued | Terminal successful order operation, finalized order and certificate details. |
| Certificate deployed | Successful deployment task and relevant step outcomes. |
| Endpoint verified | An actual check of the intended TLS service and served certificate. |
The default automatic renewal window is 30 days before expiry when unset. nextAllowedRenewal is a hold/backoff time; it is not expiry or a guaranteed execution time. On failure, inspect challenge status, DNS record status, operation history and task logs before retrying. Cancellation is best effort and cannot revoke an already issued certificate.
MCP exposes five guides through get_workflow_guidance: certificates, certificate-accounts, certificate-dns, certificate-automation and certificate-scripting. Private-key downloads, DNS credentials, EAB secrets and account-key import remain outside model context.