@genlobe/mcp-server 3.5.1 → 3.6.1
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/README.md +3 -2
- package/dist/index.js +361 -26
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -82,7 +82,7 @@ Edit `claude_desktop_config.json`:
|
|
|
82
82
|
|
|
83
83
|
## Tools
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
19 tools, in four groups.
|
|
86
86
|
|
|
87
87
|
### Documentation (offline, no API key needed)
|
|
88
88
|
|
|
@@ -90,7 +90,8 @@ Edit `claude_desktop_config.json`:
|
|
|
90
90
|
|---|---|
|
|
91
91
|
| `get_api_overview` | High-level architecture, auth model, key concepts, recommended call order. **Start here.** |
|
|
92
92
|
| `list_endpoint_categories` | Bare list of end-user endpoint categories plus a one-line summary of each. ~30 tokens. Call this once when you don't already know what's available; then use `get_end_user_endpoints({ category })` for the actual docs. |
|
|
93
|
-
| `get_end_user_endpoints` | Reference for end-user endpoints in ONE category. Pass `category` (one of `authentication`, `organizations`, `subscriptions`, `billing`, `usage`, `agents`, `users`, `plans`, `ai`, `entities`, `departments`, `files`, `external_agents`). The `billing` category
|
|
93
|
+
| `get_end_user_endpoints` | Reference for end-user endpoints in ONE category. Pass `category` (one of `authentication`, `organizations`, `subscriptions`, `billing`, `organization_admin`, `usage`, `agents`, `users`, `plans`, `ai`, `entities`, `departments`, `files`, `external_agents`). The `billing` category covers Tier-3 admin read-only billing endpoints (`/v1/organization-admin/{org_id}/{plans, config/stripe, audit, subscriptions}`); the new `organization_admin` category covers the non-billing Org Owner Dashboard surfaces (members, customers, agents, knowledge bases, agent-change notifications, Stripe webhook audit). Calling without a category returns the full catalog — use sparingly. |
|
|
94
|
+
| `get_reserved_schema_slugs` | Returns the 53 slugs the Custom Entities subsystem refuses at `POST /v1/entity/schemas` (ADR-0011 — they collide with native DB tables: `users`, `conversations`, `agents`, …). Pure data, no network call. Use it to pre-validate before issuing the POST and avoid a `400` round-trip. |
|
|
94
95
|
| `get_request_headers` | The exact HTTP headers required for end-user requests, with examples. |
|
|
95
96
|
| `get_authentication_flow` | Step-by-step register → login → refresh → logout, including token storage and refresh-on-401 patterns. |
|
|
96
97
|
| `get_common_patterns` | Pagination, error handling, optimistic updates, file upload, RAG queries, agent execution. |
|
package/dist/index.js
CHANGED
|
@@ -192,6 +192,82 @@ The \`sk_live_*\` key never reaches the browser. It lives only on the tenant's o
|
|
|
192
192
|
}
|
|
193
193
|
};
|
|
194
194
|
// =============================================================================
|
|
195
|
+
// Reserved schema slugs (ADR-0011)
|
|
196
|
+
// =============================================================================
|
|
197
|
+
//
|
|
198
|
+
// Mirrors `RESERVED_SCHEMA_SLUGS` in
|
|
199
|
+
// `src/tenants/services/custom_data_schema_service.py`. The backend is the
|
|
200
|
+
// authoritative source — this list is documentation-only and is exposed
|
|
201
|
+
// through the `get_reserved_schema_slugs` tool so agents can pre-validate
|
|
202
|
+
// before POSTing to /v1/entity/schemas.
|
|
203
|
+
//
|
|
204
|
+
// When the backend list changes (a new native __tablename__ is added),
|
|
205
|
+
// this constant MUST be updated in the same MCP PR.
|
|
206
|
+
const RESERVED_SCHEMA_SLUGS = Object.freeze([
|
|
207
|
+
// --- Alembic / Postgres internals -------------------------------------
|
|
208
|
+
"alembic_version",
|
|
209
|
+
// --- Tenants domain ---------------------------------------------------
|
|
210
|
+
"tenants",
|
|
211
|
+
"tenant_members",
|
|
212
|
+
"tenant_configs",
|
|
213
|
+
"tenant_password_reset_tokens",
|
|
214
|
+
"api_keys",
|
|
215
|
+
"email_logs",
|
|
216
|
+
"email_domains",
|
|
217
|
+
"email_verification_codes",
|
|
218
|
+
"custom_data_schemas",
|
|
219
|
+
"custom_data_records",
|
|
220
|
+
// --- Organizations domain --------------------------------------------
|
|
221
|
+
"organizations",
|
|
222
|
+
"organization_members",
|
|
223
|
+
"organization_configs",
|
|
224
|
+
"organization_invitations",
|
|
225
|
+
"departments",
|
|
226
|
+
"permissions",
|
|
227
|
+
"role_permissions",
|
|
228
|
+
// --- Users / Auth -----------------------------------------------------
|
|
229
|
+
"users",
|
|
230
|
+
"user_settings",
|
|
231
|
+
"password_reset_tokens",
|
|
232
|
+
// --- Subscriptions / Billing -----------------------------------------
|
|
233
|
+
"plans",
|
|
234
|
+
"tenant_plans",
|
|
235
|
+
"organization_plans",
|
|
236
|
+
"subscriptions",
|
|
237
|
+
"tenant_subscriptions",
|
|
238
|
+
"tenant_usages",
|
|
239
|
+
"tenant_usage_details",
|
|
240
|
+
"organization_usage_details",
|
|
241
|
+
"plan_usages",
|
|
242
|
+
"usage_logs",
|
|
243
|
+
"billing_audit_log",
|
|
244
|
+
"billing_meters",
|
|
245
|
+
"processed_stripe_events",
|
|
246
|
+
// --- AI domain --------------------------------------------------------
|
|
247
|
+
"agents",
|
|
248
|
+
"agent_executions",
|
|
249
|
+
"agent_tools",
|
|
250
|
+
"tool_executions",
|
|
251
|
+
"tool_secrets",
|
|
252
|
+
"external_agents",
|
|
253
|
+
"external_agent_calls",
|
|
254
|
+
"conversations",
|
|
255
|
+
"conversation_messages",
|
|
256
|
+
"knowledge_bases",
|
|
257
|
+
"documents",
|
|
258
|
+
"document_chunks",
|
|
259
|
+
// --- Files / Drive ---------------------------------------------------
|
|
260
|
+
"tenant_files",
|
|
261
|
+
"user_files",
|
|
262
|
+
"folders",
|
|
263
|
+
// --- Workflows (no Python model; defined only in migration) ---------
|
|
264
|
+
"workflows",
|
|
265
|
+
"workflow_executions",
|
|
266
|
+
"node_executions",
|
|
267
|
+
// --- Admin domain ----------------------------------------------------
|
|
268
|
+
"admin_audit_logs",
|
|
269
|
+
]);
|
|
270
|
+
// =============================================================================
|
|
195
271
|
// End-User Endpoints (for building frontends)
|
|
196
272
|
// =============================================================================
|
|
197
273
|
const END_USER_ENDPOINTS = {
|
|
@@ -223,7 +299,8 @@ const END_USER_ENDPOINTS = {
|
|
|
223
299
|
display_name: "string | null",
|
|
224
300
|
avatar_url: "string | null",
|
|
225
301
|
is_active: "boolean",
|
|
226
|
-
created_at: "ISO datetime"
|
|
302
|
+
created_at: "ISO datetime",
|
|
303
|
+
profile_data: "object — Tenant-defined free-form metadata for this user. Defaults to {} when empty (never null). Mutate via PATCH /v1/users/me/profile-data. ADR-0010."
|
|
227
304
|
}
|
|
228
305
|
},
|
|
229
306
|
response_when_verification_required: {
|
|
@@ -275,7 +352,8 @@ const END_USER_ENDPOINTS = {
|
|
|
275
352
|
display_name: "string | null",
|
|
276
353
|
avatar_url: "string | null",
|
|
277
354
|
is_active: "boolean",
|
|
278
|
-
created_at: "ISO datetime"
|
|
355
|
+
created_at: "ISO datetime",
|
|
356
|
+
profile_data: "object — Tenant-defined free-form metadata. Defaults to {} when empty (never null). ADR-0010."
|
|
279
357
|
}
|
|
280
358
|
},
|
|
281
359
|
{
|
|
@@ -1101,29 +1179,217 @@ const END_USER_ENDPOINTS = {
|
|
|
1101
1179
|
"403": "Caller is not an OrganizationMember with role owner/admin of the path's org."
|
|
1102
1180
|
}
|
|
1103
1181
|
},
|
|
1182
|
+
// ---------------------------------------------------------------
|
|
1183
|
+
// Org-admin Subscription list (Tier-3, end-user subscriptions view).
|
|
1184
|
+
// Distinct from the END-USER read at GET /v1/organizations/{id}/billing/subscription
|
|
1185
|
+
// (which returns ONLY the caller's own subscription). This one is
|
|
1186
|
+
// the dashboard's "list of paying customers" surface.
|
|
1187
|
+
// ---------------------------------------------------------------
|
|
1104
1188
|
{
|
|
1105
1189
|
method: "GET",
|
|
1106
|
-
path: "/v1/organization-admin/{organization_id}/
|
|
1107
|
-
summary: "
|
|
1190
|
+
path: "/v1/organization-admin/{organization_id}/subscriptions",
|
|
1191
|
+
summary: "List end-user subscriptions for the Organization (admin)",
|
|
1108
1192
|
auth: { api_key: "pk_live_* or sk_live_*", jwt: true, require_org_admin: true },
|
|
1109
1193
|
query_params: {
|
|
1110
|
-
|
|
1111
|
-
offset: "integer (default 0, ≥ 0)",
|
|
1112
|
-
action_prefix: "string (optional) — filter by action prefix, e.g. 'config.stripe' or 'webhook.security'."
|
|
1194
|
+
status: "string (optional) — comma-separated subscription statuses to filter (e.g. 'active,trialing,past_due'). Omit for all."
|
|
1113
1195
|
},
|
|
1114
1196
|
response: {
|
|
1115
|
-
items: "array of
|
|
1116
|
-
total: "number"
|
|
1117
|
-
limit: "integer (echo)",
|
|
1118
|
-
offset: "integer (echo)"
|
|
1197
|
+
items: "array of SubscriptionResponse — every Subscription row scoped to this Organization, sorted newest-first.",
|
|
1198
|
+
total: "number"
|
|
1119
1199
|
},
|
|
1120
|
-
note: "
|
|
1200
|
+
note: "Active statuses for the 'paying customers' count are: active, trialing, past_due. canceled / incomplete_expired / stripe_disconnected do NOT count as active.",
|
|
1121
1201
|
errors: {
|
|
1122
1202
|
"403": "Caller is not an OrganizationMember with role owner/admin of the path's org."
|
|
1123
1203
|
}
|
|
1124
1204
|
}
|
|
1125
1205
|
]
|
|
1126
1206
|
},
|
|
1207
|
+
organization_admin: {
|
|
1208
|
+
description: "Organization Owner / Admin surface that an agent uses while BUILDING the Tenant's product — team management (`members`), AI resource management (`agents` visibility, `knowledge-bases` + `documents` CRUD). Excludes observability endpoints (audit log, webhook delivery history, admin notifications, customer CRM list) — those live in the dashboards for humans, not in the MCP. Auth pattern across all of these: pk_live_*/sk_live_* + end-user JWT + `require_org_admin` (OrganizationMember.role IN owner/admin). For billing-specific admin endpoints (Tier-3 plans, Stripe config status) see the `billing` category. Secret-setting paths go through redirect-URL tools (`get_stripe_config_url`, `get_plan_management_url`, `get_agent_secrets_url`).",
|
|
1209
|
+
endpoints: [
|
|
1210
|
+
{
|
|
1211
|
+
method: "GET",
|
|
1212
|
+
path: "/v1/organization-admin/{organization_id}/members",
|
|
1213
|
+
summary: "List active members of the Organization (admin view)",
|
|
1214
|
+
auth: { api_key: "pk_live_* or sk_live_*", jwt: true, require_org_admin: true },
|
|
1215
|
+
response: {
|
|
1216
|
+
items: "array of OrganizationMemberResponse: { user_id (uuid), email (string), display_name (string | null), avatar_url (string | null), role ('owner'|'admin'|'member'|'developer'), is_active (boolean), joined_at (ISO datetime) }",
|
|
1217
|
+
total: "number"
|
|
1218
|
+
},
|
|
1219
|
+
note: "Subset of /v1/organizations/{org_id}/members but enforces require_org_admin (rejects TenantMember JWT). Use this when building the Org Owner dashboard's Members page.",
|
|
1220
|
+
errors: {
|
|
1221
|
+
"403": "Caller is not an OrganizationMember with role owner/admin of the path's org."
|
|
1222
|
+
}
|
|
1223
|
+
},
|
|
1224
|
+
{
|
|
1225
|
+
method: "PATCH",
|
|
1226
|
+
path: "/v1/organization-admin/{organization_id}/members/{member_user_id}/role",
|
|
1227
|
+
summary: "Update a member's role within the Organization",
|
|
1228
|
+
auth: { api_key: "pk_live_* or sk_live_*", jwt: true, require_org_admin: true },
|
|
1229
|
+
request_body: {
|
|
1230
|
+
role: "string (required) — one of 'owner', 'admin', 'member', 'developer'."
|
|
1231
|
+
},
|
|
1232
|
+
response: "OrganizationMemberResponse — the updated member row.",
|
|
1233
|
+
notes: "Service-level guards: only owners can promote to owner; admins cannot touch owners; the last active owner cannot be demoted (returns 400).",
|
|
1234
|
+
errors: {
|
|
1235
|
+
"400": "Last-owner demotion guard / target not a member.",
|
|
1236
|
+
"403": "Insufficient role for the requested transition (e.g. admin trying to touch an owner).",
|
|
1237
|
+
"404": "Member not found in this organization."
|
|
1238
|
+
}
|
|
1239
|
+
},
|
|
1240
|
+
{
|
|
1241
|
+
method: "DELETE",
|
|
1242
|
+
path: "/v1/organization-admin/{organization_id}/members/{member_user_id}",
|
|
1243
|
+
summary: "Remove a member from the Organization",
|
|
1244
|
+
auth: { api_key: "pk_live_* or sk_live_*", jwt: true, require_org_admin: true },
|
|
1245
|
+
response: "204 No Content",
|
|
1246
|
+
notes: "Service-level guards: only owners can remove other owners; the last active owner cannot be removed.",
|
|
1247
|
+
errors: {
|
|
1248
|
+
"400": "Last-owner removal guard.",
|
|
1249
|
+
"403": "Insufficient role for removal (e.g. admin trying to remove an owner).",
|
|
1250
|
+
"404": "Member not found in this organization."
|
|
1251
|
+
}
|
|
1252
|
+
},
|
|
1253
|
+
{
|
|
1254
|
+
method: "GET",
|
|
1255
|
+
path: "/v1/organization-admin/{organization_id}/agents",
|
|
1256
|
+
summary: "List agents visible to the Organization (Hybrid Catalog — ADR-0006 v2)",
|
|
1257
|
+
auth: { api_key: "pk_live_* or sk_live_*", jwt: true, require_org_admin: true },
|
|
1258
|
+
query_params: {
|
|
1259
|
+
include_catalog: "boolean (default true) — when true, includes public agents from the Tenant's root Organization (the catalog). When false, returns only agents owned by this Organization.",
|
|
1260
|
+
skip: "integer (default 0, ≥ 0)",
|
|
1261
|
+
limit: "integer (default 100, 1 ≤ limit ≤ 200)"
|
|
1262
|
+
},
|
|
1263
|
+
response: {
|
|
1264
|
+
items: "array of AgentResponse: { id, tenant_id, organization_id, is_public, forked_from_agent_id, name, description, system_prompt, response_type, rag_provider, rag_role, is_active, rag_config, mcp_servers, created_by, created_at, updated_at }",
|
|
1265
|
+
total: "number"
|
|
1266
|
+
},
|
|
1267
|
+
note: "Visibility rules (ADR-0006 v2 Hybrid Catalog): agents where organization_id == this Org UNION (if include_catalog=true) agents where is_public=true AND organization_id is the Tenant's root Organization. To customize a catalog agent, the Org forks it via POST /v1/agents/{id}/fork (Tenant Dashboard endpoint — not exposed to end-users in the MCP).",
|
|
1268
|
+
errors: {
|
|
1269
|
+
"403": "Caller is not an OrganizationMember with role owner/admin of the path's org."
|
|
1270
|
+
}
|
|
1271
|
+
},
|
|
1272
|
+
// ---------------------------------------------------------------
|
|
1273
|
+
// Knowledge Base management (per-Org, ADR-0006 v2 §rag_role).
|
|
1274
|
+
// Org-scoped CRUD on KnowledgeBase + Document. Replaces the legacy
|
|
1275
|
+
// single-store rag_config.store_id path (closes cross-org RAG leak G5).
|
|
1276
|
+
// ---------------------------------------------------------------
|
|
1277
|
+
{
|
|
1278
|
+
method: "POST",
|
|
1279
|
+
path: "/v1/organization-admin/{organization_id}/knowledge-bases",
|
|
1280
|
+
summary: "Create a KnowledgeBase in the caller's Organization",
|
|
1281
|
+
auth: { api_key: "pk_live_* or sk_live_*", jwt: true, require_org_admin: true },
|
|
1282
|
+
request_body: {
|
|
1283
|
+
name: "string (optional, max 200)",
|
|
1284
|
+
description: "string (optional)",
|
|
1285
|
+
role_tag: "string (optional, max 100) — Declarative tag matched against Agent.rag_role at runtime. When an Agent is invoked, the runtime looks up a KB in the caller's Org with role_tag == agent.rag_role and uses its vector store.",
|
|
1286
|
+
vector_store_config: "object (optional) — provider-specific vector-store settings (e.g. OpenAI File Search store id).",
|
|
1287
|
+
embedding_config: "object (optional) — provider-specific embedding settings."
|
|
1288
|
+
},
|
|
1289
|
+
response: {
|
|
1290
|
+
id: "uuid",
|
|
1291
|
+
organization_id: "uuid",
|
|
1292
|
+
name: "string | null",
|
|
1293
|
+
description: "string | null",
|
|
1294
|
+
role_tag: "string | null",
|
|
1295
|
+
is_active: "boolean",
|
|
1296
|
+
is_processing: "boolean"
|
|
1297
|
+
},
|
|
1298
|
+
notes: "KBs are per-Organization (KnowledgeBase.organization_id REQUIRED). Agents bind to per-Org KBs via the `rag_role` tag — the Agent declares `rag_role='support'` and the runtime finds the calling Org's KB with `role_tag='support'`. Multiple Orgs can have a KB with the same `role_tag`; each Org sees only its own."
|
|
1299
|
+
},
|
|
1300
|
+
{
|
|
1301
|
+
method: "GET",
|
|
1302
|
+
path: "/v1/organization-admin/{organization_id}/knowledge-bases",
|
|
1303
|
+
summary: "List KnowledgeBases in the caller's Organization",
|
|
1304
|
+
auth: { api_key: "pk_live_* or sk_live_*", jwt: true, require_org_admin: true },
|
|
1305
|
+
query_params: {
|
|
1306
|
+
include_inactive: "boolean (default false)",
|
|
1307
|
+
skip: "integer (default 0, ≥ 0)",
|
|
1308
|
+
limit: "integer (default 100, 1 ≤ limit ≤ 200)"
|
|
1309
|
+
},
|
|
1310
|
+
response: "Array of KnowledgeBaseResponse (same shape as POST response)."
|
|
1311
|
+
},
|
|
1312
|
+
{
|
|
1313
|
+
method: "GET",
|
|
1314
|
+
path: "/v1/organization-admin/{organization_id}/knowledge-bases/{kb_id}",
|
|
1315
|
+
summary: "Get a KnowledgeBase by ID",
|
|
1316
|
+
auth: { api_key: "pk_live_* or sk_live_*", jwt: true, require_org_admin: true },
|
|
1317
|
+
response: "KnowledgeBaseResponse",
|
|
1318
|
+
errors: {
|
|
1319
|
+
"404": "KB not found OR kb.organization_id != path organization_id."
|
|
1320
|
+
}
|
|
1321
|
+
},
|
|
1322
|
+
{
|
|
1323
|
+
method: "PATCH",
|
|
1324
|
+
path: "/v1/organization-admin/{organization_id}/knowledge-bases/{kb_id}",
|
|
1325
|
+
summary: "Update a KnowledgeBase (partial)",
|
|
1326
|
+
auth: { api_key: "pk_live_* or sk_live_*", jwt: true, require_org_admin: true },
|
|
1327
|
+
request_body: {
|
|
1328
|
+
name: "string (optional)",
|
|
1329
|
+
description: "string (optional)",
|
|
1330
|
+
role_tag: "string (optional)",
|
|
1331
|
+
vector_store_config: "object (optional)",
|
|
1332
|
+
embedding_config: "object (optional)",
|
|
1333
|
+
is_active: "boolean (optional)"
|
|
1334
|
+
},
|
|
1335
|
+
response: "KnowledgeBaseResponse"
|
|
1336
|
+
},
|
|
1337
|
+
{
|
|
1338
|
+
method: "DELETE",
|
|
1339
|
+
path: "/v1/organization-admin/{organization_id}/knowledge-bases/{kb_id}",
|
|
1340
|
+
summary: "Soft delete a KnowledgeBase (is_active=false). Documents survive for audit.",
|
|
1341
|
+
auth: { api_key: "pk_live_* or sk_live_*", jwt: true, require_org_admin: true },
|
|
1342
|
+
response: "204 No Content"
|
|
1343
|
+
},
|
|
1344
|
+
{
|
|
1345
|
+
method: "POST",
|
|
1346
|
+
path: "/v1/organization-admin/{organization_id}/knowledge-bases/{kb_id}/documents",
|
|
1347
|
+
summary: "Upload a document to a KnowledgeBase",
|
|
1348
|
+
auth: { api_key: "pk_live_* or sk_live_*", jwt: true, require_org_admin: true },
|
|
1349
|
+
request_body: "multipart/form-data with `file` (single file). File size hard cap: 100MB (413 if exceeded).",
|
|
1350
|
+
response: {
|
|
1351
|
+
id: "integer",
|
|
1352
|
+
knowledge_base_id: "uuid",
|
|
1353
|
+
organization_id: "uuid",
|
|
1354
|
+
filename: "string",
|
|
1355
|
+
file_size: "integer (bytes)",
|
|
1356
|
+
content_type: "string",
|
|
1357
|
+
status: "string — UPLOADED initially; worker layer transitions to PROCESSING/READY/FAILED.",
|
|
1358
|
+
error_message: "string | null"
|
|
1359
|
+
},
|
|
1360
|
+
notes: "The controller only records metadata; the worker layer consumes Document rows with status=UPLOADED and pushes to the storage provider. Cross-Org uploads (kb.organization_id != caller's Org) return 404, never 403.",
|
|
1361
|
+
errors: {
|
|
1362
|
+
"400": "Empty file or missing filename.",
|
|
1363
|
+
"413": "File size exceeds 100MB."
|
|
1364
|
+
}
|
|
1365
|
+
},
|
|
1366
|
+
{
|
|
1367
|
+
method: "GET",
|
|
1368
|
+
path: "/v1/organization-admin/{organization_id}/knowledge-bases/{kb_id}/documents",
|
|
1369
|
+
summary: "List documents in a KnowledgeBase",
|
|
1370
|
+
auth: { api_key: "pk_live_* or sk_live_*", jwt: true, require_org_admin: true },
|
|
1371
|
+
query_params: {
|
|
1372
|
+
skip: "integer (default 0, ≥ 0)",
|
|
1373
|
+
limit: "integer (default 100, 1 ≤ limit ≤ 200)"
|
|
1374
|
+
},
|
|
1375
|
+
response: "Array of DocumentResponse."
|
|
1376
|
+
},
|
|
1377
|
+
{
|
|
1378
|
+
method: "GET",
|
|
1379
|
+
path: "/v1/organization-admin/{organization_id}/knowledge-bases/{kb_id}/documents/{document_id}",
|
|
1380
|
+
summary: "Get a document by ID",
|
|
1381
|
+
auth: { api_key: "pk_live_* or sk_live_*", jwt: true, require_org_admin: true },
|
|
1382
|
+
response: "DocumentResponse"
|
|
1383
|
+
},
|
|
1384
|
+
{
|
|
1385
|
+
method: "DELETE",
|
|
1386
|
+
path: "/v1/organization-admin/{organization_id}/knowledge-bases/{kb_id}/documents/{document_id}",
|
|
1387
|
+
summary: "Delete a document from a KnowledgeBase",
|
|
1388
|
+
auth: { api_key: "pk_live_* or sk_live_*", jwt: true, require_org_admin: true },
|
|
1389
|
+
response: "204 No Content"
|
|
1390
|
+
}
|
|
1391
|
+
]
|
|
1392
|
+
},
|
|
1127
1393
|
usage: {
|
|
1128
1394
|
description: "Usage tracking and limits. Endpoints map to /v1/api/usage/* (current/history) and /v1/usage/* (stats/check/consume).",
|
|
1129
1395
|
endpoints: [
|
|
@@ -1467,8 +1733,26 @@ const END_USER_ENDPOINTS = {
|
|
|
1467
1733
|
]
|
|
1468
1734
|
},
|
|
1469
1735
|
users: {
|
|
1470
|
-
description: "User management - CRUD, settings, activation/deactivation. Dual auth: sk_live_* for admin ops, pk_live_* + JWT for self-service.",
|
|
1736
|
+
description: "User management - CRUD, settings, activation/deactivation, and Tenant-defined `profile_data` extensions (ADR-0010). Dual auth: sk_live_* for admin ops, pk_live_* + JWT for self-service.",
|
|
1471
1737
|
endpoints: [
|
|
1738
|
+
{
|
|
1739
|
+
method: "PATCH",
|
|
1740
|
+
path: "/v1/users/me/profile-data",
|
|
1741
|
+
summary: "Merge keys into the authenticated user's profile_data (ADR-0010)",
|
|
1742
|
+
auth: { api_key: "pk_live_* or sk_live_*", jwt: true },
|
|
1743
|
+
request_body: {
|
|
1744
|
+
profile_data: "object (required) — Top-level keys to merge into the existing profile_data JSONB. Keys present here overwrite same-named keys; keys absent are preserved. To clear a key, send it with value `null`. To clear the whole document, a future DELETE endpoint will be added (not implemented yet)."
|
|
1745
|
+
},
|
|
1746
|
+
response: "UserResponse — the updated row, including the merged profile_data. Same shape as GET /v1/users/{user_id}.",
|
|
1747
|
+
notes: "Merge semantics, NOT replace. The target user_id is taken from the decoded JWT — there is no body/path parameter that can redirect the write, so a user can ONLY edit their own profile_data. There is no admin-override path on this endpoint by design (use PUT /v1/users/{user_id} with sk_live_* if a Tenant admin needs to mutate someone else's row; that endpoint does NOT touch profile_data today). The platform does NOT validate against any schema — the Tenant owns the shape end-to-end. PII warning: do NOT store unencrypted PII (passwords, SSNs, card numbers); the column is plaintext at rest and ships on every /me call. Tenants needing per-Org-scoped or schema-validated user metadata can layer a custom entity (e.g. `user_profiles`) on top.",
|
|
1748
|
+
example_request: `{
|
|
1749
|
+
"profile_data": {
|
|
1750
|
+
"phone": "+1-555-0123",
|
|
1751
|
+
"preferences": { "theme": "dark", "lang": "en" },
|
|
1752
|
+
"premium_tier": "gold"
|
|
1753
|
+
}
|
|
1754
|
+
}`
|
|
1755
|
+
},
|
|
1472
1756
|
{
|
|
1473
1757
|
method: "POST",
|
|
1474
1758
|
path: "/v1/users",
|
|
@@ -1498,6 +1782,7 @@ const END_USER_ENDPOINTS = {
|
|
|
1498
1782
|
status: "string",
|
|
1499
1783
|
current_plan_id: "uuid | null",
|
|
1500
1784
|
default_organization_id: "uuid | null",
|
|
1785
|
+
profile_data: "object — Tenant-defined free-form metadata (ADR-0010). Defaults to {} when empty (POST does NOT seed this — mutate via PATCH /v1/users/me/profile-data afterward).",
|
|
1501
1786
|
created_at: "ISO datetime",
|
|
1502
1787
|
updated_at: "ISO datetime",
|
|
1503
1788
|
settings: "UserSettingsResponse | null"
|
|
@@ -1555,6 +1840,7 @@ const END_USER_ENDPOINTS = {
|
|
|
1555
1840
|
status: "string",
|
|
1556
1841
|
current_plan_id: "uuid | null",
|
|
1557
1842
|
default_organization_id: "uuid | null",
|
|
1843
|
+
profile_data: "object — Tenant-defined free-form metadata (ADR-0010). Defaults to {} when empty.",
|
|
1558
1844
|
created_at: "ISO datetime",
|
|
1559
1845
|
updated_at: "ISO datetime",
|
|
1560
1846
|
settings: "UserSettingsResponse | null (only if include_settings=true)"
|
|
@@ -1695,7 +1981,7 @@ const END_USER_ENDPOINTS = {
|
|
|
1695
1981
|
]
|
|
1696
1982
|
},
|
|
1697
1983
|
entities: {
|
|
1698
|
-
description: "Entity management (Custom Data) - define schemas and manage records. Two contexts: End-User API (API Key + JWT + X-Organization-Id) and Dashboard (Tenant JWT).",
|
|
1984
|
+
description: "Entity management (Custom Data) - define schemas and manage records. Two contexts: End-User API (API Key + JWT + X-Organization-Id) and Dashboard (Tenant JWT). Phase 3 additions: `reference` field type + cross-schema `join` clauses (ADR-0009), and reserved-slug enforcement (ADR-0011). Use `get_reserved_schema_slugs()` to pre-validate slugs.",
|
|
1699
1985
|
endpoints: [
|
|
1700
1986
|
// ── End-User Schema Endpoints ──
|
|
1701
1987
|
{
|
|
@@ -1729,7 +2015,8 @@ const END_USER_ENDPOINTS = {
|
|
|
1729
2015
|
enum: '{"type":"enum","required":true,"values":["draft","published","archived"]} // KEY IS "values", NOT "choices" — Genlobe rejects "choices" with 400.',
|
|
1730
2016
|
email: '{"type":"email","required":true,"max_length":255}',
|
|
1731
2017
|
url: '{"type":"url","required":false,"max_length":2048}',
|
|
1732
|
-
phone: '{"type":"phone","required":false,"max_length":20}'
|
|
2018
|
+
phone: '{"type":"phone","required":false,"max_length":20}',
|
|
2019
|
+
reference: '{"type":"reference","target_schema_slug":"users","required":true,"on_delete":"set_null"} // ADR-0009. target_schema_slug must be lowercase letters/numbers/hyphens and reference an existing schema slug in the same Org — use the literal "users" for the native users table. on_delete is one of "set_null" (default), "restrict", or "cascade". Self-references (target_schema_slug == this schema\'s slug) are rejected with 400.'
|
|
1733
2020
|
},
|
|
1734
2021
|
example_request: `{
|
|
1735
2022
|
"name": "Blog Post",
|
|
@@ -1739,10 +2026,11 @@ const END_USER_ENDPOINTS = {
|
|
|
1739
2026
|
"title": {"type": "string", "required": true, "max_length": 255},
|
|
1740
2027
|
"body": {"type": "text", "required": true},
|
|
1741
2028
|
"status": {"type": "enum", "required": true, "values": ["draft", "published", "archived"]},
|
|
1742
|
-
"views": {"type": "integer", "required": false, "min": 0}
|
|
2029
|
+
"views": {"type": "integer", "required": false, "min": 0},
|
|
2030
|
+
"author": {"type": "reference", "target_schema_slug": "users", "required": true, "on_delete": "restrict"}
|
|
1743
2031
|
}
|
|
1744
2032
|
}`,
|
|
1745
|
-
notes: "Returns 409 if name or slug already exists. Common pitfall: the enum field uses 'values' (an array) — 'choices' is rejected with a 400 that names this directly. The validator runs at field level, so all errors come back together in `detail.errors[]`."
|
|
2033
|
+
notes: "Returns 409 if name or slug already exists. Returns 400 if the slug collides with a native DB table (e.g. `users`, `conversations`, `agents`, `subscriptions`, ...) — ADR-0011 reserves 53 such slugs (case-insensitive). Call `get_reserved_schema_slugs()` to get the full list and pre-validate before POSTing. Common pitfall: the enum field uses 'values' (an array) — 'choices' is rejected with a 400 that names this directly. Reference fields (ADR-0009) are validated app-side (no SQL FK from JSONB) — `target_schema_slug` MUST point at an existing schema in the same Organization, or the literal `users` for the native users table. The validator runs at field level, so all errors come back together in `detail.errors[]`."
|
|
1746
2034
|
},
|
|
1747
2035
|
{
|
|
1748
2036
|
method: "GET",
|
|
@@ -1818,11 +2106,12 @@ const END_USER_ENDPOINTS = {
|
|
|
1818
2106
|
{
|
|
1819
2107
|
method: "POST",
|
|
1820
2108
|
path: "/v1/entity/records/search",
|
|
1821
|
-
summary: "Advanced search for entity records with filters and
|
|
2109
|
+
summary: "Advanced search for entity records with filters, ordering, and cross-schema joins (ADR-0009)",
|
|
1822
2110
|
auth: { api_key: "sk_live_* or pk_live_*", jwt: false, headers: "X-Organization-Id required when key is not organization-scoped" },
|
|
1823
2111
|
request_body: {
|
|
1824
2112
|
schema_id: "uuid (optional) - filter by schema",
|
|
1825
|
-
query: "object (optional) - filters: {field: value} for equality, {field: {operator: 'gt', value: 100}} for operators"
|
|
2113
|
+
query: "object (optional) - filters: {field: value} for equality, {field: {operator: 'gt', value: 100}} for operators",
|
|
2114
|
+
join: "array (optional, ADR-0009) — Cross-schema inner-join clauses against reference fields. Each item: { 'field': string (reference field on source schema), 'target_schema_slug': string (must match the field's declared target; use 'users' for the native users table), 'where': object (optional, JSONB equality predicates applied to the target's data; empty means 'just confirm the target exists') }. Multiple clauses are AND-ed. Inner-join only — no left/right. The target's fields are NOT returned to the caller; joins are filter-only. `where` does NOT support nested joins. Implemented as one EXISTS sub-select per clause (no N+1)."
|
|
1826
2115
|
},
|
|
1827
2116
|
query_params: {
|
|
1828
2117
|
page: "number (default 1)",
|
|
@@ -1830,14 +2119,21 @@ const END_USER_ENDPOINTS = {
|
|
|
1830
2119
|
order_by: "string (default 'created_at')",
|
|
1831
2120
|
order_dir: "'asc' | 'desc' (default 'desc')"
|
|
1832
2121
|
},
|
|
1833
|
-
notes: "Supported operators
|
|
2122
|
+
notes: "Supported operators in `query`: eq, ne, gt, gte, lt, lte, like, ilike, in, not_in. Row-level scope (ADR-0007): regular end-users (role=member) only see records where created_by_id = current_user.id; OrgAdmin and TenantMember bypass via include_all=true (audit-logged). Use the simpler GET /v1/entity/records/mine for the common 'my data' query.",
|
|
1834
2123
|
example_request: `{
|
|
1835
2124
|
"schema_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
1836
2125
|
"query": {
|
|
1837
2126
|
"price": { "operator": "gt", "value": 100 },
|
|
1838
2127
|
"category": "electronics",
|
|
1839
2128
|
"status": { "operator": "in", "value": ["active", "pending"] }
|
|
1840
|
-
}
|
|
2129
|
+
},
|
|
2130
|
+
"join": [
|
|
2131
|
+
{
|
|
2132
|
+
"field": "author",
|
|
2133
|
+
"target_schema_slug": "users",
|
|
2134
|
+
"where": { "is_active": true }
|
|
2135
|
+
}
|
|
2136
|
+
]
|
|
1841
2137
|
}`
|
|
1842
2138
|
}
|
|
1843
2139
|
]
|
|
@@ -3231,21 +3527,26 @@ burns context quickly.
|
|
|
3231
3527
|
If you don't know which categories exist yet, call list_endpoint_categories()
|
|
3232
3528
|
first.
|
|
3233
3529
|
|
|
3234
|
-
Categories: authentication, organizations, subscriptions, billing (
|
|
3530
|
+
Categories: authentication, organizations, subscriptions, billing (incl. Tier-3 admin read-only endpoints + subscriptions list), organization_admin (non-billing Org Owner Dashboard surfaces — members, customers, agents, KB, notifications, webhook audit), usage, agents, users (incl. PATCH /users/me/profile-data — ADR-0010), plans, ai, entities (Phase 3: reference fields + cross-schema join — ADR-0009; reserved slugs — ADR-0011), departments, files, external_agents.
|
|
3235
3531
|
|
|
3236
|
-
The 'billing' category
|
|
3532
|
+
The 'billing' category covers both the end-user surface
|
|
3237
3533
|
(/v1/organizations/{org_id}/billing/*) and the Organization-admin read-only
|
|
3238
|
-
surface (/v1/organization-admin/{org_id}/{plans, config/stripe, audit}).
|
|
3534
|
+
billing surface (/v1/organization-admin/{org_id}/{plans, config/stripe, audit, subscriptions}).
|
|
3239
3535
|
Secret-setting paths (config/stripe POST/PATCH/DELETE, plan CRUD that needs
|
|
3240
3536
|
the Stripe key) go through get_stripe_config_url / get_plan_management_url —
|
|
3241
|
-
the MCP never accepts raw secrets inline
|
|
3537
|
+
the MCP never accepts raw secrets inline.
|
|
3538
|
+
|
|
3539
|
+
The 'organization_admin' category covers the non-billing admin surfaces:
|
|
3540
|
+
members CRUD, customers list, agents visibility (Hybrid Catalog — ADR-0006 v2),
|
|
3541
|
+
KnowledgeBase + Documents CRUD (per-Org via rag_role), agent-change
|
|
3542
|
+
notifications, and the Stripe webhook event audit log.`,
|
|
3242
3543
|
inputSchema: {
|
|
3243
3544
|
type: "object",
|
|
3244
3545
|
properties: {
|
|
3245
3546
|
category: {
|
|
3246
3547
|
type: "string",
|
|
3247
3548
|
description: "Filter by category (strongly recommended). Leave empty only when you explicitly want the full catalog.",
|
|
3248
|
-
enum: ["authentication", "organizations", "subscriptions", "billing", "usage", "agents", "users", "plans", "ai", "entities", "departments", "files", "external_agents"],
|
|
3549
|
+
enum: ["authentication", "organizations", "subscriptions", "billing", "organization_admin", "usage", "agents", "users", "plans", "ai", "entities", "departments", "files", "external_agents"],
|
|
3249
3550
|
},
|
|
3250
3551
|
},
|
|
3251
3552
|
required: [],
|
|
@@ -3302,6 +3603,15 @@ the MCP never accepts raw secrets inline.`,
|
|
|
3302
3603
|
required: ["org_id"],
|
|
3303
3604
|
},
|
|
3304
3605
|
},
|
|
3606
|
+
{
|
|
3607
|
+
name: "get_reserved_schema_slugs",
|
|
3608
|
+
description: `Return the full list of schema slugs the Custom Entities subsystem reserves (ADR-0011). These slugs collide with native DB tables (e.g. \`users\`, \`conversations\`, \`agents\`, \`subscriptions\`, \`alembic_version\`, ...) and CANNOT be used as a custom data schema slug — the server rejects them at \`POST /v1/entity/schemas\` with a 400. Comparison is case-insensitive and ignores surrounding whitespace. Call this tool BEFORE issuing a \`POST /v1/entity/schemas\` so the agent can refuse client-side instead of round-tripping a 400. Pure data; no network call.`,
|
|
3609
|
+
inputSchema: {
|
|
3610
|
+
type: "object",
|
|
3611
|
+
properties: {},
|
|
3612
|
+
required: [],
|
|
3613
|
+
},
|
|
3614
|
+
},
|
|
3305
3615
|
{
|
|
3306
3616
|
name: "get_request_headers",
|
|
3307
3617
|
description: "Get detailed information about required HTTP headers for API requests.",
|
|
@@ -3647,6 +3957,29 @@ ${JSON.stringify({ categories, summaries }, null, 2)}`,
|
|
|
3647
3957
|
],
|
|
3648
3958
|
};
|
|
3649
3959
|
}
|
|
3960
|
+
case "get_reserved_schema_slugs": {
|
|
3961
|
+
// ADR-0011: returns the full list of slugs that cannot be used
|
|
3962
|
+
// for a Custom Entity schema because they collide with a native
|
|
3963
|
+
// DB table. Agents should call this BEFORE issuing
|
|
3964
|
+
// POST /v1/entity/schemas so they can refuse client-side.
|
|
3965
|
+
const slugs = [...RESERVED_SCHEMA_SLUGS];
|
|
3966
|
+
return {
|
|
3967
|
+
content: [
|
|
3968
|
+
{
|
|
3969
|
+
type: "text",
|
|
3970
|
+
text: JSON.stringify({
|
|
3971
|
+
reserved_slugs: slugs,
|
|
3972
|
+
total: slugs.length,
|
|
3973
|
+
comparison: "case-insensitive (server normalizes via .strip().lower() before comparison)",
|
|
3974
|
+
rejection_status: 400,
|
|
3975
|
+
rejection_message_template: "Schema slug '<slug>' is reserved (collides with a native table). Choose a different name.",
|
|
3976
|
+
source_of_truth: "src/tenants/services/custom_data_schema_service.py — RESERVED_SCHEMA_SLUGS. This MCP tool MUST be kept in sync; when a new native __tablename__ ships, both lists are updated in the same PR.",
|
|
3977
|
+
adr: "docs/adr/0011-namespace-collision-policy.md",
|
|
3978
|
+
}, null, 2),
|
|
3979
|
+
},
|
|
3980
|
+
],
|
|
3981
|
+
};
|
|
3982
|
+
}
|
|
3650
3983
|
case "get_request_headers": {
|
|
3651
3984
|
return {
|
|
3652
3985
|
content: [
|
|
@@ -4536,6 +4869,8 @@ async function main() {
|
|
|
4536
4869
|
console.error(` - get_stripe_config_url — Dashboard URL to set/rotate the Org's Stripe keys`);
|
|
4537
4870
|
console.error(` - get_agent_secrets_url — Dashboard URL to rotate an Agent's secrets`);
|
|
4538
4871
|
console.error(` - get_plan_management_url — Dashboard URL to create/edit Plans`);
|
|
4872
|
+
console.error(`\nCustom Entities helpers (ADR-0011):`);
|
|
4873
|
+
console.error(` - get_reserved_schema_slugs — Pre-validate schema slug before POST /v1/entity/schemas`);
|
|
4539
4874
|
console.error(`\nAuthenticated helpers:`);
|
|
4540
4875
|
console.error(` - list_end_users (sk_live_* required)`);
|
|
4541
4876
|
console.error(` - list_oauth_providers (any key)`);
|
package/package.json
CHANGED