tapflow
팀 전체가 사용할 수 있는 자체 호스팅 iOS·Android 시뮬레이터 스트리밍
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A remote MCP server that lets Meta Muse (and, with the same code, Claude and ChatGPT) book Strategent's free AI Readiness Audit. Scheduling runs on Cal.com. Every lead lands in one Supabase table and in Slack.
Muse -> POST /mcp (OAuth bearer) -> 4 tools -> Cal.com API (availability, booking)
-> Supabase (audit_requests, tool_logs)
-> Slack + email (lead alert)
Status: code complete and tested against fakes and a mocked Cal.com (130 tests). The Cal.com client has been run
live (27 Oct 2026): npm run cal:setup and one real test booking, made through the same src/cal.ts client the
server uses. Not yet run live: the deployed server, OAuth, Supabase, Slack, email, or Muse.
| Tool | What it does | Writes |
|---|---|---|
check_audit_availability | Up to 8 open 30-minute slots in the next 14 days, in the user's timezone | nothing |
book_audit_call | Books a slot in Cal.com, saves the lead, alerts the team | Cal.com, Supabase, Slack, email |
request_written_audit | Saves a written-audit request, alerts the team | Supabase, Slack, email |
get_audit_request_status | Status of requests made through the same connection | nothing |
Descriptions are in src/copy.ts, verbatim from the brief. All brand copy lives in that one file.
POST /mcp streamable HTTP, stateless, JSON responsesGET /.well-known/oauth-authorization-server, GET /.well-known/oauth-protected-resourcePOST /oauth/register (dynamic client registration), GET|POST /oauth/authorize, POST /oauth/tokenGET /privacy, GET /terms redirect to the privacy policy and terms of service on strategent.app (/privacy-policy
and /terms-of-service). The sign-in page and the OAuth metadata link to the same pages.POST /webhooks/cal Cal.com webhook receiver for reschedules and cancellations (signed; off until CAL_WEBHOOK_SECRET is set)GET /cron/retention daily retention cleanup (Vercel Cron; needs CRON_SECRET, see "Retention cleanup")GET /healthGET /docs: public documentation page (endpoint, sign-in, tools, limits). Give this URL to Muse as the API or MCP documentation link.Cal.com (Ruchi). Create the event type AI Readiness Audit: 30 minutes, URL slug audit, location Google
Meet (install and connect the Google Calendar app first so Meet is available). In the event's Limits settings:
buffer after 15 minutes, minimum notice 4 hours, max 3 bookings per day. Set the availability schedule to the hours
you and Nico actually hold. Host: you alone. Then create an API key (Settings, Developer, API keys) and share it
through 1Password only.
Menu names are from memory; Cal.com moves things around.
Already done for the Strategent account (26 Oct 2026, through the Cal.com connector): event type
AI Readiness Audit exists with id 7650820, slug audit, 30 minutes, Google Meet, 15 minute buffer after,
4 hour minimum notice, max 3 per day, and all seven booking questions as optional text fields. It uses a new
schedule, "Audit calls" (id 2556615): Mon, Tue, Thu, Fri, 10am to 4pm Pacific. The account username was renamed
from strategent-eykb5a to strategent on 27 Oct 2026, so the public page is cal.com/strategent/audit (the old
URL now returns 404). The API key exists; it still needs to go into the host's environment variables.
First live check. CAL_API_KEY=... npm run cal:setup confirms the key and lists event types with their ids.
Set CAL_EVENT_TYPE_ID and BOOKING_PAGE_URL (your public booking page, for example cal.com/yourname/audit) and
run it again. Then:
npm run cal:setup -- --create-fields adds the seven booking questions to the event type (all optional), through
Cal.com's API, so nobody has to click them in. They are: business name, website, city, industry, what is taking
the most time, phone, and where to start with AI.npm run cal:setup -- --book [email protected] makes one real test booking. Check three things: the booking
succeeds, the Meet link appears, and the printed reschedule and cancel links open (see "Not verified"). Cancel
the test booking afterwards.Supabase. Run supabase/schema.sql in the SQL editor. Copy the project URL and service-role key.
Slack and email. Create #leads and add an incoming webhook. Create a Resend key and verify the sending domain.
Deploy. Vercel: import the repo, set the variables from .env.example, add the domain connect.strategent.app.
routes everything to and sets (the "Other" preset). Without that,
Vercel auto-detects Hono and the build fails with .
pins to , which also keeps that line out of the build log.
Any Node host also works: serves on .
Generate with .
Optional: reminder emails (24 hours and 1 hour before) are a Cal.com setting (Workflows). Whether that needs a paid plan is not verified.
When someone reschedules or cancels through the Cal.com links, Cal.com tells the connector, which updates the lead in
Supabase (new time, booking uid and links, or status cancelled) and emails the team (and posts to Slack when that is
set up). Without this the lead keeps showing the old time.
openssl rand -base64 48, or in PowerShell
$b = New-Object byte[] 48; (New-Object System.Security.Cryptography.RNGCryptoServiceProvider).GetBytes($b); [Convert]::ToBase64String($b) | Set-Clipboard).CAL_WEBHOOK_SECRET (Production, Sensitive) and redeploy./settings/developer/webhooks) and create a webhook:
subscriber URL https://connect.strategent.app/webhooks/cal, the same secret, and the triggers Booking
rescheduled and Booking cancelled only. A webhook there covers all your booking links, which is fine because
the connector ignores bookings it did not create; Cal.com can also attach one to a single event type.[cal-webhook] line per delivery.Cal.com signs each delivery with HMAC-SHA256 of the raw body in the x-cal-signature-256 header. The connector rejects
anything without a valid signature, ignores bookings it did not create, and treats a repeated delivery as already done.
If a change cannot be saved (for example it would clash with another booked call), the team gets an email to fix the
lead by hand.
See .env.example. Required: SIGNING_SECRET, CAL_API_KEY, CAL_EVENT_TYPE_ID, BOOKING_PAGE_URL,
SUPABASE_URL, SUPABASE_SERVICE_KEY. The server refuses to start and lists what is missing.
GET /v2/slots with eventTypeId, start, end (version 2024-09-04). Slots come grouped by
date. Cal.com documents no maximum range, so the client asks a week at a time and merges.POST /v2/bookings (version 2026-02-25) with the attendee, the Google Meet location, and the answers in
bookingFieldsResponses, keyed by question slug. The write is never retried, so a flaky response cannot double book.2026-06-12.src/cal.ts, and tests assert the exact strings. If Cal.com changes
defaults, nothing shifts silently.src/cal.ts and src/calAdmin.ts talks to the scheduler through src/scheduler.ts.
Changing provider again means rewriting those files, not the tools.src/oauth.ts; the tools only need a Principal./.well-known/oauth-protected-resource and sends WWW-Authenticate on 401, as the MCP
spec requires. The brief's endpoint list omitted it.start, end, timezone and an optional part_of_day instead of one date_range.slot_token, name, email, business_name. Written audit needs
name, email, business_name, and website or city. Everything else is optional.industry and channel_interest are free text in the schema, normalised on the server (channel_interest uses
back_office). A model that sends "hotel" gets "Hospitality" instead of an error. In Cal.com they are plain text
questions rather than dropdowns, because Cal.com's select options need exact values we cannot confirm without a
live call. Upgrade them to dropdowns later if you want cleaner data from direct bookers.get_audit_request_status only sees requests made through the same connection, so knowing an email address
reveals nothing about anyone else. The cost: after reconnecting, earlier requests no longer show.check_audit_availability tells the model to offer a written audit. book_audit_call saves a
call_pending lead and promises a call time by email. request_written_audit accepts wants_call_time for the same
case.{ "<date>": [{ "start": "<ISO with offset>" }] }, which is what
src/cal.ts parses. Wednesday is correctly empty.npm run cal:setup signs in, lists the event types, and finds all seven booking questions present, so
--create-fields had nothing to add.createBooking succeeded: a Google Meet link was returned, the confirmation email arrived
with the right event, time and description, and every booking answer was stored. The test booking has been cancelled.https://cal.com/reschedule/{uid} and
https://cal.com/booking/{uid}?cancel=true) both work, so RESCHEDULE_URL_TEMPLATE and CANCEL_URL_TEMPLATE need
no override.src/cal.ts follow
the assumptions above, not an observed Cal.com error.HTTPS_PROXY. Run with
NODE_USE_ENV_PROXY=1 (Node 22.21 or later). Not needed on a normal machine or on Vercel.pending booking. It is treated as booked, but the host would
still need to confirm. Leave "requires confirmation" off for this event.call_pending and the
Slack alert says to check the calendar for a duplicate.isError results. Set ALLOWED_REDIRECT_HOSTS once the domain is known.cancelled. All three alert
emails (new call, rescheduled, cancelled) reached the inbox. On a reschedule Cal.com sends only
BOOKING_RESCHEDULED, not a BOOKING_CANCELLED for the old booking, so there is no duplicate alert. The handler
would still end in the right state if that ever changed (a later reschedule restores the request), but the team would
then get one spurious "cancelled" email.The privacy policy (sections 3.5 and 10) and the Muse data questionnaire promise that audit requests and connector
activity logs are kept 12 months. GET /cron/retention enforces that. Vercel Cron calls it daily at 03:17 UTC
(vercel.json), and it deletes:
audit_requests created more than 12 months ago (a request with a call still in the future is kept),tool_logs created more than 12 months ago,oauth_used_ids (replaces the optional pg_cron job in supabase/schema.sql).To turn it on, add CRON_SECRET to Vercel (Production, Sensitive, any random 32+ character string) and redeploy.
Vercel sends it as Authorization: Bearer ... on each run; without it the endpoint answers 503 and nothing runs. The job
logs only counts. If a run fails, the team gets a "Retention cleanup failed" email. Cron jobs run on production
deployments only, and the Hobby plan allows one run per day.
The periods live in RETENTION_MONTHS in src/retention.ts. Change the policy text first, then the numbers. Calendar
and booking records held by Cal.com and Google follow those providers' own retention, as the policy says.
Descriptions are verbatim from the brief. Two additions are worth considering because Muse matches on this text:
check_audit_availability description.
Today the local intent appears only in the listing and the booking confirmation.The region lists (src/region.ts) decide which leads get the LOCAL tag in Slack. Inglewood is currently la_other.
npm install
npm test # no network needed
npm run typecheck
npm run dev # needs real credentials; use the tests for offline work
Layout: src/tools.ts (all booking logic), src/scheduler.ts (provider interface), src/cal.ts (Cal.com client),
src/calAdmin.ts (setup helpers), src/oauth.ts, src/store.ts, src/notify.ts, src/mcp.ts (tool registration and
logging), src/app.ts (routes), test/ (fakes in test/helpers.ts).
vercel.jsonapi/index.ts"framework": nullTS2688: Cannot find type definition file for 'node'tsconfig.jsontypeRoots./node_modules/@typesnpm startPORTSIGNING_SECRETopenssl rand -base64 48Smoke test. curl https://connect.strategent.app/health, then open /.well-known/oauth-authorization-server.
An unauthenticated POST /mcp must return 401 with a WWW-Authenticate header.
Add to Muse. Settings, Connectors, Add custom connector, URL https://connect.strategent.app/mcp. Then run the
edge-case checklist from the brief in a live session. The automated version of that list is in
test/tools.test.ts (tests marked [checklist]).
Submit at muse.ai/platform with the listing copy from the brief, the privacy and terms links, and a 60-second recording of a booking.
WRITTEN_OPEN_CAPSEND_REQUESTER_ACK).muse, claude, chatgpt) from the registered client name.BOOKING_PAGE_URL. The brief's copy pointed at a Calendly page, so that line of
copy changed. Ruchi should approve the new link.