Glance MCP

Public MCP lets ChatGPT, Claude, or Cursor create and update Glance widgets. The host is the intelligence layer. Glance is the Home Screen.

Install the connector on glance.cool/mcp. This page is how it works after you connect.

What each side does

  • Your host — Jira, mail, the other apps already connected in ChatGPT or Claude. Glance does not need a Jira connector.
  • Glance — the widget slot, the layout language, ingest, and pinning on iPhone.

That is different from Glance AI in the iOS app. In-app Chat can also wire Glance automations and device sources. Public MCP cannot create Glance automations — the host pushes with ingest instead. Free Glance accounts can connect. Custom ChatGPT connectors usually need Developer Mode on a paid ChatGPT plan. That is not a Glance plan.

Auth

  • MCP — sign in on glance.cool and Allow. The host then calls tools with your OAuth token. Live updates use the ingest tool. Do not curl the ingest URL from the host.
  • Write key HTTP — for Shortcuts, Zapier, Make, or your backend. Same XOR payload. The key is shown once when the widget is created. Dynamic Ingest.

Typical flow

  1. get_plan — do not assume ChatGPT Plus or Claude Pro is Glance Pro.
  2. list_widgets — if any exist, ask whether to update one or create another.
  3. Design a tree from Layout Language and list_golden_examples.
  4. Save a layout with create_template, or skip that on Pro+ and send inline_ui on ingest.
  5. If new: create_dynamic_widget, then ingest.
  6. Pin on iPhone. Pin to Home Screen.

Ingest from the host

content keys are binding names inside {{ }}, not Jira or GitHub field IDs. Exactly one layout arm.

// Saved layout
{ "feed_id": "<feed uuid>", "template_id": "<template uuid>", "content": { "headline": "Standup in 10 min" } }

// UI on Demand (Pro+)
{ "feed_id": "<feed uuid>", "inline_ui": { "tree": { … }, "widget_size": "medium" }, "content": { "headline": "Standup in 10 min" } }

Never send template_id with inline_ui or a top-level tree. If get_plan.capabilities.ui_on_demand is false, only template_id. Details and the HTTP shape are on Dynamic Ingest · UI on Demand.

Tools

Public MCP is a subset. Automations, integration OAuth, and device permissions stay in the iOS app / Glance AI.

ToolRole
get_planLive quotas and capabilities. Call before promising UI on Demand or extra layouts.
list_widgetsExisting widgets. Ask create vs update. Do not silently duplicate.
create_dynamic_widgetNew widget + feed. Returns write_key once, for Shortcuts / HTTP only.
get_widget_statusLast ingest, live layout, uiMode. Never returns a write key.
list_templates / get_templateSaved layouts. get_template returns one tree.
validate_templateOptional. Structural errors block save. Design warnings do not.
create_template / update_templateSave or revise a layout.
list_golden_examplesReference trees before designing a new one.
ingestPush live content. OAuth only. XOR template_id or inline_ui.
delete_widgetPermanent. Confirm first.

Plans

agent_messages_per_day counts in-app Glance AI only, not ChatGPT or Claude tokens. UI on Demand is Pro and Power. Call get_plan rather than guessing. The live numbers sit on Features.

Design skill

Same file the host can read at glance://skills/design. MCP is the tools. This skill is how the host should compose the widget. Install from glance.cool/mcp: SKILL.md, zip, or npx skills add https://glance.cool/skills/glance-design/SKILL.md.

Glance Widget Design Skill

You design iOS home screen widgets that feel native, calm, and glanceable — like Apple built them. This skill covers visual design and composition only. Workflow, tools, integrations, and sizing math live in the main agent skill.

Diversity over templates: Every widget should fit its data and the user's intent. These are principles and patterns — not a single layout to copy. Vary structure, density, and emphasis. Never force one recipe when another fits better.


Design north star

Widgets should feel like Apple system UI: clear hierarchy, generous whitespace, restrained color, SF typography. A user glancing at their home screen should read the widget in under two seconds.

TraitWhat it means in practice
GlanceableOne clear takeaway — a number, status, or headline
NativeSystem fonts, semantic colors, no "web app" density
CalmMostly neutral surfaces; color carries meaning, not decoration
IntentionalEvery element earns its space — if it doesn't help, remove it

Color — Apple-native default, user-guided override

Default (no user color preference)

Think Settings / Stocks / Weather — not marketing landing pages.

RoleGuidance
BackgroundOmit background on root for system adaptive fill, or #FFFFFF / #F2F2F7 (light) — never loud gradients unless the user asks
Primary text#000000 or omit color (system primary)
Secondary / labels#8E8E93 (iOS secondary label) — captions, timestamps, units
Tertiary / hints#AEAEB2 — de-emphasized metadata only
AccentOne semantic accent per widget — e.g. #007AFF (system blue) for links/active, #34C759 success, #FF9500 warning, #FF3B30 alert
Progress / fillsMuted track #E5E5EA, fill = single accent

Rules: - Never use more than one accent hue unless the user requests a colorful or branded look. - Never fill large areas with saturated color — accents belong on small elements (badge, progress fill, status dot, one headline word). - Prefer opacity and weight over more colors to create hierarchy.

iOS color format (critical on device)

The iOS renderer only parses 6-digit hex (#RRGGBB). Values like #FFFFFFCC or #FFFFFF40 are ignored and fall back to system .primary (often black on light widgets).

  • Use solid 6-digit hex for every color, background, backgroundColor, trackColor, fillColor.
  • For muted/secondary text on dark or gradient backgrounds, pick a lighter solid tint (e.g. #FFE8F5 on purple gradients) — not alpha suffixes.
  • On colorful widgets, desaturated label colors still beat 8-char hex.

When the user gives color direction

Follow the user. If they say "dark purple theme", "brand pink #E91E8C", or "match my logo colors" — apply their palette to backgrounds, accents, and text while keeping hierarchy and readability. Still use muted variants for labels (#8E8E93 or a desaturated version of their accent).

If they share no preference, use the Apple-native defaults above.


Typography

Use SF Pro (sf-pro or omit fontFamily). Reserve sf-rounded for playful/countdown widgets; sf-mono for code/GitHub hashes only.

RolefontSizefontWeightcolor
Hero value24–32bold or heavyprimary
Section title15–17semiboldprimary
Body / detail13–15regular or mediumprimary or secondary
Caption / label10–12regular or medium#8E8E93
Unit / suffix11–13mediumsecondary — on stat via suffix

Limits: At most 3 distinct font sizes per widget. At most 2 weights in active use (e.g. semibold + regular).

Always set maxLines: 1 on titles and hero lines in small and medium widgets. Use maxLines: 2 sparingly on large only when content demands it.


Spacing rhythm

Pick one rhythm and stick to it for the whole tree:

TokenUse
8 ptTight gaps inside a row (icon + label)
12 ptRoot padding, default spacing within sections
16 ptBetween major sections on large widgets

Root container: `padding: 12` minimum (16 for airy large layouts). Never mix 6 / 10 / 14 randomly.

Use spacer with flex: 1 to push footer elements (badge, timestamp) to the bottom on large — don't stack everything at the top.


Visual hierarchy — the one-hero rule

Every widget needs one focal point:

SizeTypical hero
smallOne stat value, one large number text, or one avatar + short label
mediumHero left or top + supporting detail opposite/below
largeHero row + 2–4 supporting metrics or a content block

Everything else is supporting — smaller, lighter color, fewer lines.

Do not give equal visual weight to five text lines. If everything is bold and 16 pt, nothing is important.


Static vs dynamic bindings

Only {{variable_name}} becomes a content field (upload form, automation ingest, bindings_required).

Use caseTemplate syntaxIn derived schema?
Live data (username, KPI value, event title)"binding": "{{username}}"Yes
Fixed section label ("Profile views today")"binding": "Profile views today"No
Fixed metric name under a ring ("Revenue")"binding": "Revenue"No
Decorative brand icon (design constant)"binding": "https://…/icon.png" on imageNo
SF Symbol"binding": "bag.fill" on iconNo
Progress-dependent caption"binding": "{{overall_goal_caption}}"Yes

Rule: If the copy or asset never changes per refresh, use a plain literal — not {{}}. This keeps the upload flow clean and matches how the goldens are authored.

Static images on device: use HTTPS PNG/JPEG URLs. Local paths like /brand-icons/… only work in React preview.


Golden reference library

Six device-approved examples live in packages/sdk/goldens/. They are the quality bar — adapt their structure to the user's data; never paste one verbatim with wrong bindings.

Before designing: call list_golden_examples (filter by widget_size or fetch one with example_id).

IDSizePatternWhen to adapt
s1-glance-kpismallGradient + username + 2 stacked KPI stats + static brand iconSocial/account KPIs, branded small metrics
s2-glance-mediasmallWhite card: static section label → title → centered thumbnail → captionLatest post/video/article thumbnails
m1-split-stripmediumLeft: static title stack · Right: hero statSingle headline metric strips (monitoring, uptime)
m2-multi-sourcemediumLeft motion panel + right spend card + calendar event rowsMulti-integration dashboards (device + cloud)
l1-app-performancelargeDark 2×2 KPI rings (z-stack + circular_progress) + quarterly progress_barCustom business metrics with goal progress
l2-outfit-of-the-daylargeGradient + hero image + shoppable item rows (href + icon)Creator commerce, product lists, playful layouts

Golden techniques worth copying

  • S1: gradient root; static caption literals above dynamic stat values; trailing brand image with static URL
  • S2: explicit spacer gaps between title/image/caption; maxLines on all text; white #FFFFFF root background
  • M1: horizontal split with flex: 1 text column + trailing hero stat (valueFontSize: 40)
  • M2: nested gray cards (#F2F2F7); color accent bars beside calendar rows; formatted strings in text not stat
  • L1: ring container 82×82 with circular_progress size 70, lineWidth 5 (prevents stroke clip); value text centered in z-stack; overall_goal_caption stays dynamic
  • L2: gradient with spacing as gap; fillContainer hero image; href on shop tap targets; sf-rounded for playful headers

Size patterns (adapt — do not copy blindly)

Prefer picking a golden reference above, then adapt. These ASCII sketches are fallbacks when no golden fits:

Small (170×170) — "one glance"

Best for: single KPI, countdown, status, one image thumbnail.

vertical container, padding 12, spacing 8
  → caption text (12pt, secondary, maxLines 1)     // label
  → stat OR large text (hero, 26–30pt)             // THE number/word
  → optional: badge OR relative_time (11pt)        // context

Avoid: horizontal rows of 3+ items, multiple stats, long paragraphs.

Medium (364×170) — "headline strip"

Best for: integration dashboard, social snapshot, calendar next event.

Pattern A — split row:

vertical, padding 12
  → horizontal row, spacing 12, alignment center
      → left column (vertical): title + subtitle
      → right: stat OR circular_progress OR avatar/image

Pattern B — title + detail row:

vertical, padding 12, spacing 8
  → title text (15pt semibold, maxLines 1)
  → horizontal row: 2–3 compact stats OR image + text pair

Avoid: more than one horizontal band; cramming 4 columns.

Large (364×382) — "dashboard card"

Best for: multi-metric boards, feed digests, rich integration views.

vertical, padding 12–16, spacing 12
  → header row (horizontal): title + optional badge
  → main content: 2–3 stats in a row OR 2×2 grid of images/metrics
  → spacer (flex 1)                                    // optional
  → footer: progress_bar OR relative_time OR caption   // optional

Use divider between header and body only when it clarifies — not by default.


Component combinations that look polished

ComboWhen to use
stat + caption text aboveKPI widgets (followers, revenue, streak)
avatar + vertical text stack in horizontal rowSocial / account identity
image (cornerRadius 8) + text besideLatest post, thumbnail + caption
badge (subtle bg #E5E5EA, text primary)Status chips — "Live", "3 new"
progress_bar (height 6–8, muted track)Goal completion — one per widget
z-stack + full-bleed image + text with light colorEvent spotlight — use sparingly
status_dot + textHealth / server / pipeline status
relative_time or date in caption style"Updated 2m ago" footer

`stat` tips: Use valueFontSize 26–32 for hero stats; labelFontSize 11; suffix for units (K, %, °). Prefer ig_followers_fmt style formatted strings in text when the integration provides them.


Layout polish

  • Alignment: leading for LTR text blocks; center for single hero in small; trailing for meta (time, badge) in header rows — but see reload button rule below.
  • Reload button: Glance overlays a reload control in the top-right (~40×40 pt). Never put hero values or must-read text there; prefer leading clusters for top-band KPIs (label + value side-by-side).
  • Images: Always set explicit width / height; cornerRadius: 8–12 for photos; contentMode: "fill" for thumbnails.
  • Nested cards: Inner container with background: "#F2F2F7", cornerRadius: 10, padding: 10 — sparingly, one level deep max.
  • Full bleed: Only gradient root for dramatic widgets — and only when user wants flair or data suits it (event poster, media highlight).

Anti-patterns — never ship these

Anti-patternWhy it fails
5+ text nodes all 14 pt regularNo hierarchy — wallpaper of words
Rainbow hex on every elementFeels non-native, noisy
Horizontal row of 4 images on smallGuaranteed clip / crush
stat for currency ($1,234) or % stringsType errors + ugly fallback
Root padding: 0 or missingCorner clip on home screen
Hero stat / spend in top-trailing cornerHidden under reload button overlay
gap, borderRadius, textAlign style keysSilently ignored — use correct keys from main skill
{{}} on fixed labels or decorative iconsForces upload fields; use static literals instead
8-char hex colors (#RRGGBBAA)iOS ignores them — text falls back to black primary

Design process (before you write JSON)

  1. Clarify intent — glance KPI? digest? status? media?
  2. Pick `widget_size` — smallest size that fits without clutter.
  3. Choose one hero — what is the single takeaway?
  4. `list_golden_examples` — pick the closest golden; call with example_id to load its tree.
  5. Adapt the pattern — swap bindings for real integration fields; static labels stay literal.
  6. Assign typography — hero / body / caption sizes from table.
  7. Apply color — native defaults unless user specified palette; 6-digit hex only.
  8. Run sizing math — main skill algorithm; shrink before dropping the hero.
  9. (Optional) `validate_template` — max 2 calls per design for early feedback; then create_template. Structure must pass; design warnings do not block save.
  10. Preview pause — describe what the user will see; invite tweaks.

Pre-submit checklist

Before create_template, confirm mentally (server structure is the save gate; padding/overflow are warnings):

  • [ ] One clear hero element
  • [ ] ≤ 3 font sizes, ≤ 2 active weights
  • [ ] Root padding ≥ 12 (guideline — ROOT_PADDING_LOW will not block save)
  • [ ] Labels use secondary color (#8E8E93 or user-muted variant)
  • [ ] At most one accent color (unless user asked for more)
  • [ ] maxLines set on text that must not wrap
  • [ ] Top-trailing corner clear of hero values (reload button overlay)
  • [ ] Static labels/icons use plain literals (no {{}} unless value changes per refresh)
  • [ ] All colors are 6-digit #RRGGBB (no alpha suffix)
  • [ ] Layout suits the data — not a generic placeholder grid

Talking to the user about design

  • Describe the visual hierarchy in plain language: *"Large follower count up top, latest post caption below in gray."*
  • Offer one alternative when useful: *"I can also do a side-by-side layout with your profile photo — prefer that?"*
  • If the user says it looks plain, add structure (nested card, badge, progress) or typography contrast — not more random colors.