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

Shortlyai

mcp-snagarjuna07-shortlyai · by SNagarjuna07

Production-grade URL shortener built with Java 25 + Spring Boot 4 microservices, Redis, Kafka, and Spring AI

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

Install

$ agentstack add mcp-snagarjuna07-shortlyai

✓ 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 No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • 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-snagarjuna07-shortlyai)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
2mo 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 Shortlyai? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

🔗 ShortlyAI

**A production-grade URL shortener built as a Java 25 / Spring Boot 4 microservices platform with a built-in AI agent you can just talk to, and an MCP server so Claude can manage your links directly.**

> Most URL shortener projects are a single Spring Boot app with one table. > This one is six independently deployable services with service discovery, circuit breakers, a full observability stack, an LLM-powered ReAct agent that can shorten, inspect, analyze, and delete your links through plain English, and a native MCP server so Claude Desktop can do the same - all spun up with a single docker compose up.

If this saves you a weekend of wiring microservices together, a star helps a lot and tells me to keep building.


⚡ Load Test Results

Benchmark on the redirect hot path (GET /r/{slug}) - cache-aside Redis, single local machine running all 15 Docker containers simultaneously. Tested with k6.

| VUs | RPS | Avg Latency | p95 | Errors | |-----|-----|-------------|-----|--------| | 50 | 342 | 20 ms | 48 ms | 0% | | 100 | 681 | 19 ms | 44 ms | 0% | | 200 | 1,332 | 24 ms | 62 ms | 0% | | 500 | 1,576 | 163 ms | 383 ms | 0% | | 700 | 1,259 | 346 ms | 817 ms | 0% |

284,485 total requests. 0 failures. 0 dropped connections.

The system peaks at ~1,576 req/s at 500 VUs then degrades gracefully, latency climbs but the error rate stays flat at zero. That's backpressure working correctly (connection pool queuing), not a crash. At the realistic sweet spot of 200 concurrent users, the redirect path serves 1,332 req/s at 24 ms average latency - Redis cache-aside doing its job.

> Numbers are from a single-instance, local-machine run with all 15 containers sharing one host. A dedicated Redis + Postgres deployment would push these significantly higher. The more interesting stat is zero errors under 700 VUs. The system slows, it doesn't break.


🤖 Talk to your links

ShortlyAI's standout feature is ai-service - a Spring AI ReAct agent that turns plain-English requests into real actions across the platform.

POST /api/v1/ai/agent
{
  "message": "Shorten https://www.github.com and tell me how many clicks it has so far"
}
{
  "reply": "The shortened URL for https://www.github.com is http://localhost:8082/G and it currently has 0 clicks."
}

Under the hood, the agent reasons step-by-step: it calls a shortenUrl tool against url-service, gets back a real urlId, then chains into getUrlStats against analytics-service, all without the LLM ever touching a database directly, and without the user ever knowing which microservice did what.

Try also:

  • "What are my top 3 most clicked links?"
  • "Delete the URL with slug ABC123, I confirm it"
  • "Is this URL safe: http://verify-paypal-login.xyz"

Resilience built in: if url-service or analytics-service is down or slow, the agent doesn't crash. Resilience4j circuit breakers trip and the agent replies conversationally:

{
  "reply": "URL shortening is temporarily unavailable. Please try again in a moment."
}

🔌 Use it from Claude Desktop (MCP)

ai-service doubles as a native MCP server - point Claude Desktop at it and manage your shortened URLs without leaving the chat window.

1. Generate an API key (one-time, via auth-service):

POST /api/v1/auth/apikeys
Authorization: Bearer 
{ "name": "Claude Desktop" }

You'll get back a sk_... key, copy it immediately, it's shown exactly once.

2. Wire it into Claude Desktop's config:

{
  "mcpServers": {
    "shortlyai": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "http://localhost:8080/mcp",
        "--header", "X-MCP-Key: sk_your_key_here"
      ]
    }
  }
}

> On Windows, wrap the command as "cmd" / ["/c", "npx", ...].

3. Tools exposed to Claude:

| Tool | What it does | |---|---| | mcp_shortenUrl | Shorten a long URL, return the short link + numeric ID | | mcp_getUrlDetails | Look up a URL's original destination + click count by slug | | mcp_deleteUrl | Permanently delete a shortened URL (Claude confirms before calling) | | mcp_getUrlStats | Click count for a specific URL by ID | | mcp_getTopUrls | Your top-performing links by click count |

Auth is API-key based (SHA-256 hashed, validated against Redis on every call) rather than JWT, MCP connections are long-lived and tokens shouldn't expire mid-session. Every tool call is circuit-breaker protected against the same url-service/analytics-service dependencies the chat agent uses.


🏗️ Architecture

graph TB
    Client[("Client")]
    Eureka{{"eureka-server :8761Service Registry"}}
    Gateway["api-gateway :8080JWT • Rate limiting • Circuit breakers • Routing"]

    subgraph Services
        Auth["auth-service :8081JWT + OAuth2 + Refresh tokens"]
        Url["url-service :8082Shortening • Base62 • Redirects"]
        Analytics["analytics-service :8083Click tracking • Bloom filter"]
        AI["ai-service :8084ReAct agent • MCP server • Classification • Safety"]
    end

    PG1[("Postgresshortlyai_auth")]
    PG2[("Postgresshortlyai_urls")]
    PG3[("Postgresshortlyai_analytics")]
    RedisDB[("Redis 7cache • rate limit • bloom filter • API keys")]
    Kafka{{"Apache Kafka"}}
    Obs["Prometheus + Grafanametrics & dashboards"]
    MCP[("Claude Desktopvia MCP")]

    Client --> Gateway
    MCP -. "X-MCP-Key" .-> AI

    Gateway -. discovers .-> Eureka
    Auth -. registers .-> Eureka
    Url -. registers .-> Eureka
    Analytics -. registers .-> Eureka
    AI -. registers .-> Eureka

    Gateway -- "circuit breaker" --> Auth
    Gateway -- "circuit breaker" --> Url
    Gateway -- "circuit breaker" --> Analytics
    Gateway -- "circuit breaker" --> AI

    Auth --> PG1
    Auth --> RedisDB

    Url --> PG2
    Url --> RedisDB
    Url -- "url.created / url.clicks / url.deleted" --> Kafka

    Kafka --> Analytics
    Analytics --> PG3
    Analytics --> RedisDB

    Kafka --> AI
    AI -- "url.classified" --> Kafka
    Kafka -.-> Url
    AI -- "circuit breaker + retry" --> Url
    AI -- "circuit breaker + retry" --> Analytics

    Auth -.->|/actuator/prometheus| Obs
    Url -.->|/actuator/prometheus| Obs
    Analytics -.->|/actuator/prometheus| Obs
    AI -.->|/actuator/prometheus| Obs
    Gateway -.->|/actuator/prometheus| Obs

Event flow example: shortening a URL triggers url.created → consumed by both analytics-service (initializes click counters) and ai-service (classifies the URL via LLM, generates a title, runs a safety check) → ai-service publishes url.classified → consumed back by url-service to persist the AI-generated title/category/safety flag. Fully async, fully decoupled — a real SAGA choreography, not a hardcoded call chain.


🚀 One command, full stack

git clone https://github.com/SNagarjuna07/shortlyai.git
cd shortlyai
cp .env.example .env
# fill in: DB credentials, Redis password, JWT secret, Groq API key, mail credentials

docker compose up -d --build

That's it — 15 containers, fully wired:

| What | URL | |---|---| | API Gateway (entry point) | http://localhost:8080 | | Swagger UI (all services, one page) | http://localhost:8080/swagger-ui.html | | Eureka dashboard | http://localhost:8761 | | Grafana (dashboards) | http://localhost:3000 (admin / admin) | | Prometheus | http://localhost:9090 | | Kafka UI | http://localhost:8090 |

All 6 services build from multi-stage Dockerfiles (eclipse-temurin:25-jdkeclipse-temurin:25-jre), register with Eureka on startup, and expose /actuator/prometheus for metrics scraping out of the box.


📘 API Docs (Swagger / OpenAPI)

Every service ships full OpenAPI 3.1 docs via springdoc-openapi, aggregated into a single Swagger UI at the gateway:

| Service | Swagger UI | |---|---| | Gateway - aggregated, all services | http://localhost:8080/swagger-ui.html | | Auth Service | http://localhost:8081/swagger-ui.html | | URL Service | http://localhost:8082/swagger-ui.html | | Analytics Service | http://localhost:8083/swagger-ui.html | | AI Service | http://localhost:8084/swagger-ui.html |


✨ Key Features

| Category | What's implemented | |---|---| | AI / LLM | ReAct agent (Spring AI + tool calling), AI URL classification (title, category, safety), AI slug suggestions, AI-generated analytics summaries | | MCP | Native MCP server (STREAMABLE transport) exposing URL/analytics tools to Claude Desktop, hashed API-key auth, circuit-breaker-protected tool calls | | API Docs | OpenAPI 3.1 on every service via springdoc, aggregated single Swagger UI at the gateway | | Auth & Security | JWT access/refresh tokens, OAuth2 Google login, BCrypt password hashing, email verification, audit logging, header-based service-to-service auth enforced independently on every service | | URL Shortening | Base62 encoding, custom slugs, expiry dates, cache-aside Redis caching - 1,332 req/s at 24 ms avg p50 on a single instance | | Analytics | Real-time click counters (Redis), hourly rollups, Bloom-filter click deduplication, per-user top-URLs leaderboard | | Service Discovery | Netflix Eureka - all 5 business services self-register; gateway routes via lb:// for dynamic load balancing | | Resilience | Resilience4j circuit breakers + retries on every cross-service call, with custom fallbacks; DLQ + scheduled retry for failed Kafka publishes | | Distributed Jobs | ShedLock-coordinated scheduled jobs (expiry cleanup, cache warming, DLQ retry, token cleanup) - safe across multiple instances | | Gateway | Spring Cloud Gateway (WebFlux) - central JWT validation, Redis token-bucket rate limiting, per-route circuit breakers, CORS, trace ID propagation | | Observability | Custom Grafana dashboard (request rate, latency, JVM heap/threads, GC pauses, error rate, circuit breaker state), Prometheus metrics across all 6 services, structured JSON logging (Logback + Logstash encoder), MDC trace IDs | | Modern Java | Java 25, virtual threads, records for all DTOs/events, sealed types, text blocks for SQL/prompts |


📊 Observability

Every service exposes /actuator/prometheus. The included Grafana dashboard (provisioned automatically via docker compose up) ships with:

  1. HTTP request rate - traffic per service
  2. Average latency - per-service response times
  3. Circuit breaker state - CLOSED / OPEN / HALF_OPEN per downstream dependency
  4. JVM heap + GC - memory pressure visible at a glance
  5. 5xx error rate - errors separated from normal traffic
  6. Active virtual threads - thread pool health

🛡️ Resilience

Two layers of circuit breakers, both Resilience4j, both Spring Boot 4 native:

  • ai-serviceurl-service / analytics-service - @CircuitBreaker + @Retry + @TimeLimiter on CompletableFuture-returning ops methods, backed by explicit readTimeout on the underlying RestClient (shorter than the TimeLimiter window) so cancellation is real, not just cosmetic. 4xx responses pass through untouched; connection failures and 5xx trip the breaker and trigger a friendly fallback the agent relays in plain English.
  • api-gateway → all 4 downstream services - declarative CircuitBreaker route filters per service, with per-service-tuned thresholds (LLM-backed ai-service gets longer slow-call/timeout windows than CRUD services) and a dedicated FallbackController returning structured 503 JSON instead of hangs or raw stack traces.

🛠️ Tech Stack

| Layer | Technology | |---|---| | Language / Runtime | Java 25 (virtual threads enabled) | | Framework | Spring Boot 4, Spring Cloud Gateway, Spring Security 7 | | Service Discovery | Netflix Eureka (Spring Cloud) | | AI | Spring AI 2.0, ReAct tool-calling agent, MCP server, OpenAI-compatible LLM (Groq) | | API Docs | springdoc-openapi 3 (OpenAPI 3.1, Swagger UI, gateway-aggregated) | | Database | PostgreSQL 16 + Liquibase migrations | | Cache / Rate Limiting | Redis 7 (RedisBloom module) | | Messaging | Apache Kafka | | Build | Maven (multi-module) | | Containerization | Docker + Docker Compose (15-container stack) | | Resilience | Resilience4j (resilience4j-spring-boot4, Spring Cloud Circuit Breaker), ShedLock | | Logging | SLF4J + Logback + Logstash JSON encoder, Loki + Promtail | | Metrics | Micrometer + Prometheus + Grafana | | Load Testing | k6 |


📡 Services at a Glance

| Service | Port | Responsibility | |---|---|---| | eureka-server | 8761 | Service registry - all 5 services below register here | | api-gateway | 8080 | Single entry point - JWT validation, rate limiting, circuit breakers, routing, CORS, aggregated Swagger UI | | auth-service | 8081 | Registration, login, JWT/refresh tokens, OAuth2 Google, email verification, MCP API keys | | url-service | 8082 | URL shortening, Base62 slugs, redirects, cache-aside Redis, Kafka event publishing | | analytics-service | 8083 | Kafka consumer for click events, Bloom-filter dedup, real-time + hourly analytics | | ai-service | 8084 | ReAct agent, MCP server, AI URL classification, slug suggestions, safety checks, summaries |


📂 Project Structure

shortlyai/
├── docker-compose.yml       # full 15-container stack
├── prometheus.yml
├── promtail-config.yml
├── grafana/provisioning/    # auto-provisioned datasource + dashboard
├── eureka-server/
├── api-gateway/             # routing, auth, rate limiting, circuit breakers, Swagger aggregation
├── auth-service/            # JWT + OAuth2 + refresh tokens + MCP API keys
├── url-service/
│   └── src/main/java/com/shortlyai/url/
│       ├── shortening/      # Base62, core CRUD
│       ├── redirect/        # Public redirect endpoint
│       ├── expiry/          # Scheduled cleanup
│       ├── consumer/        # Consumes AI classification results
│       ├── dlq/             # Dead-letter-queue retry
│       └── events/          # Kafka event records
├── analytics-service/       # Click tracking, Bloom filter, rollups
└── ai-service/
    └── src/main/java/com/shortlyai/ai/
        ├── agent/           # ChatClient + @Tool methods (circuit-breaker protected)
        ├── mcp/             # MCP server tools + API key auth filter
        ├── classification/  # AI title/category/safety pipeline
        ├── slug/            # AI slug suggestions
        ├── safety/          # Phishing/scam URL analysis
        └── summary/         # AI-generated analytics summaries

Every service follows feature-based packaging, each feature folder contains its own controller, service, repository, and DTOs. No layer-based controllers/, services/, repositories/ folders.


🗺️ Project Status

  • [x] eureka-server - service discovery for all 5 business services
  • [x] auth-service - JWT, OAuth2 Google, refresh tokens, audit logging, MCP API keys
  • [x] url-service - shortening, redirects, cache-aside, Kafka events, DLQ retry
  • [x] analytics-service - click tracking, Bloom filter dedup, hourly rollups, per-user leaderboard
  • [x] api-gateway - JWT validation, rate limiting, routing, CORS, circuit breakers, aggregated Swagger UI
  • [x] ai-service - ReAct agent, AI classification pipeline, slug/safety/summary endpoints
  • [x] MCP server - tested end-to-end with Claude Desktop via mcp-remote
  • [x] OpenAPI / Swagger UI - every service, aggregated at the gateway
  • [x] Full Docker containerization - 15 containers, single docker compose up
  • [x] Observability - Prometheus + custom Grafana dashboard (6 panels)
  • [x] Resilience4j circuit breakers - gateway-level + AI-agent-level + MCP-level, with fallbacks
  • [x] Load tested - 1,332 req/s @ 24 ms avg, 0 errors, single instance

🧠 Engineering Highlights

  • Event-driven SAGA choreography - URL creatio

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.