Skip to main content
Glama
server.ts5.27 kB
#!/usr/bin/env node 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 { CopyPasteHandler } from './handlers/copyPasteHandler.js'; import { FileSystemStorage } from './services/fileSystemStorage.js'; import { CopyPasteParams } from './types/index.js'; /** * Clipboard MCP Server * Context-efficient file editing через position-based copy/paste operations */ class ClipboardMCPServer { private server: Server; private copyPasteHandler: CopyPasteHandler; constructor() { this.server = new Server( { name: 'clipboard-mcp-server', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); // Инициализация storage и handler const storageService = new FileSystemStorage(); this.copyPasteHandler = new CopyPasteHandler(storageService); this.setupToolHandlers(); } private setupToolHandlers() { // Регистрация доступных tools this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: 'copy_paste', description: 'Copy/paste content between files using text patterns. Find content by search pattern, insert at marker location.', inputSchema: { type: 'object', properties: { source: { type: 'object', properties: { file: { type: 'string', description: 'Path to source file' }, start_pattern: { type: 'string', description: 'Text pattern to find start of content to copy (e.g., "function processData", "// Section start")' }, end_pattern: { type: 'string', description: 'Optional: text pattern for end of content. If not provided, uses line_count' }, line_count: { type: 'number', description: 'Optional: number of lines to copy from start_pattern. Default: 1' } }, required: ['file', 'start_pattern'] }, target: { type: 'object', properties: { file: { type: 'string', description: 'Path to target file' }, marker: { type: 'string', description: 'Text pattern to find insertion point (e.g., "// Insert here", "class MyClass")' }, position: { type: 'string', enum: ['before', 'after', 'replace'], description: 'Where to insert relative to marker: before, after, or replace the marker' }, replace_pattern: { type: 'string', description: 'Optional: specific text pattern to replace (when position=replace)' } }, required: ['file', 'marker', 'position'] }, cut: { type: 'boolean', description: 'Optional: true to cut (move) instead of copy. Default: false' } }, required: ['source', 'target'] } } ] })); // Обработчик вызова tools this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; if (name === 'copy_paste') { try { // Валидация и типизация входных аргументов if (!args || typeof args !== 'object') { throw new Error('Invalid arguments provided'); } const params = args as unknown as CopyPasteParams; const result = await this.copyPasteHandler.execute(params); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2) } ] }; } catch (error) { return { content: [ { type: 'text', text: JSON.stringify({ success: false, message: `Tool execution error: ${error instanceof Error ? error.message : 'Unknown error'}` }, null, 2) } ], isError: true }; } } throw new Error(`Unknown tool: ${name}`); }); } async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); console.error('Clipboard MCP Server running on stdio'); } } // Запуск сервера const server = new ClipboardMCPServer(); server.run().catch((error) => { console.error('Server error:', error); process.exit(1); });

Implementation Reference

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/witqq/clipboard-mcp'

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