MCP Terminal Server

/** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { execSync } from 'child_process'; import * as clc from 'colorette'; import { z } from 'zod'; const SupportedFlagValuesSchema = z.union([ z.undefined(), z.string(), z.boolean(), z.array(z.string()), ]); export const BaseToolPluginActionSchema = z.object({ args: z.optional( z.array( z.object({ description: z.string(), flag: z.string(), // Flag uses Commander syntax; i.e. '-q, --quiet' defaultValue: SupportedFlagValuesSchema, }) ) ), hook: z .function() .args(z.optional(z.record(z.string(), SupportedFlagValuesSchema))) .returns(z.union([z.void(), z.promise(z.void())])), }); export const ToolPluginActionSchema = BaseToolPluginActionSchema.extend({ action: z.string(), helpText: z.string(), }); export const ToolPluginSubCommandsSchema = z.object({ login: z.optional(BaseToolPluginActionSchema), deploy: z.optional(BaseToolPluginActionSchema), }); export const ToolPluginSchema = z.object({ name: z.string(), keyword: z.string(), actions: z.array(ToolPluginActionSchema), subCommands: z.optional(ToolPluginSubCommandsSchema), }); export type SupportedFlagValues = z.infer<typeof SupportedFlagValuesSchema>; export type BaseToolPluginAction = z.infer<typeof BaseToolPluginActionSchema>; export type ToolPluginAction = z.infer<typeof ToolPluginActionSchema>; export type ToolPlugin = z.infer<typeof ToolPluginSchema>; export type SpecialAction = keyof z.infer<typeof ToolPluginSubCommandsSchema>; const SEPARATOR = '==========================='; /** * Executes the command given, returning the contents of STDOUT. * * The contents of STDOUT are hidden during execution. This function will * also print out the commands that will be run for transparency to the user. */ export function cliCommand(command: string, options?: string): void { const commandString = command + (options ? ` ${options}` : ''); console.log(`Running ${clc.bold(commandString)}...\n${SEPARATOR}`); try { execSync(commandString, { stdio: 'inherit', encoding: 'utf8' }); } catch (e) { console.log(`${SEPARATOR}\n`); throw e; } console.log(`${SEPARATOR}\n`); }