Skip to main content
Glama
MCPServerCommand.php4.82 kB
<?php namespace App\Console\Commands; use App\Services\MCPService; use Illuminate\Console\Command; use Illuminate\Support\Facades\Log; class MCPServerCommand extends Command { protected $signature = 'mcp:server {--debug : Enable debug output}'; protected $description = 'Start MCP Server using stdio transport'; private MCPService $mcpService; public function __construct(MCPService $mcpService) { parent::__construct(); $this->mcpService = $mcpService; } public function handle() { $debug = $this->option('debug'); if ($debug) { $this->info('Starting MCP Server with stdio transport...'); $this->info('Waiting for JSON-RPC requests...'); $this->info('Send JSON-RPC messages to stdin. Example:'); $this->info('{"jsonrpc":"2.0","method":"tools/list","params":{},"id":1}'); $this->info('Press Ctrl+C to stop.'); } while (true) { // 讀取一行輸入 $input = fgets(STDIN); if ($input === false) { // EOF reached break; } $input = trim($input); // Remove BOM if present $input = preg_replace('/^\xEF\xBB\xBF/', '', $input); if (empty($input)) { continue; } if ($debug) { $this->info("Received input: " . $input); } try { $request = json_decode($input, true); if (!$request || json_last_error() !== JSON_ERROR_NONE) { $error = 'Parse error: ' . json_last_error_msg(); if ($debug) $this->error($error); $this->sendError(-32700, $error, null); continue; } $method = $request['method'] ?? ''; $params = $request['params'] ?? []; $id = $request['id'] ?? null; if ($debug) { $this->info("Processing method: {$method}"); } $result = $this->handleMethod($method, $params); $this->sendResult($result, $id); if ($debug) { $this->info("Sent response for method: {$method}"); } // For piped input, exit after processing one request if (!$debug) { // On Windows, we'll just process one request for piped input if (PHP_OS_FAMILY === 'Windows' || !function_exists('posix_isatty') || !posix_isatty(STDIN)) { break; } } } catch (\Exception $e) { $errorMsg = 'Internal error: ' . $e->getMessage(); if ($debug) { $this->error($errorMsg); $this->error($e->getTraceAsString()); } Log::error('MCP Server 錯誤', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); $this->sendError(-32603, $errorMsg, $request['id'] ?? null); } } } private function handleMethod(string $method, array $params) { switch ($method) { case 'initialize': return $this->mcpService->initialize($params); case 'tools/list': return $this->mcpService->getToolsList(); case 'tools/call': $name = $params['name'] ?? ''; $arguments = $params['arguments'] ?? []; return $this->mcpService->callTool($name, $arguments); case 'ping': return ['status' => 'pong']; case 'notifications/initialized': return ['status' => 'ok']; default: throw new \Exception("Unknown method: {$method}"); } } private function sendResult($result, $id) { $response = [ 'jsonrpc' => '2.0', 'result' => $result, 'id' => $id ]; echo json_encode($response) . "\n"; if (ob_get_level()) { ob_flush(); } flush(); } private function sendError(int $code, string $message, $id) { $response = [ 'jsonrpc' => '2.0', 'error' => [ 'code' => $code, 'message' => $message ], 'id' => $id ]; echo json_encode($response) . "\n"; if (ob_get_level()) { ob_flush(); } flush(); } }

Latest Blog Posts

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/uberr2000/mcp_demo'

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