# Loyalty Agent Service A production-ready AI-powered assistant for managing a Loyalty platform, built on the **Model Context Protocol (MCP)**. ## Architecture ``` Frontend (React/Vite :9333) ↓ WebSocket (STOMP) loyalty-agent (:9332) ← Orchestrator + BFF ↓ MCP SSE Transport (/sse, /message) loyalty-mcp-server (:9331) ← MCP Tool Server ↓ REST + OAuth2 (Keycloak) Loyalty Core API (:8081) ← Backend Services ``` ### Modules | Module | Port | Role | |--------|------|------| | `loyalty-mcp-server` | 9331 | MCP Server — exposes 25 tools via SSE transport | | `loyalty-agent` | 9332 | AI Agent — orchestrates LLM + MCP tools | | Frontend (root) | 9333 | React/Vite chat UI | ## Technology Stack - **Java 25**, Spring Boot 4.0.0, Spring AI 2.x - **MCP Transport**: SSE (WebMVC) via `spring-ai-starter-mcp-server-webmvc` - **LLM**: Ollama (qwen3.5:4b, configurable) - **Auth**: Keycloak OAuth2 Client Credentials - **Persistence**: PostgreSQL (agent conversation history) - **Frontend**: React + Vite + WebSocket (STOMP) ## MCP Capabilities ### Tools (25 registered) | Category | Tools | |----------|-------| | Campaign | `searchCampaigns`, `countCampaigns`, `getCampaignById`, `getCampaignsByIds`, `generateCampaignId`, `checkCampaignId`, `createCampaign` | | Campaign Rule | `searchRules`, `countRules`, `getRuleById`, `getRulesByIds`, `generateRuleId`, `checkRuleId`, `createRule`, `findMatchingRules` | | Pool Definition | `getPoolDefinitionById`, `getPoolDefinitionsByIds`, `searchPoolDefinitions` | | Counter | `getCounterDefinitionById`, `getCounterDefinitionsByIds` | | Deduction Sequence | `getDeductionSequenceById`, `getDefaultDeductionSequence` | | Transaction Code | `getTransactionCode`, `getTransactionCodes`, `checkTransactionCodeExists` | ### Resources & Prompts - Resources, resource templates, prompts, and completions capabilities are enabled via Spring AI autoconfiguration - Currently no custom resources or prompts defined (the autoconfiguration registers empty capability declarations) ### Transport - **SSE**: `/sse` endpoint for server-sent events - **Message**: `/message` endpoint for client-to-server messages - **Keep-alive**: 30-second interval configured ## Startup Instructions ### Prerequisites - Java 25+ - Node.js & pnpm - PostgreSQL (for agent persistence) - `.env` file created (see `.env` for template) ### Start Backend Modules ```bash # Start both modules with one script: ./start-all.sh # Or start individually: ./mvnw spring-boot:run -pl loyalty-mcp-server ./mvnw spring-boot:run -pl loyalty-agent ``` ### Start Frontend ```bash pnpm install pnpm dev ``` ### Configuration Key environment variables (see `.env`): | Variable | Description | |----------|-------------| | `LOYALTY_CORE_BASE_URL` | Base URL for Loyalty Core API | | `KEYCLOAK_TOKEN_URI` | Keycloak token endpoint | | `KEYCLOAK_CLIENT_ID` | OAuth2 client ID | | `KEYCLOAK_CLIENT_SECRET` | OAuth2 client secret | | `SPRING_DATASOURCE_URL` | PostgreSQL connection for agent | | `OLLAMA_BASE_URL` | Ollama LLM endpoint | ## Error Handling - **AOP Aspect** (`GlobalToolExceptionHandlerAspect`): Wraps all `@McpTool` methods, catches exceptions and returns safe `Result.failure()` responses - **REST Exception Handler** (`GlobalMcpExceptionHandler`): Catches transport-level exceptions with safe error response - **Agent-side** (`ToolInterceptor`): Sanitizes error responses, auto-reconnects on dropped SSE connections, truncates large results ## Security - OAuth2 Client Credentials flow for backend API authentication - No internal stack traces or credentials exposed to MCP client - Input validation on all tool parameters - Response body logging limited to debug level with truncation ## Running Tests ```bash # All tests ./mvnw test # MCP server tests only ./mvnw test -pl loyalty-mcp-server # Agent tests only ./mvnw test -pl loyalty-agent ``` ## Health Checks Both services expose Spring Boot Actuator health endpoints: ``` GET /actuator/health — Overall health GET /actuator/health/liveness — Kubernetes liveness probe GET /actuator/health/readiness — Kubernetes readiness probe ``` ## Additional Tools (Domain Services) | Category | Tools | |----------|-------| | App Param | `searchAppParam`, `getAppParamById` | | Dynamic Attribute | `searchDynamicAttribute`, `getDynamicAttributeById` | | Journey | `searchJourney`, `getJourneyById` | | User | `searchUser`, `getUserById` | | Customer | `searchCustomers`, `getCustomerById` | | Catalogue | `searchCatalogues`, `getCatalogueById` | | Transaction | `searchTransactions`, `getTransactionById` | ## Further Documentation - [ARCHITECTURE.md](ARCHITECTURE.md) — System architecture, data flow, security model - [DEPLOYMENT.md](DEPLOYMENT.md) — Production deployment guide - [.env.example](.env.example) — Environment variable template