Spec Driven Development
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
제작자가 쓴 설명(영어 원문)
Ask about your Dreambooth Studio photobooths: sessions, revenue, credits, projects, device status.
이 세 가지는 절대 하나의 점수로 합치지 않아요. 의견, 측정, 인기는 서로 다른 것이니까요.
이 서버는 아직 쉬운 말로 된 요약을 쓰지 못했어요. 아래는 레지스트리에서 읽어 온 사실이에요.
쓰고 있는 AI 앱을 고른 다음 설정을 복사하세요.
필요한 것
어떤 앱을 쓰세요?
위에서 앱을 고르세요. 기억해 두었다가 다음부터는 버튼에 “…에 설치”라고 표시해요.
웹, 데스크톱, 모바일의 Claude에서 쓸 수 있어요:
https://mcp.dreamboothstudio.com/mcp터미널에서 이 명령어를 실행하세요
claude mcp add --transport http dreambooth https://mcp.dreamboothstudio.com/mcp프로젝트의 .cursor/mcp.json 또는 ~/.cursor/mcp.json에 붙여 넣으세요
{
"mcpServers": {
"dreambooth": {
"url": "https://mcp.dreamboothstudio.com/mcp"
}
}
}브라우저가 앱을 열지 물어본 다음, 앱이 설정을 보여 주고 확인을 요청해요. 키 값은 비워 두니 직접 입력하세요.
프로젝트의 .vscode/mcp.json에 붙여 넣으세요
{
"servers": {
"dreambooth": {
"type": "http",
"url": "https://mcp.dreamboothstudio.com/mcp"
}
}
}브라우저가 앱을 열지 물어본 다음, 앱이 설정을 보여 주고 확인을 요청해요. 키 값은 비워 두니 직접 입력하세요.
ChatGPT는 인터넷에 있는 서버에만 연결할 수 있어요:
https://mcp.dreamboothstudio.com/mcp메뉴 이름은 요금제나 시기에 따라 조금 다를 수 있어요.
선택한 앱은 이 기기의 쿠키에만 저장돼요. 계정은 필요 없어요.
이 설정은 제작자의 레지스트리 정보로 만들었어요. README와 다르면 README를 따르세요.
아직 이 서버의 도구 목록을 읽지 않았어요. 엔드포인트는 차례대로 돌아가며 점검해요.
누구나 볼 수 있는 정보를 점검했고, 코드는 읽지 않았어요. 해당하지 않는 항목은 개수에서 뺐어요. · 2026년 11월 7일 점검
레지스트리 이름이 도메인 dreamboothstudio.com 기준으로 확인되었어요(레지스트리가 도메인 소유를 확인해요)
아직 GitHub에서 이 저장소를 읽어 오지 않았어요
아직 GitHub에서 이 저장소를 읽어 오지 않았어요
아직 점검하지 않았어요. 엔드포인트는 차례대로 돌아가며 점검해요
아직 점검하지 않았어요. 엔드포인트는 차례대로 돌아가며 점검해요
아직 점검하지 않았어요. 엔드포인트를 점검할 때 도구 목록을 읽어요
레지스트리에서 이 카테고리의 활성 서버 전체와 비교했어요. 스타는 게시자가 저장소를 소유한 경우에만 세요.
해당하는 기본 점검 1개 중 1개를 통과했어요. 코드는 읽지 않았어요. 키나 토큰을 넣기 전에 서버가 어떤 권한을 요구하는지 확인하고, 꼭 필요한 권한만 있는 키를 쓰세요.
레지스트리에 필수 키가 나와 있지 않아요. 다만 처음 쓸 때 로그인을 요구하는 서버도 있어요.
제작자의 클라우드에서 실행돼요. 설치 없이 인터넷으로 연결하지만, 보내는 내용은 제작자의 서버를 거쳐요.
GitHub 저장소는 마지막으로 – 변경됐고, 최신 버전(0.1.0)은 3개월 전 레지스트리에 올라왔어요.
Claude Desktop, Claude Code, Cursor, VS Code처럼 MCP를 지원하는 앱에서 쓸 수 있어요. URL로 연결되기 때문에, 원격 MCP 서버를 지원하는 앱(예: 개발자 모드의 ChatGPT)에서도 쓸 수 있어요.
같은 카테고리에는: Spec Driven Development, Remote Desktop Commander, Python MCP
같은 카테고리에서 다른 제작자가 만든 서버예요. 스타 순으로 정렬했어요.
카드 보는 법:★ 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.
Local-only Python MCP server for the Files.com API.
제작자의 저장소에서 쓰인 그대로 가져왔어요. PopNx MCP가 검토하거나 보증한 내용이 아니에요. HTML, 이미지, 스크립트는 제거했어요. 링크를 누르면 이 사이트를 벗어나요.
MCP server for Dreambooth Studio. Lets ChatGPT, Claude and Gemini answer an operator's questions about their own booths — "how did my Bandung booth do this week?" — by wrapping the Studio API the dashboard already uses.
Status: live at `https://mcp.dreamboothstudio.com/mcp` (server 0.3.0). Streamable HTTP + stdio, 23 tools — 13 read-only, 9 that create or edit something, and connect_account. Listed in the official MCP Registry as com.dreamboothstudio/dreambooth v0.1.0 (registry versions are immutable, so that entry stays at 0.1.0).
Ten tools are always registered, on stdio and on every HTTP session:
connect_account | starts the device flow |
| read | connection_status · get_sessions · get_gallery_stats · search_docs |
| read | list_projects · get_project · get_revenue_summary · get_credits · get_wallet_transactions |
session_info is an eleventh, registered only when MCP_DIAGNOSTICS=1.
Twelve more, listed on every connection (see below for what guards them):
| creates | create_booth · start_booth · refine_booth · create_filter · duplicate_project |
| creates | start_frame · refine_frame · save_frame |
| edits | update_booth_draft |
| read | get_booth_draft · check_generation · preview_filter |
Phase 3 hardening has since landed, on the OAuth path: the Studio runs a full OAuth 2.1 authorization server — PKCE S256 only, one-hour access tokens, 30-day refresh, dynamic client registration, RFC 8707 resource audience, RFC 7009 revocation, and a CSRF-bound consent screen that names the scopes being granted. This server is a protected resource in front of it (RFC 9728). Both discovery documents are live.
The device flow is the older path and keeps the older properties — its token is a year long, unscoped and unrevocable, so it must not be able to write. It cannot: the Studio refuses it with a 403 and a sentence naming the fix, exactly as it refuses a read-scoped OAuth token.
The tool list is the same on every connection. The twelve above used to be registered only when a request carried a bearer, which made tools/list answer 10 tools with no Authorization header and 22 with any string as one — the check was on the header's presence, not on anything in it. That is gone. An inventory that moves is unusable: the ChatGPT submission portal scans from the browser with no credential, so it could only ever see the read half while the submission declared all 22, and any client caching a pre-sign-in list keeps offering ten tools to an operator who has connected an account. What guards these tools now is what always decided the outcome anyway — AUTH_REQUIRED_TOOLS turns an uncredentialled call into the 401 that *starts* the OAuth flow, and the Studio's 403 answers a token without booths:write. There is no feature flag in this — an earlier version of this README described one, and it was removed; deploy order is what guards a new tool. See Connecting an account.
Design: docs/dreambooth-mcp-design.md in the Studio repo. Inline cards in ChatGPT: docs/apps-sdk-widgets-plan.md.
This service holds no database, no business logic, and no aggregations. Every tool wraps a route the Studio already exposes, so there is exactly one implementation of "what is this operator's revenue" and it lives in the Studio. The moment an aggregation is copied in here, it becomes a second source of truth that drifts silently — which is how you end up with three different revenue numbers and no way to tell which is right.
Also permanently out of scope: withdrawals, payout accounts, MFA/step-up, subscription token regeneration, and anything under /api/admin.
npm install
cp .env.example .env
npm run dev # Streamable HTTP on PORT (default 8080) npm run dev:stdio # stdio, for Claude Desktop
npm run build npm run inspect # stdio smoke: handshake, tools/list, widgets, every tool npm run inspect:http # HTTP smoke: sessions, isolation, unknown-session 404 npm run preview # writes each widget state to .preview/ to open in a browser
inspect:http runs dist/, so npm run build first or you are testing the last build rather than your change.
Both smokes run without a token. search_docs needs no auth, and the authed tools must come back with a readable message naming connect_account rather than crashing — that failure path is part of what the checks verify.
There is no token to configure, in either transport. The operator asks their assistant to connect; connect_account starts the device flow the Studio already runs for the Electron booth and returns a Google link for them to open (Google only: the Studio builds an accounts.google.com URL). A client that signs in through its own connector settings (a request with no session and no credential) gets use_client_sign_in and no link instead; that sign-in is the Studio's login page, which takes an email and password as well as Google. The tool returns immediately and polls in the background — a tool call that blocks for minutes reads as a hung server to every MCP client, and by the time they ask their next question the token is in place.
That includes local development. A pasted token would be a session-equivalent credential (one year, no scopes, no revocation) sitting in a file on disk, and in HTTP mode it would authenticate every incoming session as that one account. Approving in a browser after a restart takes about fifteen seconds; that is the whole cost of not having it.
Device-flow tokens are held in memory, per MCP session. A restart means everyone reconnects, which is the right trade for that path: there is no credential store to protect. The token itself is session-equivalent — one year, no scopes, no revocation — and that has not changed.
What changed is that it is no longer the only way in. A client that arrives with its own Authorization: Bearer is on the OAuth path, where the token expires in an hour, carries a scope the operator approved by name, and can be revoked at /api/oauth/revoke. Nothing is stored here on that path at all: the credential belongs to the request that carried it and is never written into a session, where a later request quoting the same session id could read it.
The two credentials are deliberately not equivalent in what they may do. The Studio refuses a non-GET from a device-flow token on any route that opted into connector writes — the weaker credential must not inherit access granted to the stronger one. Everything the booth fleet POSTs with that token is untouched. The write tools are still *listed* on a device-flow session, because the tool list must not depend on the credential; calling one there returns the Studio's 403 and its sentence, which tells the operator what to do instead.
Reading is unchanged on both: a session that never connects an account can read nothing but search_docs.
Railway, following the dreambooth-whatsapp recipe: railway.json with npm run build / npm start, healthcheck on /health, restart ON_FAILURE. No Dockerfile, no CI, and no volume — this service is stateless.
Set DREAMBOOTH_API_URL and ALLOWED_HOSTS. There is no token to configure. Leave MCP_DIAGNOSTICS unset in production — see the tools section. OPENAI_APPS_CHALLENGE is set only while a directory submission is in flight — see docs/chatgpt-listing.md.
ALLOWED_HOSTS must list both public hostnames:
ALLOWED_HOSTS=mcp.dreamboothstudio.com,dreambooth-mcp-production.up.railway.app
Railway keeps serving its generated hostname after a custom domain is attached, and DNS-rebinding protection is an allow-list, not a filter — naming only one host makes the other return 400 on /mcp. /health keeps answering ok either way, because it is registered ahead of the transport, so the healthcheck cannot tell you this broke. Leaving the variable empty disables the protection entirely rather than allowing everything through some safer path.
server.json is the registry manifest. Entries cannot be unpublished and each version is immutable — a changed URL or a fixed typo means publishing a new version, never editing the old one.
./mcp-publisher validate server.json # checks against the live registry, publishes nothing
./mcp-publisher login dns --domain dreamboothstudio.com --private-key "$(openssl pkey -in key.pem -noout -text | grep -A3 priv: | tail -n +2 | tr -d ' :\n')" ./mcp-publisher publish
Always validate first; it is the only step in that sequence you can take back.
The com.dreamboothstudio namespace is proved by a TXT record on the apex (dreamboothstudio.com, not the mcp subdomain), signed by key.pem. That file is gitignored and lives on one machine. Losing it is recoverable — generate a new Ed25519 pair and replace the TXT record. Leaking it is not: this repo is public, and whoever holds it can publish under com.dreamboothstudio/* permanently.
The hosted server needs no install. In any client that accepts a remote MCP server, point it at:
https://mcp.dreamboothstudio.com/mcp
For running a local checkout — against a preview Studio, or a branch. To use the deployed server, add the URL above instead; there is nothing to clone.
Add to claude_desktop_config.json. --stdio is required — the entry point defaults to HTTP, and without it Claude Desktop starts a web server and waits forever for a reply on stdin.
{
"mcpServers": { "dreambooth": { "command": "npx", "args": ["tsx", "src/index.ts", "--stdio"], "cwd": "/absolute/path/to/dreambooth-mcp", "env": { "DREAMBOOTH_API_URL": "https://dreamboothstudio.com" } } } }
| Tool | Wraps | Auth |
|---|---|---|
get_sessions | GET /api/sessions | Bearer |
get_gallery_stats | GET /api/gallery | Bearer |
search_docs | /docs-search-index-{locale}.json | none |
list_projects | GET /api/projects | Bearer |
get_project | GET /api/projects?id= + GET /api/device-monitoring | Bearer |
get_revenue_summary | GET /api/me/revenue-summary | Bearer |
get_credits | GET /api/credits | Bearer |
get_wallet_transactions | GET /api/wallet-transactions | Bearer |
That is the complete read set. Two more wrap a route that creates something:
| Tool | Wraps | Auth |
|---|---|---|
create_filter | POST /api/filters | Bearer + booths:write |
duplicate_project | POST /api/projects?duplicate | Bearer + booths:write |
start_frame | POST /api/ai/frames/start, then POST /api/ai/threads/{id}/messages | Bearer + booths:write |
refine_frame | POST /api/ai/threads/{id}/messages | Bearer + booths:write |
check_generation | nothing — reads this process | Bearer |
save_frame | POST /api/ai/frames/from-generation | Bearer + booths:write |
preview_filter | GET /api/filters/preview | Bearer (read is enough) |
start_booth | POST /api/onboarding/generate | Bearer + booths:write |
refine_booth | POST /api/onboarding/generate (regen, or a rebuild) | Bearer + booths:write |
create_booth | GET /api/onboarding/draft → GET by-slug?checkOnly → POST /api/onboarding/draft-frames → GET /api/onboarding/frames + /catalog (+ /api/ai-effects/catalog) → POST /api/projects/onboarding → GET by-slug | Bearer + booths:write |
get_booth_draft | GET /api/onboarding/draft | Bearer (read is enough) |
| update_booth_draft | PATCH /api/onboarding/draft (+ `/api/
앞부분만 보여 드려요. 나머지는 저장소에서 읽어 보세요