Configuration
wrangler.toml (the whole file)
name = "plot-mcp-worker"
main = "src/index.ts"
compatibility_date = "2026-04-22"
workers_dev = true
[[routes]]
pattern = "your-worker.your-domain.com/*"
zone_name = "your-domain.com"
[[kv_namespaces]]
binding = "SHORT_LINKS"
id = "YOUR_KV_NAMESPACE_ID"
preview_id = "YOUR_KV_PREVIEW_NAMESPACE_ID"
[build]
command = ""
[[rules]]
type = "Data"
globs = ["**/*.ttf"]
fallthrough = true
KV namespace SHORT_LINKS
Binding name SHORT_LINKS. Three uses:
- Short link records — key
short:{8-char-token}, JSON value{path, payload}, TTL 30 days - Fonts (critical) — key
font:arial-unicode-cn-gb2312(TTF bytes), keyfont:arial-sans(TTF bytes), no TTL - Anything else? — no, those are the only two namespaces referenced in
src/index.tsandsrc/render.ts
Font upload (one-time setup)
loadFonts in src/render.ts L79-97 fetches both fonts from KV on first PNG render. If either is missing, it throws No CJK font loaded from KV (...). The fonts must be uploaded as raw arrayBuffer:
wrangler kv:key put --binding=SHORT_LINKS "font:arial-unicode-cn-gb2312" --path=./fonts/ArialUnicodeCN.ttf
wrangler kv:key put --binding=SHORT_LINKS "font:arial-sans" --path=./fonts/ArialSans.ttf
The first font (CJK) is also parsed with opentype.js and used by pathifyCjkText to convert CJK glyphs and math unicode (π, ², ³, ∫, √, etc.) to SVG paths before resvg renders them. Without this, Chinese labels and math symbols render as □.
The [[rules]] for .ttf
Wrangler's default behavior tries to bundle TTF files into the worker script, which fails for large fonts. The rule { type = "Data", globs = ["**/*.ttf"], fallthrough = true } tells wrangler: treat .ttf files as data (separate asset) and fall through to the next matching rule. This is what lets the fonts live in KV instead of being inlined into the worker bundle.
Constants (from src/constants.ts)
| Constant | Value | Used for |
|---|---|---|
SERVER_NAME | "plot-mcp-worker" | health/init response |
SERVER_VERSION | "0.4.14" | health/init response (differs from package.json) |
SHORT_LINK_PATH_PREFIX | "/s/" | Short URL path prefix |
SHORT_LINK_TOKEN_LENGTH | 8 | Token length |
SHORT_LINK_TTL_SECONDS | 2592000 (30 days) | KV TTL for short link records |
MIN_POINTS / MAX_POINTS | 10 / 20000 | Series point count clamp |
DEFAULT_POINTS | 1000 | When caller doesn't specify |
MAX_EXPR_LENGTH | 400 | Truncate math expressions |
MAX_TITLE_LENGTH | 120 | Truncate titles |
MAX_LABEL_LENGTH | 80 | Truncate labels |
MAX_SERIES | 12 | Max series per plot |
MAX_FORCE_ITEMS | 16 | Max forces per body |
MAX_FORCE_BODIES | 8 | Max bodies in one scene |
MAX_CIRCUIT_COMPONENTS | 24 | Max components per circuit |
MAX_3D_SURFACES | 6 | Max surfaces in 3D scene |
DEFAULT_WIDTH / DEFAULT_HEIGHT | 1200 / 720 | SVG/PNG canvas size |
DEFAULT_FONT_FAMILY | "ArialUnicodeCN" | Used for resvg font lookup |
DEFAULT_PALETTE | 8 colors (blue/red/green/amber/purple/cyan/orange/pink) | Series auto-color when caller omits color |
TypeScript config (tsconfig.json)
{
"compilerOptions": {
"target": "ES2022",
"module": "ES2022",
"moduleResolution": "Bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"types": ["@cloudflare/workers-types"]
},
"include": ["src/**/*.ts"]
}
ES2022 + strict mode. skipLibCheck skips checking @cloudflare/workers-types. Wrangler's Bundler resolution mode means you don't need to declare explicit import paths for the npm dependencies.