@mcp-use/tunnel
v0.1.4
Published
Simple bore tunnel client - one command to get a public URL
Readme
Bore with Subdomain Routing
A complete solution for running bore with ngrok/localtunnel-style subdomain routing and automatic HTTPS via Cloudflare.
┌──────────────────────────────────────────────────────────────┐
│ User types: https://happy-cat.local.mcp-use.run │
└─────────────────────────┬────────────────────────────────────┘
│ HTTPS (Cloudflare handles SSL)
│
┌─────────────────────────▼────────────────────────────────────┐
│ Cloudflare (Free SSL + DDoS) │
└─────────────────────────┬────────────────────────────────────┘
│ HTTP
│
┌─────────────────────────▼────────────────────────────────────┐
│ HTTP Proxy (subdomain routing) │
│ happy-cat → localhost:8123 │
└─────────────────────────┬────────────────────────────────────┘
│
┌─────────────────────────▼────────────────────────────────────┐
│ Bore Server (TCP tunnels) │
└─────────────────────────┬────────────────────────────────────┘
│ Tunnel
│
┌─────────────────────────▼────────────────────────────────────┐
│ Bore Client (user's local machine) │
│ bore local 3000 --to server.com │
└─────────────────────────┬────────────────────────────────────┘
│
┌─────────────────────────▼────────────────────────────────────┐
│ Local Web Server (port 3000) │
└──────────────────────────────────────────────────────────────┘🌟 Features
- ✨ Subdomain routing -
happy-blue-cat.local.mcp-use.runstyle URLs - 🔒 Automatic HTTPS - Free SSL via Cloudflare
- 🔐 Token-based authentication - Prevents port scanning and tunnel hijacking
- 🛡️ Path restrictions - Configurable path restrictions (default:
/mcp**and/mcp-use**, or allow all paths with/) - 🌐 WebSocket support - Full bidirectional communication
- 🎯 REST API - Simple tunnel management
- 📦 NPX client - No installation needed for clients
- 🐳 Docker ready - Easy deployment
- 🚀 Railway/Render compatible - Deploy in minutes
📦 What's Included
This repository contains:
@mcp-use/tunnel- NPX client for bore tunnels (no Rust needed!)proxy-server- HTTP proxy with subdomain routing- Cloudflare integration - HTTPS without managing certificates
- Complete deployment guides - Railway, Docker, VPS, etc.
🚀 Quick Start
Server Setup (5 minutes)
Option 1: Railway (Easiest)
- Fork this repo
- Deploy to Railway
- Set environment variable:
BASE_DOMAIN=your-domain.com - Follow CLOUDFLARE-SETUP.md
Option 2: Docker
cd proxy-server
docker-compose up -dSee DEPLOYMENT.md for more options.
Client Usage
# 1. Start your local service
python -m http.server 3000
# 2. Create tunnel - that's it!
npx @mcp-use/tunnel 3000
# Output:
# ╭─────────────────────────────────────────────╮
# │ 🎉 Tunnel Created Successfully! │
# ╰─────────────────────────────────────────────╯
#
# 🌐 Public URL:
# https://happy-blue-cat.local.mcp-use.run
#
# 📍 Subdomain: happy-blue-cat
# 🔌 Local Port: 3000
# 🚪 Remote Port: 8456
#
# ╭─────────────────────────────────────────────╮
# │ Press Ctrl+C to close the tunnel │
# ╰─────────────────────────────────────────────╯
# 3. Access your service!
curl https://happy-blue-cat.local.mcp-use.runRailway Deployments (Custom Control Port)
Railway exposes TCP ports with random external ports (e.g., caboose.proxy.rlwy.net:23894 → :7835). The server includes a custom bore build with --control-port support.
⚠️ Important: The tunnel ports (8000-9000) that bore assigns are NOT externally accessible - they're only used internally by the HTTP proxy on Railway. Users access tunnels via subdomain URLs (e.g., https://happy-cat.local.mcp-use.run), not direct port access.
The API response includes the correct connection command:
# Get connection info from API
curl https://your-domain.com/api/tunnels
# Response includes:
# "bore_command": "bore local <PORT> --to caboose.proxy.rlwy.net --control-port 23894"Usage with Railway:
The mcp-tunnel command automatically uses the correct server configuration:
# Set environment variables once
export BORE_SERVER=caboose.proxy.rlwy.net
export BORE_CONTROL_PORT=23894
# Then just use the simple command
npx @mcp-use/tunnel 3000
# Automatically connects to Railway and shows your URL!Note: The package includes custom bore binaries with --control-port support built-in.
📚 Documentation
- ARCHITECTURE.md - How everything works together (READ THIS FIRST!)
- SECURITY.md - Security guide & best practices
- ADMIN-CLI.md - Admin CLI for tunnel management
- PATH-RESTRICTIONS.md - Path restrictions security feature
- CLOUDFLARE-SETUP.md - Complete Cloudflare configuration guide
- DEPLOYMENT.md - Deploy to Railway, Docker, VPS, etc.
- RAILWAY-TCP-BRANDING.md - Brand Railway TCP proxy domain
- CUSTOM-BORE-SETUP.md - Build & distribute custom bore binaries
- proxy-server/README.md - HTTP proxy documentation
❓ FAQ
Do I need to handle HTTPS in my app?
No! If you use Cloudflare (recommended), it handles SSL termination. Your app only needs HTTP (port 80).
See: CLOUDFLARE-SETUP.md
How is this different from ngrok?
| Feature | ngrok | localtunnel | This Project | | ----------------- | ---------- | ----------- | ------------------- | | Subdomain routing | ✅ | ✅ | ✅ | | Custom domains | ✅ (paid) | ✅ | ✅ (free) | | Self-hostable | ❌ | ✅ | ✅ | | HTTPS | ✅ | ✅ | ✅ (via Cloudflare) | | Free tier limits | 40 req/min | None | None (self-hosted) | | Written in | Go | Node.js | Rust + Node.js |
How much does it cost?
- Cloudflare: FREE ✅
- Domain: ~$10/year
- Railway: ~$5/month (500 hours free tier)
- Total: ~$10/year + optional $5/month
Or self-host on a $4-6/month VPS!
Can I use my own domain?
Yes! Any domain works. Just configure DNS and Cloudflare:
- Point
*.local.your-domain.comto your server - Set
BASE_DOMAIN=local.your-domain.com - Configure Cloudflare for free HTTPS
See: CLOUDFLARE-SETUP.md
🏗️ Architecture
Components
Bore Server (Rust)
- TCP tunnel server
- Listens on port 7835 (control) + 8000-9000 (tunnels)
- From github.com/ekzhang/bore
HTTP Proxy (Node.js)
- Routes HTTP traffic based on subdomain
- Manages subdomain → port mappings
- REST API for tunnel management
Cloudflare (External)
- SSL/TLS termination
- DDoS protection
- Global CDN
- FREE!
NPX Client Wrapper (Node.js)
- Downloads bore binary automatically
- No Rust installation needed
- Works with
npxdirectly
Data Flow
User Request (HTTPS)
→ Cloudflare (SSL termination)
→ HTTP Proxy (subdomain routing)
→ Bore Tunnel (TCP proxy)
→ Bore Client (user's machine)
→ Local Service🛠️ Development
Prerequisites
- Node.js 18+
- Rust (for building bore)
- Docker (optional)
Local Development
# Install dependencies
cd proxy-server
yarn install
# Start proxy server (requires bore binary)
yarn start
# Or use Docker
docker-compose upProject Structure
mcp-use-tunnel/
├── bore/ # Bore source code (Git submodule)
├── proxy-server/ # HTTP proxy with subdomain routing
│ ├── index.js # Main proxy server
│ ├── package.json
│ ├── Dockerfile
│ └── docker-compose.yml
├── cli.js # NPX bore wrapper
├── package.json # bore-npx package
├── CLOUDFLARE-SETUP.md # Cloudflare guide
├── DEPLOYMENT.md # Deployment guide
└── README.md # This file🔒 Security Features
- ✅ Token-based authentication - Prevents port scanning attacks
- ✅ IP-based validation - Prevents token theft
- ✅ Path restrictions - Only
/mcp**and/mcp-use**paths allowed - ✅ Rate limiting - Prevents API abuse
- ✅ Connection limits - Prevents resource exhaustion
- ✅ Automatic cleanup - Expired tunnels removed automatically
- ✅ Pre-assigned ports - No random port scanning possible
See SECURITY.md for details.
🤝 Contributing
Contributions welcome! Some ideas:
- [ ] Web dashboard for tunnel management
- [ ] Metrics and monitoring
- [ ] Data transfer limits
- [ ] More client wrappers (Python, Go, etc.)
📝 License
MIT
🙏 Credits
- bore by @ekzhang - The amazing TCP tunnel
- Cloudflare - Free SSL and DDoS protection
- Inspired by ngrok and localtunnel
🔗 Links
📧 Support
- Open an issue on GitHub
- Check CLOUDFLARE-SETUP.md for common issues
- Read DEPLOYMENT.md for platform-specific help
Made with ❤️ for the developer community
