@@ -14,6 +14,7 @@ import {
1414 invokeForProtocol ,
1515 listMcpTools ,
1616 loadProjectConfig ,
17+ waitForServerReady ,
1718} from '../../operations/dev' ;
1819import { getGatewayEnvVars } from '../../operations/dev/gateway-env.js' ;
1920import { FatalError } from '../../tui/components' ;
@@ -137,7 +138,7 @@ export const registerDev = (program: Command) => {
137138 . command ( 'dev' )
138139 . alias ( 'd' )
139140 . description ( COMMAND_DESCRIPTIONS . dev )
140- . argument ( '[prompt]' , 'Invoke running dev server with this prompt [non-interactive]' )
141+ . argument ( '[prompt]' , 'Invoke local agent with this prompt (auto-starts server if needed) [non-interactive]' )
141142 . option ( '-p, --port <port>' , 'Port for development server' , '8080' )
142143 . option ( '-a, --agent <name>' , 'Agent to run or invoke (required if multiple agents)' )
143144 . option ( '-s, --stream' , 'Stream response when invoking [non-interactive]' )
@@ -160,10 +161,11 @@ export const registerDev = (program: Command) => {
160161 headers = parseHeaderFlags ( opts . header ) ;
161162 }
162163
163- // If a prompt is provided, call the dev server and exit
164+ // If a prompt is provided, invoke the dev server (auto-starting if needed)
164165 const invokePrompt = positionalPrompt ;
165166 if ( invokePrompt ) {
166- const invokeProject = await loadProjectConfig ( getWorkingDirectory ( ) ) ;
167+ const workingDir = getWorkingDirectory ( ) ;
168+ const invokeProject = await loadProjectConfig ( workingDir ) ;
167169
168170 // Determine which agent/port to invoke
169171 let invokePort = port ;
@@ -184,18 +186,84 @@ export const registerDev = (program: Command) => {
184186 if ( protocol === 'A2A' ) invokePort = 9000 ;
185187 else if ( protocol === 'MCP' ) invokePort = 8000 ;
186188
187- // Show model info if available (not applicable to MCP)
188- if ( protocol !== 'MCP' && targetAgent ?. modelProvider ) {
189- console . log ( `Provider: ${ targetAgent . modelProvider } ` ) ;
189+ // Check if a dev server is already running on the target port
190+ const serverRunning = await waitForServerReady ( invokePort , 500 ) ;
191+
192+ // Auto-start a dev server if none is running
193+ let autoStartedServer : ReturnType < typeof createDevServer > | undefined ;
194+ if ( ! serverRunning ) {
195+ if ( ! invokeProject ) {
196+ console . error ( 'Error: No dev server running and no agentcore project found.' ) ;
197+ console . error ( 'Start a dev server first: agentcore dev' ) ;
198+ process . exit ( 1 ) ;
199+ }
200+
201+ const configRoot = findConfigRoot ( workingDir ) ;
202+ const envVars = configRoot ? await readEnvFile ( configRoot ) : { } ;
203+ const gatewayEnvVars = await getGatewayEnvVars ( ) ;
204+ const mergedEnvVars = { ...gatewayEnvVars , ...envVars } ;
205+ const agentName = opts . agent ?? invokeProject . agents [ 0 ] ?. name ;
206+ const config = getDevConfig ( workingDir , invokeProject , configRoot ?? undefined , agentName ) ;
207+
208+ if ( ! config ) {
209+ console . error ( 'Error: No dev-supported agents found.' ) ;
210+ process . exit ( 1 ) ;
211+ }
212+
213+ const serverErrors : string [ ] = [ ] ;
214+ let resolveServerExit : ( ) => void ;
215+ const serverExitPromise = new Promise < void > ( resolve => {
216+ resolveServerExit = resolve ;
217+ } ) ;
218+
219+ const devCallbacks = {
220+ onLog : ( level : string , msg : string ) => {
221+ if ( level === 'error' ) serverErrors . push ( msg ) ;
222+ } ,
223+ onExit : ( ) => {
224+ resolveServerExit ( ) ;
225+ } ,
226+ } ;
227+
228+ const server = createDevServer ( config , {
229+ port : invokePort ,
230+ envVars : mergedEnvVars ,
231+ callbacks : devCallbacks ,
232+ } ) ;
233+ await server . start ( ) ;
234+
235+ // Wait for server to accept connections, bail early if process crashes
236+ const ready = await Promise . race ( [ waitForServerReady ( invokePort ) , serverExitPromise . then ( ( ) => false ) ] ) ;
237+
238+ if ( ! ready ) {
239+ if ( serverErrors . length > 0 ) {
240+ console . error ( serverErrors . slice ( - 5 ) . join ( '\n' ) ) ;
241+ }
242+ console . error ( 'Error: Dev server failed to start. Run "agentcore dev --logs" for details.' ) ;
243+ server . kill ( ) ;
244+ process . exit ( 1 ) ;
245+ }
246+ autoStartedServer = server ;
190247 }
191248
192- // Protocol-aware dispatch
193- if ( protocol === 'MCP' ) {
194- await handleMcpInvoke ( invokePort , invokePrompt , opts . tool , opts . input , headers ) ;
195- } else if ( protocol === 'A2A' ) {
196- await invokeA2ADevServer ( invokePort , invokePrompt , headers ) ;
197- } else {
198- await invokeDevServer ( invokePort , invokePrompt , opts . stream ?? false , headers ) ;
249+ try {
250+ // Show model info if available (not applicable to MCP)
251+ if ( protocol !== 'MCP' && targetAgent ?. modelProvider ) {
252+ console . log ( `Provider: ${ targetAgent . modelProvider } ` ) ;
253+ }
254+
255+ // Protocol-aware dispatch
256+ if ( protocol === 'MCP' ) {
257+ await handleMcpInvoke ( invokePort , invokePrompt , opts . tool , opts . input , headers ) ;
258+ } else if ( protocol === 'A2A' ) {
259+ await invokeA2ADevServer ( invokePort , invokePrompt , headers ) ;
260+ } else {
261+ await invokeDevServer ( invokePort , invokePrompt , opts . stream ?? false , headers ) ;
262+ }
263+ } finally {
264+ if ( autoStartedServer ) {
265+ autoStartedServer . kill ( ) ;
266+ }
199267 }
200268 return ;
201269 }
0 commit comments