11#!/usr/bin/env node
22import { parseArgs } from "node:util" ;
3+ import * as readline from "node:readline/promises" ;
4+ import { stdin , stdout } from "node:process" ;
35import { z } from "zod" ;
46import { PROVIDERS_OR_POLICIES } from "@huggingface/inference" ;
57import { Agent } from "@huggingface/mcp-client" ;
68import { version as packageVersion } from "../package.json" ;
7- import { ServerConfigSchema } from "./lib/types" ;
8- import { debug , error } from "./lib/utils" ;
9+ import { InputConfigSchema , ServerConfigSchema } from "./lib/types" ;
10+ import { debug , error , ANSI } from "./lib/utils" ;
911import { mainCliLoop } from "./lib/mainCliLoop" ;
1012import { loadConfigFrom } from "./lib/loadConfigFrom" ;
1113
@@ -70,6 +72,7 @@ async function main() {
7072 provider : z . enum ( PROVIDERS_OR_POLICIES ) . optional ( ) ,
7173 endpointUrl : z . string ( ) . optional ( ) ,
7274 apiKey : z . string ( ) . optional ( ) ,
75+ inputs : z . array ( InputConfigSchema ) . optional ( ) ,
7376 servers : z . array ( ServerConfigSchema ) ,
7477 } )
7578 . refine ( ( data ) => data . provider !== undefined || data . endpointUrl !== undefined , {
@@ -85,6 +88,81 @@ async function main() {
8588 process . exit ( 1 ) ;
8689 }
8790
91+ // Handle inputs (i.e. env variables injection)
92+ if ( config . inputs && config . inputs . length > 0 ) {
93+ const rl = readline . createInterface ( { input : stdin , output : stdout } ) ;
94+
95+ stdout . write ( ANSI . BLUE ) ;
96+ stdout . write ( "Some initial inputs are required by the agent. " ) ;
97+ stdout . write ( "Please provide a value or leave empty to load from env." ) ;
98+ stdout . write ( ANSI . RESET ) ;
99+ stdout . write ( "\n" ) ;
100+
101+ for ( const inputItem of config . inputs ) {
102+ const inputId = inputItem . id ;
103+ const description = inputItem . description ;
104+ const envSpecialValue = `\${input:${ inputId } }` ; // Special value to indicate env variable injection
105+
106+ // Check env variables that will use this input
107+ const inputVars = new Set < string > ( ) ;
108+ for ( const server of config . servers ) {
109+ if ( server . type === "stdio" && server . config . env ) {
110+ for ( const [ key , value ] of Object . entries ( server . config . env ) ) {
111+ if ( value === envSpecialValue ) {
112+ inputVars . add ( key ) ;
113+ }
114+ }
115+ }
116+ }
117+
118+ if ( inputVars . size === 0 ) {
119+ stdout . write ( ANSI . YELLOW ) ;
120+ stdout . write ( `Input ${ inputId } defined in config but not used by any server.` ) ;
121+ stdout . write ( ANSI . RESET ) ;
122+ stdout . write ( "\n" ) ;
123+ continue ;
124+ }
125+
126+ // Prompt user for input
127+ stdout . write ( ANSI . BLUE ) ;
128+ stdout . write ( ` • ${ inputId } ` ) ;
129+ stdout . write ( ANSI . RESET ) ;
130+ stdout . write ( `: ${ description } . (default: load from ${ Array . from ( inputVars ) . join ( ", " ) } ) ` ) ;
131+
132+ const userInput = ( await rl . question ( "" ) ) . trim ( ) ;
133+
134+ // Inject user input (or env variable) into servers' env
135+ for ( const server of config . servers ) {
136+ if ( server . type === "stdio" && server . config . env ) {
137+ for ( const [ key , value ] of Object . entries ( server . config . env ) ) {
138+ if ( value === envSpecialValue ) {
139+ if ( userInput ) {
140+ server . config . env [ key ] = userInput ;
141+ } else {
142+ const valueFromEnv = process . env [ key ] || "" ;
143+ server . config . env [ key ] = valueFromEnv ;
144+ if ( valueFromEnv ) {
145+ stdout . write ( ANSI . GREEN ) ;
146+ stdout . write ( `Value successfully loaded from '${ key } '` ) ;
147+ stdout . write ( ANSI . RESET ) ;
148+ stdout . write ( "\n" ) ;
149+ } else {
150+ stdout . write ( ANSI . YELLOW ) ;
151+ stdout . write ( `No value found for '${ key } ' in environment variables. Continuing.` ) ;
152+ stdout . write ( ANSI . RESET ) ;
153+ stdout . write ( "\n" ) ;
154+ }
155+ }
156+ }
157+ }
158+ }
159+ }
160+ }
161+
162+ stdout . write ( "\n" ) ;
163+ rl . close ( ) ;
164+ }
165+
88166 const agent = new Agent (
89167 config . endpointUrl
90168 ? {
0 commit comments