内容

Python 和 AI 代理的零依赖图表库。支持 SVG 和 PNG,15 种图表类型,一行代码即可启动的 MCP 服务器,以及 Claude 技能。
[](https://codecov.io/github/marzukia/charted) [](https://github.com/marzukia/charted/actions/workflows/ci.yml)
## 快速入门
```sh
uv add charted
```
或者使用 pip:
```sh
pip install charted
```
```python
from charted import BarChart
chart = BarChart(
title="按季度销售",
data=[120, 180, 210, 150],
labels=["Q1", "Q2", "Q3", "Q4"],
)
chart.save("chart.svg")
chart.save("chart.png") # PNG 导出(需要 cairosvg)
```
这就是整个流程:传递一个数字列表,得到一个图像。不需要 numpy,不需要 pandas,也不需要配置文件。
> **核心原则:** charted 本身具有零运行时依赖。PNG 导出和 MCP 服务器支持是可选的额外功能,它们会引入自己的依赖,而基础库保持纯 Python。
## 图表库
每种图表类型都已渲染。下面的每个图像都是由 charted 本身生成的,使用的示例脚本;[快速游览](#quick-tour) 部分展示了每张图表背后的代码。
| | | |
|---|---|---|
| **条形图**  | **柱形图**  | **折线图**  |
| **散点图**  | **饼图**  | **面积图**  |
| **雷达图**  | **箱线图**  | **直方图**  |
| **热力图**  | **甘特图**  | **气泡图**  |
| **组合图**  | **极坐标面积图**  | |
桑基图也支持;请参阅 [快速游览](#quick-tour) 部分,了解流程和漏斗示例。
## 集成
使用 `uvx` 运行 MCP 服务器,无需安装:
```sh
uvx --from charted[mcp] charted-mcp
```
这会将带有 MCP 额外功能的 charted 提取到一个临时环境中,并在标准输入/输出上启动服务器,以便代理可以生成图表,而无需您将 charted 添加到项目或虚拟环境中。
### 客户端配置
| 客户端 | 设置 |
|--------|-------|
| Claude Code | `claude mcp add charted -- uvx --from charted[mcp] charted-mcp` |
| Cursor, Cline, 其他客户端 | 将下面的 JSON 添加到客户端的 MCP 服务器配置文件中 |
```json
{
"mcpServers": {
"charted": {
"command": "uvx",
"args": ["--from", "charted[mcp]", "charted-mcp"]
}
}
}
```
服务器公开了 `create_chart`、`list_chart_types`、`list_themes` 和 `chart_from_csv`。请参阅下面的 [MCP 服务器](#mcp-server-ai-agent-integration) 部分,了解工具详细信息和 `pip install` 路径。
### Claude 技能
通过一行命令安装图表技能:
```sh
claude skill install charted
```
### 图表库
[快速游览](#quick-tour) 部分渲染了每种图表类型,并附有生成它们的代码。相同的示例位于 `docs/examples/` 中。
## 为什么选择 Charted?
- **零运行时依赖**:纯 Python,无需 numpy/pandas
- **15 种图表类型**:条形图、柱形图、折线图、散点图、饼图、面积图、雷达图、箱线图、直方图、热力图、甘特图、气泡图、组合图、极坐标面积图、桑基图
- **多系列支持**:堆叠、并排、分组布局
- **负值处理**:正确的零基线计算
- **SVG 和 PNG 输出**:原生 SVG,PNG 通过可选的 `cairosvg`(`pip install charted[png]`)
- **主题系统**:3 个内置预设 + 自定义主题组合
- **每系列样式**:使用 SeriesStyle 生成器进行精细控制
- **数据加载**:内置 CSV/JSON 解析器
- **Markdown 导出**:生成可嵌入的 Markdown 片段
- **CLI 包含**:无需编写 Python 代码即可创建图表
- **Jupyter 就绪**:图表自动内联渲染
- **基础图表类**:用于动态图表类型选择的统一 API
## 快速游览
每种图表类型都共享相同的简单接口:传递数据、标签、尺寸和标题:
```python
from charted.charts import BarChart, LineChart, PieChart
# 条形图:带有负值的单系列
BarChart(
title="按地区利润/亏损(百万美元)",
data=[-12, 34, -8, 52, -5, 28, 41, -19, 15, 60],
labels=["北", "南", "东", "西", "中央", "太平洋", "大西洋", "山区", "平原", "大都会"],
width=700, height=500,
).save("bar.svg")
```

```python
# 条形图:多系列并排
BarChart(
title="按季度收入 vs 支出(千美元)",
data=[[120, -45, 180, -30, 210, -60], [-80, -20, -95, -15, -110, -25]],
labels=["Q1 Prod", "Q1 Ops", "Q2 Prod", "Q2 Ops", "Q3 Prod", "Q3 Ops"],
width=700, height=500,
).save("bar_multi.svg")
```

```python
# 条形图:堆叠
BarChart(
title="按部门预算(千美元)",
data=[[100, -50, 120], [80, 60, -40]],
labels=["Q1", "Q2", "Q3"],
series_names=["收入", "支出"],
x_stacked=True, width=700, height=400,
).save("bar_stacked.svg")
```

```python
# 条形图:带有负值的并排
BarChart(
title="按季度收入 vs 支出(千美元)",
data=[[120, 180, 210], [-80, -95, -110]],
labels=["Q1", "Q2", "Q3"],
series_names=["收入", "支出"],
width=700, height=400,
).save("bar_sidebyside.svg")
```

---
```python
# 折线图:多系列信号数据
import math
from charted.charts import LineChart
n = 20
LineChart(
title="信号分析:原始 vs 过滤 vs 基线",
data=[
[math.sin(i * 0.5) * 30 + (i % 7 - 3) * 5 for i in range(n)],
[math.sin(i * 0.5) * 25 for i in range(n)],
[math.sin(i * 0.5) * 10 - 5 for i in range(n)],
],
labels=[str(i) for i in range(n)],
width=700, height=400,
).save("line.svg")
```

```python
# 折线图:XY 模式,温度异常数据
years = list(range(1990, 2010))
anomalies = [-15, -5, 10, 20, 5, 25, 15, 30, 10, 20, 40, 25, 45, 30, 50, 35, 60, 55, 45, 70]
baseline = [round(5 + 2 * math.sin(i * 0.4) + i * 0.5, 1) for i in range(len(years))]
LineChart(
title="温度异常 vs 5 年滚动基线(1990-2009)",
data=[anomalies, baseline],
x_data=years,
labels=[str(y) for y in years],
width=700, height=400,
).save("xy_line.svg")
```

```python
# 折线图:单系列
LineChart(
title="月活跃用户(千)",
data=[[42, 48, 55, 61, 58, 70, 80, 78, 85, 92, 88, 100]],
labels=["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
series_names=["MAU"], width=700, height=400,
).save("line_single.svg")
```

---
```python
# 折线图:对数刻度(可选)用于跨数量级的数据。
# 传递 y_scale="log"(或 x_scale="log");LogScale 实例也有效。
LineChart(
title="请求/秒(对数刻度)",
data=[[1, 8, 60, 450, 3200, 25000]],
labels=["t0", "t1", "t2", "t3", "t4", "t5"],
series_names=["rps"],
y_scale="log",
width=700, height=400,
).save("line_log.svg")
```

---
```python
# 散点图:多系列聚类分析
import random
from charted.charts import ScatterChart
random.seed(42)
ca_x = [30 + random.gauss(0, 8) for _ in range(20)]
ca_y = [40 + random.gauss(0, 8) for _ in range(20)]
cb_x = [70 + random.gauss(0, 10) for _ in range(20)]
cb_y = [20 + random.gauss(0, 10) for _ in range(20)]
ScatterChart(
title="聚类分析:两个不同群体",
x_data=[ca_x, cb_x], y_data=[ca_y, cb_y],
series_names=["A 组", "B 组"],
width=700, height=400,
).save("scatter.svg")
```

```python
# 散点图:单系列:单系列二次曲线
random.seed(1)
x_vals = [i for i in range(5, 95, 5)]
y_vals = [round(10 + (v - 50) ** 2 / 50 + random.gauss(0, 4), 1) for v in x_vals]
ScatterChart(
title="U 型响应曲线:信号 vs 输入",
x_data=x_vals, y_data=y_vals,
series_names=["观测结果"],
width=700, height=400,
).save("scatter_single.svg")
```

---
```python
# 饼图:基本
from charted.charts import PieChart
PieChart(
title="产品线市场份额",
data=[35, 28, 18, 12, 7],
labels=["产品 A", "产品 B", "产品 C", "产品 D", "其他"],
width=600, height=500,
).save("pie.svg")
```

```python
# 饼图:甜甜圈模式
PieChart(
title="操作系统市场份额",
data=[72, 15, 8, 5],
labels=["Windows", "macOS", "Linux", "其他"],
inner_radius=0.5, width=600, height=500,
).save("pie_doughnut.svg")
```

---
```python
# 雷达图:多系列
from charted.charts import RadarChart
RadarChart(
title="玩家技能比较",
data=[[85, 90, 75, 88, 92], [70, 85, 90, 75, 80]],
labels=["速度", "力量", "防御", "技巧", "耐力"],
width=600, height=500,
).save("radar.svg")
```

```python
# 雷达图:单系列
RadarChart(
title="角色属性",
data=[20, 35, 30, 45, 25],
labels=["速度", "力量", "耐力", "防御", "技能"],
width=600, height=500,
).save("radar_multi.svg")
```

---
```python
# 面积图:CPU 温度(24 小时)
from charted.charts import AreaChart
temps = [42 + 10 * math.sin(i * 0.6) + (hash(str(i)) % 5 - 2) * 1.5 for i in range(24)]
AreaChart(
title="CPU 温度(°C):24 小时周期",
data=[round(t, 1) for t in temps],
labels=[f"{h}:00" for h in range(24)],
width=700, height=400,
).save("area.svg")
```

```python
# 面积图:多系列收入按渠道划分
AreaChart(
title="多系列面积图:按渠道划分的收入",
data=[[30, 50, 45, 60, 70, 80, 65, 55], [20, 35, 30, 45, 50, 55, 40, 35]],
labels=["Q1", "Q2", "Q3", "Q4", "Q5", "Q6", "Q7", "Q8"],
series_names=["在线", "零售"],
width=700, height=400,
).save("area_multi.svg")
```

---
```python
# 箱线图:分布四分位数与异常值
import random
from charted.charts import BoxPlot
random.seed(42)
box_a = [round(random.gauss(50, 10), 1) for _ in range(50)] + [95, 5, 102]
box_b = [round(random.gauss(70, 15), 1) for _ in range(50)] + [120, 30, 130]
box_c = [round(random.gauss(30, 8), 1) for _ in range(50)] + [55, 8, 60]
BoxPlot(
title="测试成绩按组别:含异常值",
data=[box_a, box_b, box_c],
labels=["A 组", "B 组", "C 组"],
width=700, height=400,
).save("boxplot.svg")
```

---
```python
# 直方图:正态分布(钟形曲线)
import random
from charted.charts import Histogram
random.seed(42)
scores = [random.gauss(50, 15) for _ in range(500)]
Histogram(
title="考试成绩:正态分布(500 名学生,10 个箱)",
data=scores,
bins=10, width=700, height=400,
).save("histogram.svg")
```

---
```python
# 热力图:每月温度矩阵
from charted.charts import HeatmapChart
HeatmapChart(
title="平均气温(°C):每月按城市",
data=[
[35, 36, 38, 40, 43, 45, 47, 46, 44, 41, 38, 36],
[22, 24, 28, 32, 36, 40, 42, 41, 38, 33, 27, 23],
[15, 18, 22, 27, 32, 37, 40, 39, 35, 29, 22, 17],
[5, 8, 14, 20, 26, 32, 35, 34, 29, 22, 14, 7],
[-2, 2, 10, 18, 25, 31, 34, 33, 27, 19, 10, 3],
],
x_labels=["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
y_labels=["迪拜", "悉尼", "东京", "柏林", "莫斯科"],
width=700, height=450,
low_color="#21639e", high_color="#f97316",
show_values=True, value_format=".0f",
).save("heatmap.svg")
```

```python
# 甘特图:软件项目时间线
from charted.charts import GanttChart
GanttChart(
title="软件项目时间线:2026 年第一季度",
data=[(0, 2), (1, 4), (3, 6), (5, 8), (6, 9)],
labels=["设计", "前端", "后端", "测试", "部署"],
width=700, height=400,
dependencies=[(0, 1), (0, 2), (2, 3), (3, 4)],
show_today_line=True,
x_position=4.5,
).save("gantt.svg")
```

```python
# Sankey:流程图(d3-sankey 布局)
from charted.charts import SankeyChart
SankeyChart(
title="电力从发电到消费",
nodes=["煤炭", "天然气", "太阳能", "电网", "家庭", "工业", "出口"],
links=[
("煤炭", "电网", 45), ("天然气", "电网", 30), ("太阳能", "电网", 15),
("电网", "家庭", 40), ("电网", "工业", 35), ("电网", "出口", 15),
],
width=800, height=500,
).save("sankey.svg")
```
节点按列放置以对齐,然后在几个迭代中放松,以便连接的节点对齐并尽可能少地交叉。链接厚度与流量值成比例;每个节点堆叠的宽度总和等于节点的高度。将链接表示为 `(source, target, value)` 元组或 `{source, target, value}` 字典;端点可以是节点名称或索引。密集列中的节点标签会分开以保持可读性,而不是重叠。
`对齐` 选项控制节点如何分配到列中:`justify`(默认,如 d3-sankey)将所有汇聚点推到最后一列;`left` 保留每个节点在其深度;`right` 按距汇聚点距离对齐;`center` 是 `left`,并将源固定在第一列。
**对于漏斗/流失数据,请使用 `alignment="left"`。** 漏斗在不同深度有多个流失点(失败过滤器,未响应,取消等)。在默认 `justify` 下,这些都被拉到一个高而密集的最终列中,这会压扁漏斗形状。`left` 允许每个流失点在其自然阶段终止,因此图表呈现为真正的漏斗阶梯:
# 通道:招聘流程图,左对齐以便退出项位于其深度
SankeyChart(
title="招聘流程",
nodes=[
"已申请", "通过筛选", "未通过筛选",
"已面试", "已拒绝", "已提供录用", "已拒绝录用", "已录用",
],
links=[
("已申请", "通过筛选", 320), ("已申请", "未通过筛选", 680),
("通过筛选", "已面试", 140), ("通过筛选", "已拒绝", 180),
("已面试", "已提供录用", 60), ("已面试", "已拒绝", 80),
("已提供录用", "已录用", 45), ("已提供录用", "已拒绝录用", 15),
],
alignment="left",
width=900, height=400,
).save("funnel.svg")
---
## 主题
三种内置主题(浅色、深色、高对比度)以及自定义主题组合:
```python
from charted import BarChart
# 内置主题
chart = BarChart(data=[120, 180, 210], labels=["第一季度", "第二季度", "第三季度"], theme="light")
chart = BarChart(data=[120, 180, 210], labels=["第一季度", "第二季度", "第三季度"], theme="dark")
chart = BarChart(data=[120, 180, 210], labels=["第一季度", "第二季度", "第三季度"], theme="high-contrast")
```
| 主题 | 预览 |
|-------|---------|
| 浅色 |  |
| 深色 |  |
| 高对比度 |  |
请参阅 [主题文档](docs/guides/theming.md) 以获取自定义调色板、字体覆盖和按系列样式。
---
## 命令行界面用法
无需编写Python即可生成图表:
```sh
# 从CSV文件
python -m charted create bar output.svg --data sales.csv
# 从JSON文件
python -m charted create column chart.svg -d data.json
# 设置标题和尺寸
python -m charted create bar output.svg --data sales.csv \
--title "第三季度销售额" --width 900 --height 400
# 批量处理目录
python -m charted batch input_data/ output_svg/
```
`--title`、`--width` 和 `--height` 参数会覆盖 `--config` 文件中相同的参数值。
**CSV格式(默认):**
第一列是x轴标签。其他列是数据系列。
```csv
季度,收入,支出
第一季度,120,80
第二季度,180,95
第三季度,210,110
```
**宽CSV格式(`--transpose`):**
如果您的CSV文件是横向排列的,每个系列一行,x值跨标题行,请传递 `--transpose` 参数。角单元格将被忽略,其余标题行成为x轴标签,每个后续行是一个以其第一个单元格命名的系列。如果不使用 `--transpose` 参数,此布局将绘制时交换轴,因此该标志是显式的而不是猜测的。
```csv
系列,第一季度,第二季度,第三季度
收入,120,180,210
支出,80,95,110
```
```sh
python -m charted create column out.svg --data wide.csv --transpose
```
**JSON格式:**
```json
{
"labels": ["第一季度", "第二季度", "第三季度"],
"data": [[120, 180, 210], [80, 95, 110]],
"series_names": ["收入", "支出"]
}
```
完整命令行文档:`python -m charted --help`
---
## 数据加载
无需pandas加载CSV/JSON:
```python
from charted import load_csv, load_json, BarChart
# 从CSV文件
x, y, labels = load_csv("sales.csv", x_col="季度", y_col="收入")
chart = BarChart(data=y, labels=x, title=labels[0])
chart.save("sales.svg")
# 从JSON文件
x, y, labels = load_json("data.json")
chart = ColumnChart(data=y, labels=x)
```
---
## Jupyter Notebook
图表自动内联渲染,无需额外设置:
```python
from charted.charts import BarChart
chart = BarChart(
title="季度销售额",
data=[120, 180, 210, 150],
labels=["第一季度", "第二季度", "第三季度", "第四季度"],
)
# 在笔记本单元格中内联渲染
```
---
## Markdown导出
```python
from charted import BarChart
chart = BarChart(data=[120, 180, 210], labels=["第一季度", "第二季度", "第三季度"], title="销售额")
# 使用文件路径
chart.save("docs/sales.svg")
md = chart.to_markdown(path="docs/sales.svg") # 
# 作为内联数据URL
md = chart.to_markdown() # 数据URL嵌入markdown
```
---
## 基础图表类
在运行时动态选择图表类型:
```python
from charted import Chart
chart = Chart(
data=[120, 180, 210],
labels=["第一季度", "第二季度", "第三季度"],
title="销售额",
chart_type="bar", # 或 column, line, scatter, pie, area, boxplot, histogram, heatmap, gantt
)
chart.save("chart.svg")
# 访问所有图表方法
svg = chart.to_svg()
md = chart.to_markdown()
```
---
## 安装
**库(在代码中使用):**
```sh
uv add charted
```
或使用pip:
```sh
pip install charted
```
**命令行界面或MCP服务器(独立工具,无需项目安装):**
```sh
uvx charted ...
# 或
pipx install charted
```
> 注意:`uvx`/`pipx`安装的包在其自己的隔离环境中运行,无法导入到您的项目代码中。当您想在脚本中`import charted`时,请使用`uv add`或`pip install`。
可选额外功能(这些添加依赖项,核心库保持零依赖):
```sh
uv add "charted[png]" # 通过cairosvg导出PNG
uv add "charted[mcp]" # 用于AI代理集成的MCP服务器
uv add "charted[duckdb]" # 从SQL查询生成图表
uv add "charted[dev]" # 包括PNG视觉测试的开发工具
# pip等效命令
pip install 'charted[png]'
pip install 'charted[mcp]'
pip install 'charted[duckdb]'
pip install 'charted[dev]'
```
## PNG导出
直接保存图表为PNG文件:
```python
chart = BarChart(data=[10, 20, 30], labels=["A", "B", "C"])
chart.save("chart.svg") # SVG(无额外依赖)
chart.save("chart.png") # PNG(需要cairosvg)
chart.save("chart.png", scale=3) # PNG,3倍分辨率
```
PNG导出需要`cairosvg`。如果未安装,`save()`会引发一个有用的`ImportError`,并附有安装说明。
---
## MCP服务器(AI代理集成)
Charted包含一个MCP服务器,以便AI代理(Claude Code、Cursor等)可以在不编写Python的情况下生成图表:
```sh
# 独立运行(无需安装步骤,推荐)
uvx --from 'charted[mcp]' charted-mcp
# 或安装额外功能并直接运行
pip install 'charted[mcp]'
charted-mcp
# 注册到Claude Code
claude mcp add charted -- uvx --from 'charted[mcp]' charted-mcp
```
暴露工具:`create_chart`, `list_chart_types`, `list_themes`, `chart_from_csv`。需要`charted[mcp]`额外功能。
`create_chart` 和 `chart_from_csv` 可以接受 `svg`, `html`, `data_url` 或 `png` 的 `output_format`。当 `output_format="png"` 时,工具会返回一个光栅化的PNG图像,以便代理可以在聊天界面中直接显示图表,而不是中继原始SVG标记。`mcp` 额外功能包括 `cairosvg`,因此使用上面的 `uvx` 命令时,PNG输出开箱即用。PNG光栅化需要cairo的系统库;在Debian/Ubuntu上,使用 `apt install libcairo2` 安装它们。
---
## 更多功能
以下是公共API的其他一些部分,上述示例未涵盖:
**自动图表选择。** `auto(data, **kwargs)` 根据数据形状选择图表类型(1D变成条形图或饼图,矩阵变成热力图等),并返回图表实例。`auto_size(data, width, height)` 返回 `(width, height)`,当您不传递显式尺寸时,它会将数据集缩放至该尺寸。
```python
from charted import auto
chart = auto([10, 20, 30], title="销售额")
```
**从字典或DataFrame构建。** `from_dict({"data": ..., "chart_type": ...})` 从配置字典构建图表。`from_dataframe(df)` 获取pandas DataFrame(或普通字典的列),并使用第一个数字列作为数据,索引或第一个字符串列作为标签。
```python
from charted import from_dict, from_dataframe
chart = from_dict({"chart_type": "line", "data": [1, 2, 3]})
chart = from_dataframe(df) # 如果pandas缺失,则回退到普通字典
```
**内联和数据URL嵌入。** `inline_svg(path)` 读取SVG文件作为字符串嵌入HTML或笔记本。`chart_to_data_url(path)` 返回相同的SVG URL编码为 `data:image/svg+xml,...` URI,您可以直接将其放入 `<img>` 标签或markdown图像中。
**保存和恢复图表配置。** `chart.to_config()` 将图表序列化为JSON友好的字典(尺寸、数据、标签、比例、参考线、注释等)。`Chart.from_config(config, **overrides)` 从该字典中重建图表,并将关键字覆盖合并到顶部。
```python
config = chart.to_config()
chart2 = Chart.from_config(config, title="更新的标题")
```
**流畅的样式。** `chart.style(**kwargs)` 应用主题覆盖并返回图表进行链接,因此您可以设置诸如 `background_color` 或 `legend_font_size` 之类的内容,而无需进行构造函数。
```python
chart = BarChart(data=[1, 2, 3]).style(background_color="#fff", legend_font_size=12)
```
**HTML中的悬停提示。** `chart.to_html(tooltips=True)` 附加一个本地SVG `<title>` 到每个数据标记,以便浏览器显示一个内置的悬停提示,无需JavaScript。这仅影响HTML输出;`to_svg()` 和 `save()` 不会更改。
**命名调色板。** `resolve_palette(name)` 将内置调色板名称之一转换为您可以传递为 `colors=` 的十六进制颜色列表。名称位于 `NAMED_PALETTES`:`default`, `viridis`, `ocean`, `categorical`, `rainbow`, `monochrome`, `pastel`, `sunset`, `forest`, `inferno`, 和色盲安全的 `okabe-ito`.
```python
from charted import resolve_palette
chart = BarChart(data=[1, 2, 3], colors=resolve_palette("viridis"))
```
**参考线。** 传递 `reference_lines=[{"value": 50, "axis": "y", "label": "目标"}]` 以绘制水平或垂直线与可选标签。`axis` 为 `"y"` 表示水平线(默认)或 `"x"` 表示垂直线。
**注释。** 传递 `annotations=[...]` 使用 `LineAnnotation`, `BoxAnnotation`, 或 `LabelAnnotation` 在图表上标记线、阴影区域或文本。
```python
from charted import BarChart, LineAnnotation, BoxAnnotation, LabelAnnotation
```
**对数和时间刻度。** 传递 `x_scale=` 或 `y_scale=` 为 `"log"` 表示对数轴,或 `"time"` 表示时间轴(接受日期、datetime或ISO日期字符串作为x值)。默认是 `"linear"`。对数和时间刻度在条形或柱状图的数值轴上被拒绝,因为它们从零基线填充。
```python
LineChart(data=[1, 10, 100, 1000], labels=["a", "b", "c", "d"], y_scale="log")
```
---
## 链接
- [完整文档](https://charted.mrzk.io)
- [配置参考](docs/guides/configuration.md)
- [主题指南](docs/guides/theming.md)
### 字体系统
Charted通过在 `fonts/definitions/` 中使用预定义的字体度量来避免tkinter。生成新的字体定义:
```sh
uv run python charted/commands/create_font_definition.py Helvetica
```
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器