Google Chat Webhook MCP Server
Sends messages to Google Chat via webhooks with automatic Markdown to Cards V2 conversion, supporting headers, lists, code blocks, tables, and images with validation and fallback handling.
README
Google Chat Webhook MCP Server
An MCP (Model Context Protocol) server that sends messages to Google Chat via webhooks. Automatically converts Markdown to Google Chat Cards V2 format with image validation, structured logging, and fallback handling.
Features
- π MCP Protocol Support: Integrates with Claude Code, GitHub Copilot, and other MCP clients
- οΏ½ MCP Protocol Support: Integrates with Claude Code, GitHub Copilot, and other MCP clients
- οΏ½π Markdown β Cards V2 Auto-conversion: Supports headers, lists, code blocks, tables, images, and more
- πΌοΈ Image URL Validation: Validates with HEAD requests (HTTP status, Content-Type, size)
- π Auto Fallback: Automatically falls back to text when Cards V2 fails
- π Structured Logging: JSON format with 30-day retention
- β Test Automation: Snapshot tests, integration tests, CI/CD pipeline
Installation
npm (Recommended)
npm install -g google-chat-webhook-mcp
From Source (Development)
git clone https://github.com/ice3x2/google-chat-webhook-mcp.git
cd google-chat-webhook-mcp
npm install
npm run build
Google Chat Webhook Setup
Before configuring the MCP server, create a Google Chat Webhook URL:
- Open your Google Chat space
- Menu β "Apps & integrations" β "Manage webhooks"
- Click "Add webhook"
- Enter a name and copy the URL
- Use it in the configuration below
MCP Client Configuration
1. Claude Code
Config File Location
- Windows:
%USERPROFILE%\.claude.json - macOS/Linux:
~/.claude.json
Note: Claude Desktop uses different paths:
- Windows:
%APPDATA%\Claude\claude_desktop_config.json - macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
npm Installation
{
"mcpServers": {
"google-chat": {
"command": "npx",
"args": ["-y", "google-chat-webhook-mcp"],
"env": {
"GOOGLE_CHAT_WEBHOOK_URL": "https://chat.googleapis.com/v1/spaces/xxx/messages?key=xxx&token=xxx"
}
}
}
}
Source Installation
{
"mcpServers": {
"google-chat": {
"command": "node",
"args": ["C:\\path\\to\\google-chat-webhook-mcp\\dist\\index.js"],
"env": {
"GOOGLE_CHAT_WEBHOOK_URL": "https://chat.googleapis.com/v1/spaces/xxx/messages?key=xxx&token=xxx"
}
}
}
}
β οΈ Note: Use \\ or / for Windows paths (e.g., C:/path/to/...)
Configuration Scopes
Claude Code supports three configuration scopes:
- User Scope (Global):
~/.claude.json- Available across all projects - Project Scope (Shared):
.mcp.jsonin project root - Version-controlled, team-shared - Local Scope (Private): Project-specific, personal settings
Priority: Local > Project > User
Project-Scoped Configuration (.mcp.json)
For team-shared MCP servers, create .mcp.json in your project root:
{
"mcpServers": {
"google-chat": {
"command": "npx",
"args": ["-y", "google-chat-webhook-mcp"],
"env": {
"GOOGLE_CHAT_WEBHOOK_URL": "${GOOGLE_CHAT_WEBHOOK_URL}"
}
}
}
}
Benefits:
- β Version-controlled with Git
- β Team-shared configuration
- β
Environment variable support:
${VAR}or${VAR:-default} - β Project-specific MCP servers
Environment Variables: Each team member can set their own webhook URL:
# Linux/macOS
export GOOGLE_CHAT_WEBHOOK_URL="https://chat.googleapis.com/v1/spaces/xxx/messages?key=xxx&token=xxx"
# Windows (PowerShell)
$env:GOOGLE_CHAT_WEBHOOK_URL="https://chat.googleapis.com/v1/spaces/xxx/messages?key=xxx&token=xxx"
How to Apply
User-scoped configuration (~/.claude.json):
- Edit
~/.claude.json(or%USERPROFILE%\.claude.jsonon Windows) - Save the file
- Restart Claude Code if already running
Project-scoped configuration (.mcp.json):
- Create
.mcp.jsonin project root - Set environment variables for sensitive data
- Commit
.mcp.jsonto version control - Use commands like "Send a message to Google Chat"
2. GitHub Copilot (VS Code)
VS Code GitHub Copilot supports MCP through agent mode. Configure MCP servers in workspace or user settings.
Configuration File Locations
Choose one of the following:
- User Settings:
~/.vscode/settings.jsonor%APPDATA%\Code\User\settings.json(Windows) - Workspace Settings:
.vscode/settings.jsonin your project root - Claude Code Config (Auto-import): Copy from
~/.claude.json
Configuration (mcp.json format)
Add to settings.json:
{
"github.copilot.chat.mcp.servers": {
"google-chat": {
"command": "npx",
"args": ["-y", "google-chat-webhook-mcp"],
"env": {
"GOOGLE_CHAT_WEBHOOK_URL": "https://chat.googleapis.com/v1/spaces/xxx/messages?key=xxx&token=xxx"
}
}
}
}
Features
- Agent Mode Integration: MCP tools available in agent workflow
- Per-Session Tool Selection: Choose which tools to enable per session
- STDIO & SSE Support: Both transport types supported
- Debugging: Restart commands and output logging built-in
Using with Agent Mode
- Open GitHub Copilot Chat in VS Code
- Enable agent mode (if not already enabled)
- Start a conversation - Copilot will automatically access MCP tools
- Tools require approval before execution
Example:
@workspace Send a deployment summary to Google Chat
π Note: GitHub Copilot's MCP support includes agent mode, allowing sophisticated workflows. Make sure you're using the latest VS Code and GitHub Copilot extension.
3. Other MCP Clients
Works with any MCP-compatible client:
{
"command": "npx",
"args": ["-y", "google-chat-webhook-mcp"],
"env": {
"GOOGLE_CHAT_WEBHOOK_URL": "your-webhook-url"
}
}
Usage
MCP Tools (3 Tools)
Available tools in Claude Code or other MCP clients:
1. send_google_chat_text
Send simple text messages
Example (Claude Code):
Send "Hello from Claude!" to Google Chat
Parameters:
{
"text": "Hello, Google Chat!"
}
2. send_google_chat_cards_v2
Send Cards V2 format directly (advanced users)
Parameters:
{
"text": "Card Message",
"cardsV2": [
{
"cardId": "unique-card",
"card": {
"header": { "title": "Card Title" },
"sections": [
{
"widgets": [
{ "textParagraph": { "text": "Card content" } }
]
}
]
}
}
]
}
3. send_google_chat_markdown β Recommended
Convert Markdown to Cards V2 and send
Example (Claude Code):
Send this markdown to Google Chat:
# Project Update
- Task 1: β
Completed
- Task 2: π§ In Progress
**Deadline**: Tomorrow
Parameters:
{
"markdown": "# Title\n\n**Bold** and *italic*\n\n- List item 1\n- List item 2\n\n```python\nprint('Hello')\n```",
"cardTitle": "Markdown Message",
"fallbackToText": true
}
Options:
cardTitle: Title shown at the top of the card (optional)fallbackToText: Auto-send as text on conversion failure (default: false)
Claude Code Usage Example
After setup, Claude will automatically use MCP tools when you chat naturally:
π€ User:
"Send a project status update to Google Chat. Show 3 completed tasks and 2 in-progress tasks as a markdown list."
π€ Claude:
(Automatically calls
send_google_chat_markdowntool)I've sent the message to Google Chat. The project status has been updated.
Supported Markdown Syntax
Markdown written in Claude or MCP clients is automatically converted to Google Chat Cards V2.
| Syntax | Markdown Example | Google Chat Rendering |
|---|---|---|
| Headers | # H1, ## H2, ### H3 |
Bold with size differences |
| Bold | **bold** or __bold__ |
bold |
| Italic | *italic* or _italic_ |
italic |
| Inline Code | `code` |
code (monospace) |
| Code Block | ```python\ncode\n``` |
Syntax-highlighted box |
| Ordered List | 1. First\n2. Second |
1. First<br>2. Second |
| Unordered List | - Item or * Item |
β’ Item |
| Nested List | - nested (2-space indent) |
β’ nested (Em space) |
| Table | | A | B |\n|--|--| |
Monospace table |
| Image |  |
Image widget (after validation) |
| Link | [text](https://...) |
Clickable link |
| Horizontal Rule | --- or *** |
Divider |
| Blockquote | > quote |
Indented + gray text |
Example Markdown:
# Project Deployment Complete π
## Key Changes
- **Performance**: API response 30% faster
- **Bug Fix**: Login error resolved
- New feature added
## Deployment Status
| Environment | Status | Version |
|-------------|--------|---------|
| Production | β
| v2.1.0 |
| Staging | β
| v2.1.0 |
## Next Steps
1. Monitor for 24 hours
2. Collect user feedback
3. Plan next sprint
Code example:
```python
def deploy():
print("Deploying v2.1.0...")
return True
See documentation for details.
**Result:** Headers, lists, tables, and code blocks are all visually distinguished in Google Chat.
## Environment Variables
### Required
| Variable | Description | Example |
|----------|-------------|---------|
| `GOOGLE_CHAT_WEBHOOK_URL` | Google Chat Webhook URL | `https://chat.googleapis.com/v1/spaces/xxx/messages?key=xxx&token=xxx` |
### Optional (Logging)
| Variable | Description | Default | Values |
|----------|-------------|---------|--------|
| `LOG_LEVEL` | Log level | `INFO` | `DEBUG`, `INFO`, `WARN`, `ERROR` |
| `LOG_DIR` | Log directory path | `./logs` | Absolute/relative path |
| `LOG_RETENTION_DAYS` | Days to keep logs | `30` | Number (days) |
| `LOG_ENABLE_CONSOLE` | Enable console output | `true` | `true`, `false` |
### Configuration Methods
#### Claude Code (~/.claude.json)
```json
{
"mcpServers": {
"google-chat": {
"command": "npx",
"args": ["-y", "google-chat-webhook-mcp"],
"env": {
"GOOGLE_CHAT_WEBHOOK_URL": "https://chat.googleapis.com/v1/spaces/xxx/messages?key=xxx&token=xxx",
"LOG_LEVEL": "INFO",
"LOG_RETENTION_DAYS": "30"
}
}
}
}
.env File (Development)
Create .env in project root:
GOOGLE_CHAT_WEBHOOK_URL=https://chat.googleapis.com/v1/spaces/xxx/messages?key=xxx&token=xxx
LOG_LEVEL=INFO
LOG_DIR=./logs
LOG_RETENTION_DAYS=30
LOG_ENABLE_CONSOLE=true
Limitations
Google Chat API Constraints
| Item | Limit | Workaround |
|---|---|---|
| Image Protocol | HTTPS only | HTTP URLs replaced with text links |
| Image Size | Max 5MB | Show as link on validation failure |
| Image Auth | Public URLs only | No access if auth required |
| Content-Type | image/* only |
HTML pages rejected |
| Markdown Support | Limited | Unsupported syntax approximated |
Markdown Conversion Limitations
β Fully Supported:
- Headers (H1~H6)
- Bold, italic, inline code
- Ordered/unordered lists (up to 3 levels)
- Code blocks (syntax highlighting)
- Tables (monospace)
- Links, images
β οΈ Partial Support:
- Complex nesting β Simplified
- HTML tags β Converted to text
- Blockquotes β Shown as indents
β Not Supported:
- Footnotes
- Definition lists
- Math formulas (LaTeX)
- Task checkboxes (
- [ ],- [x]) - Emoji shortcodes (
:smile:, Unicode emojis work)
FAQ
Q: Images not displaying
A: Image validation failure causes:
- HTTPS only (HTTP not supported)
- File size: Must be under 5MB
- Public access: Must be accessible without auth
- Content-Type: Response header must be
image/*
Debug:
cat logs/app-YYYY-MM-DD.log | grep "image_validation_failed"
Q: Cards V2 conversion fails
A: Use fallbackToText option:
{
"markdown": "...",
"fallbackToText": true
}
Check logs for details:
cat logs/errors-YYYY-MM-DD.log
Q: Too many log files
A: Adjust with environment variables:
{
"env": {
"LOG_LEVEL": "WARN",
"LOG_RETENTION_DAYS": "7"
}
}
Q: Multiple Google Chat spaces
A: Register separate MCP server instances:
{
"mcpServers": {
"google-chat-team-a": {
"command": "npx",
"args": ["-y", "google-chat-webhook-mcp"],
"env": {
"GOOGLE_CHAT_WEBHOOK_URL": "https://chat.googleapis.com/.../team-a/..."
}
},
"google-chat-team-b": {
"command": "npx",
"args": ["-y", "google-chat-webhook-mcp"],
"env": {
"GOOGLE_CHAT_WEBHOOK_URL": "https://chat.googleapis.com/.../team-b/..."
}
}
}
}
License
MIT License - LICENSE
Links
Korean:
MCP (Model Context Protocol) μλ²λ‘ Google Chat μΉν μ ν΅ν΄ λ©μμ§λ₯Ό μ μ‘ν©λλ€. Markdownμ Google Chat Cards V2 νμμΌλ‘ μλ λ³ννλ©°, μ΄λ―Έμ§ κ²μ¦, μλ λ‘κΉ , ν΄λ°± μ²λ¦¬λ₯Ό μ§μν©λλ€.
μ£Όμ κΈ°λ₯
- π MCP νλ‘ν μ½ μ§μ: Claude Code, GitHub Copilot λ±κ³Ό ν΅ν©
- π Markdown β Cards V2 μλ λ³ν: ν€λ, 리μ€νΈ, μ½λλΈλ‘, ν, μ΄λ―Έμ§ λ± μ§μ
- πΌοΈ μ΄λ―Έμ§ URL κ²μ¦: HEAD μμ²μΌλ‘ μ ν¨μ± νμΈ (HTTP μν, Content-Type, ν¬κΈ°)
- π μλ ν΄λ°±: Cards V2 μ€ν¨ μ ν μ€νΈλ‘ μλ μ ν
- π ꡬ쑰νλ λ‘κΉ : JSON νμ, 30μΌ μλ 보κ΄
- β ν μ€νΈ μλν: μ€λ μ· ν μ€νΈ, ν΅ν© ν μ€νΈ, CI/CD νμ΄νλΌμΈ
μ€μΉ
npm μ€μΉ (κΆμ₯)
npm install -g google-chat-webhook-mcp
μμ€ μ€μΉ (κ°λ°μ©)
git clone https://github.com/ice3x2/google-chat-webhook-mcp.git
cd google-chat-webhook-mcp
npm install
npm run build
Google Chat Webhook URL μμ±
MCP μλ² μ€μ μ μ λ¨Όμ Google Chat Webhook URLμ μμ±ν΄μΌ ν©λλ€:
- Google Chat μ€νμ΄μ€ μ΄κΈ°
- μλ¨ λ©λ΄ β "μ± λ° ν΅ν©" β "Webhook κ΄λ¦¬"
- "Webhook μΆκ°" ν΄λ¦
- μ΄λ¦ μ λ ₯ ν URL 볡μ¬
- μλ μ€μ μμ μ¬μ©
MCP ν΄λΌμ΄μΈνΈ μ€μ
1. Claude Code
μ€μ νμΌ μμΉ
- Windows:
%USERPROFILE%\.claude.json - macOS/Linux:
~/.claude.json
μ°Έκ³ : Claude Desktopμ λ€λ₯Έ κ²½λ‘λ₯Ό μ¬μ©ν©λλ€:
- Windows:
%APPDATA%\Claude\claude_desktop_config.json - macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
npm μ€μΉ μ
{
"mcpServers": {
"google-chat": {
"command": "npx",
"args": ["-y", "google-chat-webhook-mcp"],
"env": {
"GOOGLE_CHAT_WEBHOOK_URL": "https://chat.googleapis.com/v1/spaces/xxx/messages?key=xxx&token=xxx"
}
}
}
}
μμ€ μ€μΉ μ
{
"mcpServers": {
"google-chat": {
"command": "node",
"args": ["C:\\path\\to\\google-chat-webhook-mcp\\dist\\index.js"],
"env": {
"GOOGLE_CHAT_WEBHOOK_URL": "https://chat.googleapis.com/v1/spaces/xxx/messages?key=xxx&token=xxx"
}
}
}
}
β οΈ μ£Όμ: Windows κ²½λ‘λ \\ λλ / μ¬μ© (μ: C:/path/to/...)
μ€μ μ€μ½ν
Claude Codeλ 3κ°μ§ μ€μ μ€μ½νλ₯Ό μ§μν©λλ€:
- User Scope (μ μ):
~/.claude.json- λͺ¨λ νλ‘μ νΈμμ μ¬μ© κ°λ₯ - Project Scope (곡μ ): νλ‘μ νΈ λ£¨νΈμ
.mcp.json- λ²μ κ΄λ¦¬, ν 곡μ κ°λ₯ - Local Scope (κ°μΈ): νλ‘μ νΈλ³ κ°μΈ μ€μ
μ°μ μμ: Local > Project > User
νλ‘μ νΈ μμ€ μ€μ (.mcp.json)
νκ³Ό 곡μ ν MCP μλ² μ€μ μ νλ‘μ νΈ λ£¨νΈμ .mcp.json νμΌμ μμ±νμΈμ:
{
"mcpServers": {
"google-chat": {
"command": "npx",
"args": ["-y", "google-chat-webhook-mcp"],
"env": {
"GOOGLE_CHAT_WEBHOOK_URL": "${GOOGLE_CHAT_WEBHOOK_URL}"
}
}
}
}
μ₯μ :
- β GitμΌλ‘ λ²μ κ΄λ¦¬ κ°λ₯
- β νκ³Ό μ€μ 곡μ
- β
νκ²½ λ³μ μ§μ:
${VAR}λλ${VAR:-κΈ°λ³Έκ°} - β νλ‘μ νΈλ³ MCP μλ² μ€μ
νκ²½ λ³μ μ€μ : κ° νμμ΄ μμ μ Webhook URLμ μ€μ ν μ μμ΅λλ€:
# Linux/macOS
export GOOGLE_CHAT_WEBHOOK_URL="https://chat.googleapis.com/v1/spaces/xxx/messages?key=xxx&token=xxx"
# Windows (PowerShell)
$env:GOOGLE_CHAT_WEBHOOK_URL="https://chat.googleapis.com/v1/spaces/xxx/messages?key=xxx&token=xxx"
μ μ© λ°©λ²
User μμ€ μ€μ (~/.claude.json):
~/.claude.jsonνΈμ§ (Windowsλ%USERPROFILE%\.claude.json)- νμΌ μ μ₯
- Claude Codeκ° μ€ν μ€μ΄λ©΄ μ¬μμ
Project μμ€ μ€μ (.mcp.json):
- νλ‘μ νΈ λ£¨νΈμ
.mcp.jsonμμ± - λ―Όκ°ν λ°μ΄ν°λ νκ²½ λ³μλ‘ μ€μ
.mcp.jsonμ λ²μ κ΄λ¦¬ μμ€ν μ 컀λ°- "Send a message to Google Chat" κ°μ λͺ λ Ή μ¬μ©
2. GitHub Copilot (VS Code)
VS Code GitHub Copilotμ μμ΄μ νΈ λͺ¨λλ₯Ό ν΅ν΄ MCPλ₯Ό μ§μν©λλ€. μν¬μ€νμ΄μ€ λλ μ¬μ©μ μ€μ μμ MCP μλ²λ₯Ό ꡬμ±ν μ μμ΅λλ€.
μ€μ νμΌ μμΉ
λ€μ μ€ νλλ₯Ό μ ν:
- μ¬μ©μ μ€μ :
~/.vscode/settings.jsonλλ%APPDATA%\Code\User\settings.json(Windows) - μν¬μ€νμ΄μ€ μ€μ : νλ‘μ νΈ λ£¨νΈμ
.vscode/settings.json - Claude Code μ€μ (μλ κ°μ Έμ€κΈ°):
~/.claude.jsonμμ 볡μ¬
μ€μ λ°©λ² (mcp.json νμ)
settings.jsonμ μΆκ°:
{
"github.copilot.chat.mcp.servers": {
"google-chat": {
"command": "npx",
"args": ["-y", "google-chat-webhook-mcp"],
"env": {
"GOOGLE_CHAT_WEBHOOK_URL": "https://chat.googleapis.com/v1/spaces/xxx/messages?key=xxx&token=xxx"
}
}
}
}
κΈ°λ₯
- μμ΄μ νΈ λͺ¨λ ν΅ν©: μμ΄μ νΈ μν¬νλ‘μ°μμ MCP λꡬ μ¬μ© κ°λ₯
- μΈμ λ³ λꡬ μ ν: μΈμ λ§λ€ νμ±νν λꡬ μ ν κ°λ₯
- STDIO & SSE μ§μ: λ μ μ‘ λ°©μ λͺ¨λ μ§μ
- λλ²κΉ : μ¬μμ λͺ λ Ή λ° μΆλ ₯ λ‘κΉ λ΄μ₯
μμ΄μ νΈ λͺ¨λμμ μ¬μ©νκΈ°
- VS Codeμμ GitHub Copilot μ±ν μ΄κΈ°
- μμ΄μ νΈ λͺ¨λ νμ±ν (κΈ°λ³Έ νμ±νλ κ²½μ°λ μμ)
- λν μμ - Copilotμ΄ μλμΌλ‘ MCP λꡬμ μ κ·Ό
- λꡬ μ€ν μ μΉμΈ νμ
μμ:
@workspace λ°°ν¬ μμ½μ Google Chatμ μ μ‘ν΄μ€
π μ°Έκ³ : GitHub Copilotμ MCP μ§μμ μμ΄μ νΈ λͺ¨λλ₯Ό ν¬ν¨νμ¬ μ κ΅ν μν¬νλ‘μ°λ₯Ό μ§μν©λλ€. μ΅μ λ²μ μ VS Codeμ GitHub Copilot νμ₯μ μ¬μ©νμΈμ.
3. κΈ°ν MCP ν΄λΌμ΄μΈνΈ
MCP νλ‘ν μ½μ μ§μνλ λͺ¨λ ν΄λΌμ΄μΈνΈμμ μ¬μ© κ°λ₯ν©λλ€:
{
"command": "npx",
"args": ["-y", "google-chat-webhook-mcp"],
"env": {
"GOOGLE_CHAT_WEBHOOK_URL": "your-webhook-url"
}
}
1. Google Chat μ€νμ΄μ€ μ΄κΈ°
2. μλ¨ λ©λ΄ β "μ± λ° ν΅ν©" β "Webhook κ΄λ¦¬"
3. "Webhook μΆκ°" ν΄λ¦
4. μ΄λ¦ μ
λ ₯ ν URL 볡μ¬
5. νκ²½ λ³μμ μ€μ
## μ¬μ©λ²
### MCP λꡬ (3κ°μ§)
Claude Codeμ΄λ λ€λ₯Έ MCP ν΄λΌμ΄μΈνΈμμ λ€μ λꡬλ€μ μ¬μ©ν μ μμ΅λλ€:
#### 1. `send_google_chat_text`
κ°λ¨ν ν
μ€νΈ λ©μμ§ μ μ‘
**μμ (Claude Code):**
Send "Hello from Claude!" to Google Chat
**νλΌλ―Έν°:**
```json
{
"text": "μλ
νμΈμ, Google Chat!"
}
2. send_google_chat_cards_v2
Cards V2 νμμΌλ‘ μ§μ μ μ‘ (κ³ κΈ μ¬μ©μμ©)
νλΌλ―Έν°:
{
"text": "Card Message",
"cardsV2": [
{
"cardId": "unique-card",
"card": {
"header": { "title": "Card Title" },
"sections": [
{
"widgets": [
{ "textParagraph": { "text": "Card content" } }
]
}
]
}
}
]
}
3. send_google_chat_markdown β μΆμ²
Markdownμ Cards V2λ‘ μλ λ³ννμ¬ μ μ‘
μμ (Claude Code):
Send this markdown to Google Chat:
# Project Update
- Task 1: β
Completed
- Task 2: π§ In Progress
**Deadline**: Tomorrow
νλΌλ―Έν°:
{
"markdown": "# μ λͺ©\n\n**κ΅΅μ κΈμ¨**μ *κΈ°μΈμ*\n\n- 리μ€νΈ νλͺ© 1\n- 리μ€νΈ νλͺ© 2\n\n```python\nprint('Hello')\n```",
"cardTitle": "λ§ν¬λ€μ΄ λ©μμ§",
"fallbackToText": true
}
μ΅μ :
cardTitle: μΉ΄λ μλ¨μ νμλ μ λͺ© (μ ν)fallbackToText: λ³ν μ€ν¨ μ ν μ€νΈλ‘ μλ μ μ‘ (κΈ°λ³Έκ°: false)
Claude Code μ¬μ© μμ
μ€μ μλ£ ν Claudeμ μμ°μ΄λ‘ λννλ©΄ μλμΌλ‘ MCP λꡬλ₯Ό μ¬μ©ν©λλ€:
π€ μ¬μ©μ:
"Google Chatμ νλ‘μ νΈ μν μ λ°μ΄νΈλ₯Ό 보λ΄μ€. μλ£λ μμ 3κ°, μ§ν μ€μΈ μμ 2κ°λ₯Ό λ§ν¬λ€μ΄ 리μ€νΈλ‘ μμ±ν΄μ."
π€ Claude:
(μλμΌλ‘
send_google_chat_markdownλꡬ νΈμΆ)Google Chatμ λ©μμ§λ₯Ό μ μ‘νμ΅λλ€. νλ‘μ νΈ μνκ° μ λ°μ΄νΈλμμ΅λλ€.
π€ μ¬μ©μ:
"λ°©κΈ λ³΄λΈ λ©μμ§μ μ½λ μμ λ μΆκ°ν΄μ€."
π€ Claude:
(λ€μ MarkdownμΌλ‘ λ©μμ§ μμ± λ° μ μ‘)
μ§μνλ Markdown λ¬Έλ²
Claudeλ MCP ν΄λΌμ΄μΈνΈμμ MarkdownμΌλ‘ λ©μμ§λ₯Ό μμ±νλ©΄ μλμΌλ‘ Google Chat Cards V2λ‘ λ³νλ©λλ€.
| λ¬Έλ² | Markdown μμ | Google Chat λ λλ§ |
|---|---|---|
| ν€λ | # H1, ## H2, ### H3 |
κ΅΅μ κΈμ¨ + ν¬κΈ° μ°¨λ± |
| κ΅΅κ² | **bold** λλ __bold__ |
bold |
| κΈ°μΈμ | *italic* λλ _italic_ |
italic |
| μΈλΌμΈ μ½λ | `code` |
code (κ³ μ ν ν°νΈ) |
| μ½λλΈλ‘ | ```python\ncode\n``` |
ꡬ문 κ°μ‘° λ°μ€ |
| μμ 리μ€νΈ | 1. First\n2. Second |
1. First<br>2. Second |
| λΉμμ 리μ€νΈ | - Item λλ * Item |
β’ Item |
| μ€μ²© 리μ€νΈ | - nested (2μΉΈ λ€μ¬μ°κΈ°) |
β’ nested (Em space) |
| ν | | A | B |\n|--|--| |
κ³ μ ν ν°νΈ ν |
| μ΄λ―Έμ§ |  |
μ΄λ―Έμ§ μμ ― (URL κ²μ¦ ν) |
| λ§ν¬ | [ν
μ€νΈ](https://...) |
ν΄λ¦ κ°λ₯ν λ§ν¬ |
| μνμ | --- λλ *** |
ꡬλΆμ |
| μΈμ©λ¬Έ | > quote |
λ€μ¬μ°κΈ° + νμ ν μ€νΈ |
μμ Markdown:
# νλ‘μ νΈ λ°°ν¬ μλ£ π
## μ£Όμ λ³κ²½μ¬ν
- **μ±λ₯ κ°μ **: API μλ΅ μλ 30% ν₯μ
- **λ²κ·Έ μμ **: λ‘κ·ΈμΈ μ€λ₯ ν΄κ²°
- μ κΈ°λ₯ μΆκ°
## λ°°ν¬ μν
| νκ²½ | μν | λ²μ |
|------|------|------|
| Production | β
| v2.1.0 |
| Staging | β
| v2.1.0 |
## λ€μ λ¨κ³
1. λͺ¨λν°λ§ 24μκ°
2. μ¬μ©μ νΌλλ°± μμ§
3. λ€μ μ€νλ¦°νΈ κ³ν
μ½λ μμ :
```python
def deploy():
print("Deploying v2.1.0...")
return True
μμΈν λ΄μ©μ λ¬Έμλ₯Ό μ°Έμ‘°νμΈμ.
**λ³ν κ²°κ³Ό:** Google Chatμμ ν€λ, 리μ€νΈ, ν, μ½λλΈλ‘μ΄ λͺ¨λ μκ°μ μΌλ‘ ꡬλΆλμ΄ νμλ©λλ€.
## νκ²½ λ³μ
### νμ νκ²½ λ³μ
| λ³μλͺ
| μ€λͺ
| μμ |
|--------|------|------|
| `GOOGLE_CHAT_WEBHOOK_URL` | Google Chat Webhook URL | `https://chat.googleapis.com/v1/spaces/xxx/messages?key=xxx&token=xxx` |
### μ ν νκ²½ λ³μ (λ‘κΉ
)
| λ³μλͺ
| μ€λͺ
| κΈ°λ³Έκ° | νμ©κ° |
|--------|------|--------|--------|
| `LOG_LEVEL` | λ‘κ·Έ λ 벨 | `INFO` | `DEBUG`, `INFO`, `WARN`, `ERROR` |
| `LOG_DIR` | λ‘κ·Έ λλ ν 리 κ²½λ‘ | `./logs` | μ λ/μλ κ²½λ‘ |
| `LOG_RETENTION_DAYS` | λ‘κ·Έ λ³΄κ΄ μΌμ | `30` | μ«μ (μΌ) |
| `LOG_ENABLE_CONSOLE` | μ½μ μΆλ ₯ μ¬λΆ | `true` | `true`, `false` |
### μ€μ λ°©λ²
#### Claude Code (~/.claude.json)
```json
{
"mcpServers": {
"google-chat": {
"command": "npx",
"args": ["-y", "google-chat-webhook-mcp"],
"env": {
"GOOGLE_CHAT_WEBHOOK_URL": "https://chat.googleapis.com/v1/spaces/xxx/messages?key=xxx&token=xxx",
"LOG_LEVEL": "INFO",
"LOG_RETENTION_DAYS": "30"
}
}
}
}
.env νμΌ (κ°λ°μ©)
νλ‘μ νΈ λ£¨νΈμ .env νμΌ μμ±:
GOOGLE_CHAT_WEBHOOK_URL=https://chat.googleapis.com/v1/spaces/xxx/messages?key=xxx&token=xxx
LOG_LEVEL=INFO
LOG_DIR=./logs
LOG_RETENTION_DAYS=30
LOG_ENABLE_CONSOLE=true
μμ€ν νκ²½ λ³μ
Windows (PowerShell):
$env:GOOGLE_CHAT_WEBHOOK_URL="https://chat.googleapis.com/v1/spaces/xxx/messages?key=xxx&token=xxx"
Linux/macOS (Bash/Zsh):
export GOOGLE_CHAT_WEBHOOK_URL="https://chat.googleapis.com/v1/spaces/xxx/messages?key=xxx&token=xxx"
κ°λ°
# μμ‘΄μ± μ€μΉ
npm install
# λΉλ
npm run build
# κ°λ° λͺ¨λ (TypeScript μ§μ μ€ν)
npm run dev
# Lint κ²μ¬
npm run lint
# Lint μλ μμ
npm run lint:fix
# ν
μ€νΈ
npm run test:snapshot # μ€λ
μ· ν
μ€νΈ (12κ°)
npm run test:logging # λ‘κΉ
μμ€ν
ν
μ€νΈ
npm run test:integration # ν΅ν© ν
μ€νΈ (μΉν
νμ)
npm test # μ 체 ν
μ€νΈ
μν€ν μ²
src/
βββ index.ts # μ§μ
μ
βββ server.ts # MCP μλ² μ€μ
βββ tools/ # MCP λꡬ
β βββ sendTextMessage.ts # ν
μ€νΈ μ μ‘
β βββ sendCardsV2Message.ts # Cards V2 μ μ‘
β βββ sendMarkdownMessage.ts # Markdown μ μ‘ (λ©μΈ)
β βββ markdownToCards.ts # Markdown β Cards V2 λ³ν
βββ utils/ # μ νΈλ¦¬ν°
β βββ imageValidator.ts # μ΄λ―Έμ§ URL κ²μ¦
β βββ cardsV2Validator.ts # Cards V2 μ€ν€λ§ κ²μ¦
β βββ logger.ts # λ‘κΉ
μμ€ν
β βββ logCleaner.ts # λ‘κ·Έ μ 리
βββ types/ # νμ
μ μ
βββ markdown.ts
βββ googleChat.ts
βββ log.ts
λ‘κΉ
λ‘κ·Έ νμΌ κ΅¬μ‘°
logs/
βββ app-2025-10-29.log # μΌλ³ λ‘κ·Έ (λͺ¨λ λ 벨)
βββ errors-2025-10-29.log # μλ¬ μ μ© λ‘κ·Έ
βββ ... # 30μΌ μλ μμ
λ‘κ·Έ ν¬λ§· (JSON)
{
"timestamp": "2025-10-29T12:34:56.789Z",
"level": "INFO",
"module": "sendMarkdownMessage",
"event": "message_sent",
"messageId": "spaces/xxx/messages/yyy",
"elapsed": 123,
"usedFallback": false,
"cardTitle": "Test Card"
}
λ‘κ·Έ μ΄λ²€νΈ
message_sent: λ©μμ§ μ μ‘ μ±κ³΅fallback_used: ν΄λ°± μ¬μ© (Cards V2 β Text)image_validation_failed: μ΄λ―Έμ§ κ²μ¦ μ€ν¨send_failed: μ μ‘ μ€ν¨validation_failed: κ²μ¦ μ€ν¨
λ‘κ·Έ μ 리
- μλ² μμ μ μλ μ 리 (30μΌ μ΄μ λ‘κ·Έ μμ )
- 24μκ°λ§λ€ μλ μ€ν
- νκ²½ λ³μ
LOG_RETENTION_DAYSλ‘ μ€μ κ°λ₯
μ νμ¬ν
Google Chat API μ μ½μ¬ν
| νλͺ© | μ ν | λμ λ°©λ² |
|---|---|---|
| μ΄λ―Έμ§ νλ‘ν μ½ | HTTPSλ§ μ§μ | HTTP URLμ ν μ€νΈ λ§ν¬λ‘ λ체 |
| μ΄λ―Έμ§ ν¬κΈ° | μ΅λ 5MB | κ²μ¦ μ€ν¨ μ λ§ν¬λ‘ νμ |
| μ΄λ―Έμ§ μΈμ¦ | κ³΅κ° URLλ§ κ°λ₯ | μΈμ¦ νμ μ μ κ·Ό λΆκ° |
| Content-Type | image/*λ§ νμ© |
HTML νμ΄μ§ λ±μ κ±°λΆ |
| Markdown μ§μ | μ νμ | λ―Έμ§μ λ¬Έλ²μ κ·Όμ¬μΉλ‘ λ³ν |
Markdown λ³ν μ μ½μ¬ν
β μμ μ§μ:
- ν€λ (H1~H6)
- κ΅΅κ², κΈ°μΈμ, μΈλΌμΈ μ½λ
- μμ/λΉμμ 리μ€νΈ (μ΅λ 3λ¨κ³ μ€μ²©)
- μ½λλΈλ‘ (ꡬ문 κ°μ‘°)
- ν (κ³ μ ν ν°νΈ)
- λ§ν¬, μ΄λ―Έμ§
β οΈ λΆλΆ μ§μ:
- 볡μ‘ν μ€μ²© ꡬ쑰 β λ¨μνλ¨
- HTML νκ·Έ β ν μ€νΈλ‘ λ³ν
- μΈμ©λ¬Έ β λ€μ¬μ°κΈ°λ‘ νν
β λ―Έμ§μ:
- κ°μ£Ό (footnotes)
- μ μ 리μ€νΈ (definition lists)
- μν μμ (LaTeX)
- μμ
체ν¬λ°μ€ (
- [ ],- [x]) - Emoji λ¨μΆμ½λ (
:smile:λ±, μ λμ½λ μ΄λͺ¨μ§λ κ°λ₯)
μ±λ₯ λ° μ ν
- μ΄λ―Έμ§ κ²μ¦ νμμμ: 5μ΄
- Webhook μμ² νμμμ: 5μ΄
- λ‘κ·Έ νμΌ ν¬κΈ°: 무μ ν (30μΌ μλ μμ )
- λμ μμ²: μ ν μμ (Google Chat API μ ν μ€μ)
보μ κ³ λ €μ¬ν
β οΈ Webhook URLμ λ―Όκ° μ 보μ λλ€:
- Gitμ 컀λ°νμ§ λ§μΈμ
- κ³΅κ° μ μ₯μμ λ ΈμΆ κΈμ§
- μ κΈ°μ μΌλ‘ μ¬μμ± κΆμ₯
.envνμΌμ.gitignoreμ ν¬ν¨ νμ
FAQ
Q: μ΄λ―Έμ§κ° νμλμ§ μμ΅λλ€
A: μ΄λ―Έμ§ URL κ²μ¦ μ€ν¨ μμΈ:
- HTTPSλ§ μ§μ (HTTPλ λΆκ°)
- νμΌ ν¬κΈ°: 5MB μ΄νμ¬μΌ ν¨
- κ³΅κ° μ κ·Ό: μΈμ¦ μμ΄ μ κ·Ό κ°λ₯ν URLμ΄μ΄μΌ ν¨
- Content-Type: μλ΅ ν€λκ°
image/*μ¬μΌ ν¨
λλ²κΉ :
# λ‘κ·Έ νμΈ
cat logs/app-YYYY-MM-DD.log | grep "image_validation_failed"
κ²μ¦ μ€ν¨ μ λμ:
- μ΄λ―Έμ§λ ν μ€νΈ λ§ν¬λ‘ λ체λ¨
- μ:
β οΈ μ΄λ―Έμ§ λ‘λ μ€ν¨: https://... (HTTP 404: Not Found)
Q: Cards V2 λ³νμ΄ μ€ν¨ν©λλ€
A: λ€μμ νμΈνμΈμ:
-
fallbackToText μ΅μ μ¬μ©:
{ "markdown": "...", "fallbackToText": true }λ³ν μ€ν¨ μ μλμΌλ‘ ν μ€νΈλ‘ μ μ‘λ©λλ€.
-
λ‘κ·Έμμ μμΈ νμΈ:
cat logs/errors-YYYY-MM-DD.log -
μ§μνμ§ μλ Markdown λ¬Έλ²:
- κ°μ£Ό (footnotes)
- μ μ 리μ€νΈ (definition lists)
- 볡μ‘ν HTML νκ·Έ
Q: λ‘κ·Έ νμΌμ΄ λ무 λ§μ΄ μμ λλ€
A: νκ²½ λ³μλ‘ μ‘°μ :
{
"env": {
"LOG_LEVEL": "WARN",
"LOG_RETENTION_DAYS": "7"
}
}
LOG_LEVEL=ERROR: μλ¬λ§ κΈ°λ‘LOG_RETENTION_DAYS=7: 7μΌλ§ 보κ΄LOG_ENABLE_CONSOLE=false: μ½μ μΆλ ₯ λΉνμ±ν
Q: npx μ€ν μ "command not found" μ€λ₯
A: Node.jsμ npmμ΄ μ€μΉλμ΄ μλμ§ νμΈ:
node --version # v18.0.0 μ΄μ κΆμ₯
npm --version
μ€μΉλμ§ μμλ€λ©΄:
- Windows: https://nodejs.org/ μμ λ€μ΄λ‘λ
- macOS:
brew install node - Linux:
sudo apt install nodejs npm(Ubuntu/Debian)
Q: Webhook URLμ μ΄λ»κ² μμ νκ² κ΄λ¦¬νλμ?
A:
- νκ²½ λ³μ μ¬μ© (μ€μ νμΌμ μ§μ μ°μ§ λ§μΈμ)
- Gitμ 컀λ°νμ§ λ§μΈμ (.gitignore νμΈ)
- μ κΈ°μ μΌλ‘ μ¬μμ± (μ μΆ μμ¬ μ)
- Google Chatμμ Webhook μμ λ‘ λ¬΄ν¨ν κ°λ₯
Q: μ¬λ¬ Google Chat μ€νμ΄μ€μ λ©μμ§λ₯Ό 보λ΄κ³ μΆμ΅λλ€
A: κ° μ€νμ΄μ€λ§λ€ λ€λ₯Έ MCP μλ² μΈμ€ν΄μ€ λ±λ‘:
{
"mcpServers": {
"google-chat-team-a": {
"command": "npx",
"args": ["-y", "google-chat-webhook-mcp"],
"env": {
"GOOGLE_CHAT_WEBHOOK_URL": "https://chat.googleapis.com/.../team-a/..."
}
},
"google-chat-team-b": {
"command": "npx",
"args": ["-y", "google-chat-webhook-mcp"],
"env": {
"GOOGLE_CHAT_WEBHOOK_URL": "https://chat.googleapis.com/.../team-b/..."
}
}
}
}
Claudeμμ "Send to team-a" λλ "Send to team-b"λ‘ κ΅¬λΆνμ¬ μ¬μ©ν μ μμ΅λλ€.
CI/CD
GitHub Actionsλ‘ μλν:
- β Node.js 18.x, 20.x λ§€νΈλ¦μ€ λΉλ
- β ESLint, λΉλ, ν μ€νΈ
- β μ€λ μ· ν μ€νΈ (12κ°)
- β ν΅ν© ν μ€νΈ (master λΈλμΉ)
μν¬νλ‘μ°: .github/workflows/ci.yml
κΈ°μ¬
μ΄μμ PRμ νμν©λλ€!
λΌμ΄μ μ€
MIT License - LICENSE
λ¬Έμ
κ΄λ ¨ νλ‘μ νΈ
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
E2B
Using MCP to run code via e2b.