@centrali-io/centrali-mcp 5.0.3 → 5.1.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 CHANGED
@@ -266,7 +266,7 @@ After connecting, call `describe_centrali` first — it returns the full capabil
266
266
  ### Identity
267
267
  | Tool | Description |
268
268
  |------|-------------|
269
- | `get_current_identity` | Get the MCP's own service account ID and details |
269
+ | `get_current_identity` | Get the current authenticated MCP identity (service account or OAuth user) |
270
270
 
271
271
  ### Structures (Deprecated)
272
272
  | Tool | Description |
package/dist/index.js CHANGED
@@ -78,7 +78,10 @@ function main() {
78
78
  (0, validation_js_1.registerValidationTools)(server, sdk);
79
79
  (0, pages_js_1.registerPageTools)(server, sdk, baseUrl, workspaceId);
80
80
  (0, auth_providers_js_1.registerAuthProviderTools)(server, sdk, baseUrl, workspaceId);
81
- (0, service_accounts_js_1.registerServiceAccountTools)(server, sdk, baseUrl, workspaceId, clientId);
81
+ (0, service_accounts_js_1.registerServiceAccountTools)(server, sdk, baseUrl, workspaceId, {
82
+ clientId,
83
+ isServiceAccount: true,
84
+ });
82
85
  (0, describe_js_1.registerDescribeTools)(server);
83
86
  // Register resources
84
87
  (0, structures_js_2.registerCollectionResources)(server, sdk);
@@ -1,3 +1,9 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { CentraliSDK } from "@centrali-io/centrali-sdk";
3
- export declare function registerServiceAccountTools(server: McpServer, sdk: CentraliSDK, centraliUrl: string, workspaceId: string, ownClientId?: string): void;
3
+ export interface CurrentIdentityContext {
4
+ clientId?: string;
5
+ userId?: string;
6
+ scopes?: string[];
7
+ isServiceAccount?: boolean;
8
+ }
9
+ export declare function registerServiceAccountTools(server: McpServer, sdk: CentraliSDK, centraliUrl: string, workspaceId: string, currentIdentity?: CurrentIdentityContext): void;
@@ -85,16 +85,42 @@ function formatError(error, context) {
85
85
  }
86
86
  return `Error ${context}: ${error instanceof Error ? error.message : String(error)}`;
87
87
  }
88
- function registerServiceAccountTools(server, sdk, centraliUrl, workspaceId, ownClientId) {
88
+ function registerServiceAccountTools(server, sdk, centraliUrl, workspaceId, currentIdentity) {
89
89
  const getSaClient = () => createIamClient(sdk, centraliUrl, workspaceId, "service-accounts");
90
+ const getUsersClient = () => createIamClient(sdk, centraliUrl, workspaceId, "users");
90
91
  const getRolesClient = () => createIamClient(sdk, centraliUrl, workspaceId, "roles");
91
92
  const getGroupsClient = () => createIamClient(sdk, centraliUrl, workspaceId, "groups");
92
93
  // ── Identity ─────────────────────────────────────────────────────
93
- server.tool("get_current_identity", "Get the current MCP service account's identity its numeric ID, clientId, name, roles, and groups. Call this first when you need to check or fix your own permissions (e.g., after a 403 error). Returns the SA details needed for scan_service_account_permissions and generate_remediation.", {}, () => __awaiter(this, void 0, void 0, function* () {
94
- var _a, _b, _c;
94
+ server.tool("get_current_identity", "Get the current authenticated MCP identity. In stdio/service-account mode, returns the MCP service account. In hosted OAuth mode, fetches the authenticated user's profile, roles, and groups from IAM.", {}, () => __awaiter(this, void 0, void 0, function* () {
95
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
95
96
  try {
97
+ if ((currentIdentity === null || currentIdentity === void 0 ? void 0 : currentIdentity.userId) && !currentIdentity.isServiceAccount) {
98
+ const meRes = yield getUsersClient().get("/me");
99
+ const user = meRes.data;
100
+ return {
101
+ content: [{
102
+ type: "text",
103
+ text: JSON.stringify({
104
+ identityType: "user",
105
+ userId: (_a = user.id) !== null && _a !== void 0 ? _a : currentIdentity.userId,
106
+ email: (_b = user.email) !== null && _b !== void 0 ? _b : null,
107
+ name: (_d = (_c = user.name) !== null && _c !== void 0 ? _c : user.displayName) !== null && _d !== void 0 ? _d : null,
108
+ firstName: (_e = user.firstName) !== null && _e !== void 0 ? _e : null,
109
+ lastName: (_f = user.lastName) !== null && _f !== void 0 ? _f : null,
110
+ username: (_g = user.username) !== null && _g !== void 0 ? _g : null,
111
+ roles: ((_h = user.roles) !== null && _h !== void 0 ? _h : []).map((r) => { var _a; return (_a = r.name) !== null && _a !== void 0 ? _a : r; }),
112
+ groups: ((_j = user.groups) !== null && _j !== void 0 ? _j : []).map((g) => { var _a; return (_a = g.name) !== null && _a !== void 0 ? _a : g; }),
113
+ scopes: (_k = currentIdentity.scopes) !== null && _k !== void 0 ? _k : [],
114
+ workspace: workspaceId,
115
+ oauthClientId: (_l = currentIdentity.clientId) !== null && _l !== void 0 ? _l : null,
116
+ _hint: "Authenticated via OAuth user token. Roles and groups are fetched from IAM. Scopes come from the OAuth token. If a tool still returns 403, check both OAuth scopes and workspace IAM policies. Service-account remediation tools do not apply to user identities.",
117
+ }, null, 2),
118
+ }],
119
+ };
120
+ }
121
+ const ownClientId = currentIdentity === null || currentIdentity === void 0 ? void 0 : currentIdentity.clientId;
96
122
  const result = yield getSaClient().get("/", { params: { pageSize: 100 } });
97
- const accounts = (_c = (_b = (_a = result.data) === null || _a === void 0 ? void 0 : _a.data) !== null && _b !== void 0 ? _b : result.data) !== null && _c !== void 0 ? _c : [];
123
+ const accounts = (_p = (_o = (_m = result.data) === null || _m === void 0 ? void 0 : _m.data) !== null && _o !== void 0 ? _o : result.data) !== null && _p !== void 0 ? _p : [];
98
124
  const me = Array.isArray(accounts)
99
125
  ? accounts.find((sa) => sa.clientId === ownClientId)
100
126
  : null;
@@ -105,7 +131,7 @@ function registerServiceAccountTools(server, sdk, centraliUrl, workspaceId, ownC
105
131
  text: JSON.stringify({
106
132
  error: "Could not identify current service account",
107
133
  clientId: ownClientId,
108
- hint: "The service account may not have permission to list service accounts, or the clientId doesn't match any SA in this workspace.",
134
+ hint: "The service account may not have permission to list service accounts, or the clientId doesn't match any service account in this workspace.",
109
135
  }, null, 2),
110
136
  }],
111
137
  isError: true,
@@ -115,11 +141,13 @@ function registerServiceAccountTools(server, sdk, centraliUrl, workspaceId, ownC
115
141
  content: [{
116
142
  type: "text",
117
143
  text: JSON.stringify({
144
+ identityType: "service-account",
118
145
  id: me.id,
119
146
  clientId: me.clientId,
120
147
  name: me.name,
121
148
  description: me.description,
122
149
  revoked: me.revoked,
150
+ workspace: workspaceId,
123
151
  _hint: "Use this 'id' (numeric) with scan_service_account_permissions, simulate_service_account_permission, and generate_remediation to check or fix your own permissions.",
124
152
  }, null, 2),
125
153
  }],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@centrali-io/centrali-mcp",
3
- "version": "5.0.3",
3
+ "version": "5.1.0",
4
4
  "description": "Centrali MCP Server - AI assistant integration for Centrali workspaces",
5
5
  "main": "dist/index.js",
6
6
  "type": "commonjs",
package/src/index.ts CHANGED
@@ -75,7 +75,10 @@ async function main() {
75
75
  registerValidationTools(server, sdk);
76
76
  registerPageTools(server, sdk, baseUrl, workspaceId);
77
77
  registerAuthProviderTools(server, sdk, baseUrl, workspaceId);
78
- registerServiceAccountTools(server, sdk, baseUrl, workspaceId, clientId);
78
+ registerServiceAccountTools(server, sdk, baseUrl, workspaceId, {
79
+ clientId,
80
+ isServiceAccount: true,
81
+ });
79
82
  registerDescribeTools(server);
80
83
 
81
84
  // Register resources
@@ -78,8 +78,22 @@ function formatError(error: unknown, context: string): string {
78
78
  return `Error ${context}: ${error instanceof Error ? error.message : String(error)}`;
79
79
  }
80
80
 
81
- export function registerServiceAccountTools(server: McpServer, sdk: CentraliSDK, centraliUrl: string, workspaceId: string, ownClientId?: string) {
81
+ export interface CurrentIdentityContext {
82
+ clientId?: string;
83
+ userId?: string;
84
+ scopes?: string[];
85
+ isServiceAccount?: boolean;
86
+ }
87
+
88
+ export function registerServiceAccountTools(
89
+ server: McpServer,
90
+ sdk: CentraliSDK,
91
+ centraliUrl: string,
92
+ workspaceId: string,
93
+ currentIdentity?: CurrentIdentityContext,
94
+ ) {
82
95
  const getSaClient = () => createIamClient(sdk, centraliUrl, workspaceId, "service-accounts");
96
+ const getUsersClient = () => createIamClient(sdk, centraliUrl, workspaceId, "users");
83
97
  const getRolesClient = () => createIamClient(sdk, centraliUrl, workspaceId, "roles");
84
98
  const getGroupsClient = () => createIamClient(sdk, centraliUrl, workspaceId, "groups");
85
99
 
@@ -87,10 +101,37 @@ export function registerServiceAccountTools(server: McpServer, sdk: CentraliSDK,
87
101
 
88
102
  server.tool(
89
103
  "get_current_identity",
90
- "Get the current MCP service account's identity its numeric ID, clientId, name, roles, and groups. Call this first when you need to check or fix your own permissions (e.g., after a 403 error). Returns the SA details needed for scan_service_account_permissions and generate_remediation.",
104
+ "Get the current authenticated MCP identity. In stdio/service-account mode, returns the MCP service account. In hosted OAuth mode, fetches the authenticated user's profile, roles, and groups from IAM.",
91
105
  {},
92
106
  async () => {
93
107
  try {
108
+ if (currentIdentity?.userId && !currentIdentity.isServiceAccount) {
109
+ const meRes = await getUsersClient().get("/me");
110
+ const user = meRes.data;
111
+
112
+ return {
113
+ content: [{
114
+ type: "text",
115
+ text: JSON.stringify({
116
+ identityType: "user",
117
+ userId: user.id ?? currentIdentity.userId,
118
+ email: user.email ?? null,
119
+ name: user.name ?? user.displayName ?? null,
120
+ firstName: user.firstName ?? null,
121
+ lastName: user.lastName ?? null,
122
+ username: user.username ?? null,
123
+ roles: (user.roles ?? []).map((r: any) => r.name ?? r),
124
+ groups: (user.groups ?? []).map((g: any) => g.name ?? g),
125
+ scopes: currentIdentity.scopes ?? [],
126
+ workspace: workspaceId,
127
+ oauthClientId: currentIdentity.clientId ?? null,
128
+ _hint: "Authenticated via OAuth user token. Roles and groups are fetched from IAM. Scopes come from the OAuth token. If a tool still returns 403, check both OAuth scopes and workspace IAM policies. Service-account remediation tools do not apply to user identities.",
129
+ }, null, 2),
130
+ }],
131
+ };
132
+ }
133
+
134
+ const ownClientId = currentIdentity?.clientId;
94
135
  const result = await getSaClient().get("/", { params: { pageSize: 100 } });
95
136
  const accounts = result.data?.data ?? result.data ?? [];
96
137
  const me = Array.isArray(accounts)
@@ -104,7 +145,7 @@ export function registerServiceAccountTools(server: McpServer, sdk: CentraliSDK,
104
145
  text: JSON.stringify({
105
146
  error: "Could not identify current service account",
106
147
  clientId: ownClientId,
107
- hint: "The service account may not have permission to list service accounts, or the clientId doesn't match any SA in this workspace.",
148
+ hint: "The service account may not have permission to list service accounts, or the clientId doesn't match any service account in this workspace.",
108
149
  }, null, 2),
109
150
  }],
110
151
  isError: true,
@@ -115,11 +156,13 @@ export function registerServiceAccountTools(server: McpServer, sdk: CentraliSDK,
115
156
  content: [{
116
157
  type: "text",
117
158
  text: JSON.stringify({
159
+ identityType: "service-account",
118
160
  id: me.id,
119
161
  clientId: me.clientId,
120
162
  name: me.name,
121
163
  description: me.description,
122
164
  revoked: me.revoked,
165
+ workspace: workspaceId,
123
166
  _hint: "Use this 'id' (numeric) with scan_service_account_permissions, simulate_service_account_permission, and generate_remediation to check or fix your own permissions.",
124
167
  }, null, 2),
125
168
  }],