@@ -46,6 +46,8 @@ export interface OfficialEnvironmentVariable {
4646 */
4747export interface OfficialTransport {
4848 type : 'stdio' | 'streamable-http' | 'sse' ;
49+ command ?: string ; // Optional in official registry
50+ args ?: string [ ] ; // Optional in official registry
4951}
5052
5153/**
@@ -176,6 +178,62 @@ export function createSlug(officialName: string): string {
176178// TRANSPORT TYPE DERIVATION
177179// =============================================================================
178180
181+ /**
182+ * Infer command and args for STDIO packages based on registry type
183+ *
184+ * The official MCP registry doesn't always provide command/args in the transport object.
185+ * We need to infer them based on the package's registryType and identifier.
186+ *
187+ * @param pkg - Official package data
188+ * @returns Inferred transport with command and args
189+ */
190+ export function inferStdioTransport ( pkg : OfficialPackage ) : {
191+ command : string ;
192+ args : string [ ] ;
193+ } {
194+ // If transport already has command and args, use them
195+ if ( pkg . transport . command && pkg . transport . args ) {
196+ return {
197+ command : pkg . transport . command ,
198+ args : pkg . transport . args
199+ } ;
200+ }
201+
202+ // Otherwise, infer based on registryType
203+ const identifier = pkg . identifier ;
204+
205+ switch ( pkg . registryType . toLowerCase ( ) ) {
206+ case 'npm' :
207+ // NPM packages: npx -y <package-name>
208+ return {
209+ command : 'npx' ,
210+ args : [ '-y' , identifier ]
211+ } ;
212+
213+ case 'pypi' :
214+ // PyPI packages: uvx <package-name>
215+ // Alternative: python -m <package-name>
216+ return {
217+ command : 'uvx' ,
218+ args : [ identifier ]
219+ } ;
220+
221+ case 'docker' :
222+ // Docker images: docker run <image-name>
223+ return {
224+ command : 'docker' ,
225+ args : [ 'run' , identifier ]
226+ } ;
227+
228+ default :
229+ // Fallback to npx for unknown types
230+ return {
231+ command : 'npx' ,
232+ args : [ identifier ]
233+ } ;
234+ }
235+ }
236+
179237/**
180238 * Derive DeployStack transport_type from official packages/remotes
181239 *
@@ -365,6 +423,8 @@ export function mapHeadersToThreeTier(
365423/**
366424 * Map official runtime/package arguments to DeployStack's 3-tier args system
367425 *
426+ * IMPORTANT: For STDIO packages, we need to infer command/args if not provided
427+ *
368428 * @param packages - Official packages array
369429 * @returns DeployStack ConfigurationSchema args configuration
370430 */
@@ -382,6 +442,29 @@ export function mapArgumentsToThreeTier(
382442 // Extract runtime and package arguments
383443 const pkg = packages [ 0 ] ;
384444
445+ // For STDIO packages, infer transport command/args if not provided
446+ if ( pkg . transport . type === 'stdio' ) {
447+ const inferredTransport = inferStdioTransport ( pkg ) ;
448+
449+ // Add inferred args as template args (locked)
450+ for ( const arg of inferredTransport . args ) {
451+ templateArgs . push ( {
452+ value : arg ,
453+ locked : true ,
454+ description : `Static argument: ${ arg } `
455+ } ) ;
456+ }
457+
458+ // Store command in the package for later use
459+ // This will be used when constructing the packages array
460+ if ( ! pkg . transport . command ) {
461+ pkg . transport . command = inferredTransport . command ;
462+ }
463+ if ( ! pkg . transport . args ) {
464+ pkg . transport . args = inferredTransport . args ;
465+ }
466+ }
467+
385468 // Package arguments go to template (locked)
386469 if ( pkg . packageArguments && pkg . packageArguments . length > 0 ) {
387470 for ( const arg of pkg . packageArguments ) {
@@ -435,12 +518,17 @@ export async function transformOfficialToDeployStack(
435518 fetchGitHubMetadata ?: boolean ;
436519 }
437520) : Promise < Partial < CreateGlobalServerRequest > > {
521+ // IMPORTANT: Create a deep copy of packages to avoid mutating the original
522+ // We'll be adding inferred command/args to the packages during transformation
523+ const packagesCopy = officialServer . packages ? JSON . parse ( JSON . stringify ( officialServer . packages ) ) : undefined ;
524+
438525 // Extract 3-tier configurations from packages (env vars + args)
439526 const envConfig = mapEnvironmentVariablesToThreeTier (
440- officialServer . packages ?. [ 0 ] ?. environmentVariables || [ ]
527+ packagesCopy ?. [ 0 ] ?. environmentVariables || [ ]
441528 ) ;
442529
443- const argsConfig = mapArgumentsToThreeTier ( officialServer . packages ) ;
530+ // This will infer and add command/args to packagesCopy if missing
531+ const argsConfig = mapArgumentsToThreeTier ( packagesCopy ) ;
444532
445533 // Extract 3-tier configurations from remotes (headers)
446534 // Merge headers from all remotes (in case there are multiple endpoints)
@@ -500,7 +588,8 @@ export async function transformOfficialToDeployStack(
500588 website_url : officialServer . websiteUrl ,
501589
502590 // Official format storage (will be JSON stringified by create-global.ts)
503- packages : officialServer . packages ,
591+ // Use packagesCopy which now has inferred command/args
592+ packages : packagesCopy ,
504593 remotes : officialServer . remotes ,
505594
506595 // Derived DeployStack fields
0 commit comments