SF-MCP
Enables querying SAP SuccessFactors OData API metadata and managing Role-Based Permission (RBP) configurations. It provides tools for retrieving entity metadata, listing permission roles, and inspecting user-specific access rights through MCP-compatible clients.
README
SF-MCP: SAP SuccessFactors MCP Server
A secure Model Context Protocol (MCP) server providing 12 tools for querying and managing SAP SuccessFactors via OData APIs.
Overview
This MCP server enables Claude Desktop (or any MCP-compatible client) to interact with SAP SuccessFactors. It provides tools for configuration management, role-based permissions (RBP), data querying, and cross-instance comparison.
Features
Tools (12 total)
| Category | Tool | Description |
|---|---|---|
| Configuration | get_configuration |
Retrieve OData metadata for any entity |
| Configuration | list_entities |
Discover all available OData entities |
| Configuration | compare_configurations |
Compare entity config between instances |
| RBP Security | get_rbp_roles |
List all Role-Based Permission roles |
| RBP Security | get_role_permissions |
Get permissions for specific roles |
| RBP Security | get_user_permissions |
Get all permissions for a user |
| RBP Security | get_user_roles |
Get roles assigned to a user |
| RBP Security | get_permission_metadata |
Map UI labels to permission types |
| RBP Security | check_user_permission |
Check if user has specific permission |
| RBP Security | get_dynamic_groups |
List permission groups (dynamic groups) |
| Data Query | query_odata |
Flexible OData queries with filtering |
| Data Validation | get_picklist_values |
Get dropdown/picklist options |
Security Features
- Input Validation: Regex-based validation prevents OData injection attacks
- XXE Protection: Uses
defusedxmllibrary for safe XML parsing - Audit Logging: JSON-structured logs compatible with Cloud Logging
- Secret Manager: GCP Secret Manager integration for credential storage
- Credential Flexibility: Pass credentials per-request or use environment defaults
Prerequisites
- Python 3.10 or higher
- uv package manager
- SAP SuccessFactors account with API access
Installation
-
Clone or download this repository
-
Install dependencies
cd sf-mcp uv sync -
Configure credentials
Credentials can be provided in three ways (in order of precedence):
- Per-request parameters:
auth_user_idandauth_passwordon each tool call - Environment variables:
SF_USER_IDandSF_PASSWORD - GCP Secret Manager: Secrets named
sf-user-idandsf-password
Variable Required Description SF_USER_IDYes* Your SuccessFactors user ID (without @instance) SF_PASSWORDYes* Your SuccessFactors password SF_API_HOSTNo API host (defaults to api55preview.sapsf.eu)*Required unless using per-request credentials or Secret Manager
- Per-request parameters:
Usage
Running with MCP Dev Server
For development and testing:
uv run mcp dev main.py
Running Standalone
uv run main.py
Claude Desktop Integration
Add to your Claude Desktop configuration:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"sf-mcp": {
"command": "/path/to/uv",
"args": [
"--directory",
"/path/to/sf-mcp",
"run",
"main.py"
],
"env": {
"SF_USER_ID": "your_user_id",
"SF_PASSWORD": "your_password"
}
}
}
}
For Cloud Run deployment:
{
"mcpServers": {
"sf-mcp": {
"url": "https://sf-mcp-xxxxx-uc.a.run.app/mcp"
}
}
}
Tool Reference
Configuration Tools
get_configuration
Retrieves OData metadata for a specified SuccessFactors entity.
| Parameter | Type | Required | Description |
|---|---|---|---|
instance |
string | Yes | SuccessFactors company ID |
entity |
string | Yes | OData entity name (e.g., "User", "Position") |
environment |
string | No | "preview" or "production" (default: preview) |
auth_user_id |
string | No | Override default credentials |
auth_password |
string | No | Override default credentials |
Example:
Get the configuration metadata for the "User" entity in instance "mycompany"
list_entities
Discover all available OData entities in an instance.
| Parameter | Type | Required | Description |
|---|---|---|---|
instance |
string | Yes | SuccessFactors company ID |
category |
string | No | Filter: "foundation", "employee", "talent", "platform", or "all" |
environment |
string | No | "preview" or "production" (default: preview) |
auth_user_id |
string | No | Override default credentials |
auth_password |
string | No | Override default credentials |
Response:
{
"entities": ["User", "Position", "EmpEmployment", ...],
"count": 150,
"total_available": 500,
"by_category": {
"foundation": 85,
"employee": 120,
"talent": 45,
"platform": 30,
"other": 220
}
}
compare_configurations
Compare entity configuration between two instances (e.g., dev vs prod).
| Parameter | Type | Required | Description |
|---|---|---|---|
instance1 |
string | Yes | First instance (e.g., dev) |
instance2 |
string | Yes | Second instance (e.g., prod) |
entity |
string | Yes | Entity to compare |
environment1 |
string | No | Environment for instance1 (default: preview) |
environment2 |
string | No | Environment for instance2 (default: production) |
auth_user_id |
string | No | Override default credentials |
auth_password |
string | No | Override default credentials |
Response:
{
"entity": "User",
"comparison": {
"fields_only_in_instance1": ["customField1"],
"fields_only_in_instance2": ["customField2"],
"fields_in_both": 45,
"type_differences": [],
"match_percentage": 95.5
},
"summary": {
"is_identical": false,
"differences_found": 2
}
}
RBP Security Tools
get_rbp_roles
Lists all Role-Based Permission roles.
| Parameter | Type | Required | Description |
|---|---|---|---|
instance |
string | Yes | SuccessFactors company ID |
include_description |
boolean | No | Include role descriptions (default: false) |
environment |
string | No | "preview" or "production" (default: preview) |
auth_user_id |
string | No | Override default credentials |
auth_password |
string | No | Override default credentials |
get_role_permissions
Gets permissions assigned to specific RBP roles. Supports multiple role IDs.
| Parameter | Type | Required | Description |
|---|---|---|---|
instance |
string | Yes | SuccessFactors company ID |
role_ids |
string | Yes | Single ID or comma-separated: "10" or "10,20,30" |
locale |
string | No | Locale for labels (default: en-US) |
environment |
string | No | "preview" or "production" (default: preview) |
auth_user_id |
string | No | Override default credentials |
auth_password |
string | No | Override default credentials |
get_user_permissions
Gets all permissions for specific users based on their assigned roles.
| Parameter | Type | Required | Description |
|---|---|---|---|
instance |
string | Yes | SuccessFactors company ID |
user_ids |
string | Yes | Single ID or comma-separated: "admin" or "admin,user2" |
locale |
string | No | Locale for labels (default: en-US) |
environment |
string | No | "preview" or "production" (default: preview) |
auth_user_id |
string | No | Override default credentials |
auth_password |
string | No | Override default credentials |
get_user_roles
Gets all RBP roles assigned to a specific user.
| Parameter | Type | Required | Description |
|---|---|---|---|
instance |
string | Yes | SuccessFactors company ID |
user_id |
string | Yes | User ID to look up roles for |
include_permissions |
boolean | No | Also fetch permissions for each role (default: false) |
environment |
string | No | "preview" or "production" (default: preview) |
auth_user_id |
string | No | Override default credentials |
auth_password |
string | No | Override default credentials |
Response:
{
"user_id": "admin",
"roles": [
{"roleId": "10", "roleName": "Administrator", "roleDesc": "Full access"},
{"roleId": "20", "roleName": "HR Manager", "roleDesc": "HR functions"}
],
"role_count": 2
}
get_permission_metadata
Maps UI labels to permission types and values.
| Parameter | Type | Required | Description |
|---|---|---|---|
instance |
string | Yes | SuccessFactors company ID |
locale |
string | No | Locale for labels (default: en-US) |
environment |
string | No | "preview" or "production" (default: preview) |
auth_user_id |
string | No | Override default credentials |
auth_password |
string | No | Override default credentials |
check_user_permission
Check if a user has a specific permission for a target user.
| Parameter | Type | Required | Description |
|---|---|---|---|
instance |
string | Yes | SuccessFactors company ID |
access_user_id |
string | Yes | User whose permission to check |
target_user_id |
string | Yes | Target user of the permission |
perm_type |
string | Yes | Permission type from metadata |
perm_string_value |
string | Yes | Permission string value |
perm_long_value |
string | No | Permission long value (default: -1L) |
environment |
string | No | "preview" or "production" (default: preview) |
auth_user_id |
string | No | Override default credentials |
auth_password |
string | No | Override default credentials |
get_dynamic_groups
Lists dynamic groups (permission groups) used in RBP rules.
| Parameter | Type | Required | Description |
|---|---|---|---|
instance |
string | Yes | SuccessFactors company ID |
group_type |
string | No | Filter by group type |
environment |
string | No | "preview" or "production" (default: preview) |
auth_user_id |
string | No | Override default credentials |
auth_password |
string | No | Override default credentials |
Data Query Tools
query_odata
Execute flexible OData queries against any SuccessFactors entity.
| Parameter | Type | Required | Description |
|---|---|---|---|
instance |
string | Yes | SuccessFactors company ID |
entity |
string | Yes | Entity name or entity with key: "User" or "User('admin')" |
select |
string | No | Fields to return: "userId,firstName,lastName" |
filter |
string | No | OData filter: "status eq 'active'" |
expand |
string | No | Navigation properties: "empInfo,jobInfoNav" |
top |
integer | No | Max records (default: 100, max: 1000) |
skip |
integer | No | Records to skip for pagination |
orderby |
string | No | Sort: "lastName asc" or "hireDate desc" |
environment |
string | No | "preview" or "production" (default: preview) |
auth_user_id |
string | No | Override default credentials |
auth_password |
string | No | Override default credentials |
Examples:
# Get active users
entity="User", filter="status eq 'active'", select="userId,firstName,lastName"
# Get single user with expanded info
entity="User('admin')", expand="empInfo"
# Paginate through positions
entity="Position", top=100, skip=100
Response:
{
"entity": "User",
"results": [...],
"count": 100,
"next_skip": 200
}
Data Validation Tools
get_picklist_values
Get all values for a specific picklist (dropdown options).
| Parameter | Type | Required | Description |
|---|---|---|---|
instance |
string | Yes | SuccessFactors company ID |
picklist_id |
string | Yes | Picklist ID: "ecJobFunction", "nationality" |
locale |
string | No | Locale for labels (default: en-US) |
include_inactive |
boolean | No | Include inactive values (default: false) |
environment |
string | No | "preview" or "production" (default: preview) |
auth_user_id |
string | No | Override default credentials |
auth_password |
string | No | Override default credentials |
Common Picklists:
ecJobFunction- Job functionsecJobCode- Job codesecPayGrade- Pay gradesecDepartment- Departmentsnationality- Countries/nationalitiesmaritalStatus- Marital status options
Response:
{
"picklist_id": "nationality",
"locale": "en-US",
"values": [
{"id": "US", "externalCode": "US", "label": "United States", "status": "active"},
{"id": "UK", "externalCode": "UK", "label": "United Kingdom", "status": "active"}
],
"count": 195,
"has_inactive": true
}
Common SuccessFactors Entities
| Category | Entities |
|---|---|
| Employee | User, EmpEmployment, EmpJob, PerPersonal, PerPhone, PerEmail |
| Foundation | FOCompany, FODepartment, FOJobCode, FOLocation, FOPayGrade |
| Position | Position, PositionEntity, PositionMatrixRelationship |
| Talent | Goal, GoalPlan, PerformanceReview, Competency |
| Recruiting | JobRequisition, Candidate, JobApplication |
Use list_entities to discover all available entities in your instance.
Cloud Deployment (Google Cloud Run)
Prerequisites
- Google Cloud account with billing enabled
- Google Cloud CLI installed
Deploy with Secret Manager (Recommended)
# Set project
export PROJECT_ID=your-gcp-project-id
gcloud config set project $PROJECT_ID
# Enable required APIs
gcloud services enable secretmanager.googleapis.com run.googleapis.com
# Create secrets
echo -n "your_user_id" | gcloud secrets create sf-user-id --data-file=-
echo -n "your_password" | gcloud secrets create sf-password --data-file=-
# Grant access to Cloud Run service account
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
gcloud secrets add-iam-policy-binding sf-user-id \
--member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
gcloud secrets add-iam-policy-binding sf-password \
--member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
# Build and deploy
gcloud builds submit --tag gcr.io/$PROJECT_ID/sf-mcp
gcloud run deploy sf-mcp \
--image gcr.io/$PROJECT_ID/sf-mcp \
--platform managed \
--region us-central1 \
--set-env-vars "GCP_PROJECT_ID=$PROJECT_ID"
Local Testing with Docker
# Build the image
docker build -t sf-mcp .
# Run locally
docker run -p 8080:8080 \
-e SF_USER_ID=your_user \
-e SF_PASSWORD=your_pass \
sf-mcp
# Test endpoint
curl http://localhost:8080/mcp
Project Structure
sf-mcp/
├── main.py # MCP server with 12 tools
├── pyproject.toml # Project dependencies
├── uv.lock # Dependency lock file
├── Dockerfile # Container image for Cloud Run
├── .env # Local credentials (gitignored)
├── .gitignore # Git ignore rules
└── README.md # This documentation
Dependencies
fastmcp>=2.0.0- Model Context Protocol SDKrequests>=2.31.0- HTTP client librarydefusedxml>=0.7.0- Safe XML parsing (XXE protection)python-dotenv>=1.0.0- Environment variable loaderuvicorn>=0.30.0- ASGI server for HTTP transport
Troubleshooting
Authentication Errors (HTTP 401)
- Verify credentials format: user ID without @instance
- Check password is correct
- Ensure API user has proper permissions in SuccessFactors
Validation Errors
The server validates all inputs to prevent injection attacks. If you see validation errors:
instance: Must contain only alphanumeric, underscores, hyphensentity: Must be valid OData entity namefilter: Cannot contain blocked keywords ($batch, $metadata, script tags)locale: Must be format like "en-US" or "de"
Server Disconnected
- Verify
uvpath in config is correct - Check logs:
tail -f ~/Library/Logs/Claude/mcp*.log - Test manually:
uv run mcp dev main.py
Security Considerations
- Input Validation: All parameters validated with regex patterns
- XXE Protection: XML parsing uses defusedxml library
- Audit Logging: All tool invocations logged in JSON format
- Secret Manager: Production credentials stored in GCP Secret Manager
- No Hardcoded Secrets: Credentials from environment or parameters only
- Minimal Permissions: Use dedicated API user with required permissions only
License
MIT License
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
E2B
Using MCP to run code via e2b.