mcp server
goshort
Self-hosted URL shortener in Go — single binary, SQLite-backed, zero config. Custom aliases, expiration, CLI, Redis cache, MCP server for AI agents (Claude Code, Cursor). Deploy anywhere: Docker, Fly.
Set up
Runs on your computer. Pick your agent and operating system.
This project does not publish an install method we can turn into a config. Follow the README instead.
README
synced Oct 21, 2026✨ Features
- Zero-collision codes — atomic SQLite counter + Sqids: non-sequential, bijective, no retry loops
- Custom aliases — bring your own slug (
/my-link); charset isolation prevents collision with generated codes - URL expiration — configurable TTL with lazy expiry on read + hourly background cleanup; update expiry via
PATCH - Batch creation —
POST /api/v1/urls/batchaccepts up to 100 URLs; per-item success/failure - QR codes —
GET /api/v1/urls/{code}/qr?format=png|jpeg|svgreturns a QR code for any short link in three formats - Link previews —
titleanddescriptionauto-fetched on create (fail-open, private-IP blocked) - Spam detection — optional Google Safe Browsing v4 integration; unsafe URLs rejected with 422 (fail-open)
- Switchable cache —
none | memory | redisat config time; cache-aside with TTL capped to remaining expiry - API key auth — constant-time comparison; per-IP token bucket rate limiting
- CLI client —
goshort-clifor shorten, list, stats, delete from the terminal - Public shorten endpoint —
POST /api/v1/urls/public: no auth, 5 req/min rate limit, 30-day expiry; powers the landing page widget - Landing page — goshort.ngockhoi96.dev: Astro static site on Cloudflare Workers with live shorten widget
- MCP server — AI agents (Claude Code, Cursor) can shorten, list, and manage URLs via Model Context Protocol
- Prometheus metrics + structured logs —
/metricsendpoint,slogthroughout, no extra dependencies - Self-documenting API — OpenAPI 3.1 spec + interactive Scalar UI at
/docs
🏗️ Architecture
Full architecture diagrams: high-level, request flow, layer boundaries.
🛠️ Tech Stack
| Component | Technology |
|---|---|
| Language | Go 1.26 |
| HTTP | Chi v5 |
| Database | SQLite via sqlc (pure Go, no CGO) |
| Encoding | Sqids (zero-collision, non-sequential) |
| CLI | Cobra |
| Config | Koanf v2 (TOML + env vars) |
| Cache | go-redis v9 |
| Metrics | Prometheus |
| Rate Limit | rate (token bucket) |
| MCP | go-sdk v1.6 (official) |
| Migrations | goose v3 (embedded FS, versioned SQL) |
| QR codes | go-qrcode |
| Spam detection | Google Safe Browsing Lookup API v4 (optional, fail-open) |
| Reverse Proxy | Caddy (Docker Compose) |
| Release | GoReleaser + GitHub Actions |
| Website | Astro v6, Tailwind CSS v4, Biome v2, Bun, Cloudflare Workers |
🚀 Quick Start
a. Docker Compose (recommended)
curl -O https://raw.githubusercontent.com/anIcedAntFA/goshort/main/docker-compose.yml
curl -O https://raw.githubusercontent.com/anIcedAntFA/goshort/main/goshort.toml
docker compose up -d
Caddy handles TLS automatically. Edit goshort.toml to set your base_url and api_key.
b. Binary (GitHub Releases)
curl -L https://github.com/anIcedAntFA/goshort/releases/latest/download/goshort_linux_amd64.tar.gz | tar xz
./goshort
Grab goshort_darwin_arm64, goshort_windows_amd64, etc. from the releases page.
c. go install
go install github.com/anIcedAntFA/goshort/cmd/server@latest
goshort
📡 Usage
Create a short URL:
curl -s -X POST http://localhost:8080/api/v1/urls \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{"url": "https://example.com/very/long/path", "expires_in": "30d"}'
{
"short_code": "k7Xm2p",
"short_url": "http://localhost:8080/k7Xm2p",
"original_url": "https://example.com/very/long/path",
"expires_at": "2025-08-01T00:00:00Z"
}
Redirect:
curl -L http://localhost:8080/k7Xm2p
# → 302 to https://example.com/very/long/path
💻 CLI
# Install
go install github.com/anIcedAntFA/goshort/cmd/cli@latest
# Shorten a URL
goshort-cli shorten https://example.com/long --alias my-link --expires 7d
# List all URLs (paginated)
goshort-cli list --page 1 --per-page 20
# Inspect a short code or alias
goshort-cli stats k7Xm2p
# Delete a short URL
goshort-cli delete k7Xm2p
Config file (~/.goshort.toml):
server_url = "http://localhost:8080"
api_key = "your-api-key"
Per-command overrides (precedence: flag > env > config):
| Flag | Env var |
|---|---|
--server | GOSHORT_SERVER_URL |
--api-key | GOSHORT_API_KEY |
--json | — |
🤖 MCP (AI Agent Integration)
GoShort ships an MCP server so AI agents like Claude Code and Cursor can shorten, list, and manage URLs directly.
Local — stdio
make build
Create .mcp.json in your project root:
{
"mcpServers": {
"goshort": {
"command": "./bin/goshort",
"args": ["--mcp"],
"env": { "GOSHORT_STORAGE_SQLITE_PATH": "./data/goshort.db" }
}
}
}
Remote — Streamable HTTP
The /mcp endpoint is served on the main port alongside the REST API. No separate server needed.
# Connect Claude Code to deployed instance
claude mcp add goshort-remote \
--transport http \
https://goshort.app/mcp \
--header "X-API-Key: your-api-key"
Tools
| Tool | Description |
|---|---|
shorten_url | Create a short URL (alias + expiry optional) |
batch_shorten_urls | Create up to 100 short URLs in one call |
list_urls | List URLs with pagination |
get_url_stats | Click count and full details for a URL |
delete_url | Delete a short URL |
lookup_url | Resolve a short code to its original URL |
update_url | Update the expiry of an existing short URL |
Resources
| URI | Description |
|---|---|
goshort://stats/summary | Total URL count and top URLs by clicks |
goshort://urls/{code} | Full details for a specific short code |
goshort://urls/{code}/qr | QR code blob for a short URL (PNG/JPEG/SVG via ?format=) |
Prompts
| Prompt | Description |
|---|---|
shorten_and_share | Shorten + format for sharing (platform-aware) |
batch_shorten | Shorten multiple URLs and return a table |
⚙️ Configuration
[server]
port = 8080
base_url = "https://short.yourdomain.com"
[auth]
api_key = "your-secret-key" # empty = no auth
[cache]
driver = "none" # none | memory | redis
[shortener]
default_expiry = "0" # "0" = no expiry; or "7d", "30d", "365d"
Every key maps to GOSHORT_<SECTION>_<KEY> env var — e.g., GOSHORT_AUTH_API_KEY=secret. Full reference: goshort.toml.
📋 API
| Method | Path | Auth | Description |
|---|---|---|---|
POST | /api/v1/urls | Yes | Create short URL |
POST | /api/v1/urls/batch | Yes | Create up to 100 URLs |
GET | /api/v1/urls | Yes | List URLs (paginated) |
GET | /api/v1/urls/:code | Yes | Get URL details |
PATCH | /api/v1/urls/:code | Yes | Update URL expiry |
DELETE | /api/v1/urls/:code | Yes | Delete short URL |
POST | /api/v1/urls/public | No | Public shorten (30d TTL) |
GET | /api/v1/urls/:code/qr | No | QR code (PNG/JPEG/SVG) |
GET | /:code | No | Redirect (302) |
GET | /health | No | Health check |
GET | /metrics | No | Prometheus metrics |
GET | /docs | No | Interactive API docs |
POST | /mcp | Yes | MCP Streamable HTTP |
Auth: X-API-Key: <key> header. Redirect codes: 302 Found, 404 Not Found, 410 Gone (expired).
POST /api/v1/urls body:
| Field | Type | Required | Notes |
|---|---|---|---|
url | string | Yes | Max 2048 chars |
custom_alias | string | No | ^[a-zA-Z0-9-]{3,30}$ |
expires_in | string | No | 1h, 7d, 30d, 90d, 365d, never |
Interactive docs at goshort.app/docs. Landing page at goshort.ngockhoi96.dev.
📁 Project Structure
See docs/DESIGN.md for the full architecture, layer boundaries, and design rationale.
🧑💻 Development
git clone https://github.com/anIcedAntFA/goshort
cd goshort
lefthook install # install git hooks (once after clone)
make help # list all targets
Run make help for the full list of targets. See CONTRIBUTING.md for the full development workflow including Redis integration tests and git hooks.
🚢 Deployment
See docs/DEPLOYMENT.md for comprehensive guides.
Docker Compose — GoShort + Caddy (auto-TLS):
docker compose up -d
Fly.io — API + redirects + MCP at goshort.app:
fly launch && fly deploy
Landing page — goshort.ngockhoi96.dev (Cloudflare Workers, static Astro build):
make website/build && cd website && wrangler deploy
Bare VPS — Nginx + systemd + Certbot (see DEPLOYMENT.md)
🗺️ Roadmap
| Phase | Focus | Status |
|---|---|---|
| 1 | Core library — SQLite, sqlc, Sqids, TDD | ✅ v0.1.0 |
| 2 | HTTP API, caching, config, Prometheus | ✅ v0.2.0 |
| 3 | Auth, rate limiting, CLI, Docker, release infra | ✅ v0.3.0 |
| 3.5 | Deploy — Fly.io + Cloudflare CDN | ✅ goshort.app |
| 4 | MCP server — Claude / Cursor integration | ✅ v0.4.0 |
| 5 | Batch, QR codes, link previews, spam detection | ✅ v0.5.0 |
| 6 | Landing page (Cloudflare Workers), public endpoint | ✅ v0.6.0 |
| 7+ | Analytics, PostgreSQL, Redis counter | 🔲 |
Each phase ships a working, deployable product.
⭐ Star History
📄 License
MIT — see LICENSE.