Connection lost. Reconnecting… attempt 1 of 8
Paused. Your work is held on the server.
Could not reconnect.
This session has expired on the server.
An unhandled error has occurred.
Sedna.UI
v0.17.0 · main

MCP server

this site, not the package

This site answers to agents as well as to people. One read-only endpoint, six tools and four resources, over the same bytes the pages render.

Public, unauthenticated and read-only Every tool is annotated readOnlyHint, so a client that honours the hint calls them without prompting, and there will never be a seventh tool that writes — enforced by a test.

Add it

One URL. Streamable HTTP, no key, no install.

Any MCP client

The endpoint is https://www.sedna-ui.com/mcp. It is stateless, so a client may reconnect or fan out across processes without leaving sessions behind.

{
  "mcpServers": {
    "sedna-ui": {
      "type": "http",
      "url": "https://www.sedna-ui.com/mcp"
    }
  }
}

Claude Code

Or add it to a project's .mcp.json with the block above.

claude mcp add --transport http sedna-ui https://www.sedna-ui.com/mcp

The six tools

Six verbs, no overlap, shaped around one workflow: an agent writing a page in a consuming app and needing the exact markup plus enough semantics to pick the right variant.

ToolWhat it answers
search “What is there for a sortable table with status badges?” Ranks examples, classes, tokens and pages together. Returns references, never markup.
get_example The markup for up to five examples, byte-for-byte what this site renders. Valid in a .razor page and an .html file alike.
describe_class What a class actually does: the declarations from the shipped stylesheet, its cascade layer, its modifiers, and which examples use it. Also the way to check a class your app already styles before upgrading.
get_page Every example on one page — one call instead of five. With no id, the page list.
get_tokens The tokens as an ordered array of blocks, media condition included, for writing brand.css.
get_integration_guide The host page and its load order, the branding recipe, the JavaScript and C# surface, or the rules a consuming app follows.

The whole loop

searchget_exampledescribe_class. Nothing else is needed to write a page.

search { "query": "filter bar above a sortable table", "installedVersion": "0.2.0" }

  → hits: [ { kind: "page",    ref: "/toolbar", title: "Toolbar",    score: 78 },
            { kind: "example", ref: "Toolbar/FilterBar",   classes: ["toolbar", "toolbar-field", …] },
            { kind: "example", ref: "Table/SortableTable", classes: ["table", "table-sortable", …] },
            { kind: "class",   ref: ".table-sticky", blurb: "In layer sedna.paint. Used by 2 example(s)." } ]

get_example { "ids": ["Toolbar/FilterBar", "Table/SortableTable"] }

  → the markup, byte-for-byte what this site renders, plus every class it uses
    and the release each one first shipped in.

describe_class { "names": ["table-sortable", "col-num"] }

  → the declarations the shipped stylesheet holds for each, its cascade layer,
    its modifiers, and which examples use it.

describe_class

Up to ten class names per call. The declarations come from the stylesheet the running app serves, and usedByExamples points at the pages that show the class in context.

describe_class { "names": ["health-badge", "stat-target"], "installedVersion": "0.4.0" }

{
  "meta": {
    "branch": "main",
    "commit": "9ac438c",
    "builtUtc": "2026-08-03T11:20:44Z",
    "latestRelease": "0.4.0",
    "installedVersion": "0.4.0",
    "warning": "2 of these are not in 0.4.0: .health-badge, .stat-target. Upgrade Sedna.UI, or use something else."
  },
  "classes": [
    {
      "name": ".health-badge",
      "layer": "sedna.paint",
      "declarations": ["display: inline-flex", "align-items: center", "gap: var(--space-3)", "…"],
      "modifiers": [".health-badge--live", ".health-badge--streaming", ".health-badge--down"],
      "usedByExamples": ["/status#a-connection-s-state"],
      "since": "unreleased"
    },
    {
      "name": ".stat-target",
      "layer": "sedna.paint",
      "declarations": ["font-size: var(--text-2)", "color: var(--muted)"],
      "modifiers": [],
      "usedByExamples": ["/stat#target-link-and-unavailable"],
      "since": "unreleased"
    }
  ],
  "notFound": []
}

# `declarations` is read from the stylesheet the running app serves, so it is
# what ships rather than a transcription. `since` comes from the git tags via
# build/class-history.sh, and `meta.warning` names everything in the answer
# that the version you passed does not have — so an agent can tell "copy this"
# from "upgrade first" without asking. At most ten names per call.

The four resources

Whole artefacts, addressable by URI. A resource is attached by the person rather than pulled by the model. Nothing is resource-only: get_tokens and get_integration_guide duplicate two of these, because clients vary widely in resource support.

URITypeWhat it is
sednaui://stylesheet text/css The whole shipped stylesheet, exactly as the package delivers it.
sednaui://tokens application/json The token export, as an ordered array of blocks.
sednaui://version application/json What this catalogue was built from, and the latest released version.
sednaui://docs/{name} text/markdown One documentation file: getting-started, architecture, CLAUDE.consuming-app, releasing.

Say which version you have

This site is built from main and can be ahead of any release, so every tool takes installedVersion. Pass it and the meta.warning block names everything in the answer your version does not have — including anything with no since at all, which is in no release yet. The results still come back.

Limits

They apply to /mcp alone, never globally — a global limiter would also count this site's own SignalR upgrades. A rejected call answers 429 with Retry-After: 60.

LimitValueWhy
Concurrent requests16, plus 8 queued The actual control. Not partitioned, so there is nothing to spoof around.
Per caller60 burst, 30/min Fairness, not security: behind a proxy whose addresses we do not control, per-IP limiting is not a security measure.
Request body256 KB JSON-RPC calls here are a few hundred bytes.
Per call 25 / 5 / 10 Hits from search, ids per get_example, names per describe_class. Markup is capped at 8 KB per example and cut at a tag boundary, so a truncated response still parses.

Then give the agent the rules

The server answers questions. It does not stop an agent inventing a class name or wrapping a table in a component — so copy docs/CLAUDE.consuming-app.md (opens in a new tab) into your app's own CLAUDE.md, or fetch it through get_integration_guide { "section": "rules" }.