{"name":"io.customerdashboard/customerdashboard","slug":"customerdashboard","title":"CustomerDashboard","description":"Build dashboards on your own data, including multi-customer views with per-customer login.","url":"https://mcp.market/server/customerdashboard","rating":null,"grade":"C","score":60,"certified":false,"status":"active","category":"other","tags":[],"presence":{"score":8,"stars":null,"forks":null,"downloads_week":null,"last_push_at":null,"license":null},"uptime":{"percent":100,"checks":7,"ok":7,"last_checked_at":"2026-09-21T03:06:04.834Z","last_ok_at":"2026-09-21T03:06:04.834Z","latency_ms":121},"claimed":false,"transport":"remote","callable_via_gateway":true,"default_price_micros":0,"repository":null,"website":"https://customerdashboard.io","version":"0.1.0","remotes":[{"type":"streamable-http","url":"https://app.customerdashboard.io/mcp"}],"packages":[],"tools":[{"name":"add_customer","description":"Add one of your customers to a multi-customer dashboard. The customerId must exactly match the value that identifies them in your own database, because it is what gets bound to :customer_id in every widget query. Adding a customer does not give anyone access; use add_customer_user for that. Subject to your plan's customer limit.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"A dashboard of type 'customer'."},"name":{"type":"string","minLength":1,"maxLength":200,"description":"Display name for this customer, for your own reference."},"customerId":{"type":"string","minLength":1,"maxLength":200,"description":"The identifier for this customer in your own data, for example the value in your orders.customer_id column. Must match exactly."}},"required":["dashboardId","name","customerId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"add_customer_user","description":"Create a login for one of your customers so they can sign in to the published dashboard and see their own data. If you do not supply a password a strong one is generated and returned once. Subject to your plan's users-per-customer limit.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"Dashboard id."},"customerRecordId":{"type":"string","minLength":1,"description":"The customer's id from list_customers."},"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$","description":"The person's email address. Must be unique on this dashboard."},"password":{"description":"Leave empty to have a strong password generated.","type":"string","minLength":4,"maxLength":200}},"required":["dashboardId","customerRecordId","email"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"add_data_source","description":"Connect a new database or spreadsheet to your workspace. Test the settings with test_data_source_connection first: this tool saves them whether or not they work. Subject to your plan's data source limit.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200,"description":"A name for this connection, shown in the dashboard editor."},"type":{"type":"string","enum":["postgres","mysql","mssql","oracle","aurora","redshift","bigquery","snowflake","googleSheets","api","custom"],"description":"Connector type. Call list_supported_data_connectors for the settings each one expects."},"config":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Connection settings for this connector type, for example { host, port, database, username, password, ssl } for postgres. Credentials are stored encrypted at rest and are never returned by read tools."}},"required":["name","type","config"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"create_dashboard","description":"Create a dashboard. Use type 'customer' for a multi-customer dashboard where each of your customers signs in and sees only their own rows, or 'internal' for a normal dashboard you view yourself or publish as one shared view. A 'Default' view is created automatically. Subject to your plan's dashboard limit.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200,"description":"Dashboard name."},"type":{"description":"'customer' for a per-customer, login-gated dashboard; 'internal' for a single shared dashboard. Defaults to 'internal'. This cannot be changed later.","type":"string","enum":["internal","customer"]}},"required":["name"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"create_view","description":"Add a view (tab) to a dashboard. New views are appended after the existing ones. Subject to your plan's view limit.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"Dashboard id."},"name":{"type":"string","minLength":1,"maxLength":200,"description":"View name, shown on the tab."}},"required":["dashboardId","name"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"create_widget","description":"Add a chart, table or KPI to a view. Call list_widget_types for the visualizationConfig each type needs, and run_query_preview first to confirm the query returns the columns you are about to reference. On a multi-customer dashboard the query must filter on :customer_id. Subject to your plan's widget limit.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"viewId":{"type":"string","minLength":1,"description":"View id the widget belongs to."},"dataSourceId":{"type":"string","minLength":1,"description":"Data source the query runs against."},"title":{"type":"string","minLength":1,"maxLength":200,"description":"Widget title."},"query":{"type":"string","minLength":1,"description":"SQL, or an A1 range for Google Sheets. On a customer dashboard include :customer_id, for example \"WHERE customer_id = :customer_id\"."},"visualizationType":{"type":"string","enum":["table","number","lineChart","barChart","stackedBarChart","stackedLineChart","comboChart","scatterChart","histogram","pivotTable","pieChart"]},"visualizationConfig":{"description":"Field mappings and display options for this visualization type. Call list_widget_types for the keys each type expects.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"layout":{"type":"object","properties":{"x":{"type":"integer","minimum":0,"maximum":11},"y":{"type":"integer","minimum":0,"maximum":9007199254740991},"width":{"type":"integer","minimum":1,"maximum":12},"height":{"type":"integer","minimum":1,"maximum":9007199254740991}},"required":["x","y","width","height"],"description":"Position and size on the 12-column grid. Omit on create and a free slot is chosen for you."},"allowSharedAcrossAllCustomers":{"description":"Only for customer dashboards. Set true, after the user explicitly confirms, to allow a query with no per-customer filter so every customer sees identical rows.","type":"boolean"}},"required":["viewId","dataSourceId","title","query","visualizationType"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"delete_customer","description":"Permanently remove a customer from a multi-customer dashboard, along with all of their logins. They lose access immediately. Calling this without confirm returns a preview. This cannot be undone.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"Dashboard id."},"customerRecordId":{"type":"string","minLength":1,"description":"The customer's id from list_customers."},"confirm":{"description":"Set to true only after the user has seen what will be deleted and explicitly agreed. Calling without it returns a preview instead of deleting.","type":"boolean"},"confirmName":{"description":"The exact current name of the item being deleted, copied from the preview. Required alongside confirm.","type":"string"}},"required":["dashboardId","customerRecordId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"delete_customer_user","description":"Permanently remove one login from a customer. They can no longer sign in. Calling this without confirm returns a preview. The customer itself and their data access rule remain.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"Dashboard id."},"customerRecordId":{"type":"string","minLength":1,"description":"The customer's id from list_customers."},"userId":{"type":"string","minLength":1,"description":"The login's id."},"confirm":{"description":"Set to true only after the user has seen what will be deleted and explicitly agreed. Calling without it returns a preview instead of deleting.","type":"boolean"},"confirmName":{"description":"The exact current name of the item being deleted, copied from the preview. Required alongside confirm.","type":"string"}},"required":["dashboardId","customerRecordId","userId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"delete_dashboard","description":"Permanently delete a dashboard and everything on it. Calling this without confirm returns a preview of what would be removed; deleting for real needs confirm plus the dashboard's exact name. This cannot be undone.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"Dashboard id."},"confirm":{"description":"Set to true only after the user has seen what will be deleted and explicitly agreed. Calling without it returns a preview instead of deleting.","type":"boolean"},"confirmName":{"description":"The exact current name of the item being deleted, copied from the preview. Required alongside confirm.","type":"string"}},"required":["dashboardId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"delete_data_source","description":"Permanently delete a data source connection. This is refused while any widget still uses it. Calling this without confirm returns a preview. Your actual database is untouched; only the connection is removed.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"dataSourceId":{"type":"string","minLength":1,"description":"Data source id."},"confirm":{"description":"Set to true only after the user has seen what will be deleted and explicitly agreed. Calling without it returns a preview instead of deleting.","type":"boolean"},"confirmName":{"description":"The exact current name of the item being deleted, copied from the preview. Required alongside confirm.","type":"string"}},"required":["dataSourceId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"delete_view","description":"Permanently delete a view and every widget on it. Calling this without confirm returns a preview. This cannot be undone.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"Dashboard id."},"viewId":{"type":"string","minLength":1,"description":"View id."},"confirm":{"description":"Set to true only after the user has seen what will be deleted and explicitly agreed. Calling without it returns a preview instead of deleting.","type":"boolean"},"confirmName":{"description":"The exact current name of the item being deleted, copied from the preview. Required alongside confirm.","type":"string"}},"required":["dashboardId","viewId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"delete_widget","description":"Permanently delete a widget. Calling this without confirm returns a preview. This cannot be undone.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"viewId":{"type":"string","minLength":1,"description":"View id."},"widgetId":{"type":"string","minLength":1,"description":"Widget id."},"confirm":{"description":"Set to true only after the user has seen what will be deleted and explicitly agreed. Calling without it returns a preview instead of deleting.","type":"boolean"},"confirmName":{"description":"The exact current name of the item being deleted, copied from the preview. Required alongside confirm.","type":"string"}},"required":["viewId","widgetId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"explain_customer_filtering","description":"Explain exactly how to write widget queries so each customer only sees their own rows on a multi-customer dashboard. Call this before writing any query for a `customer` type dashboard. No sign-in required.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{},"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"get_account","description":"Get the signed-in CustomerDashboard account: name, email, workspace, current plan, what the plan allows and how much of it is already used. Call this first in an authenticated session to learn the workspace you are working in.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{},"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"get_dashboard","description":"Get one dashboard in full: its settings, theme, publishing state, every view, and every widget on each view including the widget queries. This is the fastest way to understand an existing dashboard before changing it.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"Dashboard id."},"includeWidgets":{"description":"Include every widget on every view. Defaults to true.","type":"boolean"}},"required":["dashboardId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"get_dashboard_share_url","description":"Get the public URL of a published dashboard, and who can open it. Returns nothing to share if the dashboard is still private.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"Dashboard id."}},"required":["dashboardId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"get_data_source","description":"Get one data source by id, including its non-secret connection settings. Credentials are never included.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"dataSourceId":{"type":"string","minLength":1,"description":"Data source id."}},"required":["dataSourceId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"get_data_source_schema","description":"List the tables and columns available in a connected data source, so you can write correct widget queries. Supported for PostgreSQL, MySQL, SQL Server, Oracle, Aurora, Redshift and Google Sheets.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"dataSourceId":{"type":"string","minLength":1,"description":"Data source id."},"table":{"description":"Return only this table. Useful when a database has many tables.","type":"string"}},"required":["dataSourceId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"get_platform_overview","description":"Explain what CustomerDashboard.io is, how multi-customer dashboards work, and how workspaces, dashboards, views, widgets and customers fit together. Call this first when you are unfamiliar with the product. No sign-in required.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{},"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"get_started","description":"Explain how to sign up for the free trial and connect this MCP server to a CustomerDashboard account, plus the order of steps for building a first multi-customer dashboard. No sign-in required.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{},"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"list_customers","description":"List the customers on a multi-customer dashboard, each with the customerId their data is filtered by and how many logins they have.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"Dashboard id."},"includeUsers":{"description":"Include each customer's login email addresses.","type":"boolean"}},"required":["dashboardId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"list_dashboards","description":"List every dashboard in your workspace, with its type, publishing state and share URL if published.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{},"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"list_data_sources","description":"List every data source connected to your workspace. Connection credentials are never included.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{},"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"list_plans_and_limits","description":"List CustomerDashboard's subscription plans, their monthly price and the resource limits each one allows. Useful for explaining why a create operation was blocked. No sign-in required.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{},"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"list_supported_data_connectors","description":"List every data source type CustomerDashboard can connect to, the settings each one needs, whether widgets can query it, and whether its schema can be introspected. No sign-in required.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{},"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"list_views","description":"List the views (tabs) on a dashboard, in display order, with how many widgets each one holds.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"Dashboard id."}},"required":["dashboardId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"list_widget_types","description":"List every visualization a widget can use, with the visualizationConfig keys each type requires and accepts. Call this before creating widgets so the configuration is correct first time. No sign-in required.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{},"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"list_widgets","description":"List the widgets on a view, including each widget's query and visualization configuration.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"viewId":{"type":"string","minLength":1,"description":"View id."}},"required":["viewId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"publish_dashboard","description":"Publish a dashboard and return its share URL. A customer dashboard is always login-gated, so its customers sign in with the logins you created. An internal dashboard can be published as 'public' (anyone with the link) or 'protected' (one shared username and password).","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"Dashboard id."},"access":{"description":"For internal dashboards: 'public' means anyone with the link, 'protected' requires a shared username and password. Ignored for customer dashboards, which always require a per-customer login. Defaults to 'protected'.","type":"string","enum":["public","protected"]},"username":{"description":"Shared username, for 'protected' access.","type":"string","minLength":1,"maxLength":100},"password":{"description":"Shared password, for 'protected' access. Leave empty to have one generated and returned once.","type":"string","minLength":4,"maxLength":200}},"required":["dashboardId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"reorder_views","description":"Set the tab order of a dashboard's views. Pass every view id in the order you want them shown. This is also the order they rotate in on a wall display.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"Dashboard id."},"viewIds":{"minItems":1,"type":"array","items":{"type":"string","minLength":1},"description":"Every view id on this dashboard, in the order you want."}},"required":["dashboardId","viewIds"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"run_query_preview","description":"Run a query against a connected data source and return the first few rows, so you can confirm it works before putting it on a widget. Results are capped at 100 rows. If the query contains :customer_id you must also say which customer to preview as, using customerId or dashboardId.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"dataSourceId":{"type":"string","minLength":1,"description":"Data source id."},"query":{"type":"string","minLength":1,"description":"The SQL to run, or an A1 range for Google Sheets. Use :customer_id where a customer's own identifier belongs."},"customerId":{"description":"The id of a customer (from list_customers) to run the query as. Required when the query uses :customer_id, unless dashboardId is given.","type":"string"},"dashboardId":{"description":"A customer dashboard whose configured test customer should be used instead of a real customer. Only needed when the query uses :customer_id.","type":"string"},"limit":{"description":"Rows to return. Defaults to 25.","type":"integer","minimum":1,"maximum":100}},"required":["dataSourceId","query"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"set_dashboard_formatting","description":"Set the default locale and number, currency, percentage, duration, date and datetime formatting for a dashboard. Individual widgets can still override these.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"Dashboard id."},"locale":{"description":"BCP 47 locale such as en-US, en-GB or de-DE.","type":"string","maxLength":20},"nullDisplay":{"description":"What to show for an empty value, for example a dash.","type":"string","maxLength":20},"number":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"currency":{"description":"For example { \"currency\": \"USD\", \"decimals\": 2 }.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"percentage":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"duration":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"date":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"datetime":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["dashboardId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"set_dashboard_theme","description":"Set the colour theme of a dashboard: page and surface backgrounds, text colours, brand colours and the chart series palette. All colours are hex values. Pass every field, since the theme is stored as one object.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"Dashboard id."},"backgroundColor":{"type":"string","pattern":"^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$","description":"Page background."},"surfaceColor":{"type":"string","pattern":"^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$","description":"Background of each widget card."},"primaryTextColor":{"type":"string","pattern":"^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$","description":"Main text."},"secondaryTextColor":{"type":"string","pattern":"^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$","description":"Muted and secondary text."},"primaryBrandColor":{"type":"string","pattern":"^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$","description":"Main accent, used as the first chart series colour."},"secondaryBrandColor":{"description":"Secondary accent, used for the second chart series.","type":"string","pattern":"^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"},"chartSeriesColors":{"description":"Explicit chart series palette. Leave empty to derive one from the brand colours.","maxItems":20,"type":"array","items":{"type":"string","pattern":"^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"}}},"required":["dashboardId","backgroundColor","surfaceColor","primaryTextColor","secondaryTextColor","primaryBrandColor"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"set_widget_layout","description":"Reposition several widgets on a view at once, on the 12-column grid. Use this to lay out a whole view rather than moving widgets one at a time.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"viewId":{"type":"string","minLength":1,"description":"View id."},"layouts":{"minItems":1,"type":"array","items":{"type":"object","properties":{"widgetId":{"type":"string","minLength":1},"layout":{"type":"object","properties":{"x":{"type":"integer","minimum":0,"maximum":11},"y":{"type":"integer","minimum":0,"maximum":9007199254740991},"width":{"type":"integer","minimum":1,"maximum":12},"height":{"type":"integer","minimum":1,"maximum":9007199254740991}},"required":["x","y","width","height"],"description":"Position and size on the 12-column grid. Omit on create and a free slot is chosen for you."}},"required":["widgetId","layout"]},"description":"The widgets to move, with their new positions."}},"required":["viewId","layouts"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"test_data_source_connection","description":"Check whether a set of connection settings actually works, before saving them. Pass an existing dataSourceId to retest a saved connection, or a type and config to test new settings.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"dataSourceId":{"description":"Test a saved data source. Omit to test new settings.","type":"string","minLength":1},"type":{"type":"string","enum":["postgres","mysql","mssql","oracle","aurora","redshift","bigquery","snowflake","googleSheets","api","custom"],"description":"Connector type. Call list_supported_data_connectors for the settings each one expects."},"config":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Connection settings for this connector type, for example { host, port, database, username, password, ssl } for postgres. Credentials are stored encrypted at rest and are never returned by read tools."}},"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"unpublish_dashboard","description":"Make a dashboard private again. The existing share link stops working immediately, and any shared username and password are cleared. Widgets and data are untouched.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"Dashboard id."}},"required":["dashboardId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"update_customer","description":"Rename a customer or correct the customerId their data is filtered by. Changing customerId immediately changes which rows they see, so confirm the new value with the user first.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"Dashboard id."},"customerRecordId":{"type":"string","minLength":1,"description":"The customer's id from list_customers (not their customerId)."},"name":{"type":"string","minLength":1,"maxLength":200},"customerId":{"description":"New identifier from your own data. This changes which rows this customer can see.","type":"string","minLength":1,"maxLength":200}},"required":["dashboardId","customerRecordId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"update_dashboard","description":"Rename a dashboard, set how long each view is shown when the dashboard auto-rotates on a screen, or set the test customer used to preview a customer dashboard. Use set_dashboard_theme for colours and publish_dashboard for sharing.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"Dashboard id."},"name":{"type":"string","minLength":1,"maxLength":200},"viewRotationSeconds":{"description":"Seconds each view is shown before rotating to the next, for wall displays. 0 or null turns rotation off.","anyOf":[{"type":"integer","minimum":0,"maximum":86400},{"type":"null"}]},"testCustomerId":{"description":"A customer identifier from your own data, used to preview a customer dashboard before real customers exist. This is bound to :customer_id during previews only.","anyOf":[{"type":"string","minLength":1,"maxLength":200},{"type":"null"}]}},"required":["dashboardId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"update_data_source","description":"Rename a data source or replace its connection settings. The config you pass replaces the stored one entirely, so include every setting, not just the changed ones.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"dataSourceId":{"type":"string","minLength":1,"description":"Data source id."},"name":{"type":"string","minLength":1,"maxLength":200},"config":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Connection settings for this connector type, for example { host, port, database, username, password, ssl } for postgres. Credentials are stored encrypted at rest and are never returned by read tools."}},"required":["dataSourceId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"update_view","description":"Rename a view. Use reorder_views to change the tab order.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"Dashboard id."},"viewId":{"type":"string","minLength":1,"description":"View id."},"name":{"type":"string","minLength":1,"maxLength":200,"description":"New view name."}},"required":["dashboardId","viewId","name"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"update_widget","description":"Change a widget's title, query, visualization type, configuration, data source or position. Only the fields you pass are changed.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"viewId":{"type":"string","minLength":1,"description":"View id the widget belongs to."},"widgetId":{"type":"string","minLength":1,"description":"Widget id."},"title":{"type":"string","minLength":1,"maxLength":200},"query":{"type":"string","minLength":1},"visualizationType":{"type":"string","enum":["table","number","lineChart","barChart","stackedBarChart","stackedLineChart","comboChart","scatterChart","histogram","pivotTable","pieChart"]},"visualizationConfig":{"description":"Replaces the whole configuration object, so include every key you want to keep.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"dataSourceId":{"type":"string","minLength":1},"layout":{"type":"object","properties":{"x":{"type":"integer","minimum":0,"maximum":11},"y":{"type":"integer","minimum":0,"maximum":9007199254740991},"width":{"type":"integer","minimum":1,"maximum":12},"height":{"type":"integer","minimum":1,"maximum":9007199254740991}},"required":["x","y","width","height"],"description":"Position and size on the 12-column grid. Omit on create and a free slot is chosen for you."},"allowSharedAcrossAllCustomers":{"description":"Only for customer dashboards. Set true, after the user explicitly confirms, to allow a query with no per-customer filter.","type":"boolean"}},"required":["viewId","widgetId"],"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"validate_customer_filtering","description":"Audit a multi-customer dashboard and report any widget whose query would show the same rows to every customer. Run this before publishing a customer dashboard, and any time its queries change.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1,"description":"Dashboard id."}},"required":["dashboardId"],"$schema":"http://json-schema.org/draft-07/schema#"}}],"scan":{"score":60,"grade":"C","scanned_at":"2026-09-20T16:17:19.891Z","report":{"scannerVersion":"0.1.9","scannedAt":"2026-09-20T16:17:19.873Z","components":{"code":{"score":-1,"max":25,"notes":["remote-only server, no package to scan"]},"reliability":{"score":20,"max":20,"notes":["remote reachable in 1548ms"]},"poisoning":{"score":15,"max":15,"notes":["42 tool descriptions checked"]},"auth":{"score":3,"max":15,"notes":["open endpoint exposes 17 write-action tools with no auth"]},"maintenance":{"score":3,"max":15,"notes":["no repository listed"]},"identity":{"score":4,"max":10,"notes":["verified namespace with website, no repo"]}},"findings":[{"id":"auth.open-write","severity":"high","component":"auth","title":"Write-action tools reachable without authentication"},{"id":"maint.no-repo","severity":"low","component":"maintenance","title":"No source repository listed"}],"inputs":{"probes":[{"url":"https://app.customerdashboard.io/mcp","reachable":true,"authRequired":false,"latencyMs":1548,"serverInfo":{"name":"customerdashboard","version":"0.1.0"}}],"packages":[],"repo":{"found":false},"icon":{"url":"https://customerdashboard.io/favicon.ico","source":"site","width":96,"height":96},"presence":{"stars":null,"forks":null,"downloadsWeek":null,"license":null,"lastPushAt":null,"score":8}}}},"grade_history":[],"reviews":[]}