npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@centrali-io/centrali-mcp

v6.6.0

Published

Centrali MCP Server - AI assistant integration for Centrali workspaces

Readme

@centrali-io/centrali-mcp

MCP (Model Context Protocol) server for the Centrali platform. Lets AI assistants (Claude, Cursor, etc.) interact with Centrali workspaces — query data, manage records, search, trigger compute functions, inspect execution results, build orchestrations, and more.

Full documentation: docs.centrali.io — SDK guide, API reference, compute functions, orchestrations, and more.

Two ways to connect

Option 1: Hosted MCP Server (recommended)

The easiest way to connect any AI client to Centrali. Add a single URL — authentication happens in the browser via OAuth.

Claude Desktop / Claude Code / Cursor:

{
  "mcpServers": {
    "centrali": {
      "type": "url",
      "url": "https://mcp.centrali.io"
    }
  }
}

On first use, your AI client opens a browser for login and workspace selection. No client ID, secret, or workspace slug needed.

Option 2: Stdio with Service Account (CI/automation)

For headless environments (CI pipelines, automation scripts, cron jobs) where browser login isn't possible. Uses service account credentials with RBAC permissions.

{
  "mcpServers": {
    "centrali": {
      "command": "npx",
      "args": ["@centrali-io/centrali-mcp"],
      "env": {
        "CENTRALI_URL": "https://centrali.io",
        "CENTRALI_CLIENT_ID": "<service-account-client-id>",
        "CENTRALI_CLIENT_SECRET": "<service-account-secret>",
        "CENTRALI_WORKSPACE": "my-workspace"
      }
    }
  }
}

Migrating from OAuth stdio to hosted

If you were previously using CENTRALI_OAUTH_CLIENT_ID with the stdio package, switch to the hosted URL:

  1. Remove the old command/args/env configuration
  2. Replace with: { "type": "url", "url": "https://mcp.centrali.io" }
  3. On next connection, authenticate in the browser

Environment Variables (stdio mode only)

| Variable | Required | Description | |----------|----------|-------------| | CENTRALI_URL | Yes | Centrali instance URL (e.g., https://centrali.io) | | CENTRALI_WORKSPACE | Yes | Workspace slug to operate in | | CENTRALI_CLIENT_ID | Yes | Service account client ID | | CENTRALI_CLIENT_SECRET | Yes | Service account client secret |

Service Account Permissions

A freshly created service account has no permissions by default. You must assign it a role before the MCP server can do anything useful, otherwise every tool call will return 403 Forbidden.

Quickest setup — full admin access:

  1. In the Console, go to Settings > Service Accounts
  2. Create your service account and save the client secret
  3. Open the service account, go to the Groups tab
  4. Add it to the workspace_administrators group

Least-privilege setup: Create a custom group with a policy scoped to the resources you need. See the Policies and Permissions guide for details.

Getting Started

After connecting, call describe_centrali first — it returns the full capability map, feature matrix, and SDK integration guidance. Then use the specific describe_* tools for deeper schema details on any domain.

Available Tools

Discovery (call these first)

| Tool | Description | |------|-------------| | describe_centrali | Platform overview, feature matrix, SDK integration guidance, and list of all tools | | describe_collections | Schema reference for collections (data models, field types, constraints) | | describe_records | Schema reference for record operations (filters, sorting, pagination, expand) | | describe_search | Schema reference for full-text search | | describe_compute | Compute function reference (input contract, secrets, async execution, api object) | | describe_saved_queries | Saved-query schema reference (parameterized queries, variables) | | describe_orchestrations | Orchestration reference (multi-step workflows, encrypted params) | | describe_insights | Anomaly insights reference | | describe_validation | Data validation reference | | describe_pages | Pages builder reference | | describe_page_definition | Page definition schema (blocks, layouts) | | describe_page_blocks | Available block types for pages | | describe_page_actions | Page action system reference | | describe_navigation | Navigation configuration reference | | describe_auth_providers | Auth provider reference (BYOT setup, claim mappings) | | describe_service_accounts | Service account & IAM reference (SA setup, roles, groups, permissions) | | describe_webhooks | Outbound webhook reference (subscription shape, signature, retry/replay) |

Collections

| Tool | Description | |------|-------------| | list_collections | List all data collections (schemas) in the workspace | | get_collection | Get full schema for a collection by record slug | | create_collection | Create a new collection with typed properties | | update_collection | Update an existing collection | | delete_collection | Delete a collection and all its records |

Records

| Tool | Description | |------|-------------| | query_records | Query records using the canonical Centrali query language (POST /records/query). Accepts a QueryDefinition body (where, text, sort, page, select). | | get_record | Get a single record by ID | | get_records_by_ids | Get multiple records by IDs | | create_record | Create a new record | | update_record | Update an existing record | | upsert_record | Create or update a record | | delete_record | Soft or hard delete a record | | restore_record | Restore a soft-deleted record |

Search

| Tool | Description | |------|-------------| | search_records | Full-text search across workspace records |

Compute

| Tool | Description | |------|-------------| | list_functions | List compute functions | | get_function | Get a function by ID (includes code) | | create_function | Create a new compute function | | update_function | Update a function (code, name, timeout) | | delete_function | Delete a compute function | | test_function | Test execute code without saving | | list_triggers | List function triggers (on-demand, event-driven, scheduled, http-trigger) | | get_trigger | Get a trigger by ID | | create_trigger | Create a new trigger | | update_trigger | Update a trigger | | delete_trigger | Delete a trigger | | invoke_trigger | Invoke an on-demand trigger (returns job ID — async) | | pause_trigger | Pause a trigger | | resume_trigger | Resume a paused trigger | | get_function_run | Get execution result by run ID (status, output, errors) | | list_function_runs | List runs by trigger or function ID (execution history) | | get_compute_job_status | Check async job status by job ID (poll after invoke_trigger) | | list_allowed_domains | List allowed domains for outbound HTTP | | add_allowed_domain | Add a domain to the allowlist | | invoke_endpoint | Call a sync compute endpoint by path (returns response inline) | | remove_allowed_domain | Remove a domain from the allowlist |

Saved Queries

Saved queries store a canonical QueryDefinition plus optional variables and an optional multi-collection joins[] clause.

| Tool | Description | |------|-------------| | list_saved_queries | List saved queries, optionally by collection | | get_saved_query | Get a saved query by ID | | create_saved_query | Create a reusable parameterized query (canonical body) | | update_saved_query | Update a saved query (canonical body) | | delete_saved_query | Delete a saved query | | execute_saved_query | Execute a saved query with optional variables | | test_saved_query | Test a canonical query definition without saving |

Typed parameter discovery → execute. Saved queries authored with typed parameters expose their parameter shape through describe_saved_queries (schema reference) and get_saved_query / list_saved_queries (per-row variables declarations). The expected discover-then-execute flow:

  1. Discover schema (one-shot) — describe_saved_queries returns the QueryVariableDefinition shape (type, required?, default?, description?) and the supported VariableType union (string | number | boolean | datetime | id | { array: T } | { reference: collectionSlug }).
  2. Discover the queryget_saved_query returns the row including variables. Read each entry to learn what to bind. The canonical response includes queryDefinition.resource (always equal to the row's recordSlug):
    {
      "id": "…",
      "name": "Monthly revenue",
      "recordSlug": "orders",
      "queryDefinition": {
        "resource": "orders",
        "where": { "and": [
          { "data.month": { "eq": "${month}" } },
          { "data.region": { "eq": "${region}" } }
        ]},
        "sort": [{ "field": "data.amount", "direction": "desc" }],
        "page": { "limit": 100 }
      },
      "variables": {
        "month":  { "type": "datetime", "required": true, "description": "Month bucket (UTC)" },
        "region": { "type": "string",   "required": true }
      }
    }
  3. Execute typed — pass concrete values via execute_saved_query's variables arg. The server validates each value against its declared type (no coercion — "123" will not be accepted for a number declaration) and then substitutes. datetime accepts an ISO-8601 string:
    {
      "recordSlug": "orders",
      "queryId": "…",
      "variables": { "month": "2026-04-01T00:00:00Z", "region": "us-east" }
    }
    Typed errors surface as variable_type_mismatch, missing_required_variable, or extra_variable. Untyped (legacy) rows have variables: null and accept any keys; values are stringified before substitution. The untyped fallback is also taken by post-backfill rows (canonical body, no declarations yet) until an author promotes them.

The MCP test_saved_query tool intentionally does not expose variableDeclarations — its dry-run path falls back to legacy string substitution and does not enforce typed declarations. Round-trip via create_saved_query + execute_saved_query to validate typed parameters end-to-end.

Multi-collection joins. Saved queries support an optional joins[] clause inside queryDefinition (max 4 entries). Each entry joins another collection to the primary record set:

{
  "resource": "orders",
  "where": { "data.status": { "eq": "open" } },
  "joins": [
    {
      "foreignSlug": "customers",
      "localField": "data.customerId",
      "foreignField": "id",
      "joinType": "left",
      "select": ["id", "data.name", "data.email"],
      "alias": "customer"
    }
  ],
  "sort": [{ "field": "createdAt", "direction": "desc" }],
  "page": { "limit": 50 }
}

Constraints (validated by @centrali/query):

  • joinType must be 'inner' or 'left''right' and 'full' are rejected by the executor with unsupported_clause.
  • text and joins cannot appear in the same query (unsupported_combination).
  • Aliases (or implicit foreignSlug) must be unique within joins[] (duplicate_join_alias).
  • Cap of 4 entries (joins_length_exceeded).
  • localField may use <priorAlias>.<field> to chain a join through an earlier alias.

execute_saved_query returns { rows, meta, fields }. Each entry in rows carries joined data under a top-level _joined key:

{
  "rows": [
    {
      "id": "order-123",
      "data": { "status": "open" },
      "_joined": {
        "customer": { "id": "cust-1", "data": { "name": "Acme" } }
      }
    }
  ],
  "meta": { "limit": 50, "offset": 0, "total": 1 },
  "fields": [{ "name": "id" }, { "name": "data" }, { "name": "_joined" }]
}

LEFT joins surface null for unmatched rows.

Authorization (SECURITY DEFINER, locked 2026-05-04). Saved queries are author-bound — the AUTHOR's permissions define what the query can read; the executor only needs an execute check on the saved-query resource at runtime.

  • Author time (create_saved_query / update_saved_query / test_saved_query): the caller must hold records:list on the primary collection AND on every collection referenced in joins[]. The data service returns 403 if any access is missing.
  • Execute time (execute_saved_query): only execute on the saved-query resource is checked; there is no per-collection re-check, and field-level redaction follows the author's permissions, not the executor's. Secret-masking still applies unconditionally.

AI assistants should not propose saved queries (or join chains) against collections the author can't read — execute will succeed for less-privileged callers, but authoring will fail.

Reserved clauses. Saved-query create/update/test surfaces reject text (full-text search) and include (relation expansion) with 422 unsupported_clause. Those clauses are available on the ad-hoc POST /records/query surface only — don't author saved queries that use them.

Orchestrations

| Tool | Description | |------|-------------| | list_orchestrations | List all orchestrations in the workspace | | get_orchestration | Get orchestration details including step definitions | | create_orchestration | Create a multi-step workflow | | update_orchestration | Update an orchestration (steps, triggers, encrypted params) | | delete_orchestration | Delete an orchestration and its runs | | activate_orchestration | Activate an orchestration (enable triggers) | | pause_orchestration | Pause an orchestration (disable triggers) | | trigger_orchestration | Trigger a run with optional input data | | list_orchestration_runs | List runs for an orchestration | | get_orchestration_run | Get run details (use includeSteps=true for step-by-step debugging) |

Insights (Anomaly Detection)

| Tool | Description | |------|-------------| | trigger_anomaly_analysis | Start an anomaly detection scan | | list_insights | List anomaly insights | | get_insight | Get a single insight | | acknowledge_insight | Mark an insight as reviewed | | dismiss_insight | Dismiss an insight | | get_insights_summary | Get insights summary counts |

Validation (Data Quality)

| Tool | Description | |------|-------------| | trigger_validation_scan | Start a data quality scan | | list_validation_suggestions | List validation suggestions | | accept_validation_suggestion | Accept a fix (applies to record) | | reject_validation_suggestion | Reject a suggestion | | get_validation_summary | Get validation summary counts |

Pages

| Tool | Description | |------|-------------| | list_pages | List all pages in the workspace | | get_page | Get a page by ID | | create_page | Create a new page (list, detail, form, or dashboard) | | update_page | Update page metadata (name, slug, description) | | delete_page | Soft-delete a page | | save_page_draft | Save or update a page's draft definition | | get_page_draft | Get the current draft of a page | | list_page_versions | List all versions of a page | | validate_page | Validate a page draft before publishing | | publish_page | Publish a page to its runtime URL | | unpublish_page | Unpublish a page | | set_page_access_policy | Set access policy (public, authenticated, role-gated) | | get_page_theme | Get workspace page theme | | set_page_theme | Set workspace page theme (colors, logo, font) | | get_navigation | Get workspace navigation config | | set_navigation | Set workspace navigation config | | delete_navigation | Delete navigation config (revert to standalone pages) | | generate_starter_pages | Generate page proposals from structure IDs | | accept_page_proposal | Accept a generated proposal and create the page |

Service Accounts & IAM

| Tool | Description | |------|-------------| | list_service_accounts | List all service accounts | | get_service_account | Get service account details | | create_service_account | Create a service account (returns clientId + clientSecret) | | update_service_account_name | Update SA display name | | update_service_account_description | Update SA description | | delete_service_account | Permanently delete a service account | | rotate_service_account_secret | Rotate client secret (old one immediately invalidated) | | revoke_service_account | Permanently revoke a service account | | generate_dev_token | Generate a short-lived dev token for testing | | scan_service_account_permissions | Full access matrix audit (Allow/Deny per resource+action) | | simulate_service_account_permission | Simulate an authorization check with evaluation trace | | generate_remediation | Generate options to grant missing permissions (role, group, or new policy) | | preview_remediation | Preview what changes a remediation option would make | | apply_remediation | Apply a remediation option to grant access | | list_service_account_roles | List roles assigned to a SA | | assign_role_to_service_account | Assign a role to a SA | | remove_role_from_service_account | Remove a role from a SA | | list_service_account_groups | List groups a SA belongs to | | add_service_account_to_group | Add SA to a group | | remove_service_account_from_group | Remove SA from a group | | list_roles | List all roles in the workspace | | get_role | Get role details with permissions | | create_role | Create a role with permissions | | update_role | Update a role | | delete_role | Delete a role | | list_groups | List all groups | | get_group | Get group details | | create_group | Create a group | | update_group | Update a group | | delete_group | Delete a group |

Webhook Subscriptions

| Tool | Description | |------|-------------| | list_webhook_subscriptions | List all outbound webhook subscriptions | | get_webhook_subscription | Get a subscription by ID (secret not included) | | create_webhook_subscription | Create a subscription — response returns the whsec_ signing secret once | | update_webhook_subscription | Update name, URL, events, recordSlugs, or active flag | | delete_webhook_subscription | Delete a subscription (delivery history retained) | | rotate_webhook_subscription_secret | Regenerate the signing secret (immediate cutover) | | list_webhook_deliveries | List delivery history for a subscription (trimmed rows) | | get_webhook_delivery | Get a single delivery with full payload and response body | | retry_webhook_delivery | Replay a delivery — reuses the original payload and signature | | cancel_webhook_delivery | Cancel a retrying delivery (flips to failed with distinctive marker) |

Publishable Keys (Frontend)

| Tool | Description | |------|-------------| | list_publishable_keys | List all publishable keys | | get_publishable_key | Get key details with scopes | | create_publishable_key | Create a scoped frontend key (pk_live_...) | | update_publishable_key | Update label or scopes | | revoke_publishable_key | Revoke a key (immediate, irreversible) |

Identity

| Tool | Description | |------|-------------| | get_current_identity | Get the current authenticated MCP identity (service account or OAuth user) |

Structures (Deprecated)

| Tool | Description | |------|-------------| | list_structures | Deprecated: use list_collections | | get_structure | Deprecated: use get_collection |

Resources

| URI | Description | |-----|-------------| | centrali://collections | List of all collections with name, slug, description | | centrali://collections/{slug} | Full schema for a specific collection |

Development

# Install dependencies
npm install

# Build
npm run build

# Test with MCP inspector
CENTRALI_URL=https://centrali.io \
CENTRALI_CLIENT_ID=... \
CENTRALI_CLIENT_SECRET=... \
CENTRALI_WORKSPACE=my-workspace \
npx @modelcontextprotocol/inspector node dist/index.js