@centrali-io/centrali-mcp 5.1.2 → 5.3.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/README.md +15 -0
- package/dist/index.js +2 -0
- package/dist/tools/_register.d.ts +24 -0
- package/dist/tools/_register.js +44 -0
- package/dist/tools/auth-providers.js +15 -30
- package/dist/tools/compute.js +48 -69
- package/dist/tools/describe.js +174 -21
- package/dist/tools/insights.js +13 -36
- package/dist/tools/orchestrations.js +21 -44
- package/dist/tools/pages.js +39 -61
- package/dist/tools/records.js +29 -50
- package/dist/tools/search.js +3 -24
- package/dist/tools/service-accounts.js +93 -108
- package/dist/tools/smart-queries.js +15 -36
- package/dist/tools/structures.js +23 -61
- package/dist/tools/validation.js +11 -34
- package/dist/tools/webhook-subscriptions.d.ts +3 -0
- package/dist/tools/webhook-subscriptions.js +292 -0
- package/package.json +5 -6
- package/src/index.ts +2 -0
- package/src/tools/_register.ts +53 -0
- package/src/tools/auth-providers.ts +8 -24
- package/src/tools/compute.ts +25 -46
- package/src/tools/describe.ts +200 -21
- package/src/tools/insights.ts +19 -28
- package/src/tools/orchestrations.ts +11 -34
- package/src/tools/pages.ts +20 -41
- package/src/tools/records.ts +15 -36
- package/src/tools/search.ts +7 -22
- package/src/tools/service-accounts.ts +47 -63
- package/src/tools/smart-queries.ts +8 -29
- package/src/tools/structures.ts +12 -50
- package/src/tools/validation.ts +21 -27
- package/src/tools/webhook-subscriptions.ts +363 -0
package/README.md
CHANGED
|
@@ -101,6 +101,7 @@ After connecting, call `describe_centrali` first — it returns the full capabil
|
|
|
101
101
|
| `describe_navigation` | Navigation configuration reference |
|
|
102
102
|
| `describe_auth_providers` | Auth provider reference (BYOT setup, claim mappings) |
|
|
103
103
|
| `describe_service_accounts` | Service account & IAM reference (SA setup, roles, groups, permissions) |
|
|
104
|
+
| `describe_webhooks` | Outbound webhook reference (subscription shape, signature, retry/replay) |
|
|
104
105
|
|
|
105
106
|
### Collections
|
|
106
107
|
| Tool | Description |
|
|
@@ -254,6 +255,20 @@ After connecting, call `describe_centrali` first — it returns the full capabil
|
|
|
254
255
|
| `update_group` | Update a group |
|
|
255
256
|
| `delete_group` | Delete a group |
|
|
256
257
|
|
|
258
|
+
### Webhook Subscriptions
|
|
259
|
+
| Tool | Description |
|
|
260
|
+
|------|-------------|
|
|
261
|
+
| `list_webhook_subscriptions` | List all outbound webhook subscriptions |
|
|
262
|
+
| `get_webhook_subscription` | Get a subscription by ID (secret not included) |
|
|
263
|
+
| `create_webhook_subscription` | Create a subscription — response returns the `whsec_` signing secret once |
|
|
264
|
+
| `update_webhook_subscription` | Update name, URL, events, recordSlugs, or active flag |
|
|
265
|
+
| `delete_webhook_subscription` | Delete a subscription (delivery history retained) |
|
|
266
|
+
| `rotate_webhook_subscription_secret` | Regenerate the signing secret (immediate cutover) |
|
|
267
|
+
| `list_webhook_deliveries` | List delivery history for a subscription (trimmed rows) |
|
|
268
|
+
| `get_webhook_delivery` | Get a single delivery with full payload and response body |
|
|
269
|
+
| `retry_webhook_delivery` | Replay a delivery — reuses the original payload and signature |
|
|
270
|
+
| `cancel_webhook_delivery` | Cancel a retrying delivery (flips to failed with distinctive marker) |
|
|
271
|
+
|
|
257
272
|
### Publishable Keys (Frontend)
|
|
258
273
|
| Tool | Description |
|
|
259
274
|
|------|-------------|
|
package/dist/index.js
CHANGED
|
@@ -25,6 +25,7 @@ const pages_js_1 = require("./tools/pages.js");
|
|
|
25
25
|
const describe_js_1 = require("./tools/describe.js");
|
|
26
26
|
const auth_providers_js_1 = require("./tools/auth-providers.js");
|
|
27
27
|
const service_accounts_js_1 = require("./tools/service-accounts.js");
|
|
28
|
+
const webhook_subscriptions_js_1 = require("./tools/webhook-subscriptions.js");
|
|
28
29
|
const structures_js_2 = require("./resources/structures.js");
|
|
29
30
|
function getRequiredEnv(name) {
|
|
30
31
|
const value = process.env[name];
|
|
@@ -82,6 +83,7 @@ function main() {
|
|
|
82
83
|
clientId,
|
|
83
84
|
isServiceAccount: true,
|
|
84
85
|
});
|
|
86
|
+
(0, webhook_subscriptions_js_1.registerWebhookSubscriptionTools)(server, sdk);
|
|
85
87
|
(0, describe_js_1.registerDescribeTools)(server);
|
|
86
88
|
// Register resources
|
|
87
89
|
(0, structures_js_2.registerCollectionResources)(server, sdk);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { ZodRawShape } from "zod";
|
|
3
|
+
export type ToolResult = {
|
|
4
|
+
content: Array<{
|
|
5
|
+
type: "text";
|
|
6
|
+
text: string;
|
|
7
|
+
}>;
|
|
8
|
+
isError?: boolean;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Thin wrapper around `server.tool(...)` that severs the MCP SDK's deep
|
|
12
|
+
* Zod-shape → handler-arg type inference. Each direct call to `server.tool()`
|
|
13
|
+
* forces TypeScript to elaborate a ~10M-instantiation type graph (MCP SDK
|
|
14
|
+
* `ShapeOutput` generics over Zod raw shapes), which OOMs tsc at ~4 GB.
|
|
15
|
+
*
|
|
16
|
+
* This helper casts the schema and handler at the MCP boundary, so tsc never
|
|
17
|
+
* walks that graph. Runtime behavior is identical — the MCP SDK still
|
|
18
|
+
* validates the payload against the Zod schema before invoking the handler.
|
|
19
|
+
*
|
|
20
|
+
* Call sites annotate the arg shape explicitly via the `Args` generic so the
|
|
21
|
+
* handler body stays fully type-safe.
|
|
22
|
+
*/
|
|
23
|
+
export declare function registerTool<Args>(server: McpServer, name: string, description: string, schema: ZodRawShape, handler: (args: Args) => Promise<ToolResult>): void;
|
|
24
|
+
export declare function formatError(error: unknown, context: string): string;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerTool = registerTool;
|
|
4
|
+
exports.formatError = formatError;
|
|
5
|
+
/**
|
|
6
|
+
* Thin wrapper around `server.tool(...)` that severs the MCP SDK's deep
|
|
7
|
+
* Zod-shape → handler-arg type inference. Each direct call to `server.tool()`
|
|
8
|
+
* forces TypeScript to elaborate a ~10M-instantiation type graph (MCP SDK
|
|
9
|
+
* `ShapeOutput` generics over Zod raw shapes), which OOMs tsc at ~4 GB.
|
|
10
|
+
*
|
|
11
|
+
* This helper casts the schema and handler at the MCP boundary, so tsc never
|
|
12
|
+
* walks that graph. Runtime behavior is identical — the MCP SDK still
|
|
13
|
+
* validates the payload against the Zod schema before invoking the handler.
|
|
14
|
+
*
|
|
15
|
+
* Call sites annotate the arg shape explicitly via the `Args` generic so the
|
|
16
|
+
* handler body stays fully type-safe.
|
|
17
|
+
*/
|
|
18
|
+
function registerTool(server, name, description, schema, handler) {
|
|
19
|
+
server.tool(name, description, schema, handler);
|
|
20
|
+
}
|
|
21
|
+
function formatError(error, context) {
|
|
22
|
+
var _a, _b;
|
|
23
|
+
if (error && typeof error === "object") {
|
|
24
|
+
const e = error;
|
|
25
|
+
if ("message" in e) {
|
|
26
|
+
let msg = `Error ${context}`;
|
|
27
|
+
if ("code" in e || "status" in e) {
|
|
28
|
+
msg += `: [${(_b = (_a = e.code) !== null && _a !== void 0 ? _a : e.status) !== null && _b !== void 0 ? _b : "ERROR"}] ${e.message}`;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
msg += `: ${e.message}`;
|
|
32
|
+
}
|
|
33
|
+
if (Array.isArray(e.fieldErrors) && e.fieldErrors.length > 0) {
|
|
34
|
+
msg +=
|
|
35
|
+
"\nField errors:\n" +
|
|
36
|
+
e.fieldErrors
|
|
37
|
+
.map((f) => ` ${f.field}: ${f.message}`)
|
|
38
|
+
.join("\n");
|
|
39
|
+
}
|
|
40
|
+
return msg;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return `Error ${context}: ${error instanceof Error ? error.message : String(error)}`;
|
|
44
|
+
}
|
|
@@ -15,6 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.registerAuthProviderTools = registerAuthProviderTools;
|
|
16
16
|
const axios_1 = __importDefault(require("axios"));
|
|
17
17
|
const zod_1 = require("zod");
|
|
18
|
+
const _register_js_1 = require("./_register.js");
|
|
18
19
|
/**
|
|
19
20
|
* Ensures the SDK has a valid token by making a lightweight SDK call if needed.
|
|
20
21
|
*/
|
|
@@ -69,22 +70,6 @@ function createIamClient(sdk, centraliUrl, workspaceId) {
|
|
|
69
70
|
}));
|
|
70
71
|
return client;
|
|
71
72
|
}
|
|
72
|
-
function formatError(error, context) {
|
|
73
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
74
|
-
if (error && typeof error === "object") {
|
|
75
|
-
const e = error;
|
|
76
|
-
if ((_a = e.response) === null || _a === void 0 ? void 0 : _a.data) {
|
|
77
|
-
const d = e.response.data;
|
|
78
|
-
const code = (_e = (_d = (_b = d.code) !== null && _b !== void 0 ? _b : (_c = d.error) === null || _c === void 0 ? void 0 : _c.code) !== null && _d !== void 0 ? _d : e.response.status) !== null && _e !== void 0 ? _e : "ERROR";
|
|
79
|
-
const message = (_h = (_f = d.message) !== null && _f !== void 0 ? _f : (_g = d.error) === null || _g === void 0 ? void 0 : _g.message) !== null && _h !== void 0 ? _h : JSON.stringify(d);
|
|
80
|
-
return `Error ${context}: [${code}] ${message}`;
|
|
81
|
-
}
|
|
82
|
-
if ("message" in e) {
|
|
83
|
-
return `Error ${context}: ${e.message}`;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return `Error ${context}: ${error instanceof Error ? error.message : String(error)}`;
|
|
87
|
-
}
|
|
88
73
|
const ClaimMappingZod = zod_1.z.object({
|
|
89
74
|
attribute: zod_1.z.string().describe("Attribute name used in policies (automatically prefixed with ext_). Must start with a letter, alphanumeric + underscores only. Example: 'role' becomes ext_role in policies."),
|
|
90
75
|
jwtPath: zod_1.z.string().describe("Dot-notation path to extract from the JWT payload. Examples: 'org_role', 'metadata.plan', 'organization.role'"),
|
|
@@ -95,7 +80,7 @@ const ClaimMappingZod = zod_1.z.object({
|
|
|
95
80
|
function registerAuthProviderTools(server, sdk, centraliUrl, workspaceId) {
|
|
96
81
|
const getClient = () => createIamClient(sdk, centraliUrl, workspaceId);
|
|
97
82
|
// ── List ──────────────────────────────────────────────────────────
|
|
98
|
-
|
|
83
|
+
(0, _register_js_1.registerTool)(server, "list_auth_providers", "List external auth providers configured in the workspace. These are identity providers (Clerk, Auth0, Okta, etc.) that can issue JWTs accepted by Centrali for BYOT (Bring Your Own Token) authorization.", {
|
|
99
84
|
includeInactive: zod_1.z.boolean().optional().describe("Include inactive providers (default: false)"),
|
|
100
85
|
}, (_a) => __awaiter(this, [_a], void 0, function* ({ includeInactive }) {
|
|
101
86
|
try {
|
|
@@ -109,13 +94,13 @@ function registerAuthProviderTools(server, sdk, centraliUrl, workspaceId) {
|
|
|
109
94
|
}
|
|
110
95
|
catch (error) {
|
|
111
96
|
return {
|
|
112
|
-
content: [{ type: "text", text: formatError(error, "listing auth providers") }],
|
|
97
|
+
content: [{ type: "text", text: (0, _register_js_1.formatError)(error, "listing auth providers") }],
|
|
113
98
|
isError: true,
|
|
114
99
|
};
|
|
115
100
|
}
|
|
116
101
|
}));
|
|
117
102
|
// ── Get ───────────────────────────────────────────────────────────
|
|
118
|
-
|
|
103
|
+
(0, _register_js_1.registerTool)(server, "get_auth_provider", "Get details of an external auth provider by ID, including claim mappings and JWKS configuration.", {
|
|
119
104
|
providerId: zod_1.z.string().describe("The provider ID (UUID)"),
|
|
120
105
|
}, (_a) => __awaiter(this, [_a], void 0, function* ({ providerId }) {
|
|
121
106
|
try {
|
|
@@ -126,13 +111,13 @@ function registerAuthProviderTools(server, sdk, centraliUrl, workspaceId) {
|
|
|
126
111
|
}
|
|
127
112
|
catch (error) {
|
|
128
113
|
return {
|
|
129
|
-
content: [{ type: "text", text: formatError(error, `getting auth provider '${providerId}'`) }],
|
|
114
|
+
content: [{ type: "text", text: (0, _register_js_1.formatError)(error, `getting auth provider '${providerId}'`) }],
|
|
130
115
|
isError: true,
|
|
131
116
|
};
|
|
132
117
|
}
|
|
133
118
|
}));
|
|
134
119
|
// ── Create ────────────────────────────────────────────────────────
|
|
135
|
-
|
|
120
|
+
(0, _register_js_1.registerTool)(server, "create_auth_provider", "Create an external auth provider for BYOT (Bring Your Own Token). This lets your app's users authenticate with Clerk, Auth0, Okta, or any OIDC provider, and Centrali validates their JWTs and extracts claims for authorization policies. Call describe_auth_providers for the full setup guide.", {
|
|
136
121
|
name: zod_1.z.string().describe("Display name (e.g., 'Production Clerk')"),
|
|
137
122
|
slug: zod_1.z.string().describe("URL-safe unique slug (lowercase, hyphens allowed, e.g., 'production-clerk')"),
|
|
138
123
|
providerType: zod_1.z.enum(["oidc", "clerk", "auth0", "keycloak", "okta", "custom"]).describe("Identity provider type. Use 'clerk', 'auth0', 'okta', or 'keycloak' for built-in support, 'oidc' for any OIDC-compliant provider, or 'custom' for a custom JWT issuer."),
|
|
@@ -165,13 +150,13 @@ function registerAuthProviderTools(server, sdk, centraliUrl, workspaceId) {
|
|
|
165
150
|
}
|
|
166
151
|
catch (error) {
|
|
167
152
|
return {
|
|
168
|
-
content: [{ type: "text", text: formatError(error, `creating auth provider '${name}'`) }],
|
|
153
|
+
content: [{ type: "text", text: (0, _register_js_1.formatError)(error, `creating auth provider '${name}'`) }],
|
|
169
154
|
isError: true,
|
|
170
155
|
};
|
|
171
156
|
}
|
|
172
157
|
}));
|
|
173
158
|
// ── Update ────────────────────────────────────────────────────────
|
|
174
|
-
|
|
159
|
+
(0, _register_js_1.registerTool)(server, "update_auth_provider", "Update an external auth provider. Only include the fields you want to change. Use this to update claim mappings, allowed audiences, or deactivate a provider.", {
|
|
175
160
|
providerId: zod_1.z.string().describe("The provider ID (UUID) to update"),
|
|
176
161
|
name: zod_1.z.string().optional().describe("Updated display name"),
|
|
177
162
|
jwksUrl: zod_1.z.string().optional().describe("Updated JWKS URL"),
|
|
@@ -207,13 +192,13 @@ function registerAuthProviderTools(server, sdk, centraliUrl, workspaceId) {
|
|
|
207
192
|
}
|
|
208
193
|
catch (error) {
|
|
209
194
|
return {
|
|
210
|
-
content: [{ type: "text", text: formatError(error, `updating auth provider '${providerId}'`) }],
|
|
195
|
+
content: [{ type: "text", text: (0, _register_js_1.formatError)(error, `updating auth provider '${providerId}'`) }],
|
|
211
196
|
isError: true,
|
|
212
197
|
};
|
|
213
198
|
}
|
|
214
199
|
}));
|
|
215
200
|
// ── Delete ────────────────────────────────────────────────────────
|
|
216
|
-
|
|
201
|
+
(0, _register_js_1.registerTool)(server, "delete_auth_provider", "Delete an external auth provider. Tokens from this provider will no longer be accepted.", {
|
|
217
202
|
providerId: zod_1.z.string().describe("The provider ID (UUID) to delete"),
|
|
218
203
|
}, (_a) => __awaiter(this, [_a], void 0, function* ({ providerId }) {
|
|
219
204
|
try {
|
|
@@ -224,13 +209,13 @@ function registerAuthProviderTools(server, sdk, centraliUrl, workspaceId) {
|
|
|
224
209
|
}
|
|
225
210
|
catch (error) {
|
|
226
211
|
return {
|
|
227
|
-
content: [{ type: "text", text: formatError(error, `deleting auth provider '${providerId}'`) }],
|
|
212
|
+
content: [{ type: "text", text: (0, _register_js_1.formatError)(error, `deleting auth provider '${providerId}'`) }],
|
|
228
213
|
isError: true,
|
|
229
214
|
};
|
|
230
215
|
}
|
|
231
216
|
}));
|
|
232
217
|
// ── Test Claim Extraction ─────────────────────────────────────────
|
|
233
|
-
|
|
218
|
+
(0, _register_js_1.registerTool)(server, "test_auth_provider", "Test claim extraction for an auth provider by passing a sample JWT. Decodes the token (without signature verification) and shows which claims would be extracted using the provider's configured mappings. Use this to validate your claim mappings before deploying.", {
|
|
234
219
|
providerId: zod_1.z.string().describe("The provider ID (UUID) to test against"),
|
|
235
220
|
token: zod_1.z.string().describe("A sample JWT token from your identity provider"),
|
|
236
221
|
}, (_a) => __awaiter(this, [_a], void 0, function* ({ providerId, token }) {
|
|
@@ -242,13 +227,13 @@ function registerAuthProviderTools(server, sdk, centraliUrl, workspaceId) {
|
|
|
242
227
|
}
|
|
243
228
|
catch (error) {
|
|
244
229
|
return {
|
|
245
|
-
content: [{ type: "text", text: formatError(error, `testing auth provider '${providerId}'`) }],
|
|
230
|
+
content: [{ type: "text", text: (0, _register_js_1.formatError)(error, `testing auth provider '${providerId}'`) }],
|
|
246
231
|
isError: true,
|
|
247
232
|
};
|
|
248
233
|
}
|
|
249
234
|
}));
|
|
250
235
|
// ── Refresh JWKS ──────────────────────────────────────────────────
|
|
251
|
-
|
|
236
|
+
(0, _register_js_1.registerTool)(server, "refresh_auth_provider_jwks", "Force refresh the cached JWKS (JSON Web Key Set) for an auth provider. Use this after your identity provider rotates its signing keys.", {
|
|
252
237
|
providerId: zod_1.z.string().describe("The provider ID (UUID)"),
|
|
253
238
|
}, (_a) => __awaiter(this, [_a], void 0, function* ({ providerId }) {
|
|
254
239
|
try {
|
|
@@ -259,7 +244,7 @@ function registerAuthProviderTools(server, sdk, centraliUrl, workspaceId) {
|
|
|
259
244
|
}
|
|
260
245
|
catch (error) {
|
|
261
246
|
return {
|
|
262
|
-
content: [{ type: "text", text: formatError(error, `refreshing JWKS for auth provider '${providerId}'`) }],
|
|
247
|
+
content: [{ type: "text", text: (0, _register_js_1.formatError)(error, `refreshing JWKS for auth provider '${providerId}'`) }],
|
|
263
248
|
isError: true,
|
|
264
249
|
};
|
|
265
250
|
}
|