Meridian MCP
Deploy, roll back, read logs, manage billing plans and debug webhooks for Shopify apps hosted on Meridian, from your coding agent.
Hosted MCP Server
npx add-mcp 'https://mcp.the-meridian.ai/mcp'Installs into Claude Code, Codex, Cursor and more
Documentation
Meridian MCP
Meridian MCP connects the AI coding client you already work in (Cursor, Claude Code, Codex, or Claude Desktop) to your Meridian organizations and apps. Instead of guessing, the agent reads your app's real Plan Builder catalog, deploy plane, runtime logs, secret metadata, Shopify API alerts, Grow config (emails, automations, segments, discounts), and developer databases before it writes a line of code.
So the agent reads your actual feature and event keys before writing isEnabled() / track() calls, reads the real error off a failed deployment before proposing a fix, and can trigger a deploy or roll one back without you leaving the editor.
| Server URL | https://mcp.the-meridian.ai/mcp |
| Transport | Streamable HTTP |
| Authentication | OAuth 2.1 authorization code + PKCE, with dynamic client registration |
| Authorization | Your existing organization role and permissions, re-checked on every call |
| Server version | 1.14.0 |
| Where to set it up | The Meridian MCP page (/mcp) in the dashboard |
Meridian MCP never grants access you don't already have in the dashboard. Every tool call resolves the signed-in user and runs the same permission checks the web app runs, on the same catalog: a tool that mirrors a dashboard action needs the permission that action needs, and a role's app scope applies to every app-scoped tool.
This server accesses the production Meridian platform only, including the staging and development environments of its apps. Apps created on the separate Meridian staging platform are not available through this server. See Environments.
Connect an AI client
There is no API key and no token to paste anywhere. The dashboard hands out a URL; your client obtains its own credentials over OAuth, and you approve the connection once in a browser.
- Add the server URL to your MCP client (see below).
- The client discovers Meridian's OAuth endpoints and registers itself. Nothing has to be pre-created in the dashboard.
- The client opens Meridian's consent screen in a browser. It names the client, what it asks for, and where the access goes: an application on your computer, or a remote server, which the screen names and warns you about. If you are signed out of the dashboard, or your session has expired, Meridian asks you to sign in first and then takes you straight to the consent screen. You don't need to start the connection again from your client.
- On Approve, the client exchanges the authorization code for its tokens. On Deny, nothing is granted.
- The client appears under Connected AI clients on the Meridian MCP page, with when it connected and when it was last used.
Every client reads the same config:
{
"mcpServers": {
"meridian": {
"url": "https://mcp.the-meridian.ai/mcp"
}
}
}
| Client | How to add it |
|---|---|
| Cursor | Customize in the sidebar (Settings → Tools & MCP before Cursor 3), or add the snippet to ~/.cursor/mcp.json (global) or .cursor/mcp.json (project). Cursor shows a Connect button that opens the consent screen. |
| Claude Code | Run claude mcp add --transport http meridian https://mcp.the-meridian.ai/mcp, then run /mcp to authenticate. |
| Codex | Add [mcp_servers.meridian] with url = "https://mcp.the-meridian.ai/mcp" to ~/.codex/config.toml (or .codex/config.toml in a trusted project), then run codex mcp login meridian to open the consent screen. |
| Claude Desktop | Settings → Connectors → Add custom connector, paste the server URL, then approve in the browser. |
meridian skills install writes this config for Claude Code, Codex and Cursor in one go, together with the Meridian agent skill. See AI coding agents.
Revoke a client
Connected AI clients lists every client you've approved. Revoking one invalidates its access token and refresh token immediately. The client stops working and has to connect and be approved again. Revoked entries stay in the list, marked as revoked, rather than disappearing. Connections are per developer, not per organization.
How tools are scoped
The server keeps no state between calls. There's no "current app" or "current organization", so every app-scoped tool takes explicit identifiers:
| Argument | Required | What it is |
|---|---|---|
app_id | On app-scoped tools | The app's public identifier, as returned by apps_list. |
organization_id | Optional | An organization uuid or slug. When supplied, app_id is resolved within it and may be a slug too. |
The opening move for an agent is whoami, then apps_list. The identifiers every other tool needs come from those two calls. Output always uses the same public identifiers the platform API exposes; internal numeric ids never appear.
Tool catalog
Fifty-eight tools. Each is annotated so a well-behaved client knows what it can run unattended: read-only (no side effects), idempotent (safe to repeat), destructive (needs confirmation), or write (creates or updates Meridian config, draft-only for emails and automations). The catalog leans towards facts your repository can't tell you: the variables injected into the deployed runtime, the live database schema, where webhooks are routed, and the Grow config an agent needs when wiring lifecycle flows.
Orientation
| Tool | Annotation | Purpose |
|---|---|---|
whoami | read-only | The calling user plus every organization they belong to, with role and key permissions. No arguments. |
apps_list | read-only | Apps visible to the user, each with the app_id every other tool needs. |
app_get | read-only | One app's detail: Shopify connection state, environments, plan feature entitlements. Each environment carries the same addresses, domains and database as environments_list, without the scaling config. The environments field is omitted without Hosting: View on the app, and the entitlements without Plan builder: View. |
docs_search | read-only | Ranked passages from Meridian's public product docs (the same knowledge base Answers uses). Returns path, title, URL, heading, anchor, snippet, and score. No app_id. |
docs_get | read-only | One public docs page in full by relative path (for example mcp-server.mdx). Same tree as meridian://docs/{path}. |
Plan Builder
The highest-value surface: what an agent reads before writing SDK integration code, and, since 1.13.0, what it uses to set up an app's plans and features without the dashboard.
| Tool | Annotation | Purpose |
|---|---|---|
plans_list | read-only | The app's plans (handle, status, monthly/yearly price, trial days) and the feature and event terms each grants. |
features_list | read-only | The feature catalog: each feature's key (what isEnabled("<key>") gates on), type (boolean/number), and per-plan value. |
events_list | read-only | The metered-usage event catalog: each event's key (what track({ eventKey }) reports against), unit, and per-plan terms. |
events_create | write | Adds a metered-usage event to the catalog: name, key (lowercase snake_case, unique per app across events and usage views, immutable), optional unit, description, and default metering terms. Per-plan terms are set on the plan with plan_create or plan_update. |
feature_create | write | Adds a feature to the catalog: name, key (what isEnabled("<key>") checks, lowercase snake_case, unique per app, immutable), type (boolean or number, immutable), optional description. The feature is in no plan until a plan grants it. |
feature_update | write | Renames a feature or edits its description. Its key and type never change. |
plan_create | write | Creates a plan as a draft: name, price_monthly (0 for a free plan), optional description, price_yearly, trial_days, the features it grants (with a value for a number feature) and its per-event usage events terms. Merchants don't see it until it is activated. |
plan_update | write | Edits a plan: only the fields sent change. features and events each replace the plan's whole list. Never changes its status. |
plan_activate | write | Puts a draft live, so merchants can subscribe to it. Requires confirm: true in the same call. |
plan_deactivate | write | Takes an active plan off the pricing page (back to draft). Stores already subscribed keep it. |
entitlements_explain | read-only | What one shop is entitled to right now, resolved through the same path the SDK reads. A debugging aid for a gate behaving unexpectedly. |
The write tools follow the same rules as the Plan Builder in the dashboard, and need Plan builder: Edit on the app:
- A plan name is unique among the app's plans, and a plan's shape is checked as on the dashboard: a yearly price needs a monthly one, and at most one event charges for usage, on a plan without a yearly price.
- A plan with live subscribers refuses a change that would cost them more (
PLAN_LOCKED). Save it as a new version from the dashboard: they stay on the version they approved. - Only the current version of a plan can be activated, and an older version keeps its name.
- Activating any plan needs the app's session store, as in the dashboard. See Publishing plans.
- A paid plan (a price, or an event with an overage rate) can only go live once the app can charge through Shopify:
plan_activate, and aplan_updatethat prices an active free plan, are refused withSHOPIFY_BILLING_NOT_READYand what is missing (the Shopify client ID or secret in Settings > Meridian SDK, the Partner connection in Settings > Integrations). See Paid plans need Shopify billing set up. plan_activatewithoutconfirm: truechanges nothing and says what activating would do. Have your agent ask you before it passesconfirm: true. A plan that is already active is returned unchanged.plan_deactivateundoes it, without confirmation: nobody is charged by it.- Changes to an active plan reach new merchants at once, as a save in the dashboard does.
Deploy
| Tool | Annotation | Purpose |
|---|---|---|
environments_list | read-only | Environments with type, region, base URL, public URL, domains, scaling config, database, and config_pending_deploy (true when settings changed that only reach the app with the next deploy) with config_changed_at. |
app_readiness_get | read-only | Whether the app is ready to deploy: each readiness check with key, status (pass, warn, fail), code (such as missing_shopify_client_secret), message and fix (where in the dashboard, with its URL). A fail makes the deploy fail before its build. Takes an optional environment_id (default: production). Needs Hosting: View. |
managed_variables_list | read-only | The variables Meridian injects at deploy time (SHOPIFY_API_KEY, the MERIDIAN_* and managed DB_* set). Names and metadata only, never values. |
github_refs_list | read-only | Branches and recent commits of the connected GitHub repository. |
deployments_list | read-only | Recent deployments with status, current step, build step (built, reused image, or none for a rollback), timing, git ref/sha, and who triggered them. A failed one carries error_message, and error_message_pending: true while that reason may still be replaced by the container's output or the stored build log. |
deployment_get | read-only | One deployment's detail: finished, steps (queued, build, deploy, verify, each with status, timing, duration and detail), its log lines and build/runtime log links. wait_until: "finished" waits up to 50 seconds for the deployment to finish before answering, so an agent follows a deploy without a sleep loop. Lines come newest first (order: "asc" for oldest first), limit keeps the latest (default 100), and build boilerplate is left out unless include_noise: true. See Following a deployment. |
logs_tail | read-only | Recent runtime logs for one environment, when the app's plan includes logs. Options include since/until, deployment_id, min_severity (a floor, so WARNING also matches errors), and contains. Every answer carries server_time and the window queried, in UTC. |
secrets_list | read-only | Secret and environment-variable metadata: key, scope, creator, timestamps. Never a value. With environment_id, what that environment gets: its own entries and the app-level ones it inherits. |
previews_list | read-only | Pull-request preview deployments: PR number, head sha, URL, status, expiry. |
resource_usage_get | read-only | Current CPU/memory/network usage against limits, plus hosting meters for the billing period. A periodic sample. |
resource_usage_history | read-only | Time-range CPU/memory/network/throughput/latency history for one environment. |
deployment_create | idempotent | Trigger a deployment of a git_sha to one of the app's environments, like the Deploy button. |
deployment_rollback | destructive | Shift live traffic back to a previously succeeded deployment's revision. No rebuild. |
Call app_readiness_get before deployment_create: it names what would make the deploy fail in seconds and what would break the app after it. Call managed_variables_list before writing any code that reads process.env. Those variables are in neither the repository nor secrets_list, so an agent reading only your config concludes they're unset. Use github_refs_list to feed deployment_create a real git_sha: a sha that hasn't been pushed fails late during the build.
secrets_list without environment_id lists the app-level entries, the ones every environment inherits. With environment_id, it lists what that environment really gets: its own entries plus every app-level entry, marked inherited: true. An app-level entry the environment replaces with its own entry of the same key stays listed with overridden_by_environment: true, like the struck-through line the dashboard shows for it. These entries are sorted by key, so an override sits next to what it replaces, and count counts all of them.
In environments_list and app_get, base_url is the environment's Cloud Run origin, null until its first deploy. Where the app answers is public_url, built from platform_hostname ({slug}.the-meridian.app in production, {slug}-staging.the-meridian.app and {slug}-dev.the-meridian.app in the others). domains lists the platform domain first, with status active, not_deployed (never deployed) or disabled (hosting turned off for the organization), then each custom domain with its status, its certificate state tls (active, provisioning, failed, or null when Meridian holds none), dns_all_verified, the dns_records to add, and certificate_expires_at, ownership_expires_at and error_message. database gives the database's status, engine, and, when it failed, a sanitised error_code and error_message: the database add-on when the environment has one, otherwise the managed environment database, and null when it has neither. database_status is that same status (pending, provisioning, ready, failed, deleting or deleted). Neither tool ever gives the database host, user, name, connection name or password, and an error_message that would name one is replaced with a generic one, while error_code still says what failed.
logs_tail reads a since or until without an offset as UTC, and answers with server_time, the server's current time in UTC, next to the since and until it queried, also in UTC. A since more than five minutes after the server's time is refused with an error that gives the server time and the gap, because it could only return nothing: it usually means a local time was sent without its offset. An environment that was never deployed has no runtime, so its tail is empty and carries a note that says so.
Webhooks
| Tool | Annotation | Purpose |
|---|---|---|
webhook_routes_list | read-only | Which Shopify topics are routed, the forward_path each is delivered to, whether Shopify accepted the subscription, and the destination itself: forward_host plus the forward_host_source it came from. |
webhook_deliveries_list | read-only | Recent inbound deliveries: topic, shop, status, attempts, the response code your handler returned, and any error. |
Together these separate the two failures that look identical from inside your code: no delivery row means Shopify never sent it (check the route); a 4xx/5xx response_code means it arrived and your handler rejected it. Neither tool returns the webhook body or headers.
In webhook_routes_list, each route's registration counts the stores where Shopify accepted the subscription (registered_shops) and where it did not (failed_shops, with last_error). A store Meridian could not reach at all, because its token was revoked or can't be renewed, or Shopify refused the request, counts as failed on every topic it hasn't registered, and its last_error starts with Could not reach followed by the store. A store that uninstalled your app drops out of these counts the next time you save the topic set.
forward_host is the origin Meridian really posts to, and forward_host_source says which destination won: external (the verified external domain you selected as the forward host), environment (your app's Meridian deployment), or platform. A platform source is Meridian's own receiver, the last resort when an app has neither: forwarded events stop there and never reach your app, and forward_url then gives the single URL they go to. Both are null when nothing is routed at all.
reconcile_available says whether Meridian can reach the stores that already installed your app, which it can only do when the app is deployed on Meridian. When it is false, Meridian can't register topics on those stores itself: the SDK registers your topic set on each store when that store authenticates your app (see Re-registering webhooks). Managed topics are in that set from install on. A route you added reaches a store only at that store's first sign-in after you added it, so each such route carries sign_in: installed_shops, and awaiting_shops, the installed stores that haven't signed in since. A sign-in within five minutes of adding the route still counts as awaiting, because the SDK can serve the topic set it cached before. sign_in is null on managed topics, and on every route when reconcile_available is true.
Shopify API alerts
| Tool | Annotation | Purpose |
|---|---|---|
shopify_alerts_list | read-only | Open API-deprecation alerts: the changelog entry, severity, migration deadline, matched code references, and whether a fix suggestion exists. |
shopify_alert_get | read-only | One alert plus its stored fix suggestion, if generated. |
Both need the Shopify API alerts: View permission on the app.
Databases
| Tool | Annotation | Purpose |
|---|---|---|
dev_database_get | read-only | Your own developer database for the app: status, storage usage, lifecycle timestamps, recent migration runs. Metadata only. |
dev_database_migrate | idempotent | Record a migration run that already happened locally. It does not execute one. |
dev_database_reset | destructive | Drop and recreate your developer database schema. Requires confirm: true. |
database_schema_get | read-only | The table, column and index structure of an environment's managed database. Structure only, never rows. |
Developer database tools only ever reach the caller's own database, never a teammate's, even for an organization owner. Read database_schema_get before writing a migration or query against a deployed environment: the live schema is whatever the last applied migration produced, and your repository may not agree with it.
CRM
| Tool | Annotation | Purpose |
|---|---|---|
custom_fields_list | read-only | The app's custom field definitions: handle, type, the options a select field allows, and whether the field is readable by your app. Optional shop_domain also returns that store's values and needs crm.merchants.view. |
custom_field_values_set | idempotent | Set custom field values on a store, keyed by handle. A null value clears one, at most 20 per call. Writes through the same single writer the dashboard uses, so the custom field changed automation trigger fires exactly as it would otherwise. |
crm_segments_list | read-only | Segment definitions and conditions (not membership dumps). |
crm_segment_get | read-only | One segment's definition and conditions. |
Emails
| Tool | Annotation | Purpose |
|---|---|---|
emails_list | read-only | Email templates for the app: name, status, subject, timestamps. Never HTML or design. Newest first, 20 per call by default (limit up to 100). While next_cursor is not null, call again with it as cursor and the same status and search to read the next page. |
email_get | read-only | One template's metadata. Never the body. |
emails_variables_list | read-only | The merge-tag catalog available when authoring subjects and bodies. Optional shop_domain swaps the samples for that store's values and also needs crm.merchants.view. A value the store does not have reads empty, such as its Shopify Partner data while the store is known only from its install. |
email_create | write | Create an inactive draft (name, optional subject and preview text). Status is always forced inactive; design/HTML cannot be set through MCP. |
email_update | write | Update an email's name, subject, or preview text. Cannot activate or edit the body. An active email must keep a subject, so clearing it is refused until the email is deactivated. Like a save in the dashboard, it also updates the Send email steps of every automation that sends the email, so their next send uses the change. |
Edit the body and activate in the dashboard. MCP never live-sends.
Automations
| Tool | Annotation | Purpose |
|---|---|---|
automations_list | read-only | Automations with status, node count, and timestamps. |
automation_get | read-only | One automation's config and graph. Graphs strip emailHtml; node ids are remapped to public node_id values. |
automation_runs_list | read-only | Recent runs for an automation. |
automations_metrics_get | read-only | Aggregate run metrics. |
automations_catalog_get | read-only | Builder catalogs: triggers, conditions, actions the graph can use. |
automation_create | write | Create an inactive draft (name, optional description of up to 2,000 characters). |
automation_update | write | Update name, description (up to 2,000 characters), and/or draft graph. Graph updates only while inactive; no emailHtml. A Send Email step references an email by emailUuid, and Meridian fills its subject, preview text and HTML from that email, so an emailSubject the graph carries is replaced. |
automation_test_run | write | Dry-run an automation against a store (or synthetic store) and return the trace. Nothing is sent, metered, or persisted. A real store (shop_domain) also needs crm.merchants.view. A synthetic store does not. |
Discounts
| Tool | Annotation | Purpose |
|---|---|---|
discounts_list | read-only | Plan Builder discount codes: name, type, value, status, duration. |
discount_get | read-only | One discount's detail. |
discount_create | write | Creates a discount: a code merchants type at subscribe, or an automatic one (auto_apply) with no code. Percentage or fixed amount, forever or for a number of billing cycles, for every plan or some (plan_ids), every store or some. |
discount_update | write | Edits a discount: only the fields sent change. Deactivate it with status: inactive. |
The write tools follow the dashboard's discount rules and need Plan builder: Edit on the app:
- A code is unique per app and stored uppercase. A percentage is capped at 100.
- A write that leaves an automatic discount active needs
confirm: true, because it applies by itself to every new subscription it matches. Renaming one or editing its description does not. A code discount, and any inactive discount, never needs it. - A subscription keeps a discount it got when it subscribed, even after the discount is deactivated.
- Creating a discount counts against the app's discount allowance, as in the dashboard.
Resources and prompts
Two resources give the agent retrievable context: meridian://docs/{path} (Meridian's public product documentation, the same pages at help.the-meridian.ai; empty path returns an index of .md/.mdx paths). Prefer docs_search mid-task and meridian://apps/{app}/config (an app's whole configuration as one JSON document).
Two prompts arrive pre-filled with live data:
integrate_sdk: a guided walkthrough for wiring@the-meridian/sdkinto a Shopify embedded app, pre-filled with that app's real feature and event keys, types, and per-plan values. Optionalsurfacenarrows it toprovider,pricing,usage, orserver.debug_failed_deploy: a guided investigation of a failed deployment, pre-filled with its real status, error, and recent build events, followed by an ordered set of follow-up calls.
What Meridian MCP never returns
No tool ever returns a secret value, not for a secret and not for a plain environment variable. An agent can confirm a variable exists and is spelled correctly, which is what almost every "missing env var" investigation actually needs.
secrets_listandmanaged_variables_listreturn metadata only, never values and never the Secret Manager reference.dev_database_getreturns no password, connection string, or certificate. Connect with the Meridian CLI (meridian dev).emails_list/email_getreturn metadata only, never HTML or design.webhook_deliveries_listreturns no body and no request headers.- Internal identifiers and internal-team-only flags never appear.
Some things are intentionally absent, because doing them through an agent is a worse idea than doing them in the dashboard: reading rows from your databases, writing secrets, deleting plans, features or discounts, saving a new version of a plan, live email sends, activating automations, and account administration (billing, team, roles, auth settings). Store membership exports and report runs stay dashboard-only; CRM definitions (custom fields, segments) and Grow config are the exception.
Mutations
Nineteen tools write; the other thirty-nine only read. Eighteen of them change something, and every successful change is recorded in the organization's activity log with the tool that made it. The nineteenth, automation_test_run, is a dry trace that changes nothing and leaves no entry.
events_createadds one metered-usage event to the catalog. It does not touch per-plan terms.feature_create/feature_updateadd a feature or rename one. A plan grants it throughplan_createorplan_update.plan_createwrites a draft plan.plan_updateedits a plan, draft or active, and is refused when the change would cost its live subscribers more.plan_activateputs a plan live: merchants can subscribe right after, and pay if it is paid. Requiresconfirm: true, and is refused for a paid plan while Shopify billing is not set up.plan_deactivatetakes a plan off the pricing page. Its subscribers keep it.discount_create/discount_updatewrite a discount. Leaving an automatic discount active requiresconfirm: true.deployment_createis idempotent on(environment_id, git_sha): repeating it while that deployment is in flight returns the same one. A different sha while a deployment is active is refused: one active deployment per environment. It deploys to the environment you name, production or a development or staging one, with the same permissions as the dashboard.deployment_rollbackshifts live traffic (annotated destructive). Refused if the target didn't succeed or the environment has another deployment in progress.dev_database_migraterecords a run; it does not execute one.meridian migrateruns the migration locally and records it automatically.dev_database_resetdestroys every table and row in your developer database schema. Requiresconfirm: true.custom_field_values_setwrites custom field values on a store and fires the automation trigger a dashboard edit would.email_createwrites an inactive metadata draft.email_updatechanges an email's metadata and, as a dashboard save does, the snapshot that every automation sending the email sends from. Neither activates, edits the body, or sends.automation_create/automation_updatewrite inactive drafts; graph updates only while inactive; noemailHtml.automation_test_runis a dry trace: no mail, no metering, no persisted run.
Plan requirements
Meridian MCP is gated on the mcp plan feature, and the deploy-related tools additionally on the deploy feature. Every tier (Lite, Pro, and Enterprise) includes both, so no plan change is needed. Lite meters MCP calls (1,000 requests a month); Pro and Enterprise don't meter them. Every call about an app counts, tools, prompts and the meridian://apps/{app}/config resource alike.
The Plan Builder belongs to public apps, so the tools that read or write an app's plans, features and events, the integrate_sdk prompt and the meridian://apps/{app}/config resource refuse a private app with This feature is only available for public applications.
While an organization is in demo mode, its real apps are out of reach through MCP as on the web: a call naming one answers App not found, or you do not have access to it.
| Refusal | What it means |
|---|---|
| This app's Meridian plan does not include the Meridian MCP feature. | The app's plan lacks mcp. Nothing works for that app. |
| This app's Meridian plan does not include the Deploy feature. | The app's plan lacks deploy. The deploy-plane and webhook tools refuse; Plan Builder, Grow, Shopify alert, and developer database tools keep working. |
| Deployment is unavailable until a plan is chosen: … | The organization is on its free trial and has not chosen the plan that starts when it ends. deployment_create refuses until someone with Billing: Manage chooses one from the app's Hosting or billing page. Nothing is charged before the trial ends. See Hosting during the trial. |
| App not found, or you do not have access to it. | The app_id is wrong, belongs to an organization you can't reach, or your role lacks the permission the tool needs (for example hosting.promote for deployment_create to production, or shopify_alerts.view for the alert tools). The two cases read the same on purpose, so a tool can't be used to probe for apps you can't see. Re-run apps_list, then ask an admin to grant the missing permission through a role. |
Versioning
The server reports its version on connect and follows semver. New tools, new resources, and new optional fields on an existing tool's output bump the minor version. A breaking change to an existing tool's contract, meaning a removed or renamed field or changed semantics, bumps the major version.
| Version | What changed |
|---|---|
1.14.0 | Added plan_deactivate, discount_create and discount_update (an active automatic discount requires confirm: true). |
1.13.0 | Added the Plan Builder write tools: feature_create, feature_update, plan_create, plan_update, and plan_activate (requires confirm: true). A refusal from the Plan Builder (PLAN_LOCKED, SHOPIFY_BILLING_NOT_READY, an older plan version) now reaches the agent as its message and code. |
1.12.0 | deployment_get follows a deploy to its end: wait_until: "finished" waits up to 50 seconds, finished and steps are new, and events now come newest first by default, keep the latest lines and leave build boilerplate out (order, include_noise, boilerplate_filtered). The deployment fields of the deploy tools gain error_message_pending. A failed deployment's error_message no longer repeats Cloud Run's port and timeout advice for a crash at boot, quotes the failing build step's first error block, and drops npm's update notices. |
1.11.0 | Added app_readiness_get, the readiness checks a deploy runs before its build. |
1.10.0 | Fixes empty answers that read as real ones. secrets_list with environment_id now also lists the app-level entries the environment inherits, with inherited and overridden_by_environment, so its count counts them too. logs_tail refuses a since more than five minutes ahead of the server and returns server_time, with since / until echoed in UTC, and a note on a never-deployed environment. environments_list and app_get gain platform_hostname, public_url, domains and database, and their database_status now reads the database add-on before the legacy managed database. |
1.9.0 | Added events_create, which adds a metered-usage event to an app's catalog. |
1.8.0 | environments_list gains config_pending_deploy and config_changed_at. |
1.7.0 | Added docs_search and docs_get over this documentation site. |
1.6.0 | Added sanitised error_message on failed previews and developer databases, and database_error_code / database_error_message on environments_list when provisioning failed. |
1.5.0 | Renamed the product to Meridian MCP (feature key developer_mcp became mcp), and added Grow tools for emails, automations, CRM segments, and discounts (reads, inactive draft writes, and automation_test_run). |
1.4.0 | Added custom_fields_list and custom_field_values_set. |
1.3.0 | Added the optional deployment_id, min_severity, contains, and until arguments to logs_tail, changing no existing field's semantics. |
1.2.0 | Added the read-only resource_usage_get and resource_usage_history. |
1.1.0 | Added six read-only tools: managed_variables_list, github_refs_list, previews_list, webhook_routes_list, webhook_deliveries_list, and database_schema_get. |
Troubleshooting
| Symptom | Cause and fix |
|---|---|
| The client asks to authenticate again, or every call fails as unauthorized | The connection was revoked (or the token invalidated). Reconnect from the client and approve again. |
events_create says the key is already used by a usage view | Event keys and usage view keys share one namespace per app. Pick another key, or use the existing view. |
plan_activate or plan_update answers SHOPIFY_BILLING_NOT_READY | The plan is paid and the app cannot charge through Shopify yet. Add what the message names (client ID, client secret, Partner connection), then retry. A free plan activates without them. |
plan_update answers PLAN_LOCKED | Stores pay for this plan, and the change would cost them more. Save it as a new version from the plan's page in the dashboard. |
discount_create or discount_update answers that confirm was not supplied | The write would leave an automatic discount active. Nothing changed. Have the agent call it again with confirm: true once you have decided. |
plan_activate answers that confirm was not supplied | Nothing changed. The agent has to call it again with confirm: true, once you have decided to offer the plan. |
| The agent invents feature or event keys that don't exist | It skipped the catalog. Point it at features_list / events_list, or run the integrate_sdk prompt. |
| The agent invents platform behaviour that doesn't match Meridian | It skipped the docs. Point it at docs_search (then docs_get for the full page), and use live catalog tools for real feature/event keys. |
meridian://docs/ paths from an older client no longer resolve | Paths now match the public Mintlify tree (for example mcp-server.mdx), not the old internal codex layout. Re-read the empty-path index. |
| Calls start failing after a burst of activity | Tool calls are rate limited per user (120 per minute). deployment_create, deployment_rollback and dev_database_reset share a tighter budget of 10 per minute, the same as the dashboard's deploy, rollback and reset buttons. Wait and retry. |
| The client can't complete registration | Dynamic client registration is rate limited per IP. Wait before retrying rather than re-adding the server repeatedly. |
The agent expects dev_database_migrate to run the migration | It doesn't. Run meridian migrate locally. |
The agent expects email_create or automation_create to go live | Creates are always inactive. Activate in the dashboard after editing the body/graph there. |
This documentation is built and hosted on Mintlify, a developer documentation platform.