@typeroll/mcp-server 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -305,6 +305,32 @@ read_page page_id=...
305
305
  update_page page_id=... patch={ html_content: "<...><img src='{cdn_url}' alt='…' /></...>" }
306
306
  ```
307
307
 
308
+ ### "Stop an image over-fetching a too-large variant"
309
+
310
+ When an image renders much narrower than the viewport (a container-constrained
311
+ hero, a sidebar thumbnail), the default `<picture sizes>` of
312
+ `(max-width: 768px) 100vw, 800px` makes the browser pull a wider srcset variant
313
+ than it needs — Lighthouse flags it as wasted bytes. Three levers, narrowest
314
+ wins:
315
+
316
+ ```
317
+ # 1. Per-image: put a real `sizes` on the <img>. Survives the transform verbatim.
318
+ update_page page_id=... patch={ html_content:
319
+ "<img src='{cdn_url}' alt='…' sizes='(max-width: 640px) 360px, 560px' />" }
320
+
321
+ # 2. Per-page default (applies to every image on the page that has no own sizes):
322
+ update_page page_id=... patch={ image_sizes_default: "(max-width: 640px) 360px, 560px" }
323
+
324
+ # 3. Site-wide default (fallback under the page default):
325
+ update_site_settings image_sizes_default="(max-width: 640px) 360px, 560px"
326
+ ```
327
+
328
+ Precedence: per-image `sizes` > page `image_sizes_default` >
329
+ site `image_sizes_default` > the generic built-in. To opt a single image out of
330
+ the platform's auto-`<picture>` entirely, hand-write your own `<picture>` with
331
+ custom `<source media=…>` — the transform leaves an existing `<picture>`
332
+ untouched (it no longer re-wraps the inner `<img>`).
333
+
308
334
  ### "Fill missing alt-text across the media library"
309
335
 
310
336
  ```
@@ -90,6 +90,7 @@ export const pageTools = [
90
90
  author: z.string().optional(),
91
91
  language: z.string().optional().describe('BCP-47 tag overriding the site default (e.g. "en" on an otherwise Swedish site).'),
92
92
  template: z.string().optional().describe('Page template id (PageTemplate). Wraps the body in the template tree at render time.'),
93
+ image_sizes_default: z.string().optional().describe('Per-page default `sizes` for responsive images (e.g. "(max-width: 640px) 360px, 560px"). Overrides the site setting; a per-<img> `sizes` attr still wins. Set when this page\'s images render narrower than the generic default so the browser stops over-fetching.'),
93
94
  version: versionParam,
94
95
  },
95
96
  handler: withErrorBoundary(async (args, { client, siteId }) => {
@@ -121,6 +122,7 @@ export const pageTools = [
121
122
  canonical_url: z.string().optional(),
122
123
  noindex: z.boolean().optional(),
123
124
  lastmod_override: z.string().optional().describe('Override the sitemap <lastmod>. Empty string suppresses lastmod for this page entirely.'),
125
+ image_sizes_default: z.string().optional().describe('Per-page default `sizes` for responsive images (e.g. "(max-width: 640px) 360px, 560px"). Overrides the site setting; a per-<img> `sizes` attr still wins. Set when this page\'s images render narrower than the generic default so the browser stops over-fetching the larger variant.'),
124
126
  json_ld: z.string().optional(),
125
127
  schema_type: z.string().optional().describe('Free-form Schema.org type ("Service", "Course", "Product", …) used for auto JSON-LD emission. Use service.* for Service-specific fields.'),
126
128
  service: z
@@ -10,7 +10,7 @@ import { ok, withErrorBoundary } from './helpers.js';
10
10
  export const settingsTools = [
11
11
  {
12
12
  name: 'read_site_settings',
13
- description: "Read every site setting: name, tagline, logo, favicon, colors, fonts, contact info, social links, default SEO suffix, language, robots_txt, plus the scriptable surfaces scripts_head, scripts_body_end, and custom_css.",
13
+ description: "Read every site setting: name, tagline, logo, favicon, colors, fonts, contact info, social links, default SEO suffix, language, robots_txt, image_sizes_default, plus the scriptable surfaces scripts_head, scripts_body_end, and custom_css.",
14
14
  handler: withErrorBoundary(async (_args, { client, siteId }) => {
15
15
  const res = await client.get(siteId, 'settings');
16
16
  return ok(res);
@@ -32,6 +32,7 @@ export const settingsTools = [
32
32
  default_seo_suffix: z.string().optional(),
33
33
  language: z.string().optional().describe('BCP-47 tag (e.g. "en", "sv", "en-GB"). Drives <html lang> on the rendered site.'),
34
34
  robots_txt: z.string().optional(),
35
+ image_sizes_default: z.string().optional().describe('Site-wide default `sizes` attribute for responsive-image <picture> output, e.g. "(max-width: 640px) 360px, 560px". Tells the browser how wide images actually render so it stops over-fetching the larger srcset variant. A page can override via its own image_sizes_default; a per-<img> `sizes` attribute wins over both. Leave unset for the generic "(max-width: 768px) 100vw, 800px".'),
35
36
  // Scriptable surfaces. Trusted because the caller has an API key.
36
37
  scripts_head: z.string().optional().describe('Raw HTML injected into <head> on every page. Use for analytics, fonts, third-party CSS links.'),
37
38
  scripts_body_end: z.string().optional().describe('Raw HTML injected just before </body> on every page. Use for chat widgets, deferred analytics.'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typeroll/mcp-server",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Model Context Protocol server for the Typeroll public API. Use with Claude Code or any MCP-compatible client to manage a Typeroll site.",
5
5
  "license": "MIT",
6
6
  "repository": {