A TypeScript Model Context Protocol server for
SailPoint Identity Security Cloud, built on the official
SailPoint TypeScript SDK
(sailpoint-api-client).
Currently exposes one tool: search_identities.
npm install
npm run buildCredentials are read from SAIL_BASE_URL, SAIL_CLIENT_ID and
SAIL_CLIENT_SECRET. At startup the server loads them from .env in the
project root. Create a
personal access token in your tenant under Preferences → Personal Access
Tokens; it needs a role that can read identities (e.g. sp:scopes:all or
an admin/helpdesk role).
cp .env.example .env # then fill in your three values
chmod 600 .envThe server loads .env from its own project folder, so it works no matter which
directory the MCP client launches it from. Keep the file private: it is
gitignored, and chmod 600 .env makes it readable only by you. Variables set in
your shell or in an MCP client's env block take precedence over .env.
npm start # node dist/index.js — speaks MCP over stdioclaude mcp add sailpoint -- node /absolute/path/to/typescript-mcp-server/dist/index.js{
"mcpServers": {
"sailpoint": {
"command": "node",
"args": ["/absolute/path/to/sailpoint-mcp-server/dist/index.js"]
}
}
}Wraps POST /search/v1 (SearchApi.searchPostV1) against the identities
index with queryType: SAILPOINT.
| Parameter | Type | Default | Description |
|---|---|---|---|
query |
string |
— | Query-string syntax, e.g. attributes.department:Engineering |
limit |
number |
25 |
1–250 results |
offset |
number |
0 |
Paging offset |
sort |
string[] |
— | e.g. ["displayName", "-created"] |
attributes |
string[] |
— | Restrict returned fields (queryResultFilter.includes) to keep responses small |
includeNested |
boolean |
false |
Include nested access, accounts, apps objects |
count |
boolean |
false |
Also return the total match count from X-Total-Count |
Example query strings:
*
name:Aaron*
attributes.cloudLifecycleState:active AND attributes.country:US
@access(name:"Administrator")
Response is JSON text containing query, returned, offset, limit,
optional totalCount, and the identities array.
Errors (auth failures, bad queries) are returned as MCP tool errors with the HTTP status and response body, rather than crashing the server.
npm run typecheck # tsc --noEmit
npm run watch # incremental build
node smoke.js # handshake + tools/list + one live search_identities callsmoke.js requires working credentials for the tool call to succeed; the
handshake and tools/list portions work without them.
- The project is CommonJS:
sailpoint-api-clientis CJS-only and several of its value exports (Index,QueryType) are not reachable via ESM named imports. Those are imported fromsailpoint-api-client/dist/search/api, since the package root re-exports API classes but not the search enums. - All logging goes to stderr. The SDK writes diagnostics with
console.log, which would corrupt the JSON-RPC framing on stdout, so everyconsolechannel is redirected at startup (src/logger.ts).
Add a register* function under src/tools/ following
searchIdentities.ts, then call it from
src/index.ts. Reuse getSearchApi() — or add a sibling accessor
in src/sailpoint.ts for other SDK API classes — so the
resolved token is shared.