@@ -105,6 +105,9 @@ Docs: https://github.com/Shrike-Security/shrike-mcp`);
105105// Track connected customer for rate limiting (stdio mode)
106106let currentCustomerId : string | null = null ;
107107
108+ // True when running without an API key — scan responses include a signup hint
109+ let unauthenticated = false ;
110+
108111// Key rotation manager — initialized in authenticate()
109112let keyRotationManager : KeyRotationManager | null = null ;
110113
@@ -293,6 +296,25 @@ function validateToolArgs(name: string, args: Record<string, unknown> | undefine
293296 }
294297}
295298
299+ // =============================================================================
300+ // SIGNUP HINT
301+ // =============================================================================
302+
303+ /**
304+ * When running without an API key, appends a hint to scan results so the
305+ * agent (or user) knows they're only getting L1-L5 regex scanning and can
306+ * upgrade by running `npx shrike-mcp --signup`.
307+ */
308+ function maybeAddSignupHint ( result : any ) : any {
309+ if ( ! unauthenticated || typeof result !== 'object' || result === null ) {
310+ return result ;
311+ }
312+ return {
313+ ...result ,
314+ _note : 'Running in free tier (regex-only). For LLM-powered analysis and session correlation, run: npx shrike-mcp --signup' ,
315+ } ;
316+ }
317+
296318// =============================================================================
297319// SERVER CREATION
298320// =============================================================================
@@ -373,8 +395,9 @@ function createServer(options: CreateServerOptions = {}): Server {
373395 validateToolArgs ( actualToolName , input ) ;
374396 const entry = TOOL_REGISTRY [ actualToolName ] ;
375397 const result = await entry . handler ( input , effectiveCustomerId ) ;
398+ const output = maybeAddSignupHint ( result ) ;
376399 return {
377- content : [ { type : 'text' , text : JSON . stringify ( result , null , entry . compact ? undefined : 2 ) } ] ,
400+ content : [ { type : 'text' , text : JSON . stringify ( output , null , entry . compact ? undefined : 2 ) } ] ,
378401 } ;
379402 }
380403
@@ -394,8 +417,9 @@ function createServer(options: CreateServerOptions = {}): Server {
394417
395418 validateToolArgs ( name , args as Record < string , unknown > | undefined ) ;
396419 const result = await entry . handler ( args , effectiveCustomerId ) ;
420+ const output = maybeAddSignupHint ( result ) ;
397421 return {
398- content : [ { type : 'text' , text : JSON . stringify ( result , null , entry . compact ? undefined : 2 ) } ] ,
422+ content : [ { type : 'text' , text : JSON . stringify ( output , null , entry . compact ? undefined : 2 ) } ] ,
399423 } ;
400424 } catch ( error ) {
401425 if ( error instanceof McpError ) {
@@ -577,11 +601,22 @@ async function authenticate(): Promise<void> {
577601 } else {
578602 console . error ( `No API key found (checked: SHRIKE_API_KEY env, ~/.shrike/credentials)` ) ;
579603 console . error ( ' Running without authentication (free tier — L1-L5 regex only)' ) ;
580- console . error ( ' To get a free API key: npx shrike-mcp --signup' ) ;
581- if ( config . transport === 'http' ) {
604+
605+ // If running interactively (TTY), offer inline signup
606+ if ( config . transport === 'stdio' && process . stdin . isTTY ) {
607+ console . error ( '' ) ;
608+ console . error ( ' No API key configured. Create a free account? Run:' ) ;
609+ console . error ( ' npx shrike-mcp --signup' ) ;
610+ console . error ( '' ) ;
611+ } else if ( config . transport === 'http' ) {
582612 console . error ( ' HTTP mode: clients can authenticate via Authorization header per-request' ) ;
613+ } else {
614+ // Agent-driven stdio: log the hint so it appears in MCP server stderr
615+ console . error ( ' To unlock full scanning (LLM analysis, session correlation):' ) ;
616+ console . error ( ' npx shrike-mcp --signup' ) ;
583617 }
584618 currentCustomerId = 'anonymous ';
619+ unauthenticated = true ;
585620 }
586621}
587622
0 commit comments