@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
package/README.md
CHANGED
|
@@ -1,78 +1,64 @@
|
|
|
1
|
-
# @nitrostack/cli
|
|
1
|
+
# @nitrostack/cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Official NitroStack CLI for scaffolding, developing, and maintaining MCP server
|
|
4
|
+
projects.
|
|
4
5
|
|
|
5
|
-
[](https://www.npmjs.com/package/@nitrostack/cli)
|
|
7
|
+
[](https://www.npmjs.com/package/@nitrostack/cli)
|
|
8
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## ✨ Key Features
|
|
14
|
-
|
|
15
|
-
- **🏗️ Instant Scaffolding**: Bootstrap new MCP servers from professional templates in seconds.
|
|
16
|
-
- **🛠️ Code Generators**: Generate Modules, Tools, Guards, and Middleware with a single command.
|
|
17
|
-
- **🔄 Live Reload**: Powerful dev server with hot-reloading for rapid development.
|
|
18
|
-
- **🏷️ Type Generation**: Automatically generate TypeScript interfaces from your tool schemas.
|
|
19
|
-
- **🎨 Visual Studio**: Launch the built-in NitroStudio to test inputs/outputs and preview widgets.
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## 📦 Installation
|
|
24
|
-
|
|
25
|
-
We recommend installing the CLI globally to access the `nitrostack-cli` command anywhere:
|
|
10
|
+
## Installation
|
|
26
11
|
|
|
27
12
|
```bash
|
|
28
13
|
npm install -g @nitrostack/cli
|
|
29
14
|
```
|
|
30
15
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
## 🚀 Commands Overview
|
|
16
|
+
## Quick Start
|
|
34
17
|
|
|
35
|
-
### Initialize a New Project
|
|
36
18
|
```bash
|
|
37
|
-
nitrostack-cli init my-project
|
|
19
|
+
nitrostack-cli init my-project --template typescript-starter
|
|
20
|
+
cd my-project
|
|
21
|
+
npm run dev
|
|
38
22
|
```
|
|
39
23
|
|
|
40
|
-
|
|
24
|
+
## Core Commands
|
|
41
25
|
|
|
42
|
-
### Start Development Server
|
|
43
26
|
```bash
|
|
27
|
+
nitrostack-cli init <project-name> [--template <name>]
|
|
44
28
|
nitrostack-cli dev
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### Scaffold a New Tool
|
|
48
|
-
```bash
|
|
49
|
-
nitrostack-cli generate tool my-tool --module users
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### Build for Production
|
|
53
|
-
```bash
|
|
54
29
|
nitrostack-cli build
|
|
30
|
+
nitrostack-cli start
|
|
31
|
+
nitrostack-cli generate <type> [name] [--module <name>]
|
|
32
|
+
nitrostack-cli install
|
|
33
|
+
nitrostack-cli upgrade
|
|
55
34
|
```
|
|
56
35
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
## 🎨 NitroStudio
|
|
36
|
+
## Templates
|
|
60
37
|
|
|
61
|
-
|
|
38
|
+
- `typescript-starter`
|
|
39
|
+
- `typescript-oauth`
|
|
40
|
+
- `typescript-pizzaz`
|
|
62
41
|
|
|
63
|
-
|
|
42
|
+
## NitroStudio
|
|
64
43
|
|
|
65
|
-
|
|
44
|
+
NitroStudio is the recommended companion app for testing and debugging MCP
|
|
45
|
+
servers built with NitroStack.
|
|
66
46
|
|
|
67
|
-
|
|
47
|
+
- Download: <https://nitrostack.ai/studio>
|
|
48
|
+
- Studio: <https://nitrostack.ai/studio>
|
|
68
49
|
|
|
69
|
-
##
|
|
50
|
+
## Links
|
|
70
51
|
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
-
|
|
52
|
+
- CLI docs: <https://docs.nitrostack.ai/cli/overview>
|
|
53
|
+
- Full docs: <https://docs.nitrostack.ai>
|
|
54
|
+
- Source: <https://github.com/nitrocloudofficial/nitrostack>
|
|
55
|
+
- npm: <https://www.npmjs.com/package/@nitrostack/cli>
|
|
56
|
+
- Blog: <https://blog.nitrostack.ai>
|
|
75
57
|
|
|
76
|
-
|
|
58
|
+
## Community
|
|
77
59
|
|
|
78
|
-
|
|
60
|
+
- Discord: <https://discord.gg/uVWey6UhuD>
|
|
61
|
+
- X: <https://x.com/nitrostackai>
|
|
62
|
+
- YouTube: <https://www.youtube.com/@nitrostackai>
|
|
63
|
+
- LinkedIn: <https://linkedin.com/company/nitrostack-ai/>
|
|
64
|
+
- GitHub: <https://github.com/nitrostackai>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAmBA,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAmBA,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,iBAgPvD"}
|
package/dist/commands/build.js
CHANGED
|
@@ -76,6 +76,17 @@ export async function buildCommand(options) {
|
|
|
76
76
|
if (fs.existsSync(APP_DIR)) {
|
|
77
77
|
findWidgetPages(APP_DIR);
|
|
78
78
|
}
|
|
79
|
+
// Linked @nitrostack/widgets often has its own node_modules/react (e.g. v19) while this app
|
|
80
|
+
// uses v18. Esbuild resolves from the realpath of the symlinked package, so without aliases
|
|
81
|
+
// the widget bundle can contain two Reacts and render blank in MCP hosts. Next.js can use
|
|
82
|
+
// webpack aliases in next.config.js; production `nitrostack-cli build` mirrors that here.
|
|
83
|
+
const widgetsNm = path.join(widgetsPath, 'node_modules');
|
|
84
|
+
const widgetReactAliases = {
|
|
85
|
+
react: path.join(widgetsNm, 'react'),
|
|
86
|
+
'react-dom': path.join(widgetsNm, 'react-dom'),
|
|
87
|
+
'react/jsx-runtime': path.join(widgetsNm, 'react', 'jsx-runtime.js'),
|
|
88
|
+
'react/jsx-dev-runtime': path.join(widgetsNm, 'react', 'jsx-dev-runtime.js'),
|
|
89
|
+
};
|
|
79
90
|
// Bundle each widget
|
|
80
91
|
for (const widget of widgetPages) {
|
|
81
92
|
const tempEntry = path.join(OUT_DIR, `_temp_${widget.outputName}.jsx`);
|
|
@@ -118,7 +129,8 @@ function init() {
|
|
|
118
129
|
jsx: 'automatic',
|
|
119
130
|
jsxImportSource: 'react',
|
|
120
131
|
external: [],
|
|
121
|
-
nodePaths: [
|
|
132
|
+
nodePaths: [widgetsNm],
|
|
133
|
+
alias: widgetReactAliases,
|
|
122
134
|
define: {
|
|
123
135
|
'process.env.NODE_ENV': '"production"'
|
|
124
136
|
},
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface CursorOptions {
|
|
2
|
+
global?: boolean;
|
|
3
|
+
local?: boolean;
|
|
4
|
+
type?: string;
|
|
5
|
+
url?: string;
|
|
6
|
+
port?: string;
|
|
7
|
+
force?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function cursorCommand(options: CursorOptions): Promise<void>;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=cursor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/commands/cursor.ts"],"names":[],"mappings":"AAqBA,UAAU,aAAa;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAuBD,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAoOzE"}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import os from 'os';
|
|
5
|
+
import inquirer from 'inquirer';
|
|
6
|
+
import { createHeader, createSuccessBox, createErrorBox, NitroSpinner, log, spacer, nextSteps, showFooter, NITRO_BANNER_FULL } from '../ui/branding.js';
|
|
7
|
+
import { trackEvent, shutdownAnalytics } from '../analytics/posthog.js';
|
|
8
|
+
/** Normalize CLI --type values, including the deprecated `sse` alias. */
|
|
9
|
+
function normalizeConnectionType(raw) {
|
|
10
|
+
if (!raw)
|
|
11
|
+
return undefined;
|
|
12
|
+
if (raw === 'sse')
|
|
13
|
+
return 'legacy-sse';
|
|
14
|
+
if (raw === 'command' || raw === 'legacy-sse' || raw === 'streamable-http') {
|
|
15
|
+
return raw;
|
|
16
|
+
}
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
function defaultHttpUrl(type, port) {
|
|
20
|
+
if (type === 'streamable-http') {
|
|
21
|
+
return `http://localhost:${port}/mcp`;
|
|
22
|
+
}
|
|
23
|
+
return `http://localhost:${port}/sse`;
|
|
24
|
+
}
|
|
25
|
+
function isHttpConnectionType(type) {
|
|
26
|
+
return type === 'legacy-sse' || type === 'streamable-http';
|
|
27
|
+
}
|
|
28
|
+
export async function cursorCommand(options) {
|
|
29
|
+
console.log(NITRO_BANNER_FULL);
|
|
30
|
+
console.log(createHeader('Cursor Integration', 'Configure MCP server in Cursor'));
|
|
31
|
+
const startTime = Date.now();
|
|
32
|
+
trackEvent('cli_command_invoked', {
|
|
33
|
+
command: 'cursor',
|
|
34
|
+
options: Object.keys(options).filter(k => options[k] !== undefined),
|
|
35
|
+
});
|
|
36
|
+
const projectRoot = process.cwd();
|
|
37
|
+
const packageJsonPath = path.join(projectRoot, 'package.json');
|
|
38
|
+
// Validate project
|
|
39
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
40
|
+
console.log(createErrorBox('Not a Valid Project', 'package.json not found in the current directory.'));
|
|
41
|
+
trackEvent('cli_cursor_failed', {
|
|
42
|
+
error: 'Not a valid project: package.json missing',
|
|
43
|
+
});
|
|
44
|
+
await shutdownAnalytics();
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
let packageJson;
|
|
48
|
+
try {
|
|
49
|
+
packageJson = await fs.readJson(packageJsonPath);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
console.log(createErrorBox('Invalid package.json', 'Could not parse project package.json.'));
|
|
53
|
+
trackEvent('cli_cursor_failed', {
|
|
54
|
+
error: 'Invalid package.json parsing error',
|
|
55
|
+
});
|
|
56
|
+
await shutdownAnalytics();
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
const rawName = packageJson.name || path.basename(projectRoot);
|
|
60
|
+
const serverName = rawName.includes('/') ? rawName.split('/').pop() : rawName;
|
|
61
|
+
let target;
|
|
62
|
+
if (options.global) {
|
|
63
|
+
target = 'global';
|
|
64
|
+
}
|
|
65
|
+
else if (options.local) {
|
|
66
|
+
target = 'local';
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const answers = await inquirer.prompt([
|
|
70
|
+
{
|
|
71
|
+
type: 'list',
|
|
72
|
+
name: 'target',
|
|
73
|
+
message: chalk.white('Where would you like to install the Cursor MCP configuration?'),
|
|
74
|
+
choices: [
|
|
75
|
+
{ name: `Project-level ${chalk.dim('(.cursor/mcp.json)')}`, value: 'local' },
|
|
76
|
+
{ name: `Global ${chalk.dim('(~/.cursor/mcp.json)')}`, value: 'global' },
|
|
77
|
+
],
|
|
78
|
+
default: 'local',
|
|
79
|
+
}
|
|
80
|
+
]);
|
|
81
|
+
target = answers.target;
|
|
82
|
+
}
|
|
83
|
+
let type = normalizeConnectionType(options.type);
|
|
84
|
+
if (options.type && !type) {
|
|
85
|
+
console.log(createErrorBox('Invalid connection type', `Unknown --type "${options.type}". Use: command, legacy-sse, or streamable-http.`));
|
|
86
|
+
await shutdownAnalytics();
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
if (!type) {
|
|
90
|
+
const answers = await inquirer.prompt([
|
|
91
|
+
{
|
|
92
|
+
type: 'list',
|
|
93
|
+
name: 'type',
|
|
94
|
+
message: chalk.white('Choose the connection type for Cursor:'),
|
|
95
|
+
choices: [
|
|
96
|
+
{ name: `Command (Stdio) ${chalk.dim('─ Starts subprocess (recommended for local dev)')}`, value: 'command' },
|
|
97
|
+
{ name: `Legacy SSE (/sse) ${chalk.dim('─ Cursor and older HTTP clients (recommended for Cursor)')}`, value: 'legacy-sse' },
|
|
98
|
+
{ name: `Streamable HTTP (/mcp) ${chalk.dim('─ MCP Inspector and modern Streamable HTTP clients')}`, value: 'streamable-http' },
|
|
99
|
+
],
|
|
100
|
+
default: 'command',
|
|
101
|
+
}
|
|
102
|
+
]);
|
|
103
|
+
type = answers.type;
|
|
104
|
+
}
|
|
105
|
+
if (!type) {
|
|
106
|
+
console.log(createErrorBox('Invalid connection type', 'No connection type selected.'));
|
|
107
|
+
await shutdownAnalytics();
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
const port = options.port || '3000';
|
|
111
|
+
let httpUrl = options.url;
|
|
112
|
+
if (isHttpConnectionType(type) && !httpUrl) {
|
|
113
|
+
const defaultUrl = defaultHttpUrl(type, port);
|
|
114
|
+
const urlHint = type === 'legacy-sse'
|
|
115
|
+
? chalk.dim('Default /sse; /mcp also works for Cursor (legacy SSE fallback on GET).')
|
|
116
|
+
: chalk.dim('For MCP Inspector and clients that use POST initialize + mcp-session-id.');
|
|
117
|
+
const answers = await inquirer.prompt([
|
|
118
|
+
{
|
|
119
|
+
type: 'input',
|
|
120
|
+
name: 'url',
|
|
121
|
+
message: chalk.white('HTTP connection URL:'),
|
|
122
|
+
default: defaultUrl,
|
|
123
|
+
}
|
|
124
|
+
]);
|
|
125
|
+
httpUrl = answers.url;
|
|
126
|
+
if (urlHint) {
|
|
127
|
+
console.log(urlHint);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
let configFilePath;
|
|
131
|
+
if (target === 'global') {
|
|
132
|
+
configFilePath = path.join(os.homedir(), '.cursor', 'mcp.json');
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
configFilePath = path.join(projectRoot, '.cursor', 'mcp.json');
|
|
136
|
+
}
|
|
137
|
+
let entry;
|
|
138
|
+
if (type === 'command') {
|
|
139
|
+
const absIndexPath = path.join(projectRoot, 'dist', 'index.js');
|
|
140
|
+
entry = {
|
|
141
|
+
command: 'node',
|
|
142
|
+
args: [absIndexPath],
|
|
143
|
+
env: {}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
entry = {
|
|
148
|
+
url: httpUrl
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
const spinner = new NitroSpinner(`Configuring Cursor MCP server...`).start();
|
|
152
|
+
try {
|
|
153
|
+
await fs.ensureDir(path.dirname(configFilePath));
|
|
154
|
+
let mcpConfig = { mcpServers: {} };
|
|
155
|
+
if (await fs.pathExists(configFilePath)) {
|
|
156
|
+
try {
|
|
157
|
+
mcpConfig = await fs.readJson(configFilePath);
|
|
158
|
+
}
|
|
159
|
+
catch (e) {
|
|
160
|
+
// Corrupted or empty file, initialize it
|
|
161
|
+
mcpConfig = { mcpServers: {} };
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (!mcpConfig.mcpServers) {
|
|
165
|
+
mcpConfig.mcpServers = {};
|
|
166
|
+
}
|
|
167
|
+
// Check if it already exists
|
|
168
|
+
if (mcpConfig.mcpServers[serverName] && !options.force) {
|
|
169
|
+
spinner.stop();
|
|
170
|
+
const { overwrite } = await inquirer.prompt([
|
|
171
|
+
{
|
|
172
|
+
type: 'confirm',
|
|
173
|
+
name: 'overwrite',
|
|
174
|
+
message: chalk.yellow(`MCP Server "${serverName}" is already registered in Cursor config. Overwrite?`),
|
|
175
|
+
default: true,
|
|
176
|
+
}
|
|
177
|
+
]);
|
|
178
|
+
if (!overwrite) {
|
|
179
|
+
log('Cancelled integration', 'warning');
|
|
180
|
+
trackEvent('cli_cursor_cancelled', {
|
|
181
|
+
server_name: serverName,
|
|
182
|
+
target,
|
|
183
|
+
type,
|
|
184
|
+
});
|
|
185
|
+
await shutdownAnalytics();
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
spinner.start();
|
|
189
|
+
}
|
|
190
|
+
mcpConfig.mcpServers[serverName] = entry;
|
|
191
|
+
await fs.writeJson(configFilePath, mcpConfig, { spaces: 2 });
|
|
192
|
+
spinner.succeed(`Registered "${serverName}" in Cursor config`);
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
spinner.fail('Failed to update Cursor configuration');
|
|
196
|
+
console.log(createErrorBox('Integration Failed', err instanceof Error ? err.message : String(err)));
|
|
197
|
+
trackEvent('cli_cursor_failed', {
|
|
198
|
+
error: err instanceof Error ? err.message : String(err),
|
|
199
|
+
target,
|
|
200
|
+
type,
|
|
201
|
+
});
|
|
202
|
+
await shutdownAnalytics();
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
// Summary
|
|
206
|
+
spacer();
|
|
207
|
+
console.log(createSuccessBox('Cursor Integration Successful', [
|
|
208
|
+
`Configured target: ${chalk.cyan(configFilePath)}`,
|
|
209
|
+
`Server registered: ${chalk.cyan(serverName)}`,
|
|
210
|
+
`Connection type: ${chalk.cyan(type)}`,
|
|
211
|
+
type === 'command'
|
|
212
|
+
? `Command path: ${chalk.dim(path.join(projectRoot, 'dist', 'index.js'))}`
|
|
213
|
+
: `HTTP URL: ${chalk.cyan(httpUrl)}`
|
|
214
|
+
]));
|
|
215
|
+
if (type === 'command') {
|
|
216
|
+
// Check if dist/index.js exists
|
|
217
|
+
const distIndexPath = path.join(projectRoot, 'dist', 'index.js');
|
|
218
|
+
if (!fs.existsSync(distIndexPath)) {
|
|
219
|
+
log('Warning: dist/index.js not found. Remember to run "npm run build" first!', 'warning');
|
|
220
|
+
spacer();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (type === 'legacy-sse') {
|
|
224
|
+
log('Tip: ensure the server is running in dual or http mode before connecting from Cursor.', 'info');
|
|
225
|
+
}
|
|
226
|
+
nextSteps([
|
|
227
|
+
'Restart/Reload your Cursor window to load the new MCP server',
|
|
228
|
+
'Check active MCP servers in Cursor under Settings > Tools > MCP',
|
|
229
|
+
]);
|
|
230
|
+
showFooter();
|
|
231
|
+
trackEvent('cli_cursor_completed', {
|
|
232
|
+
target,
|
|
233
|
+
type,
|
|
234
|
+
server_name: serverName,
|
|
235
|
+
duration_ms: Date.now() - startTime,
|
|
236
|
+
});
|
|
237
|
+
await shutdownAnalytics();
|
|
238
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":"AAgUA,UAAU,eAAe;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwHvG"}
|
|
@@ -17,13 +17,12 @@ const TEMPLATES = {
|
|
|
17
17
|
@Middleware()
|
|
18
18
|
export class ${name} implements MiddlewareInterface {
|
|
19
19
|
async use(context: ExecutionContext, next: () => Promise<any>) {
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
// Use context.logger instead of console.log — console breaks JSON-RPC over stdio in MCP mode
|
|
21
|
+
context.logger.info(\`[\${context.toolName}] Started\`);
|
|
22
|
+
|
|
23
23
|
const result = await next();
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
console.log(\`[\${context.toolName}] Completed\`);
|
|
24
|
+
|
|
25
|
+
context.logger.info(\`[\${context.toolName}] Completed\`);
|
|
27
26
|
|
|
28
27
|
return result;
|
|
29
28
|
}
|
package/dist/commands/init.js
CHANGED
|
@@ -293,7 +293,7 @@ async function createProjectFromScratch(targetDir, projectName, answers) {
|
|
|
293
293
|
};
|
|
294
294
|
fs.writeJSONSync(path.join(targetDir, 'tsconfig.json'), tsconfig, { spaces: 2 });
|
|
295
295
|
fs.mkdirSync(path.join(targetDir, 'src'), { recursive: true });
|
|
296
|
-
const indexTs = `import { createServer,
|
|
296
|
+
const indexTs = `import { createServer, Tool, z } from '@nitrostack/core';
|
|
297
297
|
|
|
298
298
|
const server = createServer({
|
|
299
299
|
name: '${projectName}',
|
|
@@ -302,7 +302,7 @@ const server = createServer({
|
|
|
302
302
|
});
|
|
303
303
|
|
|
304
304
|
server.tool(
|
|
305
|
-
|
|
305
|
+
new Tool({
|
|
306
306
|
name: 'hello',
|
|
307
307
|
description: 'Say hello to someone',
|
|
308
308
|
inputSchema: z.object({
|
|
@@ -347,7 +347,7 @@ npm run build
|
|
|
347
347
|
npm start
|
|
348
348
|
\`\`\`
|
|
349
349
|
|
|
350
|
-
Built with [NitroStack](https://nitrostack.
|
|
350
|
+
Built with [NitroStack](https://nitrostack.ai) ⚡
|
|
351
351
|
`;
|
|
352
352
|
fs.writeFileSync(path.join(targetDir, 'README.md'), readme);
|
|
353
353
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAiBA,UAAU,YAAY;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAiBA,UAAU,YAAY;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,iBA0FvD"}
|
package/dist/commands/start.js
CHANGED
|
@@ -35,6 +35,8 @@ export async function startCommand(options) {
|
|
|
35
35
|
{ label: 'Server', value: `http://localhost:${port}` },
|
|
36
36
|
{ label: 'Mode', value: 'Production' },
|
|
37
37
|
{ label: 'Transport', value: 'HTTP + STDIO (dual)' },
|
|
38
|
+
{ label: 'Streamable HTTP', value: `http://localhost:${port}/mcp` },
|
|
39
|
+
{ label: 'Legacy SDK SSE', value: `http://localhost:${port}/sse` },
|
|
38
40
|
...(hasBuiltWidgets ? [{ label: 'Widgets', value: 'Bundled' }] : []),
|
|
39
41
|
]));
|
|
40
42
|
log('Starting server...', 'info');
|
|
@@ -2,6 +2,18 @@ interface UpgradeOptions {
|
|
|
2
2
|
latest?: boolean;
|
|
3
3
|
dryRun?: boolean;
|
|
4
4
|
}
|
|
5
|
+
/**
|
|
6
|
+
* Fetch a package's latest published version from NPM using standard https module.
|
|
7
|
+
*/
|
|
8
|
+
export declare function fetchLatestNpmVersion(packageName: string): Promise<string>;
|
|
9
|
+
/**
|
|
10
|
+
* Compare two version strings
|
|
11
|
+
*/
|
|
12
|
+
export declare function compareVersions(v1: string, v2: string): number;
|
|
13
|
+
/**
|
|
14
|
+
* Determine if a dependency refers to a local file or workspace link.
|
|
15
|
+
*/
|
|
16
|
+
export declare function isLocalDependency(version: string): boolean;
|
|
5
17
|
/**
|
|
6
18
|
* Main upgrade command handler
|
|
7
19
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../../src/commands/upgrade.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../../src/commands/upgrade.ts"],"names":[],"mappings":"AA2BA,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAUD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgD1E;AA2BD;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAa9D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAM1D;AAqED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAsI3E"}
|