Spec Driven Development
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
제작자가 쓴 설명(영어 원문)
A webhook URL that wakes your AI agent: every POST to it wakes the conversation watching it.
이 세 가지는 절대 하나의 점수로 합치지 않아요. 의견, 측정, 인기는 서로 다른 것이니까요.
이 서버는 아직 쉬운 말로 된 요약을 쓰지 못했어요. 아래는 레지스트리에서 읽어 온 사실이에요.
쓰고 있는 AI 앱을 고른 다음 설정을 복사하세요.
필요한 것
어떤 앱을 쓰세요?
위에서 앱을 고르세요. 기억해 두었다가 다음부터는 버튼에 “…에 설치”라고 표시해요.
웹, 데스크톱, 모바일의 Claude에서 쓸 수 있어요:
https://try.wakeshift.ai/t/{link}/mcp주소에 나만 아는 {…} 부분(예: 내 계정)이 있어서, 복사한 뒤 직접 채워 주세요.
터미널에서 이 명령어를 실행하세요
claude mcp add --transport http webhooks 'https://try.wakeshift.ai/t/{link}/mcp'주소에 나만 아는 {…} 부분(예: 내 계정)이 있어서, 복사한 뒤 직접 채워 주세요.
프로젝트의 .cursor/mcp.json 또는 ~/.cursor/mcp.json에 붙여 넣으세요
{
"mcpServers": {
"webhooks": {
"url": "https://try.wakeshift.ai/t/{link}/mcp"
}
}
}브라우저가 앱을 열지 물어본 다음, 앱이 설정을 보여 주고 확인을 요청해요. 키 값은 비워 두니 직접 입력하세요.
주소에 나만 아는 {…} 부분(예: 내 계정)이 있어서, 복사한 뒤 직접 채워 주세요.
프로젝트의 .vscode/mcp.json에 붙여 넣으세요
{
"servers": {
"webhooks": {
"type": "http",
"url": "https://try.wakeshift.ai/t/{link}/mcp"
}
}
}브라우저가 앱을 열지 물어본 다음, 앱이 설정을 보여 주고 확인을 요청해요. 키 값은 비워 두니 직접 입력하세요.
ChatGPT는 인터넷에 있는 서버에만 연결할 수 있어요:
https://try.wakeshift.ai/t/{link}/mcp주소에 나만 아는 {…} 부분(예: 내 계정)이 있어서, 복사한 뒤 직접 채워 주세요.
메뉴 이름은 요금제나 시기에 따라 조금 다를 수 있어요.
선택한 앱은 이 기기의 쿠키에만 저장돼요. 계정은 필요 없어요.
이 설정은 제작자의 레지스트리 정보로 만들었어요. README와 다르면 README를 따르세요.
주소에 내 값이 필요해서 대신 도구 목록을 읽을 수 없어요.
누구나 볼 수 있는 정보를 점검했고, 코드는 읽지 않았어요. 해당하지 않는 항목은 개수에서 뺐어요. · 2026년 11월 6일 점검
레지스트리 이름이 도메인 wakeshift.ai 기준으로 확인되었어요(레지스트리가 도메인 소유를 확인해요)
아직 GitHub에서 이 저장소를 읽어 오지 않았어요
아직 GitHub에서 이 저장소를 읽어 오지 않았어요
주소에 내 계정 값이 필요해서 대신 점검할 수 없어요
주소에 내 계정 값이 필요해서 대신 점검할 수 없어요
아직 점검하지 않았어요. 엔드포인트를 점검할 때 도구 목록을 읽어요
레지스트리에서 이 카테고리의 활성 서버 전체와 비교했어요. 스타는 게시자가 저장소를 소유한 경우에만 세요.
해당하는 기본 점검 1개 중 1개를 통과했어요. 코드는 읽지 않았어요. 키나 토큰을 넣기 전에 서버가 어떤 권한을 요구하는지 확인하고, 꼭 필요한 권한만 있는 키를 쓰세요.
레지스트리에 필수 키가 나와 있지 않아요. 다만 처음 쓸 때 로그인을 요구하는 서버도 있어요.
제작자의 클라우드에서 실행돼요. 설치 없이 인터넷으로 연결하지만, 보내는 내용은 제작자의 서버를 거쳐요.
GitHub 저장소는 마지막으로 – 변경됐고, 최신 버전(1.0.0)은 그저께 레지스트리에 올라왔어요.
Claude Desktop, Claude Code, Cursor, VS Code처럼 MCP를 지원하는 앱에서 쓸 수 있어요. URL로 연결되기 때문에, 원격 MCP 서버를 지원하는 앱(예: 개발자 모드의 ChatGPT)에서도 쓸 수 있어요.
같은 카테고리에는: Spec Driven Development, Remote Desktop Commander, zanadir
같은 카테고리에서 다른 제작자가 만든 서버예요. 스타 순으로 정렬했어요.
카드 보는 법:★ GitHub 스타i세 기둥: 리뷰 · 점검 · 사용 정도i업데이트 = 최신 버전을 레지스트리에 공개한 날i
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Remote Desktop Commander: use files, terminal and processes on your own computers from any AI app.
Find what a repository's CI is missing, and which security checks cannot fail the build.
제작자의 저장소에서 쓰인 그대로 가져왔어요. PopNx MCP가 검토하거나 보증한 내용이 아니에요. HTML, 이미지, 스크립트는 제거했어요. 링크를 누르면 이 사이트를 벗어나요.
A webhook URL that wakes your agent: get a link, add it to your agent (Claude Code, Codex, Cursor, Antigravity, opencode, Copilot CLI or any MCP client), ask the agent to watch, and every POST to your webhook URL (curl, Postman, GitHub, Stripe, Linear, your own app) wakes it. Wakeshift runs it at try.wakeshift.ai. Built on the TypeScript SDK, @wakeshift/sdk.
TRY_SECRET and names a random webhook ID and when it was made. The MCP URL (/t/ /mcp), the page (/l/ ), the webhook URLs (/in/ , one token per signature check) and the signing secret are all derived from it. Nothing is stored. A link expires after 7 days without use; when it was last used is kept in the database (written at most every 5 minutes per instance). When it expires, Wakeshift is asked to forget the webhook (forgetUser with the webhook ID, which is the app's user for it): its workspace, the conversations that watched it, their subscriptions and deliveries. The sweep queues it in the database in the transaction that deletes the link's own rows, and every instance works the queue every 10 minutes, retrying a failure with backoff (a minute, doubling, at most 6 hours) until Wakeshift says it's done.webhook.received (argument: the webhook's ID; only the webhook's own SDK user, anyone with its link, may subscribe) carries what was posted: summary, a line saying what happened, then the parsed body and the headers that say who sent it. Every tool is wrapped with attached.events (the handle wake.attach returns), and takes Wakeshift's arguments through attached.inputs. watch subscribes the calling conversation with call.subscribe; unwatch ends it with call.unsubscribe. The wrapper adds one Wakeshift block to each tool's result: how the conversation is woken after a subscribe, pending messages and a Codex thread's beacon otherwise. A call that fails ends the subscription it made. A client that speaks MCP Events (ChatGPT) gets no conversation subscription: the block tells it to subscribe to webhook.received itself. A post becomes event.emit. wake.attach adds subscribe_events, unsubscribe_events and list_subscriptions.Mcp-Session-Id, and each request builds the MCP server afresh from them on whichever instance it reaches (the SDK's transport in stateless mode; the session ID is checked here, 404 if unknown or another link's). So sessions survive restarts and need no affinity, and the client's name and capabilities (which decide how Cursor, opencode and the rest are woken, and whether a client subscribes itself) are right on every instance: the rebuilt server answers getClientVersion and getClientCapabilities from the stored initialize, and the wrapper reads them. Sessions idle for 7 days are dropped (the client initializes again). Tools: watch, unwatch, recent_posts, webhook_info.POST, PUT or PATCH /in/ , any body up to 64 KB. The event's text says what happened: for GitHub (from X-GitHub-Event) GitHub workflow_run completed: failure on main (tests) in acme/api; for Stripe Stripe invoice.payment_failed: in_…, USD 49.00, open (evt_…, test mode); for Linear Linear Issue create: ENG-123 Checkout page 500s; for anything else POST to your webhook (with (empty body) if it was), since the data has the rest: the text doesn't repeat the body, so a small post's data fits on one Monitor line (480 bytes) in full. Its data is the parsed body (body, or body_base64), the method, content type, a few headers that say who sent it (including Linear-Event and Linear-Delivery; never Authorization, cookies or signatures) and, for Stripe and Linear, source (the event type and ID). Retries are one publish: by Idempotency-Key, X-GitHub-Delivery, Linear-Delivery, or a Stripe event's evt_ ID. On a GitHub, Stripe or Linear URL only the service's own ID counts (Idempotency-Key isn't signed, so a captured delivery replayed with a fresh one would wake the agent again); a Stripe URL uses only the evt_ ID from the signed body. GET explains how to post; a body more than 256 KB over the limit has its connection dropped rather than read.X-Hub-Signature-256 and Authorization: Bearer use secrets derived per webhook and per check (try_gh_…, try_bearer_…). Stripe and Linear make their own secret: the user pastes it into the page, and it's sealed into that URL's token (AES-256-GCM with a key derived from TRY_SECRET). It's stored only in that form: the URL is kept as the webhook's checked URL (below) until the link expires. Stripe's Stripe-Signature (t=…,v1=…, HMAC-SHA256 of t.body) must be within 5 minutes; Linear's Linear-Signature (hex HMAC-SHA256 of the body) needs a webhookTimestamp within a minute.POST /l/ /rotate) replaces the open URL. Its token then carries the webhook's open-URL generation, kept per webhook in the database (hooks.open_gen), and a post or GET to an open URL of any other generation gets 410 (replaced), on every instance at once. The webhook ID (the SDK user, so its subscriptions), the link and MCP URL, the history and the checked URLs stay as they were, and the live view gets a line saying the URL changed. Only the link's code can ask (a webhook URL is a different capability, and can't), from this site's page: a request whose Origin or Sec-Fetch-Site says another site sent it gets 403. Ten an hour per webhook (429 past that).watch and webhook_info give the checked URL the user last picked (a GitHub or bearer tab they opened, a Stripe or Linear URL they made, or the URL a service last posted to), and say which check it uses. It's kept for as long as the link lives.Retry-After), so whoever has the open URL can't use up the checked one's. Refused posts (401, 413) don't count; retries do (each is still a request to Wakeshift, so a repeated Idempotency-Key can't get round the limits). 20,000 an hour across all webhooks, 30 new links an hour per address (an IPv6 address by its /64; kept as an HMAC of the address, for the hour). TRY_PER_HOUR, TRY_PER_DAY, TRY_GLOBAL_PER_HOUR and TRY_LINKS_PER_HOUR change them, and the terms and privacy policy state the limits in use.Retry-After and a plain message (JSON for webhooks, JSON-RPC for MCP, a page for pages), never a 500. A link's page still comes up when the database is slow, without its history; the live view retries and says so (below). Wakeshift's own 429 or 503 on publish becomes a 503 with Retry-After for the poster./l/ /live): each post (received, refused, rate limited, the start of what was posted, and how many watching conversations the publish reached), and each watch and unwatch. Lines are kept in the database (the last 50 per webhook) and reach pages on every instance by NOTIFY on the webhook's channel (try_ ; each instance LISTENs only for webhooks it has a page open for, and replays the recent lines whenever its connection comes back after a drop; it pings that connection every 30 seconds so a silent drop is noticed). A webhook's refused and rate-limited posts get at most 10 lines a minute per instance, so a flood of bad signatures doesn't push real posts out. The rest are counted, and once the minute is over (or the instance stops) each instance adds its count to the webhook's one line for that minute, which the page updates in place: one line a minute with the total across instances, written at most once a minute per webhook by each instance. A live view that doesn't keep up with what's written to it is dropped (EventSource reconnects). Each line goes with its seq as its SSE ID, and a live view asks for the lines after the newest it has (?after= , or Last-Event-ID when EventSource reconnects by itself), so after a gap it shows what happened meanwhile (as far as the last 50 go). When the server refuses it (429, 503), EventSource gives up; the page tries again after 2 seconds, doubling to 30 at most (randomized a little), back to 2 once connected, and at once when the page is looked at again, the network comes back or the status poll gets an answer (liveConnection in page.ts). The page shows who called watch, "sent to N watching conversations" per post, and whether an agent is connected right now and how (stream, hooks or polling): it polls /l/ /status every 10 seconds, which asks Wakeshift for webhook.received's status with the webhook's ID (event.status, read-only).wst_…).migrations/). (cd third_party/wakeshift-node && npm ci && npm run build)
cd webhooks && npm ci && npm run build
.env.example to .env, fill it in, and run it:| Variable | |
|---|---|
WAKESHIFT_KEY | The app's key from step 1 |
WAKESHIFT_CORE | Wakeshift's URL (default https://app.wakeshift.ai) |
TRY_SECRET | Signs links; 32 or more random bytes. Changing it ends every link |
TRY_DATABASE_URL | The database from step 2; every instance shares it |
TRY_DB_POOL | Connections per instance (default 3), plus one that listens for the live view |
PUBLIC_URL | Your copy's public URL (default http://localhost:$PORT) |
PORT | Listen port (default 8380) |
TRY_PROXY_HOPS | Proxies in front of it that append to X-Forwarded-For (Google's load balancer: 2); 0 uses the socket's address |
TRY_PER_HOUR, TRY_PER_DAY, TRY_GLOBAL_PER_HOUR, TRY_LINKS_PER_HOUR | Optional: the limits above |
set -a; . ./.env; set +a
npm start
PUBLIC_URL, get a link, and run the command its tab for your agent shows.npm run lint
npm test # unit tests; needs WAKESHIFT_TEST_DATABASE_URL, a Postgres URL for a role that can create databases
The end-to-end and load tests run Webhooks against the Wakeshift server, so they run in Wakeshift's own repository.
This repository is generated from Wakeshift's main repository. Pull requests are welcome: we apply them there and publish the result. See CONTRIBUTING.