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
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。