Hubungkan MCP Termilo

Hubungkan agen AI ke profil tenant Anda. MCP Termilo memakai satu endpoint Streamable HTTP dan API key tenant untuk membaca link booking aktif atau mengelola token branding sesuai scope key.

Kontrak live
Endpoint production adalah https://api.termilo.id/mcp/<TENANT_ID> dengan header Authorization: Bearer <TERMILO_API_KEY>. Jangan tambahkan /v1 atau memakai slug tenant sebagai pengganti tenant ID.

Prasyarat#

  1. Buka Dashboard → API keys, buat key dengan scope Booking · baca untuk link booking atau Branding MCP untuk tampilan, lalu salin secret yang hanya ditampilkan sekali.
  2. Ambil tenant ID dari config booking publik. Ganti tenant slug dengan bagian terakhir URL booking Anda.
  3. Simpan key di secret manager atau environment variable client.
curl -s "https://book.termilo.id/book/<TENANT_SLUG>/config" \ | jq -r '.data.tenant.tenantId'

Dukungan client#

Client yang menerima static HTTP header dapat dipakai sekarang. UI yang hanya menerima OAuth connector harus menunggu OAuth MCP Termilo.

ClientJalur koneksiStatus
OpenClawRemote MCP + static headerDidukung
Hermes Agentmcp_servers + environment headerDidukung
Claude CodeHTTP MCP + static headerDidukung
OpenAI Responses APIRemote MCP + authorizationDidukung
ChatGPT UIMembutuhkan OAuth discoveryMenunggu OAuth
Claude.ai / Desktop connectorMembutuhkan OAuth flowMenunggu OAuth

Tool tenant#

get_booking_linksbookings:readread · risiko low

List active services and their direct public booking links.

Input:
No input.
Output:
Active service slug, name, duration, public-safe location, and direct booking URL.
Contoh:
{}
get_serviceservices:readread · risiko low

Read one service configuration by id or slug, including location policy and booking link.

Input:
serviceId or serviceSlug (exactly one).
Output:
Slug, name, duration, buffers, status, staff ids, location policy, and direct booking URL.
Contoh:
{"serviceSlug":"onboarding-konektor"}
preview_availabilitybookings:readread · risiko low

Preview bookable slots for one service before sharing its booking link.

Input:
serviceSlug plus either days (1-60 from now) or an explicit fromMs/toMs window.
Output:
Service timezone, resolved window, slot count, and the first slots with start and end instants.
Contoh:
{"serviceSlug":"onboarding-konektor","days":14}
create_serviceservices:writewrite · risiko medium

Create one bookable service with its location policy. Requires an idempotency key.

Input:
idempotencyKey, slug, name, durationMin, optional buffers/description/status, location, and optional dryRun.
Output:
serviceId, slug, status, booking URL, public-safe location, and idempotentReplay.
Contoh:
{"idempotencyKey":"konektor-onboarding-v1","slug":"onboarding-konektor","name":"Onboarding Konektor","durationMin":45,"location":{"locationType":"online_meeting","provider":"google_calendar"}}
update_serviceservices:writewrite · risiko medium

Update one existing service and optionally replace its location policy.

Input:
serviceId plus at least one changed field, optional location, and optional dryRun.
Output:
Updated serviceId, slug, status, booking URL, and public-safe location.
Contoh:
{"serviceId":"svc_01H","durationMin":60,"dryRun":true}
archive_serviceservices:writewrite · risiko high

Archive one service by setting status to disabled. Recoverable through update_service.

Input:
serviceId and optional dryRun.
Output:
serviceId, status disabled, and the previous status for recovery.
Contoh:
{"serviceId":"svc_01H"}
list_bookingsbookings:readread · risiko low

List bookings for this tenant, optionally filtered by status and time window.

Input:
Optional status, fromMs, toMs, and limit up to 100.
Output:
Booking id, status, service, window, timezone, and contact-light customer summary.
Contoh:
{"status":"confirmed","limit":20}
get_bookingbookings:readread · risiko low

Read one booking including its meeting or offline location status.

Input:
bookingId.
Output:
Booking lifecycle fields plus meeting state: pending, ready with join URL, or not applicable.
Contoh:
{"bookingId":"bkg_01H"}
create_bookingbookings:writewrite · risiko medium

Create one booking on behalf of a customer. Requires an idempotency key.

Input:
idempotencyKey, serviceSlug, startsAtMs, customer name plus email or phone, and optional dryRun.
Output:
bookingId, status, window, manage URL when issued, and idempotentReplay.
Contoh:
{"idempotencyKey":"support-case-4821","serviceSlug":"support-konektor","startsAtMs":1800000000000,"customer":{"name":"Rani","primaryEmail":"rani@example.com"}}
reschedule_bookingbookings:writewrite · risiko medium

Move one booking to a new start instant, re-checking availability and locks.

Input:
bookingId, startsAtMs, and optional dryRun.
Output:
Updated booking status and window.
Contoh:
{"bookingId":"bkg_01H","startsAtMs":1800003600000}
cancel_bookingbookings:writewrite · risiko high

Cancel one booking with an optional reason.

Input:
bookingId, optional reason, and optional dryRun.
Output:
Cancelled booking status and cancellation instant.
Contoh:
{"bookingId":"bkg_01H","reason":"Customer requested"}
get_brandingbranding:readread · risiko low

Read the effective Termilo branding for this tenant.

Input:
No input.
Output:
Effective validated branding tokens and the tenant booking URL.
Contoh:
{}
update_brandingbranding:writewrite · risiko medium

Update validated Termilo branding tokens for this tenant.

Input:
One or more validated branding fields such as brandName, logoUrl, or primaryHex.
Output:
Updated effective branding tokens; arbitrary CSS, HTML, and JavaScript are rejected.
Contoh:
{"primaryHex":"#0E766E"}
get_payment_providerspayments:readread · risiko low

Read DOKU and Pakasir BYOK booking-payment configuration without secrets.

Input:
No input.
Output:
Provider status, public identifier, callback URL, onboarding links, and hasSecret only.
Contoh:
{}
configure_payment_providerpayments:writewrite · risiko high

Save and optionally activate a tenant-owned DOKU or Pakasir booking credential. Secrets are write-only.

Input:
provider: a discriminated DOKU or Pakasir configuration; secretKey/apiKey are write-only.
Output:
Redacted provider status and onboarding metadata; credentials are never returned.
Contoh:
{"provider":{"providerKey":"doku","environment":"sandbox","clientId":"BRN-0001","secretKey":"<WRITE_ONLY_SECRET>","active":true}}
disconnect_payment_providerpayments:writewrite · risiko high

Delete one tenant-owned booking-payment credential.

Input:
providerKey: doku or pakasir.
Output:
Disconnected provider status without credentials.
Contoh:
{"providerKey":"doku"}
list_webhookswebhooks:readread · risiko low

List outbound webhook subscriptions without their signing secrets.

Input:
No input.
Output:
Subscription id, URL, event filter, status, and timestamps. Secrets are never returned.
Contoh:
{}
create_webhookwebhooks:writewrite · risiko high

Create one outbound webhook subscription. The signing secret is returned once and never again.

Input:
HTTPS url, optional eventFilter and description, optional status, and optional dryRun.
Output:
Subscription metadata plus the write-only signing secret shown exactly once on create.
Contoh:
{"url":"https://hooks.konektor.id/termilo","eventFilter":["booking.created","booking.cancelled"]}
rotate_webhook_secretwebhooks:writewrite · risiko high

Issue a new signing secret for one webhook subscription and invalidate the old one.

Input:
webhookId and optional dryRun.
Output:
Subscription metadata plus the new write-only signing secret shown exactly once.
Contoh:
{"webhookId":"whsub_01H"}
disable_webhookwebhooks:writewrite · risiko high

Disable one webhook subscription so it stops receiving deliveries. Recoverable.

Input:
webhookId and optional dryRun.
Output:
Subscription metadata with status disabled and the previous status for recovery.
Contoh:
{"webhookId":"whsub_01H"}
send_test_webhookwebhooks:writewrite · risiko medium

Enqueue one signed test delivery to a webhook subscription without touching booking data.

Input:
webhookId and optional dryRun.
Output:
Queued delivery id and event id to correlate with list_webhook_deliveries.
Contoh:
{"webhookId":"whsub_01H"}
list_webhook_deliverieswebhooks:readread · risiko low

Read webhook delivery diagnostics: status, attempts, retry reason, and next retry instant.

Input:
Optional webhookId, status, limit up to 100, and offset.
Output:
Delivery id, event id, event type, status, attemptCount, errorClass, nextRetryAtMs, and target URL. No secrets or request bodies.
Contoh:
{"status":"failed","limit":20}

Field yang dapat diubah: brandName, logoUrl, primaryHex, accentHex, backgroundHex, surfaceHex, textHex, shape, font, template, dan poweredBy.

Bukan editor CSS bebas
Tool update tidak menerima CSS, HTML, JavaScript, font URL, atau file base64. Logo harus berupa URL HTTPS dan kombinasi warna harus lulus contrast ratio minimum 4.5:1.

OpenClaw#

OpenClaw 2026.7.1-2 menerima header CLI dalam formatKEY=VALUE. Simpan key di~/.openclaw/.env; server definition dan template header tetap disimpan di config lokal. Kedua file wajib mode0600 dan hanya boleh ada di perangkat tepercaya.

export TERMILO_TENANT_ID="<TENANT_ID>" export TERMILO_MCP_API_KEY="<TERMILO_API_KEY>" umask 077 touch ~/.openclaw/.env printf 'TERMILO_MCP_API_KEY=%s\n' "$TERMILO_MCP_API_KEY" >> ~/.openclaw/.env chmod 600 ~/.openclaw/.env openclaw mcp add termilo \ --url "https://api.termilo.id/mcp/${TERMILO_TENANT_ID}" \ --transport streamable-http \ --header 'Authorization=Bearer ${TERMILO_MCP_API_KEY}' \ --include 'get_booking_links,get_branding' chmod 600 ~/.openclaw/openclaw.json openclaw mcp doctor termilo --probe openclaw mcp probe termilo --json openclaw mcp reload

Rujukan: OpenClaw MCP CLI dan environment loading.

Hermes Agent#

Hermes dapat membaca header dari environment variable saat runtime. Simpan key di ~/.hermes/.env, lalu tambahkan server HTTP di config.

# ~/.hermes/.env TERMILO_MCP_API_KEY=<TERMILO_API_KEY>

Jalankan /reload-mcp di Hermes atau restart agent. Tool tampil dengan prefix mcp_termilo_.

Rujukan: Hermes Agent MCP.

ChatGPT dan OpenAI#

ChatGPT UI belum bisa memakai API key Termilo
UI connector ChatGPT mengandalkan OAuth discovery dan tidak menyediakan field custom Authorization header. Sampai OAuth MCP Termilo tersedia, gunakan OpenAI Responses API untuk koneksi programatik.

Set TERMILO_MCP_URL ke endpoint tenant danTERMILO_MCP_API_KEY ke secret. Ganti placeholder model dengan model yang mendukung remote MCP. Approval selalu diaktifkan agar update branding tidak berjalan diam-diam.

import OpenAI from "openai"; const openai = new OpenAI(); const response = await openai.responses.create({ model: "<MCP_CAPABLE_MODEL>", input: "Tampilkan branding Termilo saya.", tools: [{ type: "mcp", server_label: "termilo", server_url: process.env.TERMILO_MCP_URL, authorization: process.env.TERMILO_MCP_API_KEY, allowed_tools: ["get_branding", "update_branding"], require_approval: "always", }], }); console.log(response.output_text);

Rujukan: OpenAI remote MCP tools dan koneksi MCP ke ChatGPT.

Claude#

Claude Code mendukung HTTP MCP dengan custom header dan ekspansi environment variable. Simpan contoh berikut sebagai .mcp.json, export kedua variable sebelum membuka Claude Code, lalu jalankan /mcp untuk memeriksa status.

{ "mcpServers": { "termilo": { "type": "http", "url": "https://api.termilo.id/mcp/${TERMILO_TENANT_ID}", "headers": { "Authorization": "Bearer ${TERMILO_MCP_API_KEY}" } } } }
Claude.ai dan connector akun berbeda
Form connector akun Claude.ai/Desktop mengikuti alur remote connector dengan OAuth. Static bearer Termilo saat ini didukung di Claude Code, bukan pada form connector akun tersebut.

Rujukan: Claude Code MCP dan Claude custom connectors.

Uji koneksi#

Mulai dengan read-only prompt:

Tampilkan branding Termilo saya. Jangan ubah apa pun.

Lalu uji update dengan review eksplisit:

Siapkan perubahan primaryHex menjadi #0E766E. Tampilkan perubahan yang akan dibuat dan minta persetujuan saya sebelum memanggil update_branding.

Setelah update, buka halaman booking Anda pada browser baru untuk memastikan profil efektif yang sama dipakai hosted page dan embed.

Troubleshooting#

401 AUTH_REQUIRED
Key hilang, invalid, expired, revoked, atau tidak cocok dengan tenant ID pada URL.
403
Key tidak memiliki scope tool yang dipanggil, atau request browser membawa Origin yang tidak dipercaya.
429
Terlalu banyak request. Tunggu lalu ulangi; jangan membuat retry loop rapat.
Tool tidak muncul
Pastikan URL memuat tenant ID, reload/restart client, lalu jalankan doctor, probe, atau /mcp sesuai client.
ChatGPT/Claude connector gagal auth
Gunakan jalur API/Claude Code yang didukung. UI connector menunggu OAuth MCP Termilo.

Keamanan#

Jangan tempel API key ke prompt, chat, screenshot, issue, atau repository Git. Siapa pun yang memegang key dapat memakai scope yang diberikan.
  • Pilih preset Branding MCP, bukan akses penuh.
  • Gunakan environment variable jika client mendukungnya.
  • Jangan bagikan satu key ke banyak perangkat atau anggota tim.
  • Jika key bocor atau hilang, rotate atau revoke segera dari halaman API keys.