sitewright (sitewright-cms/sitewright) is an MCP server listed on the M8ven Trust Index. It scores 74 out of 100, grade C. It declares 55 tools. No publisher has claimed this listing.
Open-source, self-hostable platform for agencies to build & run all their client sites: code-first authoring with live in-place editing, a built-in CMS, i18n, rich interactive components, and framework-free static publishing — plus an AI assistant + MCP so coding agents can build & edit your sites.
Emerging. No concerning findings. Grades remain capped until the project builds reputation through adoption. Grades reflect the full trust pyramid: code, verification depth, and reputation. New projects cap at C until adoption is earned.
How we verified
Verified is a snapshot. Live keeps it current, and builds your track record.
⚡ Connect GitHub → continuous verification on every pushwhy connect →Who stands behind it
sitewright-cms
Source: github_repo_search
Claim it to get a verified publisher badge, a free copy of our full audit findings, and direct contact for any high-priority issues we find. Or connect your repo for our deepest verification, Live Monitored: read-only, revoke anytime. What we access →
Install from
The grade above is for the source repository. Registries can serve a different version, so we mark the ones we were not able to read.
These names and descriptions are the publisher's own, read from the source code. We print them as written. Our assessment is the findings above, not this list.
get_scopeShow whether this agent is connected and, if so, the project, role, and capabilities. Call this first.
loginConnect this agent to a Sitewright project. Returns a URL + code for the user to approve in their browser.
switch_projectRe-authenticate to connect to a DIFFERENT project (project scope is fixed per connection). Returns a URL + code to approve.
get_componentsThe authoring contracts of the first-party interactive components (carousel, tabs, lightbox, modal, banner, form): markers, data-sw-part roles, config attributes, and copy-paste markup skeletons. Optionally filter by type or marker.
search_iconsFind icon names for {{sw-icon "name"}} (Phosphor, filled by default; add a ":weight" suffix like ":bold" or ":duotone"). Pass ONE OR MORE search terms, comma- or whitespace-separated (e.g. "settings, trash cart") — returns matching names per term. Searches Phosphor names, Lucide-name aliases and key…
search_texturesFind transparent background TEXTURES (tileable PNG overlays — paper, fabric, noise, denim, grid…) to set as an element background. Pass ONE OR MORE terms, comma- or whitespace-separated (e.g. "paper, fabric denim") — returns matching texture names per term, each with ready-to-paste CSS. The colour c…
get_capabilitiesOne INDEX of everything this platform can do and WHERE each is documented: the interactive components, the get_guide topics, the {{sw-*}} reference, how each content kind is written, and a need→tool lookup (e.g. "ripple" → get_guide effects, "collections" → get_guide datasets). Call this before assu…
get_guideget_referenceThe authoring REFERENCE for writing a page `source`: the {{sw-*}} HELPERS, the data-sw-* editable DIRECTIVES, the BINDING namespaces (company / website / page / page.data / pages / dataset / item / nav …), and the {{#each}} LOOP VARIABLES. Derived from the live engine, so it always matches what ship…
list_pagesList the project’s pages. Returns METADATA only by default (id/path/title/status/nav/parent/order/template/…): a page’s Handlebars `source` and `data` store are omitted and described under `_summary` instead, because a full listing of a real site runs to hundreds of KB and blows the tool-output limi…
get_pageGet one page by id. For code-first pages the design is in the `source` field. The response also carries `previewUrl` — a signed DRAFT preview of this page that needs no login and works with no deploy target.
list_contentList all entities of a content kind. For kind 'entry' pass `dataset` (a dataset slug) to list ONLY that dataset's entries — an entry id is unique only within its dataset, so an unscoped entry list returns EVERY dataset's rows mixed together. Pass summary:true to omit the heavy body fields (source / …
get_contentGet one content entity by kind + id. For an ENTRY also pass `dataset` (its owning dataset slug) — an entry id is only unique WITHIN its dataset, so two datasets can share an id.
list_revisionsList a content entity's revision history, newest first (id, op, who, when, note). Pair with restore_revision to roll back a bad edit. For an ENTRY also pass `dataset` (its owning dataset slug).
restore_revisionRestore a content entity to an earlier revision (its id from list_revisions). Non-destructive: the current version stays in history, and a deleted entity is recreated. For an ENTRY also pass `dataset` (its owning slug) — the same one used with list_revisions.
preview_pagecompare_to_sourcefidelity_checkThe OBJECTIVE clone-fidelity gate for an imported page: renders your BUILD and the ORIGINAL source, measures computed styles per element + whole-bar chrome facts, and returns a measured PASS/FAIL — body (font/gradient/coverage) and chrome (position/size/style + skew, font-weight, letter-spacing, rad…
clone_auditThe OBJECTIVE clone-acceptance prerequisite — the facts a screenshot can't show and computed-style coverage can't game. fidelity_check only measures computed styles, so it passes a clone whose datasets are duplicated, whose modals were dropped, whose slider is dead, whose fonts don't actually load, …
pagespeed_auditLighthouse PAGE-SPEED + SEO audit of a page, run against a DEPLOY-EQUIVALENT build (minified like Publish, with production cache headers — not the sandboxed draft preview). Returns four category scores 0–100 (performance, accessibility, best-practices, seo), core lab metrics (FCP / LCP / TBT / CLS /…
visual_auditThe VISUAL acceptance gate for a cloned/imported page — the reliable fidelity signal the computed-style scorers (fidelity_check / clone_audit's visual leg) miss (they score fonts/gradients/coverage of TEXT elements and are BLIND to layout, images, section design, and modals; a hollow page scores gre…
inspect_sourceMEASURE a rendered page — settled markup + REAL computed styles + REAL rects for the CSS selectors you name. This is how you get NUMBERS off the LIVE ORIGINAL (font-size, padding, gap, colour, gradient stops, border-radius, shadow, transform), which the other fidelity tools cannot give you: they all…
compare_regionsHIGH-RESOLUTION visual compare of an imported page's chrome: crops the nav HEADER and FOOTER (or pass regions to limit) of your BUILD and the ORIGINAL, at 2× device scale as lossless WebP, and returns them build-then-original per region. Use it to SEE fine detail that compare_to_source's 1× full-pag…
get_publish_statusRead where this project actually stands. `status` is the headline: "unpublished" whenever no deploy target is configured — publishing BUILDS the site, but nothing serves it until a target exists, so there is no live address. `url` is non-null ONLY for Local Hosting; it is null for a remote (FTP/SFTP…
list_submissionsList form submissions for the project, newest first. Optionally filter by formId and paginate with limit/offset.
list_stock_providersList the configured stock-image providers and whether each is available (openverse needs no key; unsplash/pexels/pixabay need an instance-admin key). Only needed to explain a gap — search_stock_images with provider "all" already uses every available one.
search_stock_imagesSearch stock photos. `provider: "all"` (the default choice) queries every available provider at once and interleaves the results; name one provider to search only that. Each hit carries its own `provider` — pass it back to import_stock_image along with the id. Returns provider-hosted `thumbUrl` (gri…
list_mediaList the project’s self-hosted media assets — each with the URL to reference in an <img src> / href, plus kind, dimensions and alt. Optionally filter by kind = image | file | font.
list_media_foldersList the project’s media FOLDERS (virtual grouping labels — slash-delimited paths, "" = root). Call before organizing assets so you reuse existing folders instead of creating duplicates.
put_pageCreate or REPLACE a page. The page id is taken from page.id. This is a TOTAL replace — every field you omit is deleted, so only use it when you are writing the whole page. TWO fields survive an omission: `parent` (a page always hangs off a home, so a replace never yanks a sub-page up to the root and…
patch_pagePATCH an existing page: send only the fields you want to change and everything else is kept. Use this instead of put_page for partial edits — put_page REPLACES, so `{id, path, title, nav}` would silently wipe `source`, `status`, `description` and `order` (`parent` and the `data.swImport` import mark…
delete_pageDelete a page by id. Needs the content:delete capability.
patch_critical_cssput_contentCreate or replace a content entity of the given kind. Args: { kind, id, data } — plus `dataset` (the owning dataset slug) when kind is "entry". For PAGES prefer put_page (fully typed). `data` must match that kind’s schema; you may OMIT `data.id` (and an entry’s `data.dataset`) — they are copied from…
delete_contentDelete a content entity by kind + id. For an ENTRY also pass `dataset` (its owning dataset slug). Needs the content:delete capability.
delete_content_bulkDelete MANY entities of one kind in ONE call: { kind, ids:[…] } — plus `dataset` (the owning dataset slug) when kind is "entry". Use this instead of looping delete_content when clearing up after an import (junk datasets, a batch of entries or scaffolded pages): one call instead of N, so you do not b…
add_languageAdd a translation-target LANGUAGE to the site — the ONLY correct way to do so. In ONE atomic step it registers the locale AND scaffolds an inherited translated page for EVERY existing page (the /<locale>/… subtree; each variant inherits the main language's code, so you then only fill in its translat…
remove_languageRemove a translation-target language: drops the locale from settings AND cascade-deletes every page in that language's /<locale>/… subtree (and prunes its translation-catalog column). The default (main) language cannot be removed. Needs the content:delete capability.
import_stock_imageImport a stock photo (by provider + id from search_stock_images) into the project. The server downloads, optimizes, and self-hosts it as a media asset with attribution — never a hotlink.
import_websiteCrawl + IMPORT a public https website URL into THIS project — the FIRST step of cloning/nativizing a site. The server fetches and RENDERS the live page(s) itself (executing JS, following an embed/preview wrapper to the real framed site), self-hosts the images + fonts, and creates the imported `swImp…
import_statusimport_imageImport an image into the project from a PUBLIC https URL — the server downloads, optimizes, and self-hosts it (never a hotlink), returning the stored asset (use its `url` in your <img src>). For STOCK photos use search_stock_images + import_stock_image instead. This is the ONLY URL-based import, and…
create_media_uploadUpload a LOCAL file (a logo, a photo, a font, a PDF) into the project media library. Use this when the file is on YOUR disk; use import_image when it is at a public https URL. TWO STEPS: (1) call this to get a one-shot `uploadUrl`, (2) send the file to it yourself, e.g. `curl -T ./logo.png "<uploadU…
upload_mediareplace_mediacreate_media_replaceREPLACE a LARGE local file in place (the ticket lane for replace_media — a photo, a video, a PDF). TWO STEPS: (1) call this with the asset `id` to get a one-shot `uploadUrl`, (2) send the file to it yourself, e.g. `curl -T ./hero.jpg "<uploadUrl>?filename=hero.jpg"` — always pass ?filename=, since a…
create_media_folderCreate an (empty) media folder + any missing ancestors. `path` is a slash-delimited grouping label (segments: letters, digits, space, _ or -), e.g. "About/Gallery". Folders are virtual labels; the file bytes stay where they are.
rename_media_folderRename OR move a media folder: re-roots the folder subtree AND re-files every asset under it. `from`/`to` are full folder paths. Fails if `to` already exists.
move_media_bulkmove_mediaMove and/or rename a single media asset: `folder` re-files it (use list_media_folders / create_media_folder), `filename` sets its display name. Pass at least one. The asset URL is unchanged.
transform_imageRotate (90/180/270 clockwise) and/or crop an image asset. Rotation is applied FIRST, so `crop` is measured against the image AS TURNED — the same order an editor shows you. By default it edits IN PLACE: the asset id, stored name and URL do not change, so every page/dataset reference keeps working an…
delete_mediaDelete a single media asset — it moves to the File Manager Recycle Bin (RECOVERABLE for 90 days, then auto-purged). It is hidden from the media list and EXCLUDED from the next publish (a still-referenced page would then show a broken image on the republished site), so make sure NO page/dataset still…
rename_datasetRename a dataset's slug AND/OR its display name. The slug must be an UNDERSCORE identifier (e.g. `faq_passengers`, NOT `faq-passengers` — it is used as a `dataset.<slug>` Handlebars path). This CASCADES automatically: every entry's `dataset` field and every page/template source's `{{#each dataset.<s…
publish_projectBuild the project’s static site from current saved content.
ai_cloneAutonomously clone/nativize EVERY imported page to the acceptance gate (server-side import→author→gate→iterate→publish). Requires a configured AI provider; a generic MCP agent can instead run the clone_site workflow itself.
Tool annotations
No tools have read-only/destructive annotations
Add readOnlyHint or destructiveHint annotations to every tool so hosts can warn users before invoking.
All four hints declared on every tool
55/55 tools missing one or more hints — get_scope (missing: readOnlyHint, destructiveHint, idempotentHint, openWorldHint); login (missing: readOnlyHint, destructiveHint, idempotentHint, openWorldHint); switch_project (missing: readOnlyHint, destructiveHint, idempotentHint, openWorldHint), +52 more. OpenAI's directory rejects tools where any of the four hints are missing or non-boolean.
For every tool, set all four hints (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) to explicit true/false values that match the handler’s actual behaviour.
Tool inputs are validated
13/17 tool handlers declare input schemas (76%)
Declare an inputSchema with zod/joi/yup on every tool definition.
Claim the listing to review these findings one by one and send us a correction where you disagree, straight to the team. Claiming also means we tell you when the grade moves, and reach you first if we find anything urgent.
[](https://m8ven.ai/mcp/sitewright-cms/sitewright)?variant=verified to the badge URL.Vetting this one by hand? Tool Check is an MCP that scores other MCPs. Add it once and ask Claude, ChatGPT, or any MCP client to grade a server, surface CVEs, check the publisher, and suggest safer alternatives — before you install.
https://m8ven.ai/api/mcp/tool-check