In 30 seconds
┌────────────────────────────────────────────────────────────────────┐
│ Your AI clients (any of them) │
│ Claude Desktop · Cursor · Windsurf · ChatGPT · … │
└─────────────────────────────┬──────────────────────────────────────┘
│ one MCP endpoint, one auth token
▼
┌────────────────────────────────────────────────────────────────────┐
│ Kebab MCP (your Vercel deploy) │
│ │
│ /api/mcp → registry → 97+ tools across 17 connectors │
│ │
│ Dashboard at /config: enable connectors, write Skills, │
│ add custom HTTP API tools, watch live logs. │
└─────────────────────────────┬──────────────────────────────────────┘
│ your tokens, never ours
▼
┌────────────────────────────────────────────────────────────────────┐
│ Google Workspace · Slack · Notion · Obsidian · GitHub · Linear │
│ Airtable · Browser (Browserbase) · Apify · Composio · … │
└────────────────────────────────────────────────────────────────────┘
What it is. A self-hosted MCP server framework that ships with 97+ pre-built tools across 17 connectors. Deploys to Vercel free tier. Open-source, AGPL-3.0.
Why it exists. Every AI client wants its own MCP server. Five clients × five tool sources = 25 half-broken integrations. Kebab is one backend that every client talks to.
What you get:
- ✅ One deploy, one endpoint — every AI client speaks to the same
https://your-fork.vercel.app/api/mcp - ✅ 97+ tools, no code — Gmail, Calendar, Drive, Slack, Notion, Obsidian, GitHub, Linear, Airtable, Apify, Browser, Unipile (LinkedIn + WhatsApp), paywalled articles, custom Skills, custom HTTP APIs
- ✅ Your tokens, your KV — credentials live in your Upstash; we have no servers, no telemetry, no lock-in
- ✅ Dashboard included — enable/disable connectors live, run any tool from the playground, write Skills in markdown, watch logs
Who it's not for. If you only need one MCP integration (e.g. just Gmail), grab the official one. Kebab earns its keep at ≥ 3 tool sources or ≥ 2 AI clients.
Who is this for?
- Solo builders who use Claude / Cursor / ChatGPT side-by-side and want one tool set everywhere.
- Small ops teams that need an internal AI backend wired to Slack / Notion / Linear / Google Workspace without paying per seat.
- Privacy-minded developers who'd rather hand their OAuth refresh tokens to their own Vercel project than to a third party.
If you just want a single MCP integration, you don't need this — pick the official one. Kebab earns its keep when you have ≥ 3 tool sources or ≥ 2 AI clients.
Why Kebab MCP?
| Kebab MCP | Separate MCP servers | Hosted platforms | |
|---|---|---|---|
| Setup | Fork + env vars + deploy | 5 repos, 5 configs | Sign up + monthly fee |
| Tools | 97+ pre-built | Build your own | 1000s (but vendor lock-in) |
| Endpoint | 1 | 5+ | 1 (their server) |
| Cost | Free (Vercel free tier) | Free but complex | $0–80/month |
| Data | Your Vercel, your keys | Your machines | Their servers |
Quick Start
Two paths cover ~95% of users — Fork + Vercel for the recommended path, Docker for full control. The CLI installer is tucked under the "more" toggle.
Option A — Fork + Deploy on Vercel (recommended)
The deploy hub at /deploy walks through this visually. The flow:
- Fork on GitHub — keeps your deployment linked to upstream so updates land in one click.
- Import to Vercel — pick your fork from the list, click Import, keep all defaults, click Deploy.
- Attach Upstash KV — after the first deploy completes, open your project → Storage tab → Connect Database → Upstash for Redis (Free plan). Vercel injects the env vars and auto-redeploys. Without this, your auth token and credentials don't survive serverless cold starts.
- Open the deployed URL → land on
/welcome, mint yourMCP_AUTH_TOKEN, paste it into your AI client.
Why not the one-click Deploy Button? Vercel's
/new/clonecreates a standalone snapshot — not a real GitHub fork — so the dashboard's Update now flow can never sync upstream changes. We tried it and reverted (case study: docs/TROUBLESHOOTING.md). The fork-first flow takes one extra click and stays maintainable forever.
"I see 'Admin auth not configured' after deploy" — You're on a cold lambda that hasn't rehydrated MCP_AUTH_TOKEN from Upstash. Confirm the KV integration is attached (or paste the token into the project's env vars) and reload. See docs/TROUBLESHOOTING.md (BUG-07, BUG-10, BUG-11).
"Which Upstash env vars should I set?" — Either UPSTASH_REDIS_REST_URL + UPSTASH_REDIS_REST_TOKEN (manual setup) or KV_REST_API_URL + KV_REST_API_TOKEN (Vercel Marketplace integration, auto-injected). If both, UPSTASH_REDIS_REST_* wins.
"What does MYMCP_RECOVERY_RESET=1 do?" — Wipes persisted bootstrap state and forces a fresh welcome. Do NOT set it permanently — every cold lambda wipes state, so any token minted while the var is set vanishes. See BUG-05.
"Welcome flow loops me back to /welcome" — Usually KV not configured + MYMCP_ALLOW_EPHEMERAL_SECRET=1 unset, cold-lambda rehydrate failing silently, or INSTANCE_MODE=showcase accidentally set. Full index: docs/TROUBLESHOOTING.md.
Option B — Self-hosted (Docker or local dev)
git clone https://github.com/Yassinello/kebab-mcp.git
cd kebab-mcp
cp .env.example .env # Fill MCP_AUTH_TOKEN at minimum
# Docker
docker compose up
# Or local dev
npm install && npm run dev
Dashboard at http://localhost:3000/config?token=<your-token>, MCP endpoint at http://localhost:3000/api/mcp.
See .env.example for every env var. Connectors auto-activate when their credentials are present — no toggling needed.
npx @yassinello/create-kebab-mcp@latest
Five-step CLI: project setup → clone → pick connectors → paste credentials → install & deploy. Leaves you with a working .env, installed deps, and an upstream remote for future npm run update.
You can also ask Claude in a Claude Code conversation: "Run npx @yassinello/create-kebab-mcp@latest and help me set up Kebab MCP." Claude can then wire the resulting endpoint into your client config.
Connect your AI client
Claude Desktop — ~/Library/Application Support/Claude/claude_desktop_config.json (Mac) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"kebab": {
"url": "https://your-app.vercel.app/api/mcp",
"headers": { "Authorization": "Bearer YOUR_MCP_AUTH_TOKEN" }
}
}
}
Claude Code — ~/.claude.json (global) or .mcp.json (per-project):
{
"mcpServers": {
"kebab": {
"type": "http",
"url": "https://your-app.vercel.app/api/mcp",
"headers": { "Authorization": "Bearer YOUR_MCP_AUTH_TOKEN" }
}
}
}
Cursor — ~/.cursor/mcp.json (global) or .cursor/mcp.json (per-project): same shape as Claude Desktop.
Windsurf — ~/.codeium/windsurf/mcp_config.json: same shape, but the URL field is named serverUrl.
ChatGPT / Other MCP clients — POST to https://your-app.vercel.app/api/mcp with Authorization: Bearer YOUR_MCP_AUTH_TOKEN.
Features
Five families of capability. Each connector auto-activates when its credentials are in your env.
🔌 Connectors — 17 built-in integrations
Google Workspace, Obsidian Vault, Slack, Notion, GitHub, Linear, Airtable, Browser Automation, Apify (LinkedIn reads), Unipile (LinkedIn + WhatsApp), Composio (1000+ apps via bridge), Paywall Readers, Webhooks. 97+ production-ready tools total. Setup is one env var per connector.
🛠️ Custom Tools — bring any HTTP API
API Connections turns any HTTP endpoint into an MCP tool — paste an OpenAPI spec or wire a REST endpoint, define the auth, ship. No code, no PR. Useful for internal APIs, niche SaaS, or quick experiments.
⚡ Skills — prompt-powered workflows
Skills are user-defined tools built from prompt templates. Compose existing tools in the dashboard's visual wizard, save, and the skill becomes skill_<name> in your MCP client. Versioned — every edit is a new revision, with one-click rollback.
📊 Dashboard & Ops
Unified /config page covers connector status, per-tool toggles, live logs, deep health checks, OAuth flows, Skill composer, API playground, and one-click upstream updates. The Welcome wizard handles first-run token minting and credential collection.
🔒 Security & Ownership
Self-hosted by design. Timing-safe token comparison, multi-tenant auth, per-token rate limits, SSRF protection on browser tools, HMAC validation on webhooks, env-only configuration (no config files, git pull never conflicts), HttpOnly OAuth cookies with PKCE.
| Connector | Tools | Auth | Setup |
|---|---|---|---|
| Google Workspace | 18 | OAuth | 5 min |
| Obsidian Vault | 14 | GitHub PAT | 2 min |
| Browser Automation | 7 | Browserbase + OpenRouter | 3 min |
| Slack | 6 | Bot token | 2 min |
| Notion | 5 | Integration token | 2 min |
| Apify (LinkedIn) | 10 | API token | 1 min |
| Unipile (LinkedIn + WhatsApp) | 10 | DSN + token | 3 min |
| GitHub Issues | 6 | PAT | 1 min |
| Linear | 6 | API key | 1 min |
| Airtable | 7 | PAT | 1 min |
| Composio | 2 | API key (1000+ apps via the bridge) | 2 min |
| Paywall Readers | 1 (+1 w/ Browser) | — | 0 min |
| Webhook Receiver | 3 | Optional HMAC | 0 min |
| Skills | dyn. | — | 0 min |
| API Connections | dyn. | per-API | 1 min |
| Custom Tools | dyn. | — | 1 min |
| Admin & Logs | 5 | Admin token | 0 min |
Per-tool details and env vars: docs/CONNECTORS.md.
Use Cases
A few prompts to give you the shape of what's possible:
- Daily ops dashboard — "Summarize this week's calendar conflicts, group my unread Slack threads by channel, and create a Linear issue for each unresolved thread."
- Inbox triage — "Find every email from this customer in the last 30 days, summarize the request, and draft a response — but don't send it."
- Research → notes — "Search LinkedIn for product managers in the seed-stage SaaS space, extract their last 3 posts, and append the digest to my Obsidian daily note."
Configuration
All configuration is via environment variables. Full reference: .env.example.
Auth
| Variable | Required | Description |
|---|---|---|
MCP_AUTH_TOKEN |
Yes | Bearer token(s) for MCP endpoint — supports comma-separated list |
ADMIN_AUTH_TOKEN |
No | Separate token for dashboard (falls back to MCP_AUTH_TOKEN) |
MCP_AUTH_TOKEN accepts a comma-separated list of tokens, one per MCP client. Each token must be ≥ 16 characters. An 8-character SHA-256 hash prefix is stored with every log entry so you can identify which client made each call — without logging the token itself.
Instance settings
v0.12 renamed the env-var prefix from MYMCP_* to KEBAB_*. Both are accepted during the 2-release transition; the operator sees one boot-time deprecation warning per legacy variable. See CHANGELOG § v0.12 migration guide.
| Variable | Legacy | Default | Description |
|---|---|---|---|
KEBAB_TIMEZONE |
MYMCP_TIMEZONE |
UTC |
Timezone for date formatting |
KEBAB_LOCALE |
MYMCP_LOCALE |
en-US |
Locale for date/number formatting |
KEBAB_DISPLAY_NAME |
MYMCP_DISPLAY_NAME |
User |
Display name in dashboard |
KEBAB_CONTEXT_PATH |
MYMCP_CONTEXT_PATH |
System/context.md |
Path to context file in vault |
KEBAB_TOOL_TIMEOUT |
MYMCP_TOOL_TIMEOUT |
30000 |
Tool timeout in ms |
KEBAB_ERROR_WEBHOOK_URL |
MYMCP_ERROR_WEBHOOK_URL |
— | Webhook for error alerts |
Connector control
Connectors activate automatically when their credentials are present. Override with:
KEBAB_DISABLE_GOOGLE=true # Force-disable even with credentials
KEBAB_ENABLED_PACKS=vault,admin # Only listed connectors are considered
Architecture
src/
core/ ← Framework: types, registry, config, auth, logging, events
connectors/
google/ ← Google Workspace (21+ tools)
manifest.ts ← Connector definition (single source of truth)
lib/ ← Gmail, Calendar, Contacts, Drive, Chat wrappers
tools/ ← Individual tool handlers
vault/ ← Obsidian Vault (14 tools)
browser/ slack/ notion/ apify/ paywall/ composio/
github/ linear/ airtable/ webhook/ skills/ admin/
app/
api/mcp ← MCP endpoint (~30 lines — reads from registry)
api/health ← Public liveness + deep health checks
api/admin/* ← Private: status, stats, verify, call (auth-gated)
api/webhook/* ← Inbound webhook receiver
/welcome ← Guided onboarding
/config ← Unified dashboard
How it works: each connector has a manifest.ts declaring its tools and required env vars. The registry checks env vars and determines which connectors are active. route.ts iterates enabled connectors and registers tools via the MCP SDK. Everything — dashboard, health, admin API — derives from the same manifests.
Design principles: env vars only (no config files, git pull never conflicts) · single source of truth (manifests drive registration, dashboard, docs) · framework vs instance separation (zero personal references in code) · contract-level compatibility (same tool names and schemas across versions).
Development
npm run dev # Start dev server
npm run build # Production build
npm run lint # ESLint
npm run format # Prettier
npm run test:contract # Verify tool contracts
npm run test:e2e # Playwright welcome-flow E2E
Pre-commit hook (Husky): lint-staged + contract test. Tooling configs (size-limit.json, knip.ts) live under config/.
API endpoints
| Endpoint | Auth | Description |
|---|---|---|
POST /api/mcp |
MCP_AUTH_TOKEN | MCP Streamable HTTP |
GET /api/health |
Public | { ok, version } — add ?deep=1 for connector diagnostics |
GET /api/admin/status |
Admin | Connector diagnostics + diagnose() results |
GET /api/admin/stats |
Admin | Tool usage analytics |
POST /api/admin/call |
Admin | Invoke any tool (playground API) |
POST /api/webhook/:name |
Webhook secret | Inbound webhook receiver |
GET /api/cron/health |
Cron | Scheduled health check + webhook alert |
Full reference: docs/API.md.
Security
| Layer | Protection |
|---|---|
| Auth | Timing-safe token comparison (MCP + Admin), multi-tenant support |
| SSRF | Browser tools block localhost, private IPs (v4+v6), cloud metadata |
| Errors | API keys stripped from error messages |
| Rate limiting | Per-token RPM cap (configurable), LinkedIn feed: 3 calls/day |
| OAuth | State parameter validation, PKCE, HttpOnly cookies |
| Dashboard | Private by default — all admin routes require auth |
| Webhooks | HMAC-SHA256 signature validation (opt-in per webhook) |
| CI | ESLint (no-any enforced), Prettier, Vitest, contract tests, build checks |
Updates & durability
Kebab MCP is a template repository. Your copy is standalone — it won't auto-update. The right path depends on where you run it:
| Where you run it | How updates work |
|---|---|
| Vercel (most users) | One-click sync from the dashboard via GitHub's API — no terminal needed |
| Local dev | Auto-pull on every dev server start (silent, fast-forward only) |
| Docker / self-hosted | npm run update (or git fetch upstream && git merge upstream/main) |
The Vercel dashboard runs a daily cron at 8h UTC that pre-fetches upstream status, so the Overview banner loads instantly. Your .env, data/, and saved credentials in Upstash KV are never touched — all customization lives in env vars.
Disable the in-dashboard update feature with KEBAB_DISABLE_UPDATE_API=1. Smoke-test recipe: docs/TROUBLESHOOTING.md § Phase 61 update flow.
Community & Roadmap
- GitHub Discussions — questions, ideas, feedback: github.com/Yassinello/kebab-mcp/discussions
- GitHub Issues — bugs and feature requests: github.com/Yassinello/kebab-mcp/issues
Roadmap (subject to change):
- Cloudflare Workers deploy target
- Stripe + Plaid connectors
- Web UI for Skills authoring
- Multi-tenant mode (single deploy, multiple users)
Shipped releases: docs/CHANGELOG.md.
Contributing
See docs/CONTRIBUTING.md for how to add tools, connectors, and custom extensions. Quick version: create a file in src/connectors/<connector>/tools/, add it to the connector's manifest.ts. Done.
Documentation
Ordered by reader journey — discover, deploy, use, author, contribute.
- docs/API.md — route-by-route API reference (all 42 endpoints)
- docs/CONNECTORS.md — per-connector setup and env var reference
- docs/CONNECTOR-AUTHORING.md — zero-to-live authoring walkthrough
- docs/HOSTING.md — host compatibility matrix (Vercel, Docker, Fly, Render, Cloud Run, bare-metal) + degraded-mode contract
- docs/TROUBLESHOOTING.md — symptom → fix index for every shipped bug + security finding
- docs/SECURITY-ADVISORIES.md — published advisory index
- docs/CONTRIBUTING.md — contribution guide + coverage philosophy
- docs/CHANGELOG.md — version history
- docs/SECURITY.md — vulnerability reporting
- docs/ARCHITECTURE.md — developer / fork-maintainer guide (durable bootstrap pattern, conventions, env-var reference)
Tech Stack
Next.js 16 · TypeScript 6 · Zod 4 · MCP SDK · Vercel Serverless · Arctic (OAuth) · Stagehand + Browserbase · Apify SDK
No comments yet
Be the first to share your take.