Pax8 Renewal & License Optimizer

A worked example of an advanced workflow: a Claude-managed scheduled agent that, once a week, sweeps Pax8 subscriptions across managed companies to surface upcoming renewals in the next 30, 60, and 90 days (with committed monthly value) and flags over-provisioned subscriptions as optimization candidates. It posts a combined renewal and optimization digest to Slack as a canvas with a one-line summary. There are no servers and no code to deploy: the agent is a saved prompt plus a schedule plus two MCP connectors, running in Claude's cloud.

What it builds

The finished workflow runs unattended on a weekly Monday cron. Each run it lists subscriptions for every managed company in Pax8, buckets upcoming renewals into 30, 60, and 90-day windows with their committed monthly value, flags subscriptions whose provisioned seat counts look over-allocated relative to usage, and notifies your team — turning scattered subscription data into a single renewal calendar and spend-optimization digest with a Slack trail. The routine is entirely read-only on Pax8; the only write is delivering the report via the Slack connector.


Prerequisites

Before building, your Claude account needs all of the following:

RequirementNotes
WYRE MCP Gateway connector Connected in claude.ai (https://mcp.wyre.ai/v1/mcp). Provides the gateway tools. See the Gateway overview.
Pax8 tools in the gateway The Pax8 connector must be enabled in the gateway. Verify with gateway__search_tools (query: "pax8") and use the exact tool names the catalog returns. The tool names used in this guide (pax8_list_companies, pax8_list_subscriptions, pax8_list_products) follow the gateway naming convention — confirm against the catalog before building.
Slack connector The first-party Slack connector connected in claude.ai (https://mcp.slack.com/mcp). Provides slack_create_canvas and slack_send_message.
Scheduled routines access Created via the /schedule capability; managed at claude.ai/code/routines.
A destination Slack channel e.g. #sw-dev, plus its channel ID. The Slack connector must have access to it.

Known gotchas

These are the things that cost real time the first time through. Account for them up front and the build genuinely takes minutes.

  • Confirm Pax8 tool names against the gateway catalog before building. The tool names in this guide (pax8_list_companies, pax8_list_subscriptions, pax8_list_products) follow the gateway's <vendor>_<action>_<entity> naming convention and are the most likely names — but always run gateway__search_tools with query "pax8" first and use whatever names the catalog actually returns. Setting wrong tool names in permitted_tools means the routine runs with no effective tools.
  • A large Pax8 estate may need scoping — list companies first, then iterate. Like the Datto fleet sweep, sweeping every company's subscriptions in a single routine run risks overflowing the run's payload before it can finish. Call pax8_list_companies first to see how many companies you manage, then sample a few subscription payloads to gauge size. If the combined payload is heavy, bake a fixed set of priority company IDs into the routine prompt rather than iterating the whole estate.
  • License-usage signals may not be available from Pax8 alone. Pax8 subscription records expose provisioned quantities and pricing; whether they include active-usage figures (consumed seats, active licenses) depends on the product and what the Pax8 API surfaces. Where no usage signal is available, the optimization section flags candidates for human review rather than asserting reclaimable spend. Do not tune the routine prompt to invent usage figures.
  • permitted_tools must be populated per connector. A routine with a connector attached but an empty permitted_tools list runs with no tools and silently does nothing — no error, no output. List the exact tool names the routine needs, using the confirmed names from the gateway catalog.
  • A routine reaches only its attached connectors. The routine sandbox blocks arbitrary network egress, so notifications must go through the Slack connector's tools, not an outbound webhook. Attach every connector the workflow touches.
  • Faster-than-hourly cadences are rejected. The routine scheduler will not accept a cron more frequent than hourly. A weekly cron is well within bounds. Cron expressions are interpreted as UTC: Monday 09:00 America/New_York = 0 13 * * 1 in UTC (or 0 14 * * 1 during EDT offset months — confirm your preferred offset).
  • If Slack does not appear in the /schedule connector list, read its connector_uuid and url from an existing routine that already uses Slack (RemoteTrigger list → get → mcp_connections).
  • Prefer list payloads over per-record gets. Subscription data needed for both the renewal calendar and the optimization heuristic should be available from pax8_list_subscriptions without a per-record fetch. Per-record calls across a large subscription estate risk the 60-second tool timeout.

The one-shot build prompt

With the connectors above in place, paste this to Claude. It confirms the gateway and Pax8 reachability, assesses payload size, creates the routine with both connectors and populated permitted_tools, and verifies it end to end.

Build me a scheduled Pax8 Renewal & License Optimizer agent. Do all of this
end to end:

1. Confirm the WYRE MCP Gateway works and Pax8 is reachable: call
   gateway__search_tools with query "pax8" to get the exact tool names, then
   call pax8_list_companies (or the catalog-confirmed equivalent) and check it
   returns your managed companies.
2. Confirm a Slack connector is connected. Note the destination channel name
   and ID (e.g. #sw-dev). If Slack does not show in the /schedule connector
   list, read its connector_uuid and url from an existing routine that already
   uses Slack (RemoteTrigger list -> get -> mcp_connections).
3. Assess payload size. Call pax8_list_subscriptions for one or two companies
   to gauge how large the per-company subscription payload is. If your Pax8
   estate is large (many companies with many subscriptions each), choose a
   fixed set of priority companies and bake their IDs into the routine prompt
   rather than sweeping the whole estate in one run.
4. Create a Claude-managed scheduled routine named "Pax8 Renewal & License
   Optimizer":
   - Schedule: weekly, cron "0 13 * * 1" (Monday 09:00 America/New_York =
     13:00 UTC). Faster-than-hourly cadences are rejected.
   - Attach TWO connectors, each with permitted_tools populated:
       * WYRE MCP Gateway: pax8_list_companies, pax8_list_subscriptions,
         pax8_list_products  (use the exact names from the gateway catalog)
       * Slack: slack_create_canvas, slack_send_message
     An empty permitted_tools list = the routine runs with no tools.
   - Routine prompt: every run, list managed companies, list each company's
     subscriptions, bucket renewals by 30/60/90-day window with committed
     monthly value, flag over-provisioned subscriptions and estimate
     reclaimable monthly spend, build the combined renewal + optimization
     report, publish it as a Slack canvas, and post a one-line summary
     linking the canvas. Use the exact routine prompt below.
5. Trigger a manual run and verify: a canvas titled "Pax8 Renewals &
   Optimization - <date>" was created, a one-line summary landed in the
   destination channel, and the report content matches live Pax8 data
   (spot-check one company's subscriptions).

The resulting routine prompt

This is the lean prompt the build process installs into the scheduled routine itself. Substitute your own destination channel and bake in specific company IDs if your estate needs scoping.

You are the Pax8 Renewal & License Optimizer. You run weekly. Keep it lean.

Use ONLY: pax8_list_companies, pax8_list_subscriptions, pax8_list_products,
slack_create_canvas, slack_send_message.
Confirm exact tool names against the gateway catalog (gateway__search_tools)
before the first run and update permitted_tools if any names differ.

Today's date: use the current date at runtime to calculate renewal windows.

--- RENEWAL CALENDAR ---

1. Call pax8_list_companies to get the list of managed companies.
   If a fixed company list is baked in below, use that instead:
   - <company-id-1> - <company name 1>
   - <company-id-2> - <company name 2>
   - ... (bake in IDs if your estate is large) ...

2. For each company, call pax8_list_subscriptions. For each subscription
   record, read: company name, product/SKU name, quantity (provisioned seats),
   commitment term, renewal date (or end date), and unit price.

3. Bucket each subscription by days until renewal from today:
   - 30-day window:  renews within 0-30 days
   - 60-day window:  renews within 31-60 days
   - 90-day window:  renews within 61-90 days
   Skip subscriptions renewing beyond 90 days.

4. For each bucketed subscription record the committed monthly value:
   quantity x unit price x billing frequency factor (monthly = 1,
   annual = divide annual total by 12). Label the value as estimated
   if the billing period or unit price is unclear from the payload.

--- OPTIMIZATION OPPORTUNITIES ---

5. For each subscription, assess whether the provisioned seat count looks
   over-allocated:
   - If a usage figure is available in the payload (active seats, consumed
     licenses, etc.), flag any subscription where provisioned quantity
     materially exceeds active usage (e.g. more than 20% unallocated).
     Estimate reclaimable monthly spend: (provisioned - active) x unit price.
   - If no usage signal is available in the payload, flag the subscription
     as a "candidate for human review" — do NOT assert reclaimable spend
     without a usage figure.
   Include the line: "Usage data availability varies by product; candidates
   marked for review require manual verification in the Pax8 portal."

--- REPORT ---

6. Build a combined report:
   SECTION A — Renewal Calendar
     For each 30/60/90-day bucket: list company, product/SKU, quantity,
     renewal date, and estimated committed monthly value.
     End with a bucket summary (count and total committed monthly value per
     window).

   SECTION B — Optimization Opportunities
     List each flagged subscription: company, product/SKU, provisioned
     quantity, active usage (if available), estimated reclaimable monthly
     spend (if calculable), or "candidate for human review".
     End with total estimated reclaimable monthly spend (where calculable).

7. slack_create_canvas titled "Pax8 Renewals & Optimization - <today's date>"
   with the full combined report. Then slack_send_message to #sw-dev: a
   one-line summary ("Pax8: N renewals in 90 days (~$X committed/mo),
   N optimization candidates - see canvas") linking the canvas.

8. If a company's subscriptions cannot be read, list it in a "could not read"
   section instead of skipping it silently.

How it works

A weekly cadence, by design

Subscription renewals have a predictable calendar horizon — the 30/60/90-day windows give account managers and procurement time to act before auto-renewal locks in the next term. Running weekly on Monday morning means the team starts each week with a fresh renewal view. A weekly sweep is also light on API calls compared to daily.

The renewal calendar: 30/60/90-day buckets with committed value

For each subscription the routine reads the renewal or commitment date and calculates days until renewal from the run date. Subscriptions are bucketed into three windows: within 30 days (act soon), 31–60 days (plan), 61–90 days (pipeline). Each entry in the calendar carries the subscription's committed monthly value — quantity times unit price, normalized to a monthly figure so annual and monthly subscriptions are directly comparable. The section ends with a per-bucket total so the reader can see at a glance how much committed spend is rolling over in each window.

The optimization heuristic and why it stays advisory

Where the Pax8 payload includes an active-usage figure (consumed seats, active licenses), the routine flags subscriptions whose provisioned quantity materially exceeds that usage and estimates reclaimable monthly spend. Where no usage figure is in the payload — which may be the case for many product types — the routine marks those subscriptions as candidates for human review and explicitly does not invent a reclaimable spend number. This is intentional: asserting recoverability without a usage signal would make the report unreliable. The optimization section is a triage list, not an invoice. A cross-check against M365 assigned licenses (see Extending it below) can sharpen this signal for Microsoft-seat products.


Extending it

The natural first extension is a true provisioned-vs-assigned reconciliation for Microsoft-seat products: cross-check Pax8 provisioned quantities against M365 assigned licenses via the CIPP or Microsoft 365 connectors (see the M365 License Auditor guide). Pax8 tells you how many seats you are paying for; CIPP tells you how many are actually assigned to users. The gap between the two is the reclaim opportunity — a signal that neither system alone can surface.

A second extension is feeding the renewal calendar into a broader renewal workflow: if your team tracks renewals in Autotask or HaloPSA, a second connector on the same routine (or a downstream routine triggered by the canvas) could create or update renewal opportunity records automatically when subscriptions enter the 30-day bucket.

Questions or a workflow you'd like documented? Open an issue in the msp-claude-plugins repository.