Skip to main content
Glama
skippr-hq

Skippr Extension MCP Server

by skippr-hq

Send Message to Extension

skippr_send_to_extension

Send 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

TableJSON Schema
NameRequiredDescriptionDefault
extensionIdYesThe extension ID to send the message to
typeYesMessage type
payloadNoThe message payload

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
successYes
extensionIdYes
messageYes

Implementation Reference

  • 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);
      }
    );
  • 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);
    }
  • 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;
    }
  • 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(),
      }),
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden for behavioral disclosure. It only states 'sends a message' but does not explain if the operation is synchronous, what happens if the extension is not connected, or any side effects. This is insufficient for safe usage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence that is front-loaded with the core action. No unnecessary words, efficient and clear.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no annotations and the presence of an output schema (not shown), the description should still cover behavior, error handling, or prerequisites. It lacks information on success/failure responses and constraints, making it incomplete for a tool with three parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema descriptions are adequate. The tool description does not add any additional meaning beyond the schema, so it meets the baseline expectation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action: sending a message to a specific browser extension by its ID. It uses a specific verb and resource, and distinguishes from sibling tools like notify_all_extensions (sends to all) and notify_project_extensions (sends to project group).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives or when not to use it. Prerequisites (e.g., extension must be connected) are not mentioned, leaving the agent without clear context for selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/skippr-hq/extension-mcp-server'

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