@kylewadegrove/cutline-mcp-cli 0.5.1 → 0.6.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.
@@ -2,4 +2,5 @@ export interface CallbackResult {
2
2
  token: string;
3
3
  email?: string;
4
4
  }
5
- export declare function startCallbackServer(): Promise<CallbackResult>;
5
+ export type CallbackSource = 'login' | 'setup' | 'upgrade';
6
+ export declare function startCallbackServer(source?: CallbackSource): Promise<CallbackResult>;
@@ -1,7 +1,7 @@
1
1
  import express from 'express';
2
2
  const CALLBACK_PORT = 8765;
3
3
  const TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes (allows time for email magic link)
4
- export async function startCallbackServer() {
4
+ export async function startCallbackServer(source = 'login') {
5
5
  return new Promise((resolve, reject) => {
6
6
  const app = express();
7
7
  let server;
@@ -59,12 +59,17 @@ export async function startCallbackServer() {
59
59
  <div class="checkmark">&#10003;</div>
60
60
  <h1>You're in!</h1>
61
61
  ${email ? `<p class="email">${email}</p>` : ''}
62
+ ${source === 'login' ? `
62
63
  <div class="steps">
63
64
  <h3>Next in your terminal</h3>
64
65
  <div class="step"><span class="num">1</span><span>Run <code>cutline-mcp init</code> to generate IDE rules</span></div>
65
66
  <div class="step"><span class="num">2</span><span>Run <code>cutline-mcp setup</code> to connect MCP servers</span></div>
66
67
  <div class="step"><span class="num">3</span><span>Ask your agent: <em>"Run an engineering audit"</em></span></div>
67
- </div>
68
+ </div>` : `
69
+ <div class="steps">
70
+ <h3>Go back to your terminal</h3>
71
+ <div class="step"><span class="num">&#10003;</span><span>Setup is finishing automatically — check your terminal for next steps.</span></div>
72
+ </div>`}
68
73
  <p class="close">You can close this tab.</p>
69
74
  </div>
70
75
  </body>
@@ -1,5 +1,7 @@
1
+ import { type CallbackSource } from '../auth/callback.js';
1
2
  export declare function loginCommand(options: {
2
3
  staging?: boolean;
3
4
  signup?: boolean;
4
5
  email?: string;
6
+ source?: CallbackSource;
5
7
  }): Promise<void>;
@@ -91,7 +91,7 @@ export async function loginCommand(options) {
91
91
  }
92
92
  // Start callback server
93
93
  spinner.text = 'Waiting for authentication...';
94
- const serverPromise = startCallbackServer();
94
+ const serverPromise = startCallbackServer(options.source ?? 'login');
95
95
  // Open browser — default is the quick email-only flow
96
96
  let authUrl = `${config.AUTH_URL}?callback=${encodeURIComponent(config.CALLBACK_URL)}`;
97
97
  if (options.signup) {
@@ -126,8 +126,14 @@ export async function setupCommand(options) {
126
126
  const hasToken = await getRefreshToken();
127
127
  if (!hasToken && !options.skipLogin) {
128
128
  console.log(chalk.dim(' No credentials found — starting login flow.\n'));
129
- await loginCommand({ staging: options.staging });
129
+ await loginCommand({ staging: options.staging, source: 'setup' });
130
130
  console.log();
131
+ const tokenAfterLogin = await getRefreshToken();
132
+ if (!tokenAfterLogin) {
133
+ console.log(chalk.yellow(' Login not completed — trying account creation instead.\n'));
134
+ await loginCommand({ staging: options.staging, signup: true, source: 'setup' });
135
+ console.log();
136
+ }
131
137
  }
132
138
  const spinner = ora('Detecting account tier...').start();
133
139
  const { tier, email, idToken } = await detectTier({ staging: options.staging });
@@ -231,7 +237,7 @@ export async function setupCommand(options) {
231
237
  }
232
238
  console.log();
233
239
  // ── 6. What you can do ───────────────────────────────────────────────────
234
- console.log(chalk.bold(' Restart your IDE, then ask your AI agent:\n'));
240
+ console.log(chalk.bold(' Start a new terminal or restart your MCP servers, then ask your AI agent:\n'));
235
241
  if (tier === 'premium') {
236
242
  if (!graphConnected) {
237
243
  console.log(` ${chalk.cyan('→')} ${chalk.white('cutline-mcp setup')} ${chalk.dim('(re-run to connect a product graph)')}`);
@@ -243,6 +249,7 @@ export async function setupCommand(options) {
243
249
  { cmd: 'Check constraints for src/api/upload.ts', desc: 'Get NFR boundaries for a specific file' },
244
250
  { cmd: 'Generate .cutline.md for my product', desc: 'Write the constraint routing engine' },
245
251
  { cmd: 'What does my persona think about X?', desc: 'AI persona feedback on features' },
252
+ ...(!graphConnected ? [{ cmd: 'Connect my Cutline product graph', desc: 'Link a completed pre-mortem for constraint-aware code guidance' }] : []),
246
253
  ];
247
254
  for (const item of items) {
248
255
  console.log(` ${chalk.cyan('→')} ${chalk.white(`"${item.cmd}"`)}`);
@@ -48,7 +48,7 @@ export async function upgradeCommand(options) {
48
48
  const spinner = ora('Waiting for upgrade and re-authentication...').start();
49
49
  try {
50
50
  // Start callback server for re-auth after upgrade
51
- const serverPromise = startCallbackServer();
51
+ const serverPromise = startCallbackServer('upgrade');
52
52
  // Open upgrade page with callback for re-auth
53
53
  // The upgrade page will redirect to mcp-auth after successful upgrade
54
54
  const upgradeUrl = `${baseUrl}/upgrade?mcp_callback=${encodeURIComponent(config.CALLBACK_URL)}`;
package/dist/index.js CHANGED
@@ -25,6 +25,11 @@ program
25
25
  .option('--signup', 'Open sign-up page instead of sign-in')
26
26
  .option('--email <address>', 'Request sign-in with specific email address')
27
27
  .action(loginCommand);
28
+ program
29
+ .command('signup')
30
+ .description('Create a new Cutline account')
31
+ .option('--staging', 'Use staging environment')
32
+ .action((opts) => loginCommand({ signup: true, staging: opts.staging }));
28
33
  program
29
34
  .command('logout')
30
35
  .description('Remove stored credentials')