Cloudscript Renderer for MCP Documentation

Cloudscript Renderer for MCP Documentation turns a pasted Model Context Protocol (MCP) Registry server.json document or tools/list result into structured, readable documentation on a Confluence page. It is purpose-built for MCP: not a generic JSON viewer, not another MCP server product. It is a Confluence Cloud app built on Atlassian Forge, and every document is detected, parsed and drawn in your browser when the page is viewed.

Because the page holds the live document rather than a screenshot, the source stays canonical: edit the pasted JSON in the macro and the page re-renders from it, so every server documents identically and nothing goes stale silently. There is no generative step between the JSON and the page to drop, reword or hallucinate a field. If your team stands up internal MCP servers that appear in no public registry and currently documents them as unformatted JSON dumps in code blocks, or not at all, this macro puts that information on the Confluence pages your developers, security reviewers and platform team already read.

Coming soon to the Atlassian Marketplace.

Inserting the macro

Edit a Confluence page and insert the macro titled MCP Server Documentation, either by typing /mcp in the editor or by choosing it from the macro browser, where it also answers to searches for "model context protocol", "server" and "tools". To place documentation for several servers on one page, add a separate macro for each: every macro holds and renders its own pasted source independently.

The Confluence macro browser showing the "MCP Server Documentation" macro, found by searching "mcp", with its icon and description visible.
Insert the macro from the editor: search "mcp" or any of its other search terms in the macro browser.

Pasting a server.json or tools/list result

Open the macro's configuration and paste your MCP artefact into the editor, which shows the placeholder text "Paste your server.json or tools/list JSON here…" until you do. The renderer detects which of the two formats you pasted, in this precedence order: a server.json document (identified by its $schema or by its overall shape), then a tools/list result (bare or wrapped in a JSON-RPC envelope), then a JSON-RPC error object, then anything else as a generic, unrecognised document. A live status line above the editor reads "Detected format: " followed by server.json, tools/list result, JSON-RPC error response, unrecognised (generic view), invalid JSON, or nothing pasted yet, so you can see what the renderer made of your paste as you edit.

If detection picks the wrong format for an ambiguous paste, a Format override select beside the detected-format line lets you force it: Auto-detect, server.json, or tools/list. Choosing a specific format bypasses detection entirely and parses your paste that way; choosing Auto-detect (the default) hands the decision back to the precedence order above.

The macro configuration editor with a server.json document pasted in, reading "Detected format: server.json" above a Format override select set to Auto-detect, and a size meter below the editor.
The configuration editor: paste your JSON, and the detected-format line and size meter update as you type.

The sample document

An empty macro offers a one-click sample: a "Load a sample server.json" link appears beneath the editor whenever the draft is empty. It loads a small, synthetic com.example/sample-server entry with a package, a secret-bearing environment variable, and a remote, so a first render succeeds within seconds and gives you a working document to replace with your own paste.

What renders

A parsed server.json renders as a header block (name, description, version and schema declaration), one labelled section per package with its environment-variable and argument tables, and a remotes table where the document declares any. A parsed tools/list result renders one capability card per tool, each with its description, a nested parameter table built from the tool's inputSchema, and a collapsed raw-JSON view with its own copy button. Any field neither format's mapping recognises still renders, in a generic key-value section, instead of being dropped silently.

A rendered server.json document: header with name, description and schema link, a package table with an environment-variable row badged "secret", a "View on GitHub" link pill in the repository row, and an Install command row reading npx notesync-mcp-server.
A server.json entry rendered as a header, a package table and an install command, with secret variables badged.

Tool annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) render as small coloured pills on the card, one colour per hint regardless of its declared value. Hovering or focusing a pill shows a tooltip stating exactly what that declared value means - for example, a tool with destructiveHint: true carries a pill labelled "destructive" whose tooltip reads "Declares the tool may perform destructive updates to its environment. Spec-meaningful only when the tool is not read-only." An annotation key the renderer does not recognise still shows as a plain grey pill with its own tooltip explaining that it is shown verbatim and uninterpreted. None of this is a security control: the MCP specification itself designates these as self-declared hints, and the renderer's summary panel states that caution exactly once, in its legend, not on every pill.

A capability card with a pill labelled "destructive" hovered, showing a tooltip that reads: Declares the tool may perform destructive updates to its environment. Spec-meaningful only when the tool is not read-only.
Hovering or focusing an annotation pill shows exactly what the declared hint means, sourced from the MCP specification's own wording.

Links behave the same way throughout: where a repository, website, $schema or package-registry URL is displayed, it is inserted as a clickable link. Where the link is for a recognised host (GitHub, GitLab, npm, PyPI, NuGet, Docker Hub), it is displayed as a labelled button for ease of reading (for example, "View on GitHub"). Every link opens through Confluence's own host application in a new tab, and only well-formed http or https URLs ever become links at all. Each package with a recognised registry type also gets a dedicated "Install command" row in its table (npx <name> for npm, pip install <name> for PyPI, and so on), shown as copyable code text to make your documentation immediately useful.

When a rendered document carries three or more capability cards, a summary panel appears directly below the Tools heading, listing every card by name. Where supported by your browser, selecting an entry brings that card into view and focuses it.

A rendered tools/list result with a table of contents listing 13 tool names as links, above a summary panel showing a legend of the four annotation colours plus a grey "other" row and the self-declared-hints caution line.
Three or more capability cards adds a summary panel with an annotation legend.

Editing and re-rendering

The pasted source is the one canonical copy: editing the macro and saving replaces it, and the page re-renders from the new source the next time it is viewed. Re-opening the editor always shows your stored source back, unchanged. A copy affordance in the top-right corner of the edit zone places the current draft on the clipboard byte-for-byte, including any characters the rendered view would otherwise strip - this is the one surface where the unedited paste survives.

The editor saves on Cmd+Enter (macOS) or Ctrl+Enter, and cancels on Escape, from anywhere inside the configuration panel; a hint in the actions row states the shortcut for your platform. Saving is disabled while your draft is over the size limit, and the editor panel fills the height Confluence gives it, so there is no dead space in the dialog at any Confluence-provided size.

Exporting to PDF and Word

Because the live document is drawn in your browser when the page is viewed, exporting the page to PDF or Word, or viewing its version history, runs a separate, stateless transform that reproduces the same content as native document structure: headings, tables and code blocks, not a flattened image. Tool annotation pills export as their plain label; the summary panel, its legend and the caution line export too, in the same order they render on the page, for documents that meet the three-card threshold.

If the stored source no longer parses as JSON at export time, the export falls back to that raw source in a code block instead of producing a blank page. If the macro has no stored source at all, the export is a short explanatory paragraph instead of an empty frame. An export can never be blank.

Edge cases and limits

Each edge case renders a specific, readable message in place of a blank or broken frame:

  • Empty. An unconfigured macro reads "No MCP document yet." and points you at the editor's sample document.
  • Invalid JSON. A paste that is not valid JSON reads "This document is not valid JSON.", with the parser's diagnostic message and, where the parser can report one, a line and column. The stored source itself still renders beneath the diagnostic, as a code snippet you can copy.
  • Over the size limit. Source over 512 KiB reads "This document exceeds the size limit.", naming your source's actual size against the 512 KiB cap. The same limit is enforced in the configuration editor, where saving is disabled once your draft is over, and on the live page, so a document that was valid when saved cannot later grow past the limit and break the page.
  • A JSON-RPC error response. A pasted error object, not a tool listing, reads "This document cannot be rendered.", naming the error code and message it carries instead of attempting to show it as documentation.
  • An unrecognised format. Valid JSON that matches neither server.json nor tools/list still renders, generically, under a "format not recognised" notice.
  • No tools declared. A tools/list result with an empty tools array renders an info notice saying so, not a blank page.
  • A partial list. A result carrying a nextCursor renders a warning notice that the server declares more tools than are shown.
  • Duplicate tool names. Every duplicate declaration still renders as its own card, with an info notice naming which tool names were duplicated.
  • Deeply nested parameters. A parameter schema nested beyond eight levels stops expanding as a table at that depth; the deeper structure is still available in the card's raw-JSON view.
  • An internal problem. Anything else that goes wrong falls back to a generic, readable "The renderer hit an unexpected problem." card instead of a blank macro.

Every rendered state that is not the document itself carries the renderer's engine version in a small footer; quote it if you contact support.

An error card reading "This document is not valid JSON.", showing a diagnostic message with a line and column, and the stored source rendered as a copyable code snippet beneath it.
Invalid JSON shows the parser's own diagnostic, plus the stored source itself, rather than a blank error.
A warning card reading "This document exceeds the size limit.", stating the source's size against the 512 KiB cap.
Source over 512 KiB is rejected before parsing, with the limit enforced in both the editor and the live page.

String hygiene and disclosure

Every string in a pasted document is treated as untrusted. Script tags, HTML and markdown syntax inside a pasted name, description or field render as plain visible text, never as HTML - so a hostile paste cannot inject a live element onto your page. A URL becomes a clickable link only when it parses as an http or https address; every other scheme, including javascript: and data:, renders as inert text instead.

Unicode bidirectional-override and zero-width characters, which can visually reverse text or hide characters from a reviewer, are stripped from every rendered string before display. When a paste actually contained any, the rendered page carries a plain info notice disclosing it: "Control characters (bidirectional overrides or zero-width characters) were removed from the rendered text. The stored source is unchanged." Nothing is silently normalised without that disclosure, and the underlying stored source itself is never altered - only the rendered display and the copy button that follows it are affected. The editor's own copy affordance, described above, is the one place the untouched paste is available verbatim.

An info notice at the top of a rendered document reading: Control characters (bidirectional overrides or zero-width characters) were removed from the rendered text. The stored source is unchanged.
When a paste contains invisible bidirectional or zero-width characters, the renderer strips them and discloses it plainly.

Security and privacy

The app requests no Confluence or Jira permissions at all: its manifest declares an empty scope list, so it cannot read your pages, modify content, or see account or directory data beyond what you paste into its own configuration. It declares no external network destination of any kind, and it operates no storage of its own - the pasted source lives only in the macro's own configuration on your Confluence page, and rendering happens client-side, in your browser, when the page is viewed.

One narrow exception applies. When a page is exported to PDF or Word, or its history is viewed, a single stateless, server-side function reads the pasted source from that request only, to reproduce the same document as native content (see "Exporting to PDF and Word" above); it stores nothing and makes no network call of its own. Links you click open through Confluence's own host application, which is your browser's navigation carried out by the host, not a request the app makes itself. For the full detail, see the Privacy Policy; our broader posture is described on the Security and Trust Center pages.

About MCP

Cloudscript Renderer for MCP Documentation is an independent tool and is not affiliated with, or endorsed by, the Model Context Protocol project. It does not implement the protocol and does not connect to any MCP server; it renders documents you paste into it. Model Context Protocol® and MCP™ are marks of their respective owners. Learn more about the protocol at modelcontextprotocol.io.

Legal

Terms and privacy specific to this app: