Skip to content

albonidrizi/event-management

Repository files navigation

Event Management API

CI Java 17 MCP License: MIT

Event-management backend with two first-class interfaces: a JAX-RS REST API for applications and a Model Context Protocol server for AI clients. Both interfaces reuse the same validation, transactions, services, JDBC repositories, and MySQL data.

Why This Project Stands Out

  • One domain exposed through REST, local MCP stdio, and remote MCP Streamable HTTP.
  • 32 MCP tools, 7 resources, and 8 parameterized resource templates.
  • Real business workflows: capacity checks, transactional bulk registration, cancellation, check-in, audit logs, status history, pagination, reporting, and CSV export.
  • No ORM: SQL, joins, aggregations, transactions, and repository boundaries are explicit.
  • Reproducible setup with Docker Compose, Maven Wrapper, seeded MySQL, CI, and integration tests with a 60% line-coverage gate.
  • Safe-by-default configuration: no committed database password and guarded remote MCP binding.

Stack

  • Java 17+
  • Jersey / JAX-RS
  • Apache Tomcat 9
  • JDBC
  • MySQL
  • Maven
  • JSON request/response bodies
  • Model Context Protocol server over stdio
  • No ORM

Architecture

flowchart LR
    App["REST clients"] --> REST["JAX-RS resources"]
    AI["Gemini / Claude / Copilot / ChatGPT"] --> MCP["MCP stdio or HTTP"]
    REST --> Service["Shared services and business rules"]
    MCP --> Service
    Service --> Repo["JDBC repositories"]
    Repo --> DB[("MySQL")]
Loading

REST and MCP run as separate processes, but they reuse the same business logic, validation, transactions, repositories, and MySQL database.

Packages:

config       JAX-RS, Jackson, database connection config
model        Entity models and status enums
dto          Request/response DTOs
resource     REST endpoints
mcp          MCP server, tools, resources, and resource templates
service      Business logic, validation, transactions
repository   JDBC SQL access
exception    JSON error handling

Main Business Modules

  • Event categories
  • Events
  • Participants
  • Event registrations
  • Check-in flow
  • Registration summary reports

Quick Start With Docker

Requirements: Docker Desktop and Git.

cp .env.example .env
# Replace every placeholder in .env, then:
docker compose up --build

Verify the REST API:

GET http://localhost:8081/event-management-api/api/events/health

Run the optional protected MCP HTTP container too:

docker compose --profile mcp-http up --build

The MCP endpoint is http://localhost:8090/mcp and requires the Bearer token configured in .env.

Database Setup

Database URL and username have local defaults. The password is intentionally required and must be supplied outside Git:

DB_URL=jdbc:mysql://localhost:3306/event_management?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
DB_USERNAME=root
DB_PASSWORD=your-local-password

You can override these with environment variables or JVM system properties:

-Devent.db.url=jdbc:mysql://localhost:3306/event_management?useSSL=false&serverTimezone=UTC
-Devent.db.username=root
-Devent.db.password=your_password

Create the database:

CREATE DATABASE event_management;
USE event_management;

Then run:

src/main/resources/schema.sql

Optional sample data:

src/main/resources/seed-data.sql

The schema includes primary keys, foreign keys, unique constraints, indexes, soft delete flags, and audit columns. It also includes extension tables for registration status history and audit logs.

Build

./mvnw clean package

Outputs:

target/event-management-api.war
target/event-management-mcp.jar
target/event-management-mcp-http.jar

MCP Server

The project includes an executable Model Context Protocol server built with the official Java MCP SDK and the stdio transport.

It exposes:

  • 32 tools for reading and changing event-management data
  • 7 static read-only resources
  • 8 parameterized resource templates
  • CRUD operations for categories, participants, events, and registrations
  • Registration, bulk registration, cancellation, check-in, reports, CSV export, status history, and audit logs

MCP resources are read-only. MCP tools can read, create, update, and delete data.

Two MCP transports are available:

  • event-management-mcp.jar: local stdio transport for Gemini CLI and similar clients
  • event-management-mcp-http.jar: Streamable HTTP transport for ChatGPT and remote MCP clients

The stdio server is tested with Gemini CLI, Claude Code, and GitHub Copilot in VS Code.

Build both the REST API and MCP server:

./mvnw clean package

Normally, an MCP client starts the server automatically using:

java -jar target/event-management-mcp.jar

Connect Gemini CLI

Register the MCP server from the project directory:

gemini mcp add --scope project --transport stdio --timeout 30000 event-management java -- -jar "C:\absolute\path\to\target\event-management-mcp.jar"

Verify the connection:

gemini mcp list

Expected status:

event-management - Connected

Example prompts:

List all active participants using event-management MCP.
Create a category named Music using event-management MCP.
Show the registration summary for event ID 1.

Connect ChatGPT

Start the Streamable HTTP server:

java -jar target/event-management-mcp-http.jar

It listens on:

http://127.0.0.1:8090/mcp

Expose it temporarily over HTTPS:

ngrok http 8090

In ChatGPT, enable developer mode, create a custom app/connector, and use:

https://your-ngrok-domain.ngrok.app/mcp

Localhost mode can run without authentication. Set MCP_HTTP_BEARER_TOKEN to protect compatible clients. The server refuses to bind outside localhost without a token unless MCP_HTTP_ALLOW_INSECURE_REMOTE=true is explicitly set for a temporary test-data demo. A production deployment should use stable HTTPS and OAuth 2.1.

Connect Claude Code

claude mcp add --transport stdio --scope local event-management -- java -jar target/event-management-mcp.jar
claude mcp list

Connect GitHub Copilot

The included .vscode/mcp.json configures the local stdio server. In VS Code, open Copilot Chat, select Agent, and enable event-management from the tools picker.

Full MCP setup, client configuration, tools, and resources are documented in:

MCP.md

Run Locally

REST and MCP do not require one shared process:

  • Run REST with Maven Cargo when testing HTTP endpoints.
  • Gemini CLI or another MCP client starts the MCP JAR when it needs MCP tools.
  • Both processes connect directly to the same MySQL database.

With embedded Tomcat 9 through Maven Cargo:

./mvnw package cargo:run

The project is configured for port 8081.

Health check:

GET http://localhost:8081/event-management-api/api/events/health

Response:

{
  "status": "API is running"
}

MCP health prompt:

Use event-management MCP to check the server health.

Verification

Run the automated tests:

./mvnw verify

The integration tests verify MCP initialization over stdio and Streamable HTTP, Bearer token protection, complete write lifecycles, all read tools and resources, parameterized resources, concurrent tool calls, database row counts, and clean shutdown after the stdio client disconnects. CI runs the same verification against a real MySQL service, enforces at least 60% line coverage, and publishes the JaCoCo report as an artifact.

For a quick REST walkthrough after startup:

./scripts/demo-rest.ps1

Deploy to Tomcat

  1. Install Apache Tomcat 9.
  2. Build with mvn clean package.
  3. Copy target/event-management-api.war to Tomcat webapps.
  4. Start Tomcat.
  5. Use:
http://localhost:8080/event-management-api/api/events/health

Use Tomcat 9, not Tomcat 10, because this project uses javax.ws.rs and Servlet 4.

Error Format

All handled errors return JSON:

{
  "errorCode": "VALIDATION_ERROR",
  "message": "capacity must be greater than 0"
}

Common status codes:

  • 400 Bad Request: validation errors
  • 404 Not Found: missing entity
  • 409 Conflict: business conflict, duplicate registration, full event
  • 500 Internal Server Error: unexpected failure

Status Values

Event status:

ACTIVE
CANCELLED
COMPLETED

Registration status:

REGISTERED
CANCELLED
ATTENDED

Endpoints

Event Categories CRUD

GET    /api/event-categories
GET    /api/event-categories/{id}
POST   /api/event-categories
PUT    /api/event-categories/{id}
DELETE /api/event-categories/{id}

Events CRUD

GET    /api/events
GET    /api/events?status=ACTIVE
GET    /api/events?categoryId=1
GET    /api/events/{id}
POST   /api/events
PUT    /api/events/{id}
DELETE /api/events/{id}

Participants CRUD

GET    /api/participants
GET    /api/participants/{id}
POST   /api/participants
PUT    /api/participants/{id}
DELETE /api/participants/{id}

Registrations CRUD

GET    /api/registrations
GET    /api/registrations/{id}
POST   /api/registrations
PUT    /api/registrations/{id}
DELETE /api/registrations/{id}

Business Endpoints

POST /api/events/{id}/register
POST /api/events/{id}/register-bulk
POST /api/events/{id}/cancel-registration
POST /api/registrations/{id}/check-in
GET  /api/registrations/{id}/status-history
GET  /api/events/{id}/participants
GET  /api/events/{id}/participants/export
GET  /api/events/available
GET  /api/events/search?search=java&page=1&size=10
GET  /api/events/{id}/registration-summary
GET  /api/audit-logs

Extensions Added

  • Status history: registration_status_history stores old and new registration statuses.
  • Pagination and search: GET /api/events/search supports search, status, categoryId, page, and size.
  • Audit table: audit_log records registration actions such as register, bulk register, cancel, and check-in.
  • CSV export: GET /api/events/{id}/participants/export returns participants as text/csv.
  • Bulk operation: POST /api/events/{id}/register-bulk registers multiple participants in one transaction.

Business Endpoint Design

Full endpoint-by-endpoint business design is documented in:

BUSINESS_DESIGN.md

POST /api/events/{id}/register

Purpose: registers a participant for an active event if capacity is available.

Request:

{
  "participantId": 1
}

Validation:

  • Event must exist.
  • Participant must exist.
  • Event status must be ACTIVE.
  • Event date must not be in the past.
  • Participant must not already be registered.
  • Capacity must not be full.

Processing:

  • Opens a JDBC transaction.
  • Reads event and participant.
  • Checks existing registration and capacity.
  • Inserts event_registration.
  • Commits or rolls back.

Failure cases:

  • 400 missing participantId
  • 404 event or participant missing
  • 409 duplicate registration or full event

POST /api/registrations/{id}/check-in

Purpose: marks a registered participant as attended.

Validation:

  • Registration must exist.
  • Cancelled registration cannot be checked in.
  • Already attended registration returns conflict.

Processing:

  • Opens a transaction.
  • Reads registration.
  • Updates status to ATTENDED.
  • Commits or rolls back.

GET /api/events/{id}/participants

Purpose: lists participants registered for an event.

SQL concept: uses JOIN between event_registration and participant.

GET /api/events/{id}/registration-summary

Purpose: returns capacity, registered, attended, cancelled, and remaining seats.

SQL concept: uses SUM(CASE ...), GROUP BY, and calculated remaining capacity. The implementation also includes COUNT and AVG in this summary query.

Example response:

{
  "eventId": 1,
  "eventTitle": "Java Backend Workshop",
  "capacity": 40,
  "totalRegistrations": 22,
  "registered": 12,
  "attended": 8,
  "cancelled": 2,
  "remaining": 28,
  "attendanceRate": 0.36
}

Example Requests

Use:

src/main/resources/api-examples.http

or import the same URLs manually in Postman or Charles.

Project Documents

About

Production-ready Java event management backend with REST API, MySQL, Docker, CI/CD, and MCP integration for ChatGPT, Gemini, Claude, and Copilot.

Topics

Resources

License

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages