@swebsy/mcp
MCP server that lets a coding agent (Claude Code, Codex, Cursor, Windsurf, …) drive an open Swebsy Studio tab over a local 127.0.0.1 WebSocket relay.
npm · fingerprint 7f8d98011a52772fe7fe0f9e · repository · RSS
44tools
2recorded versions
24dtracked
changed 2d ago
What changed
Changed 2026-10-28 13:06 UTC
8 descriptions rewritten, 1 schema or annotation change with the description left byte-identical.
--- pinned/swebsy_add_section +++ observed/swebsy_add_section { "annotations": { "destructiveHint": false, - "description": "Insert a new section into the current page. Use for adding discrete sections (hero, features, pricing, CTA) to an existing page. Appends to the end by default; to place it somewhere specific, pass `position` plus the `targetPath` of the component to place it next to.", + "description": "Insert a new section into the current page. Use for adding discrete sections (hero, features, pricing, CTA) to an existing page. Supply exactly one of `component` (a component tree) or `html` (one root element). Appends to the end by default; to place it somewhere specific, pass `position` plus the `targetPath` of the component to place it next to.", "inputSchema": { "additionalProperties": false, "properties": { - "description": "The section component to insert.", + "description": "The section component to insert. Omit when sending `html`.", "properties": { "a": { "additionalProperties": { + "html": { + "description": "The section as HTML with a single root element (e.g. one <section>). No data-gjs-* attributes. Omit when sending `component`.", + "type": "string" + }, "position": { "description": "Where to insert. Defaults to 'end' if omitted. 'before-selected'/'after-selected' are measured against `targetPath` when you pass one, otherwise against the canvas selection — so pass `targetPath` with them unless the user has selected something.", "enum": [ - "summary", - "component" + "summary" ], "type": "object" },
--- pinned/swebsy_delete_section +++ observed/swebsy_delete_section { "annotations": { "destructiveHint": true, - "description": "Remove a component from the current page entirely. Use this instead of emptying a section's contents — an emptied section leaves a stray blank div on the page. Deletes the selected component by default; pass `targetPath` (from `read_page`) to delete a component you did not select.", + "description": "Remove a component from the current page entirely. Use this instead of emptying a section's contents — an emptied section leaves a stray blank div on the page. Deletes the selected component by default; pass `targetId` or `targetPath` (from `read_page`) to delete a component you did not select.", "inputSchema": { "additionalProperties": false, "properties": { + "targetId": { + "description": "The component to delete by its id, as `read_page` shows it after `#` (e.g. \"ieyubib\", or \"call-2-2\" in a symbol instance). Stays valid when other components move or are added, unlike a path. Pass this OR the path, not both.", + "minLength": 1, + "type": "string" + }, "targetPath": { "description": "Zero-based component indexes from the current page root, exactly as returned by the most recent `read_page` call. Omit to delete the selected component.", "items": {
--- pinned/swebsy_duplicate_section +++ observed/swebsy_duplicate_section { "annotations": { "destructiveHint": false, - "description": "Copy a component (with its classes and styles) and insert the copy right after it. Paths after it shift by one — call `read_page` before the next path-based edit.", + "description": "Copy a component (with its classes and styles) and insert the copy right after it. Paths after it shift by one — call `read_page` before the next path-based edit (ids don't shift).", "inputSchema": { "additionalProperties": false, "properties": { + "targetId": { + "description": "The component to copy by its id, as `read_page` shows it after `#` (e.g. \"ieyubib\", or \"call-2-2\" in a symbol instance). Stays valid when other components move or are added, unlike a path. Pass this OR the path, not both.", + "minLength": 1, + "type": "string" + }, "targetPath": { "description": "Path (from the most recent `read_page`) of the component to copy.", "items": { - "required": [ - "targetPath" - ], "type": "object" }, "name": "swebsy_duplicate_section",
--- pinned/swebsy_edit_section +++ observed/swebsy_edit_section { "annotations": { "destructiveHint": false, - "description": "Modify an existing component. By default this edits the selected component. To edit a component identified by `read_page`, provide its `targetPath`; an explicit path overrides the canvas selection. Preferred: provide `component` — the full replacement component tree (compact DSL OK), best for structural changes. Alternative: provide `html` — the complete modified HTML string. Fallback: provide `patch` — JSON Patch (RFC 6902) for tiny single-property tweaks. Supply exactly one. Preserve existing IDs: an id kept in the edit keeps the styles attached to it; an id you drop loses them.", + "description": "Modify an existing component. By default this edits the selected component. To edit a component identified by `read_page`, provide its `targetId` (preferred — survives other edits) or `targetPath`; an explicit target overrides the canvas selection. Preferred: provide `component` — the full replacement component tree (compact DSL OK), best for structural changes. Alternative: provide `html` — the complete modified HTML string. Fallback: provide `patch` — JSON Patch (RFC 6902) for tiny single-property tweaks. Supply exactly one. Preserve existing IDs: an id kept in the edit keeps the styles attached to it; an id you drop loses them. The result's `id` is the component's id after the edit (a replacing edit can give it a new one). `changed: false` means the page's HTML/CSS/JS came out identical, so the edit did not show up; `success: false` means a patched attribute is not what the page exports.", "inputSchema": { "additionalProperties": false, "properties": { - "description": "JSON Patch (RFC 6902) operations applied to the target component JSON. Only for tiny single-property tweaks.", + "description": "JSON Patch (RFC 6902) operations applied to the target component JSON. Only for tiny single-property tweaks. HTML attributes live under /attributes (an image's src is /attributes/src), classes at /classes, text at /content.", "items": { "additionalProperties": false, "properties": { + "targetId": { + "description": "The component to edit by its id, as `read_page` shows it after `#` (e.g. \"ieyubib\", or \"call-2-2\" in a symbol instance). Stays valid when other components move or are added, unlike a path. Pass this OR the path, not both.", + "minLength": 1, + "type": "string" + }, "targetPath": { "description": "Zero-based component indexes from the current page root, exactly as returned by the most recent `read_page` call (for example [0] for the first top-level section or [0, 2] for its third child). Use this when the user names or relatively identifies a component instead of selecting it.", "items": {
--- pinned/swebsy_link_page +++ observed/swebsy_link_page { "annotations": { "destructiveHint": false, - "description": "Point an existing link at a project page — the same wiring the UI's 'Link to' picker does. Pass the link's `targetPath` (from `read_page`) and the target `page` (id or name). For a navbar link this sets its page target so the href and active state stay in sync; for a plain link or button it sets href to the page's ./slug.html. Use after `create_page` to wire a navbar to the new page.", + "description": "Point an existing link at a project page — the same wiring the UI's 'Link to' picker does. Pass the link's `targetId` or `targetPath` (from `read_page`) and the target `page` (id or name). For a navbar link this sets its page target so the href and active state stay in sync; for a plain link or button it sets href to the page's ./slug.html. Use after `create_page` to wire a navbar to the new page.", "inputSchema": { "additionalProperties": false, "properties": { + "targetId": { + "description": "The link by its id, as `read_page` shows it after `#` (e.g. \"ieyubib\", or \"call-2-2\" in a symbol instance). Stays valid when other components move or are added, unlike a path. Pass this OR the path, not both.", + "minLength": 1, + "type": "string" + }, "targetPath": { "description": "Zero-based component indexes from the current page root, exactly as returned by `read_page` (e.g. the nav link inside the navbar).", "items": { - "targetPath", "page" ], "type": "object"
--- pinned/swebsy_move_section +++ observed/swebsy_move_section { "annotations": { "destructiveHint": false, - "description": "Move a component to just before or after another component on the current page — reorder sections, swap columns, lift a CTA above the footer. The component keeps its id, classes and id-styles. ALWAYS use this to reorder; delete + re-add loses the component's styles.", + "description": "Move a component to just before or after another component on the current page — reorder sections, swap columns, lift a CTA above the footer. The component keeps its id, classes and id-styles. ALWAYS use this to reorder; delete + re-add loses the component's styles. Name each side by id (`targetId`/`anchorId`) or by path (`targetPath`/`anchorPath`).", "inputSchema": { "additionalProperties": false, "properties": { + "anchorId": { + "description": "The component to place it next to by its id, as `read_page` shows it after `#` (e.g. \"ieyubib\", or \"call-2-2\" in a symbol instance). Stays valid when other components move or are added, unlike a path. Pass this OR the path, not both.", + "minLength": 1, + "type": "string" + }, "anchorPath": { "description": "Path (from the same `read_page`) of the component to place it next to.", "items": { + "targetId": { + "description": "The component to move by its id, as `read_page` shows it after `#` (e.g. \"ieyubib\", or \"call-2-2\" in a symbol instance). Stays valid when other components move or are added, unlike a path. Pass this OR the path, not both.", + "minLength": 1, + "type": "string" + }, "targetPath": { "description": "Path (from the most recent `read_page`) of the component to move.", "items": { - "required": [ - "targetPath", - "anchorPath" - ], "type": "object" }, "name": "swebsy_move_section",
--- pinned/swebsy_read_page +++ observed/swebsy_read_page { "annotations": { "destructiveHint": false, - "description": "Read the current page structure and addressable component target paths. Call this BEFORE editing a named or relative page component that is not the current selection. The default `sections` read lists every top-level section with its target path — enough to pick the one to edit. When copying content between components, use `detail: full` WITH the `targetPath` of the one section you're copying, not a whole-page read. Also call it AFTER applying edits to verify the result.", + "description": "Read the current page structure: each line shows a component's target path and its `#id`. edit_section, delete_section, move_section, duplicate_section and link_page take either — prefer the id (`targetId`), which survives moves and inserts; other tools take the path. Use the id only to target; don't copy auto ids into markup. Call this BEFORE editing a named or relative page component that is not the current selection. The default `sections` read lists every top-level section with its target path — enough to pick the one to edit. To find a nested element (a link, button, card) pass that section's `targetPath` plus `depth` — one call instead of drilling down level by level. When copying content between components, use `detail: full` WITH the `targetPath` of the one section you're copying, not a whole-page read. Also call it AFTER applying edits to verify the result.", "inputSchema": { "additionalProperties": false, "properties": { + "depth": { + "description": "Optional. How many levels of the indexed tree to print below the section layer (default 1 = each section only, deeper nodes summarised as '(N descendants)'). Every printed line keeps its target path. Pair with `targetPath` to see a whole section in one call — e.g. `targetPath: [7], depth: 6` lists every link in the footer with its path for link_page/edit_section. Above 1 the read is capped at ~24 KB and ends with a '…(truncated: … next is [path])' marker if it doesn't fit; values above 12 are clamped.", + "maximum": 12, + "minimum": 1, + "type": "integer" + }, "detail": { - "description": "'sections' (default): every section at the read root with its target path, an ~80-char text preview, and its descendant count — bounded and complete (~1-2 KB). 'outline': a deeper type/tag/class tree, character-capped. 'full': the complete cleaned JSON tree, for copying content between components (scope it with targetPath).", + "description": "'sections' (default): every section at the read root with its target path, an ~80-char text preview, and its descendant count — bounded and complete (~1-2 KB). 'outline': a deeper type/tag/class tree, character-capped (~2 KB; prefer `sections` + `depth`). 'full': the complete cleaned JSON tree, for copying content between components (scope it with targetPath).", "enum": [ "sections", "outline",
--- pinned/swebsy_update_settings +++ observed/swebsy_update_settings { "annotations": { "destructiveHint": false, - "description": "Raw CSS appended to the compiled stylesheet (canvas + export). Use for SITE-WIDE rules that utilities/tokens can't express — restyling a whole component type (e.g. make every `.btn` neobrutalist), custom box-shadows, border-width/radius. Colors MUST use theme vars (var(--color-neutral), var(--color-secondary)) so they stay dark-mode aware. This REPLACES the previous value — send the full CSS you want, not a fragment. This CSS is document-scoped: it does NOT travel into a harvested block, so it locks styled sections to this template. NEVER use it to build a repeated custom component (card, link block, tile) — make that a SYMBOL styled with theme classes so it stays harvestable. Reserve custom CSS for genuinely global polish only.", + "description": "Raw CSS appended to the compiled stylesheet (canvas + export). Use for SITE-WIDE rules that utilities/tokens can't express — restyling a whole component type (e.g. make every `.btn` neobrutalist), custom box-shadows, border-width/radius. Colors MUST use theme vars (var(--color-neutral), var(--color-secondary)) so they stay dark-mode aware. This REPLACES the previous value — send the full CSS you want, not a fragment. This CSS is document-scoped: it does NOT travel into a harvested block, so it locks styled sections to this template. NEVER use it to build a repeated custom component (card, link block, tile) — make that a SYMBOL styled with theme classes so it stays harvestable. Reserve custom CSS for genuinely global polish only. NEVER set type here (font-family, font-size, font-weight, font-style, letter-spacing, line-height, text-transform) on a class: that text's type disappears from the style panel. Fonts go in typography.fontFamily roles (a second display face in the free role, e.g. mono, applied per element with font-mono); size/weight/italic/tracking/case are utility classes on the element. Only bare-element defaults (body, h1-h6, p) inside @layer components may set type.", "type": "string" }, "darkMode": {
--- pinned/swebsy_upload_asset +++ observed/swebsy_upload_asset { "annotations": { "destructiveHint": false, - "description": "Upload a local image, font, video, audio or PDF file into the open site and return its `assetId`, `src` and a `usage` snippet. Images go in the asset library for `image` components, video for `video` components (`attributes.src`), audio for `audio`, PDFs as a link `href`; fonts are stored for `update_settings` fonts.custom. This is the ONLY way to get your own imagery (screenshots, logos, textures, mockups) into a site — an `image` with an empty src gets a random stock photo instead. Reads the file from the agent's own filesystem, so pass a path you can see (for example a screenshot you just captured). The asset is stored in the project and travels with static export and project JSON.", + "description": "Upload a local image, font, video, audio or PDF file into the open site and return its `assetId`, `src` and a `usage` snippet. Images go in the asset library for `image` components, video for `video` components (`attributes.src`), audio for `audio`, PDFs as a link `href`; fonts are stored for `update_settings` fonts.custom. This is the ONLY way to get your own imagery (screenshots, logos, textures, mockups) into a site — an `image` with an empty src gets a random stock photo instead. Reads the file from the agent's own filesystem, so pass a path you can see (for example a screenshot you just captured). The asset is stored in the project and travels with static export and project JSON. Pass `path` or `paths` (exactly one). Several files: pass `paths` (up to 25) instead of `path` for one call that returns a compact `{assets: {basename: src}, failed: {basename: reason}}` map.", "inputSchema": { "additionalProperties": false, "properties": { - "description": "Optional display name in the asset library. Defaults to the file's own basename.", + "description": "Optional display name in the asset library, single `path` only. Defaults to the file's own basename.", "type": "string" }, "path": { - "description": "Absolute path to the file on the agent's machine. Images: .png, .jpg, .jpeg, .webp, .gif, .avif, .svg. Fonts (for `update_settings` fonts.custom, pass the returned assetId): .woff2, .woff, .ttf, .otf. Video: .mp4, .m4v, .webm, .mov, .ogv. Audio: .mp3, .m4a, .wav, .ogg. Documents: .pdf. Max 10 MB (the hosting per-file cap) — re-encode larger files first (for video: H.264 .mp4, 1080p or less, `-movflags +faststart`). Prefer .svg for logos and other flat vector art so it stays crisp at any size; uploaded SVG is sanitized (scripts and external references are stripped).", + "description": "Absolute path to the file on the agent's machine. Pass `path` or `paths` (exactly one). Images: .png, .jpg, .jpeg, .webp, .gif, .avif, .svg. Fonts (for `update_settings` fonts.custom, pass the returned assetId): .woff2, .woff, .ttf, .otf. Video: .mp4, .m4v, .webm, .mov, .ogv. Audio: .mp3, .m4a, .wav, .ogg. Documents: .pdf. Max 10 MB (the hosting per-file cap) — re-encode larger files first (for video: H.264 .mp4, 1080p or less, `-movflags +faststart`). Prefer .svg for logos and other flat vector art so it stays crisp at any size; uploaded SVG is sanitized (scripts and external references are stripped).", "minLength": 1, "type": "string" + }, + "paths": { + "description": "Batch form: absolute paths of up to 25 files (same types and 10 MB cap as `path`). Pass `path` or `paths` (exactly one). Each file is uploaded on its own, so one bad file lands in `failed` without stopping the rest. Display names are the basenames; `filename` is not used.", + "items": { + "minLength": 1, + "type": "string" + }, + "maxItems": 25, + "minItems": 1, + "type": "array" } }, - "required": [ - "path" - ], "type": "object" }, "name": "swebsy_upload_asset",
Current tools
Show all 44 tool fingerprints
swebsy_add_section
swebsy_add_symbol_instance
swebsy_animate_page
swebsy_capture
swebsy_commit_design_direction
swebsy_create_page
swebsy_create_site
swebsy_delete_asset
swebsy_delete_page
swebsy_delete_section
swebsy_delete_symbol
swebsy_detach_symbol
swebsy_duplicate_page
swebsy_duplicate_section
swebsy_edit_section
swebsy_export
swebsy_get_builder_guide
swebsy_get_skill
swebsy_insert_block
swebsy_link_page
swebsy_list_assets
swebsy_list_blocks
swebsy_list_pages
swebsy_list_sites
swebsy_list_skills
swebsy_list_symbols
swebsy_list_templates
swebsy_move_section
swebsy_open_site
swebsy_promote_to_symbol
swebsy_read_page
swebsy_read_selection
swebsy_redo
swebsy_rename_site
swebsy_rename_symbol
swebsy_replace_page_content
swebsy_select_page
swebsy_start_pairing
swebsy_status
swebsy_undo
swebsy_update_page
swebsy_update_settings
swebsy_upload_asset
swebsy_wrap_section
Watch this server yourself
If you run this server, put the proxy in front of it. It pins these exact fingerprints on first connect and stops the session if they move.
npx -y mcp-pin@0.2.3 -- <your @swebsy/mcp command>
Or subscribe to this page's RSS feed to be told when it changes.
Badge
The badge states one fact about time and nothing else. It never claims a server is safe.
[](https://mcp-pin.gautamkhosla.com/servers/104320eec91b17b8.html)