Skip to main content
Glama
ice3x2

Google Chat Webhook MCP Server

by ice3x2

Send Google Chat Markdown

send_google_chat_markdown

Send formatted messages to Google Chat by converting Markdown to Cards V2 format with automatic fallback to plain text when needed.

Instructions

Convert Markdown to Cards V2 and send to configured Google Chat webhook. Falls back to text on failure.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
markdownYes
cardTitleNo
fallbackToTextNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
successYes
messageIdNo
usedFallbackNo

Implementation Reference

  • The MCP tool handler function that receives tool parameters, calls the sendMarkdownMessage helper, and returns structured MCP response or error.
    const sendMarkdownHandler = (async ({ markdown, cardTitle, fallbackToText }: { markdown: string; cardTitle?: string; fallbackToText?: boolean }) => {
      try {
        const result = await sendMarkdownMessage(webhook || '', { markdown, cardTitle, fallbackToText });
        return { content: [{ type: 'text', text: JSON.stringify(result) }], structuredContent: result };
      } catch (err: unknown) {
        const e = err as Error;
        return { content: [{ type: 'text', text: `Error: ${e.message}` }], isError: true };
      }
    }) as any;
  • Zod schemas defining the input parameters (markdown required, cardTitle and fallbackToText optional) and output structure (success, usedFallback, messageId).
    inputSchema: ( { markdown: z.string(), cardTitle: z.string().optional(), fallbackToText: z.boolean().optional() } as unknown ) as any,
    outputSchema: ( { success: z.boolean(), usedFallback: z.boolean().optional(), messageId: z.string().optional() } as unknown ) as any
  • src/server.ts:133-142 (registration)
    MCP server registration of the 'send_google_chat_markdown' tool with title, description, schemas, and handler reference.
    server.registerTool(
      'send_google_chat_markdown',
      {
        title: 'Send Google Chat Markdown',
        description: 'Convert Markdown to Cards V2 and send to configured Google Chat webhook. Falls back to text on failure.',
        inputSchema: ( { markdown: z.string(), cardTitle: z.string().optional(), fallbackToText: z.boolean().optional() } as unknown ) as any,
        outputSchema: ( { success: z.boolean(), usedFallback: z.boolean().optional(), messageId: z.string().optional() } as unknown ) as any
      },
      sendMarkdownHandler
    );
  • The core implementation that converts Markdown to Google Chat Cards V2, validates the cards, sends the message, and falls back to plain text if Cards V2 fails.
    export async function sendMarkdownMessage(webhookUrl: string, options: SendMarkdownOptions): Promise<SendMarkdownResult> {
      const { markdown, cardTitle, fallbackToText = true } = options;
      const startTime = Date.now();
    
      // Phase0: 시도형 스텁 - 변환 후 바로 sendCardsV2Message 호출
      try {
        const cardsV2 = await markdownToCardsV2(markdown, cardTitle);
        // validate before sending
        try {
          validateCardsV2(cardsV2);
        } catch (valErr) {
          logger.warn('sendMarkdownMessage', 'validation_failed', {
            error: String(valErr),
            cardTitle,
          });
          throw new Error(`Cards V2 validation failed: ${valErr}`);
        }
    
        const response = await sendCardsV2Message({ text: cardTitle || 'Markdown Message', cardsV2 }, webhookUrl);
        const elapsed = Date.now() - startTime;
        
        logger.info('sendMarkdownMessage', 'message_sent', {
          messageId: (response && response.name) || 'unknown',
          elapsed,
          usedFallback: false,
          cardTitle,
        });
    
        return { success: true, messageId: (response && response.name) || undefined, usedFallback: false };
      } catch (err: any) {
        if (fallbackToText) {
          // 폴백: 원본 Markdown 그대로 텍스트 전송
          try {
            const r = await sendTextMessage({ text: markdown }, webhookUrl);
            const elapsed = Date.now() - startTime;
            
            logger.warn('sendMarkdownMessage', 'fallback_used', {
              messageId: (r && r.name) || 'unknown',
              reason: String(err),
              elapsed,
            });
    
            return { success: true, messageId: r && r.name, usedFallback: true, fallbackReason: String(err) };
          } catch (sendErr: any) {
            logger.error('sendMarkdownMessage', 'send_failed', {
              error: String(sendErr),
              cardTitle,
              markdown: markdown.substring(0, 100), // 처음 100자만 로깅
            });
            return { success: false, error: String(sendErr) };
          }
        }
    
        logger.error('sendMarkdownMessage', 'send_failed', {
          error: String(err),
          cardTitle,
          markdown: markdown.substring(0, 100), // 처음 100자만 로깅
        });
    
        return { success: false, error: String(err) };
      }
    }
Behavior3/5

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

With no annotations provided, the description carries full burden. It discloses key behavioral traits: conversion to Cards V2 format, webhook-based sending, and fallback behavior on failure. However, it doesn't mention authentication requirements, rate limits, error handling specifics, or what constitutes 'failure' beyond the fallback.

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?

The description is extremely concise (two sentences) and front-loaded with the core functionality. Every word earns its place - no redundant information or unnecessary elaboration. Perfectly sized for the tool's complexity.

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

Completeness3/5

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

Given the tool has an output schema (which handles return values), no annotations, and moderate complexity, the description covers the core transformation and delivery mechanism adequately. However, it lacks details about the webhook configuration, authentication, error scenarios beyond fallback, and parameter usage that would make it more complete.

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

Parameters2/5

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

With 0% schema description coverage and 3 parameters, the description adds minimal semantic value. It mentions 'markdown' content and 'fallbackToText' behavior by name only, but doesn't explain what 'cardTitle' does, parameter formats, or constraints. The description doesn't adequately compensate for the schema's lack of parameter documentation.

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 specific action ('Convert Markdown to Cards V2 and send'), the resource ('configured Google Chat webhook'), and distinguishes from siblings by mentioning the markdown conversion capability. It explicitly differentiates from send_google_chat_cards_v2 and send_google_chat_text by focusing on markdown input.

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

Usage Guidelines4/5

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

The description provides clear context about when to use this tool (when you have markdown content to send to Google Chat) and mentions fallback behavior, but doesn't explicitly state when NOT to use it or provide direct alternatives. It implies usage vs. siblings by describing the markdown conversion feature.

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/ice3x2/google-chat-webhook-mcp'

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