Zuar Portal Blocks MCP Server
This server lets you manage HTML blocks and explore data on a Zuar Portal through an MCP client like Claude.
Block Management:
List blocks – Retrieve all portal blocks, optionally filtered by ID or returning only id+name pairs
Get a block – Fetch a single block's full details, including HTML/CSS and query configuration
Create an HTML block – Author a new block with name, CSS, data/query config, tags, and access controls
Update an HTML block – Partially modify any field of an existing block by UUID
Delete a block – Permanently remove a block by UUID
Data Source & Query Discovery:
List datasources – Discover available datasources to find the correct UUID for wiring blocks to data
List saved queries – Retrieve saved queries (Portal 1.18+), with a graceful fallback for older portals
Data Exploration:
Fetch sample rows – Preview up to 50 real rows from a datasource to see accurate column names and values before authoring a block
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Zuar Portal Blocks MCP ServerCreate an HTML block that displays a bar chart of monthly sales"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Zuar Portal — MCP Server
Let Claude operate your Zuar Portal (zPortal) for you — author HTML blocks, build pages, manage data sources, queries, themes and users, explore real data, and keep a git-versioned, revertible history of every change, all through natural language.
An MCP server that exposes a Zuar Portal's REST + auth APIs to any MCP client (Claude Desktop, Claude Code, …). It turns "build me a sales dashboard" into the right sequence of authenticated calls — discover data sources → write a saved query → author a validated HTML block → bind it → place it on a page — with bundled authoring guidance, layered write-safety, and a revertible history.
Quick install (Claude Desktop): download zuar-portal-mcp.mcpb from the latest release and double-click it. You'll be asked for three portal values — no terminal, no config files. Jump to install ↓
At a glance
flowchart TB
CD["<b>MCP Client</b><br/>Claude Desktop · Claude Code · any MCP client"]
CD -- "JSON-RPC / stdio" --> S
subgraph server["zuar-portal-mcp server"]
direction TB
S["index.ts → buildServer()"]
S --> BT["🧱 <b>Block tools</b><br/>typed authoring + place_blocks"]
S --> RT["📦 <b>Resource tools</b><br/>generic CRUD · 18 kinds (blocks included)"]
S --> AT["⚡ <b>Action tools</b><br/>query · profile · users · config"]
S --> VC["🕓 <b>Version-control tools</b><br/>snapshot · history · diff · restore"]
S --> EL["🪄 <b>Setup & design</b><br/>configure_project · synthesize_theme"]
G{{"🛡️ <b>Safety & integrity gates</b><br/>write-domain · structure · refs · impact · SQL"}}
BT & RT & AT & VC & EL --> G
end
G --> HTTP["portalClient.ts<br/>login · X-Api-Key · retry · circuit breaker"]
HTTP -- "/api + /auth · HTTPS" --> P[("Zuar Portal")]
BT -. "mirrors every content write" .-> GIT[("git VC repo<br/>revertible")]
classDef gate fill:#fde68a,stroke:#b45309,color:#000;
class G gateEvery write is tagged with a risk domain and passes the safety gates before anything reaches the portal; every successful content write is mirrored to a git repo so it can be reverted.
Related MCP server: AutoWP MCP Server
Contents
What Claude can do with it — the 37-tool catalog
The Claude Code agent ecosystem — pipeline, agents, model/effort routing
Troubleshooting · Development · Bundle · Security · License
📚 Full documentation lives in docs/ — overview, install & config, a reference for all 37 tools, block authoring, the design system, version control, the in-block zPortal API, the agent ecosystem & model routing, tool gating, safety gates, and troubleshooting.
Highlights
🧰 One uniform surface (v3.0.0) | 37 tools, one model — blocks are a validated registry kind, one declarative |
🖱️ One-click install | A signed |
🧱 Validated authoring | HTML blocks go through rule-checked tools ( |
🏢 Multi-portal, multi-repo (v2.4.0) | One install drives a different portal + git repo per folder via |
🪄 Guided, no-JSON setup |
|
🤝 A team of agents | In Claude Code, a gated build → style → responsive → debug → adversary → advisor pipeline of specialist subagents builds blocks for you — each on a right-sized model. |
🔒 Enterprise safety (v2.5–2.6) | Risk-domain write gating, least-privilege tool scoping, structural + referential integrity gates, pre-delete impact analysis, and an opt-in audit log. |
🕓 Revertible history (v2.2.0) | Every content write mirrors to a git repo — revert any change with |
What Claude can do with it
37 tools — one uniform surface ("a resource is a resource") across 11 capability groups. The full per-tool reference (params, risk domain, examples) is in docs/03 · Tools Reference.
Upgrading from 2.x? v3.0.0 is a breaking redesign (48 → 37 tools). Every removed v2 name maps to a v3 primitive — see CHANGELOG.md. Set PORTAL_COMPAT_TOOLS=1 to temporarily register the old names as deprecated aliases that forward to the same gated v3 handlers.
🧱 Block tools — typed + validated
Blocks are now a first-class registry kind: list, fetch, and delete them with the generic resource tools (resource: "block"), and the block-authoring rules run as a per-kind validator at the registry write chokepoint — create_resource (block) is validated exactly like create_block. The typed fronts remain for ergonomic authoring:
Tool | What it does |
| Run the authoring rules against a block payload without writing — iterate until clean. |
| Create an HTML block (validated against authoring rules). |
| Update an HTML block — merged over the current block so untouched fields survive. |
| Bind a block to a datasource/query (auto-creates the query); sets |
| One declarative placement primitive — add, update, hide, or remove blocks on a page grid in a single atomic write. |
Pass resource plus a body/id. Call describe_resource to see each resource's fields, required-to-create fields, supported verbs, and risk domain.
Tool | What it does |
| List resources, or describe one (fields, verbs, domain). |
| List records — always returns the paged envelope |
| Get one record by id — e.g. |
| Search by name (case-insensitive substring, or exact id) across kinds — optional |
| Read-only dependency query, both directions: |
| Create a record (write-gated by domain; per-kind validators — blocks get the full authoring rules). |
| Update a record (merged over current; write-gated). |
| Delete a record (write-gated; pre-delete impact analysis; |
| Read-only sweep for malformed records, dangling refs, and risky SQL. |
Covered resources: block, layout (pages), datasource, query, db_modification, partial, theme, snippet, translation, dashboard, tag, user, group, permission, access_policy, api_key, credential, system.
Every write tool accepts
dry_run: true— every gate runs (domain, structure, per-kind rules, references, impact), nothing is written, and the response carriesapplied: falseplus what would have been written.
Tool | What it does | Domain |
| Per-column stats (type, distinct values, min/max) plus raw sample rows ( | read |
| Run a saved query by id and return results (optional row | read |
| Run a saved DB write by name. Needs | data |
| Change the current user's password. | admin |
| Read a user's group membership and permissions in one call. | read |
| Replace a user's groups and/or permissions — each provided list is a full replace; needs | admin |
| Read / set portal config by path. | read / admin |
| Portal version + about (capability check). | read |
| Show active block-authoring rules. | read |
| The | read |
| Report the current posture — enabled/disabled tool groups, write-safety, VC + audit status, and the active config (portal / VC repo, secrets redacted) under its | read |
| Per-tool call count, error rate, latency, uptime, breaker state (always available). | read |
| Connect this folder to a portal — guided (elicitation: portal creds + optional GitHub VC, both validated live) or headless with | setup |
| Re-read config from disk (project/bundle/env) without a restart; resets the portal session. | setup |
| Pure theme synthesis — preferences (± an SSRF-guarded website color fetch) → a token map plus the exact | design |
| Read-only migration audit — every block classified by function, all code-bearing fields scanned (comment/string-aware), placement via layouts/partials/snippets, hardcoded-origin sweep, bound-query preflight, browser-probe checklist. | migration |
| Refresh a saved query's stored column metadata from a live execution — SQL untouched, dry-run by default, round-trip verified. | migration |
The current user's profile is plain resource CRUD now:
get_resource/update_resourcewithresource: "user", id: "me". Guided migration scoping is themigration_kickoffprompt (see Prompts below).
Tool | What it does |
| Show whether VC is configured and the repo state. |
| Commit the full current portal state to the git repo — a durable checkpoint. |
| Show the commit history of content changes. |
| Unified diff between two committed versions — record-scoped ( |
| Restore a resource to a previous committed version. |
See docs/07 · Version Control.
Resources (zportal://guide/*) — authoring guidance Claude reads before building, so blocks follow zPortal conventions even on a fresh machine: block-structure, currentblock, zportal-api, charting, conventions, design-system, visual-verification, migration-1.18, loading-overlay, migration-playbook, and block-performance.
Prompts — guided workflows now live here rather than in the tool surface (8): zuar_portal_quickstart (orient → route), create_zportal_block (discover → build → create), setup_zuar_project (connect this folder, routes to configure_project), migrate_block_to_118 (one legacy block → the 1.18 lifecycle), add_loading_overlay (the sanctioned spinner + fade-out), block_perf_pass (the large-dataset perf audit: measure → trim SELECT * → chart-lib prefetch → 60 s honest timeouts), design_intake (guided theming — walks brand/website/density/radius, drives synthesize_theme, then creates the theme via create_resource), and migration_kickoff (guided migration scoping — batches the scope decisions, writes .zuar-portal/migration-scope.json, then runs migration_preflight).
The Claude Code agent ecosystem
When this repo is your Claude Code working directory, the MCP tools come with a team of specialists in .claude/. You don't drive create_block/bind_block_query by hand — you describe what you want, and a gated pipeline builds, styles, hardens, and reviews it. Full guide: docs/13 · Agents & Workflows.
The block pipeline
Blocks are never shipped raw. A spec flows through quality gates, each a focused subagent:
flowchart LR
spec([spec]) --> B["🏗️ builder"] --> St["🎨 stylist"] --> R["📱 responsive"] --> D["🔧 debugger"]
D --> A{"🚨 adversary<br/><b>CODE GATE</b>"}
A -- "blocking (≤2 rounds)" --> D
A -- "clean" --> V{"👁️ visual<br/><b>GATE</b>"}
V -- "blocking (≤2 rounds)" --> D
V -- "clean / skipped" --> Ad["🧭 advisor"] --> ship([ship ✅])
classDef gate fill:#fde68a,stroke:#b45309,color:#000;
classDef ro fill:#dbeafe,stroke:#1d4ed8,color:#000;
class A,V gate
class Ad roThe adversary (gate) red-teams the block and proves each finding with evidence; while it returns blocking findings the pipeline loops back to the debugger. The visual gate (the adversary with browser eyes) then opens the rendered block in Claude for Chrome — screenshot, console, network — and a blank render, console error, sample-not-live data, or overflow loops back to the debugger too; it's best-effort and skips with a note when the extension isn't connected or the block isn't on a page. The advisor asks "is this the right block?" All gates are read-only — they carry no write tools and physically cannot mutate the portal (browsing/screenshotting is read-only). Beyond the six pipeline agents, four specialists handle broader jobs: portal-data-expert, portal-theme-designer, portal-bulk-operator (snapshot-first), and portal-onboarding.
Seeing the portal (Claude for Chrome)
Every gate above reasons about a block from its code and query rows — but a block can validate, bind, and still render blank, throw a runtime console error, overflow its grid cell, or silently show its hardcoded sample fallback instead of live data. With the Claude for Chrome extension connected, the agents can see the portal: open the page, screenshot the block, and read the browser console/network — for visual debugging and a final visual sign-off.
Recorded at setup.
configure_projectasks whether you use Claude for Chrome and storesbrowser.claudeInChromein./.zuar-portal/config.json;get_capabilitiesreports it.Used where it pays. The debugger looks before it guesses; the adversary owns the visual gate; the stylist and responsive-specialist screenshot their work (the latter steps widths with
resize_window); the advisor checks it reads at a glance.Sign-in caveat. The MCP authenticates with an API key, but the browser needs a logged-in session — to view private pages you must be signed into your portal in Chrome. The MCP can't log you in.
Graceful by design. No extension, or the block isn't on a page? Every agent falls back to code-only review and says so. The doctrine lives in the
zportal://guide/visual-verificationresource.
Slash commands
Command | What it runs |
| First-time per-folder setup + alignment Q&A → config + project brief. |
| The full build→style→responsive→debug→adversary→advisor pipeline for one block. |
| Design or apply a portal-wide theme. |
| A guarded bulk change across many blocks/pages (snapshot → dry-run → atomic apply). |
| Read-only audit of existing blocks — bugs, a11y, responsiveness, design fit. |
| Run the alignment Q&A on its own. |
Model & effort routing
Each agent runs on the model and reasoning effort that fit its job — sharp where judgment matters, cheap where the work is mechanical. Three composing layers:
1 · Agent defaults (model:/effort: frontmatter) — for a direct call (a fast surgical edit, or one agent dispatched from a command):
Tier | Agents | Model · effort |
🧠 Judgment / data | data-expert, adversary, advisor |
|
🛠️ Authoring | builder, stylist, debugger, bulk-operator, theme-designer, onboarding |
|
⚡ Mechanical | responsive-specialist |
|
2 · Workflow tier toggle — portal-block-pipeline.js and portal-audit.js take args:{ …, tier } and set each stage's model/effort explicitly:
| For… | Builders | Judgment gates |
| cheap iteration, throwaway drafts, triage | sonnet/haiku · low | sonnet · medium |
| a normal build / audit | sonnet · medium | opus · high |
| production / executive build, pre-release audit | opus · high | opus · xhigh |
3 · Commands pin to sonnet · medium — they only orchestrate (pre-flight → dispatch → synthesize); quality lives in the agents/workflow they call. /portal-build and /portal-audit infer the tier from your phrasing.
The MCP server never selects a model — only the agents, commands, and workflows that drive it do. Re-tier via agent frontmatter or a workflow's
ROUTINGtable; see.claude/README.md.
Guided onboarding & theming (elicitation)
On a client that supports elicitation (Claude Desktop, Claude Code), configure_project prompts you field-by-field instead of making you hand-edit JSON — and validates everything live before committing. Guided theming is now the design_intake MCP prompt, which orchestrates the pure synthesize_theme tool. If the client can't prompt, configure_project falls back to argument-only mode (interactive: false).
flowchart TB
subgraph setup["🔌 configure_project — connect a portal"]
direction TB
s1["Portal URL"] --> s2["API key 🔒"] --> s3["User ID"] --> s4{"add GitHub VC?<br/>(optional)"}
s4 --> s4b{"use Claude for Chrome?<br/>👁️ visual checks"}
s4b --> s5["✓ live portal login<br/>✓ GitHub token + repo (API)"] --> s6[["writes .zuar-portal/config.json<br/>+ .gitignore"]]
end
subgraph intake["🎨 design_intake prompt — theme the portal"]
direction TB
d1["brand + website"] --> d2["fetch site 🛡️ SSRF-guarded<br/>→ suggest brand colors"] --> d3["palette · density · radius"]
d3 --> d4["header + sidebar style"] --> d5{"confirm?"} --> d6[["synthesize_theme →<br/>create_resource (theme)"]]
endconfigure_projectrefuses to clobber an existing config, validates with a real login, and writes a gitignored./.zuar-portal/. It also asks whether you use Claude for Chrome (stored asbrowser.claudeInChrome) so the build pipeline can see your blocks render — visual debugging + a final visual gate (see Seeing the portal). Thesetup_zuar_projectprompt and/portal-setuproute to it; passinteractive: falsefor the direct, no-prompt path. (Replaces v2'ssetup_portalandinit_project_config.)The
design_intakeprompt fetches the brand's website throughsynthesize_theme's SSRF-guarded fetch to suggest a palette, then walks density/radius/header/sidebar and, on your confirmation, creates athemeresource viacreate_resource.synthesize_themeitself is pure — it returns the token map and the exactcreate_withcall, and never writes.
Requirements
A Zuar Portal reachable over HTTPS, with an account that can manage blocks (admin recommended).
Claude Desktop for the one-click
.mcpb(Node ships with it) — or Node.js 18+ for the developer /npxpath.
Getting your portal credentials
You need three values, entered once during install.
# | Value | Where |
1 | Portal URL | The base URL, no trailing path — e.g. |
2 | Portal API Key | Admin → Auth → API Keys → create/copy a key. It inherits its user's permissions — that user must be able to create/edit/delete blocks. |
3 | Portal User ID | Admin → Users → your user → copy the UUID from the page URL. |
Keep the API Key and User ID private. In the Claude Desktop bundle they're declaredsensitive (masked, stored securely) and never leave the machine running the server.
Install — Claude Desktop (one-click)
Download
zuar-portal-mcp.mcpbfrom the latest release.Double-click it, or drag it onto the Claude Desktop window. An install dialog appears.
Fill in Portal URL, Portal API Key, Portal User ID (and optionally the write-safety toggles).
Confirm. The tools, resources, and prompts are now available to Claude.
To update later, install a newer .mcpb over the old one.
Install — Claude Code & other MCP clients
This server speaks MCP over stdio, so any MCP-capable client can use it. Provide the three values as environment variables.
From a local clone (works today):
git clone https://github.com/patrickdeanfox/zuar-portal-mcp.git
cd zuar-portal-mcp
npm install
npm run build # compiles TypeScript -> dist/Then register it in your client's MCP config (claude_desktop_config.json, or .mcp.json for Claude Code):
{
"mcpServers": {
"zuar-portal-blocks": {
"command": "node",
"args": ["/absolute/path/to/zuar-portal-mcp/dist/index.js"],
"env": {
"PORTAL_URL": "https://your-portal.zuarbase.net",
"PORTAL_API_KEY": "your-portal-api-key",
"PORTAL_USER_ID": "your-portal-user-uuid"
}
}
}
}{
"mcpServers": {
"zuar-portal-blocks": {
"command": "npx",
"args": ["-y", "zuar-portal-mcp-server"],
"env": {
"PORTAL_URL": "https://your-portal.zuarbase.net",
"PORTAL_API_KEY": "your-portal-api-key",
"PORTAL_USER_ID": "your-portal-user-uuid"
}
}
}
}Per-project configuration (multiple portals)
One MCP install can drive a different portal — and a different git state-repo — in every folder. At startup the server resolves credentials in layers, highest priority first:
flowchart LR
A["1 · Project config<br/><code>./.zuar-portal/config.json</code><br/>(walks up from cwd)"] --> R{{"resolved<br/>credentials"}}
B["2 · Environment<br/><code>PORTAL_*</code> env vars<br/>(Desktop / MCPB)"] --> R
C["3 · Bundle config<br/><code>config.json</code> beside bundle"] --> REach field resolves independently, so a project file can override just the portal while inheriting the rest. Empty values are ignored, so a blank Desktop field never shadows a project value. The file uses one schema for both the portal and its VC repo:
{
"portal": { "url": "https://team-a.zuarbase.net", "apiKey": "…", "userId": "…" },
"vc": { "dir": "/path/to/team-a-state", "push": true,
"remote_url": "https://github.com/you/team-a-portal-state.git", "token": "…" }
}Set it up without hand-editing JSON: ask Claude to run configure_project (see Guided onboarding ↑). get_capabilities shows which portal/repo is in effect under its config key (secrets redacted). ./.zuar-portal/ is gitignored, so credentials are never committed.
Getting started
Once installed, just talk to Claude:
Confirm the connection — "List the datasources on my portal." →
list_resource (datasource).Look at real data — "Show me a few sample rows from the Sales datasource." →
profile_datasource(per-column stats + raw sample rows, so Claude sees the real column names first).Create a block — "Create a stat-card block 'Total Orders' showing the order count from Sales." → reads
zportal://guide/*, builds the two-field block,create_block, reports the UUID.Iterate — "Make the number bigger and use the portal's primary color." / "Turn it into a bar chart of orders by state." →
update_block.
InClaude Code, run /portal-build "a stat card of total orders from Sales" to push the spec through the whole gated pipeline, or invoke the create_zportal_block prompt for a structured discover → build → create flow.
Write safety & tool gating
Every write is tagged with a risk domain, gated independently:
Domain | Covers | Default | Enable with |
| blocks, layouts, partials, themes, queries, snippets, translations, dashboards, tags | on | (on unless read-only) |
| datasources, db_modifications, | off |
|
| users, groups, permissions, access policies, API keys, credentials, system, config, passwords | off |
|
PORTAL_READONLY=1disables every write — reads and discovery still work.A blocked write returns a clear message naming the flag to set; nothing reaches the portal.
run_db_modificationadditionally requiresconfirm: trueon every call.Deletes and user/password mutations are marked destructive to MCP clients.
Uniform
dry_run: true(v3.0.0) on every write tool — all gates run (domain, structure, per-kind rules, references, impact) but nothing is written; the response reportsapplied: falseand what would have changed. A dry run never bypasses a gate.
Least-privilege tool scoping (v2.5.0) — disable whole capability groups with PORTAL_DISABLE_TOOLS=users,config, or stand up a build-only allowlist with PORTAL_ENABLE_TOOLS=blocks,resources,data (deny wins).
Upgrading from 2.x — PORTAL_COMPAT_TOOLS=1 (off by default) registers the removed v2 tool names as deprecated aliases in a compat group; each alias forwards to the same gated v3 handler, so aliases confer no extra capability.
Integrity gates (v2.5–2.6, server-side, cannot be bypassed) — every content write is checked for portal-compatible structure (a page missing grid.layouts is repaired or rejected) and dangling references; deletes run pre-delete impact analysis and refuse to orphan dependents unless force=true; user deletes refuse to remove the last admin; unscoped mass SQL needs allow_unfiltered=true. Run the read-only validate_portal anytime to sweep for problems. Full guide: docs/16 · Safety & Integrity.
In the Claude Desktop bundle these are install-dialog toggles; for other clients set them as env vars. Deeper dive: docs/14 · Tool Gating & Guidance.
Resilience, observability & hardening
Production-grade behaviour for a local, single-user server — safe defaults, no configuration required.
Resilience (the portal HTTP client every tool calls through):
Behaviour | Default | Tune with |
Per-attempt timeout | 30 s |
|
Retries on transient failure (network, 408/425/429/5xx), exp. backoff + jitter, honouring | 2 |
|
Circuit breaker — fail fast while the upstream is down | opens after 5 failures, 15 s cooldown |
|
Max request body size | 5 MB |
|
Max tool input size (rejected at the MCP boundary) | 2 MB |
|
Retry safety: GET retries on any transient signal; writes retry only on a pre-response network error or explicit 429/503 — never on an ambiguous 502/504 that may already have applied.
Observability — every call gets a request id, latency, and an error tally. get_metrics (always-on) reports per-tool counts, error rate, latency, uptime, and the breaker state — metadata only, no payloads or secrets. Set PORTAL_LOG_FORMAT=json for structured stderr logs; PORTAL_AUDIT_LOG appends metadata-only JSONL for every content/data/admin write.
Output secret redaction — secret-bearing fields (password, secret, token, api_key, …) are masked as [redacted] on resource reads, so they never flow into the model's context. Identifier *_id fields are never masked; create/update responses are intact (so a freshly generated secret can be seen once). Disable with PORTAL_REDACT_SECRETS=0.
Troubleshooting
Symptom | Likely cause / fix |
"Missing portal credentials: …" | One of |
"Portal login failed: HTTP 401/403" | Wrong API key or user ID, or the user lacks permission. Regenerate the key; confirm the user can manage blocks. |
| Your portal predates the saved-queries API (1.18+). Use |
Tools don't appear in Claude | Reinstall the |
A v2 tool name is missing ( | v3.0.0 removed/renamed it — see |
Want to see what it's doing | Set |
"circuit breaker is open" | The upstream failed repeatedly; it auto-recovers after a short cooldown. |
A stored secret returns | Read redaction is on. Set |
More: docs/12 · Troubleshooting.
Development
npm install
npm run build # tsc -> dist/
PORTAL_DEBUG=1 npm start # run locally on stdio (debug logs to stderr)
npm test # build + run the test suite (no portal/network needed)
npx @modelcontextprotocol/inspector node dist/index.js # interactive testingTests (npm test, no credentials / no network): rules.test.ts (the block validator — each footgun rule + partial-update behaviour), config.test.ts (write-safety posture + tool-gating policy), contract.test.ts (end-to-end MCP contract: initialize, tools/list, input-schema rejection, validation, gating).
Project layout:
src/ # MCP server source (compiled to dist/)
index.ts # stdio entrypoint
server.ts # tools, resources, prompts
portalClient.ts # auth + request (login, X-Api-Key, retry, breaker)
config.ts # layered credential resolution + write-safety + tool gating
resources.ts # generic resource registry
rules.ts # block authoring rules + validation
structure.ts # structural write-gate (portal-breaking-shape guard)
safety.ts # referential integrity, pre-delete impact, SQL/admin gates
naming.ts # scope·kind·subject naming grammar
design.ts / theme.ts / color.ts / website.ts # design system + synthesize_theme (design_intake prompt)
github.ts # GitHub VC validation for configure_project
portalVc.ts # git version control of content writes
guidance.ts # bundled authoring guidance (zportal://guide resources)
observability.ts / redact.ts # metrics + secret redaction
assets/ # runtime-loaded: conventions.md, design.md, rules.json
.claude/ # Claude Code agent ecosystem (agents, commands, skills, workflows)
docs/ # user documentation
reference/ context/ # API swagger + corpus + dev notes (not shipped in the .mcpb)For local dev, drop a project config at ./.zuar-portal/config.json (or run configure_project) instead of env vars. ./.zuar-portal/ and any config.json are gitignored — never commit them.
Building the .mcpb bundle
npm install -g @anthropic-ai/mcpb # or: npx @anthropic-ai/mcpb <cmd>
npm install && npm run build
npm prune --omit=dev # production node_modules only
mcpb validate manifest.json
mcpb pack # -> zuar-portal-mcp.mcpb.mcpbignore excludes src/, dev files, local config, and the non-runtime reference/, context/, .claude/ dirs. Attach the .mcpb to a GitHub Release for one-click install.
Security
Credentials are never logged. Debug output (gated by
PORTAL_DEBUG=1) goes to stderr only, so it never corrupts the MCP stdio stream.The API Key and User ID are declared sensitive in the bundle manifest.
The server talks only to the Portal URL you configure; the base URL is validated as a well-formed
http(s)origin at startup.synthesize_theme's website fetch (driven by thedesign_intakeprompt) is SSRF-guarded.create_block/update_blockare restricted totype: "html"and reject other types before any portal call.Secret-bearing fields are redacted from reads; tool inputs and request bodies are size-capped.
See SECURITY.md for the full posture: the per-tool-group data-touch matrix, credential handling, network egress, and data retention.
License
MIT.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/patrickdeanfox/zuar-portal-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server