GrowthOS
by Astoriel
README.md
# GrowthOS
**Answer growth questions in plain English. No SQL required.**
## Project status
Experimental beta. Snapshot date: 2025-12-15. The strongest current evaluation path is weekly growth review, funnel diagnosis, and channel efficiency review. See [STATUS.md](STATUS.md) and [KNOWN_LIMITATIONS.md](KNOWN_LIMITATIONS.md).
GrowthOS is an open-source MCP analytics server that connects your AI assistant (Claude, Cursor, or any MCP-compatible client) directly to your marketing and product data. Ask questions about funnels, retention, CAC, churn, anomalies, channel performance, forecasts, Shapley attribution, and narrative summaries — and get structured, benchmark-referenced answers in seconds.
[](https://www.python.org)
[](LICENSE)
[](STATUS.md)
[](#tool-reference)
[](https://duckdb.org)
---
## Screenshots
| CAC & LTV by Channel | Funnel Analysis |
|---|---|
|  |  |
| Churn Segmentation | Weekly Growth Summary |
|---|---|
|  |  |
**REST API (Swagger UI)**

---
## What GrowthOS Does
```
Claude / Cursor / any MCP client
│
▼
┌──────────────────────────────┐
│ GrowthOS MCP Server │ GrowthOS sits between your AI assistant and your data
│ 49 tools · DuckDB · SQL │ It exposes **49 MCP tools** that your AI can call to run real analysis — funnel breakdowns, CAC/LTV calculations, cohort retention matrices,
│ Semantic layer · Benchmarks │ anomaly detection, SQL queries, and more — then formats results with benchmark comparisons so you get context,
└────────────┬─────────────────┘ not just numbers.
│
┌──────────────────────┐
│ Your data sources │
│ CSV · PostgreSQL │
│ Stripe · Meta Ads │
│ Google Ads · HubSpot│
│ Mixpanel · Amplitude│
└──────────────────────┘
```
---
## 5 Questions GrowthOS Answers Reliably
1. **"Why did CAC increase last week and is it sustainable?"**
Channel-level CAC, LTV, and ROAS with automated invest/cut/watch classification.
2. **"Where is our funnel breaking and what should we test first?"**
Step-by-step conversion rates with the biggest drop-off identified automatically.
3. **"How bad is our retention and how does it compare to benchmarks?"**
Cohort retention matrix vs. B2B SaaS medians with Good / Average / Poor rating.
4. **"Which users are at risk of churning and how do we bring them back?"**
Active / At-Risk / Churned segmentation using configurable inactivity thresholds.
5. **"What will our spend and signups look like in the next 30 days?"**
Linear regression and exponential smoothing forecasts with confidence bands.
---
## Who It's For
- **Growth teams** who want fast, repeatable answers without waiting for a data analyst
- **Founders and PMs** reviewing weekly metrics in Claude, Cursor, or any AI
- **Marketing ops** managing multi-channel attribution across Google, Meta, Stripe, HubSpot, Mixpanel, Amplitude, and CSV exports
## Who It's Not For
- Teams that need dashboards or BI charts (use Metabase, Looker, etc.)
- Real-time streaming data (GrowthOS reads CSV/DuckDB snapshots)
- Enterprise RBAC or multi-tenant data isolation
---
## Quick Start
### Install
```bash
pip install growth-os
```
### Claude Desktop
Add to `~/.claude/claude_desktop_config.json`:
```json
{
"mcpServers": {
"growth-os": {
"command": "uvx",
"args": ["growth-os"],
"env": {
"GROWTH_DATA_DIR": "/path/to/your/csv/folder"
}
}
}
}
```
### Cursor / Windsurf / any MCP client
```json
{
"mcpServers": {
"growth-os": {
"command": "uvx",
"args": ["growth-os"],
"env": {
"GROWTH_DATA_DIR": "./data"
}
}
}
}
```
### From source
```bash
git clone https://github.com/Astoriel/GrowthOS.git
cd GrowthOS
pip install -e ".[dev]"
python -m growth_os.server
```
---
## Demo Mode — No Data Required
Skip `GROWTH_DATA_DIR` entirely. GrowthOS auto-generates realistic sample marketing data on startup — useful for exploring all 49 tools before connecting real data. Every connector (HubSpot, Mixpanel, Amplitude, Stripe, Meta, Google Ads) also runs in **demo mode** with synthetic mock data when credentials are absent.
Try it immediately:
```bash
pip install growth-os
# In Claude: "Give me a weekly growth summary"
# GrowthOS responds with real analysis on auto-generated sample data
```
---
## Data Sources and Connectors
### CSV Mode
Point `GROWTH_DATA_DIR` at a folder containing CSV files. GrowthOS loads all CSVs as queryable DuckDB tables.
```bash
export GROWTH_DATA_DIR=/path/to/csv/folder
```
Recommended file names (auto-detected schema):
| File | Key Columns |
|---|---|
| `marketing_spend.csv` | `date`, `channel`, `spend`, `impressions`, `clicks` |
| `user_events.csv` | `user_id`, `event_type`, `event_date`, `utm_source` |
| `campaigns.csv` | `campaign_id`, `channel`, `name`, `start_date`, `spend` |
Column names are flexible — use `suggest_attribution_mappings` to auto-map aliases.
### PostgreSQL Mode
```bash
export POSTGRES_URL=postgresql://user:pass@host:5432/dbname
```
GrowthOS attaches PostgreSQL as a **read-only DuckDB extension**. All queries are read-only; write/DDL operations are blocked at the AST level.
### Stripe
```bash
export STRIPE_API_KEY=sk_live_...
```
Syncs invoices, subscriptions, charges, and events. Call `sync_stripe_billing` from your AI assistant.
### Meta Ads
```bash
export META_ACCESS_TOKEN=...
export META_AD_ACCOUNT_ID=act_...
export META_API_VERSION=v21.0 # optional, default v21.0
```
Syncs campaigns and daily ad insights. Call `sync_meta_ads`.
### Google Ads
```bash
export GOOGLE_ADS_DEVELOPER_TOKEN=...
export GOOGLE_ADS_CUSTOMER_ID=...
export GOOGLE_ADS_LOGIN_CUSTOMER_ID=... # manager account ID, if applicable
export GOOGLE_ADS_ACCESS_TOKEN=...
export GOOGLE_ADS_REFRESH_TOKEN=...
export GOOGLE_ADS_CLIENT_ID=...
export GOOGLE_ADS_CLIENT_SECRET=...
export GOOGLE_ADS_API_VERSION=v19 # optional, default v19
```
Syncs campaigns and click performance. Call `sync_google_ads`.
### HubSpot
Uses a **Private App access token** (not an API key). Create a Private App in HubSpot Settings → Integrations → Private Apps, and grant these scopes:
- `crm.objects.contacts.read`
- `crm.objects.deals.read`
```bash
export HUBSPOT_ACCESS_TOKEN=pat-eu1-... # Private App token
export HUBSPOT_BASE_URL=https://api.hubapi.com # optional
```
Call `sync_hubspot` to pull contacts and deals. Falls back to **demo mode** (100–200 mock rows) when `HUBSPOT_ACCESS_TOKEN` is unset.
### Mixpanel
Uses the **API Secret** from Project Settings (not the project token).
```bash
export MIXPANEL_API_SECRET=... # Project API Secret
export MIXPANEL_PROJECT_ID=... # Project numeric ID (optional)
export MIXPANEL_EU=true # true = EU data residency (default)
```
Call `sync_mixpanel` to pull event streams and funnel data. Funnel data falls back to mock if the account is on the free plan (HTTP 402). Falls back to **demo mode** (up to 500 mock events + 3 funnel templates) when `MIXPANEL_API_SECRET` is unset.
### Amplitude
Requires both the **API Key** and **Secret Key** from the Amplitude project settings (under General → API Keys). Note: the JavaScript SDK snippet key is a different key and will not work here.
```bash
export AMPLITUDE_API_KEY=... # From Project Settings → API Keys
export AMPLITUDE_SECRET_KEY=... # Secret key (required alongside API key)
export AMPLITUDE_EU=true # true = EU data residency (default)
```
Call `sync_amplitude` to pull events and user cohorts. Falls back to **demo mode** (500 mock events + 8 mock cohorts) when either key is missing.
---
## REST API Server
Run GrowthOS as a standalone HTTP API alongside the MCP server:
```bash
pip install "growth-os[api]"
growth-os-api
```
The API server starts at `http://localhost:8000`. Swagger docs at `http://localhost:8000/docs`.
| Method | Path | Description |
|---|---|---|
| `GET` | `/health` | Server health, loaded tables, timestamp |
| `POST` | `/query` | Execute a read-only SQL query |
| `GET` | `/tables` | List all loaded tables |
| `GET` | `/tables/{name}` | Schema and stats for a specific table |
| `GET` | `/analysis/funnel` | Funnel conversion rates |
| `GET` | `/analysis/cac-ltv` | CAC / LTV / ROAS by channel |
| `GET` | `/analysis/churn` | User churn segmentation |
| `GET` | `/analysis/anomalies` | Anomaly detection in any metric |
| `GET` | `/reports/growth-summary` | Weekly growth KPI summary |
---
## Sample Prompts
> All prompts work in demo mode or with real data.
**Weekly review:**
> "Give me a weekly growth summary comparing this week to last week."
**Funnel diagnosis:**
> "Analyze the signup → activation → purchase funnel and tell me where we're losing users."
**CAC/LTV:**
> "What's our CAC and LTV by channel? Which channels should we scale up?"
**Retention check:**
> "How is our month-1 retention trending and how does it compare to SaaS benchmarks?"
**Churn investigation:**
> "How many users churned last month and how many are at risk right now?"
**Anomaly investigation:**
> "Something looks off in our spend last Tuesday. Detect any anomalies in marketing_spend."
**Shapley attribution:**
> "Compute Shapley-value attribution across all channels for the last 90 days."
**Forecasting:**
> "Forecast our daily signups for the next 30 days using linear trend and exponential smoothing."
**Narrative review:**
> "Write a plain-English growth narrative with headline findings and a recommendation."
**Data drift alert:**
> "Alert me via webhook if spend drifts more than 15% compared to last week."
**HubSpot contacts:**
> "Sync our HubSpot contacts and show a breakdown by lifecycle stage."
**Profile setup:**
> "Save my current setup as a profile called 'production' for next session."
---
## Tool Reference
All 49 registered MCP tools:
### Discovery
| Tool | Description |
|---|---|
| `health_check` | Server status, loaded tables, DuckDB version, timestamp |
| `list_tables` | List all available data tables |
| `describe_table` | Schema, sample rows, and column statistics for any table |
| `run_query` | Execute a read-only SQL query (DuckDB dialect); supports `offset`/`limit` pagination |
### Analysis
| Tool | Description |
|---|---|
| `analyze_funnel` | Step-by-step funnel conversion rates |
| `compute_cac_ltv` | CAC, LTV, and ROAS by channel with benchmark comparison |
| `cohort_retention` | Cohort retention matrix (weekly or monthly) vs. B2B SaaS medians |
| `channel_attribution` | Attributed revenue and ROAS per channel |
| `analyze_churn` | User segmentation: Active / At-Risk / Churned |
| `detect_anomalies` | Spike/drop detection in any metric time series |
### Workflow Tools (Combined Multi-Step Analysis)
| Tool | Description |
|---|---|
| `funnel_diagnosis` | Funnel + churn in one response with prioritized next-step recommendations |
| `channel_efficiency_review` | CAC + LTV + ROAS with automated invest / cut / watch classification |
| `anomaly_explanation` | Anomalies + likely cause hypotheses + investigation actions |
| `detect_data_drift` | Compare current vs. previous period; flags shifts >20% |
| `funnel_ab_comparison` | Side-by-side funnel conversion for two time periods with Δ (pp) column |
| `drift_alert` | Detect metric drift and optionally fire a webhook notification |
| `scheduled_report_preview` | Preview weekly growth report and optionally deliver it via webhook |
### Forecasting
| Tool | Description |
|---|---|
| `forecast_metric` | Forecast any metric column using linear regression or exponential smoothing, with confidence bands |
| `forecast_growth_kpis` | Forecast spend and daily active users for the next N days |
### Reports
| Tool | Description |
|---|---|
| `growth_summary` | Weekly growth KPI summary with period-over-period comparison |
| `weekly_growth_review` | Full weekly growth review workflow |
| `executive_summary` | Board-level executive summary |
| `paid_growth_review` | Paid spend vs. Stripe revenue comparison |
| `campaign_performance_review` | Campaign ranking by spend, efficiency, and risk |
| `attribution_bridge_review` | Campaign-to-revenue attribution bridge |
| `narrative_growth_review` | Plain-English prose narrative with headline, findings, and recommendation |
### Data Quality
| Tool | Description |
|---|---|
| `validate_data` | Validate tables against GrowthOS schema contracts |
| `inspect_freshness` | Check data freshness across all loaded tables |
| `list_connectors` | List configured connectors and their readiness status |
### Attribution Mapping
| Tool | Description |
|---|---|
| `attribution_mapping_diagnostics` | Coverage gaps, unmapped keys, alias rule usage |
| `suggest_attribution_mappings` | Auto-suggest high-confidence alias rules from your data |
| `attribution_mapping_review_pack` | Read-only review: coverage deltas, risk flags, audit trail |
| `preview_apply_attribution_mappings` | Preview coverage lift before applying any changes |
| `apply_suggested_attribution_mappings` | Apply approved aliases (high-risk rules blocked unless `force=true`) |
| `review_attribution_mappings` | Inspect active rules and full audit history |
| `rollback_attribution_mappings` | Undo specific alias changes by ID |
### Integrations
| Tool | Description |
|---|---|
| `sync_stripe_billing` | Sync Stripe invoices, subscriptions, and events to local CSV |
| `stripe_revenue_summary` | Revenue summary from synced Stripe data |
| `sync_meta_ads` | Sync Meta Ads campaigns and daily insights |
| `meta_ads_summary` | Spend, clicks, impressions from synced Meta data |
| `sync_google_ads` | Sync Google Ads campaigns and click performance |
| `google_ads_summary` | Spend, clicks, conversions from synced Google Ads data |
| `sync_hubspot` | Sync HubSpot contacts and deals (demo mode when no token) |
| `hubspot_contacts_summary` | Contacts breakdown by lifecycle stage |
| `sync_mixpanel` | Sync Mixpanel events and funnels (demo mode when no secret) |
| `sync_amplitude` | Sync Amplitude events and user cohorts (demo mode when no keys) |
### Workspace Profiles
| Tool | Description |
|---|---|
| `save_workspace_profile` | Save named configuration (data dir, Postgres URL, custom metrics) |
| `load_workspace_profile` | Load and apply a saved profile |
| `list_workspace_profiles` | List all saved profiles |
---
## Workspace Profiles and Custom Metrics
Save any combination of data directory, Postgres URL, and business mode as a named profile:
```
> "Save my current setup as a profile called 'production'."
> "Load the 'production' profile."
```
Profiles support **custom metric definitions** — define SQL-based KPIs with benchmark thresholds and units that GrowthOS evaluates alongside built-in metrics:
```
> "Add a custom metric: 'avg_order_value' = revenue / orders, benchmark 45, unit USD."
```
---
## Architecture
```
src/growth_os/
├── app/
│ ├── server.py # FastMCP server factory
│ ├── registry.py # 49 MCP tool registrations
│ └── lifespan.py # Startup sample data provisioning
├── api/
│ └── server.py # FastAPI REST API (optional)
├── config/
│ ├── settings.py # Pydantic-settings env config
│ └── profiles.py # Workspace profiles + custom metrics
├── connectors/
│ ├── duckdb.py # DuckDB engine + query cache
│ ├── csv.py # CSV ingestion
│ ├── postgres.py # PostgreSQL attach (read-only)
│ ├── stripe.py # Stripe Billing API
│ ├── meta_ads.py # Meta Marketing API
│ ├── google_ads.py # Google Ads API
│ ├── hubspot.py # HubSpot CRM v3 (contacts + deals)
│ ├── mixpanel.py # Mixpanel Export + Funnels API
│ ├── amplitude.py # Amplitude Export + Cohorts API
│ └── webhook.py # Outbound webhook dispatcher
├── domain/
│ ├── models.py # ToolEnvelope, shared models
│ ├── exceptions.py # ConnectorError, QueryError
│ ├── enums.py # FreshnessStatus, Severity, ChurnMode
│ └── contracts.py # Schema contracts for validation
├── ingestion/
│ ├── catalog.py # Table catalog
│ ├── freshness.py # Freshness detection
│ ├── validators.py # Data quality validators
│ ├── mapping.py # Attribution mapping engine
│ └── loaders.py # Data loading orchestration
├── observability/
│ ├── logging.py # Structured JSON logging
│ ├── tracing.py # @trace decorator
│ └── audit.py # Append-only audit log
├── presentation/
│ └── markdown.py # ToolEnvelope formatter + narrative builder
├── query/
│ ├── safety.py # AST-based SQL validator (sqlglot)
│ └── builder.py # Query builder
├── semantic/
│ ├── metrics.py # CAC, LTV, churn (3 modes), ROAS
│ ├── benchmarks.py # B2B SaaS benchmark data
│ ├── funnels.py # Funnel step definitions
│ ├── retention.py # Retention cohort logic
│ ├── attribution.py # UTM attribution + Shapley values
│ └── forecasting.py # Linear OLS + exponential smoothing
├── services/
│ ├── analysis_service.py
│ ├── catalog_service.py
│ ├── diagnostics_service.py
│ ├── reporting_service.py
│ ├── integration_service.py
│ ├── notification_service.py
│ └── forecasting_service.py
├── demo/
│ ├── sample_generator.py # Synthetic marketing data
│ └── scenarios.py # 4 curated demo scenarios
└── tools/
├── discovery/ # health_check, list_tables, describe_table, run_query
├── analysis/ # funnel, cac_ltv, retention, churn, anomalies
├── reports/ # growth_summary, executive, narrative, forecasting
└── admin/ # profiles, connectors, attribution mapping
```
**Key design decisions:**
- **Read-only enforcement** — All SQL is validated by an AST parser (sqlglot) before execution. Any write, DDL, multi-statement, or PRAGMA operation is rejected.
- **Demo-first** — Every connector and every analysis runs on synthetic data with no configuration. Real credentials are optional.
- **Benchmark context** — Metrics are always compared to B2B SaaS median benchmarks (A16Z, OpenView) so raw numbers come with meaning.
- **Structured output** — All tools return `ToolEnvelope` objects rendered as clean markdown tables, not raw JSON blobs.
---
## Test Suite
219 tests across 14 test files, covering unit tests, integration tests, and smoke tests.
```bash
pytest tests/ -q --tb=short
# 219 passed in ~8s
```
### Test files
| File | What it covers |
|---|---|
| `test_app_smoke.py` | Server creation, tool registration, FastMCP integration |
| `test_connector.py` | HubSpot, Mixpanel, Amplitude — demo mode, real API mock, error paths |
| `test_demo_runtime.py` | Full demo scenario execution end-to-end |
| `test_formatters.py` | ToolEnvelope markdown rendering, narrative formatting, business mode |
| `test_google_ads_connector.py` | Google Ads mock API, pagination, error handling |
| `test_guardrails.py` | Attribution guardrails: high-risk rule blocking, force override |
| `test_ingestion.py` | CSV loading, freshness detection, schema validation, mapping engine |
| `test_meta_ads_connector.py` | Meta Ads API mock, rate limits, data normalization |
| `test_metrics.py` | CAC/LTV/ROAS computation, churn modes, Shapley attribution |
| `test_profiles.py` | Save/load/list/delete profiles, custom metric definitions |
| `test_schema.py` | Schema contracts, data validation, column type inference |
| `test_sql_safety.py` | SQL AST validator — 40+ blocked patterns, allowed queries |
| `test_stripe_connector.py` | Stripe invoice/subscription sync, pagination, normalization |
| `test_workflow_tools.py` | funnel_diagnosis, channel_efficiency_review, anomaly_explanation |
### Real API connectivity tests
Connectors were tested against live APIs in development. Results:
| Connector | Auth | Data | Notes |
|---|---|---|---|
| **HubSpot** (`pat-eu1-...`) | ✅ Token accepted | Requires CRM scopes | Add `crm.objects.contacts.read` + `crm.objects.deals.read` to Private App |
| **Mixpanel** | ✅ Auth confirmed | 0 events (empty project) | Funnels fallback to mock on free plan (HTTP 402) |
| **Amplitude** | ✅ Auth confirmed | 6 real cohorts fetched | Export 404 = no events tracked yet |
| **Stripe** | ✅ (mock) | Full invoice/subscription sync | Tested against Stripe test mode |
| **Meta Ads** | ✅ (mock) | Campaign + insights sync | Tested against Graph API mock |
| **Google Ads** | ✅ (mock) | Campaign + click sync | Full OAuth flow tested |
---
## Configuration Reference
All settings are environment variables (case-insensitive):
### Core
| Variable | Default | Description |
|---|---|---|
| `GROWTH_DATA_DIR` | _(none)_ | Path to folder with CSV files |
| `POSTGRES_URL` | _(none)_ | PostgreSQL connection URL (read-only) |
| `DB_PATH` | _(in-memory)_ | DuckDB file path (set to persist between runs) |
| `SERVER_NAME` | `growth-os` | MCP server display name |
| `MAX_QUERY_ROWS` | `10000` | Maximum rows returned per query |
| `QUERY_TIMEOUT_SECONDS` | `30` | Query execution timeout |
| `DEFAULT_TRANSPORT` | `stdio` | MCP transport: `stdio` or `sse` |
| `BUSINESS_MODE` | `false` | Enable business-friendly output mode |
| `SEMANTIC_PROFILE_PATH` | _(none)_ | Path to semantic profile JSON |
### Stripe
| Variable | Default | Description |
|---|---|---|
| `STRIPE_API_KEY` | _(none)_ | Stripe secret key (`sk_live_...` or `sk_test_...`) |
| `STRIPE_BASE_URL` | `https://api.stripe.com/v1` | Override for testing |
### Meta Ads
| Variable | Default | Description |
|---|---|---|
| `META_ACCESS_TOKEN` | _(none)_ | User access token |
| `META_AD_ACCOUNT_ID` | _(none)_ | Ad account ID (`act_...`) |
| `META_API_VERSION` | `v21.0` | Graph API version |
| `META_BASE_URL` | `https://graph.facebook.com` | Override for testing |
### Google Ads
| Variable | Default | Description |
|---|---|---|
| `GOOGLE_ADS_DEVELOPER_TOKEN` | _(none)_ | Developer token |
| `GOOGLE_ADS_CUSTOMER_ID` | _(none)_ | Customer (CID) without dashes |
| `GOOGLE_ADS_LOGIN_CUSTOMER_ID` | _(none)_ | Manager account CID (if applicable) |
| `GOOGLE_ADS_ACCESS_TOKEN` | _(none)_ | OAuth access token |
| `GOOGLE_ADS_REFRESH_TOKEN` | _(none)_ | OAuth refresh token |
| `GOOGLE_ADS_CLIENT_ID` | _(none)_ | OAuth client ID |
| `GOOGLE_ADS_CLIENT_SECRET` | _(none)_ | OAuth client secret |
| `GOOGLE_ADS_API_VERSION` | `v19` | Ads API version |
### HubSpot
| Variable | Default | Description |
|---|---|---|
| `HUBSPOT_ACCESS_TOKEN` | _(none)_ | Private App token (`pat-eu1-...`). Omit = demo mode |
| `HUBSPOT_BASE_URL` | `https://api.hubapi.com` | Override for testing |
### Mixpanel
| Variable | Default | Description |
|---|---|---|
| `MIXPANEL_API_SECRET` | _(none)_ | Project API Secret. Omit = demo mode |
| `MIXPANEL_PROJECT_ID` | _(none)_ | Project numeric ID (optional) |
| `MIXPANEL_EU` | `true` | Use EU data residency endpoints |
### Amplitude
| Variable | Default | Description |
|---|---|---|
| `AMPLITUDE_API_KEY` | _(none)_ | Project API key. **Both keys required** for live mode |
| `AMPLITUDE_SECRET_KEY` | _(none)_ | Project Secret key |
| `AMPLITUDE_EU` | `true` | Use EU data residency endpoints |
---
## Docker
```bash
# Build
docker build -t growth-os .
# Demo mode (no credentials)
docker run -p 8000:8000 growth-os
# With CSV data
docker run -e GROWTH_DATA_DIR=/data -v /local/csv:/data growth-os
# With PostgreSQL
docker run -e POSTGRES_URL=postgresql://user:pass@host:5432/db growth-os
# With Stripe and HubSpot
docker run \
-e STRIPE_API_KEY=sk_live_... \
-e HUBSPOT_ACCESS_TOKEN=pat-eu1-... \
growth-os
```
---
## Limitations
- **Read-only enforcement.** GrowthOS enforces an AST-based SQL sandbox (sqlglot) that blocks any write, DDL, or multi-statement operation. You cannot accidentally modify data.
- **Attribution is approximate.** UTM-based attribution has known gaps: direct traffic, cross-device, and offline conversions are not captured.
- **Forecasts are statistical, not causal.** Linear and exponential smoothing forecasts extrapolate historical trends — they do not account for seasonality, planned campaigns, or market shocks. Use for directional guidance only.
- **Benchmarks are medians.** Industry benchmarks (B2B SaaS, A16Z, OpenView) reflect median-performing companies. Valid reasons to be above or below exist for every metric.
- **Data freshness matters.** Stale CSVs produce stale answers. Always run `inspect_freshness` before drawing conclusions from time-sensitive analyses.
- **Connector demo mode produces synthetic data.** Mock rows use fixed random seeds so output is deterministic and will not match your actual business metrics.
- **HubSpot scope requirement.** The Private App must have `crm.objects.contacts.read` and `crm.objects.deals.read` scopes. Without these scopes the connector returns HTTP 403 even with a valid token.
- **Mixpanel free plan.** The Funnels API returns HTTP 402 on free-tier projects. GrowthOS automatically falls back to synthetic funnel data in this case.
- **Amplitude key types.** Only the server-side API Key + Secret Key pair works for the Export API. The JavaScript SDK snippet key will not authenticate.
---
## Development
```bash
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest tests/ -q --tb=short
# Lint
python -m ruff check src/ tests/
# Verify server starts cleanly
python -c "from growth_os.app.server import create_mcp_server; create_mcp_server()"
```
### Running the REST API in development
```bash
pip install -e ".[api]"
growth-os-api
# Swagger: http://localhost:8000/docs
```
---
## Docs
- [Product Roadmap](docs/PRODUCT_ROADMAP.md)
- [Target Architecture](docs/TARGET_ARCHITECTURE.md)
- [Implementation TODO](docs/IMPLEMENTATION_TODO.md)
---
## License
MIT — see [LICENSE](LICENSE).
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues