@unified-product-graph/cloud-server 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -0
- package/LICENSE +21 -0
- package/README.md +169 -0
- package/SELF-HOSTING.md +185 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +5094 -0
- package/dist/index.js.map +1 -0
- package/dist/tools-manifest.json +3432 -0
- package/docker/Dockerfile +14 -0
- package/docker/docker-compose.yml +33 -0
- package/migrations/001_initial.sql +70 -0
- package/migrations/002_collaboration.sql +41 -0
- package/migrations/003_webhooks.sql +14 -0
- package/migrations/004_cross_product_edges.sql +22 -0
- package/package.json +75 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@unified-product-graph/cloud-server` are documented in this file.
|
|
4
|
+
|
|
5
|
+
This package co-versions with `@unified-product-graph/core` and `@unified-product-graph/mcp-server`. One version line covers the spec and both reference implementations.
|
|
6
|
+
|
|
7
|
+
## 0.6.0 · 2026-05-22 · Launch train alignment
|
|
8
|
+
|
|
9
|
+
Aligned with `@unified-product-graph/core@0.6.0`. Bumped `@unified-product-graph/core` dep to `^0.6.0`. No cloud-server surface changes — co-versioned for the launch train.
|
|
10
|
+
|
|
11
|
+
## 0.5.0 · 2026-05-19 · Inaugural public release
|
|
12
|
+
|
|
13
|
+
First public npm release on the `@unified-product-graph/` scope. Co-versions with `@unified-product-graph/core@0.5.0` and `@unified-product-graph/mcp-server@0.5.0`.
|
|
14
|
+
|
|
15
|
+
### Highlights
|
|
16
|
+
|
|
17
|
+
- **91 tools across 14 domains.** Full tool-surface parity with the local `mcp-server` (79 shared) plus 12 cloud-only: collaboration, comments, webhooks, audit-log, cross-product-edge, and Postgres-side analytics.
|
|
18
|
+
- **Spec introspection.** Playbooks, approaches, domain guides, frameworks, edge catalog, regions, lenses, type labels, entity meta, anti-patterns, benchmarks, lifecycles, scales, and migrations catalogues are all queryable as MCP tools.
|
|
19
|
+
- **Approaches.** `plan`, `inspect`, `prioritise`, `trace`, `reflect` ship as definition-lookup handlers; structured execution lands in a follow-on release.
|
|
20
|
+
- **Cross-product edges.** `create_cross_product_edge`, `list_portfolio_cross_edges`, `migrate_cross_edges` for portfolio-level relationships.
|
|
21
|
+
- **Portfolio hierarchy.** `list_portfolios`, `create_area`, `get_area_context`.
|
|
22
|
+
- **Validation and migration.** `validate_graph`, `migrate_type`, `repair_dangling_edges`, `deduplicate_nodes`, `rename_edge_type`, `export_edges`.
|
|
23
|
+
- **Audit trail.** Every write carries actor and timestamp; replay supported via append-only edge tables.
|
|
24
|
+
- **Self-hostable.** Docker-ready, Postgres-backed; bring your own database.
|
|
25
|
+
- **Shared catalog.** Cloud and local both walk `@unified-product-graph/mcp-tooling` for `ToolDefinition`, `resolveEntityType`, `buildEntitySchema`, and atomicity contracts.
|
|
26
|
+
|
|
27
|
+
### Install
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install -g @unified-product-graph/cloud-server
|
|
31
|
+
upg-cloud-server --database-url postgres://user:pass@localhost/upg
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Wire it into your MCP client by pointing at the running server. Database migrations ship with the package; see [README.md](./README.md#database-setup).
|
|
35
|
+
|
|
36
|
+
### Pairs with
|
|
37
|
+
|
|
38
|
+
- `@unified-product-graph/core@0.5.0`
|
|
39
|
+
- `@unified-product-graph/mcp-server@0.5.0` (tool-surface parity)
|
|
40
|
+
- `@unified-product-graph/mcp-tooling@0.5.0` (shared catalog and atomicity contracts)
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 The Product Creator
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# @unified-product-graph/cloud-server
|
|
2
|
+
|
|
3
|
+
**91 MCP tools across 14 domains, backed by Postgres.** Self-hostable [Model Context Protocol](https://modelcontextprotocol.io) server for the [Unified Product Graph](https://unifiedproductgraph.org).
|
|
4
|
+
|
|
5
|
+
<!-- badges -->
|
|
6
|
+
<!-- [](https://www.npmjs.com/package/@unified-product-graph/cloud-server) -->
|
|
7
|
+
<!-- [](./LICENSE) -->
|
|
8
|
+
|
|
9
|
+
## What this is
|
|
10
|
+
|
|
11
|
+
The UPG Cloud Server stores your product graph in Postgres. It exposes graph operations (products, nodes, edges, search, traversal, collaboration, webhooks) as MCP tools that any compatible client (Claude Code, Cursor, etc.) can call.
|
|
12
|
+
|
|
13
|
+
**Pick this server when you need:**
|
|
14
|
+
|
|
15
|
+
- **Multi-tenant storage.** One durable store, many products scoped by `product_id`.
|
|
16
|
+
- **Collaboration.** Comments, role-based access (`owner` / `editor` / `viewer`), audit log.
|
|
17
|
+
- **Outbound webhooks.** Fire on node and edge mutations.
|
|
18
|
+
- **A database service** under your UPG stack.
|
|
19
|
+
|
|
20
|
+
For a single user on a single graph, prefer `@unified-product-graph/mcp-server` plus a `.upg` file: version-controlled, zero infrastructure. Cloud and local share one spec; graphs round-trip between them.
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
### Option 1: Docker (recommended)
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
cd docker
|
|
28
|
+
docker compose up -d
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
This starts Postgres on port `5433` and applies the migrations automatically. The MCP server then connects to it.
|
|
32
|
+
|
|
33
|
+
### Option 2: Connect to existing Postgres
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
UPG_DATABASE_URL=postgres://user:pass@localhost:5432/mydb npx @unified-product-graph/cloud-server
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Run the [migration](#database-setup) first.
|
|
40
|
+
|
|
41
|
+
### Option 3: MCP config (Claude Code / Cursor)
|
|
42
|
+
|
|
43
|
+
Add this to your `.claude/settings.json` or MCP client config:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"mcpServers": {
|
|
48
|
+
"upg-cloud": {
|
|
49
|
+
"command": "npx",
|
|
50
|
+
"args": ["@unified-product-graph/cloud-server", "--database-url", "postgres://upg:upg@localhost:5433/upg"]
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
> **Naming.** The config key (`"upg-cloud"`) determines the tool prefix your client sees (`mcp__upg-cloud__*`). The server reports itself to the MCP registry as `unified-product-graph-cloud`. Keep `"upg-cloud"` as the key to stay compatible with existing skill playbooks.
|
|
57
|
+
|
|
58
|
+
## MCP Tools
|
|
59
|
+
|
|
60
|
+
**91 tools across 14 domains.** Reference: [`TOOLS.md`](./TOOLS.md) (generated from JSDoc by `npm run generate-tools`). The high-level shape:
|
|
61
|
+
|
|
62
|
+
| Domain | What it covers |
|
|
63
|
+
| ------ | -------------- |
|
|
64
|
+
| Products & Audit | `list_products`, `create_product`, `get_audit_log` |
|
|
65
|
+
| Context & Traversal | `get_product_context`, `get_graph_digest`, `query`, `get_changes`, `trace` |
|
|
66
|
+
| Nodes | CRUD + `get_nodes`, `search_nodes`, `list_nodes`, `move_node`, batch primitives |
|
|
67
|
+
| Edges | `create_edge`, `delete_edge`, `export_edges`, `rename_edge_type`, batch primitives |
|
|
68
|
+
| Areas | `list_product_areas`, `get_area_graph`, `create_area`, `get_area_context` |
|
|
69
|
+
| Portfolios | `create_cross_product_edge`, `list_portfolios`, `list_portfolio_cross_edges`, `migrate_cross_edges` |
|
|
70
|
+
| Schema | `get_entity_schema` (catalog-driven, shared with local) |
|
|
71
|
+
| Validation & Migration | `validate_graph`, `migrate_type`, `repair_dangling_edges`, `deduplicate_nodes` |
|
|
72
|
+
| Collaboration | `add_comment`, `list_comments`, `grant_access`, `list_collaborators` |
|
|
73
|
+
| Analytics | `get_graph_analytics` (Postgres-side aggregator) |
|
|
74
|
+
| Webhooks | `register_webhook`, `list_webhooks`, `remove_webhook` |
|
|
75
|
+
| Spec introspection | playbooks, approaches, domains, frameworks, edge catalog, regions, lenses, type labels, entity meta, anti-patterns, benchmarks, lifecycles, scales |
|
|
76
|
+
| Approaches | `plan`, `inspect`, `prioritise`, `trace`, `reflect` |
|
|
77
|
+
| Migrations catalogue | `list_type_migrations`, `list_edge_migrations`, `list_split_migrations` |
|
|
78
|
+
|
|
79
|
+
### Parity with `@unified-product-graph/mcp-server`
|
|
80
|
+
|
|
81
|
+
Cloud has full tool-surface parity with `@unified-product-graph/mcp-server`. Both walk the same catalog, schema, and atomicity contracts via `@unified-product-graph/mcp-tooling`. Cloud adds collaboration, comments, webhooks, audit-log, cross-product-edge, and Postgres-side analytics on top.
|
|
82
|
+
|
|
83
|
+
## Database Setup
|
|
84
|
+
|
|
85
|
+
Docker (`docker compose up -d`) runs migrations automatically. To apply manually:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
psql $UPG_DATABASE_URL -f migrations/001_initial.sql
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
This creates a `upg` schema with:
|
|
92
|
+
|
|
93
|
+
- **`upg.products`**: products with title, description, stage
|
|
94
|
+
- **`upg.nodes`**: typed entities (features, personas, decisions, etc.) with full-text search
|
|
95
|
+
- **`upg.edges`**: typed relationships between nodes
|
|
96
|
+
- **`upg.comments`**: comments on nodes
|
|
97
|
+
- **`upg.audit_log`**: change history per product
|
|
98
|
+
- **`upg.collaborators`**: user roles (`owner` / `editor` / `viewer`) per product
|
|
99
|
+
- **`upg.webhooks`**: registered webhook endpoints
|
|
100
|
+
|
|
101
|
+
All tables include timestamps, cascading deletes, and performance indexes.
|
|
102
|
+
|
|
103
|
+
## Configuration
|
|
104
|
+
|
|
105
|
+
| Variable | Required | Default | Description |
|
|
106
|
+
|----------|----------|---------|-------------|
|
|
107
|
+
| `UPG_DATABASE_URL` | Yes | (none) | Postgres connection string. Can also be passed as `--database-url`. |
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Environment variable
|
|
111
|
+
UPG_DATABASE_URL=postgres://upg:upg@localhost:5433/upg npx @unified-product-graph/cloud-server
|
|
112
|
+
|
|
113
|
+
# CLI flag
|
|
114
|
+
npx @unified-product-graph/cloud-server --database-url postgres://upg:upg@localhost:5433/upg
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Auth model
|
|
118
|
+
|
|
119
|
+
The server is an **MCP stdio process**. It speaks MCP over stdin/stdout to a single trusted client (Claude Code, Cursor, etc.).
|
|
120
|
+
|
|
121
|
+
Multi-tenancy is **graph-shaped**:
|
|
122
|
+
|
|
123
|
+
- Tools take `product_id` and `user_id` arguments explicitly.
|
|
124
|
+
- `grant_access` / `list_collaborators` write to `upg.collaborators` for host-side role checks.
|
|
125
|
+
- Authorisation enforcement (does this `user_id` have `editor` on this `product_id`?) sits with the wrapping layer: a hosted gateway, an authenticated HTTP transport, or a per-tenant Postgres role.
|
|
126
|
+
|
|
127
|
+
For public self-hosting, front the server with an authenticating transport. The current contract: trusted client, graph-shaped multi-tenancy.
|
|
128
|
+
|
|
129
|
+
## Open protocol, optional commercial layer
|
|
130
|
+
|
|
131
|
+
UPG is an **open protocol** for representing products as structured graphs. This server is the open-source reference implementation. See [unifiedproductgraph.org](https://unifiedproductgraph.org) for the spec and ecosystem.
|
|
132
|
+
|
|
133
|
+
Commercial products may layer guided creation journeys, AI copilots, and visual canvases on top. Think Git versus hosted Git providers. The server works standalone with any MCP-compatible client.
|
|
134
|
+
|
|
135
|
+
## Versioning
|
|
136
|
+
|
|
137
|
+
`@unified-product-graph/cloud-server` co-versions with `@unified-product-graph/core` and `@unified-product-graph/mcp-server`. One version line covers spec and both reference implementations.
|
|
138
|
+
|
|
139
|
+
See [CHANGELOG.md](./CHANGELOG.md) for release history.
|
|
140
|
+
|
|
141
|
+
## Development
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# Install dependencies
|
|
145
|
+
npm install
|
|
146
|
+
|
|
147
|
+
# Run in development mode
|
|
148
|
+
npm run dev
|
|
149
|
+
|
|
150
|
+
# Build (also regenerates TOOLS.md from JSDoc)
|
|
151
|
+
npm run build
|
|
152
|
+
|
|
153
|
+
# Type-check
|
|
154
|
+
npm run type-check
|
|
155
|
+
|
|
156
|
+
# Tests
|
|
157
|
+
npm test
|
|
158
|
+
|
|
159
|
+
# Regenerate TOOLS.md only
|
|
160
|
+
npm run generate-tools
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Contributing
|
|
164
|
+
|
|
165
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for local-dev setup, the Docker compose flow, migration conventions, and where to file issues.
|
|
166
|
+
|
|
167
|
+
## License
|
|
168
|
+
|
|
169
|
+
MIT. See [LICENSE](./LICENSE).
|
package/SELF-HOSTING.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# Self-hosting the UPG Cloud Server
|
|
2
|
+
|
|
3
|
+
The cloud server is a **Postgres-backed MCP server**. Unlike the local server
|
|
4
|
+
(`@unified-product-graph/mcp-server`), which reads and writes a single `.upg`
|
|
5
|
+
file, the cloud server stores the graph in Postgres — so a team can share one
|
|
6
|
+
source of truth with concurrent, transactional writes, multiple products, an
|
|
7
|
+
audit log, comments, and webhooks.
|
|
8
|
+
|
|
9
|
+
> **Mental model:** the local server is to Git as the cloud server is to a
|
|
10
|
+
> shared database. Same tools, same UPG semantics — different substrate.
|
|
11
|
+
|
|
12
|
+
This guide covers three deployment tiers, from "ready today" to "real SaaS."
|
|
13
|
+
|
|
14
|
+
| Tier | What you host | Auth model | Effort | Use when |
|
|
15
|
+
|------|---------------|-----------|--------|----------|
|
|
16
|
+
| **1 — Shared DB** | Just Postgres; each client runs the server locally | Connection string = full access | Minutes | A small, trusting team |
|
|
17
|
+
| **2 — Central endpoint** | The server behind a stdio→HTTP bridge + auth proxy | One shared identity, gated by a proxy | A day of ops | One shared endpoint, still one trust domain |
|
|
18
|
+
| **3 — Multi-tenant SaaS** | The server with auth + per-user identity + RLS | Per-user, per-product RBAC | A real build | External / untrusted users |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## What you should know first
|
|
23
|
+
|
|
24
|
+
- **Transport is stdio.** The server speaks MCP over stdin/stdout to a single
|
|
25
|
+
trusted client (Claude Code, Cursor, etc.). There is **no built-in network
|
|
26
|
+
endpoint** — Tiers 2 and 3 add one.
|
|
27
|
+
- **One config knob:** `UPG_DATABASE_URL` (or `--database-url`). The server
|
|
28
|
+
opens a default `pg.Pool` against it and runs `SELECT 1` at startup — **it
|
|
29
|
+
exits immediately if the database is unreachable.**
|
|
30
|
+
- **Postgres 13+** is required (the schema uses `gen_random_uuid()`).
|
|
31
|
+
- **RBAC is recorded, not yet enforced.** The schema has an `access` table
|
|
32
|
+
(`owner` / `editor` / `viewer` roles) and `grant_access` / `list_collaborators`
|
|
33
|
+
tools, but there are **no RLS policies** and the stdio server threads **no
|
|
34
|
+
per-user identity**. Today, whoever holds the connection string has full
|
|
35
|
+
access. Per-user enforcement is Tier 3 (see the roadmap below).
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Tier 1 — Shared managed Postgres (recommended starting point)
|
|
40
|
+
|
|
41
|
+
Host the **database**; every team member runs the server **locally** against it.
|
|
42
|
+
Production-ready today for a team inside one trust boundary.
|
|
43
|
+
|
|
44
|
+
### 1. Provision Postgres
|
|
45
|
+
|
|
46
|
+
Any Postgres 13+ works — [Neon](https://neon.tech), [Supabase](https://supabase.com),
|
|
47
|
+
[Railway](https://railway.app), RDS, or a VM. Grab the connection string:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
postgres://USER:PASS@HOST:5432/upg?sslmode=require
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 2. Apply the migrations (once, from any machine)
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
export UPG_DATABASE_URL='postgres://…?sslmode=require'
|
|
57
|
+
for f in migrations/*.sql; do
|
|
58
|
+
psql "$UPG_DATABASE_URL" -f "$f" # applies 001 → 004 in order
|
|
59
|
+
done
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The four migrations create the `upg` schema: `products`, `nodes`, `edges`,
|
|
63
|
+
`cross_product_edges` (001 + 004), `access` / `comments` / `audit_log`
|
|
64
|
+
(002), and `webhooks` (003).
|
|
65
|
+
|
|
66
|
+
### 3. Point each member's client at the shared DB
|
|
67
|
+
|
|
68
|
+
Add an MCP server entry to each member's client config. Keep the connection
|
|
69
|
+
string in **personal / local** config — never a committed file.
|
|
70
|
+
|
|
71
|
+
```jsonc
|
|
72
|
+
// If installed from npm (the package ships a `upg-cloud-server` bin):
|
|
73
|
+
{
|
|
74
|
+
"mcpServers": {
|
|
75
|
+
"unified-product-graph-cloud": {
|
|
76
|
+
"type": "stdio",
|
|
77
|
+
"command": "npx",
|
|
78
|
+
"args": ["-y", "@unified-product-graph/cloud-server"],
|
|
79
|
+
"env": { "UPG_DATABASE_URL": "postgres://…shared…?sslmode=require" }
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// From a monorepo checkout instead:
|
|
85
|
+
// "command": "node",
|
|
86
|
+
// "args": ["./packages/upg-cloud-server/dist/index.js"]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Restart the client. The tools appear namespaced as
|
|
90
|
+
`mcp__unified-product-graph-cloud__*`.
|
|
91
|
+
|
|
92
|
+
### 4. Work against a shared graph
|
|
93
|
+
|
|
94
|
+
The cloud server is **multi-product**, so every tool is scoped by `product_id`:
|
|
95
|
+
|
|
96
|
+
1. `create_product` → returns a product UUID.
|
|
97
|
+
2. Pass that `product_id` to `create_node`, `create_edge`, `query`, etc.
|
|
98
|
+
|
|
99
|
+
Concurrent writes from different members land as atomic Postgres transactions
|
|
100
|
+
with foreign-key integrity — no `.upg` merge conflicts.
|
|
101
|
+
|
|
102
|
+
### Local Postgres for development
|
|
103
|
+
|
|
104
|
+
A `docker-compose.yml` is included for a throwaway local database (Postgres on
|
|
105
|
+
`:5433`, migrations auto-applied on first boot):
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
cd docker
|
|
109
|
+
docker compose up -d postgres
|
|
110
|
+
# UPG_DATABASE_URL=postgres://upg:upg@localhost:5433/upg
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Tier 2 — A single shared endpoint (stdio → HTTP bridge)
|
|
116
|
+
|
|
117
|
+
Centralize the **process** so clients don't run anything locally. Wrap the
|
|
118
|
+
stdio server in an MCP HTTP bridge (e.g. [`supergateway`](https://github.com/supercorp-ai/supergateway)
|
|
119
|
+
or `mcp-proxy`, or swap in the SDK's StreamableHTTP transport) and put an
|
|
120
|
+
**auth proxy in front** — the server itself has no authentication.
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
[client] --HTTPS--> [auth proxy] --> [bridge + upg-cloud-server (stdio)] --> [managed Postgres]
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Clients then use a remote entry instead of spawning a process:
|
|
127
|
+
|
|
128
|
+
```jsonc
|
|
129
|
+
{
|
|
130
|
+
"mcpServers": {
|
|
131
|
+
"unified-product-graph-cloud": {
|
|
132
|
+
"type": "http",
|
|
133
|
+
"url": "https://upg.your-company.com/mcp",
|
|
134
|
+
"headers": { "Authorization": "Bearer <team-token>" }
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Caveat:** this centralizes the process, **not the permissions**. Every
|
|
141
|
+
client through the bridge still shares one database identity. Use Tier 2 when
|
|
142
|
+
you want one managed endpoint inside a single trust domain; use Tier 3 when
|
|
143
|
+
clients must be isolated from one another.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Tier 3 — Multi-tenant SaaS (the enforcement tier)
|
|
148
|
+
|
|
149
|
+
The data model is already built for this — `products`, `access` roles,
|
|
150
|
+
`audit_log`, `webhooks`, `cross_product_edges`. What's missing is the
|
|
151
|
+
**enforcement layer**. Reaching genuine per-user multi-tenancy requires:
|
|
152
|
+
|
|
153
|
+
1. **An HTTP transport** (replace/augment `StdioServerTransport`) that
|
|
154
|
+
authenticates each request and resolves it to a `user_id`.
|
|
155
|
+
2. **Identity propagation** into the store, so every query carries the calling
|
|
156
|
+
user (e.g. `SET LOCAL app.user_id = …` per transaction).
|
|
157
|
+
3. **RLS policies** on `upg.*` keyed off that identity and the `access` table,
|
|
158
|
+
so reads/writes are gated at the database — not by convention.
|
|
159
|
+
4. **Operational scale** — stateless server replicas behind a load balancer,
|
|
160
|
+
connection pooling (e.g. PgBouncer; the server currently opens an untuned
|
|
161
|
+
default `pg.Pool`), and the existing webhook/audit machinery wired to fire
|
|
162
|
+
on mutations.
|
|
163
|
+
|
|
164
|
+
Until those land, treat the `access` roles as **advisory metadata**, not a
|
|
165
|
+
security boundary.
|
|
166
|
+
|
|
167
|
+
> Tracked as a roadmap item — see the UPG issue tracker for "Tier-3 enforcement:
|
|
168
|
+
> HTTP transport + per-user identity + RLS."
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Choosing a tier
|
|
173
|
+
|
|
174
|
+
- **Small trusting team →** Tier 1. Host the DB, done.
|
|
175
|
+
- **Want one shared endpoint →** Tier 2. Bridge + auth proxy.
|
|
176
|
+
- **External / untrusted users →** Tier 3. Auth + identity + RLS + replicas.
|
|
177
|
+
|
|
178
|
+
## Environment reference
|
|
179
|
+
|
|
180
|
+
| Variable | Required | Description |
|
|
181
|
+
|----------|----------|-------------|
|
|
182
|
+
| `UPG_DATABASE_URL` | Yes | Postgres connection string. Also accepted as `--database-url`. |
|
|
183
|
+
|
|
184
|
+
The server is intentionally minimal in configuration — everything else lives
|
|
185
|
+
in the database.
|
package/dist/index.d.ts
ADDED