@tideorg/mcp 1.4.1 → 1.4.2
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/GAP_REGISTER.md +1 -1
- package/README.md +80 -3
- package/adapters/AGENTS.md +0 -0
- package/adapters/CLAUDE.md +0 -0
- package/adapters/replit.md +0 -0
- package/canon/anti-patterns.md +0 -0
- package/canon/concepts.md +0 -0
- package/canon/custom-contracts.md +0 -0
- package/canon/delegation.md +0 -0
- package/canon/feature-mapping.md +0 -0
- package/canon/framework-matrix.md +0 -0
- package/canon/invariants.md +0 -0
- package/canon/redirect-handler.md +0 -0
- package/canon/tidecloak-bootstrap.md +64 -0
- package/canon/tidecloak-endpoints.md +0 -0
- package/canon/troubleshooting.md +86 -0
- package/canon/version-policy.md +0 -0
- package/mcp-server/dist/http.d.ts +2 -0
- package/mcp-server/dist/http.js +46 -0
- package/mcp-server/dist/index.d.ts +0 -0
- package/mcp-server/dist/index.js +2 -601
- package/mcp-server/dist/server.d.ts +2 -0
- package/mcp-server/dist/server.js +415 -0
- package/package.json +1 -1
- package/playbooks/add-auth-nextjs-existing.md +0 -0
- package/playbooks/add-auth-nextjs-fresh.md +0 -0
- package/playbooks/add-rbac-nextjs.md +0 -0
- package/playbooks/bootstrap-realm-from-template.md +0 -0
- package/playbooks/configure-e2ee-roles-and-policies.md +0 -0
- package/playbooks/deploy-tidecloak-docker.md +0 -0
- package/playbooks/diagnose-broken-login.md +0 -0
- package/playbooks/diagnose-missing-roles-or-claims.md +0 -0
- package/playbooks/initialize-admin-and-link-account.md +0 -0
- package/playbooks/migrate-from-existing-auth.md +0 -0
- package/playbooks/protect-api-nextjs.md +0 -0
- package/playbooks/protect-routes-nextjs.md +0 -0
- package/playbooks/setup-forseti-e2ee.md +0 -0
- package/playbooks/setup-iga-admin-panel.md +0 -0
- package/playbooks/setup-server-delegation.md +0 -0
- package/playbooks/start-tidecloak-dev.md +0 -0
- package/playbooks/verify-jwt-server-side.md +0 -0
- package/prompts/add-admin-approval-flow.md +0 -0
- package/prompts/build-private-customer-portal.md +0 -0
- package/prompts/migrate-generic-auth-to-tide.md +0 -0
- package/prompts/secure-existing-app.md +0 -0
- package/reference-apps/INDEX.md +0 -0
- package/reference-apps/encrypted-communication/anti-patterns.md +0 -0
- package/reference-apps/encrypted-communication/bootstrap-sequence.md +0 -0
- package/reference-apps/encrypted-communication/manifest.yaml +0 -0
- package/reference-apps/encrypted-communication/role-policy-matrix.md +0 -0
- package/reference-apps/encrypted-communication/scenario.md +0 -0
- package/reference-apps/git-pr-signing-service/anti-patterns.md +0 -0
- package/reference-apps/git-pr-signing-service/bootstrap-sequence.md +0 -0
- package/reference-apps/git-pr-signing-service/manifest.yaml +0 -0
- package/reference-apps/git-pr-signing-service/role-policy-matrix.md +0 -0
- package/reference-apps/git-pr-signing-service/scenario.md +0 -0
- package/reference-apps/iga-admin-governance/anti-patterns.md +0 -0
- package/reference-apps/iga-admin-governance/bootstrap-sequence.md +0 -0
- package/reference-apps/iga-admin-governance/manifest.yaml +0 -0
- package/reference-apps/iga-admin-governance/role-policy-matrix.md +0 -0
- package/reference-apps/iga-admin-governance/scenario.md +0 -0
- package/reference-apps/organisation-password-manager/anti-patterns.md +0 -0
- package/reference-apps/organisation-password-manager/bootstrap-sequence.md +0 -0
- package/reference-apps/organisation-password-manager/manifest.yaml +0 -0
- package/reference-apps/organisation-password-manager/role-policy-matrix.md +0 -0
- package/reference-apps/organisation-password-manager/scenario.md +0 -0
- package/reference-apps/policy-governed-signing/anti-patterns.md +0 -0
- package/reference-apps/policy-governed-signing/bootstrap-sequence.md +0 -0
- package/reference-apps/policy-governed-signing/manifest.yaml +0 -0
- package/reference-apps/policy-governed-signing/role-policy-matrix.md +0 -0
- package/reference-apps/policy-governed-signing/scenario.md +0 -0
- package/skills/tide-diagnostics/SKILL.md +0 -0
- package/skills/tide-integration/SKILL.md +0 -0
- package/skills/tide-learning-capture/SKILL.md +0 -0
- package/skills/tide-rbac-and-e2ee/SKILL.md +0 -0
- package/skills/tide-reviewer/SKILL.md +0 -0
- package/skills/tide-route-and-api-protection/SKILL.md +0 -0
- package/skills/tide-scenario-resolver/SKILL.md +0 -0
- package/skills/tide-setup/SKILL.md +0 -0
- package/skills/tide-solutions-architect/SKILL.md +0 -0
package/GAP_REGISTER.md
CHANGED
|
@@ -43,7 +43,7 @@ Controlled status set:
|
|
|
43
43
|
| GAP-021 | Ragnarok post-transition details | STILL_UNRESOLVED | No exemplar implements Ragnarok. | Still needs transition plan. |
|
|
44
44
|
| GAP-022 | C# SDK lacks Tide-specific content | PARTIALLY_RESOLVED_BY_MULTI_EXEMPLAR | Three contracts across two exemplars demonstrate comprehensive C# API surface: `IAccessPolicy`, `DataContext`, `ExecutorContext`, `ApproversContext`, `PolicyDecision`, `DokenDto`, `DokenDto.WrapAll()`, `Decision.*`, `TideKey.From()`, `Utils.GetEpochSeconds()`, `ExecutionType`, `ApprovalType`. | Not a standalone SDK package — types are available only within Forseti contract context. |
|
|
45
45
|
| GAP-023 | Keycloak-to-TideCloak migration path | STILL_UNRESOLVED | No exemplar is a migration. All are greenfield. | Still needs migration guide. |
|
|
46
|
-
| GAP-024 | Multi-tenant / multi-realm Fabric interaction |
|
|
46
|
+
| GAP-024 | Multi-tenant / multi-realm Fabric interaction | RESOLVED_BY_MULTI_EXEMPLAR | Ratidefy SaaS (ratidefy.com) implements full multi-tenant with per-tenant realms. Two-phase provisioning: realm+user first, role assignment after Tide account link. Path-based routing (`/t/<slug>/`). Each tenant gets independent VVK, Forseti policies, and IGA. Dynamic adapter config served from DB. Key learnings: client-origin-auth key format, IDP signing requirement, role assignment ordering. | Resolved. `canon/tidecloak-bootstrap.md` updated with "Hosted / SaaS Multi-Tenant Provisioning" section. |
|
|
47
47
|
| GAP-025 | VVK ORK 12-gate verification details | STILL_UNRESOLVED | No exemplar reveals gate list. | Still needs full gate list and error behavior. |
|
|
48
48
|
| GAP-026 | Adapter JSON field documentation | RESOLVED_BY_KEYLESSH | `tidecloakConfig.ts` TypeScript interface. forseti-crypto-quickstart provides additional field: `client-origin-auth-*` (signed origin binding). | Record as canon. Additional field `client-origin-auth-*` noted (GAP-048). |
|
|
49
49
|
| GAP-027 | Production deployment guide | PARTIALLY_RESOLVED_BY_KEYLESSH | keylessh `DEPLOYMENT.md` shows container patterns. tidewarden shows Docker multi-stage builds + Dockerfile.acr for ACR. | Extract reusable patterns. Full checklist still needed. |
|
package/README.md
CHANGED
|
@@ -64,7 +64,42 @@ Add to `~/.codeium/windsurf/mcp_config.json`:
|
|
|
64
64
|
```json
|
|
65
65
|
{
|
|
66
66
|
"mcpServers": {
|
|
67
|
-
"tide
|
|
67
|
+
"tide": {
|
|
68
|
+
"url": "https://mcp.tide.org/mcp"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Or for local: `"command": "npx", "args": ["-y", "@tideorg/mcp"]`
|
|
75
|
+
|
|
76
|
+
### Zed
|
|
77
|
+
|
|
78
|
+
Add to your Zed settings (`~/.config/zed/settings.json`):
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"context_servers": {
|
|
83
|
+
"tide": {
|
|
84
|
+
"command": {
|
|
85
|
+
"path": "npx",
|
|
86
|
+
"args": ["-y", "@tideorg/mcp"]
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Note: Zed uses `context_servers` (not `mcpServers`) and doesn't yet support remote URL-based MCP servers — use the npx command.
|
|
94
|
+
|
|
95
|
+
### OpenAI Codex CLI
|
|
96
|
+
|
|
97
|
+
Add to `~/.codex/config.json`:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"mcpServers": {
|
|
102
|
+
"tide": {
|
|
68
103
|
"command": "npx",
|
|
69
104
|
"args": ["-y", "@tideorg/mcp"]
|
|
70
105
|
}
|
|
@@ -72,6 +107,8 @@ Add to `~/.codeium/windsurf/mcp_config.json`:
|
|
|
72
107
|
}
|
|
73
108
|
```
|
|
74
109
|
|
|
110
|
+
Note: Codex CLI currently supports stdio-based MCP servers only — use the npx command.
|
|
111
|
+
|
|
75
112
|
## What your AI can do with this
|
|
76
113
|
|
|
77
114
|
Once connected, your AI assistant can:
|
|
@@ -106,10 +143,50 @@ After setup, try these prompts in your AI coding tool:
|
|
|
106
143
|
| Scenarios | 5 reference architectures | Password manager, signing service, encrypted chat, governance panel |
|
|
107
144
|
| Prompts | 4 starter prompts | Secure existing app, migrate auth, admin approval, customer portal |
|
|
108
145
|
|
|
146
|
+
## Remote Server (no install required)
|
|
147
|
+
|
|
148
|
+
We host the MCP server so you don't have to install anything. Just add the URL:
|
|
149
|
+
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"mcpServers": {
|
|
153
|
+
"tide": {
|
|
154
|
+
"url": "https://mcp.tide.org/mcp"
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
No Node.js required. No npx. Works with any MCP client that supports remote servers.
|
|
161
|
+
|
|
162
|
+
## Self-hosting
|
|
163
|
+
|
|
164
|
+
Want to run your own instance? Pull from Docker Hub:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
docker run -p 3000:3000 tideorg/mcp
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Or build from source:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
docker build -t tideorg/mcp .
|
|
174
|
+
docker run -p 3000:3000 tideorg/mcp
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Then point your MCP client at `http://localhost:3000/mcp`.
|
|
178
|
+
|
|
179
|
+
Optional: set `API_TOKEN` environment variable to require Bearer token auth:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
docker run -p 3000:3000 -e API_TOKEN=your-secret tideorg/mcp
|
|
183
|
+
```
|
|
184
|
+
|
|
109
185
|
## Requirements
|
|
110
186
|
|
|
111
|
-
-
|
|
112
|
-
-
|
|
187
|
+
- **Remote server**: None (just an MCP client that supports remote URLs)
|
|
188
|
+
- **npm/npx install**: Node.js 18+
|
|
189
|
+
- **Self-hosted Docker**: Docker
|
|
113
190
|
|
|
114
191
|
No TideCloak instance needed to start — the agent will guide you through setup.
|
|
115
192
|
|
package/adapters/AGENTS.md
CHANGED
|
File without changes
|
package/adapters/CLAUDE.md
CHANGED
|
File without changes
|
package/adapters/replit.md
CHANGED
|
File without changes
|
package/canon/anti-patterns.md
CHANGED
|
File without changes
|
package/canon/concepts.md
CHANGED
|
File without changes
|
|
File without changes
|
package/canon/delegation.md
CHANGED
|
File without changes
|
package/canon/feature-mapping.md
CHANGED
|
File without changes
|
|
File without changes
|
package/canon/invariants.md
CHANGED
|
File without changes
|
|
File without changes
|
|
@@ -243,6 +243,70 @@ The bootstrap/init script must check the HTTP status of every critical step and
|
|
|
243
243
|
|
|
244
244
|
---
|
|
245
245
|
|
|
246
|
+
## Hosted / SaaS Multi-Tenant Provisioning
|
|
247
|
+
|
|
248
|
+
When bootstrapping realms programmatically on a hosted TideCloak instance (e.g., `login.dauth.me`) for a multi-tenant SaaS application, the same initialization sequence applies but with critical differences. VERIFIED (Ratidefy SaaS, ratidefy.com).
|
|
249
|
+
|
|
250
|
+
### Two-Phase Provisioning
|
|
251
|
+
|
|
252
|
+
Role assignment MUST happen after the admin user links their Tide account. IGA change requests require a Tide doken to be signable. Without a linked identity, the sign endpoint returns 200 but the change-set remains in DRAFT permanently.
|
|
253
|
+
|
|
254
|
+
**Phase A** (automated, before user interaction):
|
|
255
|
+
Steps 1–9 from the standard sequence, EXCEPT step 8c (role assignment). Generate the invite link at the end.
|
|
256
|
+
|
|
257
|
+
**Phase B** (after user links Tide account via invite link):
|
|
258
|
+
Step 8c (assign role) → Step 11 (approve role change-sets).
|
|
259
|
+
|
|
260
|
+
**Anti-pattern:** Assigning `tide-realm-admin` before the user links their Tide account. Creates an unsignable DRAFT change request. The only recovery is to delete the draft and re-assign after linking. VERIFIED.
|
|
261
|
+
|
|
262
|
+
### client-origin-auth Key Format
|
|
263
|
+
|
|
264
|
+
The adapter config exported from TideCloak includes keys like:
|
|
265
|
+
```
|
|
266
|
+
"client-origin-auth-https://myapp.example.com": "E1Kaff...=="
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
The **origin URL is part of the key name**, not just metadata. When storing adapter config fields in a database for dynamic serving, preserve the full key name. Storing only the value produces invalid config that causes `[HEIMDALL] Client origin could not be verified`.
|
|
270
|
+
|
|
271
|
+
**Correct storage format** (e.g., JSON column):
|
|
272
|
+
```json
|
|
273
|
+
{ "key": "client-origin-auth-https://myapp.example.com", "value": "E1Kaff...==" }
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
VERIFIED.
|
|
277
|
+
|
|
278
|
+
### IDP Settings Signing
|
|
279
|
+
|
|
280
|
+
After setting `CustomAdminUIDomain` on the Tide IDP, you MUST call:
|
|
281
|
+
```
|
|
282
|
+
POST /admin/realms/{realm}/vendorResources/sign-idp-settings
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Without this step, the Tide enclave rejects all signing/encryption requests from the configured origin with `Client origin could not be verified`. The sign step cryptographically binds the IDP settings to the ORK network. VERIFIED.
|
|
286
|
+
|
|
287
|
+
### Path-Based vs Subdomain Tenant Routing
|
|
288
|
+
|
|
289
|
+
If using path-based routing (`myapp.com/t/<tenant>/`) instead of subdomains (`tenant.myapp.com`):
|
|
290
|
+
- Set redirect URIs on the **root domain** (`https://myapp.com/*`), not per-tenant subdomains
|
|
291
|
+
- `CustomAdminUIDomain` must be the root domain (`https://myapp.com`)
|
|
292
|
+
- The `client-origin-auth` key will reference the root domain
|
|
293
|
+
|
|
294
|
+
Subdomain routing requires a wildcard SSL certificate. Azure App Service managed certs do not support wildcards — use path-based routing or Azure Front Door. VERIFIED.
|
|
295
|
+
|
|
296
|
+
### JWT kid Requirement
|
|
297
|
+
|
|
298
|
+
Some TideCloak realm configurations produce JWTs with missing `kid` (Key ID) in the header. The standard Keycloak admin REST API requires `kid` to verify token signatures. Tokens without `kid` cause 401 on all admin API calls even with valid roles.
|
|
299
|
+
|
|
300
|
+
**Symptom**: Token has all admin roles (`realm-admin`, `manage-users`, etc.) but admin API returns `{"error":"HTTP 401 Unauthorized"}`. TideCloak logs: `kid is null, cant find public key: realm={0}`.
|
|
301
|
+
|
|
302
|
+
**Fix**: Recreate the realm. The `kid` issue is a realm configuration problem, not a token issue. VERIFIED.
|
|
303
|
+
|
|
304
|
+
### DPoP on Hosted Instances
|
|
305
|
+
|
|
306
|
+
DPoP (`useDPoP: { mode: 'strict', alg: 'EdDSA' }`) may not be supported on all hosted TideCloak instances. Enabling DPoP on `login.dauth.me` caused 500 on the token endpoint. Do not enable DPoP unless confirmed supported by the hosting provider. Standard `secureFetch` without DPoP works for admin API calls when the token has a valid `kid`. VERIFIED.
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
246
310
|
## Data Directory Rules
|
|
247
311
|
|
|
248
312
|
- Mount `./data:/opt/keycloak/data/h2`, never the project root.
|
|
File without changes
|
package/canon/troubleshooting.md
CHANGED
|
@@ -1492,3 +1492,89 @@ VERIFIED (TIDE_LEARNINGS-001 L-11).
|
|
|
1492
1492
|
**Verification**: After fixing the server error, the request returns 200 with proper CORS headers.
|
|
1493
1493
|
|
|
1494
1494
|
VERIFIED (LEARNINGS-ratidefy-batch-001 L-15).
|
|
1495
|
+
|
|
1496
|
+
---
|
|
1497
|
+
|
|
1498
|
+
## T-20: Admin API Returns 401 Despite Valid Roles (Missing JWT kid)
|
|
1499
|
+
|
|
1500
|
+
**Symptom**: Token has all admin roles (`realm-admin`, `manage-users`, `view-users`, etc.), token is not expired, but admin REST API returns `{"error":"HTTP 401 Unauthorized"}`. TideCloak logs show `kid is null, cant find public key: realm={0}`.
|
|
1501
|
+
|
|
1502
|
+
**Possible Causes**:
|
|
1503
|
+
1. JWT header has no `kid` field — realm's EdDSA signing key configuration is broken
|
|
1504
|
+
2. Token signed with ORK threshold EdDSA but no `kid` reference for admin API to look up the verification key
|
|
1505
|
+
|
|
1506
|
+
**Diagnostics**:
|
|
1507
|
+
|
|
1508
|
+
```bash
|
|
1509
|
+
# Decode the JWT header
|
|
1510
|
+
echo '<token>' | cut -d. -f1 | base64 -d 2>/dev/null | jq .
|
|
1511
|
+
# If output shows {"alg":"EdDSA","typ":"JWT"} with NO "kid" field — that's the problem
|
|
1512
|
+
```
|
|
1513
|
+
|
|
1514
|
+
**Fix**: Recreate the TideCloak realm. The `kid` issue is a realm-level configuration problem that cannot be fixed on existing tokens. A new realm will issue tokens with proper `kid` in the JWT header.
|
|
1515
|
+
|
|
1516
|
+
**Verification**: After recreating the realm, decode a new token's header — it should include `"kid": "some-key-id"`.
|
|
1517
|
+
|
|
1518
|
+
VERIFIED (Ratidefy SaaS — ratidefy-sign realm had missing kid, recreated as ratidefy-sign-2).
|
|
1519
|
+
|
|
1520
|
+
---
|
|
1521
|
+
|
|
1522
|
+
## T-21: Enclave Error "Client origin could not be verified"
|
|
1523
|
+
|
|
1524
|
+
**Symptom**: Tide enclave popup appears and immediately closes. Browser console shows `[HEIMDALL] Recieved enclave error: Client origin could not be verified`.
|
|
1525
|
+
|
|
1526
|
+
**Possible Causes**:
|
|
1527
|
+
1. `CustomAdminUIDomain` not set on Tide IDP
|
|
1528
|
+
2. IDP settings not signed after setting `CustomAdminUIDomain`
|
|
1529
|
+
3. `client-origin-auth` key in adapter config is malformed or missing the origin URL
|
|
1530
|
+
|
|
1531
|
+
**Diagnostics**:
|
|
1532
|
+
|
|
1533
|
+
```bash
|
|
1534
|
+
# Check CustomAdminUIDomain
|
|
1535
|
+
TOKEN=$(curl -s -X POST "$TC_URL/realms/master/protocol/openid-connect/token" \
|
|
1536
|
+
-d "username=admin&password=$PASS&grant_type=password&client_id=admin-cli" | jq -r .access_token)
|
|
1537
|
+
curl -s "$TC_URL/admin/realms/$REALM/identity-provider/instances/tide" \
|
|
1538
|
+
-H "Authorization: Bearer $TOKEN" | jq '.config.CustomAdminUIDomain'
|
|
1539
|
+
|
|
1540
|
+
# Check adapter config for client-origin-auth key
|
|
1541
|
+
# The key MUST include the origin URL: "client-origin-auth-https://myapp.com"
|
|
1542
|
+
# NOT a hash/signature as the key suffix
|
|
1543
|
+
```
|
|
1544
|
+
|
|
1545
|
+
**Fix**:
|
|
1546
|
+
1. Set `CustomAdminUIDomain` to the app origin (e.g., `https://myapp.com`)
|
|
1547
|
+
2. Sign the IDP settings: `POST /admin/realms/{realm}/vendorResources/sign-idp-settings`
|
|
1548
|
+
3. Ensure adapter config `client-origin-auth` key includes the origin URL, not just the signature value
|
|
1549
|
+
|
|
1550
|
+
**Verification**: Enclave popup appears and stays open for user interaction.
|
|
1551
|
+
|
|
1552
|
+
VERIFIED (Ratidefy SaaS — IDP settings unsigned, client-origin-auth key had signature instead of origin URL).
|
|
1553
|
+
|
|
1554
|
+
---
|
|
1555
|
+
|
|
1556
|
+
## T-22: IGA Role Assignment Stuck in DRAFT (Unsignable Change Request)
|
|
1557
|
+
|
|
1558
|
+
**Symptom**: Role assigned to user via admin API, change request created, but sign/commit returns 200 without actually signing. Role remains in DRAFT state permanently.
|
|
1559
|
+
|
|
1560
|
+
**Possible Causes**:
|
|
1561
|
+
1. Role assigned before the user linked their Tide account — IGA requires a Tide doken for change request signing
|
|
1562
|
+
2. The master admin token can create change requests but cannot sign them without a Tide identity
|
|
1563
|
+
|
|
1564
|
+
**Diagnostics**:
|
|
1565
|
+
1. Check TideCloak admin → realm → Users → target user → Role Mapping tab
|
|
1566
|
+
2. If role shows "DRAFT" badge, the change request was never signed
|
|
1567
|
+
3. Check if user has a federated identity (Identity Provider Links tab)
|
|
1568
|
+
|
|
1569
|
+
**Fix**:
|
|
1570
|
+
1. Delete the DRAFT change request
|
|
1571
|
+
2. Ensure the user links their Tide account first (via invite link)
|
|
1572
|
+
3. Then assign the role — the change request can now be signed
|
|
1573
|
+
|
|
1574
|
+
**Prevention**: In automated provisioning, split into two phases:
|
|
1575
|
+
- Phase A: Create realm, user, generate invite link (no role assignment)
|
|
1576
|
+
- Phase B: After user links Tide account, assign role and approve change request
|
|
1577
|
+
|
|
1578
|
+
**Verification**: Role shows "ACTIVE" status in TideCloak admin after sign+commit.
|
|
1579
|
+
|
|
1580
|
+
VERIFIED (Ratidefy SaaS — provisioner assigned tide-realm-admin before account linking, creating permanent DRAFT).
|
package/canon/version-policy.md
CHANGED
|
File without changes
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import express from "express";
|
|
3
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
4
|
+
import { createServer } from "./server.js";
|
|
5
|
+
const app = express();
|
|
6
|
+
app.use(express.json());
|
|
7
|
+
// Optional Bearer token auth
|
|
8
|
+
const API_TOKEN = process.env.API_TOKEN;
|
|
9
|
+
if (API_TOKEN) {
|
|
10
|
+
app.use("/mcp", (req, res, next) => {
|
|
11
|
+
const auth = req.headers.authorization;
|
|
12
|
+
if (!auth || auth !== `Bearer ${API_TOKEN}`) {
|
|
13
|
+
res.status(401).json({ error: "Unauthorized" });
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
next();
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
// MCP endpoint — stateless (new server + transport per request)
|
|
20
|
+
app.post("/mcp", async (req, res) => {
|
|
21
|
+
const server = createServer();
|
|
22
|
+
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
|
|
23
|
+
res.on("close", () => {
|
|
24
|
+
transport.close();
|
|
25
|
+
server.close();
|
|
26
|
+
});
|
|
27
|
+
await server.connect(transport);
|
|
28
|
+
await transport.handleRequest(req, res, req.body);
|
|
29
|
+
});
|
|
30
|
+
// Handle GET and DELETE for SSE streams (required by protocol)
|
|
31
|
+
app.get("/mcp", async (req, res) => {
|
|
32
|
+
res.status(405).json({ error: "Method not allowed. Use POST for stateless MCP." });
|
|
33
|
+
});
|
|
34
|
+
app.delete("/mcp", async (req, res) => {
|
|
35
|
+
res.status(405).json({ error: "Method not allowed. Stateless server — no sessions to delete." });
|
|
36
|
+
});
|
|
37
|
+
// Health check for Azure / load balancers
|
|
38
|
+
app.get("/health", (_, res) => {
|
|
39
|
+
res.status(200).json({ status: "ok", name: "@tideorg/mcp" });
|
|
40
|
+
});
|
|
41
|
+
const port = parseInt(process.env.PORT || "3000", 10);
|
|
42
|
+
app.listen(port, "0.0.0.0", () => {
|
|
43
|
+
console.log(`@tideorg/mcp HTTP server listening on port ${port}`);
|
|
44
|
+
console.log(`MCP endpoint: http://0.0.0.0:${port}/mcp`);
|
|
45
|
+
console.log(`Health check: http://0.0.0.0:${port}/health`);
|
|
46
|
+
});
|
|
File without changes
|