@nitrostack/cli 1.0.10 ā 1.0.13
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/README.md +38 -52
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +13 -1
- package/dist/commands/cursor.d.ts +11 -0
- package/dist/commands/cursor.d.ts.map +1 -0
- package/dist/commands/cursor.js +238 -0
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +5 -6
- package/dist/commands/init.js +3 -3
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +2 -0
- package/dist/commands/upgrade.d.ts +12 -0
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +144 -106
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -0
- package/package.json +4 -4
- package/templates/typescript-oauth/.env.example +75 -14
- package/templates/typescript-oauth/README.md +37 -51
- package/templates/typescript-oauth/package.json +2 -1
- package/templates/typescript-oauth/src/app.module.ts +7 -0
- package/templates/typescript-oauth/src/guards/oauth.guard.ts +19 -0
- package/templates/typescript-oauth/src/index.ts +9 -11
- package/templates/typescript-oauth/src/modules/flights/flights.prompts.ts +19 -1
- package/templates/typescript-oauth/src/services/duffel.service.ts +4 -2
- package/templates/typescript-oauth/src/widgets/package.json +2 -1
- package/templates/typescript-pizzaz/.env.example +14 -0
- package/templates/typescript-pizzaz/README.md +35 -60
- package/templates/typescript-pizzaz/package.json +2 -1
- package/templates/typescript-pizzaz/src/modules/pizzaz/pizzaz.tools.ts +17 -3
- package/templates/typescript-pizzaz/src/widgets/package.json +1 -0
- package/templates/typescript-starter/.env.example +11 -5
- package/templates/typescript-starter/README.md +28 -68
- package/templates/typescript-starter/package.json +2 -1
- package/templates/typescript-starter/src/widgets/package.json +2 -1
|
@@ -41,6 +41,25 @@ export class OAuthGuard implements Guard {
|
|
|
41
41
|
} else if (metaToken) {
|
|
42
42
|
token = metaToken as string;
|
|
43
43
|
}
|
|
44
|
+
|
|
45
|
+
// Enforcement gate: when OAuth is not required (OAUTH_REQUIRED not "true"),
|
|
46
|
+
// do not reject. Best-effort: if a valid token happens to be present, attach
|
|
47
|
+
// its identity; otherwise allow the request through unauthenticated.
|
|
48
|
+
if (!OAuthModule.isAuthRequired()) {
|
|
49
|
+
if (token) {
|
|
50
|
+
const result = await OAuthModule.validateToken(token);
|
|
51
|
+
if (result.valid) {
|
|
52
|
+
const payload = result.payload as OAuthTokenPayload;
|
|
53
|
+
context.auth = {
|
|
54
|
+
subject: payload.sub,
|
|
55
|
+
scopes: this.extractScopes(payload),
|
|
56
|
+
clientId: payload.client_id,
|
|
57
|
+
tokenPayload: payload,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
44
63
|
|
|
45
64
|
if (!token) {
|
|
46
65
|
throw new Error(
|
|
@@ -28,26 +28,24 @@ async function bootstrap() {
|
|
|
28
28
|
try {
|
|
29
29
|
console.error('š Starting Calculator MCP Server with OAuth 2.1...\\n');
|
|
30
30
|
|
|
31
|
-
// Validate required environment variables for OAuth
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
missing.forEach(v => console.error(` - ${v}`));
|
|
38
|
-
console.error('\\nš” Copy .env.example to .env and configure your OAuth provider');
|
|
39
|
-
console.error(' Or check the test-oauth/.env for reference\\n');
|
|
40
|
-
process.exit(1);
|
|
31
|
+
// Validate required environment variables for OAuth, set defaults if missing
|
|
32
|
+
if (!process.env.RESOURCE_URI || !process.env.AUTH_SERVER_URL) {
|
|
33
|
+
console.error('ā ļø Warning: Missing RESOURCE_URI or AUTH_SERVER_URL environment variables.');
|
|
34
|
+
console.error(' Defaulting to local test endpoints. Copy .env.example to .env to configure.\n');
|
|
35
|
+
process.env.RESOURCE_URI = process.env.RESOURCE_URI || 'http://localhost:3000';
|
|
36
|
+
process.env.AUTH_SERVER_URL = process.env.AUTH_SERVER_URL || 'http://localhost:8080/auth';
|
|
41
37
|
}
|
|
42
38
|
|
|
43
39
|
// Create the MCP application
|
|
44
40
|
const server = await McpApplicationFactory.create(AppModule);
|
|
45
41
|
|
|
42
|
+
const authEnforced = process.env.OAUTH_REQUIRED === 'true';
|
|
46
43
|
console.error('ā
OAuth 2.1 Module configured');
|
|
47
44
|
console.error(` Resource URI: ${process.env.RESOURCE_URI}`);
|
|
48
45
|
console.error(` Auth Server: ${process.env.AUTH_SERVER_URL}`);
|
|
49
46
|
console.error(` Scopes: read, write, admin`);
|
|
50
|
-
console.error(` Audience: ${process.env.TOKEN_AUDIENCE || process.env.RESOURCE_URI}
|
|
47
|
+
console.error(` Audience: ${process.env.TOKEN_AUDIENCE || process.env.RESOURCE_URI}`);
|
|
48
|
+
console.error(` Enforcement: ${authEnforced ? 'ON (OAUTH_REQUIRED=true)' : 'OFF (dev mode ā set OAUTH_REQUIRED=true to enforce)'}\\n`);
|
|
51
49
|
|
|
52
50
|
// Start the server
|
|
53
51
|
await server.start();
|
|
@@ -79,8 +79,26 @@ Respond to EXACTLY what the user asked - nothing more.`;
|
|
|
79
79
|
]
|
|
80
80
|
})
|
|
81
81
|
async flightComparison(input: any, ctx: ExecutionContext) {
|
|
82
|
+
let ids: string[] = [];
|
|
83
|
+
if (Array.isArray(input.offerIds)) {
|
|
84
|
+
ids = input.offerIds;
|
|
85
|
+
} else if (typeof input.offerIds === 'string') {
|
|
86
|
+
const trimmed = input.offerIds.trim();
|
|
87
|
+
if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
|
|
88
|
+
try {
|
|
89
|
+
const parsed = JSON.parse(trimmed);
|
|
90
|
+
ids = Array.isArray(parsed) ? parsed : [parsed];
|
|
91
|
+
} catch {
|
|
92
|
+
ids = trimmed.split(',').map((s: string) => s.trim());
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
ids = trimmed.split(',').map((s: string) => s.trim());
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
ids = ids.filter(Boolean);
|
|
99
|
+
|
|
82
100
|
const offers = await Promise.all(
|
|
83
|
-
|
|
101
|
+
ids.map((id: string) => this.duffelService.getOffer(id))
|
|
84
102
|
);
|
|
85
103
|
|
|
86
104
|
const comparisonData = offers.map((offer: any) => {
|
|
@@ -12,9 +12,11 @@ export class DuffelService {
|
|
|
12
12
|
private duffel: Duffel;
|
|
13
13
|
|
|
14
14
|
constructor() {
|
|
15
|
-
|
|
15
|
+
let apiKey = process.env.DUFFEL_API_KEY;
|
|
16
16
|
if (!apiKey) {
|
|
17
|
-
|
|
17
|
+
console.error('ā ļø Warning: DUFFEL_API_KEY environment variable is missing.');
|
|
18
|
+
console.error(' Running with a dummy key for testing/dry-run mode.\n');
|
|
19
|
+
apiKey = 'duffel_test_dummy_key';
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
this.duffel = new Duffel({
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# NitroStack Configuration
|
|
2
|
+
NITRO_LOG_LEVEL=info
|
|
3
|
+
NITROSTACK_APP_MODE=openai
|
|
4
|
+
|
|
5
|
+
# Server Transport Configuration (Optional)
|
|
6
|
+
# =============================================================================
|
|
7
|
+
# MCP_TRANSPORT_TYPE: Toggles transport mode. Values: stdio | http | dual.
|
|
8
|
+
# Defaults to 'stdio' in development and 'dual' in production/NODE_ENV=production.
|
|
9
|
+
# =============================================================================
|
|
10
|
+
# MCP_TRANSPORT_TYPE=stdio
|
|
11
|
+
# PORT=3000
|
|
12
|
+
# HOST=localhost
|
|
13
|
+
# ENABLE_CORS=true
|
|
14
|
+
|
|
1
15
|
# Mapbox Configuration (Optional)
|
|
2
16
|
# =============================================================================
|
|
3
17
|
# The map widget uses Mapbox GL for interactive maps.
|
|
@@ -1,79 +1,54 @@
|
|
|
1
|
-
#
|
|
1
|
+
# NitroStack Pizzaz Template
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Template focused on rich, interactive widget experiences (map/list/detail flows)
|
|
4
|
+
using the NitroStack widget SDK patterns.
|
|
4
5
|
|
|
5
|
-
##
|
|
6
|
+
## What This Template Includes
|
|
6
7
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
8
|
+
- Widget-heavy module and UI structure
|
|
9
|
+
- Interactive examples for advanced frontends
|
|
10
|
+
- Optional map provider integration pattern
|
|
11
|
+
- Studio-friendly development workflow
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
## š Quick Start
|
|
15
|
-
|
|
16
|
-
### 1. Initialize Your Project
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
npx nitrostack init my-pizza-app --template typescript-pizzaz
|
|
20
|
-
cd my-pizza-app
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
### 2. Install Dependencies
|
|
13
|
+
## Quick Start
|
|
24
14
|
|
|
25
15
|
```bash
|
|
26
|
-
|
|
16
|
+
npx @nitrostack/cli init my-pizzaz-app --template typescript-pizzaz
|
|
17
|
+
cd my-pizzaz-app
|
|
18
|
+
npm run dev
|
|
27
19
|
```
|
|
28
20
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
NitroStudio provides the best experience for visual testing of widgets and maps.
|
|
32
|
-
|
|
33
|
-

|
|
34
|
-
|
|
35
|
-
1. **Download NitroStudio**: [nitrostack.ai/studio](https://nitrostack.ai/studio)
|
|
36
|
-
2. **Open Project**: Launch NitroStudio and select your project folder.
|
|
37
|
-
3. **View Maps**: Use the chat or visual tools to explore your pizza shops.
|
|
38
|
-
|
|
39
|
-
---
|
|
21
|
+
## Optional Configuration
|
|
40
22
|
|
|
41
|
-
|
|
23
|
+
If this project uses a map provider, configure API tokens in widget `.env` files
|
|
24
|
+
as documented in the template source.
|
|
42
25
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
To enable the interactive map, add your Mapbox token:
|
|
46
|
-
|
|
47
|
-
1. Get a free token at [mapbox.com](https://www.mapbox.com/).
|
|
48
|
-
2. Create `src/widgets/.env` and add:
|
|
49
|
-
```env
|
|
50
|
-
NEXT_PUBLIC_MAPBOX_TOKEN=pk.your_token_here
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
---
|
|
54
|
-
|
|
55
|
-
## š ļø Commands
|
|
26
|
+
## Common Commands
|
|
56
27
|
|
|
57
28
|
```bash
|
|
58
|
-
# Start dev server with Studio integration
|
|
59
29
|
npm run dev
|
|
60
|
-
|
|
61
|
-
# Build for production
|
|
62
30
|
npm run build
|
|
63
|
-
|
|
64
|
-
# Manage widgets directly
|
|
31
|
+
npm start
|
|
65
32
|
npm run widget <command>
|
|
66
33
|
```
|
|
67
34
|
|
|
68
|
-
##
|
|
35
|
+
## NitroStudio
|
|
36
|
+
|
|
37
|
+
NitroStudio is the fastest way to test and debug interactive widget output.
|
|
38
|
+
|
|
39
|
+
- Download: <https://nitrostack.ai/studio>
|
|
40
|
+
- Studio: <https://nitrostack.ai/studio>
|
|
41
|
+
|
|
42
|
+
## Links
|
|
43
|
+
|
|
44
|
+
- Docs: <https://docs.nitrostack.ai>
|
|
45
|
+
- Widgets docs: <https://docs.nitrostack.ai/sdk/typescript/ui/widgets>
|
|
46
|
+
- Main repository: <https://github.com/nitrocloudofficial/nitrostack>
|
|
69
47
|
|
|
70
|
-
|
|
71
|
-
- `src/widgets/app/pizza-map/` ā Next.js Map widget.
|
|
72
|
-
- `src/widgets/app/pizza-list/` ā Filterable shop list.
|
|
73
|
-
- `src/widgets/app/pizza-shop/` ā Detail view with actions.
|
|
48
|
+
## Community
|
|
74
49
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
-
|
|
78
|
-
-
|
|
79
|
-
-
|
|
50
|
+
- Discord: <https://discord.gg/uVWey6UhuD>
|
|
51
|
+
- X: <https://x.com/nitrostackai>
|
|
52
|
+
- YouTube: <https://www.youtube.com/@nitrostackai>
|
|
53
|
+
- LinkedIn: <https://linkedin.com/company/nitrostack-ai/>
|
|
54
|
+
- GitHub: <https://github.com/nitrostackai>
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { ToolDecorator as Tool, Widget, ExecutionContext, Injectable, z } from '@nitrostack/core';
|
|
2
2
|
import { PizzazService } from './pizzaz.service.js';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Pizzaz widget metadata for ChatGPT / MCP Apps (CSP for Unsplash images, optional border).
|
|
6
|
+
* For production ChatGPT submission, set `domain` to your app HTTPS origin per OpenAI Apps SDK docs.
|
|
7
|
+
*/
|
|
8
|
+
function pizzazWidget(route: string) {
|
|
9
|
+
return {
|
|
10
|
+
route,
|
|
11
|
+
prefersBorder: true,
|
|
12
|
+
csp: {
|
|
13
|
+
resourceDomains: ['https://images.unsplash.com'],
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
4
18
|
const ShowMapSchema = z.object({
|
|
5
19
|
filter: z.enum(['open_now', 'top_rated', 'all']).optional().describe('Filter to apply'),
|
|
6
20
|
});
|
|
@@ -67,7 +81,7 @@ export class PizzazTools {
|
|
|
67
81
|
}
|
|
68
82
|
}
|
|
69
83
|
})
|
|
70
|
-
@Widget('pizza-map')
|
|
84
|
+
@Widget(pizzazWidget('pizza-map'))
|
|
71
85
|
async showPizzaMap(args: z.infer<typeof ShowMapSchema>, ctx: ExecutionContext) {
|
|
72
86
|
let shops;
|
|
73
87
|
|
|
@@ -122,7 +136,7 @@ export class PizzazTools {
|
|
|
122
136
|
}
|
|
123
137
|
}
|
|
124
138
|
})
|
|
125
|
-
@Widget('pizza-list')
|
|
139
|
+
@Widget(pizzazWidget('pizza-list'))
|
|
126
140
|
async showPizzaList(args: z.infer<typeof ShowListSchema>, ctx: ExecutionContext) {
|
|
127
141
|
const shops = this.pizzazService.getShopsFiltered(args);
|
|
128
142
|
|
|
@@ -180,7 +194,7 @@ export class PizzazTools {
|
|
|
180
194
|
}
|
|
181
195
|
}
|
|
182
196
|
})
|
|
183
|
-
@Widget('pizza-shop')
|
|
197
|
+
@Widget(pizzazWidget('pizza-shop'))
|
|
184
198
|
async showPizzaShop(args: z.infer<typeof ShowShopSchema>, ctx: ExecutionContext) {
|
|
185
199
|
const shop = this.pizzazService.getShopById(args.shopId);
|
|
186
200
|
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
# NitroStack
|
|
1
|
+
# NitroStack Configuration
|
|
2
|
+
NITRO_LOG_LEVEL=info
|
|
3
|
+
NITROSTACK_APP_MODE=openai
|
|
4
|
+
|
|
5
|
+
# Server Transport Configuration (Optional)
|
|
2
6
|
# =============================================================================
|
|
3
|
-
#
|
|
7
|
+
# MCP_TRANSPORT_TYPE: Toggles transport mode. Values: stdio | http | dual.
|
|
8
|
+
# Defaults to 'stdio' in development and 'dual' in production/NODE_ENV=production.
|
|
4
9
|
# =============================================================================
|
|
5
|
-
|
|
6
|
-
#
|
|
7
|
-
#
|
|
10
|
+
# MCP_TRANSPORT_TYPE=stdio
|
|
11
|
+
# PORT=3000
|
|
12
|
+
# HOST=localhost
|
|
13
|
+
# ENABLE_CORS=true
|
|
@@ -1,89 +1,49 @@
|
|
|
1
|
-
#
|
|
1
|
+
# NitroStack Starter Template
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Minimal template for learning NitroStack fundamentals with a calculator-focused
|
|
4
|
+
MCP server and basic widgets.
|
|
4
5
|
|
|
5
|
-
##
|
|
6
|
+
## What This Template Includes
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
- `calculator` module with tools, resources, and prompts
|
|
9
|
+
- TypeScript + Zod validation setup
|
|
10
|
+
- Widget-ready project structure
|
|
11
|
+
- Production-friendly npm scripts
|
|
8
12
|
|
|
9
|
-
|
|
10
|
-
- **Interactive Tools** ā A `calculate` tool for performing arithmetic operations.
|
|
11
|
-
- **Dynamic Resources** ā A `calculator://operations` resource for discovering capabilities.
|
|
12
|
-
- **Prompt Library** ā Context-aware prompts for guiding users.
|
|
13
|
-
- **Pre-built UI Widgets** ā Beautiful, high-performance UI components for results and listings.
|
|
14
|
-
- **Production-Ready** ā Uses TypeScript, Zod for validation, and best-in-class logging.
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## š Quick Start
|
|
19
|
-
|
|
20
|
-
### 1. Initialize Your Project
|
|
21
|
-
|
|
22
|
-
If you haven't already, scaffold your project using the NitroStack CLI:
|
|
13
|
+
## Quick Start
|
|
23
14
|
|
|
24
15
|
```bash
|
|
25
|
-
npx nitrostack init my-server --template typescript-starter
|
|
16
|
+
npx @nitrostack/cli init my-server --template typescript-starter
|
|
26
17
|
cd my-server
|
|
18
|
+
npm run dev
|
|
27
19
|
```
|
|
28
20
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
Install all project dependencies (including the visual widget SDK) in one step:
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
npm run install:all
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### 3. Get NitroStudio
|
|
38
|
-
|
|
39
|
-
NitroStudio is the recommended visual client for running, testing, and managing your NitroStack projects.
|
|
40
|
-
|
|
41
|
-

|
|
42
|
-
|
|
43
|
-
1. **Download NitroStudio**: [nitrostack.ai/studio](https://nitrostack.ai/studio)
|
|
44
|
-
2. **Open Project**: Launch NitroStudio and open this project folder.
|
|
45
|
-
3. **Run**: NitroStudio handles the rest!
|
|
46
|
-
|
|
47
|
-
---
|
|
48
|
-
|
|
49
|
-
## š ļø Development
|
|
50
|
-
|
|
51
|
-
If you prefer using the command line:
|
|
21
|
+
## Common Commands
|
|
52
22
|
|
|
53
23
|
```bash
|
|
54
|
-
# Start development server (Server + Widgets + Studio)
|
|
55
24
|
npm run dev
|
|
56
|
-
|
|
57
|
-
# Build for production
|
|
58
25
|
npm run build
|
|
59
|
-
|
|
60
|
-
# Start production server
|
|
61
26
|
npm start
|
|
62
27
|
```
|
|
63
28
|
|
|
64
|
-
##
|
|
29
|
+
## NitroStudio
|
|
65
30
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
ā āāā calculator.tools.ts # @Tool implementations
|
|
72
|
-
ā āāā calculator.resources.ts # @Resource definitions
|
|
73
|
-
ā āāā calculator.prompts.ts # @Prompt templates
|
|
74
|
-
āāā widgets/ # Visual SDK UI components
|
|
75
|
-
āāā app.module.ts # Root application module
|
|
76
|
-
āāā index.ts # Server entry point
|
|
77
|
-
```
|
|
31
|
+
NitroStudio is the recommended way to test and debug this template during
|
|
32
|
+
development.
|
|
33
|
+
|
|
34
|
+
- Download: <https://nitrostack.ai/studio>
|
|
35
|
+
- Studio: <https://nitrostack.ai/studio>
|
|
78
36
|
|
|
79
|
-
##
|
|
37
|
+
## Links
|
|
80
38
|
|
|
81
|
-
|
|
39
|
+
- Docs: <https://docs.nitrostack.ai>
|
|
40
|
+
- Templates docs: <https://docs.nitrostack.ai/templates/01-starter-template>
|
|
41
|
+
- Main repository: <https://github.com/nitrocloudofficial/nitrostack>
|
|
82
42
|
|
|
83
|
-
|
|
84
|
-
- **Documentation**: [docs.nitrostack.ai](https://docs.nitrostack.ai)
|
|
85
|
-
- **Discord**: [Join our community](https://nitrostack.ai/discord)
|
|
43
|
+
## Community
|
|
86
44
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
45
|
+
- Discord: <https://discord.gg/uVWey6UhuD>
|
|
46
|
+
- X: <https://x.com/nitrostackai>
|
|
47
|
+
- YouTube: <https://www.youtube.com/@nitrostackai>
|
|
48
|
+
- LinkedIn: <https://linkedin.com/company/nitrostack-ai/>
|
|
49
|
+
- GitHub: <https://github.com/nitrostackai>
|