ASCII Table MCP Server
ASCII Table MCP Server
Beautiful tables in terminal code blocks AND as polished images — with native Thai, Pali, Roman, CJK, and emoji support.
+------------+------------------+--------+----------------------+
| Pali | Roman | Type | Meaning |
+------------+------------------+--------+----------------------+
| ปฏิจจสมุปฺปาท | paṭiccasamuppāda | Dhamma | Dependent origination |
| กามจฺฉนฺท | kāmacchanda | Nīvaraṇa | Sensual desire |
| อวิชฺชา | avijjā | Kilesa | Ignorance |
+------------+------------------+--------+----------------------+Thai + Roman + numbers → pixel-perfect alignment, every row.
🌐 Try it in your browser! → ASCII Table → Image Generator Paste CSV, pick a style, export as PNG / SVG / Grid / Box / Pipe. Thai + emoji ready. No install needed.

Why this exists: Most ASCII table libraries use len() in Python, which counts combining marks (like Thai tone marks, Devanagari vowel signs) as separate characters. This breaks alignment for any language with zero-width characters. This server uses wcwidth — the same library terminals use — so columns line up correctly, on every platform.
Features
9 table formats:
grid(+--+),box(┌─┬─┐),pipe(| | |),safe,html,png,svg+ more10 grid sub-styles:
mysql,separated,compact,gfm,reddit,rounded,rst,box,unicode,dots— inspired by ozh/ascii-tablesAuto-format: auto-detects numeric columns (right-align) and centers headers
Thai / Pali / CJK / emoji: zero-width combining marks (ิ, ี, ฺ, ◌̱, etc.) align perfectly
Safe width mode: extra padding for platforms where zero-width marks ≠ zero (Discord, browser code blocks)
Direct PNG export: headless Playwright renders styled HTML → cropped PNG with Noto Sans Thai — perfect for Discord/Telegram
Direct SVG export: vector SVG with embedded HTML (foreignObject) — zoomable, embeddable
4 polished HTML styles:
dark,light,minimal,compactCSV / TSV / JSON input: convert from any data source
Debug tools:
analyze_table,debug_table,validate_table_text— find and fix alignment issues
Direct PNG Export — One Step to a Gorgeous Table Image
For Discord, Telegram, Slack, or any place that can't render a proper monospace Thai table, use export_png to generate a cropped PNG directly — no browser, no manual screenshot, no crop step.
Style | Preview | Best for |
|
| Discord / Telegram dark mode |
|
| Documentation, PDF |
|
| Blog posts, websites |
|
| Dense data, narrow screens |
{
"headers": ["Pali", "Roman", "Type", "Meaning"],
"rows": [
["กมฺม", "kamma", "Noun", "action"],
["ญาณ", "ñāṇa", "Wisdom", "direct knowing"]
],
"style": "dark"
}Output: a .png file cropped to just the table — send it with MEDIA:<path> in Discord/Telegram.
Direct SVG Export — Vector That Scales
Use export_svg for images that need to be zoomed, embedded, or edited.
{
"headers": ["Term", "Translation"],
"rows": [["กมฺม", "Kamma"], ["ธมฺม", "Dhamma"]],
"style": "dark"
}SVG is HTML-backed (foreignObject) with Noto Sans Thai — renders sharp at any size.
Supported Formats
Quick Start
uvx (no install)
uvx --from git+https://github.com/dhammawatthumpra-coder/ascii-table-mcp ascii-table-mcppip install
git clone https://github.com/dhammawatthumpra-coder/ascii-table-mcp.git
cd ascii-table-mcp
pip install -e .
python -m ascii_table_mcpRegister with any MCP client
Claude Desktop:
{
"mcpServers": {
"ascii-table": {
"command": "python",
"args": ["-m", "ascii_table_mcp"]
}
}
}Hermes:
hermes mcp add ascii-table --command "python -m ascii_table_mcp"MCP Tools
make_table — The main event
Parameter | Type | Default | Description |
|
| — | Column headers |
|
| — | Data rows |
|
|
|
|
|
|
| One of 10 grid styles or 4 HTML styles |
|
|
| Right-align numbers, center headers |
|
|
| Extra padding for Discord/browser |
Example with style="separated":
{
"headers": ["Product", "Price", "Qty"],
"rows": [
["Noodle Soup", "45", "3"],
["Fried Rice", "55", "2"]
],
"fmt": "grid",
"style": "separated"
}+============+======+=======+
| Product | Price | Qty |
+============+======+=======+
+------------+------+-------+
| Noodle Soup | 45 | 3 |
+------------+------+-------+
| Fried Rice | 55 | 2 |
+------------+------+-------+Notice: auto_format=true right-aligns Price and Qty columns, centers headers.
make_table_from_csv
{
"csv_text": "Name,Role,Score\nAlice,Admin,95\nBob,User,87",
"fmt": "grid"
}make_table_from_json
{
"json_data": "[[\"Term\",\"Meaning\"],[\"Kamma\",\"Action\"],[\"Dhamma\",\"Truth\"]]",
"fmt": "box"
}export_png — Direct PNG export
Render table as cropped PNG via headless Playwright.
Parameter | Type | Default | Description |
|
| — | Column headers |
|
| — | Data rows |
|
|
|
|
|
|
| Font size in px |
{
"headers": ["คำบาลี", "Roman"],
"rows": [["กมฺม", "kamma"], ["ธมฺม", "dhamma"]],
"style": "dark"
}→ Returns file path to cropped PNG. Send with MEDIA:<path>.
export_svg — Direct SVG export
Render table as vector SVG (foreignObject with styled HTML).
Same parameters as export_png. Returns file path to .svg.
Debug tools
debug_table— shows exact char positions with drift analysisanalyze_table— validates column alignment in+--+tablesvalidate_table_text— structural check: column count, border alternation, format detection
Thai Character Width: The Problem This Solves
Discord, browser code blocks, and some terminals don't respect Unicode zero-width combining marks.
Characters like ิ ี ื ู ฺ each take up width=1 on screen, but wcwidth says they're width=0.
len("ก๋วยเตี๋ยว") → 10 ← Python counts combining marks
wcwidth("ก๋วยเตี๋ยว") → 7 ← Reality: only 7 visible column positionsSolution: safe_width=True
When enabled, the renderer uses len() (counts every character as width 1) instead of wcwidth, then adds padding for each combining mark:
{
"headers": ["Name", "Price"],
"rows": [["ก๋วยเตี๋ยว", "45"]],
"fmt": "grid",
"safe_width": true
}+----------------+------+
| Name | Price |
+----------------+------+
| ก๋วยเตี๋ยว | 45 |
+----------------+------+Without safe_width (discord will misalign):
+------------+------+
| Name | Price |
+------------+------+
| ก๋วยเตี๋ยว | 45 | ← column drifts right by 3 chars
+------------+------+Future: Per-Character Width Database
wcwidth and len() are both approximations. A future plan is to build a lookup table of actual display widths for each Thai character on major platforms (Windows Discord, macOS Discord, Linux terminal) for 100% guaranteed alignment.
Grid Styles Reference
Style | Top border | Header sep | Data sep | Bottom | Notes |
|
|
|
|
| default |
|
|
|
|
| bold header separator |
| none |
| none | none | frameless |
| none |
| none | none | GitHub Flavored Markdown |
| none |
| none | none | Reddit tables |
|
|
| none |
| rounded corners |
|
|
|
|
| reStructuredText |
|
|
|
|
| Unicode box-drawing |
|
|
|
|
| double-line |
|
|
| none |
| no row separators |
Format comparison
Format | Example | Best for |
|
| Terminal, code review, GitHub |
|
| Presentation, formal docs |
|
| Markdown-native |
|
| Discord, browser (zero-width ≠ 0) |
|
| Direct export — Discord/Telegram/chat apps |
|
| Vector — zoomable, embeddable |
CLI Usage
# CSV args → grid
python -m ascii_table_mcp.generate_table --grid 'Name,Age' 'Alice,30' 'Bob,25'
# TSV pipe → grid
printf 'Name\tAge\nAlice\t30\n' | python -m ascii_table_mcp.generate_table --tsv --grid
# JSON
python -m ascii_table_mcp.generate_table --json '{"headers":["A","B"],"rows":[["1","2"]]}' --grid+-------+-----+
| Name | Age |
+-------+-----+
| Alice | 30 |
| Bob | 25 |
+-------+-----+Architecture
ascii-table-mcp/
├── ascii_table_mcp/
│ ├── __init__.py # MCP server entry (FastMCP) — 9 tools
│ ├── generate_table.py # Core rendering engine + HTML + PNG + SVG
│ └── thaiwidth.py # Thai-aware display width
├── server.py # Thin CLI wrapper
├── table_to_image.py # HTML → screenshot helper (legacy)
├── table_screenshot.py # HTML generator (legacy)
├── requirements.txt # mcp + wcwidth
├── pyproject.toml # uv/pip packaging
├── ascii-table-mcp.bat # Windows launcher
├── LICENSE # MIT
├── README.md # This file (English)
├── README_TH.md # Thai documentation
├── GUIDE_TH.md # Thai user guide
├── GUIDE_EN.md # English user guide
└── examples/
├── ex_dark.png
├── ex_light.png
├── ex_minimal.png
└── ex_compact.pngWhy wcwidth Instead of len()?
len("กมฺม") → 4 ❌ (counts the dot-below as a character)
wcswidth("กมฺม") → 3 ✅ (dot-below is zero-width)Using len() for table layout:
+----------+-----------+ ← border width 8
| Pali | Roman | ← "กมฺม" = 4 chars → padding 4 → total 9 ❌
+----------+-----------+Using wcwidth:
+---------+-----------+
| Pali | Roman | ← "กมฺม" = width 3 → padding 5 → total 8 ✅
+---------+-----------+Related Projects
ozh/ascii-tables — original table style system
dmarsters/ascii-art-mcp — decorative ASCII art
schachmat/wego — Go terminal weather (go-runewidth)
wcwidth — Python wcwidth implementation
License
MIT — free for personal and commercial use.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/dhammawatthumpra-coder/ascii-table-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server



