Spaces:
Running
Running
deploy(mcp): MCP-server README (docker frontmatter) over updated trunk
Browse filesTrunk now includes the table-import performance fix (scoped TS connection +
monthly-rotating demo database): table creates drop from ~250s/call to <1s,
so MCP builds shed ~8-10 minutes. Only README differs from develop_dg.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
README.md
CHANGED
|
@@ -1,175 +1,41 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
colorFrom: blue
|
| 5 |
-
colorTo:
|
| 6 |
-
sdk:
|
| 7 |
-
|
| 8 |
-
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
license: mit
|
| 11 |
-
python_version: "3.11"
|
| 12 |
---
|
| 13 |
|
| 14 |
-
# DemoPrep
|
| 15 |
|
| 16 |
-
|
|
|
|
|
|
|
|
|
|
| 17 |
|
| 18 |
-
|
|
|
|
|
|
|
| 19 |
|
| 20 |
-
|
|
|
|
|
|
|
|
|
|
| 21 |
|
| 22 |
-
|
| 23 |
|
| 24 |
-
|
| 25 |
|
| 26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
-
|
| 29 |
-
- **Single blueprint pipeline** — one path, no keyword routing or fallback: research → LLM-authored `DemoBlueprint` → deterministic engine → validation → derived DDL → load
|
| 30 |
-
- **Realistic data** — bounded/related measures (a part never exceeds its whole, rates stay ≤ 1, prices are stable per entity) plus planted, discoverable "Demo to Win" insights the validator proves are visible
|
| 31 |
-
- **ThoughtSpot integration** — deploys the connection, tables, semantic model, and an enhanced liveboard
|
| 32 |
-
- **Interactive UI** — tabbed Gradio app with real-time progress
|
| 33 |
-
|
| 34 |
-
## 🛠️ Tech Stack
|
| 35 |
-
|
| 36 |
-
- **Frontend**: Gradio (Python web UI)
|
| 37 |
-
- **Backend**: Python 3.11
|
| 38 |
-
- **Database**: Snowflake (keypair auth)
|
| 39 |
-
- **Analytics**: ThoughtSpot (per-environment trusted auth)
|
| 40 |
-
- **AI**: multiple LLM providers (OpenAI and Anthropic/Claude), routed via `llm_config.py`
|
| 41 |
-
- **Settings**: Supabase (admin + per-user settings)
|
| 42 |
-
|
| 43 |
-
## 📋 Prerequisites
|
| 44 |
-
|
| 45 |
-
- Python 3.11
|
| 46 |
-
- Snowflake account (keypair configured)
|
| 47 |
-
- ThoughtSpot Cloud account
|
| 48 |
-
- An LLM API key (OpenAI and/or Anthropic)
|
| 49 |
-
- Supabase project (settings storage)
|
| 50 |
-
|
| 51 |
-
## 🚀 Quick Start
|
| 52 |
-
|
| 53 |
-
1. **Clone the repository**
|
| 54 |
-
```bash
|
| 55 |
-
git clone <repo-url>
|
| 56 |
-
cd demoprep
|
| 57 |
-
```
|
| 58 |
-
|
| 59 |
-
2. **Set up a virtual environment**
|
| 60 |
-
```bash
|
| 61 |
-
python -m venv .venv
|
| 62 |
-
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
| 63 |
-
```
|
| 64 |
-
|
| 65 |
-
3. **Install dependencies**
|
| 66 |
-
```bash
|
| 67 |
-
pip install -r requirements.txt
|
| 68 |
-
```
|
| 69 |
-
|
| 70 |
-
4. **Configure bootstrap environment variables** (see Configuration)
|
| 71 |
-
```bash
|
| 72 |
-
cp .env.example .env
|
| 73 |
-
# edit .env
|
| 74 |
-
```
|
| 75 |
-
|
| 76 |
-
5. **Run the application**
|
| 77 |
-
```bash
|
| 78 |
-
python app.py
|
| 79 |
-
```
|
| 80 |
-
`app.py` launches the full Gradio app defined in `chat_interface.py`.
|
| 81 |
-
|
| 82 |
-
6. **Open your browser**
|
| 83 |
-
Navigate to `http://localhost:7860` and use the **App** tab.
|
| 84 |
-
|
| 85 |
-
## ⚙️ Configuration
|
| 86 |
-
|
| 87 |
-
`.env` holds only the **bootstrap** secrets needed to start the app and reach Supabase and the LLM providers. All other credentials — the Snowflake keypair and the ThoughtSpot **per-environment trusted-auth keys** — live in **Supabase admin settings** and are loaded at runtime.
|
| 88 |
-
|
| 89 |
-
```env
|
| 90 |
-
# Supabase (settings storage)
|
| 91 |
-
SUPABASE_URL=...
|
| 92 |
-
SUPABASE_ANON_KEY=...
|
| 93 |
-
|
| 94 |
-
# LLM providers
|
| 95 |
-
OPENAI_API_KEY=...
|
| 96 |
-
GOOGLE_API_KEY=... # optional (Gemini)
|
| 97 |
-
|
| 98 |
-
# Slack deployment notifications (optional, outbound-only)
|
| 99 |
-
SLACK_BOT_TOKEN=xoxb-...
|
| 100 |
-
SLACK_DEPLOYMENT_CHANNEL_ID=C0123456789
|
| 101 |
-
```
|
| 102 |
-
|
| 103 |
-
Slack notifications use the Slack Web API to post deployment status into one approved channel. This path is outbound-only: no Socket Mode, event subscriptions, slash commands, or public request URL. The Slack app needs only the `chat:write` bot scope and must be invited to the target channel.
|
| 104 |
-
|
| 105 |
-
## 🎯 Usage
|
| 106 |
-
|
| 107 |
-
The **App tab** is the primary interface — fill the form, press **GO**, and the pipeline runs end to end:
|
| 108 |
-
|
| 109 |
-
1. **Fill the form** — vertical / line of business / function (or a custom use case), the company URL, and the target **ThoughtSpot environment**
|
| 110 |
-
2. **Press GO** — research → blueprint → data generation → validation → Snowflake load → ThoughtSpot model + liveboard
|
| 111 |
-
3. **Review** — model and liveboard links, a Demo Pack, and a Spotter Viz story appear on completion
|
| 112 |
-
|
| 113 |
-
## 📁 Project Structure
|
| 114 |
-
|
| 115 |
-
```
|
| 116 |
-
demoprep/
|
| 117 |
-
├── app.py # Entry point — launches the Gradio app on :7860
|
| 118 |
-
├── chat_interface.py # The full Gradio app (App/Chat/Admin/Settings/…) — historical name
|
| 119 |
-
├── thoughtspot_deployer.py # ThoughtSpot deploy: connection, tables, model, liveboard
|
| 120 |
-
├── liveboard_creator.py # MCP liveboard creation + TML post-processing (enhance_mcp_liveboard)
|
| 121 |
-
├── snowflake_auth.py # Snowflake keypair authentication
|
| 122 |
-
├── llm_config.py # LLM provider/model routing (single source of truth)
|
| 123 |
-
├── demo_personas.py # Vertical × Function use-case configs
|
| 124 |
-
├── demoprep_app/ # The demo-generation pipeline package
|
| 125 |
-
│ ├── pipeline/build_demo.py # the single build entry point
|
| 126 |
-
│ ├── scenario/ # blueprint contract + LLM authoring + directives
|
| 127 |
-
│ ├── dataset/ # deterministic engine + validator
|
| 128 |
-
│ ├── ddl/ # Snowflake DDL derived from the dataset
|
| 129 |
-
│ └── integrations/snowflake/ # Snowflake row loader
|
| 130 |
-
├── requirements.txt # Python dependencies
|
| 131 |
-
├── docs/ # Documentation
|
| 132 |
-
├── tests/ # Unit tests + the e2e quality harness (e2e_quality.py)
|
| 133 |
-
└── results/ # Generated demo results
|
| 134 |
-
```
|
| 135 |
-
|
| 136 |
-
## 🧪 Testing
|
| 137 |
-
|
| 138 |
-
```bash
|
| 139 |
-
# Unit tests (pytest collects test_*.py)
|
| 140 |
-
python -m pytest tests/
|
| 141 |
-
|
| 142 |
-
# End-to-end quality harness — drives a running app via the browser and grades the output
|
| 143 |
-
python tests/e2e_quality.py --env-name test
|
| 144 |
-
```
|
| 145 |
-
|
| 146 |
-
## 🤝 Contributing
|
| 147 |
-
|
| 148 |
-
1. Fork the repository
|
| 149 |
-
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
| 150 |
-
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
| 151 |
-
4. Push to the branch (`git push origin feature/amazing-feature`)
|
| 152 |
-
5. Open a Pull Request
|
| 153 |
-
|
| 154 |
-
## 📄 License
|
| 155 |
-
|
| 156 |
-
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
| 157 |
-
|
| 158 |
-
## 🙏 Acknowledgments
|
| 159 |
-
|
| 160 |
-
- ThoughtSpot for the analytics platform
|
| 161 |
-
- Snowflake for the data warehouse
|
| 162 |
-
- OpenAI and Anthropic for the AI capabilities
|
| 163 |
-
- Gradio for the web interface
|
| 164 |
-
|
| 165 |
-
## 📚 Development Notes
|
| 166 |
-
|
| 167 |
-
Sprint planning and working notes live in `dev_notes/` (gitignored); architecture and handoff docs are in `docs/`.
|
| 168 |
-
|
| 169 |
-
## 📞 Support
|
| 170 |
-
|
| 171 |
-
For support, create an issue in this repository.
|
| 172 |
-
|
| 173 |
-
---
|
| 174 |
-
|
| 175 |
-
**Built with ❤️ for the ThoughtSpot community**
|
|
|
|
| 1 |
---
|
| 2 |
+
title: DemoPrep MCP
|
| 3 |
+
emoji: 🔌
|
| 4 |
colorFrom: blue
|
| 5 |
+
colorTo: green
|
| 6 |
+
sdk: docker
|
| 7 |
+
app_port: 7860
|
|
|
|
| 8 |
pinned: false
|
| 9 |
license: mit
|
|
|
|
| 10 |
---
|
| 11 |
|
| 12 |
+
# DemoPrep MCP Server
|
| 13 |
|
| 14 |
+
An MCP (Model Context Protocol) server that exposes DemoPrep's demo-build pipeline
|
| 15 |
+
as tools an external agent (ThoughtSpot **AgentSpot**) can call — building a full
|
| 16 |
+
demo (Snowflake schema → ThoughtSpot model → liveboard) from a prospect **brief**,
|
| 17 |
+
with no human clicking through the Gradio UI.
|
| 18 |
|
| 19 |
+
- **Transport:** streamable-HTTP at `/mcp`, gated by `Authorization: Bearer <MCP_ACCESS_TOKEN>`.
|
| 20 |
+
- **Health:** unauthenticated `GET /` returns `{"status":"ok"}`.
|
| 21 |
+
- **Tools:** `ping` (connectivity check) and `build_demo_from_brief` (full build).
|
| 22 |
|
| 23 |
+
This Space shares the DemoPrep codebase with the app Space but runs the MCP
|
| 24 |
+
entrypoint (`mcp_server.py`) instead of the Gradio app — the business logic lives
|
| 25 |
+
in one place (`demoprep_app/` + the controller). Builds run for minutes, so the
|
| 26 |
+
tool is meant to be driven job-style (fire, then check back).
|
| 27 |
|
| 28 |
+
## Required secrets
|
| 29 |
|
| 30 |
+
Set these in **Settings → Repository Secrets** (nothing sensitive is committed):
|
| 31 |
|
| 32 |
+
| Secret | Purpose |
|
| 33 |
+
|--------|---------|
|
| 34 |
+
| `SUPABASE_URL`, `SUPABASE_ANON_KEY` | bootstrap → pulls Snowflake + LLM keys from admin settings |
|
| 35 |
+
| `OPENAI_API_KEY` | LLM key (env-only) |
|
| 36 |
+
| `TS_ENV_1_LABEL`, `TS_ENV_1_URL`, `TS_ENV_1_KEY_VAR` | the target ThoughtSpot environment |
|
| 37 |
+
| `MCP_OWNER_EMAIL` | TS user that owns created objects (trusted-auth) |
|
| 38 |
+
| `MCP_TS_ENV_LABEL` | which TS env label to deploy into |
|
| 39 |
+
| `MCP_ACCESS_TOKEN` | shared bearer secret the calling agent presents |
|
| 40 |
|
| 41 |
+
`MCP_TRANSPORT=http` and `MCP_HTTP_PORT=7860` are baked into the Dockerfile.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|