# CloudSense Customer Compass

MCP server for CloudSense customer upgrade assessment, analysis, and impact verification.

| | |
|---|---|
| **Package** | `cloudsense-customer-compass` |
| **Version** | `0.11.1` |
| **Python** | `>=3.10` |
| **License** | MIT |

## Prerequisites

- **`uv`** (recommended) — install with `curl -LsSf https://astral.sh/uv/install.sh | sh` (macOS/Linux) or `brew install uv` if you have Homebrew. Handles Python automatically, no separate Python install needed. See [uv installation docs](https://docs.astral.sh/uv/getting-started/installation/) for other options.
- **Or** Python 3.10+ if you prefer `pip`/`pipx`
- Salesforce CLI (`sf`) — [install](https://developer.salesforce.com/tools/salesforcecli)

## Installation

```bash
# Via uvx (recommended — no Python install needed, always runs latest)
uvx cloudsense-customer-compass

# Or via pipx (requires Python 3.10+)
pipx run cloudsense-customer-compass

# Or install globally via pip (requires Python 3.10+)
pip install cloudsense-customer-compass
```

## MCP Configuration

### Cursor IDE

Go to **Settings → MCP Servers** and add:

```json
{
  "mcpServers": {
    "CloudSense Customer Compass": {
      "command": "uvx",
      "args": ["cloudsense-customer-compass"]
    }
  }
}
```

### Claude Desktop

Add to your config file:

- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
- **Linux:** `~/.config/Claude/claude_desktop_config.json`

```json
{
  "mcpServers": {
    "CloudSense Customer Compass": {
      "command": "uvx",
      "args": ["cloudsense-customer-compass"]
    }
  }
}
```

### Claude CLI

```bash
claude mcp add "CloudSense Customer Compass" -- uvx cloudsense-customer-compass
```

## Available Tools

| Tool | Description |
|------|-------------|
| `connect_lma` | Authorize the CloudSense LMA Salesforce org. First tool to call for any workflow. |
| `find_customer` | Search for a customer by name (SOQL LIKE primary, SOSL fallback). Returns matches with region and industry for disambiguation. On confirmation, returns full account profile (industry, region, parent company, description, website, LinkedIn) for AI context. |
| `get_customer_licenses` | Retrieve all production and sandbox licenses for a customer. Searches Account links and Company name (with word-boundary filtering to exclude trialforce/training orgs). Returns per-package summary with seat utilization (licensed, used, util%), version currency (installed vs. latest available), expiry, and org breakdown. Writes full data to `customers/<slug>/licenses.json`. |
| `get_portfolio_data` | Fetch ALL active/trial production licenses enriched with seat utilization, version currency, per-package expiry, account context (region, industry, parent company), and corporate group analysis. Distinguishes `upcoming_expiry_days` (next future renewal) from `nearest_expiry_days` (includes already-expired). Includes License Expiry Interpretation rules to prevent hallucination on stale/perpetual licenses. Saves timestamped snapshots for change detection. AI applies composite scoring framework from editable `portfolio/scoring-rules.md`. |
| `save_report` | Save AI-generated analysis, insights, or discussion notes as a shareable markdown file. Works across any MCP client (Cursor, Claude Desktop, etc.). |
| `generate_visual_report` | Generate a self-contained HTML visual report with Chart.js charts. The AI builds the layout on the fly using a CSS design system -- no rigid templates. Supports KPI cards, styled tables, tags, progress bars, and interactive charts (bar, doughnut, line, etc.). Saved to `.visual-reports/` in the workspace. Auto-opens in the browser; print-to-PDF ready via Cmd/Ctrl+P or the in-page Save as PDF button. |
| `submit_feedback` | Submit a bug report or feature request. The AI detects when you mention an issue or suggest a feature and offers to send it to the team. Feedback is delivered to the same Google Sheet as usage telemetry — no extra setup needed. |

## Workflows

### Single Customer Analysis

```
connect_lma              → Authorize the CloudSense LMA org
find_customer            → Search by name, confirm (returns full account profile)
get_customer_licenses    → License, package, org summary + seat utilization
                           + version currency (installed vs. latest available)
```

### Portfolio Analysis

```
connect_lma              → Authorize the CloudSense LMA org
get_portfolio_data       → Full portfolio snapshot with health-scoring data
                           (seats, versions, region, industry, parent groups)
                           Auto-creates portfolio/scoring-rules.md on first run
                           Saves timestamped snapshot + detects changes
AI scoring               → Composite health score per customer (4 dimensions)
                           Corporate group analysis, opportunity flags
                           Uses rules from portfolio/scoring-rules.md
save_report              → Persist ranked insights as shareable markdown
                           Supports persona-based reports (exec, sales, tech, CS)
```

### Customising Health Scores

Edit `portfolio/scoring-rules.md` to change weights, thresholds, core
packages, opportunity detection rules, or report persona templates.
Changes take effect on the next `get_portfolio_data` call. You can also
override any rule conversationally (e.g. "for this analysis, treat csbb
as critical") or run what-if scenarios ("what if we drop R35 support?").

### Coming Soon

```
get_installed_packages   → Per-package baseline from customer sandbox
list_metadata            → Discover metadata members by type
retrieve_metadata        → Pull metadata in chunks
get_repo_mapping         → Map packages to GitHub repos
clone_package_repos      → Clone repos for version diff
```

## Workspace Output Structure

Tools write their output to a structured workspace directory:

```
workspace/
├── assessment.json              # LMA connection info only
├── customers/                   # per-customer data
│   ├── nbn-co-ltd/
│   │   ├── licenses.json
│   │   └── analysis-2026-03-14.md
│   └── starhub/
│       └── licenses.json
├── portfolio/                   # cross-customer analysis
│   ├── scoring-rules.md          # editable health scoring rules
│   ├── portfolio-data.json
│   ├── history/                  # timestamped snapshots for trend analysis
│   │   ├── portfolio-data-2026-03-01.json
│   │   └── portfolio-data-2026-03-14.json
│   └── insights-2026-03-14.md
├── .visual-reports/             # auto-generated HTML reports (browser viewer)
│   ├── apac-portfolio-2026-03-16.html
│   └── nbn-co-analysis-2026-03-16.html
├── packages/                    # per-package artifacts (coming soon)
│   ├── <namespace>/
│   │   ├── package-info.json
│   │   ├── version-map.json
│   │   ├── repo-from/
│   │   └── repo-to/
│   └── _skipped/
└── reference-docs/
```

## Safety

- **Read-only** against customer Salesforce orgs — never deploys, inserts, updates, or deletes
- **Whitelist-enforced** — only approved `sf` CLI subcommands can execute
- **LMA queries** scoped to `Account` and `sfLma__*` objects only
- **Customer org queries** limited to CloudSense configuration objects
- All sf CLI commands are logged for auditability

## Usage Telemetry

Built-in telemetry logs every tool call to a shared Google Sheet so the
team can see who's using what and how often. Telemetry is **on by default**
and requires no configuration from individual team members.

To opt out, add `CLOUDSENSE_TELEMETRY=off` to the `env` block in your MCP
server config:

```json
{
  "mcpServers": {
    "CloudSense Customer Compass": {
      "command": "uvx",
      "args": ["cloudsense-customer-compass"],
      "env": {
        "CLOUDSENSE_TELEMETRY": "off"
      }
    }
  }
}
```

### What Gets Logged

Each tool call sends: timestamp, OS username, hostname, server version,
tool name, sanitized arguments (sensitive fields like `password`, `token`,
`secret`, `key`, `working_directory` are redacted), duration, status
(success/error), and result size. Session start/end events are also logged.

## Troubleshooting

> **SF CLI not detected?** If the tool says it can't find the Salesforce CLI,
> try restarting Cursor. If that doesn't help, open a terminal and run
> `sf org login web --alias cs-lma`, then try again.

## Known Issues

See [docs/known-issues.md](docs/known-issues.md) for full details.

- **Concurrent tool calls crash the server** (KI-001) — Running tools from
  multiple tabs simultaneously can freeze and crash the MCP server. Use one
  tab at a time for LMA queries. Fix planned for a post-MVP release.
- **SF CLI not found on Windows** (KI-002) — Cursor may not inherit the
  system PATH on Windows, causing `sf` to not be found. v0.11.1 auto-detects
  common install locations. If that fails, login manually in your terminal
  and the tool will pick up the authorized org.

## Development

```bash
python3 -m pip install -e ".[dev]"

# Run server locally
python3 -m cloudsense_customer_compass.server

# Run tests
pytest

# Build & publish
python3 -m build
uv publish dist/*
```
