Skip to main content
Glama
server.ts•8.71 kB
/** * MCP Screenshot Server * Main server implementation */ import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js"; import { z } from "zod"; import { MCPTools } from "./tools"; import { SecurityPolicy } from "./types"; /** * MCP Screenshot Server class */ export class MCPScreenshotServer { private server: Server; private mcpTools: MCPTools; private isRunning = false; constructor( securityPolicy?: Partial<SecurityPolicy>, excludedWindowPatterns?: string[] ) { // Initialize MCP server with name and version this.server = new Server( { name: "mcp-screenshot", version: "1.0.2", }, { capabilities: { tools: {}, }, } ); // Initialize tools this.mcpTools = new MCPTools(securityPolicy, excludedWindowPatterns); // Set up request handlers this.setupHandlers(); } /** * Set up MCP request handlers */ private setupHandlers(): void { // Handle tools/list request this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: this.getToolSchemas(), })); // Handle tools/call request this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { const result = await this.handleToolCall(name, args || {}); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: JSON.stringify( { status: "error", error: { code: "TOOL_EXECUTION_ERROR", message: error instanceof Error ? error.message : "Unknown error", }, }, null, 2 ), }, ], isError: true, }; } }); } /** * Get tool schemas for tools/list */ private getToolSchemas() { return [ { name: "screenshot_capture_full", description: "Capture full screen screenshot with optional PII masking and format selection", inputSchema: { type: "object", properties: { display: { type: "string", description: "Display ID (optional, defaults to primary display)", }, format: { type: "string", enum: ["png", "jpeg", "webp", "bmp"], description: "Image format (default: png)", }, quality: { type: "number", minimum: 1, maximum: 100, description: "Compression quality for lossy formats (1-100, default: 90)", }, savePath: { type: "string", description: "File path to save screenshot (optional, returns base64 if not provided)", }, enablePIIMasking: { type: "boolean", description: "Enable PII detection and masking (default: false)", }, }, }, }, { name: "screenshot_capture_window", description: "Capture specific application window by ID or title pattern", inputSchema: { type: "object", properties: { windowId: { type: "string", description: "Window identifier (use windowId or windowTitle)", }, windowTitle: { type: "string", description: "Window title pattern to match (use windowId or windowTitle)", }, includeFrame: { type: "boolean", description: "Include window frame and title bar (default: false)", }, format: { type: "string", enum: ["png", "jpeg", "webp", "bmp"], description: "Image format (default: png)", }, quality: { type: "number", minimum: 1, maximum: 100, description: "Compression quality for lossy formats (1-100, default: 90)", }, savePath: { type: "string", description: "File path to save screenshot (optional, returns base64 if not provided)", }, }, }, }, { name: "screenshot_capture_region", description: "Capture specific rectangular region of the screen by coordinates", inputSchema: { type: "object", properties: { x: { type: "number", minimum: 0, description: "X coordinate of top-left corner", }, y: { type: "number", minimum: 0, description: "Y coordinate of top-left corner", }, width: { type: "number", minimum: 1, description: "Width of region in pixels", }, height: { type: "number", minimum: 1, description: "Height of region in pixels", }, format: { type: "string", enum: ["png", "jpeg", "webp", "bmp"], description: "Image format (default: png)", }, quality: { type: "number", minimum: 1, maximum: 100, description: "Compression quality for lossy formats (1-100, default: 90)", }, savePath: { type: "string", description: "File path to save screenshot (optional, returns base64 if not provided)", }, }, required: ["x", "y", "width", "height"], }, }, { name: "screenshot_list_displays", description: "List all connected displays with resolution and position information", inputSchema: { type: "object", properties: {}, }, }, { name: "screenshot_list_windows", description: "List all visible windows with title, process, and position information", inputSchema: { type: "object", properties: {}, }, }, ]; } /** * Handle tool call by routing to appropriate method */ private async handleToolCall( name: string, args: Record<string, any> ): Promise<any> { switch (name) { case "screenshot_capture_full": return await this.mcpTools.captureFullScreen(args); case "screenshot_capture_window": return await this.mcpTools.captureWindow(args); case "screenshot_capture_region": return await this.mcpTools.captureRegion({ x: args["x"] as number, y: args["y"] as number, width: args["width"] as number, height: args["height"] as number, format: args["format"] as any, quality: args["quality"] as number | undefined, savePath: args["savePath"] as string | undefined, }); case "screenshot_list_displays": return await this.mcpTools.listDisplays(); case "screenshot_list_windows": return await this.mcpTools.listWindows(); default: throw new Error(`Unknown tool: ${name}`); } } /** * Start the MCP server with stdio transport */ async start(): Promise<void> { if (this.isRunning) { throw new Error("Server is already running"); } const transport = new StdioServerTransport(); await this.server.connect(transport); this.isRunning = true; console.error("MCP Screenshot Server started successfully"); } /** * Stop the server and cleanup resources */ async stop(): Promise<void> { if (!this.isRunning) { return; } await this.mcpTools.cleanup(); await this.server.close(); this.isRunning = false; console.error("MCP Screenshot Server stopped"); } /** * Check if server is running */ isServerRunning(): boolean { return this.isRunning; } }

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/Digital-Defiance/mcp-screenshot'

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