miromiro-mcp 0.8.0 → 0.8.2

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/README.md CHANGED
@@ -9,18 +9,30 @@ Works with Claude (web, desktop, Claude Code), ChatGPT, Cursor, Windsurf, Codex,
9
9
 
10
10
  ## Claude Code plugin
11
11
 
12
- Install as a plugin to get the tools plus three skills that teach Claude when to reach for
13
- each one (`clone-section`, `match-brand`, `extract-assets`):
12
+ Install as a plugin to get the tools plus five skills that teach Claude when to reach for
13
+ each one:
14
+
15
+ - `elementor-section` - any site's section as an Elementor template to import into WordPress
16
+ - `shopify-section` - any site's section as a Shopify theme section (`.liquid`)
17
+ - `clone-section` - a section as Tailwind, HTML+CSS, React or Vue
18
+ - `match-brand` - a site's colors, fonts and design tokens to build in its style
19
+ - `extract-assets` - images, SVG icons, videos, audio and Lottie files
14
20
 
15
21
  ```bash
16
- claude plugin marketplace add anthropics/claude-plugins-community
17
- claude plugin install miromiro@claude-community
22
+ claude plugin marketplace add SoraiaBarroso/miromiro-mcp
23
+ claude plugin install miromiro@miromiro
18
24
  ```
19
25
 
20
26
  The plugin uses the remote server, so there is nothing to install and no key to paste - on
21
27
  first use it opens a one-click MiroMiro sign-in that links a free account (300 credits/month,
22
28
  no card).
23
29
 
30
+ ## Skills for OpenClaw and other agents
31
+
32
+ The same skills live in [`skills/`](skills). Each one uses the MiroMiro MCP tools when they
33
+ are connected and otherwise calls the REST API with `MIROMIRO_API_KEY` (free key, 300
34
+ credits a month: https://miromiro.app/api/onboarding).
35
+
24
36
  ## Quick start: remote server (nothing to install)
25
37
 
26
38
  A hosted server lives at:
@@ -109,7 +121,7 @@ Generated code is never trimmed. Results stop at roughly 20k tokens (25k for `ex
109
121
 
110
122
  The REST API and this local npm server always return everything untrimmed, so `limit` and
111
123
  `full_output` apply to the remote server only. Every tool on both servers accepts
112
- `render: true` (free accounts get 5 renders a month, then the call runs static and `usage.renderSkipped` says so; paid API plans and credit packs render without a monthly limit - see Notes), plus two more shared arguments:
124
+ `render: true` (forces a real browser, +5 credits, on every plan; usually not needed because the server re-runs JavaScript-only or refused pages in a browser by itself - see Notes), plus two more shared arguments:
113
125
 
114
126
  - `fresh: true` - skip the 24-hour cache and re-extract the live page (charged normally); use when the site just changed
115
127
  - `screenshot: true` (requires `render: true`) - the result gains a `screenshot` field: a public URL of a 1440x900 capture of the page, live for 7 days, at no extra credits - show it to the user to verify an extraction. Pass `'full'` instead of `true` for the entire page height.
@@ -136,8 +148,8 @@ The agent calls `extract_fonts` and returns every family with its font file URLs
136
148
 
137
149
  ## Notes
138
150
 
139
- - The API reads static HTML and resolves the full CSS cascade by default, so a fully client-rendered app may return little for images, video, audio and Lottie (tokens, fonts, brand, and code come from CSS and are unaffected). Pass `render: true` on any remote-server tool to run the page in a real browser first so its JavaScript executes (+5 credits). Free accounts get 5 renders a month (`usage.freeRender` reports each one and how many are left); after that a `render: true` call runs as the static extraction and `usage.renderSkipped` says so - never a refusal. Paid API plans and credit packs render without a monthly limit.
140
- - The same allowance also works without the flag: when the SITE refuses a free account's plain request (401, 403 or 406 - publishers commonly turn away datacenter IPs even for a public page), the server retries that call in a real browser automatically and free, a few times a month. The result then carries `usage.renderRescue` (a sentence to read to the user) and `usage.renderRescuesLeft`. So on a free account, do not treat a 401/403/406 as "this site cannot be extracted" until those are used up.
151
+ - The API reads static HTML and resolves the full CSS cascade first. When that comes back as a JavaScript app shell, with styles injected by scripts, or refused by the site (401, 403 or 406 - publishers commonly turn away datacenter IPs even for a public page), the server re-runs the call in a real browser by itself at no extra cost, on every plan, and the result carries `usage.autoRender` (a sentence to read to the user).
152
+ - Pass `render: true` to force the browser (+5 credits, any plan): for images, video or Lottie that only load on scroll, or when a result is still thin after the automatic pass. A 403 that says the browser was refused too means the site cannot be extracted. On extract_code and extract_design_tokens, `render: true` only permits the browser: the plain read still runs first, and the 5 credits are charged only if the browser was actually needed.
141
153
  - Every result carries `usage` with the credits left this month. If the account holds a credit pack (one-off credits that never expire, bought at https://miromiro.app/api/pricing), `usage.packCredits` is the pack balance left; packs are drawn after the monthly credits, so a free account with a pack keeps working past its 300 credits.
142
154
  - Respect the sites you extract from: check their terms before reusing assets commercially.
143
155
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "miromiro-mcp",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "MCP server for the MiroMiro design-extraction API — give your coding agent the real code, design tokens, assets, SVGs, fonts, and Lottie of any website.",
5
5
  "mcpName": "app.miromiro/miromiro",
6
6
  "type": "module",
@@ -10,7 +10,9 @@
10
10
  "type": "git",
11
11
  "url": "git+https://github.com/SoraiaBarroso/miromiro-mcp.git"
12
12
  },
13
- "bugs": { "url": "https://github.com/SoraiaBarroso/miromiro-mcp/issues" },
13
+ "bugs": {
14
+ "url": "https://github.com/SoraiaBarroso/miromiro-mcp/issues"
15
+ },
14
16
  "bin": {
15
17
  "miromiro-mcp": "src/index.mjs"
16
18
  },
package/src/index.mjs CHANGED
@@ -45,7 +45,7 @@ const NAMED_SECTIONS = ['hero', 'header', 'footer', 'pricing', 'features', 'test
45
45
  // client-rendered React/Next/SPA sites that return little statically.
46
46
  const RENDER_ARG = {
47
47
  type: 'boolean',
48
- description: 'Run the page in a real browser first so its JavaScript executes - use for client-rendered (React/Next/SPA) sites, when a normal call came back thin, or after a 403 target_blocked (bot protection refuses plain HTTP requests but usually lets a browser through). Slower, and adds 5 credits to the call. Never pass it as a first attempt: call static first and render only when the result is thin or the hint asks for it. Free accounts get 5 renders a month; after that a render=true call runs as the static extraction and usage.renderSkipped says so (never a refusal) - relay that sentence and do not pass render=true again that month. Paid API plans and credit packs render without a monthly limit. Free accounts also get rendering automatically, from the same allowance, when the SITE refuses the plain request (401/403/406): the server retries it in a browser at no charge and the result carries usage.renderRescue - read that sentence out to the user when it appears.'
48
+ description: 'Force a real browser so the page\x27s JavaScript runs before it is read. Slower, and adds 5 credits. Usually not needed: when the plain read comes back as a JavaScript app shell or the site refuses it (401/403/406), the server already re-runs the page in a browser by itself at no extra cost, and usage.autoRender says so. Pass it for images, videos or Lottie that only load on scroll, with screenshot=true, or when a result is still thin after that automatic pass. If a 403 says the browser was refused too, the site cannot be extracted - do not retry. On extract_code and extract_design_tokens, render=true only permits the browser: the plain read still runs first, and the 5 credits are charged only if the browser was actually needed.'
49
49
  }
50
50
 
51
51
  // Shared input arg: skip the 24h cache for this one call (charged normally).
@@ -82,7 +82,7 @@ const TOOLS = [
82
82
  title: 'Extract section as code',
83
83
  endpoint: 'code',
84
84
  description:
85
- "Use when the user asks to rebuild, clone, copy, port, restyle or 'make it look like' part of a real website, or wants a site's section as Tailwind, HTML+CSS, React (JSX) or Vue - or as a file to import into a site builder: framework=elementor for an Elementor template (WordPress), framework=shopify for a Shopify theme section. Give it the URL and, when the user named a part of the page, section (hero, header, footer, pricing, features, testimonials, faq, cta) - never invent a CSS selector. With neither, it auto-detects the hero; every call also returns `sections`, each other extractable section with a label and a ready selector for a follow-up call. Returns a self-contained component with the page's real resolved styles (true colors, fonts, spacing, copy) plus the tokens and assets it uses, so you adapt real values instead of estimating from a screenshot. For jsx/vue, repeated structures collapse into a data array rendered with .map()/v-for; ::before/::after come back as real elements; @keyframes ship in the css field. The `theme` field says which theme the code actually is - sites with a prefers-color-scheme dark variant return the light branch unless you pass theme='dark'; say which you returned. Not for: whole-page scraping, page text, or sites that need a login. Reads static HTML/CSS by default; if the result is thin or carries a `hint`, call again with render=true (+5 credits).",
85
+ "Use when the user asks to rebuild, clone, copy, port, restyle or 'make it look like' part of a real website, or wants a site's section as Tailwind, HTML+CSS, React (JSX) or Vue - or as a file to import into a site builder: framework=elementor for an Elementor template (WordPress), framework=shopify for a Shopify theme section. Give it the URL and, when the user named a part of the page, section (hero, header, footer, pricing, features, testimonials, faq, cta) - never invent a CSS selector. With neither, it auto-detects the hero; every call also returns `sections`, each other extractable section with a label and a ready selector for a follow-up call. Returns a self-contained component with the page's real resolved styles (true colors, fonts, spacing, copy) plus the tokens and assets it uses, so you adapt real values instead of estimating from a screenshot. For jsx/vue, repeated structures collapse into a data array rendered with .map()/v-for; ::before/::after come back as real elements; @keyframes ship in the css field. The `theme` field says which theme the code actually is - sites with a prefers-color-scheme dark variant return the light branch unless you pass theme='dark'; say which you returned. Not for: whole-page scraping, page text, or sites that need a login. Reads static HTML/CSS first and re-runs the page in a real browser by itself when that comes back as a JavaScript app shell or refused, at no extra cost (usage.autoRender says so) - no need to pass render=true.",
86
86
  inputSchema: {
87
87
  type: 'object',
88
88
  properties: {
@@ -114,7 +114,8 @@ const TOOLS = [
114
114
  label: { type: 'string' },
115
115
  elements: { type: 'number' },
116
116
  hasHeading: { type: 'boolean' },
117
- preview: { type: 'string' }
117
+ preview: { type: 'string' },
118
+ order: { type: 'number', description: 'Where the section starts on the page among the listed ones, 1 = topmost - sort by it to rebuild a whole page in sequence' }
118
119
  }
119
120
  }
120
121
  },
@@ -125,7 +126,7 @@ const TOOLS = [
125
126
  theme: { type: 'string', description: "light | dark: which one the code you just received actually is. Measured from the page, never echoed from your request - so if you asked for a theme the site cannot serve, this reports what you really got. Tell the user which theme they got when it may not match what they see on the site" },
126
127
  assets: { description: 'Images/fonts the section references' },
127
128
  summary: { description: 'What was extracted, at a glance. styledCoverage (0-100) is the quality signal: the % of elements the cascade found styles for' },
128
- hint: { type: 'string', description: 'Only present when the extraction looks degraded (client-rendered page, runtime-injected styles) - says what to do: on a static call usually retry with render=true; on a render=true call the styles could not be resolved even in a browser, do not retry' },
129
+ hint: { type: 'string', description: 'Only present when the extraction looks degraded (client-rendered page, runtime-injected styles) - says what to do (the server has already tried a browser where one would help); on a render=true call the styles could not be resolved even in a browser, do not retry' },
129
130
  usage: OUT_USAGE,
130
131
  truncation_note: OUT_TRUNCATION
131
132
  },
@@ -588,7 +589,7 @@ const INSTRUCTIONS =
588
589
  'fresh=true bypasses the 24h cache. Every result carries `usage` (credits left; `packCredits` = never-expiring pack balance when the account holds one).'
589
590
 
590
591
  const server = new Server(
591
- { name: 'miromiro', version: '0.8.0' },
592
+ { name: 'miromiro', version: '0.8.2' },
592
593
  { capabilities: { tools: {}, prompts: {} }, instructions: INSTRUCTIONS }
593
594
  )
594
595