ASCII Table MCP Server
This server generates beautifully formatted ASCII/Unicode tables with full support for Thai, Pali, CJK, emoji, and other complex scripts — and exports them as text, PNG, or SVG.
Create tables from raw headers/rows, CSV/TSV, or JSON data, with 9 output formats (grid, box, pipe, safe, html, png, svg) and 10+ grid sub-styles (mysql, gfm, reddit, rounded, unicode, dots, etc.). Auto-formats numeric columns (right-align) and centers headers automatically.
Export as images: Render polished PNG images via headless Playwright (ideal for Discord, Telegram, Slack) or scalable SVG vector graphics with embedded HTML and Noto Sans Thai font.
Handle complex scripts correctly using wcwidth for display width, properly handling zero-width combining marks (Thai tone marks, Devanagari, etc.). Enable safe_width mode for platforms like Discord or browser code blocks that miscount zero-width characters.
Debug and validate tables:
analyze_table— inspect column positions withwcwidth-aware widths to validate alignment.validate_table_text— check structural integrity (border/data alternation, column count stability, marker consistency).debug_table— generate a detailed diagnostic report with exact character positions and drift analysis for troubleshooting misaligned Unicode content.
Preview styles with sample Thai/Pali or English data using make_table_preview.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ASCII Table MCP Server create a box table with headers: คำบาลี, Roman; rows: กมฺม, kamma; อวิชฺชา, avijjā"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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
Related MCP server: mcp-markdown-tools
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.
Available Tools
7 toolsanalyze_tableA
Analyze column positions in a grid table (+---+).
Uses display-width space (via wcwidth) for position comparison, so Thai/Pali combining marks (พิทุ, สระบน/ล่าง) are handled correctly.
Scans '+' markers in border lines to define column boundaries, then validates '|' alignment in data rows.
Args: table_text: A +---+ grid table as raw text
Returns: Analysis report: column positions, alignment validation, parsed cells
Inputs: table_text (required). Returns: result
debug_tableC
Render and diagnose a table — shows exact character positions.
Produces a detailed report: plain table, annotated position analysis, and drift comparison between border markers and data pipes.
Args: headers: Optional column headers rows: Data rows data: Alias for rows
Returns: Diagnostic report with position annotations
Inputs: headers, rows, data. Returns: result
make_tableA
Render data as a table.
Args: headers: Optional list of column header strings rows: List of data rows, each a list of strings data: Alias for rows -- pass data here if you prefer (cannot use both) fmt: "grid" (default) for ASCII grid, "box" for Unicode box-drawing, "pipe" for Markdown pipe table, "safe" for char-count padding style: Table style (for grid fmt). One of: mysql, separated, compact, gfm, reddit, rounded, rst, box, unicode, dots auto_format: Auto-detect numeric columns (right-align) and center headers safe_width: Count zero-width combining marks as width 1 (for Discord/browsers)
Returns: Formatted table as a Markdown code block (grid/box/safe) or raw pipe table.
Inputs: headers, rows, data, fmt, +3 more. Returns: result
make_table_from_csvA
Parse a CSV/TSV string and render as a table.
Args: csv_text: Raw CSV-formatted text delimiter: Field delimiter (default: comma). Use '\t' for TSV. has_header: If True (default), first row is treated as column headers fmt: "grid" (default), "box", "safe", or "pipe" style: Table style (for grid fmt) auto_format: Auto-detect numeric columns
Returns: Formatted table.
Inputs: csv_text (required), delimiter, has_header, fmt, +2 more. Returns: result
make_table_from_jsonA
Parse a JSON array and render as a table.
Accepts either:
A 2D array: [["Name", "Value"], ["alpha", "1"], ...]
An object with "headers" and "rows" keys: {"headers":["Name"], "rows":[["alpha"]]}
Args: json_data: JSON string has_header: If True (default), first row is treated as column headers fmt: "grid" (default), "box", "safe", or "pipe" style: Table style (for grid fmt) auto_format: Auto-detect numeric columns
Returns: Formatted table.
Inputs: json_data (required), has_header, fmt, style, +1 more. Returns: result
make_table_previewA
Print a preview/example table with sample data.
Args: style: "thai" (default) -- example with Thai/Pali characters "simple" -- plain English example fmt: "grid" (default), "box", "pipe", or "safe" table_style: Table style for grid fmt (mysql, separated, etc.)
Returns: Formatted example table.
Inputs: style, fmt, table_style. Returns: result
validate_table_textA
Validate structural integrity of a table (box/grid/pipe).
Auto-detects format, then checks:
Border/data line alternation
Marker positions (+, ┬, etc.) are consistent
Column count is stable across rows
First and last lines are correct border type
Args: table_text: Raw table text (box, grid, or pipe format)
Returns: Validation report with any structural issues
Inputs: table_text (required). Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 7 tools
Each tool has a clearly distinct purpose: analysis, debugging, creation from various inputs, preview, and validation. Overlap is minimal, and agents can easily select the right tool.
All tool names follow a consistent verb_noun pattern using snake_case, making the set predictable and easy to navigate.
Seven tools is within the ideal range (3-15) and each tool contributes meaningfully to the server's table-focused scope without being excessive.
The tool set covers the full lifecycle: creation from raw data, CSV, JSON, preview, analysis, debugging, and validation. No obvious gaps for the intended domain.
Maintenance
Related MCP Connectors
MCP server for tabletopsimulator documentation, generated by doc2mcp.
An MCP server that measures MCP client behaviour and converts EBCDIC to ASCII, which nobody needs.
Bar-first MCP server for Tabula chart authoring, PNG rendering, and editor handoff.
MCP server for progressive tool usage at any scale (see https://klavis.ai)
Related MCP Servers
- MIT
- AlicenseNot gradedqualityDmaintenanceAn MCP server that provides tools for analyzing, linting, formatting, and generating Markdown content. It enables users to programmatically manage Markdown files through features like table of contents generation, statistics calculation, and JSON-to-table conversion.53 npm1MIT
- FlicenseNot gradedqualityDmaintenanceAn MCP server that enables AI agents to create beautiful ASCII diagrams using Unicode box-drawing characters, with support for stateful canvas operations, multiple shape types, and style customization.2-
- AlicenseAqualityDmaintenanceAn MCP server that provides utility tools for markdown processing, including ADF-to-markdown conversion, table formatting, and table of contents management.7MIT



