Send Message to Extension
skippr_send_to_extensionSend commands, notifications, or data to Skippr's browser extension to enable automated resolution of UX, accessibility, and quality issues.
Instructions
Sends a message to a specific browser extension by its ID
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| extensionId | Yes | The extension ID to send the message to | |
| type | Yes | Message type | |
| payload | No | The message payload |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| success | Yes | ||
| extensionId | Yes | ||
| message | Yes |
Implementation Reference
- src/servers/mcp.ts:129-159 (registration)Registration of the 'skippr_send_to_extension' tool with the MCP server, defining input schema (extensionId, type, payload) and output schema (success, extensionId, message).
// Extension communication tools mcpServer.registerTool( 'skippr_send_to_extension', { title: 'Send Message to Extension', description: 'Sends a message to a specific browser extension by its ID', inputSchema: z.object({ extensionId: z.string().describe('The extension ID to send the message to'), type: z.enum(['notification', 'command', 'data', 'status']).describe('Message type'), payload: z.any().describe('The message payload') }).shape, outputSchema: z.object({ success: z.boolean(), extensionId: z.string(), message: z.string() }).shape }, async (args) => { const message: z.infer<typeof ServerToClientMessageSchema> = { type: args.type, payload: args.payload }; const success = sendToExtension(args.extensionId, message); const result = { success, extensionId: args.extensionId, message: success ? 'Message sent successfully' : 'Failed to send message (extension may be disconnected)' }; return createStructuredResponse(result); } ); - src/servers/mcp.ts:146-158 (handler)Handler function that builds a ServerToClientMessage from args, calls sendToExtension(), and returns a structured response with success status.
async (args) => { const message: z.infer<typeof ServerToClientMessageSchema> = { type: args.type, payload: args.payload }; const success = sendToExtension(args.extensionId, message); const result = { success, extensionId: args.extensionId, message: success ? 'Message sent successfully' : 'Failed to send message (extension may be disconnected)' }; return createStructuredResponse(result); } - src/servers/websocket.ts:368-391 (helper)sendToExtension() helper function that looks up the extension's WebSocket connection from the clients map, adds timestamp/messageId, and sends the JSON message over the WebSocket.
export function sendToExtension(extensionId: string, message: z.infer<typeof ServerToClientMessageSchema>): boolean { const client = clients.get(extensionId); if (!client) { return false; } if (client && client.ws.readyState === WebSocket.OPEN) { try { // Add timestamp and messageId if not present const serverMessage = { ...message, timestamp: message.timestamp ?? Date.now(), messageId: message.messageId ?? crypto.randomBytes(8).toString('hex') }; client.ws.send(JSON.stringify(serverMessage)); return true; } catch (error) { console.error(`[sendToExtension] Error sending message to extension ${extensionId}:`, error); return false; } } return false; } - src/schemas/index.ts:131-165 (schema)ServerToClientMessageSchema - a discriminated union schema defining valid message types (notification, command, data, status, ping, pong) and their payloads, used to validate messages sent by the tool handler.
export const ServerToClientMessageSchema = z.discriminatedUnion('type', [ z.object({ type: z.literal('notification'), payload: NotificationPayloadSchema, timestamp: z.number().optional(), messageId: z.string().optional(), }), z.object({ type: z.literal('command'), payload: CommandPayloadSchema, timestamp: z.number().optional(), messageId: z.string().optional(), }), z.object({ type: z.literal('data'), payload: DataPayloadSchema, timestamp: z.number().optional(), messageId: z.string().optional(), }), z.object({ type: z.literal('status'), payload: StatusPayloadSchema, timestamp: z.number().optional(), messageId: z.string().optional(), }), z.object({ type: z.literal('ping'), timestamp: z.number().optional(), messageId: z.string().optional(), }), z.object({ type: z.literal('pong'), timestamp: z.number().optional(), messageId: z.string().optional(), }),