successfactors-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| SF_HOST | Yes | SuccessFactors host, e.g. example.invalid. | |
| SF_USER_ID | Yes | Technical user; must equal the certificate's CN. | |
| RESULTS_DIR | No | Where MCP tools and scripts write payload files. | ./results |
| SF_TOKEN_URL | Yes | https://{SF_HOST}/oauth/token. | |
| SF_CLIENT_KEY | Yes | OAuth2 client API key from SF Admin Center. | |
| SF_COMPANY_ID | Yes | Default tenant/company ID. | |
| REQUEST_TIMEOUT | No | HTTP timeout in seconds. | 30 |
| TENANT_KEYS_DIR | No | Where per-tenant key+cert pairs are stored. | ./tenants |
| SF_ALLOWED_HOSTS | No | JSON list of extra hosts allowed for per-request connection overrides. | |
| SF_ODATA_VERSION | No | OData REST version. | v2 |
| SF_PRIVATE_KEY_PEM | No | Base64-encoded PEM of the RSA private key (single-tenant fallback). | |
| SF_PRIVATE_KEY_PATH | No | Path template with {company_id} placeholder to the RSA private key PEM file. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| list_tenantsA | List the SuccessFactors instances this server can reach. Call this first: the company_id values it returns are what the other tools
take as their |
| odata_metadataA | Fetch OData $metadata (EDMX) and reduce it to a compact field map. entity="" pulls the whole service metadata (large — hundreds of entity types); entity="EmpJob" pulls just that entity set. The full {entity: {field: attributes}} map is written to a JSON file, and a small map is returned inline as well, so two instances can be compared without ever loading raw EDMX into the conversation. When entity is given, its navigation properties (name, target entity type, filterable) are listed too — entity-scoped $metadata doesn't carry them, so this resolves them from the full service $metadata instead (fetched once per company_id per process, then cached); a lookup failure is reported as a warning and never blocks the field output above. Use the navigation names to scope filters into other entities via $filter (see the server's "Scope with EmpJob first" guidance and odata_query's docstring) instead of pulling whole entity sets and joining locally. On a v4 tenant, entity is a service path: its root for the whole service ("talent/cdp/Learning.svc/v1"), or root plus entity set for one (".../Learning.svc/v1/Items"); both read that service's $metadata. |
| compare_metadataA | Compare the OData configuration of two instances and return the drift. entity="EmpJob" compares one entity set; entity="" compares the whole service (v4: a service path, as in odata_metadata). The comparison runs here, not in the conversation: one instance's EmpJob metadata alone is ~40 KB, so diffing two of them in context is both expensive and easy to get wrong. Returns in_sync plus, per entity, the fields missing on either side and the
fields whose attributes differ, each as [value_in_a, value_in_b]. The |
| odata_queryA | Run an OData query, following next links until exhausted or max_pages. path is the entity set and may carry query options, e.g. "FOCompany" or
"EmpJob?$select=userId,jobCode" (v4 tenant: service root first,
"talent/cdp/Learning.svc/v1/Items") — those are parsed out of path and merged
into the request; pass options either way, but prefer When max_pages > 1 and no $orderby is given, one is added from the
entity's key properties (reported as
Records are written to a JSON file; the tool returns counts, the field names of the first record, and the path. preview accepts 0-20; values above zero return that many records inline only when their serialized UTF-8 size is at most 16 KiB. Otherwise, inspect the saved file locally. |
| ce_queryA | Query the EC Compound Employee (SOAP) API and save the payload to disk. person_id_external / user_id are comma-separated and take precedence over every other filter when set. last_modified_on is an ISO datetime for a delta pull (SAP allows at most 3 months of look-back). With no filter at all this is a full extract, capped by max_pages. CompoundEmployee SFQL allows only ONE condition on last_modified_on in the WHERE clause — a query with both a lower and an upper bound (last_modified_on>X and last_modified_on<=Y) fails with INVALID_SFQL: Only one condition is allowed. This tool only ever emits the lower bound; apply any upper bound to the returned rows client-side, not by adding a second last_modified_on condition. last_modified_on's filtering also depends on an SFQL parameter, isNotFirstQuery, that this tool does not currently set: per tenant testing, a query without isNotFirstQuery ignores last_modified_on entirely and returns a full snapshot of the matching window, while isNotFirstQuery=true makes last_modified_on act as a real delta filter. Until this tool exposes that parameter, treat last_modified_on here as a full-window snapshot, not a guaranteed delta — don't rely on it alone to mean "only changed rows". select_segments defaults to the widely supported COMMON_SEGMENTS. If SF answers INVALID_SFQL naming a segment, that module is not enabled on the tenant — pass a narrower list. Only documented segment names are accepted, and person_id_external / user_id values may contain only letters, digits, space and _ . @ : / + -. Each queryMore page is written as its own XML file. The tool returns counts and paths only: one employee's payload is ~80 KB of HR data. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 5 tools
Each tool targets a distinct stage: tenant discovery (list_tenants), schema inspection (odata_metadata), drift comparison (compare_metadata), and two query surfaces split by protocol (odata_query for OData, ce_query for SOAP Compound Employee). The two query tools could momentarily be confused as 'the query tool,' but descriptions make the API split explicit. Boundaries are otherwise clear.
All names are snake_case and group sensibly by API prefix (odata_*, ce_*), with metadata-related tools sharing the _metadata suffix. However, verb-based names (list_tenants, compare_metadata) mix with noun-based names (odata_query, ce_query, odata_metadata), so the pattern is readable but not a single uniform convention.
Five tools is well-scoped for a read-only SuccessFactors integration server: one for discovery, two for metadata handling, and two for the distinct query protocols. Every tool earns its place and none feels redundant or trivial.
The surface covers the full read-only workflow: find tenants, inspect metadata, diff metadata across tenants, and query both OData and Compound Employee APIs. Gaps are minor (no direct entity-set listing shortcut or write operations), but since the server appears intentionally read-only, no critical agent dead-end exists.