dev-zeromoblt/OPlatformStudentMCP
If you are the rightful owner of OPlatformStudentMCP and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
The OPlatform Student MCP Server is a Model Context Protocol server designed to interface with the Student API, leveraging Redis FT.SEARCH capabilities for advanced querying, including geo-radius queries.
OPlatform Student MCP Server
MCP (Model Context Protocol) server for querying the Student API with Redis FT.SEARCH capabilities, including geo-radius queries.
Features
- Get Student by ID: Retrieve complete student details using their unique Zrn identifier
- Advanced Search: Redis FT.SEARCH powered queries with support for:
- Full-text search on names and addresses
- Tag-based filtering (status, grade, subscription, gender, campus)
- Geo-radius queries (find students within X km/mi of a location)
- Complex boolean queries with AND/OR operators
- Pagination support
- Real-Time Location Tracking: MQTT integration for live student location updates
- Subscribe to student location topics via AWS IoT Core
- Automatic credential refresh and connection management
- Cached location data for instant access
- Handles retained messages for last known locations
- Parent Location Tools: Answer common parent questions with contextual information:
- Where is my child? - Get current location with trip status and context
- What time will my child be back? - Get expected return time based on trip schedule
- Trip Search: Query trips with Redis FT.SEARCH for detailed transportation information
Architecture
┌─────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Claude │◄────►│ Student MCP │◄────►│ Student API │
│ Desktop │ stdio│ Server │ HTTP │ (Redis Search) │
└─────────────┘ └──────────────────┘ └─────────────────┘
│ │
│ │ IoT Creds
▼ ▼
┌─────────────┐ ┌─────────────────┐
│ Smithy Gen │ │ AWS IoT Core │
│ TypeScript │ │ (MQTT Broker) │
│ Models │ └─────────────────┘
└─────────────┘ ▲
│ MQTT
│
┌──────┴──────┐
│ Mobile App │
│ (Location) │
└─────────────┘
Prerequisites
- Node.js >= 18
- TypeScript
- Access to Student API endpoint
- Valid JWT authentication token
Local Development Setup
1. Build Smithy Models and Install Dependencies
The project uses Smithy-generated TypeScript models packaged as a local tarball dependency.
Option A: Use the automated build script (Recommended)
cd /Users/zeroman/workplace/nowzone/OPlatformStudentMCP
./build-with-models.sh
This script will:
- Build the Smithy models from OPlatformModels
- Pack them as a tarball
- Copy the tarball to
src/generated/ - Install all dependencies (including the packaged model)
- Build the TypeScript project
Option B: Manual steps
cd /Users/zeroman/workplace/nowzone/OPlatformStudentMCP
# Build and package Smithy models
npm run model
# Build the project
npm run build
3. Set Environment Variables
Create a .env file or export variables:
# Required
export STUDENT_API_ENDPOINT="https://api.zeromoblt.com"
export STUDENT_API_AUTH_TOKEN="your-jwt-token-here"
# MQTT Configuration (for real-time location tracking)
export IOT_ENDPOINT="your-iot-endpoint.iot.us-east-1.amazonaws.com"
export IOT_REGION="us-east-1"
# Optional MQTT settings
export MQTT_MAX_SUBSCRIPTIONS="100"
export MQTT_CREDENTIAL_REFRESH_INTERVAL="2580000" # 43 minutes in ms
4. Test Locally with Claude Desktop
Create or update ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"student-search": {
"command": "node",
"args": ["/Users/zeroman/workplace/nowzone/OPlatformStudentMCP/dist/index.js"],
"env": {
"STUDENT_API_ENDPOINT": "https://api.zeromoblt.com",
"STUDENT_API_AUTH_TOKEN": "your-jwt-token-here",
"IOT_ENDPOINT": "your-iot-endpoint.iot.us-east-1.amazonaws.com",
"IOT_REGION": "us-east-1"
}
}
}
}
Restart Claude Desktop to load the MCP server.
Quick Token Update (macOS):
Update your token quickly when it expires:
# 1. Copy JWT token from browser to clipboard
# 2. Run the update script
npm run update-token
# or: yarn update-token
# 3. Restart Claude Desktop
This automatically updates your Claude Desktop config with the token from clipboard. See for details.
Usage Examples
Get Student by ID
"Get student with ID ZST12345"
The MCP server will call:
{
"tool": "get_student",
"arguments": {
"id": "ZST12345"
}
}
Parent Location Tools
The parent location tools use real-time MQTT location tracking to provide accurate, up-to-the-second information about student whereabouts.
Where is my child?
"Where is student ZST12345?"
"What is the current location of my child ZST12345?"
Example responses with location freshness information:
- "Your child is at home (123 Main St, Hyderabad), waiting for pickup. The school bus is scheduled to arrive at 7:30 AM."
- "Your child is currently on the way to school (location updated 30 seconds ago). They are expected to arrive at ABC Campus at 8:15 AM."
- "Your child is at school (ABC Campus, 456 School Rd). They are scheduled for pickup at 3:00 PM."
- "Your child is on the way home (location updated just now). They are expected to arrive at 4:30 PM."
- "Your child arrived at school 15 minutes ago (ABC Campus, 456 School Rd)."
- "Your child arrived home 5 minutes ago (123 Main St, Hyderabad)."
Location Context by Trip Status:
- SCHEDULED/ACCEPTED + ONWARD: Student is at home, waiting for pickup
- SCHEDULED/ACCEPTED + RETURN: Student is at campus, waiting for pickup
- STARTED + ONWARD: Real-time location via MQTT - "on the way to school"
- STARTED + RETURN: Real-time location via MQTT - "on the way home"
- COMPLETED + ONWARD: Student is at campus (arrived at school)
- COMPLETED + RETURN: Student is at home (arrived home)
- No active trip: Last known location from MQTT (if available within 6 hours)
What time will my child be back?
"What time will student ZST12345 be back home?"
"When is my child returning home today?"
Example responses:
- "Your child is expected to return home at 4:30 PM. The return trip from ABC Campus is scheduled to depart at 3:45 PM."
- "Your child is currently on the way home and is expected to arrive at 4:25 PM (in approximately 15 minutes)."
- "Your child is at school, but no return trip is scheduled yet for today."
- "Your child is not scheduled for transportation today."
Location Fallback Behavior: When MQTT is unavailable or location data cannot be retrieved, the system uses a multi-tier fallback strategy:
- MQTT Real-Time Location (Primary): Live GPS coordinates from mobile app
- Task Location Fallback (Secondary): Actual GPS coordinates from route tracking tasks
- Generic Message (Final): Trip schedule and address information
This ensures parents always receive the most accurate location information available, even during MQTT outages.
Search Examples
Find all active students:
"Search for all active students"
→ Query: @status:{ACTIVE}
Find students by name:
"Find students named Basavaraju"
→ Query: @name:Basavaraju
Find students in a specific grade:
"Find all students in class 10 or class 11"
→ Query: @grade:{CLASS_10|CLASS_11}
Geo-radius search:
"Find students named Kumar within 5km of Empire State Building (40.748817, -73.985428)"
→ Query: @name:Kumar with lat=40.748817, lng=-73.985428, radius=5, unit=km
Complex queries:
"Find active class 12 students at campus ZCA00123"
→ Query: @status:{ACTIVE} @grade:{CLASS_12} @campusId:{ZCA00123}
Real-Time Location Tracking
The MCP server integrates with AWS IoT Core to provide real-time student location updates via MQTT. This enables accurate, up-to-the-second location information for parent queries.
Task Location Fallback
When MQTT real-time tracking is unavailable (e.g., during service outages), the system automatically falls back to Task Location Data to provide actual GPS coordinates instead of generic messages.
How It Works:
- Primary Source - MQTT: System first attempts to retrieve real-time location from MQTT
- Fallback Source - Task API: If MQTT is unavailable, system queries the Task API for route tracking data
- Coordinate Extraction: Extracts GPS coordinates from task
transitionInfo(origin/destination) - Smart Caching: Caches task location data for 30 seconds to minimize API calls
- Graceful Degradation: Falls back to generic message if both MQTT and Task data unavailable
Example Output with Task Fallback:
"Your child is on the way to school (last known location: 17.418806, 78.400413,
updated 2 minutes ago). They are expected to arrive at ABC Campus at 8:15 AM."
Configuration:
No additional configuration required. Task location fallback is automatically enabled when:
- Student has an active trip with status
STARTED - MQTT location data is unavailable
- Trip has associated tasks with valid location coordinates
Benefits:
- Transparency: Parents see actual coordinates instead of "location unavailable"
- Reliability: System continues to provide location data during MQTT outages
- Accuracy: Task coordinates reflect actual route tracking data
- Performance: 30-second cache reduces API load
Location Data Sources:
| Source | Freshness | Accuracy | Use Case |
|---|---|---|---|
| MQTT Real-Time | < 30 seconds | High (live GPS) | Normal operation |
| Task Location | 1-5 minutes | Medium (route tracking) | MQTT outage fallback |
| Generic Message | N/A | Low (scheduled only) | No location data available |
How It Works
- Mobile App Publishes: The student's mobile app publishes location updates to AWS IoT MQTT topics (
ZR-{studentUsername}) - MCP Server Subscribes: When location is requested, the server subscribes to the student's topic
- Instant Updates: Location updates are received in real-time and cached in memory
- Retained Messages: Last known location is delivered immediately upon subscription
- Automatic Cleanup: Subscriptions are removed when no longer needed
MQTT Configuration
Required Environment Variables
# AWS IoT Core endpoint (get from AWS IoT Console)
IOT_ENDPOINT="a3example.iot.us-east-1.amazonaws.com"
# AWS region where IoT Core is deployed
IOT_REGION="us-east-1"
Optional Configuration
# Maximum concurrent MQTT subscriptions (default: 100)
MQTT_MAX_SUBSCRIPTIONS="100"
# Credential refresh interval in milliseconds (default: 43 minutes)
MQTT_CREDENTIAL_REFRESH_INTERVAL="2580000"
Credential Management
The MQTT service automatically manages AWS IoT credentials:
- Automatic Refresh: Credentials are refreshed every 43 minutes (17-minute buffer before 60-minute expiry)
- Secure Storage: Temporary credentials only, stored in memory
- Retry Logic: Failed refreshes are retried with exponential backoff (2min, 5min, 10min)
- Connection Re-establishment: Fresh connection created when credentials are refreshed
Connection Management
The MQTT connector implements robust connection handling:
- Auto-Reconnection: Exponential backoff (2s, 4s, 8s, 16s, 32s, 60s, 120s max)
- Heartbeat Monitoring: 30-second keep-alive intervals
- Connection Timeout: Progressive timeout (45s base, increases with retries)
- Max Attempts: Up to 10 reconnection attempts before giving up
Subscription Management
Efficient subscription handling prevents resource exhaustion:
- Dynamic Subscriptions: Subscribe only when location is requested
- Subscription Reuse: Multiple requests for same student share one subscription
- Delayed Unsubscription: 30-second delay to handle rapid re-subscriptions
- Subscription Limit: Maximum 100 concurrent subscriptions
Location Data Caching
Location data is cached in memory for instant access:
- Retained Messages: Last known location delivered immediately on subscription
- Age Validation: Retained messages older than 6 hours are discarded
- Live Updates: Cache updated in real-time as new locations arrive
- Metadata Included: Timestamp, accuracy, speed, altitude, bearing, provider
Location Data Format
{
latitude: 17.421, // Decimal degrees
longitude: 78.399, // Decimal degrees
timestamp: 1699876543210, // Unix timestamp (ms) from mobile app
accuracy: 10.5, // Meters
speed: 2.3, // Meters per second
altitude: 520.0, // Meters
bearing: 45.0, // Degrees (0-360)
provider: "fused", // 'gps', 'network', 'fused'
lastUpdated: 1699876543500,// When MCP server received this
isRetained: false // Whether from retained MQTT message
}
Health Monitoring
Check MQTT service health via the health endpoint:
curl http://localhost:5000/health
Response includes:
- Connection status (connected/disconnected)
- Credentials validity (time remaining)
- Active subscription count
- Last heartbeat timestamp
Troubleshooting MQTT
See the Troubleshooting section below for common MQTT issues and solutions.
Redis Search Query Syntax
TEXT Fields (full-text search)
@name:Basavaraju- Contains "Basavaraju"@givenName:Raj*- Starts with "Raj"@familyName:"Kumar Singh"- Exact phrase
TAG Fields (exact match)
@status:{ACTIVE}- Single value@status:{ACTIVE|PENDING_DUES}- OR condition@grade:{CLASS_11|CLASS_12}- Multiple values
Available Fields
TEXT: name, givenName, familyName, middleName, geoAddress
TAG: status, grade, subscription, gender, campusId, primaryParentId, secondaryParentId
GEO: location (use with longitude, latitude, radius parameters)
NUMERIC: birthdate, startDate, updatedAt
Operators
*- Wildcard|- OR (within tags)-- NOT()- Grouping
See src/schemas/redis-schema.txt for complete reference.
Docker Build
Important: Before building the Docker image, you must build and pack the Smithy models:
cd /Users/zeroman/workplace/nowzone/OPlatformStudentMCP
# Build and pack models
npm run model
# Build Docker image
docker build -t student-mcp:latest .
The Dockerfile expects src/generated/smithy-o-platform-client.tgz to exist before the build.
Kubernetes Deployment
Prerequisites
- Configure Pulumi secrets:
cd /Users/zeroman/workplace/nowzone/now-zeromoblt
pulumi config set studentApiEndpoint https://api.zeromoblt.com
pulumi config set --secret studentApiAuthToken "your-jwt-token"
- Import deployment in
index.ts:
import "./deployments/student-mcp";
- Deploy:
pulumi up
View Logs
kubectl logs -n student-mcp-dev -l app=student-mcp-server -f
Project Structure
OPlatformStudentMCP/
├── src/
│ ├── index.ts # MCP server entry point
│ ├── stdio-server.ts # Claude Desktop/Kiro integration
│ ├── http-server.ts # HTTP server mode
│ ├── client/
│ │ └── apiClient.ts # Student API HTTP client
│ ├── services/
│ │ ├── mqttService.ts # MQTT service singleton
│ │ └── iotConnector.ts # AWS IoT SDK wrapper
│ ├── tools/
│ │ ├── getStudent.ts # Get student by ID tool
│ │ ├── searchStudents.ts # Search students tool
│ │ ├── getTrip.ts # Get trip by ID tool
│ │ ├── searchTrips.ts # Search trips tool
│ │ ├── getStudentLocation.ts # Get student location tool
│ │ └── getStudentReturnTime.ts # Get student return time tool
│ ├── utils/
│ │ └── locationContextBuilder.ts # Location context utilities
│ └── schemas/
│ └── redis-schema.txt # Redis search documentation
├── package.json
├── tsconfig.json
├── Dockerfile
└── README.md
Environment Variables
| Variable | Required | Description |
|---|---|---|
STUDENT_API_ENDPOINT | Yes | Student API base URL |
STUDENT_API_AUTH_TOKEN | No | Default JWT authentication token (can be overridden per-request) |
IOT_ENDPOINT | Yes* | AWS IoT Core endpoint URL (required for real-time location tracking) |
IOT_REGION | Yes* | AWS region for IoT Core (default: us-east-1) |
MQTT_MAX_SUBSCRIPTIONS | No | Maximum concurrent MQTT subscriptions (default: 100) |
MQTT_CREDENTIAL_REFRESH_INTERVAL | No | Credential refresh interval in milliseconds (default: 2580000 = 43 minutes) |
* Required only if using real-time location tracking features
Authentication
The server supports two authentication modes:
-
Per-Request Token (Recommended): Pass
authTokenparameter with each tool call- Allows dynamic token refresh
- More secure (token not hardcoded)
- Example:
{ "id": "ZST123", "authToken": "eyJ..." }
-
Default Environment Token: Set
STUDENT_API_AUTH_TOKENenvironment variable- Used when no token provided in request
- Simpler for single-user scenarios
See for detailed authentication guide.
API Reference
Tools
get_student
Retrieve a student by their unique Zrn identifier.
Input:
{
id: string, // Zrn format: Z[A-Z]{2}[0-9]{5,10}
authToken?: string // Optional: JWT token (overrides env)
}
Output: Full student object with all fields from Smithy model.
search_students
Search students using Redis FT.SEARCH syntax.
Input:
{
query: string, // Required: Redis FT.SEARCH query
offset?: number, // Pagination offset
limit?: number, // Results per page (max 100)
longitude?: number, // Geo search: center longitude
latitude?: number, // Geo search: center latitude
radius?: number, // Geo search: radius distance
unit?: "km" | "mi", // Geo search: distance unit
authToken?: string // Optional: JWT token (overrides env)
}
Output:
{
students: StudentDetails[],
total: number
}
get_student_location
Get the current location of a student with contextual information.
Input:
{
studentId: string, // Required: Student Zrn (e.g., ZST12345)
authToken?: string // Optional: JWT token (overrides env)
}
Output: Human-readable text describing:
- Current location (home, school, or in transit)
- Trip status and context
- Pickup/arrival times
- Trip details (driver, vehicle, route)
Example:
"Your child is at home (123 Main St, Hyderabad), waiting for pickup.
The school bus is scheduled to arrive at 7:30 AM."
get_student_return_time
Get the expected return time for a student based on scheduled or active return trips.
Input:
{
studentId: string, // Required: Student Zrn (e.g., ZST12345)
authToken?: string // Optional: JWT token (overrides env)
}
Output: Human-readable text describing:
- Expected arrival time at home
- Trip status (scheduled, in progress)
- Departure time from school
- Trip details (driver, vehicle, route)
Example:
"Your child is expected to return home at 4:30 PM.
The return trip from ABC Campus is scheduled to depart at 3:45 PM."
get_trip
Retrieve a trip by its unique Zrn identifier.
Input:
{
id: string, // Zrn format: ZTR[0-9]{5,10}
authToken?: string // Optional: JWT token (overrides env)
}
Output: Full trip object with stops, status, driver, vehicle, and route information.
search_trips
Search trips using Redis FT.SEARCH syntax.
Input:
{
query: string, // Required: Redis FT.SEARCH query
offset?: number, // Pagination offset
limit?: number, // Results per page (max 100)
authToken?: string // Optional: JWT token (overrides env)
}
Output:
{
trips: TripDetails[],
total: number
}
Testing Queries
You can ask Claude questions like:
Student Queries:
- "How many active students are there?"
- "Find all class 12 students at campus ZCA00123"
- "Show me students within 10km of coordinates (17.367737, 78.563020)"
- "List students with pending dues"
- "Find students named Kumar in grades 11 or 12"
Parent Location Queries:
- "Where is my child?" (if Claude has context about student ID)
- "Where is student ZST12345?"
- "What is the current location of student ZST12345?"
- "What time will my child be back?"
- "When is student ZST12345 returning home today?"
- "Is my child at school or on the way?"
Trip Queries:
- "Show me all trips for student ZST12345 today"
- "Find all active trips for driver ZDR007084"
- "List completed trips on 2025-01-15"
- "Find trips stopping at campus ZCA000053"
Troubleshooting
MCP Server Not Connecting
- Check Claude Desktop config path
- Verify environment variables are set
- Check logs:
tail -f ~/Library/Logs/Claude/mcp*.log
Authentication Errors
- Verify JWT token is valid and not expired
- Check token has proper permissions for Student API
Build Errors
- "Cannot find module '@smithy/o-platform-client'": Run
npm run modelto build and pack the Smithy models - Missing tarball in Docker build: Run
npm run modelbeforedocker build - OPlatformModels build fails: Ensure Smithy models compile:
cd ../OPlatformModels && ./gradlew clean build
MQTT Connection Issues Affecting Location Tools
When MQTT connection issues occur, the parent location tools (get_student_location and get_student_return_time) may experience degraded functionality. Here's how to diagnose and resolve issues:
Impact on Location Tools
Symptoms:
- Location responses show "real-time location unavailable"
- Location freshness information is missing
- Only scheduled trip information is returned (no live updates)
- Responses fall back to home/campus addresses instead of actual location
Fallback Behavior: The location tools are designed to gracefully degrade when MQTT is unavailable:
- STARTED trips: Falls back to "on the way to school/home" without real-time position
- No active trips: Falls back to home address instead of last known location
- Location freshness: Not included when MQTT data unavailable
- Core functionality: Tools continue to work using trip schedule and addresses
MQTT Service Not Initializing
Symptoms:
- Location tools return "MQTT service not available"
- Health check shows MQTT disconnected
- Logs show "Failed to initialize MQTT"
Solutions:
-
Check environment variables:
echo $IOT_ENDPOINT echo $IOT_REGIONBoth must be set for MQTT to initialize.
-
Verify IoT endpoint format:
- Should be:
your-endpoint.iot.us-east-1.amazonaws.com - Get from AWS IoT Console → Settings → Device data endpoint
- Should be:
-
Check authentication:
- Ensure
STUDENT_API_AUTH_TOKENis valid - IoT credentials are fetched from Student API using this token
- Ensure
-
Review logs:
# Stdio mode (Claude Desktop) tail -f ~/Library/Logs/Claude/mcp*.log | grep MQTT # HTTP mode npm run dev:http 2>&1 | grep MQTT
Connection Keeps Dropping
Symptoms:
- MQTT connects then disconnects repeatedly
- Logs show "Connection lost" or "Reconnecting..."
Solutions:
-
Check network connectivity:
ping your-endpoint.iot.us-east-1.amazonaws.com -
Verify credentials are refreshing:
- Credentials expire after 60 minutes
- Should auto-refresh every 43 minutes
- Check logs for "Refreshing IoT credentials"
-
Check for credential expiration:
- If credentials expire before refresh, connection will drop
- Verify
MQTT_CREDENTIAL_REFRESH_INTERVALis set correctly (default: 43 minutes)
-
Review reconnection attempts:
- Max 10 attempts with exponential backoff
- After max attempts, manual intervention needed
- Restart server to reset connection attempts
Subscriptions Not Working
Symptoms:
- Location requests timeout
- No location data received
- Logs show "Subscription failed"
Solutions:
-
Check subscription limit:
- Default max: 100 concurrent subscriptions
- Increase with
MQTT_MAX_SUBSCRIPTIONSif needed
-
Verify topic format:
- Topics should be:
ZR-{studentUsername} - Username is from student's
preferred_usernamefield
- Topics should be:
-
Check IoT permissions:
- IoT credentials must allow subscribing to
ZR-*topics - Verify IAM policy attached to IoT credentials
- IoT credentials must allow subscribing to
-
Test with single subscription:
- Request location for one student
- Check if subscription succeeds
- If yes, issue may be subscription limit
Old Location Data
Symptoms:
- Location data is stale (hours old)
- Timestamp doesn't match current time
Solutions:
-
Check if retained message:
- Retained messages are last known location
- May be old if student hasn't moved recently
- Check
isRetainedflag in location data
-
Verify mobile app is publishing:
- Student's mobile app must be running
- Location tracking must be enabled
- Check mobile app logs
-
Check retained message age:
- Retained messages older than 6 hours are discarded
- If location is older, it won't be cached
-
Wait for live update:
- Retained message gives last known location
- Live update will arrive when student moves
Credential Refresh Failures
Symptoms:
- Logs show "Failed to refresh credentials"
- Connection drops after ~60 minutes
- 401/403 errors from Student API
Solutions:
-
Check JWT token validity:
# Token should not be expired # Get fresh token from browser or administrator -
Verify Student API endpoint:
curl -H "Authorization: Bearer $STUDENT_API_AUTH_TOKEN" \ $STUDENT_API_ENDPOINT/iot/credentialsShould return credentials JSON.
-
Check retry logic:
- Failed refreshes retry with delays: 2min, 5min, 10min
- Check logs for retry attempts
- If all retries fail, manual intervention needed
-
Restart server:
- Fresh start will re-fetch credentials
- Ensures clean state
High Memory Usage
Symptoms:
- Server memory usage increasing over time
- Many active subscriptions
Solutions:
-
Check subscription count:
- Use health endpoint:
curl http://localhost:5000/health - Look at
activeSubscriptionscount
- Use health endpoint:
-
Verify cleanup:
- Unused subscriptions should be removed after 30 seconds
- Check logs for "Unsubscribed from topic"
-
Reduce subscription limit:
export MQTT_MAX_SUBSCRIPTIONS=50 -
Monitor location cache:
- Cache size should match active subscriptions
- Old entries should be removed when unsubscribing
Task Location Fallback Not Working
Symptoms:
- MQTT unavailable but still seeing "location unavailable" message
- No coordinates displayed during MQTT outage
- Task location not being retrieved
Solutions:
-
Verify trip has tasks:
# Check if trip has associated tasks curl -H "Authorization: Bearer $STUDENT_API_AUTH_TOKEN" \ "$STUDENT_API_ENDPOINT/tasks?tripId=ZTR225564"Should return array of tasks with
transitionInfo. -
Check task has location data:
- Tasks must have
transitionInfo.origin.locationortransitionInfo.destination.location - Coordinates must be valid (lat: -90 to 90, lng: -180 to 180)
- At least one task should have status
IN_PROGRESSor recentupdatedAt
- Tasks must have
-
Verify cache is working:
- Check logs for "Cache hit" or "Cache miss" messages
- Cache TTL is 30 seconds
- Multiple requests within 30s should use cached data
-
Check API authentication:
- Task API uses same JWT token as Student API
- Verify token has permissions to access Task endpoints
- Check for 403 errors in logs
-
Review fallback logs:
[taskLocationResolver] Fallback triggered for trip ZTR225564 (MQTT unavailable) [taskLocationResolver] Retrieved task location: 17.418806, 78.400413 (updated 2 minutes ago) [taskLocationResolver] Cache hit for trip ZTR225564 (age: 15s)
Common Issues:
| Issue | Cause | Solution |
|---|---|---|
| No tasks found | Trip not yet started or completed | Normal - fallback to generic message |
| Invalid coordinates | Task has malformed location data | Check mobile app task creation logic |
| Cache not working | System time incorrect | Verify server time is accurate |
| API timeout | Task API slow or unavailable | Check Task API health and network |
| Missing transitionInfo | Old task format or incomplete data | Update task creation to include location |
Debugging MQTT Issues
Enable verbose logging:
The MQTT service logs to stderr. Increase verbosity:
// In src/services/mqttService.ts
console.error('[MQTT] Debug info:', { /* details */ });
Check connection status:
# HTTP mode
curl http://localhost:5000/health | jq '.mqtt'
# Expected output:
{
"connected": true,
"credentialsValidFor": 2580000,
"activeSubscriptions": 5,
"lastHeartbeat": 1699876543210
}
Test IoT credentials manually:
# Get credentials from API
curl -H "Authorization: Bearer $STUDENT_API_AUTH_TOKEN" \
$STUDENT_API_ENDPOINT/iot/credentials
# Should return:
{
"accessKeyId": "ASIA...",
"secretAccessKey": "...",
"sessionToken": "...",
"expiration": "2024-01-15T12:00:00Z"
}
Monitor MQTT traffic:
Use AWS IoT Console → Test → MQTT test client to monitor topics:
- Subscribe to
ZR-*to see all student location updates - Verify messages are being published by mobile apps
Common Error Messages:
| Error | Cause | Solution |
|---|---|---|
MQTT service not initialized | Missing IOT_ENDPOINT or IOT_REGION | Set environment variables |
Failed to fetch IoT credentials | Invalid JWT token or API error | Check token validity |
Connection timeout | Network issue or wrong endpoint | Verify endpoint and network |
Subscription limit reached | Too many concurrent subscriptions | Increase MQTT_MAX_SUBSCRIPTIONS |
Invalid location payload | Malformed message from mobile app | Check mobile app logs |
Credentials expired | Refresh failed or not scheduled | Check refresh timer and retry logic |
Development
Watch Mode
npm run watch
Run Locally
npm run dev
License
MIT
Contributing
Generated from Smithy model at /Users/zeroman/workplace/nowzone/OPlatformModels/models/student.smithy