Zuar Portal Blocks MCP Server
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| PORTAL_URL | Yes | The base URL of your Zuar Portal, e.g. https://your-portal.zuarbase.net | |
| PORTAL_API_KEY | Yes | Your portal API key from Admin > Auth > API Keys | |
| PORTAL_USER_ID | Yes | Your portal user UUID from Admin > Users > your user |
Capabilities
Features and capabilities supported by this server
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| prompts | {
"listChanged": true
} |
| resources | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| create_block | Create a new HTML block. Accepts the full block payload (name, css, json_data, ui_queries, tags, access). Type is always html. Read the zportal://guide/* resources first to produce a correct two-field block. Equivalent to create_resource resource="block" with a typed schema; the authoring rules, structural and referential gates run either way. dry_run:true previews. |
| update_block | Update an existing HTML block by UUID. Only the fields you pass change — the server merges them over the current record, so an omitted ui_queries keeps the existing data binding. Authoring rules validate only your delta; violations the stored block already has are grandfathered to warnings, never blockers. dry_run:true previews the exact write. |
| bind_block_query | Give an existing block its data binding so currentBlock.queryResults[0] is populated. Pass an existing query_id, OR a datasource_id (a |
| place_blocks | Declaratively manage which blocks a page (layout) shows, in ONE atomic read-modify-write. mode=merge (default): upsert the |
| validate_blockA | Run the same authoring rules as create_block/update_block against a block payload WITHOUT writing it. Use it to iterate on HTML/JS/CSS until it's clean — it flags the footguns that only surface in a live browser (literal |
| describe_resourceA | Show a resource's path, write fields, required-to-create fields, supported verbs, and risk domain. Omit |
| list_resourceA | List records of a resource (block, datasource, layout, query, theme, partial, user, group, db_modification, etc.). Use this for discovery — e.g. find a datasource UUID before authoring a block. Always returns the paged envelope { total, offset, limit, returned, truncated, records } (default page size 100, max 500) — check |
| cleanup_scratchA | Find records that scratch conventions mark as disposable — a name starting 'TMP ·', a 'scratch'/'tmp' tag, or '(delete me)' in the name; optionally '(diagnostic)' records and unnamed ones. DRY-RUN BY DEFAULT: reports every match, why it matched, and what (if anything) references it. confirm=true deletes only the safe candidates — unreferenced, not recently touched — through the same gated delete path as delete_resource. Content deletes are VC-recorded (restorable); db_modification deletes are NOT restorable and only ever match the explicit TMP/scratch markers. |
| score_portalA | Score every block and page 0–100 on what is MECHANICALLY checkable — authoring-rule violations, dangling query bindings, orphaned blocks, naming-convention fit, SELECT * bindings, oversized HTML, unscoped CSS, page overflow and dangling placements. 100 means 'nothing mechanically wrong', NOT 'well designed' — visual/business judgment stays with review agents. Scratch-marked records are excluded (cleanup_scratch handles them). With version control on, compares against the last saved baseline (improved/regressed/added/removed per record) — the loop discipline: score, improve, re-score, and only update_baseline=true after a verified improvement. |
| find_resourceA | Search records across resource kinds by name — "find the query named X" without listing whole collections client-side. Case-insensitive substring match on name/title, plus exact-id match. Defaults to every non-admin kind (block, layout, partial, theme, query, snippet, translation, dashboard, tag, datasource, db_modification); pass |
| get_references | Read-only dependency query for a record, both directions: |
| get_resource | Fetch a single record of a resource by its id (or name, for tags). Control the token cost: summary:true returns an overview (bulk fields become size stats — a block drops ~2,750 → ~150 tokens); fields:[…] returns just those top-level fields (+ id). Omit both for the full record. |
| create_resource | Create a record. |
| update_resource | Update a record by id. Only the fields in |
| delete_resource | Delete a record by id (or name, for tags). Requires confirm:true. Same write gating as create_resource — the record's risk domain must be enabled. Refuses if other records depend on the target (pass force=true to override) and refuses to remove the last admin / your own account. Content records can be reverted with restore_resource when version control is on. |
| validate_portalA | Sweep every page (layout), partial, theme, query, block, db_modification and system record and report anything that would break or render wrong: structurally malformed records (e.g. a page missing grid.layouts — the 'all pages vanished' bug), dangling references (a page/block pointing at a deleted block/query/datasource), unscoped mass-write SQL (UPDATE/DELETE with no WHERE, TRUNCATE, DROP), and datasource hygiene (a name that leaks a connection-string/password, or a datasource reporting a broken connection). Fixes nothing — run it after bulk changes or on a schedule to catch latent breakage before users do. |
| get_rulesA | Return the active block-authoring rules: per-rule enforcement severities and the conventions text. Read this to see what create_block/update_block will enforce. |
| namingA | The |
| get_versionA | Fetch the portal version and about info — use it to gate version-specific endpoints (e.g. saved queries are 1.18+). To confirm the connection, call check_connection instead. |
| profile_datasourceA | Sample a datasource and return per-column statistics — inferred type, non-null/empty counts, distinct value count, sample distinct values for categoricals, and min/max for numerics — PLUS raw sample rows ( |
| execute_queryA | Run a saved query by id and return its results. Pass |
| run_db_modificationA | Execute a saved db_modification (INSERT/UPDATE/DELETE) by name. This WRITES to a database — and database writes have NO snapshot/rollback, unlike portal content. Requires data writes enabled (PORTAL_ALLOW_DATA_WRITES=1) and confirm=true. Refuses an unscoped mass write (UPDATE/DELETE/MERGE without a real WHERE — 1=1 doesn't count — TRUNCATE, DROP, ALTER…DROP, GRANT/REVOKE) unless allow_unfiltered=true; the check is a best-effort classifier and fails closed if the SQL can't be inspected. Pass |
| change_passwordA | Change the authenticated user's password. Requires admin writes enabled (PORTAL_ALLOW_ADMIN_WRITES=1) and confirm=true — this rotates the credential the current session signs in with. Passwords are never logged or echoed back. |
| get_user_accessA | Return the groups a user belongs to and the permissions granted to them, in one call. The user record itself is get_resource resource="user" (id "me" = the authenticated user). |
| set_user_access | Replace a user's group membership and/or permission set — pass |
| get_configA | Fetch the portal's configuration document. |
| update_config | Set a value at a config path. |
| check_connection | START HERE — confirm in ONE authenticated round-trip which Zuar Portal this folder is on, its version, who you're signed in as, what you may write, and whether browser assist is on. Proves the credentials actually work, and on failure reports the reason and the fix. Returns a few short fields rather than a JSON wall — call get_capabilities only if you then need the full tool/group, VC and audit posture. |
| get_capabilities | Report what this server can currently do AND which portal it's pointed at: enabled/disabled tool groups and tools, the write-safety posture (read-only / data / admin), the resolved project config (portal URL + user, config file path), version-control status, browser-assist flag, and whether audit logging is on. THE orientation call — run it before acting; it stays available even when other tool groups are gated off. All secrets are redacted. |
| get_metrics | Report in-memory observability metrics for THIS server process: per-tool call count, error count/rate, and latency (avg/max/last ms), plus rolled-up totals, uptime, and the upstream circuit-breaker state. Metadata only — no payloads or secrets. Resets when the process restarts. Use it to spot a failing tool or a degraded portal upstream. |
| configure_project | Connect THIS folder to a Zuar Portal — one install can serve many portals, each folder gets its own ./.zuar-portal/config.json. Collects the portal credentials (URL, API key, user ID), a name for the portal, the design intake (brand accent, light/dark, density) and — optionally — GitHub version-control settings (repo URL, PAT, local mirror path) and the Claude-for-Chrome preference, PROMPTING field-by-field via MCP elicitation when the client supports it (interactive:false forces headless argument-only mode; any field passed as an argument is used as-is and not prompted for). Validates the portal with a live login and the GitHub token/repo against the GitHub API, then writes: the config + a .gitignore (so secrets never get committed), a project design.md every block here inherits, and a managed CLAUDE.md block naming the bound portal. PINS the folder to the portal's live identity, so later writes to a DIFFERENT portal are refused instead of silently landing there. Refuses to overwrite an existing config unless overwrite=true. Secrets are stored locally and never echoed or logged. |
| reload_config | Drop every in-process config cache and re-read config from disk (project .zuar-portal/config.json, bundle config, env-derived settings), resetting the portal HTTP session. Use after MANUALLY editing a config file — edits to the already-loaded project file are also picked up automatically (mtime-aware), but a NEWLY CREATED config file or bundle/env change needs this. Note: tool-surface gating is registered at startup and still needs a server restart to change. |
| synthesize_theme | Turn brand preferences into a portal theme spec — a customProperties token map + css — WITHOUT creating anything. Give a website_url and it fetches the homepage (SSRF-guarded) to suggest brand colors when primary_color is omitted. Create the returned theme with create_resource resource="theme" body={ name, json_data: { customProperties, css } } (a normal VC-tracked content write); the response includes that exact call as |
| vc_status | Report whether portal version control is enabled (set PORTAL_VC_DIR to a git repo path), the repo location, and push config (PORTAL_VC_PUSH / PORTAL_VC_REMOTE). When enabled, every content write (blocks, layouts, queries, themes, partials, snippets, translations, dashboards, tags) is auto-committed so it can be reverted with restore_resource. |
| snapshot_portalA | Export every content resource (blocks + layouts/queries/themes/partials/snippets/translations/dashboards/tags) AND datasources to the version-control repo and commit. Run once to seed history, or anytime to capture a checkpoint. Verifies COVERAGE: staged counts are checked against live listings and any resource kind that failed to export is reported (a rollback snapshot that silently skipped saved queries is not a rollback). Requires PORTAL_VC_DIR. |
| vc_log | List recent commits, optionally scoped to one record. Use a returned hash with restore_resource to revert to that version. Requires PORTAL_VC_DIR. |
| vc_diff | Unified diff between two committed versions — of one record (resource + id) or the whole repo. Defaults answer "what did the last change change?": ref_b = HEAD, ref_a = the previous commit touching the record (or HEAD's parent repo-wide). Pass hashes from vc_log for any pair. Inspect the diff BEFORE restore_resource so a revert is never blind. Requires PORTAL_VC_DIR. |
| restore_resource | Revert a content record — or a datasource — to a prior committed version and write it back through the same gated write path as any other update (a DELETED block is recreated under its old id; a datasource restore needs data writes enabled). Omit |
| migration_preflight | Empirical migration audit of the connected portal — run BEFORE writing any conversion pattern. Covers every block by FUNCTION, not just scripted ones: classifies each placed block (scripted/template/markup/native-widget), scans EVERY code- and config-bearing field (not just the html body) for legacy patterns — comment/string-aware so a commented-out call doesn't drive scope — flags hardcoded portal origins (environment portability), maps placement through layouts AND partials AND snippets (an 'orphan' is unreachable through all three), and preflights every bound query: does it execute, does it return column metadata, are numeric columns delivered as strings, is the STORED column metadata stale (repair_query_metadata fixes that). Also returns the browser-probe checklist for the runtime questions a server-side scan cannot answer. Read-only. |
| repair_query_metadata | Re-introspect and store a saved query's COLUMN METADATA without touching its SQL or datasource binding — safe by construction (name/datasources/raw_sql/sql_form are re-sent verbatim; only |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| zuar_portal_start | Confirm the portal connection in one call, then ask what to do. The cheap way to open a session. |
| zuar_portal_quickstart | Confirm the connection + posture and route to the right next step (build a block, explore data, theme, audit, configure). |
| create_zportal_block | Guided workflow to build a correct Zuar Portal HTML block: discover data, follow the two-field structure, then create the block. |
| setup_zuar_project | Guided first-time setup via the configure_project tool: prompt for the portal URL, API key, user ID and a name for THIS folder's portal, the design intake (brand accent, theme modes, density), and optionally a GitHub version-control repo — then write ./.zuar-portal/config.json + design.md + a managed CLAUDE.md block, verify the portal login and the GitHub token/repo, and PIN the folder to the portal so writes can never land on a different one. |
| migrate_block_to_118 | Guided migration of a legacy block (async fetchResults + loadedCallback in the fetch chain) to the 1.18+ synchronous queryResults lifecycle: QUERY_INDEX slots, loadedCallback in a finally, and the columns.length readiness gate that fixes blank hidden/deferred blocks. |
| add_loading_overlay | Add the sanctioned spinner + fade-out overlay to a block already on the 1.18 queryResults pattern, so slow-query or hidden/deferred blocks show a spinner instead of blank white space while data loads. |
| block_perf_pass | Audit and fix a slow / large-data block: measure the real payload, trim a SELECT * query to the columns the block reads, prefetch the chart library in parallel with the data, and make every data-wait timeout 60 s with an honest expiry message. |
| design_intake | Guided theme design intake: interview the user about their brand, colors and feel, synthesize a portal theme with the synthesize_theme tool, and (on approval) create it with create_resource. |
| migration_kickoff | Settle a version-migration's scope decisions up front and batched — chart-widget policy, test pages, hardcoded origins, cadence, rollback home — then record them and run the preflight. |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| block-structure | Two-field HTML/CSS structure and theme variables for an HTML block. |
| zportal-api | Filters, modals, cross-block visibility, resources.load, user/page APIs, and native block types. |
| currentblock | How to read query results inside a block and react to filters. |
| charting | Which charting library to use by complexity, and how to load each via zPortal.resources.load (incl. the amCharts 2-step core-then-modules load — no AMCHARTS_LOADER). |
| migration-1.18 | Move a legacy block (async fetchResults + loadedCallback in the fetch chain) to the 1.18+ synchronous queryResults lifecycle — QUERY_INDEX slots, loadedCallback in finally, the columns.length readiness gate for hidden/deferred blocks, and the confirmed migration pitfalls. |
| migration-playbook | The version-agnostic migration METHOD, distilled from a real 1.17→1.19 run: scope by function not code, elicit scope decisions once at kickoff (the migration_kickoff prompt), treat docs as hypothesis and probe the target build (migration_preflight + browser probes), convert in minimal-diff batches with round-trip verification, verify reference-first, and the silently-blank-block diagnosis ladder. |
| loading-overlay | The sanctioned loading-state exception: add a spinner overlay to a 1.18-pattern block whose data can lag the script (slow queries, hidden/deferred reveal) — pre-flight checks, HTML/CSS, the three JS touch points, and the fade-out that removes itself. |
| block-performance | Perf playbook for slow / large-data blocks, verified in production: measure the payload first (curl timings), trim SELECT * queries to the columns the block actually reads (get_references before touching a shared query), prefetch the chart library in parallel with the data, 60 s data-wait timeouts with an honest expiry message, and change-safety discipline for production portals. |
| visual-verification | How agents SEE a rendered block (screenshot, console, network) for visual debugging and the final visual gate — when it applies, the sign-in caveat, the workflow, and graceful code-only fallback. |
| conventions | The always/never rules and code-style conventions enforced by create_block/update_block. |
| design-system | The portal's house style — palette, typography, spacing, chart styling, and component patterns. Apply it when authoring or restyling blocks so surfaces stay consistent. |
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- 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