| --- |
| title: Customer Segmentation MCP Server |
| emoji: π |
| colorFrom: blue |
| colorTo: green |
| sdk: docker |
| app_port: 7860 |
| pinned: false |
| short_description: SEP-2200 demo β structuredContent vs content |
| --- |
| |
| # Customer Segmentation MCP Server (SEP-2200 case study) |
|
|
| Remote MCP endpoint (Streamable HTTP): **`https://olaservo-mcp-customer-segmentation.hf.space/mcp`** |
|
|
| A demo MCP App that displays 250 customer records as an interactive |
| scatter/bubble chart with segment-based clustering. Copied from |
| [`modelcontextprotocol/ext-apps`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/customer-segmentation-server) |
| and deployed as a Hugging Face Docker Space. (Original README: `README.upstream.md`.) |
|
|
| ## Why it's here β the SEP-2200 lead anti-pattern |
|
|
| The single tool `get-customer-data` returns the **whole 250-record dataset twice**: |
|
|
| ```ts |
| return { |
| content: [{ type: "text", text: JSON.stringify(data) }], // -> goes to the model |
| structuredContent: data, // -> for the UI |
| }; |
| ``` |
|
|
| `content` is sent to the model (tokens + distraction). Dumping the entire |
| UI-bound dataset into `content` β *in addition to* `structuredContent` β is the |
| clearest example of the pattern SEP-2200 argues against. This Space hosts the |
| example **as-is** so the behavior can be inspected live. |
|
|
| ## Try it |
|
|
| MCP `initialize`, then `tools/list` should show `get-customer-data`; calling it |
| returns the customer dataset in both `content` and `structuredContent`. |
|
|
| ```bash |
| curl -s https://olaservo-mcp-customer-segmentation.hf.space/mcp \ |
| -H "Content-Type: application/json" \ |
| -H "Accept: application/json, text/event-stream" \ |
| -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}' |
| ``` |
|
|
| > Free CPU Spaces sleep when idle; the first request after a cold start is slow |
| > and a client may need to retry. |
|
|
| ## Build |
|
|
| Docker builds the server in-image (`node:22` + `bun`): `npm install` β |
| `npm run build` (vite single-file UI + bun-bundled `dist/index.js`) β |
| `node dist/index.js` listening on `0.0.0.0:7860` at `/mcp`. |
|
|