Skip to main content
Glama

Claude TypeScript MCP Servers

by ukkz
tools.ts5.72 kB
/** * MCP ツールハンドラー */ import { z } from "zod"; import type { ShellExecutor } from "./executor"; import { formatCommandError, formatUnexpectedError } from "./errors"; import { DEFAULT_STREAMING_TIMEOUT, DEFAULT_STREAMING_BUFFER_SIZE_KB } from "./constants"; /** * ツール入力スキーマの定義 */ export const ShellExecuteSchema = z.object({ command: z .string() .describe( "Shell command to execute. Can include full command string with args (e.g. 'git add .'). Note: 'cd' command NOT supported - use 'cwd' parameter for directory navigation", ), args: z .array(z.string()) .optional() .default([]) .describe("Command arguments array. Optional if command contains full command string"), cwd: z .string() .optional() .describe("Working directory. IMPORTANT: Use this for directory navigation, NOT 'cd' command"), env: z.record(z.string()).optional().describe("Environment variables"), timeout: z.number().optional().describe("Timeout in milliseconds"), maxOutputSizeMB: z .number() .optional() .default(1) .describe("Max output size in MB (default: 1MB)"), streaming: z .boolean() .optional() .default(true) .describe( "Streaming mode (default: true). Returns partial output for long-running commands while allowing normal commands to complete as usual", ), streamingTimeout: z .number() .optional() .describe("Timeout for streaming mode in milliseconds (default: 10000)"), streamingBufferSizeKB: z .number() .optional() .describe("Buffer size limit for streaming mode in KB (default: 100)"), killOnStreamingTimeout: z .boolean() .optional() .describe("Kill process when streaming timeout is reached (default: true)"), }); export const GetAllowedCommandsSchema = z.object({}); /** * shell_execute ツールのハンドラー * @param executor - ShellExecutorインスタンス * @param baseDirectory - 基準ディレクトリ * @returns ハンドラー関数 */ export function createExecuteHandler(executor: ShellExecutor, baseDirectory: string) { return async (args: z.infer<typeof ShellExecuteSchema>) => { try { const startTime = Date.now(); const result = await executor.executeCommand(args.command, args.args || [], { cwd: args.cwd, env: args.env, timeout: args.timeout, maxOutputSizeMB: args.maxOutputSizeMB, streaming: args.streaming, streamingTimeout: args.streamingTimeout, streamingBufferSizeKB: args.streamingBufferSizeKB, killOnStreamingTimeout: args.killOnStreamingTimeout, }); if (!result.success && !result.streamingResult) { const errorMessage = formatCommandError( result, args.command, args.args || [], args.cwd, baseDirectory, startTime, args.maxOutputSizeMB, ); return { content: [ { type: "text" as const, text: errorMessage, }, ], isError: true, }; } // ストリーミング結果の場合は、追加情報を含める let responseText = result.stdout; if (result.streamingResult) { const processStatus = result.processRunning ? "Process is still running in the background" : "Process has been terminated"; responseText = [ `[STREAMING MODE - ${processStatus}]`, `Partial output returned after ${args.streamingTimeout || DEFAULT_STREAMING_TIMEOUT}ms or ${args.streamingBufferSizeKB || DEFAULT_STREAMING_BUFFER_SIZE_KB}KB buffer`, "", "=== STDOUT ===", result.stdout || "(no output yet)", "", "=== STDERR ===", result.stderr || "(no error output yet)", "", `Note: ${processStatus}.`, result.processRunning ? "To keep process running, use killOnStreamingTimeout: false" : "", ] .filter((line) => line !== "") .join("\n"); } return { content: [ { type: "text" as const, text: responseText, }, ], isError: false, }; } catch (error) { const errorDetails = formatUnexpectedError( error, args.command, args.args || [], args.cwd, baseDirectory, args.timeout, args.maxOutputSizeMB, ); return { content: [ { type: "text" as const, text: `Unexpected error:\n${JSON.stringify(errorDetails, null, 2)}`, }, ], isError: true, }; } }; } /** * shell_get_allowed_commands ツールのハンドラー * @param executor - ShellExecutorインスタンス * @returns ハンドラー関数 */ export function createGetAllowedCommandsHandler(executor: ShellExecutor) { return async () => { try { const commands = executor.getAllowedCommands(); return { content: [ { type: "text" as const, text: `Available commands: ${commands.join(", ")}\n\n` + `Note: 'cd' command not supported - use 'cwd' parameter for directory navigation\n` + `Each command runs independently without state persistence`, }, ], isError: false, }; } catch (error) { return { content: [ { type: "text" as const, text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } }; }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ukkz/claude-ts-mcps'

If you have feedback or need assistance with the MCP directory API, please join our Discord server