query_self_service_catalog

query_self_service_catalog

Detects which Self Service catalog (Jamf Self Service, Intune Company Portal, or Munki Managed Software Center) is installed on the device, and best-effort lists available apps. Use during software-reinstall Step 4 (after check_mdm_enrollment) to surface the non-admin install path for managed enterprise users. Read-only — does not modify any state.

Metadata

Name

query_self_service_catalog

Updated

2 months ago

Source

GitHub source

Risk

Low

Requires consent

false

Affected scope

user

Code

/**
 * mcp/skills/querySelfServiceCatalog.ts — query_self_service_catalog skill
 *
 * Detects which Self Service catalog (Jamf Self Service, Intune
 * Company Portal, or Munki Managed Software Center) is installed on
 * the device, and best-effort enumerates apps available through it.
 * Used by Skill #8 (software-reinstall) so non-admin users on
 * managed devices can install through the corp catalog instead of
 * needing local admin.
 *
 * Read-only / user-scope tool — does NOT route through the privileged
 * helper daemon.  Catalogs handle privilege escalation server-side
 * via their own management agents.
 *
 * Smoke test
 *   npx tsx -r dotenv/config mcp/skills/querySelfServiceCatalog.ts
 */

import { z } from "zod";
import {
  detectCatalog,
  queryCatalog,
  type CatalogQueryResult,
} from "./_shared/selfServiceCatalogs";

// -- Meta ---------------------------------------------------------------------

export const meta = {
  name: "query_self_service_catalog",
  description:
    "Detects which Self Service catalog (Jamf Self Service, Intune " +
    "Company Portal, or Munki Managed Software Center) is installed " +
    "on the device, and best-effort lists available apps. Use during " +
    "software-reinstall Step 4 (after check_mdm_enrollment) to surface " +
    "the non-admin install path for managed enterprise users. " +
    "Read-only — does not modify any state.",
  riskLevel:       "low",
  destructive:     false,
  requiresConsent: false,
  supportsDryRun:  false,
  affectedScope:   ["user"],
  auditRequired:   false,
  schema: {},
} as const;

// -- Exported run function ----------------------------------------------------

export async function run(_args: Record<string, never> = {}): Promise<CatalogQueryResult> {
  const presence = await detectCatalog();
  return queryCatalog(presence);
}

// -- Smoke test ---------------------------------------------------------------

if (false) {
  run()
    .then(r => console.log(JSON.stringify(r, null, 2)))
    .catch((err: Error) => { console.error(err.message); process.exit(1); });
}