This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
# Build TypeScript
npm run build
# Start server (requires build first)
npm run start
# Build and start in one command
npm run build && npm run start
# Docker build and run
docker compose build && docker compose up -d
# Pull from registry and run
docker compose pull && docker compose up -d- Uses Prettier with: no semicolons, single quotes, 2-space tabs, 128 char line width
- ES modules (
"type": "module"in package.json) - use.jsextensions in imports even for TypeScript files - TypeScript strict mode enabled, targeting ES2022
The server (src/server.ts) runs both:
- Express REST API - Traditional HTTP endpoints
- Stateless MCP Server - Model Context Protocol server using
@modelcontextprotocol/sdkwith StreamableHTTPServerTransport
src/v1/- Versioned API (routers, controllers, MCP tool implementations)src/auth/- OAuth/authentication (oauth.ts for MCP bearer auth, trmnlAuth.ts for TRMNL plugin auth)src/integrations/- External API clients (WMATA metro)src/types/- TypeScript type definitionssrc/utils/- Shared utilities (logger, database, rate limiter)
- MCP endpoint (
/mcp) uses OAuth 2.0 token introspection with a Keycloak-based auth server - The auth middleware (
src/auth/oauth.ts) validates bearer tokens by calling the introspection endpoint - TRMNL plugin uses hash-based token validation stored in SQLite
Tools are registered in src/v1/mcp/registerTools.ts:
get-alerts- NWS weather alerts by stateget-forecast- Weather forecast by coordinatesget-stock- Stock quotes via yahoo-finance2get-wmata-incidents- DC Metro rail incidentsget-wmata-station-info- Metro station arrival predictions
Uses better-sqlite3 for local persistence (SQLite). Database initialization and queries are in src/utils/dbConnector.ts. The DB path defaults to ./trmnl.sqlite or can be set via TRMNL_DB_PATH env var.
/mcp- MCP server endpoint (requires OAuth)/mcp/health- MCP health check/health- API health check/v1/trmnl/*- TRMNL plugin endpoints for DC Metro widget/discord/token- Discord OAuth token exchange
Required for core functionality:
API_CLIENT_ID,API_CLIENT_SECRET- OAuth client credentials for token introspectionAUTH_SERVER_URL,AUTH_REALM- Keycloak authentication serverMCP_SERVER_URL- Resource server URL for audience validationWMATA_PRIMARY_KEY- WMATA API key for metro data
Optional:
PORT- Server port (default: 9595)LOG_LEVEL- Logging level (default: info)TRMNL_DB_PATH- SQLite database path
If on the dev branch, do not create tags or push tags to this branch. Tags should ideally only be created on the v1 branch.
CI/CD automatically cuts a GitHub release when a tag is pushed to the v1 branch — do not manually create releases via gh release create. To trigger a release, push a tag to v1 and CI/CD will handle the rest.
If creating a new release, be sure to ask the user if they wish to create one. This should happen after a merge request is done in GitHub. If creating a new release, grab the latest tag and incriment it (e.g. 1.5.5 -> 1.5.6), unless user specifies otherwise.
Major version bump example: 1.5.5 -> 2.0.0 | 2.5.3 -> 3.0.0 Minor version bump example: 1.5.5 -> 1.6.0 | 2.9.3 -> 2.10.0 Patch version bump example: 1.5.5 -> 1.5.6 | 1.9.9 -> 1.9.10