Skip to main content
Glama

Claude TypeScript MCP Servers

by ukkz
page.ts5.71 kB
/** * ページ管理系ハンドラー */ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { KnownDevices } from "puppeteer"; import { createErrorResponse, createSuccessResponse, ensureBrowser } from "../utils.js"; import { savePdf } from "../state.js"; import { SetViewportArgs, GoBackArgs, GoForwardArgs, ReloadArgs, PdfArgs, EmulateDeviceArgs, } from "../types.js"; /** * ビューポートサイズを設定する処理 */ export async function handleSetViewport( args: SetViewportArgs, server: Server, ): Promise<CallToolResult> { try { const page = await ensureBrowser(server); await page.setViewport({ width: args.width, height: args.height, deviceScaleFactor: args.deviceScaleFactor ?? 1, isMobile: args.isMobile ?? false, hasTouch: args.hasTouch ?? false, }); return createSuccessResponse( `Viewport set to ${args.width}x${args.height}\n` + `Device scale factor: ${args.deviceScaleFactor ?? 1}\n` + `Mobile emulation: ${args.isMobile ?? false}\n` + `Touch support: ${args.hasTouch ?? false}`, ); } catch (error) { return createErrorResponse(`Failed to set viewport: ${(error as Error).message}`); } } /** * ブラウザ履歴を戻る処理 */ export async function handleGoBack(args: GoBackArgs, server: Server): Promise<CallToolResult> { try { const page = await ensureBrowser(server); const startTime = Date.now(); const initialUrl = page.url(); const response = await page.goBack({ waitUntil: args.waitUntil || "load", }); if (!response) { return createErrorResponse("No previous page in history"); } const elapsed = Date.now() - startTime; const finalUrl = page.url(); return createSuccessResponse( `Navigated back in ${elapsed}ms\n` + `From: ${initialUrl}\n` + `To: ${finalUrl}`, ); } catch (error) { return createErrorResponse(`Failed to go back: ${(error as Error).message}`); } } /** * ブラウザ履歴を進む処理 */ export async function handleGoForward( args: GoForwardArgs, server: Server, ): Promise<CallToolResult> { try { const page = await ensureBrowser(server); const startTime = Date.now(); const initialUrl = page.url(); const response = await page.goForward({ waitUntil: args.waitUntil || "load", }); if (!response) { return createErrorResponse("No forward page in history"); } const elapsed = Date.now() - startTime; const finalUrl = page.url(); return createSuccessResponse( `Navigated forward in ${elapsed}ms\n` + `From: ${initialUrl}\n` + `To: ${finalUrl}`, ); } catch (error) { return createErrorResponse(`Failed to go forward: ${(error as Error).message}`); } } /** * ページをリロードする処理 */ export async function handleReload(args: ReloadArgs, server: Server): Promise<CallToolResult> { try { const page = await ensureBrowser(server); const startTime = Date.now(); const url = page.url(); await page.reload({ waitUntil: args.waitUntil || "load", }); const elapsed = Date.now() - startTime; return createSuccessResponse( `Page reloaded in ${elapsed}ms\n` + `URL: ${url}\n` + `Wait condition: ${args.waitUntil || "load"}`, ); } catch (error) { return createErrorResponse(`Failed to reload page: ${(error as Error).message}`); } } /** * PDFを生成する処理 */ export async function handlePdf(args: PdfArgs, server: Server): Promise<CallToolResult> { try { const page = await ensureBrowser(server); const pdfName = args.path || `pdf_${Date.now()}.pdf`; const pdfOptions: any = { printBackground: args.printBackground ?? false, }; if (args.format) { pdfOptions.format = args.format; } // PDFを生成 const pdfBuffer = await page.pdf(pdfOptions); const pdfBase64 = pdfBuffer.toString("base64"); // PDFを保存 savePdf(pdfName, pdfBase64); // リソースリストを更新 server.notification({ method: "notifications/resources/list_changed", }); return createSuccessResponse( `PDF generated: ${pdfName}\n` + `Format: ${args.format || "default"}\n` + `Print background: ${args.printBackground ?? false}\n` + `Size: ${(pdfBuffer.length / 1024).toFixed(2)} KB`, ); } catch (error) { return createErrorResponse(`Failed to generate PDF: ${(error as Error).message}`); } } /** * デバイスをエミュレートする処理 */ export async function handleEmulateDevice( args: EmulateDeviceArgs, server: Server, ): Promise<CallToolResult> { try { const page = await ensureBrowser(server); // Puppeteerの事前定義デバイスを取得 const device = KnownDevices[args.device as keyof typeof KnownDevices]; if (!device) { // 利用可能なデバイス名をリストアップ const availableDevices = Object.keys(KnownDevices).join(", "); return createErrorResponse( `Device '${args.device}' not found.\n` + `Available devices: ${availableDevices}`, ); } await page.emulate(device); return createSuccessResponse( `Emulating device: ${args.device}\n` + `Viewport: ${device.viewport.width}x${device.viewport.height}\n` + `User Agent: ${device.userAgent}\n` + `Has touch: ${device.viewport.hasTouch}\n` + `Is mobile: ${device.viewport.isMobile}`, ); } catch (error) { return createErrorResponse(`Failed to emulate device: ${(error as Error).message}`); } }

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