Skip to content

[MCP reslice 2/2] @churnkey/mcp tool definitions#25

Merged
hookdump merged 12 commits into
mainfrom
reslice/mcp-2-tools
Jul 2, 2026
Merged

[MCP reslice 2/2] @churnkey/mcp tool definitions#25
hookdump merged 12 commits into
mainfrom
reslice/mcp-2-tools

Conversation

@hookdump

@hookdump hookdump commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

MCP reslice 2 of 2 for @churnkey/sdk — stacked on #24 [MCP reslice 1/2] transport + OAuth client (merged). Together the two PRs reproduce the #23 MCP Overhaul byte-for-byte, re-sliced into reviewable layers — plus one deliberate fix on top (MCP OAuth login for generic clients; see “Included fix” at the bottom).

This PR is the tool surface of the @churnkey/mcp server: every tool definition (thin, well-described wrappers over the /v1/data API), the tools/index.ts registry, and the per-tool test suites. Authorization is enforced server-side by the OAuth scopes from reslice 1/2 — the tools just declare and call.

Tool families in this PR

Family Tools Origin
Sessions & analytics list_sessions, aggregate_sessions, get_flow_metrics 0.x warehouse work + get_flow_metrics (XDEV-2331)
Payment-recovery analytics list_payment_recoveries, aggregate_payment_recoveries 0.x warehouse work
Cancel-flow blueprints list_blueprints, get_blueprint, create_blueprint, update_blueprint_draft/_step/_offer, edit_survey_structure, add/remove_blueprint_step, publish_blueprint Blueprint CRUD tools (XDEV-2316)
Segments list_segments, list_segment_attributes, create_segment_flow, reorder_segments, set_segment_enabled, update_segment_filter, archive_segment Blueprint CRUD tools (XDEV-2316)
Stripe settings & adaptive offers get/update_stripe_settings, get/update_adaptive_offers XDEV-2336, XDEV-2335
DNS / hosted domains get_dns_config, set_hosted_subdomain, add/remove_custom_domain, check_domain_status XDEV-2330
Payment-recovery campaigns list/get/clone_recovery_blueprint, update_recovery_email/_email_offers/_sms, add/remove_recovery_email, update_recovery_audience, list_recovery_audience_attributes, set_recovery_blueprint_enabled, publish_recovery_blueprint, list_recovery_campaigns, get_recovery_campaign_messages, get_recovery_engagement, stop_recovery_campaign XDEV-2332 + dashboard-parity follow-up
A/B tests list/create/start/pause/complete_ab_test, get_ab_test_metrics, pick_ab_test_winner XDEV-2333
Audit get_audit_log Audit-trail read surface
Compliance dsr_access, dsr_delete Pre-existing Data API contract
Account get_account New (see below)

Rolls up these (now-closed) per-feature PRs

The overhaul squashed a series of standalone tool PRs; this reslice carries their tool-layer content forward:

(OAuth/per-user auth from #15 / XDEV-2334 and the HTTP transport from #10 live in reslice 1/2, #24.)

Added since the reslice

  • get_account + effective-mode visibility (commit ecdb80f): a no-scope get_account tool (org / user / entitlements / granted scopes / live-or-test mode) registered first so agents orient before acting; plus a modeScoped flag that echoes Mode: LIVE|TEST and a mode-sensitivity note on list_sessions/aggregate_sessions — the only mode-partitioned surface. Pairs with GET /v1/data/account in churnkey-api #889.

Verification

  • tsc clean, tsup build clean.
  • 227/227 vitest tests pass.

Supersedes: the tool portion of #23 (and #6, #16#22).

🤖 Generated with Claude Code


Included fix — MCP OAuth login for generic clients (folds in the former #29)

Discovered while running the MCP feature end-to-end against dev: generic MCP OAuth clients (Claude Code, Claude.ai, ChatGPT) could not complete login — the /authorize step returned "At least one scope is required."

Root cause: the RFC 9728 protected-resource metadata served by the MCP HTTP server (packages/mcp/src/http.ts) omitted scopes_supported. Clients that discover scopes from the PRM therefore began the authorization request with an empty scope, which the authorization server rejects. The SDK CLI was unaffected (it sends DEFAULT_SCOPES explicitly).

Fix (commit a696bde): the PRM now advertises DEFAULT_SCOPES. Confirmed against both live prod (mcp.churnkey.co) and dev (mcp-dev.churnkey.co) metadata; adds a regression test that boots the real server and asserts the PRM advertises scopes. This is the one intentional delta on top of the byte-for-byte overhaul reproduction.

Server-side companion (defense-in-depth): churnkey-api#928 makes the /authorize endpoint default an omitted scope (RFC 6749 §3.3) instead of hard-rejecting. Independent review/merge — not required for this fix.

Deploy note: the PRM is served by the hosted MCP server (Elastic Beanstalk), built from this repo via ops/mcp/deploy-mcp.sh dev|prod.

hookdump added 11 commits June 30, 2026 16:06
confirmLiteral(), the shared confirm-token guard the mutating tool definitions
gate their writes behind.
list/get_blueprint, create_blueprint, granular draft edits (update_blueprint_draft/
_step/_offer, edit_survey_structure, add/remove_blueprint_step), and the
confirm-gated publish_blueprint. Draft-only; publish is the single live gate.
list_segments, list_segment_attributes, create_segment_flow, and the
confirm-gated reorder/set_enabled/update_filter/archive on live segment config.
get_flow_metrics (per-flow performance, boosted revenue, outcomes, sample-size
warning) and the shared filter/query-builder coverage used by the session and
recovery analytics tools.
Recovery blueprint config CRUD, the clone template library, dashboard-parity
email/SMS/offer/audience editing, running-instance reads + engagement, and the
irreversible stop_recovery_campaign. Rolls up the XDEV-2332 tools + parity follow-up.
list/create/start/pause/complete_ab_test, get_ab_test_metrics (per-arm
significance, n>=30 rule), and the confirm-gated pick_ab_test_winner.
get_dns_config, set_hosted_subdomain, add/remove_custom_domain, check_domain_status
with the exact customer-side records surfaced in every response.
…335)

get/update_stripe_settings (per-setting descriptions + recommendations, conflict
explanations) and get/update_adaptive_offers (strategy presets, guardrails,
Intelligence gating, compound-scope rule).
The attributed workspace audit trail (summaries, source filtering for agent vs
dashboard actions, before/after diffs) under account.audit_log.read.
Assemble allTools() from every family above. Sweep commit — reconciles the tree
to the tool-definitions layer exactly.
Add get_account (no scope required): org / user / entitlements / granted
scopes / effective mode — registered first to nudge agents to orient before
acting. Backed by GET /v1/data/account.

Introduce a `modeScoped` tool flag that drives (a) a "Mode: LIVE|TEST" echo on
results and (b) a mode-sensitivity note appended to the description (data vs
traffic flavor by readOnlyHint). Applied ONLY to list_sessions /
aggregate_sessions — the sole mode-partitioned surface. Recovery analytics,
flow metrics, and DSR are mode-independent server-side, so they are
deliberately left unmarked. README + CHANGELOG updated to match.
@hookdump hookdump force-pushed the reslice/mcp-2-tools branch 2 times, most recently from e234a8a to e7ff2b4 Compare July 1, 2026 19:29
@hookdump hookdump requested a review from jordancardwell July 2, 2026 14:57
Generic MCP OAuth clients (Claude.ai, ChatGPT, Claude Code) discover which
scopes to request from the resource's RFC 9728 Protected Resource Metadata.
The PRM omitted `scopes_supported`, so those clients began the authorization
request with an empty scope set, which the authorization server rejects with
"At least one scope is required" — blocking OAuth login entirely for every
generic client. Only the SDK CLI was unaffected (it sends DEFAULT_SCOPES
explicitly via `churnkey auth login`).

Echo DEFAULT_SCOPES (the full supported set, matching the AS metadata's
scopes_supported) from the PRM so clients know what to request. Add a
regression test asserting the live PRM advertises scopes.

This affects prod (mcp.churnkey.co) and dev (mcp-dev.churnkey.co) identically
— both PRMs were missing the field.

Claude-Session: https://claude.ai/code/session_01HJRLEbMuREpbVfyNeMoP6h
@hookdump hookdump merged commit 28ecbf2 into main Jul 2, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants