Agent authentication
MCP server https://mcp.mdiv.pl/api/mcp accepts two authentication methods:
- OAuth 2.1 + PKCE — preferred for AI agents acting on behalf of the user (Claude Desktop, Cursor, ChatGPT with MCP). Requires
code_challenge_method=S256; the valueplainis rejected per RFC. Authorization endpoint:https://moje.mdiv.pl/oauth/authorize. Dynamic Client Registration:https://moje.mdiv.pl/api/oauth/register(RFC 7591). - Personal API Token — format
mpt_<64hex>(96 bits of entropy). Issued manually by the customer at https://moje.mdiv.pl/account/api-tokens. Passed in the headerAuthorization: Bearer mpt_….
Tokens are stored on the server as a bcrypt hash — never in plaintext. The token value is shown once, at the moment of issuance. The customer can revoke a token at any time via the panel.
Granular scopes (33)
Every token (OAuth or PAT) has an assigned subset of 33 scopes. List of domains: websites, domains, databases, email, dns, ssl, apps, jobs, packages, files, backups, commerce, profile, offline_access. Each domain has the splits :read / :write / :delete.
Implication rules:
:writeimplies:read— a token withdatabases:writecan also read.:deleteis NOT implied by:write. To delete a resource, the agent must hold a separate:deletescope.- All scopes are opt-in — by default an empty token allows nothing.
Full list and tool→scope mapping: see /en/for-ai-agents and /.well-known/mcp.json.
Tier system
Independently of token scopes, each customer account has the flag ai_deploy set by an mDiv administrator:
| Tier | What's allowed |
|---|---|
none | Default. All AI Deploy operations → 403 AI_DEPLOY_NOT_ENABLED. |
sandbox | Read-only tools only. install_*, delete_*, set_dns_records → 403 AI_DEPLOY_TIER_TOO_LOW. |
beta | Full ops range. Limit of 500 mutating calls per account per day. |
full | No restrictions beyond the physical limits of the plan. |
The customer starts on sandbox. Promotion after 1–2 weeks of testing happens after the customer's written consent and a log review. The global kill switch (AI_DEPLOY_GLOBALLY_DISABLED) allows AI Deploy to be disabled for all accounts in case of an incident on mDiv's side.
Two-step delete pattern
Every destructive operation (delete_*, in phase 1 covers only delete_domain; further resource types are added gradually) requires two calls:
preview_delete_domain({ domain_id })→{ preview_token, impact: { subdomains, ssl_certs, email_domains, warning }, expires_at }. The agent MUST show the user theimpactfield and wait for confirmation.delete_domain({ domain_id, preview_token, confirm: true})→{ deleted: true }.
The preview token has three safeguards:
- Bound to (user_id, resource_type, resource_id). The agent CANNOT slip the user a token issued for a different resource or account — the server rejects with
PREVIEW_TOKEN_OWNERSHIP_MISMATCH/PREVIEW_TOKEN_RESOURCE_MISMATCH. - Single-use — after the first use the token is invalidated.
- TTL 10 minutes. After expiry:
PREVIEW_TOKEN_EXPIRED.
Missing preview_token in a destructive call returns PREVIEW_TOKEN_MISSING; missing confirm: true → CONFIRMATION_REQUIRED. The pattern is being progressively rolled out to further resource types.
Idempotency-Key
All mutating endpoints (POST, PUT, PATCH, DELETE) honour the header Idempotency-Key with a UUID v4 supplied by the client.
- Replay with the same body within a 24h window → cached response with the header
Idempotent-Replay: true. - Replay with a different body →
409 IDEMPOTENCY_KEY_REUSED. - Invalid key format →
400 IDEMPOTENCY_KEY_INVALID. - Endpoints that return one-time secrets (
create_database, PAT issuance, OAuth token issuance) do not cache the response body. Replay re-executes the handler — the secret is not leaked via the cache.
Rate limit
Per-token sliding window of 60 seconds. Limits are more restrictive for operations with high infrastructure cost:
- Default: 60 req/min per token.
- Install ops (
install_wordpress,request_ssl): 5 req/min. Each such operation kicks off an install / certification pipeline, so aggressive polling has no use.
When exhausted: 429 RATE_LIMITED with headers X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After. The agent should respect Retry-After — ignoring it results in the token being paused.
Audit log
Every MCP call (read and write) is written to an immutable audit log on mDiv's side. Each entry contains:
- token_id (sha256 hash; never plaintext token)
- user_id, oauth_client_id (if OAuth)
- tool name, required scope, request body (PII redacted)
- resource_type, resource_id
- response status, error code
- IP, user-agent, timestamp with millisecond precision
- idempotency_key, preview_token (if used)
The customer is entitled to inspect the log for their account via the panel moje.mdiv.pl/account/audit-log. Retention: 12 months. Higher-risk logs (delete, install, token issuance) — 24 months. After retention, entries are anonymised (token_id and IP zeroed), the rest is kept for statistics.
Anomaly detection
The audit log is analysed in near real time. Detected anomalies (sample thresholds):
- A series of
delete_*in a short window (≥3 in 60s) — the token is paused pending administrator confirmation. set_dns_recordsoverwriting existing critical records (MX, SPF, DKIM) — requires email confirmation from the customer.- A sudden change in the geographical origin of requests (IP geo) — an email to the customer with a link "I don't recognise this activity → block the token".
- An attempt to enumerate other customers' resources (e.g. using somebody else's UUIDs) — immediate token block and alert to the administrator.
The policy is evolutionary: new signals are added without API changes. Rules currently in production are described in the AI Deploy changelog.
Weekly summary email
Every customer with ai_deploy ≠ none receives a summary of the previous week on Monday morning:
- call count aggregated per scope and per tool
- list of write changes (domains, databases, installs, SSL created)
- list of destructive changes (delete_*) with timestamps
- active tokens and the dates of their most recent use
- flagged anomalies (if any)
- link to the panel for disabling AI Deploy or narrowing token scopes
The subscription can be turned off in the panel, but security alerts (anomalies, token blocks) are always sent — they cannot be silenced.
Data isolation between customers
Every MCP call is filtered by the user_id context extracted from the token. The backend performs authorisation at the SQL query level — even knowing another customer's domain / database / website UUID does not allow it to be retrieved.
The audit log validates that resource.user_id == token.user_id on every operation. An attempt to use somebody else's UUID ends with 404 NOT_FOUND (not 403 — we don't disclose the resource's existence) and an entry in the anomaly detection log (section 8).
Customer databases live in separate MariaDB / PostgreSQL instances with dedicated users. Files on shared hosting are protected by open_basedir + per-user chroot.
Encryption and transport
In transit: all MCP, OAuth and customer panel endpoints enforce HTTPS (HSTS, TLS 1.3, Let's Encrypt certificates with auto-renew). HTTP connections are 301 redirected and do not serve any application endpoints.
At rest: user password hashes in argon2id; tokens (PAT, OAuth access/refresh) in bcrypt; preview tokens in memory with TTL 10 min (Redis with encryption at rest on the volume).
Backups: daily, encrypted (AES-256) before being written to remote storage. The key is never on the backed-up machine.
Secrets in response body (e.g. DB password from create_database): returned once, over Streamable HTTP, not written to logs or audit (audit records only the fact of the call, not the response content).
Incident response & disclosure
Vulnerability reports: security@…. We accept encrypted reports (PGP key available at /.well-known/security.txt). First-response time: up to 24h on business days.
Disclosure: 90-day coordinated disclosure from the date the vulnerability is confirmed. The reporter receives credit (unless they request anonymity). Hall of fame for researchers on a dedicated page after public launch (Q3 2026).
Data breach notifications: in the event of a personal-data incident (GDPR), customers are notified by email and in the panel within 72h of confirmation. The incident communication plan also includes: a detailed post-mortem on the mDiv blog, the list of affected accounts, remediation steps and recommendations for customers.
AI Deploy operational contact: ai-deploy@… or contact form.