Frontdesk AI
OfficialProvides scheduling tools for listing Calendly event types, checking availability, booking and canceling invitees, and confirming the connected Calendly account.
Sends push notifications to ntfy.sh topics for visitor alerts and notification flows.
Enables the send-email tool to deliver messages to a configured internal inbox through Resend, supporting take-a-message workflows.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Frontdesk AIBook a meeting with me next Tuesday at 3pm"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Frontdesk AI
One agent core. Three protocols. Zero config. Self-hosted personal AI concierge that books your Calendly, takes messages to your inbox, and answers questions about you — exposed to humans (chat UI), AI tools (MCP), and other agents (A2A) from a single ~250-line tool core.
Docs · Make it yours · Architecture · Contributing · Security · Agent protocols — A2A
Why this exists
Every personal site gets the same CTA: "email me and I'll get back to you." This repo is the upgrade — a streaming AI assistant that acts when visitors don't want to wait for a reply. But the real contribution is architectural:
The same assistant, three doors in. A single tool core (
calendar,send_email) served simultaneously as a human chat UI, an MCP server for AI tool clients, and an A2A agent for agent-to-agent delegation. Most projects build these as three separate codepaths; this is a minimal, readable, deployable proof that one core can serve all three.
┌──────────────────────────────┐
Humans ─────▶ │ Chat UI (POST /api/chat) │
│ │
MCP clients ─▶ │ MCP (POST /api/mcp) │──▶ ┌───────────────┐
(Claude, Cursor)│ │ │ tool core │──▶ Calendly
│ │ │ calendar │
A2A agents ─▶│ A2A (POST /a2a) │──▶ │ send_email │──▶ Email (+ ntfy)
└──────────────────────────────┘ └───────────────┘
one model, one persona, ~250 lines, shared by all three
one provider key you chooseRelated MCP server: Calendly MCP Server
Deploy in 2 steps
Click Deploy →
(Vercel forks the repo and opens its UI for you).
Or: fork on GitHub → Import in Vercel → same thing.
Add one LLM key in the Vercel project → Settings → Environment:
Key
Provider
ANTHROPIC_API_KEYClaude (recommended default)
OPENAI_API_KEYOpenAI
LLM_API_KEY(+LLM_BASE_URL)LiteLLM proxy or any OpenAI-compatible endpoint
ZAI_API_KEYZ.ai GLM (legacy default)
Then optionally:
RESEND_API_KEY+ASSISTANT_INTERNAL_EMAIL+ASSISTANT_EMAIL_FROM→ take-a-message → emailCALENDLY_ACCESS_TOKEN→ meeting bookingNTFY_TOPIC→ visit push notifications
Hit Deploy. Done — the app runs fine with just one LLM key; missing keys disable the feature with a clear error instead of breaking chat.
Every free tier you need: pick your LLM (see Swap your LLM), Vercel hobby, Calendly free, Resend free, ntfy.sh free.
Swap your LLM
Frontdesk AI is provider-agnostic. The first provider with a key configured wins (lib/ai.ts):
# Claude
ANTHROPIC_API_KEY=sk-ant-...
ANTHROPIC_MODEL=claude-sonnet-4-5
# OpenAI
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4o
# LiteLLM (or any OpenAI-compatible endpoint — Ollama, vLLM, Groq, Together…)
LLM_API_KEY=...
LLM_BASE_URL=https://your-proxy.example/v1
LLM_MODEL=your-model
# Z.ai GLM (default)
ZAI_API_KEY=...
ZAI_MODEL=glm-5.3-flashNo code changes — lib/persona.ts, lib/calendly.ts, and lib/sendEmail.ts are all provider-agnostic.
Make it yours
A full step-by-step walkthrough (persona, branding, assets, keys, deploy checklist) lives in docs/CUSTOMIZE.md → Make it yours — 10-minute checklist. Short version:
Persona — edit the
OWNERobject at the top oflib/persona.ts(name, bio, links, highlights). This is what the assistant actually knows and follows.Branding — set
NEXT_PUBLIC_ASSISTANT_NAME/NEXT_PUBLIC_ASSISTANT_TAGLINE,NEXT_PUBLIC_CONTACT_EMAIL,NEXT_PUBLIC_LINKEDIN/NEXT_PUBLIC_GITHUB,NEXT_PUBLIC_UPI_ID("buy me a coffee"), and drop your photo atpublic/avatar.jpg+ your CV atpublic/resume.pdf.Keys/config — everything is env-driven; nothing to fork-edit.
One assistant, three protocols
The same tools (lib/calendly.ts, lib/sendEmail.ts) and the same model are exposed three ways. For the full picture of why this design wins and how to add a new capability across all three surfaces, read docs/ARCHITECTURE.md.
1. Human chat UI (REST)
POST /api/chat — the streaming chat on the homepage. Vercel AI SDK streamText, multi-step tool use (maxSteps=20), rate-limited 40 req/min/IP. No auth (public).
2. MCP server (for AI tool clients)
POST /api/mcp — an MCP Streamable HTTP server exposing calendar and send_email as tools. Any MCP client (Claude, Cursor, opencode, etc.) can point at it and book meetings / take messages directly.
// MCP client config (e.g. claude_desktop_config / .mcp.json)
{
"mcpServers": {
"concierge": {
"type": "http",
"url": "https://<your-app>.vercel.app/api/mcp",
"headers": { "Authorization": "Bearer <your LLM API key>" }
}
}
}Auth: Authorization: Bearer <any configured provider key> · rate-limited 20 req/min/IP. GET /api/mcp returns a human-readable capability summary.
3. A2A agent (for agent-to-agent delegation)
POST /a2a — an A2A (Agent-to-Agent) JSON-RPC endpoint with streaming. Other AI agents discover it via the Agent Card at /.well-known/agent-card.json and delegate full tasks: book a meeting, leave a message, or ask a question.
# Discover the agent
curl https://<your-app>.vercel.app/.well-known/agent-card.json
# Send a task (blocking)
curl -X POST https://<your-app>.vercel.app/a2a \
-H "Authorization: Bearer $YOUR_LLM_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "SendMessage",
"params": { "message": { "role": "user",
"parts": [{ "type": "text", "text": "Book a 30-minute meeting on Thursday" }] } },
"id": "req-1"
}'Auth: Authorization: Bearer <any configured provider key> · rate-limited 20 req/min/IP · supports SendMessage, SendStreamingMessage, GetTask, CancelTask.
Features
Streaming chat — token-by-token streaming; raw text renders instantly mid-stream, then react-markdown appears once the reply settles (no UI jank).
Bring your own LLM — Claude, OpenAI, LiteLLM/any OpenAI-compatible endpoint, or Z.ai GLM. First key configured wins.
Calendly scheduling —
calendartool: list event types, check availability, book an invitee, cancel, confirm account.Take-a-message email —
send_emailtool delivers to your internal inbox; the envelope address is never exposed and never accepts an external recipient.Two conversation modes —
Chat(assistant & peer) andRecruiter(CV walkthrough) personas; transcripts persist per-mode in localStorage.Privacy by default — the persona never reveals your phone or internal email, refuses jailbreak attempts, and collects name + email confirmation before any booking/send.
Visitor tracking —
/api/trackbest-effort: ip-api geolocation → ntfy push + email. Never blocks the visitor.
How it works
Visitor
│ POST /api/chat {"messages", "mode"}
▼
app/api/chat/route.ts Vercel AI SDK streamText (maxSteps=20)
│ model: lib/ai.ts (Claude / OpenAI / LiteLLM / Z.ai) rate-limit: 40 req/min/IP
│ tools: calendar · send_email (Zod-validated)
▼
lib/calendly.ts ── CALENDLY_ACCESS_TOKEN ──> Calendly API
lib/sendEmail.ts ── RESEND_API_KEY ──> Resend APIlib/persona.ts supplies the persona + guardrails; the chat route sanitizes replayed tool-call history so streamText never chokes on a tool invocation missing its result.
Tech stack
Next.js 15 (App Router, React 19, TypeScript) · Vercel AI SDK v4 · Claude / OpenAI / LiteLLM / Z.ai GLM (provider-agnostic) · Calendly API · Resend · ntfy.sh · react-markdown + remark-gfm · Vitest + jsdom + Testing Library · GitHub Actions · @modelcontextprotocol/sdk (MCP) · @a2a-js/sdk (A2A).
Developing
npm install
cp .env.example .env # add your keys
npm run dev # http://localhost:3000Script | What it does |
| dev server |
| production build / serve |
|
|
| Vitest suite |
Configuration
Full reference in .env.example:
Variable | Required | Purpose |
| or one below | Z.ai GLM API key (legacy default) |
| or one above | OpenAI |
| or one above | Anthropic Claude |
| or one above | LiteLLM / OpenAI-compatible |
| Resend API key — https://resend.com/api-keys | |
| Inbox the assistant emails messages and visit alerts to | |
| Verified sender, e.g. | |
| calendar | Calendly PAT — https://calendly.com/integrations/api_webhooks |
| alerts | ntfy.sh topic for push notifications |
| branding | Header title / tagline |
| branding | Header contact links |
| branding | "Buy me a coffee" UPI id (empty hides the button) |
| branding | Fallback origin for the copied agent set-up |
| metadata |
|
| optional | IANA timezone for availability display |
| optional | Feature flags (default: enabled) |
| deploy scripts | See below |
Deploying
deploy.sh (macOS/Linux) and deploy.ps1 (Windows) each run a local build check, deploy --prod to Vercel, and report the deployment state. They temporarily hide .git during the deploy as a workaround for Vercel's seat-verification block, then restore it. Both resolve the project for status reporting from VERCEL_PROJECT_ID or .vercel/project.json (from vercel link); set your env vars in the Vercel dashboard regardless.
export VERCEL_TOKEN="<your token>"
./deploy.shTesting
Vitest tests cover the Calendly tool (booking, availability, cancellation), the email tool (env gating, ntfy best-effort), persona safety rules, /api/track, the chat UI streaming-render behavior (raw text while streaming, markdown on settle, localStorage only when idle), the MCP server (tool listing + execution through the SDK's in-memory transport), and the A2A agent (Agent Card shape, intent routing, executor event lifecycle).
Project structure
app/
api/
chat/route.ts streaming chat (tools + model + rate limit)
mcp/route.ts MCP Streamable HTTP server (calendar + send_email tools)
track/route.ts visitor tracking (ntfy push + email, best-effort)
a2a/route.ts A2A JSON-RPC endpoint (send/get/cancel task, streaming)
.well-known/agent-card.json/route.ts A2A Agent Card discovery
page.tsx chat UI (modes, streaming render, localStorage)
Markdown.tsx react-markdown wrapper
lib/
ai.ts provider-agnostic model factory (Claude/OpenAI/LiteLLM/Z.ai)
calendly.ts Calendly API wrapper (book/cancel/availability)
sendEmail.ts Resend email wrapper
mcp/server.ts MCP tool registry (calendar, send_email)
a2a/executor.ts A2A agent executor + intent routing
a2a/types.ts A2A Agent Card definition
persona.ts persona + privacy guardrails (editor-friendly template)
rateLimit.ts in-memory per-IP rate limiter
*.test.ts / *.test.tsx Vitest suites
.github/workflows/ci.yml typecheck + tests + build on push/PR
deploy.ps1 / deploy.sh Vercel production deploy scriptsFAQ
Do I need to be a developer to set this up?
No. Deploy-to-Vercel, add one LLM key, edit OWNER in lib/persona.ts and a few branding env vars. The 10-minute checklist covers it end-to-end. Editing lib/persona.ts is plain text — no framework knowledge required.
Which model should I pick? Whatever you already have a key for — Claude, OpenAI, LiteLLM (which also fronts Groq, Ollama, vLLM, Together, custom endpoints), or Z.ai GLM. Claude is a good default for concierge-style tool use. You can switch later without code changes.
Does this cost money? The app itself runs on Vercel's free hobby tier. All integrations (Calendly, Resend, ntfy.sh) have free tiers. You pay for LLM tokens — a personal site's chat traffic is pennies to a couple of dollars a month depending on the model.
Is it safe to expose on a public site? The persona never reveals your phone or internal email, refuses jailbreak attempts, and collects name+email confirmation before any booking or send. Email always routes to your internal inbox (never an external recipient), rate limits apply per IP, and MCP/A2A endpoints additionally require the bearer key. See SECURITY.md.
What's the difference between the three doors (chat / MCP / A2A)?
The chat UI is for humans visiting your site. MCP is for AI tool clients (Claude, Cursor, opencode) that want to call calendar / send_email as tools. A2A is for other AI agents to hand you a whole task end-to-end. Same tools, same model, three protocols — see ARCHITECTURE.md.
Do I need a Calendly/Resend account just to try it? No. The app runs with one LLM key alone. Missing integration keys disable that feature with a clear error instead of breaking chat.
Can I extend it with my own tools?
Yes. Add a lib/yourTool.ts with an env-gated run() function, register it as a chat tool, an MCP tool, and an A2A route case — ARCHITECTURE.md#requirements-for-adding-a-capability spells it out.
Security notes
Credentials live only in
.env(gitignored);.env.exampleships placeholders.sendEmail.tsandtrack/route.tsnever fall back to a hardcoded inbox/topic — a misconfigured fork fails loudly instead of emailing the original author's address./api/*is set tono-store; security headers (X-Content-Type-Options,X-Frame-Options,Referrer-Policy,Permissions-Policy) are applied site-wide.Rate limits:
/api/chat(40/min/IP),/api/track(24/min/IP),/api/mcp(20/min/IP),/a2a(20/min/IP).MCP and A2A require
Authorization: Bearer <a configured provider key>; the chat UI is intentionally public.The persona never reveals your phone or internal email, and refuses jailbreak attempts.
react-markdownrenders withoutrehype-raw, so raw HTML in model output is inert.Visit/push/email integrations are best-effort by design — failures never block the visitor's response.
License
MIT
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Hosted Google Calendar MCP server for AI agents. No self-hosting or Google Cloud setup.
Hosted MCP runtime where the agent is the operator: sign up by tool call, publish your own tools.
Zero-setup MCP gateway securely connecting AI to your tools with authentication and workflows
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Related MCP Servers
- AlicenseAqualityBmaintenanceAgent-native MCP server for Carly, the AI scheduling assistant. Exposes 11 tools to read and manage booking pages, event types, calendars, bookings, and available slots. Allows you to manage and create booking pages from the command line.1314MIT
- AlicenseAqualityDmaintenanceA Model Context Protocol (MCP) server for the Calendly API. Manage events, invitees, and schedule meetings directly via AI assistants.12100MIT
- AlicenseNot gradedqualityAmaintenanceMulti-server MCP tool bridge that exposes banking, email, calendar, and custom API tools for AI clients via the Model Context Protocol.2,499MIT
- AlicenseNot gradedqualityAmaintenanceLocal MCP server for reading/sending email via Gmail and managing Google Calendar events, enabling an AI agent to handle email and calendar operations through natural language.MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/tersePrompts/frontdesk-ai'
If you have feedback or need assistance with the MCP directory API, please join our Discord server