AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified MIT Self-run

Goshort

mcp-anicedantfa-goshort · by anIcedAntFA

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.io, bare VPS.

No reviews yet
0 installs
25 views
0.0% view→install

Install

$ agentstack add mcp-anicedantfa-goshort

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-anicedantfa-goshort)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
4mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Goshort? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

🔗 GoShort

Self-hosted URL shortener — single binary, SQLite-backed, zero config to start.

Turn long URLs into short, shareable links with click tracking, custom aliases, and AI agent integration.

[](https://github.com/anIcedAntFA/goshort/actions/workflows/ci.yml) [](https://www.bestpractices.dev/projects/12838) [](https://github.com/anIcedAntFA/goshort/actions/workflows/govulncheck.yml) [](https://codecov.io/gh/anIcedAntFA/goshort) [](https://goreportcard.com/report/github.com/anIcedAntFA/goshort) [](https://github.com/anIcedAntFA/goshort/releases/latest)

[](LICENSE) [](go.mod) [](https://goshort.ngockhoi96.dev) [](https://goshort.app/docs) [](https://ko-fi.com/anIcedAntFA)


✨ 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 creationPOST /api/v1/urls/batch accepts up to 100 URLs; per-item success/failure
  • QR codesGET /api/v1/urls/{code}/qr?format=png|jpeg|svg returns a QR code for any short link in three formats
  • Link previewstitle and description auto-fetched on create (fail-open, private-IP blocked)
  • Spam detection — optional Google Safe Browsing v4 integration; unsafe URLs rejected with 422 (fail-open)
  • Switchable cachenone | memory | redis at config time; cache-aside with TTL capped to remaining expiry
  • API key auth — constant-time comparison; per-IP token bucket rate limiting
  • CLI clientgoshort-cli for shorten, list, stats, delete from the terminal
  • Public shorten endpointPOST /api/v1/urls/public: no auth, 5 req/min rate limit, 30-day expiry; powers the landing page widget
  • Landing pagegoshort.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/metrics endpoint, slog throughout, no extra dependencies
  • Self-documenting API — OpenAPI 3.1 spec + interactive Scalar UI at /docs

🏗️ Architecture

Full architecture diagrams: [high-level](docs/sys-arch.png), [request flow](docs/request-flow.excalidraw), [layer boundaries](docs/layers.excalidraw).


🛠️ 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__ env var — e.g., GOSHORT_AUTH_API_KEY=secret. Full reference: [goshort.toml](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: 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](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](CONTRIBUTING.md) for the full development workflow including Redis integration tests and git hooks.


🚢 Deployment

See [docs/DEPLOYMENT.md](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 pagegoshort.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

[](https://star-history.com/#anIcedAntFA/goshort&Date)


📄 License

MIT — see [LICENSE](LICENSE).

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.