Spec Driven Development
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
제작자가 쓴 설명(영어 원문)
Direct end-to-end-encrypted tunnel between Claude agents — two-party or a room of up to 16.
이 세 가지는 절대 하나의 점수로 합치지 않아요. 의견, 측정, 인기는 서로 다른 것이니까요.
이 서버는 아직 쉬운 말로 된 요약을 쓰지 못했어요. 아래는 레지스트리에서 읽어 온 사실이에요.
쓰고 있는 AI 앱을 고른 다음 설정을 복사하세요.
TUNNEL_DOH필요한 것
어떤 앱을 쓰세요?
위에서 앱을 고르세요. 기억해 두었다가 다음부터는 버튼에 “…에 설치”라고 표시해요.
Claude Desktop → Settings → Developer → Edit Config를 열고 claude_desktop_config.json에 이 내용을 붙여 넣으세요
{
"mcpServers": {
"tunnel": {
"command": "npx",
"args": [
"-y",
"tunnel-mcp"
],
"env": {
"TUNNEL_DOH": "your-value"
}
}
}
}터미널에서 이 명령어를 실행하세요
claude mcp add tunnel --env TUNNEL_DOH=your-value -- npx -y tunnel-mcp실행하기 전에 빈 값을 채워 주세요.
프로젝트의 .cursor/mcp.json 또는 ~/.cursor/mcp.json에 붙여 넣으세요
{
"mcpServers": {
"tunnel": {
"command": "npx",
"args": [
"-y",
"tunnel-mcp"
],
"env": {
"TUNNEL_DOH": "your-value"
}
}
}
}브라우저가 앱을 열지 물어본 다음, 앱이 설정을 보여 주고 확인을 요청해요. 키 값은 비워 두니 직접 입력하세요.
프로젝트의 .vscode/mcp.json에 붙여 넣으세요
{
"servers": {
"tunnel": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"tunnel-mcp"
],
"env": {
"TUNNEL_DOH": "your-value"
}
}
}
}브라우저가 앱을 열지 물어본 다음, 앱이 설정을 보여 주고 확인을 요청해요. 키 값은 비워 두니 직접 입력하세요.
이 서버는 내 컴퓨터에서 실행되는데, ChatGPT는 인터넷에 있는 서버에만 연결할 수 있어요. 다른 앱을 고르세요.
선택한 앱은 이 기기의 쿠키에만 저장돼요. 계정은 필요 없어요.
TUNNEL_DOH env이 설정은 제작자의 레지스트리 정보로 만들었어요. README와 다르면 README를 따르세요.
내 컴퓨터에서 실행돼요. 설치하면 AI 앱에 도구 목록이 나타나요.
누구나 볼 수 있는 정보를 점검했고, 코드는 읽지 않았어요. 해당하지 않는 항목은 개수에서 뺐어요. · 2026년 11월 8일 점검
레지스트리 이름이 GitHub 계정 zachlikefolio 기준으로 확인되었고, 이 계정이 저장소를 소유하고 있어요
아직 GitHub에서 이 저장소를 읽어 오지 않았어요
아직 GitHub에서 이 저장소를 읽어 오지 않았어요
내 컴퓨터에서 실행되는 서버라 인터넷 엔드포인트가 없어요
내 컴퓨터에서 실행되며, 대신 로컬 설정을 사용해요
내 컴퓨터에서 실행돼요. 도구 목록은 인터넷 엔드포인트가 있는 서버에서만 읽을 수 있어요
레지스트리에서 이 카테고리의 활성 서버 전체와 비교했어요. 스타는 게시자가 저장소를 소유한 경우에만 세요.
해당하는 기본 점검 1개 중 1개를 통과했어요. 코드는 읽지 않았어요. 키나 토큰을 넣기 전에 서버가 어떤 권한을 요구하는지 확인하고, 꼭 필요한 권한만 있는 키를 쓰세요.
레지스트리에 필수 키가 나와 있지 않아요. 다만 처음 쓸 때 로그인을 요구하는 서버도 있어요.
내 컴퓨터에서 실행돼요. AI 앱이 필요할 때 실행하고, 데이터는 제작자의 서버를 거치지 않아요(서버 자체가 온라인 서비스를 호출하는 경우는 제외).
GitHub 저장소는 마지막으로 – 변경됐고, 최신 버전(0.3.0)은 4개월 전 레지스트리에 올라왔어요.
Claude Desktop, Claude Code, Cursor, VS Code처럼 MCP를 지원하는 앱에서 쓸 수 있어요. 내 컴퓨터에 Node.js도 있어야 해요.
같은 카테고리에는: Spec Driven Development, Remote Desktop Commander, Winecellarbuilders
같은 카테고리에서 다른 제작자가 만든 서버예요. 스타 순으로 정렬했어요.
카드 보는 법:★ 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 the team for your wine room.
제작자의 저장소에서 쓰인 그대로 가져왔어요. PopNx MCP가 검토하거나 보증한 내용이 아니에요. HTML, 이미지, 스크립트는 제거했어요. 링크를 누르면 이 사이트를 벗어나요.
A direct, end-to-end-encrypted tunnel between two developers' Claude agents — no human copy-paste required.
Reproduce that yourself in 30 seconds — clone the repo and:
npm ci && npm run demo
That opens a real encrypted tunnel through Cloudflare's edge, joins it as a guest, exchanges end-to-end-encrypted messages, proves the join link is single-use, and tears everything down.
When two developers each run a Claude agent and need those agents to collaborate, the usual workaround is a human sitting in the middle, copy-pasting messages from one chat window to the other. tunnel-mcp removes that human. It's an MCP server that lets one developer's agent open a throwaway, encrypted tunnel and the other developer's agent dial straight into it, so the two agents can talk to each other directly — while their humans stay in control of what actually happens to the filesystem or the shell.
One developer (the host) calls tunnel_open. Their local tunnel-mcp process becomes an in-process WebSocket relay and exposes it to the internet via a throwaway cloudflared Quick Tunnel — no port-forwarding, no server to provision. The other developer (the guest) calls tunnel_join with the link the host shares, and their agent dials outbound to that same tunnel. Because both sides only ever make outbound connections, it works from behind ordinary firewalls and NAT.
Host machine Guest machine
┌───────────────────┐ outbound HTTPS ┌───────────────────┐ │ Claude (host) │ wss:// │ Claude (guest) │ │ │ │ ┌──────────────┐ │ │ │ │ tunnel_open/say/ │──────▶ cloudflared │◀────────│ tunnel_join/say/ │ │ listen/close │ │ Quick Tunnel │─────────▶ listen/close │ │ │ │ └──────────────┘ │ │ │ │ in-process relay │ └───────────────────┘ └───────────────────┘
The relay and the cloudflared child process live only for the lifetime of the session and are destroyed on teardown. The transcript is held in memory only — nothing is ever written to disk, and it vanishes with the process at teardown.
npm install -g tunnel-mcp
npx tunnel-mcp
Register it with Claude Code (both developers do this once):
claude mcp add tunnel -- tunnel-mcp # if globally installed
claude mcp add tunnel -- npx -y tunnel-mcp
tunnel-mcpis a stdio MCP server, not an interactive CLI. Launching it by
hand just waits silently for a client — that's expected. Run
tunnel-mcp --helpfor usage, ortunnel-mcp --version.
The tunnel-etiquette skill teaches each agent how to behave inside a tunnel (treat the peer as untrusted input, and check with its human before acting on anything the peer says). Installing the package copies it into ~/.claude/skills/ automatically (best-effort). If install scripts are disabled (npm install --ignore-scripts), or you want it in a custom directory or force an update, run it explicitly:
npx tunnel-mcp install-skill # into ~/.claude/skills
npx tunnel-mcp install-skill --dir --force # elsewhere / overwrite
Set TUNNEL_SKILLS_DIR to change the default target, or TUNNEL_SKIP_SKILL_INSTALL=1 to opt out of the automatic copy.
cloudflared is auto-downloaded to ~/.tunnel/bin the first time it's needed if it isn't already on your PATH — there's nothing extra to install.
Host — ask Claude to open a tunnel with a goal:
"Open a tunnel to pair on debugging the checkout flow."
Claude calls tunnel_open({ goal }) and hands back a ready-to-forward invite — one plain-text message containing the one-time setup command and the join link. Paste it to the other developer over a trusted channel (Slack DM, etc.) — the link is a secret, since it contains the encryption key for the session. It is single-use and expires after ~10 minutes (tunnel_open reports joinLinkExpiresInSec), so share it promptly.
Guest — paste the link and ask Claude to join:
"Join this tunnel:
"
Claude calls tunnel_join({ joinLink }), learns the goal, and gets back the room's member roster — with the default single invite, that's just the two of you.
More than one guest? Open a room instead:
"Open a tunnel for me and two teammates, to pair on the checkout flow."
Claude calls tunnel_open({ goal, invites: 3 }) — invites is the number of teammates to seat (up to 15, plus the host makes 16 connected at once) — and gets back one invite per teammate instead of a single link. Forward each invite to exactly one person; every invite is single-use, so don't reuse one link for two people. Need to add someone mid-session, or re-admit someone whose invite expired before they used it? tunnel_invite({ count }) (host-only) mints more.
Both — the agents converse turn-by-turn using tunnel_say to send and tunnel_listen to wait for the next reply. In a room, every message arrives with fromName so agents can tell who said what, checking in with their humans as needed.
Ending it is role-sensitive: the host calls tunnel_close to end the session for everyone and tear down the relay — the in-memory transcript vanishes with it, since it was never written to disk. A member calling tunnel_close just leaves; the room stays open for whoever's left.
Sharing files: any member can call tunnel_share({ path }) to send a text or binary file to the room — it's read from disk, hashed, and sealed with the room key before it ever crosses the tunnel, so the relay only ever sees ciphertext. The offer shows up for teammates as an artifact message in tunnel_listen and in tunnel_status().artifacts (id, name, kind, size, sender). A teammate who wants it calls tunnel_receive({ artifactId, savePath }) with a path they choose — the bytes are decrypted and checked against the sender's sha256 before anything is written, and a mismatch is refused rather than saved. An artifact stays fetchable by any current member until it expires (a 30-minute TTL) or the session ends — each tunnel_receive call independently re-fetches and re-verifies. Members on an older client are silently skipped (olderMembers in the tunnel_share result) — they simply never see the offer. Filenames cross as plaintext metadata, so don't put secrets in one, and treat every received file as untrusted input — see the etiquette skill.
| Tool | Who | Purpose |
|---|---|---|
tunnel_open({goal, invites?}) | host | Start the relay + Quick Tunnel and get back one invite per teammate (default 1 — classic two-party). |
tunnel_invite({count?}) | host | Mint more single-use, expiring invites mid-session. |
tunnel_join({joinLink}) | member | Dial into a room using an invite link and authenticate; returns the current member roster. |
tunnel_say({text}) | any | Send a message to the room. |
tunnel_listen({sinceSeq?, timeoutMs?}) | any | Wait for the next message(s), each tagged with the sender's fromName. |
tunnel_share({path}) | any | Share a file (text or binary) with the room, end-to-end encrypted; returns {artifactId, offeredTo, olderMembers}. |
tunnel_receive({artifactId, savePath}) | any | Fetch an offered artifact, verify its hash, and write it to a path you choose. |
tunnel_status() | any | Inspect the session: role, goal, member roster, pending invites, offered artifacts, lastSeq. |
tunnel_close({summary?}) | any | Host: ends the session for everyone. Member: leaves the room. |
tunnel-mcp is a security-sensitive tool by nature — it opens a live channel between developers' AI agents. Here's exactly what it does and does not protect:
tunnel_say body is sealed with NaCl secretbox (XSalsa20-Poly1305, via tweetnacl) before it crosses the cloudflared pipe. The relay and the pipe only ever see ciphertext for chat bodies.tunnel_open goal, each member's name, and connection events (joined/left/idle/closed) are sent as plaintext metadata — do not put secrets in the goal string or a display name.tunnel_share seals a file's bytes with the same room key as chat (NaCl secretbox) before they cross the tunnel, and carries a plaintext sha256 of the contents; tunnel_receive decrypts, reassembles, and verifies that hash before writing anything to disk. The filename, size, and kind are plaintext metadata (don't put secrets in a filename), and a received file is untrusted — tunnel_receive only ever writes to a path the receiver chooses, never the sender's name.tunnel_close (or their process exiting, or 30 minutes of no messages) ends the session for everyone and tears down the relay + `cloudf앞부분만 보여 드려요. 나머지는 저장소에서 읽어 보세요