nitrostack 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/package.json +1 -1
  3. package/templates/typescript-auth/.env.example +23 -0
  4. package/templates/typescript-auth/src/app.module.ts +103 -0
  5. package/templates/typescript-auth/src/db/database.ts +163 -0
  6. package/templates/typescript-auth/src/db/seed.ts +374 -0
  7. package/templates/typescript-auth/src/db/setup.ts +87 -0
  8. package/templates/typescript-auth/src/events/analytics.service.ts +52 -0
  9. package/templates/typescript-auth/src/events/notification.service.ts +40 -0
  10. package/templates/typescript-auth/src/filters/global-exception.filter.ts +28 -0
  11. package/templates/typescript-auth/src/guards/README.md +75 -0
  12. package/templates/typescript-auth/src/guards/jwt.guard.ts +105 -0
  13. package/templates/typescript-auth/src/health/database.health.ts +41 -0
  14. package/templates/typescript-auth/src/index.ts +26 -0
  15. package/templates/typescript-auth/src/interceptors/transform.interceptor.ts +24 -0
  16. package/templates/typescript-auth/src/middleware/logging.middleware.ts +42 -0
  17. package/templates/typescript-auth/src/modules/addresses/addresses.module.ts +16 -0
  18. package/templates/typescript-auth/src/modules/addresses/addresses.prompts.ts +114 -0
  19. package/templates/typescript-auth/src/modules/addresses/addresses.resources.ts +40 -0
  20. package/templates/typescript-auth/src/modules/addresses/addresses.tools.ts +241 -0
  21. package/templates/typescript-auth/src/modules/auth/auth.module.ts +16 -0
  22. package/templates/typescript-auth/src/modules/auth/auth.prompts.ts +147 -0
  23. package/templates/typescript-auth/src/modules/auth/auth.resources.ts +84 -0
  24. package/templates/typescript-auth/src/modules/auth/auth.tools.ts +139 -0
  25. package/templates/typescript-auth/src/modules/cart/cart.module.ts +16 -0
  26. package/templates/typescript-auth/src/modules/cart/cart.prompts.ts +95 -0
  27. package/templates/typescript-auth/src/modules/cart/cart.resources.ts +44 -0
  28. package/templates/typescript-auth/src/modules/cart/cart.tools.ts +281 -0
  29. package/templates/typescript-auth/src/modules/orders/orders.module.ts +16 -0
  30. package/templates/typescript-auth/src/modules/orders/orders.prompts.ts +88 -0
  31. package/templates/typescript-auth/src/modules/orders/orders.resources.ts +48 -0
  32. package/templates/typescript-auth/src/modules/orders/orders.tools.ts +281 -0
  33. package/templates/typescript-auth/src/modules/products/products.module.ts +16 -0
  34. package/templates/typescript-auth/src/modules/products/products.prompts.ts +146 -0
  35. package/templates/typescript-auth/src/modules/products/products.resources.ts +98 -0
  36. package/templates/typescript-auth/src/modules/products/products.tools.ts +266 -0
  37. package/templates/typescript-auth/src/pipes/validation.pipe.ts +42 -0
  38. package/templates/typescript-auth/src/services/database.service.ts +90 -0
  39. package/templates/typescript-auth/src/widgets/app/add-to-cart/page.tsx +122 -0
  40. package/templates/typescript-auth/src/widgets/app/address-added/page.tsx +116 -0
  41. package/templates/typescript-auth/src/widgets/app/address-deleted/page.tsx +105 -0
  42. package/templates/typescript-auth/src/widgets/app/address-list/page.tsx +139 -0
  43. package/templates/typescript-auth/src/widgets/app/address-updated/page.tsx +153 -0
  44. package/templates/typescript-auth/src/widgets/app/cart-cleared/page.tsx +86 -0
  45. package/templates/typescript-auth/src/widgets/app/cart-updated/page.tsx +116 -0
  46. package/templates/typescript-auth/src/widgets/app/categories/page.tsx +134 -0
  47. package/templates/typescript-auth/src/widgets/app/layout.tsx +21 -0
  48. package/templates/typescript-auth/src/widgets/app/login-result/page.tsx +129 -0
  49. package/templates/typescript-auth/src/widgets/app/order-confirmation/page.tsx +206 -0
  50. package/templates/typescript-auth/src/widgets/app/order-details/page.tsx +225 -0
  51. package/templates/typescript-auth/src/widgets/app/order-history/page.tsx +218 -0
  52. package/templates/typescript-auth/src/widgets/app/product-card/page.tsx +121 -0
  53. package/templates/typescript-auth/src/widgets/app/products-grid/page.tsx +173 -0
  54. package/templates/typescript-auth/src/widgets/app/shopping-cart/page.tsx +187 -0
  55. package/templates/typescript-auth/src/widgets/app/whoami/page.tsx +165 -0
  56. package/templates/typescript-auth/src/widgets/next.config.js +38 -0
  57. package/templates/typescript-auth/src/widgets/package.json +18 -0
  58. package/templates/typescript-auth/src/widgets/styles/ecommerce.ts +169 -0
  59. package/templates/typescript-auth/src/widgets/tsconfig.json +28 -0
  60. package/templates/typescript-auth/src/widgets/types/tool-data.ts +141 -0
  61. package/templates/typescript-auth/src/widgets/widget-manifest.json +464 -0
  62. package/templates/typescript-auth/tsconfig.json +27 -0
  63. package/templates/typescript-auth-api-key/.env +15 -0
  64. package/templates/typescript-auth-api-key/.env.example +4 -0
  65. package/templates/typescript-auth-api-key/src/app.module.ts +38 -0
  66. package/templates/typescript-auth-api-key/src/guards/apikey.guard.ts +47 -0
  67. package/templates/typescript-auth-api-key/src/guards/multi-auth.guard.ts +157 -0
  68. package/templates/typescript-auth-api-key/src/health/system.health.ts +55 -0
  69. package/templates/typescript-auth-api-key/src/index.ts +47 -0
  70. package/templates/typescript-auth-api-key/src/modules/calculator/calculator.module.ts +12 -0
  71. package/templates/typescript-auth-api-key/src/modules/calculator/calculator.prompts.ts +73 -0
  72. package/templates/typescript-auth-api-key/src/modules/calculator/calculator.resources.ts +60 -0
  73. package/templates/typescript-auth-api-key/src/modules/calculator/calculator.tools.ts +71 -0
  74. package/templates/typescript-auth-api-key/src/modules/demo/demo.module.ts +18 -0
  75. package/templates/typescript-auth-api-key/src/modules/demo/demo.tools.ts +155 -0
  76. package/templates/typescript-auth-api-key/src/modules/demo/multi-auth.tools.ts +123 -0
  77. package/templates/typescript-auth-api-key/src/widgets/app/calculator-operations/page.tsx +133 -0
  78. package/templates/typescript-auth-api-key/src/widgets/app/calculator-result/page.tsx +134 -0
  79. package/templates/typescript-auth-api-key/src/widgets/app/layout.tsx +14 -0
  80. package/templates/typescript-auth-api-key/src/widgets/next.config.js +37 -0
  81. package/templates/typescript-auth-api-key/src/widgets/package.json +24 -0
  82. package/templates/typescript-auth-api-key/src/widgets/tsconfig.json +28 -0
  83. package/templates/typescript-auth-api-key/src/widgets/widget-manifest.json +48 -0
  84. package/templates/typescript-auth-api-key/tsconfig.json +23 -0
  85. package/templates/typescript-oauth/.env.example +91 -0
  86. package/templates/typescript-oauth/src/app.module.ts +89 -0
  87. package/templates/typescript-oauth/src/guards/oauth.guard.ts +127 -0
  88. package/templates/typescript-oauth/src/index.ts +74 -0
  89. package/templates/typescript-oauth/src/modules/demo/demo.module.ts +16 -0
  90. package/templates/typescript-oauth/src/modules/demo/demo.tools.ts +190 -0
  91. package/templates/typescript-oauth/src/widgets/app/calculator-operations/page.tsx +133 -0
  92. package/templates/typescript-oauth/src/widgets/app/calculator-result/page.tsx +134 -0
  93. package/templates/typescript-oauth/src/widgets/app/layout.tsx +14 -0
  94. package/templates/typescript-oauth/src/widgets/next.config.js +37 -0
  95. package/templates/typescript-oauth/src/widgets/package.json +24 -0
  96. package/templates/typescript-oauth/src/widgets/tsconfig.json +28 -0
  97. package/templates/typescript-oauth/src/widgets/widget-manifest.json +48 -0
  98. package/templates/typescript-oauth/tsconfig.json +23 -0
  99. package/templates/typescript-starter/.env.example +4 -0
  100. package/templates/typescript-starter/src/app.module.ts +34 -0
  101. package/templates/typescript-starter/src/health/system.health.ts +55 -0
  102. package/templates/typescript-starter/src/index.ts +27 -0
  103. package/templates/typescript-starter/src/modules/calculator/calculator.module.ts +12 -0
  104. package/templates/typescript-starter/src/modules/calculator/calculator.prompts.ts +73 -0
  105. package/templates/typescript-starter/src/modules/calculator/calculator.resources.ts +60 -0
  106. package/templates/typescript-starter/src/modules/calculator/calculator.tools.ts +71 -0
  107. package/templates/typescript-starter/src/widgets/app/calculator-operations/page.tsx +133 -0
  108. package/templates/typescript-starter/src/widgets/app/calculator-result/page.tsx +134 -0
  109. package/templates/typescript-starter/src/widgets/app/layout.tsx +14 -0
  110. package/templates/typescript-starter/src/widgets/next.config.js +37 -0
  111. package/templates/typescript-starter/src/widgets/package.json +24 -0
  112. package/templates/typescript-starter/src/widgets/tsconfig.json +28 -0
  113. package/templates/typescript-starter/src/widgets/widget-manifest.json +48 -0
  114. package/templates/typescript-starter/tsconfig.json +23 -0
  115. package/LICENSE_URLS_UPDATE_COMPLETE.md +0 -388
@@ -0,0 +1,87 @@
1
+ import * as dotenv from 'dotenv';
2
+ import { initializeSchema, clearAllData } from './database.js';
3
+ import { seedAll } from './seed.js';
4
+ import crypto from 'crypto';
5
+ import fs from 'fs';
6
+ import path from 'path';
7
+
8
+ /**
9
+ * Database setup script
10
+ * Run with: npm run setup-db
11
+ */
12
+
13
+ // Load environment variables
14
+ dotenv.config();
15
+
16
+ console.log('╔══════════════════════════════════════════════════════════════╗');
17
+ console.log('║ ║');
18
+ console.log('║ E-COMMERCE MCP SERVER - DATABASE SETUP ║');
19
+ console.log('║ ║');
20
+ console.log('╚══════════════════════════════════════════════════════════════╝\n');
21
+
22
+ try {
23
+ // 1. Initialize schema
24
+ console.log('📦 Initializing database schema...');
25
+ initializeSchema();
26
+ console.log('✅ Schema initialized\n');
27
+
28
+ // 2. Clear existing data (optional)
29
+ console.log('🗑️ Clearing existing data...');
30
+ clearAllData();
31
+ console.log('✅ Data cleared\n');
32
+
33
+ // 3. Seed data
34
+ seedAll();
35
+ console.log('');
36
+
37
+ // 4. Generate JWT secret if not exists
38
+ const envPath = path.join(process.cwd(), '.env');
39
+ const envExamplePath = path.join(process.cwd(), '.env.example');
40
+
41
+ if (!fs.existsSync(envPath) && fs.existsSync(envExamplePath)) {
42
+ console.log('📝 Creating .env file...');
43
+ let envContent = fs.readFileSync(envExamplePath, 'utf-8');
44
+
45
+ // Generate JWT secret (64 random bytes encoded as base64url)
46
+ const jwtSecret = 'jwt_secret_' + crypto.randomBytes(32).toString('base64url');
47
+ envContent = envContent.replace('your-jwt-secret-here-change-this', jwtSecret);
48
+
49
+ fs.writeFileSync(envPath, envContent);
50
+ console.log('✅ .env file created with JWT secret\n');
51
+ }
52
+
53
+ // 5. Print test credentials
54
+ console.log('═══════════════════════════════════════════════════════════════');
55
+ console.log(' TEST CREDENTIALS ');
56
+ console.log('═══════════════════════════════════════════════════════════════\n');
57
+
58
+ console.log('🧪 Test Users (use these in the inspector):');
59
+ console.log('');
60
+ console.log(' 👤 Alice Johnson');
61
+ console.log(' Email: alice@example.com');
62
+ console.log(' Password: password123');
63
+ console.log('');
64
+ console.log(' 👤 Bob Smith');
65
+ console.log(' Email: bob@example.com');
66
+ console.log(' Password: password123');
67
+ console.log('');
68
+ console.log(' 👤 Charlie Brown');
69
+ console.log(' Email: charlie@example.com');
70
+ console.log(' Password: password123');
71
+ console.log('');
72
+
73
+ console.log('═══════════════════════════════════════════════════════════════\n');
74
+
75
+ console.log('🎉 Database setup complete!\n');
76
+ console.log('Next steps:');
77
+ console.log(' 1. npm install');
78
+ console.log(' 2. npm run build');
79
+ console.log(' 3. npm run dev');
80
+ console.log(' 4. Test in inspector with the credentials above\n');
81
+
82
+ process.exit(0);
83
+ } catch (error) {
84
+ console.error('❌ Setup failed:', error);
85
+ process.exit(1);
86
+ }
87
+
@@ -0,0 +1,52 @@
1
+ import { Injectable, OnEvent } from 'nitrostack';
2
+
3
+ /**
4
+ * Analytics Service
5
+ *
6
+ * Tracks events for analytics
7
+ */
8
+ @Injectable()
9
+ export class AnalyticsService {
10
+ private events: any[] = [];
11
+
12
+ /**
13
+ * Track order creation
14
+ */
15
+ @OnEvent('order.created')
16
+ async trackOrderCreated(order: any): Promise<void> {
17
+ this.events.push({
18
+ type: 'order_created',
19
+ timestamp: new Date().toISOString(),
20
+ data: {
21
+ order_id: order.id,
22
+ total: order.total,
23
+ item_count: order.items?.length || 0,
24
+ },
25
+ });
26
+ console.log(`📊 Tracked: Order Created #${order.id}`);
27
+ }
28
+
29
+ /**
30
+ * Track product viewed
31
+ */
32
+ @OnEvent('product.viewed')
33
+ async trackProductViewed(product: any): Promise<void> {
34
+ this.events.push({
35
+ type: 'product_viewed',
36
+ timestamp: new Date().toISOString(),
37
+ data: {
38
+ product_id: product.id,
39
+ product_name: product.name,
40
+ },
41
+ });
42
+ console.log(`📊 Tracked: Product Viewed - ${product.name}`);
43
+ }
44
+
45
+ /**
46
+ * Get analytics data
47
+ */
48
+ getAnalytics(): any[] {
49
+ return this.events;
50
+ }
51
+ }
52
+
@@ -0,0 +1,40 @@
1
+ import { Injectable, OnEvent } from 'nitrostack';
2
+
3
+ /**
4
+ * Notification Service
5
+ *
6
+ * Listens to events and sends notifications
7
+ */
8
+ @Injectable()
9
+ export class NotificationService {
10
+ /**
11
+ * Handle order created event
12
+ */
13
+ @OnEvent('order.created')
14
+ async handleOrderCreated(order: any): Promise<void> {
15
+ console.log(`📧 Sending order confirmation email for order #${order.id}`);
16
+ // TODO: Implement actual email sending
17
+ console.log(` To: ${order.user_email}`);
18
+ console.log(` Subject: Order Confirmation #${order.id}`);
19
+ console.log(` Total: $${order.total}`);
20
+ }
21
+
22
+ /**
23
+ * Handle order shipped event
24
+ */
25
+ @OnEvent('order.shipped')
26
+ async handleOrderShipped(order: any): Promise<void> {
27
+ console.log(`📦 Sending shipping notification for order #${order.id}`);
28
+ // TODO: Implement actual notification
29
+ }
30
+
31
+ /**
32
+ * Handle user registered event
33
+ */
34
+ @OnEvent('user.registered')
35
+ async handleUserRegistered(user: any): Promise<void> {
36
+ console.log(`👋 Sending welcome email to ${user.email}`);
37
+ // TODO: Implement actual welcome email
38
+ }
39
+ }
40
+
@@ -0,0 +1,28 @@
1
+ import { ExceptionFilter, ExceptionFilterInterface, ExecutionContext } from 'nitrostack';
2
+
3
+ /**
4
+ * Global Exception Filter
5
+ *
6
+ * Handles all unhandled exceptions and formats error responses
7
+ */
8
+ @ExceptionFilter()
9
+ export class GlobalExceptionFilter implements ExceptionFilterInterface {
10
+ catch(exception: any, context: ExecutionContext) {
11
+ context.logger.error('Unhandled exception', {
12
+ tool: context.toolName || 'unknown',
13
+ error: exception.message,
14
+ stack: exception.stack,
15
+ });
16
+
17
+ // Format error response
18
+ return {
19
+ error: true,
20
+ message: exception.message || 'Internal server error',
21
+ code: exception.code || 'INTERNAL_ERROR',
22
+ timestamp: new Date().toISOString(),
23
+ requestId: context.requestId,
24
+ tool: context.toolName || 'unknown',
25
+ };
26
+ }
27
+ }
28
+
@@ -0,0 +1,75 @@
1
+ # Guards
2
+
3
+ Guards are classes that implement the `Guard` interface and determine whether a tool can be executed.
4
+
5
+ ## What are Guards?
6
+
7
+ Guards in NitroStack are similar to NestJS guards - they handle authorization logic before tool execution. Use the `@UseGuards()` decorator to apply guards to your tools.
8
+
9
+ ## Available Guards
10
+
11
+ ### JWTGuard
12
+
13
+ Validates JWT tokens and populates `context.auth` with user information.
14
+
15
+ **Usage:**
16
+ ```typescript
17
+ import { JWTGuard } from '../guards/jwt.guard.js';
18
+
19
+ @Tool({ name: 'get_profile', ... })
20
+ @UseGuards(JWTGuard)
21
+ async getProfile(input: any, context: ExecutionContext) {
22
+ const userId = context.auth?.subject;
23
+ // User is already authenticated!
24
+ }
25
+ ```
26
+
27
+ ## Creating Custom Guards
28
+
29
+ Create a class that implements the `Guard` interface:
30
+
31
+ ```typescript
32
+ import { Guard, ExecutionContext } from 'nitrostack';
33
+
34
+ export class RoleGuard implements Guard {
35
+ constructor(private requiredRole: string) {}
36
+
37
+ async canActivate(context: ExecutionContext): Promise<boolean> {
38
+ const userRole = context.auth?.role;
39
+
40
+ if (userRole !== this.requiredRole) {
41
+ throw new Error(`Required role: ${this.requiredRole}`);
42
+ }
43
+
44
+ return true;
45
+ }
46
+ }
47
+ ```
48
+
49
+ **Usage:**
50
+ ```typescript
51
+ @UseGuards(JWTGuard, new RoleGuard('admin'))
52
+ async deleteUser(input: any, context: ExecutionContext) {
53
+ // Only admins can execute this
54
+ }
55
+ ```
56
+
57
+ ## Guard Execution Order
58
+
59
+ Guards are executed in the order they are specified:
60
+ ```typescript
61
+ @UseGuards(JWTGuard, RoleGuard, PermissionGuard)
62
+ ```
63
+ 1. JWTGuard validates token
64
+ 2. RoleGuard checks user role
65
+ 3. PermissionGuard checks specific permissions
66
+
67
+ If any guard returns `false` or throws an error, execution stops.
68
+
69
+ ## Best Practices
70
+
71
+ 1. **Keep guards focused** - Each guard should have one responsibility
72
+ 2. **Reuse guards** - Create guards that can be used across multiple tools
73
+ 3. **Clear error messages** - Help users understand why access was denied
74
+ 4. **Log important events** - Use `context.logger` for debugging
75
+
@@ -0,0 +1,105 @@
1
+ import jwt from 'jsonwebtoken';
2
+ import { Guard, ExecutionContext, JWTPayload, JWTModule } from 'nitrostack';
3
+
4
+ /**
5
+ * JWT Guard - Validates JWT tokens and populates context.auth
6
+ *
7
+ * This is an example implementation. You can customize it for your needs.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * @Tool({ name: 'whoami', ... })
12
+ * @UseGuards(JWTGuard)
13
+ * async whoami(input: any, context: ExecutionContext) {
14
+ * // context.auth is populated with JWT payload
15
+ * return { user: context.auth };
16
+ * }
17
+ * ```
18
+ */
19
+ export class JWTGuard implements Guard {
20
+ async canActivate(context: ExecutionContext): Promise<boolean> {
21
+ try {
22
+ // Get JWT secret from JWTModule configuration
23
+ const secret = JWTModule.getSecret();
24
+ if (!secret) {
25
+ context.logger.warn('[JWTGuard] JWT secret not configured');
26
+ throw new Error('JWT authentication not configured. Set JWT_SECRET environment variable.');
27
+ }
28
+
29
+ // Extract token from context
30
+ const token = this.extractToken(context);
31
+ if (!token) {
32
+ context.logger.info('[JWTGuard] No token found in request');
33
+ throw new Error('Authentication required. Please login first and include your JWT token.');
34
+ }
35
+
36
+ // Verify token
37
+ const payload = await this.verifyToken(token, secret);
38
+ if (!payload) {
39
+ context.logger.warn('[JWTGuard] Token verification failed');
40
+ throw new Error('Invalid or expired token. Please login again.');
41
+ }
42
+
43
+ // Populate context.auth
44
+ context.auth = {
45
+ subject: payload.sub,
46
+ scopes: [],
47
+ email: payload.email,
48
+ name: payload.name,
49
+ ...payload,
50
+ };
51
+
52
+ context.logger.info(`[JWTGuard] Authentication successful for user: ${payload.sub}`);
53
+ return true;
54
+ } catch (error) {
55
+ context.logger.error('[JWTGuard] Authentication failed', error);
56
+ throw error;
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Extract JWT token from execution context
62
+ * Supports multiple token locations for maximum compatibility
63
+ */
64
+ private extractToken(context: ExecutionContext): string | null {
65
+ // Priority 1: Check metadata for _jwt field (MCP protocol)
66
+ if (context.metadata?._jwt) {
67
+ return context.metadata._jwt as string;
68
+ }
69
+
70
+ // Priority 2: Check Authorization header format in metadata
71
+ if (context.metadata?.authorization) {
72
+ const auth = context.metadata.authorization as string;
73
+ if (auth.startsWith('Bearer ')) {
74
+ return auth.substring(7);
75
+ }
76
+ return auth;
77
+ }
78
+
79
+ // Priority 3: Check metadata.headers (if present)
80
+ const headers = context.metadata?.headers as any;
81
+ if (headers?.authorization) {
82
+ const auth = headers.authorization as string;
83
+ if (auth.startsWith('Bearer ')) {
84
+ return auth.substring(7);
85
+ }
86
+ return auth;
87
+ }
88
+
89
+ return null;
90
+ }
91
+
92
+ /**
93
+ * Verify JWT token
94
+ */
95
+ private async verifyToken(token: string, secret: string): Promise<JWTPayload | null> {
96
+ try {
97
+ const cleanSecret = secret.trim();
98
+ const decoded = jwt.verify(token, cleanSecret) as JWTPayload;
99
+ return decoded;
100
+ } catch (error) {
101
+ return null;
102
+ }
103
+ }
104
+ }
105
+
@@ -0,0 +1,41 @@
1
+ import { HealthCheck, HealthCheckInterface, HealthCheckResult } from 'nitrostack';
2
+ import { DatabaseService } from '../services/database.service.js';
3
+
4
+ /**
5
+ * Database Health Check
6
+ *
7
+ * Monitors database connectivity
8
+ */
9
+ @HealthCheck({
10
+ name: 'database',
11
+ description: 'Database connectivity check',
12
+ interval: 30 // Check every 30 seconds
13
+ })
14
+ export class DatabaseHealthCheck implements HealthCheckInterface {
15
+ constructor(private database: DatabaseService) {}
16
+
17
+ async check(): Promise<HealthCheckResult> {
18
+ try {
19
+ const isConnected = await this.database.ping();
20
+
21
+ if (isConnected) {
22
+ return {
23
+ status: 'up',
24
+ message: 'Database is connected and responsive',
25
+ };
26
+ } else {
27
+ return {
28
+ status: 'down',
29
+ message: 'Database connection failed',
30
+ };
31
+ }
32
+ } catch (error: any) {
33
+ return {
34
+ status: 'down',
35
+ message: 'Database health check failed',
36
+ details: error.message,
37
+ };
38
+ }
39
+ }
40
+ }
41
+
@@ -0,0 +1,26 @@
1
+ /**
2
+ * E-commerce MCP Server
3
+ *
4
+ * Main entry point for the MCP server.
5
+ * Uses the new @McpApp decorator pattern for clean, NestJS-style architecture.
6
+ */
7
+
8
+ import { McpApplicationFactory } from 'nitrostack';
9
+ import { AppModule } from './app.module.js';
10
+
11
+ /**
12
+ * Bootstrap the application
13
+ */
14
+ async function bootstrap() {
15
+ // Create and start the MCP server from AppModule
16
+ const server = await McpApplicationFactory.create(AppModule);
17
+
18
+ // Start the server
19
+ await server.start();
20
+ }
21
+
22
+ // Start the application
23
+ bootstrap().catch((error) => {
24
+ console.error('❌ Failed to start server:', error);
25
+ process.exit(1);
26
+ });
@@ -0,0 +1,24 @@
1
+ import { Interceptor, InterceptorInterface, ExecutionContext } from 'nitrostack';
2
+
3
+ /**
4
+ * Transform Interceptor
5
+ *
6
+ * Wraps all responses in a standard format with metadata
7
+ */
8
+ @Interceptor()
9
+ export class TransformInterceptor implements InterceptorInterface {
10
+ async intercept(context: ExecutionContext, next: () => Promise<any>) {
11
+ const result = await next();
12
+
13
+ return {
14
+ success: true,
15
+ data: result,
16
+ metadata: {
17
+ timestamp: new Date().toISOString(),
18
+ requestId: context.requestId,
19
+ tool: context.toolName || 'unknown',
20
+ },
21
+ };
22
+ }
23
+ }
24
+
@@ -0,0 +1,42 @@
1
+ import { Middleware, MiddlewareInterface, ExecutionContext } from 'nitrostack';
2
+
3
+ /**
4
+ * Logging Middleware
5
+ *
6
+ * Logs all tool executions with timing information
7
+ */
8
+ @Middleware()
9
+ export class LoggingMiddleware implements MiddlewareInterface {
10
+ async use(context: ExecutionContext, next: () => Promise<any>) {
11
+ const start = performance.now();
12
+ const toolName = context.toolName || 'unknown';
13
+
14
+ context.logger.info(`[${toolName}] Started`, {
15
+ requestId: context.requestId,
16
+ user: context.auth?.subject || 'anonymous',
17
+ });
18
+
19
+ try {
20
+ const result = await next();
21
+ const duration = performance.now() - start;
22
+
23
+ context.logger.info(`[${toolName}] Completed in ${duration.toFixed(2)}ms`, {
24
+ requestId: context.requestId,
25
+ duration,
26
+ });
27
+
28
+ return result;
29
+ } catch (error: any) {
30
+ const duration = performance.now() - start;
31
+
32
+ context.logger.error(`[${toolName}] Failed after ${duration.toFixed(2)}ms`, {
33
+ requestId: context.requestId,
34
+ duration,
35
+ error: error.message,
36
+ });
37
+
38
+ throw error;
39
+ }
40
+ }
41
+ }
42
+
@@ -0,0 +1,16 @@
1
+ import { Module } from 'nitrostack';
2
+ import { AddressesTools } from './addresses.tools.js';
3
+ import { AddressesResources } from './addresses.resources.js';
4
+ import { AddressesPrompts } from './addresses.prompts.js';
5
+
6
+ /**
7
+ * Addresses Module
8
+ * Provides shipping address management, resources, and prompts
9
+ */
10
+ @Module({
11
+ name: 'addresses',
12
+ description: 'Shipping address management',
13
+ controllers: [AddressesTools, AddressesResources, AddressesPrompts],
14
+ })
15
+ export class AddressesModule {}
16
+
@@ -0,0 +1,114 @@
1
+ import { PromptDecorator as Prompt, ExecutionContext } from 'nitrostack';
2
+
3
+ /**
4
+ * Addresses Prompts
5
+ * Provides helpful prompts for address management
6
+ */
7
+ export class AddressesPrompts {
8
+ /**
9
+ * Address management help prompt
10
+ */
11
+ @Prompt({
12
+ name: 'address-help',
13
+ description: 'Get help managing shipping addresses',
14
+ })
15
+ async addressHelp(args: Record<string, any>, context: ExecutionContext) {
16
+ return [
17
+ {
18
+ role: 'user' as const,
19
+ content: 'I need help managing shipping addresses',
20
+ },
21
+ {
22
+ role: 'assistant' as const,
23
+ content: `**Shipping Address Management Guide**
24
+
25
+ **Available Tools (Requires Authentication):**
26
+ 1. \`add_address\` - Add new shipping address
27
+ 2. \`get_addresses\` - View all your addresses
28
+ 3. \`set_default_address\` - Set default for orders
29
+ 4. \`delete_address\` - Remove an address
30
+
31
+ **Adding an Address:**
32
+ \`\`\`
33
+ add_address({
34
+ full_name: "John Doe",
35
+ street: "123 Main St",
36
+ city: "New York",
37
+ state: "NY",
38
+ zip_code: "10001",
39
+ country: "USA",
40
+ phone: "+1234567890",
41
+ is_default: true
42
+ })
43
+ \`\`\`
44
+
45
+ **Required Fields:**
46
+ - ✓ full_name
47
+ - ✓ street
48
+ - ✓ city
49
+ - ✓ state
50
+ - ✓ zip_code
51
+ - ✓ phone
52
+
53
+ **Optional Fields:**
54
+ - country (defaults to "USA")
55
+ - is_default (defaults to false)
56
+
57
+ **Default Address:**
58
+ - Used automatically for orders
59
+ - Only one default address per user
60
+ - Setting new default unsets old one
61
+
62
+ **Viewing Addresses:**
63
+ \`\`\`
64
+ get_addresses({})
65
+ \`\`\`
66
+ Returns all addresses, sorted by:
67
+ 1. Default address first
68
+ 2. Then by creation date
69
+
70
+ **Setting Default:**
71
+ \`\`\`
72
+ set_default_address({
73
+ address_id: "address-uuid"
74
+ })
75
+ \`\`\`
76
+
77
+ **Deleting Address:**
78
+ \`\`\`
79
+ delete_address({
80
+ address_id: "address-uuid"
81
+ })
82
+ \`\`\`
83
+ ⚠️ Cannot be undone!
84
+
85
+ **Address Format Tips:**
86
+ 📍 **Street:** Include apartment/unit if applicable
87
+ 📍 **State:** Use 2-letter code (NY, CA, TX)
88
+ 📍 **ZIP:** 5-digit or 9-digit format
89
+ 📍 **Phone:** Include country code for international
90
+
91
+ **Common Operations:**
92
+ 1. **First Time Setup:**
93
+ - Add address with is_default: true
94
+ - Will be used for all orders
95
+
96
+ 2. **Multiple Addresses:**
97
+ - Add each address separately
98
+ - Set one as default
99
+ - Choose specific address when ordering
100
+
101
+ 3. **Update Address:**
102
+ - Delete old address
103
+ - Add new address with updated info
104
+
105
+ **Tips:**
106
+ ✓ Add address before first order
107
+ ✓ Keep at least one address on file
108
+ ✓ Verify address details before saving
109
+ ✓ Use default for frequent shipping location`,
110
+ },
111
+ ];
112
+ }
113
+ }
114
+