Skip to content

logly/mureo

v0.9.0 Breaking

This release includes 2 breaking changes for platform teams planning a safe upgrade.

✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →

✓ No known CVEs patched in this version

Topics

advertising agentic-ai ai-agents claude-code cli codex
+11 more
cursor facebook-ads gemini-cli google-ads marketing marketing-automation mcp meta-ads model-context-protocol python search-console

Affected surfaces

auth breaking_upgrade

ReleasePort's take

Moderate signal
editorial:auto 9d

The `/learn` slash command has been restored as an operational skill with persistence and approval constraints, while the `auth setup --web` CLI command has been removed in favor of a unified authentication flow within the `mureo configure` UI.

Why it matters: Restoring /learn enables persisted learning workflows; removing auth setup --web forces all users to adopt the new UI‑based authentication, eliminating legacy command paths.

Summary

AI summary

/learn slash command restored and auth setup --web removed

Changes in this release

Feature Medium

Restored `/learn` slash command as an operational skill with persistence and approval constraints.

Restored `/learn` slash command as an operational skill with persistence and approval constraints.

Source: llm_adapter@2026-05-21

Confidence: high

Feature Medium

Configured official mureo logo and dark mode for `mureo configure` UI with cohesive design-system tokens.

Configured official mureo logo and dark mode for `mureo configure` UI with cohesive design-system tokens.

Source: llm_adapter@2026-05-21

Confidence: high

Feature Medium

Introduced `mureo providers confirm <id>` command and UI button to finalize hosted‑connector verification, disabling native tools only after confirmation.

Introduced `mureo providers confirm <id>` command and UI button to finalize hosted‑connector verification, disabling native tools only after confirmation.

Source: granite4.1:30b@2026-05-22-audit

Confidence: low

Feature Medium

Added `mureo configure` Web UI (Phase 1) with localhost server, CSRF protection, CSP headers, and env‑var credential writer.

Added `mureo configure` Web UI (Phase 1) with localhost server, CSRF protection, CSP headers, and env‑var credential writer.

Source: granite4.1:30b@2026-05-22-audit

Confidence: low

Feature Low

Added Google Ads OAuth‑scope guidance in the auth step to prevent insufficient‑scope errors.

Added Google Ads OAuth‑scope guidance in the auth step to prevent insufficient‑scope errors.

Source: granite4.1:30b@2026-05-22-audit

Confidence: low

Feature Low

Removed `auth setup --web` command; unified authentication flow into `mureo configure` UI.

Removed `auth setup --web` command; unified authentication flow into `mureo configure` UI.

Source: granite4.1:30b@2026-05-22-audit

Confidence: low

Feature Low

Added per‑platform native↔official toggle in the dashboard with validation and restart guidance.

Added per‑platform native↔official toggle in the dashboard with validation and restart guidance.

Source: granite4.1:30b@2026-05-22-audit

Confidence: low

Feature Low

Clarified host selector labels in the configure UI for Claude Code vs. Desktop app and added unavailability note for credential‑guard hook on Desktop.

Clarified host selector labels in the configure UI for Claude Code vs. Desktop app and added unavailability note for credential‑guard hook on Desktop.

Source: granite4.1:30b@2026-05-22-audit

Confidence: low

Feature Low

Implemented plugin → MCP tool exposure via new `MCPToolProvider` protocol, allowing third‑party plugins to publish tools as `mcp__mureo__*`.

Implemented plugin → MCP tool exposure via new `MCPToolProvider` protocol, allowing third‑party plugins to publish tools as `mcp__mureo__*`.

Source: granite4.1:30b@2026-05-22-audit

Confidence: low

Feature Low

Added `mureo providers` CLI commands (`list`, `add`, `remove`) for managing official MCP providers with idempotent and dry‑run support.

Added `mureo providers` CLI commands (`list`, `add`, `remove`) for managing official MCP providers with idempotent and dry‑run support.

Source: granite4.1:30b@2026-05-22-audit

Confidence: low

Feature Low

Made workflow skills provider‑aware to fall back gracefully when native tools are disabled by official providers.

Made workflow skills provider‑aware to fall back gracefully when native tools are disabled by official providers.

Source: granite4.1:30b@2026-05-22-audit

Confidence: low

Performance Medium

Phase 3 plugin packaging migrated slash commands to skills, dropped `learn` entirely.

Phase 3 plugin packaging migrated slash commands to skills, dropped `learn` entirely.

Source: llm_adapter@2026-05-21

Confidence: low

Bugfix High

Prevented dead config entry for official Meta Ads provider on Claude Code; now requires manual connector setup via Claude.ai.

Prevented dead config entry for official Meta Ads provider on Claude Code; now requires manual connector setup via Claude.ai.

Source: granite4.1:30b@2026-05-22-audit

Confidence: low

Bugfix High

Fixed official Google Ads provider registration so credentials are collected and injected correctly, making the provider usable.

Fixed official Google Ads provider registration so credentials are collected and injected correctly, making the provider usable.

Source: granite4.1:30b@2026-05-22-audit

Confidence: low

Bugfix Medium

Corrected Meta hosted MCP handling on Claude Code to use Claude.ai connector instead of failing `/mcp` registration.

Corrected Meta hosted MCP handling on Claude Code to use Claude.ai connector instead of failing `/mcp` registration.

Source: granite4.1:30b@2026-05-22-audit

Confidence: low

Bugfix Medium

Fixed official/native precedence when mureo MCP is configured after an official provider, ensuring deterministic tool source selection.

Fixed official/native precedence when mureo MCP is configured after an official provider, ensuring deterministic tool source selection.

Source: granite4.1:30b@2026-05-22-audit

Confidence: low

Bugfix Medium

Resolved GA4 wizard input saving issue so credentials are persisted correctly.

Resolved GA4 wizard input saving issue so credentials are persisted correctly.

Source: granite4.1:30b@2026-05-22-audit

Confidence: low

Bugfix Medium

Fixed dashboard “mureo integrations” list to include Search Console and exclude GA4 (official only).

Fixed dashboard “mureo integrations” list to include Search Console and exclude GA4 (official only).

Source: granite4.1:30b@2026-05-22-audit

Confidence: low

Bugfix Medium

Corrected BYOD/demo relative windows calculation so demo data remains non‑empty over time.

Corrected BYOD/demo relative windows calculation so demo data remains non‑empty over time.

Source: granite4.1:30b@2026-05-22-audit

Confidence: low

Bugfix Medium

Ensured auto‑disable of mureo native tools when adding an official provider, with atomic config updates and env‑var handling.

Ensured auto‑disable of mureo native tools when adding an official provider, with atomic config updates and env‑var handling.

Source: granite4.1:30b@2026-05-22-audit

Confidence: low

Other Low

affected_surface

affected_surface

Source: llm_adapter@2026-05-21

Confidence: low

Full changelog

Fixed — /learn slash command restored (regression from #77)

  • Phase 3 plugin packaging (#77) migrated every .claude/commands/*.md slash command into an operational skill under skills/ + the bundled mureo/_data/skills/, but dropped learn entirely (deleted .claude/commands/learn.md, never created a learn skill). /learn became uninvocable while every other workflow command kept working, even though README/docs still document it. Restored as an operational skill (skills/learn/ + byte-identical bundled copy): name: learn (no _ prefix → appears in the picker), saves insights to ../_mureo-pro-diagnosis/SKILL.md (scaffolding that canonical-only knowledge base on first use), approval-required and append-only, never Claude memory or secrets/PII.

Changed — mureo configure visual refresh + official mureo logo

  • The configure Web UI got a cohesive design-system pass (refined spacing/type/color tokens, light and dark via prefers-color-scheme, crafted cards/buttons/focus states, system fonts only — strict CSP, no web fonts/CDN/build). The header now shows the official mureo wordmark (bundled logo.png / logo-dark.png, scheme-swapped). CSS-only; every data-* / data-i18n hook and EN/JA parity preserved.

Added — Google Ads OAuth-scope guidance in the auth step

  • The Web UI Google Ads auth step and docs/authentication.md now explain that a reused refresh token must carry the Google Ads scope https://www.googleapis.com/auth/adwords or API calls fail with ACCESS_TOKEN_SCOPE_INSUFFICIENT, with a link to the official Google scope reference. mureo's own OAuth already requests it; the note prevents the failure when users supply a hand-minted token.

Fixed — Meta hosted MCP on Claude Code goes through the Claude.ai connector (supersedes the earlier "/mcp register" Unreleased note)

  • A prior Unreleased change had mureo configure / mureo providers add / the wizard register meta-ads-official into ~/.claude.json on Claude Code and tell the user to finish OAuth via /mcp → Authenticate. Real-environment verification proved this cannot work: Meta's hosted MCP (https://mcp.facebook.com/ads) does not support OAuth Dynamic Client Registration, so Claude Code's /mcp OAuth fails with SDK auth failed: The provided redirect_uris are not registered for this client. Registering it locally only creates an unauthenticatable user-scope server. Corrected behavior: on Claude Code, mureo now does not register Meta locally at allinstall_provider / mureo providers add return manual_required (no ~/.claude.json write, no subprocess) and the UI/CLI point the user to add Meta as a Claude.ai account connector (claude.ai → Settings → Connectors → Add custom connector → https://mcp.facebook.com/ads; Anthropic brokers the Meta Business sign-in there, requires a paid plan, then works account-wide in Claude Code and Claude Desktop and surfaces as mcp__claude_ai_MetaAds__*). mureo-native Meta is still not auto-disabled (nothing registered/verified — native steps aside only via mureo providers confirm once the connector is verified Connected; no-strand preserved). Claude Desktop is unchanged (manual_required, Settings → Connectors). This re-aligns with the "no dead config entry / Connectors" behavior described in the bullets below; the intervening "/mcp register on Code" wording is withdrawn.

Docs — mureo configure is now the documented front door; auth setup --web removed

  • mureo auth setup --web was removed (its browser credential flow is now part of the unified mureo configure UI). README and docs (cli.md, authentication.md, getting-started.md/.ja.md, byod.md/.ja.md, architecture.md) updated: every auth setup --web reference now points to mureo configure (or terminal mureo auth setup). README gained a top-of-"Choose your setup" quickstart — pip install mureo + mureo configure — enumerating what the browser UI does (host pick, basic setup, OAuth/credentials, official MCP providers, native↔official toggle, Demo/BYOD).

Fixed — official/native precedence when mureo MCP is configured after an official provider

  • MUREO_DISABLE_<PLATFORM> (which makes the mureo-native MCP step aside so an official provider is the single source for a platform) was only auto-set by mureo providers add when a mcpServers.mureo block already existed. A user who registered the official provider first and configured the mureo MCP later ended up with native + official both active and no deterministic precedence (tool ambiguity). install_mureo_mcp (the path both basic-setup and the dashboard use) now backfills the disable env, after the mureo block is written, for already-registered pipx/npm official providers (google-ads-official, ga4-official) detected by a pure host-config registry read. Meta (hosted) is intentionally out of backfill scope — detecting it needs a network claude mcp list probe that must not run on the basic-setup path; Meta native↔official is the explicit mureo providers confirm / dashboard native-toggle (both gate on the verified connector — no-strand preserved). Best-effort and idempotent (never raises, never invents a mureo block); Search Console is never disabled. Works for both Claude Code (~/.claude.json) and Claude Desktop (claude_desktop_config.json).
  • Web-UI per-platform native↔official toggle — the dashboard now shows, per official provider (when the mureo MCP is configured), the current tool source for that platform and a button to switch. POST /api/providers/native-toggle sets/unsets MUREO_DISABLE_<PLATFORM>; status exposes the per-platform state. Switching to official is allowed only when the official path is actually usable (pipx/npm provider registered, or Meta connector verified Connected) — refused with an actionable message otherwise; switching back to native is always allowed (the un-strand path). Restart Claude to apply (the flag is read once at MCP start). Host-aware (Code + Desktop), EN + JA.

Fixed — GA4 wizard inputs were collected but never saved

  • The configure-UI auth wizard's GA4 step rendered the service-account-path / project-id inputs and a "Done" button whose handler only advanced the wizard — the entered values were discarded, so GOOGLE_APPLICATION_CREDENTIALS / GOOGLE_PROJECT_ID were never written to credentials.json and the official ga4-official MCP launched unauthenticated (same class as the earlier Google Ads bug). The Done handler now POSTs each value through the allow-listed /api/credentials/env-var writer (into the ga4 section) before advancing, only proceeding if every write succeeds (otherwise it surfaces a save-failed message and stays on the step). Host-accurate labels + saving/failure status added (EN + JA).

Changed — host selector clarity + Desktop-unavailable credential-guard hook note

  • The configure-UI host selector labels were ambiguous (Claude Code (terminal) implied terminal-only). Relabelled to Claude Code (CLI, Desktop app) vs Claude Desktop app (Chat, Cowork) so users running Claude Code inside the Desktop app correctly pick the Claude Code option (which targets ~/.claude.json). Japanese punctuation made consistent (fullwidth ).
  • The credential-guard hook has no surface on Claude Desktop (install_auth_hook is a noop:unsupported_on_desktop there). The basic-setup list (wizard and dashboard) now appends "(not available on the Desktop app)" / "(デスクトップアプリでは利用できません)" to that row when the chosen host is Claude Desktop, instead of implying it can be installed.

Fixed — dashboard "mureo integrations" listed GA4 (not native) and omitted Search Console

  • The configure-UI dashboard's mureo integrations section listed Google Ads / Meta Ads / GA4. mureo ships no native GA4 tools (GA4 is official-provider-only), so GA4 did not belong there; meanwhile the genuinely mureo-native Search Console was missing (only a sub-note under Google Ads). GA4's presence came from the ga4 credentials.json section, which actually stores the official GA4 MCP's service-account env — not a mureo-native integration.
  • Removed the GA4 row; added a Search Console row. Search Console has no own credentials section (it reuses the Google Ads Google OAuth — adwords + webmasters scopes), so the row is status-only: it shows configured the moment the wizard's Search Console / Google sign-in is done (driven by the existing credentials_oauth.google signal) and has no standalone Remove (a note directs removal to the Google Ads row, since the sign-in is shared).

Fixed — official Meta Ads provider registered a dead entry on Claude Code

  • Adding the official Meta Ads MCP (meta-ads-official, hosted at https://mcp.facebook.com/ads) on Claude Code wrote a raw {"type":"http","url":…} entry into ~/.claude.json and set MUREO_DISABLE_META_ADS=1. But Meta's hosted MCP has no OAuth Dynamic Client Registration, so Claude Code can never connect that raw entry (✗ Failed to connect) — while mureo-native Meta was disabled, leaving the user with zero Meta capability (the model fell back to a mureo-native "credentials not found" error). The Desktop path already short-circuited this; the Code path and the mureo providers add CLI did not.
  • Claude Code, the mureo providers add CLI, and Claude Desktop now treat hosted_http providers consistently: no dead config entry is written and mureo-native tools are NOT auto-disabled (auto-disabling before the official path is verified strands the user). The result is manual_required, and the UI/CLI now point the user to Claude's account-level Connectors (the working path mureo cannot create programmatically). Connectors setup guidance is host-accurate — terminal (Claude Code) vs Claude Desktop have genuinely different steps — EN + JA. mureo providers remove still self-heals a stale MUREO_DISABLE_<PLATFORM> left by the old logic so native Meta comes back.
  • mureo providers confirm <id> (new) + a Web UI "I've connected it — finalize" button close the post-setup coexistence gap: once the official hosted connector is verified Connected (parsed from claude mcp list), the overlapping MUREO_DISABLE_<PLATFORM> is set so the model stops calling the credential-less mureo-native tools. Native is only disabled after the official path is confirmed working — never before (no stranding). Claude Desktop returns manual (no programmatic signal there; the user verifies in Settings → Connectors). The claude mcp list probe is timeout-bounded so an unreachable endpoint can't hang the call.
  • The dashboard's Official MCP providers list previously showed meta-ads-official as permanently (mureo never registers a hosted connector in the config file). It now reflects the real account-level Connector state: a new POST /api/providers/hosted-status endpoint (lazily fetched, cached) flips the row to once the Connector is Connected. The probe is a SEPARATE endpoint, intentionally not folded into /api/status, so it never slows every status poll. Hosted rows never get a Remove button (mureo cannot unregister an account Connector).

Fixed — official Google Ads provider was registered but unusable

  • Selecting the official Google Ads MCP from the mureo configure Web UI registered the provider but left it unable to authenticate: (1) the wizard's Developer-Token + Google OAuth step only ran for the mureo-native provider choice, so picking official skipped credential collection entirely; and (2) the registered mcpServers["google-ads-official"] block carried no env, while the upstream google-ads-mcp reads its config only from environment variables (never mureo's ~/.mureo/credentials.json). Net effect: "✓ registered" then "✗ Failed to connect".
  • The Web UI auth step now runs for both native and official Google Ads (same Developer Token + OAuth refresh token), the wizard now orders auth before providers_install so credentials exist when the block is written, and install_provider resolves the credential env from credentials.json (closed allow-list, reverse of the per-var writer) and injects it into the registered provider block — Claude Code (~/.claude.json) and Claude Desktop alike. Meta's hosted MCP is correctly excluded (it authenticates via browser OAuth on first connect; no env to inject). Credential values are redacted from any claude mcp add-json failure message before it can reach a log line.

Added — mureo configure Web UI (Issue #88, Phase 1: localhost setup wizard)

  • mureo configure — local Web UI for non-engineer onboarding. Spawns a stdlib-only HTTP server bound to 127.0.0.1 (ephemeral port by default; --port to pin; --no-browser to suppress auto-open; --timeout-seconds for idle exit). Renders a single Japanese settings page with cards for current status, official MCP providers (add/remove via the audited mureo.providers.config_writer helpers), OAuth handoff stubs, and an allow-listed env-var writer that routes through mureo.auth_setup.save_credentials (mode 0o600). Defense-in-depth: hard-coded localhost bind, Host-header validation on every route (DNS-rebinding defense), per-process CSRF (secrets.token_urlsafe(32) + secrets.compare_digest), full CSP / X-Content-Type-Options / X-Frame-Options: DENY / Referrer-Policy: no-referrer headers, 16 KiB POST cap, basename allow-list for static assets, 405 responses for unsupported HTTP methods. Stdlib only — no Flask/FastAPI/jinja2 dependency added (regression-pinned by test_pyproject_does_not_depend_on_web_framework).

Added — plugin → MCP tool exposure (Issue #89 follow-up)

  • mureo.mcp.tool_provider: new MCPToolProvider opt-in secondary Protocol (mcp_tools() + async handle_mcp_tool()) and collect_plugin_tools(). A third-party provider discovered via the mureo.providers entry-point group that also satisfies MCPToolProvider now has its operations published as mcp__mureo__* tools. A provider that does not implement it is still discovered and skill-matched, just not exposed (graceful). Added to the stable plugin ABI (see docs/ABI-stability.md §1).
  • mureo/mcp/server.py: purely additive wiring — built-in platforms keep their static tool list and are not routed through the plugin path (no double-exposure). With no third-party plugins installed, the tool list and behaviour are byte-identical to before. Built-in tool names are reserved (a colliding plugin tool is dropped, built-ins win); plugin↔plugin collisions are first-wins; a broken/malicious plugin (construct / mcp_tools() / non-async handler / wholesale discovery failure) is skipped with a PluginToolWarning and can never crash the server or starve other plugins.
  • Docs: plugin-authoring.md §3 "Exposing operations as MCP tools", mcp-server.md "Plugin-Provided Tools", ABI-stability.md updated.

Fixed — BYOD/demo relative windows silently went empty over time

  • The CSV-backed BYOD/demo clients resolved relative MCP query windows (LAST_7_DAYS, …) against date.today(). The demo dataset has fixed historical dates, so as wall-clock time moved past it the demo silently returned []LAST_7_DAYS first, then every window — making Meta insights / anomaly checks / Search Console appear broken even though the data was present.
  • _period_to_range now accepts an optional anchor; the BYOD/demo metrics readers anchor relative windows on the dataset's own latest date (same span, ending at the most recent available day) so the demo stays non-empty regardless of the current date. anchor=None preserves the exact legacy wall-clock behaviour, so live-API and non-demo callers are completely unaffected.

Added — mureo providers CLI (Issue #86, Phase 1: Claude Code)

  • mureo providers list / add / remove — one-command install of the official platform MCP servers into Claude Code's ~/.claude/settings.json. mureo owns both package acquisition and config registration. add is idempotent; add --all installs every catalog entry and continues past per-provider failures (non-zero exit overall). --dry-run prints the planned pipx/npm argv (or, for hosted endpoints, the "no local install step" notice) plus the JSON delta without touching disk or subprocess. remove only edits the settings file (it does not uninstall the underlying pipx/npm package; no-op for hosted-HTTP entries which have none).
  • Phase 1 catalog (3 entries):
    • Google Ads (google-ads-official, pipx from github.com/googleads/google-ads-mcp — env-var Client Library config, no OAuth Proxy / ADC modes in Phase 1).
    • Meta Ads (meta-ads-official, hosted HTTP at https://mcp.facebook.com/ads — Meta's official "Meta Ads AI Connectors" announced 2026-04-29; interactive Meta Business OAuth in the browser on first connect, no Meta Developer App, no API tokens, no env vars to pre-populate; currently in public beta and free).
    • GA4 (ga4-official, pipx install analytics-mcp from github.com/googleanalytics/google-analytics-mcp — service-account JSON via GOOGLE_APPLICATION_CREDENTIALS, read-only Reporting + Admin APIs).
  • New mureo/providers/ package: catalog.py (frozen ProviderSpec + immutable Phase 1 catalog with three install_kind families: pipx, npm, hosted_http), installer.py (list-form subprocess with pipx/npm executable allow-list — no shell=True, no env= kwarg; hosted_http short-circuits subprocess entirely), config_writer.py (atomic os.replace from a same-dir .tmp.<pid> file with 0o600 mode and fd-fsync + best-effort parent-dir fsync; refuses to overwrite malformed-JSON existing settings via ConfigWriteError), coexistence.py (warning when an official provider overlaps with a mureo-native platform), mureo_env.py (per-platform MUREO_DISABLE_* env-var writers).
  • Auto-disable mureo's native tool family when an official provider for an overlapping platform is added (extension to Phase 1, per Founder Q1/Q2 review). mureo providers add google-ads-official now also writes mcpServers.mureo.env.MUREO_DISABLE_GOOGLE_ADS="1" (and analogous keys for Meta Ads / GA4) in the same atomic os.replace that adds the official provider — no torn-write window. The mureo MCP server reads these env vars once at import time and excludes the matching tool family from _ALL_TOOLS and the dispatch table; the comparison is exact-string == "1" (any other value keeps tools enabled). mureo providers remove <id> pops the matching env var. Search Console is intentionally exempt — mureo remains canonical for SC, no MUREO_DISABLE_SEARCH_CONSOLE is honored. When no mcpServers.mureo block exists, the CLI registers the official provider as before and emits a degraded coexistence note pointing at mureo setup claude-code.
  • Workflow skills are now provider-aware when an official MCP is installed. Skills under mureo/_data/skills/ (daily-check, rescue, search-term-cleanup, budget-rebalance, creative-refresh, competitive-scan, weekly-report, sync-state, onboard) keep mureo native tool names as the primary path — so existing users running mureo setup claude-code see zero behavior change. The skills now also instruct the LLM to fall back to the official MCP's equivalent tools when mureo's tools for that platform are unavailable (i.e. MUREO_DISABLE_<PLATFORM>=1 is set because the user ran mureo providers add <id>), and to gracefully skip mureo-only value-add features (anomaly detection, RSA asset audit, result_indicator analysis, rule-based scoring, etc.) with a user-facing note pointing back to mureo setup claude-code for full coverage.
  • Phase 2 (Cursor / Codex / Gemini config writing for official providers) is deferred to a separate Issue. Search Console intentionally remains out of the catalog — mureo's native MCP stays canonical.

Breaking Changes

  • Removed `mureo auth setup --web` CLI flag and its associated browser credential flow; all authentication now occurs via the unified `mureo configure` Web UI.
  • /learn slash command was deleted in Phase 3 plugin packaging and is now restored as an operational skill.

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

Share this release

Track logly/mureo

Get notified when new releases ship.

Sign up free

About logly/mureo

Framework for AI agents (Claude Code, Cursor, Codex, Gemini) to operate Google Ads, Meta Ads, and Search Console. Grounded in a local STRATEGY.md — not metric-chasing. Defense-in-depth security, local-first. Apache 2.0.

All releases →

Beta — feedback welcome: [email protected]