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.
- package/CHANGELOG.md +15 -0
- package/package.json +1 -1
- package/templates/typescript-auth/.env.example +23 -0
- package/templates/typescript-auth/src/app.module.ts +103 -0
- package/templates/typescript-auth/src/db/database.ts +163 -0
- package/templates/typescript-auth/src/db/seed.ts +374 -0
- package/templates/typescript-auth/src/db/setup.ts +87 -0
- package/templates/typescript-auth/src/events/analytics.service.ts +52 -0
- package/templates/typescript-auth/src/events/notification.service.ts +40 -0
- package/templates/typescript-auth/src/filters/global-exception.filter.ts +28 -0
- package/templates/typescript-auth/src/guards/README.md +75 -0
- package/templates/typescript-auth/src/guards/jwt.guard.ts +105 -0
- package/templates/typescript-auth/src/health/database.health.ts +41 -0
- package/templates/typescript-auth/src/index.ts +26 -0
- package/templates/typescript-auth/src/interceptors/transform.interceptor.ts +24 -0
- package/templates/typescript-auth/src/middleware/logging.middleware.ts +42 -0
- package/templates/typescript-auth/src/modules/addresses/addresses.module.ts +16 -0
- package/templates/typescript-auth/src/modules/addresses/addresses.prompts.ts +114 -0
- package/templates/typescript-auth/src/modules/addresses/addresses.resources.ts +40 -0
- package/templates/typescript-auth/src/modules/addresses/addresses.tools.ts +241 -0
- package/templates/typescript-auth/src/modules/auth/auth.module.ts +16 -0
- package/templates/typescript-auth/src/modules/auth/auth.prompts.ts +147 -0
- package/templates/typescript-auth/src/modules/auth/auth.resources.ts +84 -0
- package/templates/typescript-auth/src/modules/auth/auth.tools.ts +139 -0
- package/templates/typescript-auth/src/modules/cart/cart.module.ts +16 -0
- package/templates/typescript-auth/src/modules/cart/cart.prompts.ts +95 -0
- package/templates/typescript-auth/src/modules/cart/cart.resources.ts +44 -0
- package/templates/typescript-auth/src/modules/cart/cart.tools.ts +281 -0
- package/templates/typescript-auth/src/modules/orders/orders.module.ts +16 -0
- package/templates/typescript-auth/src/modules/orders/orders.prompts.ts +88 -0
- package/templates/typescript-auth/src/modules/orders/orders.resources.ts +48 -0
- package/templates/typescript-auth/src/modules/orders/orders.tools.ts +281 -0
- package/templates/typescript-auth/src/modules/products/products.module.ts +16 -0
- package/templates/typescript-auth/src/modules/products/products.prompts.ts +146 -0
- package/templates/typescript-auth/src/modules/products/products.resources.ts +98 -0
- package/templates/typescript-auth/src/modules/products/products.tools.ts +266 -0
- package/templates/typescript-auth/src/pipes/validation.pipe.ts +42 -0
- package/templates/typescript-auth/src/services/database.service.ts +90 -0
- package/templates/typescript-auth/src/widgets/app/add-to-cart/page.tsx +122 -0
- package/templates/typescript-auth/src/widgets/app/address-added/page.tsx +116 -0
- package/templates/typescript-auth/src/widgets/app/address-deleted/page.tsx +105 -0
- package/templates/typescript-auth/src/widgets/app/address-list/page.tsx +139 -0
- package/templates/typescript-auth/src/widgets/app/address-updated/page.tsx +153 -0
- package/templates/typescript-auth/src/widgets/app/cart-cleared/page.tsx +86 -0
- package/templates/typescript-auth/src/widgets/app/cart-updated/page.tsx +116 -0
- package/templates/typescript-auth/src/widgets/app/categories/page.tsx +134 -0
- package/templates/typescript-auth/src/widgets/app/layout.tsx +21 -0
- package/templates/typescript-auth/src/widgets/app/login-result/page.tsx +129 -0
- package/templates/typescript-auth/src/widgets/app/order-confirmation/page.tsx +206 -0
- package/templates/typescript-auth/src/widgets/app/order-details/page.tsx +225 -0
- package/templates/typescript-auth/src/widgets/app/order-history/page.tsx +218 -0
- package/templates/typescript-auth/src/widgets/app/product-card/page.tsx +121 -0
- package/templates/typescript-auth/src/widgets/app/products-grid/page.tsx +173 -0
- package/templates/typescript-auth/src/widgets/app/shopping-cart/page.tsx +187 -0
- package/templates/typescript-auth/src/widgets/app/whoami/page.tsx +165 -0
- package/templates/typescript-auth/src/widgets/next.config.js +38 -0
- package/templates/typescript-auth/src/widgets/package.json +18 -0
- package/templates/typescript-auth/src/widgets/styles/ecommerce.ts +169 -0
- package/templates/typescript-auth/src/widgets/tsconfig.json +28 -0
- package/templates/typescript-auth/src/widgets/types/tool-data.ts +141 -0
- package/templates/typescript-auth/src/widgets/widget-manifest.json +464 -0
- package/templates/typescript-auth/tsconfig.json +27 -0
- package/templates/typescript-auth-api-key/.env +15 -0
- package/templates/typescript-auth-api-key/.env.example +4 -0
- package/templates/typescript-auth-api-key/src/app.module.ts +38 -0
- package/templates/typescript-auth-api-key/src/guards/apikey.guard.ts +47 -0
- package/templates/typescript-auth-api-key/src/guards/multi-auth.guard.ts +157 -0
- package/templates/typescript-auth-api-key/src/health/system.health.ts +55 -0
- package/templates/typescript-auth-api-key/src/index.ts +47 -0
- package/templates/typescript-auth-api-key/src/modules/calculator/calculator.module.ts +12 -0
- package/templates/typescript-auth-api-key/src/modules/calculator/calculator.prompts.ts +73 -0
- package/templates/typescript-auth-api-key/src/modules/calculator/calculator.resources.ts +60 -0
- package/templates/typescript-auth-api-key/src/modules/calculator/calculator.tools.ts +71 -0
- package/templates/typescript-auth-api-key/src/modules/demo/demo.module.ts +18 -0
- package/templates/typescript-auth-api-key/src/modules/demo/demo.tools.ts +155 -0
- package/templates/typescript-auth-api-key/src/modules/demo/multi-auth.tools.ts +123 -0
- package/templates/typescript-auth-api-key/src/widgets/app/calculator-operations/page.tsx +133 -0
- package/templates/typescript-auth-api-key/src/widgets/app/calculator-result/page.tsx +134 -0
- package/templates/typescript-auth-api-key/src/widgets/app/layout.tsx +14 -0
- package/templates/typescript-auth-api-key/src/widgets/next.config.js +37 -0
- package/templates/typescript-auth-api-key/src/widgets/package.json +24 -0
- package/templates/typescript-auth-api-key/src/widgets/tsconfig.json +28 -0
- package/templates/typescript-auth-api-key/src/widgets/widget-manifest.json +48 -0
- package/templates/typescript-auth-api-key/tsconfig.json +23 -0
- package/templates/typescript-oauth/.env.example +91 -0
- package/templates/typescript-oauth/src/app.module.ts +89 -0
- package/templates/typescript-oauth/src/guards/oauth.guard.ts +127 -0
- package/templates/typescript-oauth/src/index.ts +74 -0
- package/templates/typescript-oauth/src/modules/demo/demo.module.ts +16 -0
- package/templates/typescript-oauth/src/modules/demo/demo.tools.ts +190 -0
- package/templates/typescript-oauth/src/widgets/app/calculator-operations/page.tsx +133 -0
- package/templates/typescript-oauth/src/widgets/app/calculator-result/page.tsx +134 -0
- package/templates/typescript-oauth/src/widgets/app/layout.tsx +14 -0
- package/templates/typescript-oauth/src/widgets/next.config.js +37 -0
- package/templates/typescript-oauth/src/widgets/package.json +24 -0
- package/templates/typescript-oauth/src/widgets/tsconfig.json +28 -0
- package/templates/typescript-oauth/src/widgets/widget-manifest.json +48 -0
- package/templates/typescript-oauth/tsconfig.json +23 -0
- package/templates/typescript-starter/.env.example +4 -0
- package/templates/typescript-starter/src/app.module.ts +34 -0
- package/templates/typescript-starter/src/health/system.health.ts +55 -0
- package/templates/typescript-starter/src/index.ts +27 -0
- package/templates/typescript-starter/src/modules/calculator/calculator.module.ts +12 -0
- package/templates/typescript-starter/src/modules/calculator/calculator.prompts.ts +73 -0
- package/templates/typescript-starter/src/modules/calculator/calculator.resources.ts +60 -0
- package/templates/typescript-starter/src/modules/calculator/calculator.tools.ts +71 -0
- package/templates/typescript-starter/src/widgets/app/calculator-operations/page.tsx +133 -0
- package/templates/typescript-starter/src/widgets/app/calculator-result/page.tsx +134 -0
- package/templates/typescript-starter/src/widgets/app/layout.tsx +14 -0
- package/templates/typescript-starter/src/widgets/next.config.js +37 -0
- package/templates/typescript-starter/src/widgets/package.json +24 -0
- package/templates/typescript-starter/src/widgets/tsconfig.json +28 -0
- package/templates/typescript-starter/src/widgets/widget-manifest.json +48 -0
- package/templates/typescript-starter/tsconfig.json +23 -0
- package/LICENSE_URLS_UPDATE_COMPLETE.md +0 -388
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { withToolData } from 'nitrostack/widgets';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Widget Metadata (stored in widget-manifest.json)
|
|
7
|
+
*
|
|
8
|
+
* This widget displays calculation results with operation details.
|
|
9
|
+
*
|
|
10
|
+
* Examples defined in manifest:
|
|
11
|
+
* - Addition: 5 + 3 = 8
|
|
12
|
+
* - Multiplication: 6 × 7 = 42
|
|
13
|
+
* - Division: 20 ÷ 4 = 5
|
|
14
|
+
*
|
|
15
|
+
* Frontend developers: Edit widget-manifest.json to update examples
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
interface CalculatorData {
|
|
19
|
+
operation: string;
|
|
20
|
+
a: number;
|
|
21
|
+
b: number;
|
|
22
|
+
result: number;
|
|
23
|
+
expression: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function CalculatorResult({ data }: { data: CalculatorData }) {
|
|
27
|
+
const getOperationColor = (op: string) => {
|
|
28
|
+
const colors: Record<string, string> = {
|
|
29
|
+
add: '#10b981',
|
|
30
|
+
subtract: '#f59e0b',
|
|
31
|
+
multiply: '#3b82f6',
|
|
32
|
+
divide: '#8b5cf6'
|
|
33
|
+
};
|
|
34
|
+
return colors[op] || '#6b7280';
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const getOperationIcon = (op: string) => {
|
|
38
|
+
const icons: Record<string, string> = {
|
|
39
|
+
add: '➕',
|
|
40
|
+
subtract: '➖',
|
|
41
|
+
multiply: '✖️',
|
|
42
|
+
divide: '➗'
|
|
43
|
+
};
|
|
44
|
+
return icons[op] || '🔢';
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const color = getOperationColor(data.operation);
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<div style={{
|
|
51
|
+
padding: '24px',
|
|
52
|
+
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
53
|
+
borderRadius: '16px',
|
|
54
|
+
color: 'white',
|
|
55
|
+
maxWidth: '400px',
|
|
56
|
+
boxShadow: '0 10px 30px rgba(0,0,0,0.2)'
|
|
57
|
+
}}>
|
|
58
|
+
<div style={{
|
|
59
|
+
display: 'flex',
|
|
60
|
+
alignItems: 'center',
|
|
61
|
+
gap: '12px',
|
|
62
|
+
marginBottom: '20px'
|
|
63
|
+
}}>
|
|
64
|
+
<span style={{ fontSize: '32px' }}>
|
|
65
|
+
{getOperationIcon(data.operation)}
|
|
66
|
+
</span>
|
|
67
|
+
<div>
|
|
68
|
+
<h3 style={{ margin: 0, fontSize: '18px', opacity: 0.9 }}>
|
|
69
|
+
Calculator Result
|
|
70
|
+
</h3>
|
|
71
|
+
<p style={{ margin: '4px 0 0 0', fontSize: '14px', opacity: 0.7 }}>
|
|
72
|
+
{data.operation.charAt(0).toUpperCase() + data.operation.slice(1)}
|
|
73
|
+
</p>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<div style={{
|
|
78
|
+
background: 'rgba(255, 255, 255, 0.15)',
|
|
79
|
+
borderRadius: '12px',
|
|
80
|
+
padding: '20px',
|
|
81
|
+
backdropFilter: 'blur(10px)',
|
|
82
|
+
marginBottom: '16px'
|
|
83
|
+
}}>
|
|
84
|
+
<div style={{
|
|
85
|
+
fontSize: '28px',
|
|
86
|
+
fontWeight: 'bold',
|
|
87
|
+
textAlign: 'center',
|
|
88
|
+
marginBottom: '12px',
|
|
89
|
+
fontFamily: 'monospace'
|
|
90
|
+
}}>
|
|
91
|
+
{data.expression}
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<div style={{
|
|
95
|
+
display: 'flex',
|
|
96
|
+
justifyContent: 'space-around',
|
|
97
|
+
fontSize: '14px',
|
|
98
|
+
opacity: 0.9,
|
|
99
|
+
marginTop: '16px'
|
|
100
|
+
}}>
|
|
101
|
+
<div style={{ textAlign: 'center' }}>
|
|
102
|
+
<div style={{ fontSize: '12px', opacity: 0.7 }}>First</div>
|
|
103
|
+
<div style={{ fontWeight: 'bold', fontSize: '20px' }}>{data.a}</div>
|
|
104
|
+
</div>
|
|
105
|
+
<div style={{ textAlign: 'center' }}>
|
|
106
|
+
<div style={{ fontSize: '12px', opacity: 0.7 }}>Second</div>
|
|
107
|
+
<div style={{ fontWeight: 'bold', fontSize: '20px' }}>{data.b}</div>
|
|
108
|
+
</div>
|
|
109
|
+
<div style={{ textAlign: 'center' }}>
|
|
110
|
+
<div style={{ fontSize: '12px', opacity: 0.7 }}>Result</div>
|
|
111
|
+
<div style={{
|
|
112
|
+
fontWeight: 'bold',
|
|
113
|
+
fontSize: '24px',
|
|
114
|
+
color: '#fbbf24'
|
|
115
|
+
}}>
|
|
116
|
+
{data.result}
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<div style={{
|
|
123
|
+
fontSize: '12px',
|
|
124
|
+
textAlign: 'center',
|
|
125
|
+
opacity: 0.7
|
|
126
|
+
}}>
|
|
127
|
+
✨ NitroStack Calculator
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export default withToolData(CalculatorResult);
|
|
134
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** @type {import('next').NextConfig} */
|
|
2
|
+
const nextConfig = {
|
|
3
|
+
reactStrictMode: true,
|
|
4
|
+
transpilePackages: ['nitrostack'],
|
|
5
|
+
|
|
6
|
+
// Development optimizations to prevent cache corruption
|
|
7
|
+
...(process.env.NODE_ENV === 'development' && {
|
|
8
|
+
// Use memory cache instead of filesystem cache in dev to avoid stale chunks
|
|
9
|
+
webpack: (config, { isServer }) => {
|
|
10
|
+
// Disable persistent caching in development to prevent chunk reference errors
|
|
11
|
+
if (config.cache && config.cache.type === 'filesystem') {
|
|
12
|
+
config.cache = {
|
|
13
|
+
type: 'memory',
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Improve cache busting for new files
|
|
18
|
+
if (!isServer) {
|
|
19
|
+
config.cache = false; // Disable cache completely on client in dev
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return config;
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
// Disable build activity indicator which can cause issues
|
|
26
|
+
devIndicators: {
|
|
27
|
+
buildActivity: false,
|
|
28
|
+
buildActivityPosition: 'bottom-right',
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
// Faster dev server
|
|
32
|
+
compress: false,
|
|
33
|
+
}),
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default nextConfig;
|
|
37
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "calculator-widgets",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"private": true,
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "next dev -p 3001",
|
|
8
|
+
"build": "next build",
|
|
9
|
+
"start": "next start -p 3001"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"next": "^14.2.5",
|
|
13
|
+
"react": "^18.3.1",
|
|
14
|
+
"react-dom": "^18.3.1",
|
|
15
|
+
"nitrostack": "^1.0.0"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/node": "^20",
|
|
19
|
+
"@types/react": "^18",
|
|
20
|
+
"@types/react-dom": "^18",
|
|
21
|
+
"typescript": "^5"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
5
|
+
"allowJs": true,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"module": "esnext",
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"jsx": "preserve",
|
|
15
|
+
"incremental": true,
|
|
16
|
+
"plugins": [
|
|
17
|
+
{
|
|
18
|
+
"name": "next"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"paths": {
|
|
22
|
+
"@/*": ["./*"]
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
26
|
+
"exclude": ["node_modules"]
|
|
27
|
+
}
|
|
28
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"widgets": [
|
|
4
|
+
{
|
|
5
|
+
"uri": "/calculator-result",
|
|
6
|
+
"name": "Calculator Result",
|
|
7
|
+
"description": "Displays the result of a calculation with operation details",
|
|
8
|
+
"examples": [
|
|
9
|
+
{
|
|
10
|
+
"name": "Addition Example",
|
|
11
|
+
"description": "Shows the result of adding 5 + 3",
|
|
12
|
+
"data": {
|
|
13
|
+
"operation": "add",
|
|
14
|
+
"a": 5,
|
|
15
|
+
"b": 3,
|
|
16
|
+
"result": 8,
|
|
17
|
+
"expression": "5 + 3 = 8"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "Multiplication Example",
|
|
22
|
+
"description": "Shows the result of multiplying 6 × 7",
|
|
23
|
+
"data": {
|
|
24
|
+
"operation": "multiply",
|
|
25
|
+
"a": 6,
|
|
26
|
+
"b": 7,
|
|
27
|
+
"result": 42,
|
|
28
|
+
"expression": "6 × 7 = 42"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "Division Example",
|
|
33
|
+
"description": "Shows the result of dividing 20 ÷ 4",
|
|
34
|
+
"data": {
|
|
35
|
+
"operation": "divide",
|
|
36
|
+
"a": 20,
|
|
37
|
+
"b": 4,
|
|
38
|
+
"result": 5,
|
|
39
|
+
"expression": "20 ÷ 4 = 5"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"tags": ["calculator", "math", "result"]
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
"generatedAt": "2025-01-01T00:00:00.000Z"
|
|
47
|
+
}
|
|
48
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ES2022",
|
|
5
|
+
"lib": ["ES2022"],
|
|
6
|
+
"moduleResolution": "node",
|
|
7
|
+
"rootDir": "./src",
|
|
8
|
+
"outDir": "./dist",
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
|
11
|
+
"strict": true,
|
|
12
|
+
"skipLibCheck": true,
|
|
13
|
+
"resolveJsonModule": true,
|
|
14
|
+
"declaration": true,
|
|
15
|
+
"declarationMap": true,
|
|
16
|
+
"sourceMap": true,
|
|
17
|
+
"experimentalDecorators": true,
|
|
18
|
+
"emitDecoratorMetadata": true
|
|
19
|
+
},
|
|
20
|
+
"include": ["src/**/*"],
|
|
21
|
+
"exclude": ["node_modules", "dist", "src/widgets"]
|
|
22
|
+
}
|
|
23
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { McpApp, Module, ConfigModule } from 'nitrostack';
|
|
2
|
+
import { CalculatorModule } from './modules/calculator/calculator.module.js';
|
|
3
|
+
import { SystemHealthCheck } from './health/system.health.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Root Application Module
|
|
7
|
+
*
|
|
8
|
+
* This is the main module that bootstraps the MCP server.
|
|
9
|
+
* It registers all feature modules and health checks.
|
|
10
|
+
*/
|
|
11
|
+
@McpApp({
|
|
12
|
+
module: AppModule,
|
|
13
|
+
server: {
|
|
14
|
+
name: 'calculator-server',
|
|
15
|
+
version: '1.0.0'
|
|
16
|
+
},
|
|
17
|
+
logging: {
|
|
18
|
+
level: 'info'
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
@Module({
|
|
22
|
+
name: 'app',
|
|
23
|
+
description: 'Root application module',
|
|
24
|
+
imports: [
|
|
25
|
+
ConfigModule.forRoot(),
|
|
26
|
+
CalculatorModule
|
|
27
|
+
],
|
|
28
|
+
providers: [
|
|
29
|
+
// Health Checks
|
|
30
|
+
SystemHealthCheck,
|
|
31
|
+
]
|
|
32
|
+
})
|
|
33
|
+
export class AppModule {}
|
|
34
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { HealthCheck, HealthCheckInterface, HealthCheckResult } from 'nitrostack';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* System Health Check
|
|
5
|
+
*
|
|
6
|
+
* Monitors system resources and uptime
|
|
7
|
+
*/
|
|
8
|
+
@HealthCheck({
|
|
9
|
+
name: 'system',
|
|
10
|
+
description: 'System resource and uptime check',
|
|
11
|
+
interval: 30 // Check every 30 seconds
|
|
12
|
+
})
|
|
13
|
+
export class SystemHealthCheck implements HealthCheckInterface {
|
|
14
|
+
private startTime: number;
|
|
15
|
+
|
|
16
|
+
constructor() {
|
|
17
|
+
this.startTime = Date.now();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async check(): Promise<HealthCheckResult> {
|
|
21
|
+
try {
|
|
22
|
+
const memoryUsage = process.memoryUsage();
|
|
23
|
+
const uptime = Date.now() - this.startTime;
|
|
24
|
+
const uptimeSeconds = Math.floor(uptime / 1000);
|
|
25
|
+
|
|
26
|
+
// Convert memory to MB
|
|
27
|
+
const memoryUsedMB = Math.round(memoryUsage.heapUsed / 1024 / 1024);
|
|
28
|
+
const memoryTotalMB = Math.round(memoryUsage.heapTotal / 1024 / 1024);
|
|
29
|
+
|
|
30
|
+
// Consider unhealthy if memory usage is > 90%
|
|
31
|
+
const memoryPercent = (memoryUsage.heapUsed / memoryUsage.heapTotal) * 100;
|
|
32
|
+
const isHealthy = memoryPercent < 90;
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
status: isHealthy ? 'up' : 'degraded',
|
|
36
|
+
message: isHealthy
|
|
37
|
+
? 'System is healthy'
|
|
38
|
+
: 'High memory usage detected',
|
|
39
|
+
details: {
|
|
40
|
+
uptime: `${uptimeSeconds}s`,
|
|
41
|
+
memory: `${memoryUsedMB}MB / ${memoryTotalMB}MB (${Math.round(memoryPercent)}%)`,
|
|
42
|
+
pid: process.pid,
|
|
43
|
+
nodeVersion: process.version,
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
} catch (error: any) {
|
|
47
|
+
return {
|
|
48
|
+
status: 'down',
|
|
49
|
+
message: 'System health check failed',
|
|
50
|
+
details: error.message,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calculator MCP Server
|
|
3
|
+
*
|
|
4
|
+
* Main entry point for the MCP server.
|
|
5
|
+
* Uses the @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
|
+
});
|
|
27
|
+
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Module } from 'nitrostack';
|
|
2
|
+
import { CalculatorTools } from './calculator.tools.js';
|
|
3
|
+
import { CalculatorResources } from './calculator.resources.js';
|
|
4
|
+
import { CalculatorPrompts } from './calculator.prompts.js';
|
|
5
|
+
|
|
6
|
+
@Module({
|
|
7
|
+
name: 'calculator',
|
|
8
|
+
description: 'Basic arithmetic calculator',
|
|
9
|
+
controllers: [CalculatorTools, CalculatorResources, CalculatorPrompts]
|
|
10
|
+
})
|
|
11
|
+
export class CalculatorModule {}
|
|
12
|
+
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { PromptDecorator as Prompt, ExecutionContext } from 'nitrostack';
|
|
2
|
+
|
|
3
|
+
export class CalculatorPrompts {
|
|
4
|
+
@Prompt({
|
|
5
|
+
name: 'calculator_help',
|
|
6
|
+
description: 'Get help with calculator operations',
|
|
7
|
+
arguments: [
|
|
8
|
+
{
|
|
9
|
+
name: 'operation',
|
|
10
|
+
description: 'The operation to get help with (optional)',
|
|
11
|
+
required: false
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
})
|
|
15
|
+
async getHelp(args: any, ctx: ExecutionContext) {
|
|
16
|
+
ctx.logger.info('Generating calculator help prompt');
|
|
17
|
+
|
|
18
|
+
const operation = args.operation;
|
|
19
|
+
|
|
20
|
+
if (operation) {
|
|
21
|
+
// Help for specific operation
|
|
22
|
+
const helpText = this.getOperationHelp(operation);
|
|
23
|
+
return [
|
|
24
|
+
{
|
|
25
|
+
role: 'user' as const,
|
|
26
|
+
content: `How do I use the ${operation} operation in the calculator?`
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
role: 'assistant' as const,
|
|
30
|
+
content: helpText
|
|
31
|
+
}
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// General help
|
|
36
|
+
return [
|
|
37
|
+
{
|
|
38
|
+
role: 'user' as const,
|
|
39
|
+
content: 'How do I use the calculator?'
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
role: 'assistant' as const,
|
|
43
|
+
content: `The calculator supports four basic operations:
|
|
44
|
+
|
|
45
|
+
1. **Addition** - Add two numbers together
|
|
46
|
+
Example: calculate(operation="add", a=5, b=3) = 8
|
|
47
|
+
|
|
48
|
+
2. **Subtraction** - Subtract one number from another
|
|
49
|
+
Example: calculate(operation="subtract", a=10, b=4) = 6
|
|
50
|
+
|
|
51
|
+
3. **Multiplication** - Multiply two numbers
|
|
52
|
+
Example: calculate(operation="multiply", a=6, b=7) = 42
|
|
53
|
+
|
|
54
|
+
4. **Division** - Divide one number by another
|
|
55
|
+
Example: calculate(operation="divide", a=20, b=5) = 4
|
|
56
|
+
|
|
57
|
+
Just call the 'calculate' tool with the operation and two numbers!`
|
|
58
|
+
}
|
|
59
|
+
];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private getOperationHelp(operation: string): string {
|
|
63
|
+
const helps: Record<string, string> = {
|
|
64
|
+
add: 'Use addition to sum two numbers. Call calculate(operation="add", a=5, b=3) to get 8.',
|
|
65
|
+
subtract: 'Use subtraction to find the difference. Call calculate(operation="subtract", a=10, b=4) to get 6.',
|
|
66
|
+
multiply: 'Use multiplication to find the product. Call calculate(operation="multiply", a=6, b=7) to get 42.',
|
|
67
|
+
divide: 'Use division to find the quotient. Call calculate(operation="divide", a=20, b=5) to get 4. Note: Cannot divide by zero!'
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
return helps[operation] || 'Unknown operation. Available operations: add, subtract, multiply, divide.';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { ResourceDecorator as Resource, Widget, ExecutionContext } from 'nitrostack';
|
|
2
|
+
|
|
3
|
+
export class CalculatorResources {
|
|
4
|
+
@Resource({
|
|
5
|
+
uri: 'calculator://operations',
|
|
6
|
+
name: 'Calculator Operations',
|
|
7
|
+
description: 'List of available calculator operations',
|
|
8
|
+
mimeType: 'application/json',
|
|
9
|
+
examples: {
|
|
10
|
+
response: {
|
|
11
|
+
operations: [
|
|
12
|
+
{ name: 'add', symbol: '+', description: 'Addition' },
|
|
13
|
+
{ name: 'subtract', symbol: '-', description: 'Subtraction' },
|
|
14
|
+
{ name: 'multiply', symbol: '×', description: 'Multiplication' },
|
|
15
|
+
{ name: 'divide', symbol: '÷', description: 'Division' }
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
@Widget('calculator-operations')
|
|
21
|
+
async getOperations(uri: string, ctx: ExecutionContext) {
|
|
22
|
+
ctx.logger.info('Fetching calculator operations');
|
|
23
|
+
|
|
24
|
+
const operations = [
|
|
25
|
+
{
|
|
26
|
+
name: 'add',
|
|
27
|
+
symbol: '+',
|
|
28
|
+
description: 'Addition',
|
|
29
|
+
example: '5 + 3 = 8'
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'subtract',
|
|
33
|
+
symbol: '-',
|
|
34
|
+
description: 'Subtraction',
|
|
35
|
+
example: '10 - 4 = 6'
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'multiply',
|
|
39
|
+
symbol: '×',
|
|
40
|
+
description: 'Multiplication',
|
|
41
|
+
example: '6 × 7 = 42'
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'divide',
|
|
45
|
+
symbol: '÷',
|
|
46
|
+
description: 'Division',
|
|
47
|
+
example: '20 ÷ 5 = 4'
|
|
48
|
+
}
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
contents: [{
|
|
53
|
+
uri,
|
|
54
|
+
mimeType: 'application/json',
|
|
55
|
+
text: JSON.stringify({ operations }, null, 2)
|
|
56
|
+
}]
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { ToolDecorator as Tool, Widget, ExecutionContext, z } from 'nitrostack';
|
|
2
|
+
|
|
3
|
+
export class CalculatorTools {
|
|
4
|
+
@Tool({
|
|
5
|
+
name: 'calculate',
|
|
6
|
+
description: 'Perform basic arithmetic calculations',
|
|
7
|
+
inputSchema: z.object({
|
|
8
|
+
operation: z.enum(['add', 'subtract', 'multiply', 'divide']).describe('The operation to perform'),
|
|
9
|
+
a: z.number().describe('First number'),
|
|
10
|
+
b: z.number().describe('Second number')
|
|
11
|
+
}),
|
|
12
|
+
examples: {
|
|
13
|
+
request: {
|
|
14
|
+
operation: 'add',
|
|
15
|
+
a: 5,
|
|
16
|
+
b: 3
|
|
17
|
+
},
|
|
18
|
+
response: {
|
|
19
|
+
operation: 'add',
|
|
20
|
+
a: 5,
|
|
21
|
+
b: 3,
|
|
22
|
+
result: 8,
|
|
23
|
+
expression: '5 + 3 = 8'
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
@Widget('calculator-result')
|
|
28
|
+
async calculate(input: any, ctx: ExecutionContext) {
|
|
29
|
+
ctx.logger.info('Performing calculation', {
|
|
30
|
+
operation: input.operation,
|
|
31
|
+
a: input.a,
|
|
32
|
+
b: input.b
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
let result: number;
|
|
36
|
+
let symbol: string;
|
|
37
|
+
|
|
38
|
+
switch (input.operation) {
|
|
39
|
+
case 'add':
|
|
40
|
+
result = input.a + input.b;
|
|
41
|
+
symbol = '+';
|
|
42
|
+
break;
|
|
43
|
+
case 'subtract':
|
|
44
|
+
result = input.a - input.b;
|
|
45
|
+
symbol = '-';
|
|
46
|
+
break;
|
|
47
|
+
case 'multiply':
|
|
48
|
+
result = input.a * input.b;
|
|
49
|
+
symbol = '×';
|
|
50
|
+
break;
|
|
51
|
+
case 'divide':
|
|
52
|
+
if (input.b === 0) {
|
|
53
|
+
throw new Error('Cannot divide by zero');
|
|
54
|
+
}
|
|
55
|
+
result = input.a / input.b;
|
|
56
|
+
symbol = '÷';
|
|
57
|
+
break;
|
|
58
|
+
default:
|
|
59
|
+
throw new Error('Invalid operation');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
operation: input.operation,
|
|
64
|
+
a: input.a,
|
|
65
|
+
b: input.b,
|
|
66
|
+
result,
|
|
67
|
+
expression: `${input.a} ${symbol} ${input.b} = ${result}`
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|