SuccessFactors-MCP
SAP SuccessFactors Model Context Protocol Server
Installation ·
Quick Start ·
43 Tools ·
Deployment ·
API Reference
A production-grade Model Context Protocol server that connects Claude (or any MCP client) to SAP SuccessFactors via OData APIs. Query employee data, manage permissions, run compliance reports, and administer HR operations — all through natural language.
You: "Who on the Engineering team has a work anniversary this month?"
Claude: [calls get_anniversary_employees] Found 3 upcoming anniversaries...
- Jane Smith (5 years - milestone!) - March 12
- Bob Johnson (2 years) - March 18
- Alice Chen (10 years - milestone!) - March 25
Why SF-MCP?
| Challenge |
SF-MCP Solution |
| SAP SuccessFactors APIs are complex and verbose |
43 purpose-built tools with clean interfaces |
| Building OData queries requires deep SF knowledge |
Natural language — ask Claude in plain English |
| Security concerns with API access |
Per-request auth, input validation, audit logging |
| Managing multiple SF instances |
21 data centers supported, cross-instance comparison |
| API rate limits and performance |
Connection pooling, response caching, rate limiting |
Tools
43 tools organized across 13 categories:
Configuration & Discovery (3 tools)
| Tool |
Description |
get_configuration |
Retrieve OData metadata for any entity |
list_entities |
Discover all available OData entities |
compare_configurations |
Compare entity config between two instances |
RBP Security (7 tools)
| Tool |
Description |
get_rbp_roles |
List all Role-Based Permission roles |
get_role_permissions |
Get permissions for specific roles |
get_user_permissions |
Get all permissions for a user |
get_user_roles |
Get roles assigned to a user |
get_permission_metadata |
Map UI labels to permission types |
check_user_permission |
Check if user has specific permission |
get_dynamic_groups |
List permission groups (dynamic groups) |
RBP Audit (2 tools)
| Tool |
Description |
get_role_history |
View modification history for roles |
get_role_assignment_history |
View history of role assignments |
Data Query (2 tools)
| Tool |
Description |
query_odata |
Flexible OData queries with filtering, pagination |
get_picklist_values |
Get dropdown/picklist options |
Employee Lookup (4 tools)
| Tool |
Description |
get_employee_profile |
Complete profile with job info, manager, optional compensation |
search_employees |
Find by name, department, location, or manager |
get_employee_history |
Job history — promotions, transfers, title changes |
get_team_roster |
Manager's team with direct/indirect reports |
Time Off (3 tools)
| Tool |
Description |
get_time_off_balances |
Vacation, PTO, sick leave balances |
get_upcoming_time_off |
Team absence calendar for a date range |
get_time_off_requests |
Pending/approved time-off requests |
Hiring & Onboarding (3 tools)
| Tool |
Description |
get_open_requisitions |
Job requisitions with status and hiring manager |
get_candidate_pipeline |
Candidates by stage for a requisition |
get_new_hires |
Recent/upcoming hires for onboarding |
Compliance & Reporting (3 tools)
| Tool |
Description |
get_terminations |
Terminated employees for exit processing |
get_employees_missing_data |
Incomplete profiles for compliance audits |
get_anniversary_employees |
Upcoming work anniversaries for recognition |
Performance & Compensation (2 tools)
| Tool |
Description |
get_performance_review_status |
Review form completion across the org |
get_compensation_details |
Pay breakdown with recurring/non-recurring components |
Position Management (3 tools)
| Tool |
Description |
get_position_details |
Position with incumbent, department, FTE |
get_vacant_positions |
Open positions for headcount planning |
get_org_chart |
Org hierarchy from any position (up or down) |
MDF Objects (3 tools)
| Tool |
Description |
get_mdf_object_definitions |
List custom MDF objects and their fields |
query_mdf_object |
Query any MDF/generic object (cust_*) |
get_foundation_objects |
Query foundation objects (departments, cost centers, etc.) |
Workflow (2 tools)
| Tool |
Description |
get_pending_approvals |
Pending workflow items for a user or globally |
get_workflow_history |
Audit trail of approval steps |
Monitoring & Admin (6 tools)
| Tool |
Description |
get_alert_notifications |
System alerts and notifications |
get_scheduled_job_status |
Scheduled job run status |
get_integration_center_jobs |
Integration Center job status |
get_api_quota_status |
Rate limit usage per instance |
get_cache_status |
Cache hit rates and entry counts |
clear_cache |
Clear cached responses |
Installation
Prerequisites
- Python 3.10+
- uv package manager
- SAP SuccessFactors account with API access
Setup
git clone https://github.com/aiadiguru2025/sf-mcp.git
cd sf-mcp
uv sync
Quick Start
Development mode (MCP Inspector):
uv run mcp dev main.py
Stdio mode (Claude Desktop):
uv run main.py
HTTP mode (Cloud Run / remote):
PORT=8080 uv run main.py
Claude Desktop Integration
Step 1 — Find the path to uv
# macOS / Linux
which uv
# Windows (PowerShell)
Get-Command uv | Select-Object -ExpandProperty Source
Step 2 — Edit your Claude Desktop config
| OS |
Config path |
| macOS |
~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows |
%APPDATA%\Claude\claude_desktop_config.json |
Add the sf-mcp server:
{
"mcpServers": {
"sf-mcp": {
"command": "/path/to/uv",
"args": ["--directory", "/path/to/sf-mcp", "run", "main.py"]
}
}
}
Step 3 — Restart Claude Desktop
The MCP tools icon (hammer) will appear in the input area with all 43 tools available.
Note: Credentials (auth_user_id and auth_password) are provided on each tool call — nothing is stored in the config.
Deployment
Google Cloud Run
# Build and deploy
export PROJECT_ID=your-gcp-project-id
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
Then point Claude Desktop to the remote URL:
{
"mcpServers": {
"sf-mcp": {
"url": "https://sf-mcp-xxxxx-uc.a.run.app/mcp"
}
}
}
Docker (local)
docker build -t sf-mcp .
docker run -p 8080:8080 sf-mcp
API Key Protection (optional)
Set MCP_API_KEY to require authentication on the HTTP endpoint:
MCP_API_KEY=your-secret-key PORT=8080 uv run main.py
Clients must then include X-API-Key: your-secret-key in requests.
Configuration
All tool parameters (data_center, environment, auth_user_id, auth_password) are provided per-request. Server-side environment variables are optional:
Rate Limiting
| Variable |
Default |
Description |
SF_RATE_LIMIT |
100 |
Max requests per window per instance |
SF_RATE_LIMIT_WINDOW |
60 |
Window duration in seconds |
SF_RATE_LIMIT_WARN_THRESHOLD |
0.8 |
Log warning at 80% usage |
SF_RATE_LIMIT_RETRY_AFTER |
5 |
Seconds to wait on 429 retry |
SF_RATE_LIMIT_MAX_RETRIES |
3 |
Max 429 retry attempts |
Response Caching
| Variable |
Default |
Description |
SF_CACHE_TTL_METADATA |
3600 |
Metadata cache TTL (1 hour) |
SF_CACHE_TTL_SERVICE_DOC |
3600 |
Service doc cache TTL (1 hour) |
SF_CACHE_TTL_PICKLIST |
1800 |
Picklist cache TTL (30 min) |
SF_CACHE_TTL_PERMISSIONS |
3600 |
Permission cache TTL (1 hour) |
SF_CACHE_TTL_DEFAULT |
0 |
Default TTL (0 = disabled) |
SF_CACHE_MAX_ENTRIES |
1000 |
Max cache entries before eviction |
Endpoint Protection
| Variable |
Default |
Description |
MCP_API_KEY |
(none) |
API key for HTTP endpoint auth |
Copy .env.example to .env to customize:
cp .env.example .env
Supported Data Centers
21 data centers across 6 continents with alias support:
| Data Center |
Alias |
Location |
Environments |
| DC2 |
DC57 |
Netherlands |
preview, production, sales_demo |
| DC4 |
DC68 |
Virginia, US |
preview, production, sales_demo |
| DC8 |
DC70 |
Ashburn, Virginia, US |
preview, production, sales_demo |
| DC10 |
DC66 |
Sydney, Australia |
preview, production |
| DC12 |
DC33 |
Germany |
preview, production |
| DC15 |
DC30 |
Shanghai, China |
preview, production |
| DC17 |
DC60 |
Toronto, Canada |
preview, production |
| DC19 |
DC62 |
Sao Paulo, Brazil |
preview, production |
| DC22 |
— |
Dubai, UAE |
preview, production |
| DC23 |
DC84 |
Riyadh, Saudi Arabia |
preview, production |
| DC40 |
— |
— |
sales_demo |
| DC41 |
— |
Virginia, US |
preview, production |
| DC44 |
DC52 |
Singapore |
preview, production |
| DC47 |
— |
Canada Central |
preview, production |
| DC50 |
— |
Tokyo, Japan |
preview, production |
| DC55 |
— |
Frankfurt, Germany |
preview, production |
| DC74 |
— |
Zurich, Switzerland |
preview, production |
| DC80 |
— |
Mumbai, India |
preview, production |
| DC82 |
— |
Riyadh, Saudi Arabia |
preview, production |
Architecture
sf-mcp/
├── main.py # Entry point (stdio + HTTP modes)
├── sf_mcp/
│ ├── server.py # FastMCP instance
│ ├── config.py # DC mappings, constants, env vars
│ ├── auth.py # Credential resolution, API key middleware
│ ├── client.py # HTTP client (OData, metadata, service doc, pagination)
│ ├── cache.py # TTL-based response cache with deep-copy safety
│ ├── rate_limiter.py # Sliding-window rate limiter (per-instance)
│ ├── validation.py # 10 input validators with registry pattern
│ ├── decorators.py # sf_tool decorator (cross-cutting concerns)
│ ├── dependencies.py # FastMCP DI for schema exclusion
│ ├── logging_config.py # Cloud Logging JSON formatter, audit_log()
│ ├── xml_utils.py # Safe XML parsing (defusedxml), SAP date parsing
│ └── tools/ # 43 tools across 13 modules
│ ├── configuration.py # get_configuration, compare_configurations, list_entities
│ ├── permissions.py # 7 RBP security tools
│ ├── audit.py # Role history, role assignment history
│ ├── query.py # query_odata, get_picklist_values
│ ├── employee.py # Profile, search, history, team roster
│ ├── time_off.py # Balances, upcoming absences, requests
│ ├── recruiting.py # Requisitions, pipeline, new hires
│ ├── compliance.py # Terminations, missing data, anniversaries, reviews, comp
│ ├── position.py # Position details, vacancies, org chart
│ ├── workflow.py # Pending approvals, workflow history
│ ├── mdf.py # MDF object definitions, queries, foundation objects
│ ├── monitoring.py # Alerts, scheduled jobs, integration jobs
│ ├── admin.py # Rate limit quota, cache status, cache clear
│ └── utils.py # Shared utilities (display_name)
├── tests/ # 110 tests
├── Dockerfile # Cloud Run container
├── .env.example # Configuration template
└── pyproject.toml # Project metadata, dependencies, linter config
Design Principles
Zero boilerplate — The sf_tool decorator handles request ID generation, timing, audit logging, input validation, credential checking, error handling, and $top clamping. Tool functions contain only business logic.
Secure by default — 10 input validators (regex allowlists), OData injection prevention, XXE-safe XML parsing (defusedxml), timing-safe API key comparison (hmac.compare_digest), and automatic credential masking in logs.
Production-ready — Connection pooling (requests.Session), mutation-safe response caching (deep-copy on put/get), sliding-window rate limiting with automatic 429 retry, and Cloud Logging-compatible JSON audit trail.
Schema-clean — Internal parameters (request_id, start_time, api_host) are hidden from the MCP tool schema via FastMCP's Dependency injection, keeping tool interfaces clean for LLM consumers.
Security
| Layer |
Mechanism |
| Input validation |
10 regex-based validators; OData filter blocklist checks raw + URL-decoded + double-decoded input |
| Injection prevention |
Entity paths, $select, $orderby, $filter, $expand all validated; control characters rejected |
| Authentication |
Per-request credentials (never stored); timing-safe API key comparison via hmac.compare_digest |
| XML safety |
defusedxml prevents XXE, entity expansion, and DTD attacks |
| Audit logging |
Every tool call logged with structured JSON; passwords automatically masked |
| Cache safety |
Deep-copied on store and retrieval to prevent mutation bugs |
| Date handling |
All SAP timestamp parsing uses explicit UTC to prevent timezone inconsistencies |
Testing
# Run all 110 tests
uv run pytest tests/ -v
# Run with coverage
uv run pytest tests/ --cov=sf_mcp
# Lint
uv run ruff check .
# Type check
uv run mypy sf_mcp/
Test coverage includes:
- Config — DC mapping resolution, case insensitivity, aliases, error cases
- Validation — All 10 validators with valid/invalid inputs, injection prevention
- Client — Mocked HTTP responses (200, 401, 500, empty, connection error)
- Rate limiter — Limit enforcement, sliding window, per-instance isolation, thread safety
- Cache — Put/get, TTL expiry, category TTLs, invalidation, eviction, deep-copy safety
- Pagination — Single/multi page, max_pages limit, error handling, $skip increments
- Decorators — Value injection, validation errors, max_top clamping, exception handling
API Reference
Every tool accepts these common parameters:
| Parameter |
Type |
Required |
Description |
instance |
string |
Yes |
SuccessFactors company ID |
data_center |
string |
Yes |
SAP data center code (e.g., DC55, DC10) |
environment |
string |
Yes |
preview, production, or sales_demo |
auth_user_id |
string |
Yes |
SuccessFactors user ID (without @instance) |
auth_password |
string |
Yes |
SuccessFactors password |
Configuration Tools
get_configuration
Retrieve OData metadata for a SuccessFactors entity.
| Parameter |
Type |
Required |
Description |
entity |
string |
Yes |
OData entity name (e.g., User, Position) |
list_entities
Discover all available OData entities in an instance.
| Parameter |
Type |
Required |
Description |
category |
string |
No |
foundation, employee, talent, platform, or all |
compare_configurations
Compare entity config between two instances (e.g., dev vs prod).
| Parameter |
Type |
Required |
Description |
instance1 |
string |
Yes |
First instance |
instance2 |
string |
Yes |
Second instance |
entity |
string |
Yes |
Entity to compare |
data_center1 |
string |
Yes |
Data center for instance1 |
environment1 |
string |
Yes |
Environment for instance1 |
data_center2 |
string |
Yes |
Data center for instance2 |
environment2 |
string |
Yes |
Environment for instance2 |
RBP Security Tools
get_rbp_roles
| Parameter |
Type |
Required |
Description |
include_description |
boolean |
No |
Include role descriptions (default: false) |
get_role_permissions
| Parameter |
Type |
Required |
Description |
role_ids |
string |
Yes |
Single or comma-separated: 10 or 10,20,30 |
locale |
string |
No |
Locale for labels (default: en-US) |
get_user_permissions
| Parameter |
Type |
Required |
Description |
user_ids |
string |
Yes |
Single or comma-separated: admin or admin,user2 |
locale |
string |
No |
Locale for labels (default: en-US) |
get_user_roles
| Parameter |
Type |
Required |
Description |
user_id |
string |
Yes |
User ID to look up roles for |
include_permissions |
boolean |
No |
Also fetch permissions per role (default: false) |
get_permission_metadata
| Parameter |
Type |
Required |
Description |
locale |
string |
No |
Locale for labels (default: en-US) |
check_user_permission
| Parameter |
Type |
Required |
Description |
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) |
get_dynamic_groups
| Parameter |
Type |
Required |
Description |
group_type |
string |
No |
Filter by group type |
RBP Audit Tools
get_role_history
| Parameter |
Type |
Required |
Description |
role_id |
string |
No |
Filter by role ID |
role_name |
string |
No |
Filter by role name |
from_date |
string |
No |
Start date (YYYY-MM-DD) |
to_date |
string |
No |
End date (YYYY-MM-DD) |
top |
integer |
No |
Max records (default: 100, max: 500) |
get_role_assignment_history
| Parameter |
Type |
Required |
Description |
role_id |
string |
No |
Filter by role ID |
user_id |
string |
No |
Filter by user ID |
from_date |
string |
No |
Start date (YYYY-MM-DD) |
to_date |
string |
No |
End date (YYYY-MM-DD) |
top |
integer |
No |
Max records (default: 100, max: 500) |
At least one of role_id or user_id is required.
Data Query Tools
query_odata
| Parameter |
Type |
Required |
Description |
entity |
string |
Yes |
Entity name or key: User or User('admin') |
select |
string |
No |
Fields: userId,firstName,lastName |
filter |
string |
No |
OData filter: status eq 'active' |
expand |
string |
No |
Nav properties: empInfo,jobInfoNav |
top |
integer |
No |
Max records (default: 100, max: 1000) |
skip |
integer |
No |
Records to skip |
orderby |
string |
No |
Sort: lastName asc |
paginate |
boolean |
No |
Auto-fetch all pages (default: false) |
max_pages |
integer |
No |
Max pages when paginating (default: 10, max: 50) |
get_picklist_values
| Parameter |
Type |
Required |
Description |
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) |
Employee Lookup Tools
get_employee_profile
| Parameter |
Type |
Required |
Description |
user_id |
string |
Yes |
Employee user ID |
include_compensation |
boolean |
No |
Include compensation (default: false) |
search_employees
| Parameter |
Type |
Required |
Description |
search_text |
string |
No |
Partial name search |
department |
string |
No |
Filter by department |
location |
string |
No |
Filter by location |
manager_id |
string |
No |
Filter to manager's reports |
status |
string |
No |
active, inactive, or all (default: active) |
top |
integer |
No |
Max results (default: 50, max: 200) |
get_employee_history
| Parameter |
Type |
Required |
Description |
user_id |
string |
Yes |
Employee user ID |
include_compensation_changes |
boolean |
No |
Include salary history (default: false) |
get_team_roster
| Parameter |
Type |
Required |
Description |
manager_id |
string |
Yes |
Manager's user ID |
include_indirect_reports |
boolean |
No |
Include reports-of-reports (default: false) |
top |
integer |
No |
Max direct reports (default: 100, max: 200) |
Time Off Tools
get_time_off_balances
| Parameter |
Type |
Required |
Description |
user_ids |
string |
Yes |
Comma-separated user IDs (max 50) |
as_of_date |
string |
No |
Balance as of date (YYYY-MM-DD) |
get_upcoming_time_off
| Parameter |
Type |
Required |
Description |
start_date |
string |
Yes |
Range start (YYYY-MM-DD) |
end_date |
string |
Yes |
Range end (YYYY-MM-DD) |
department |
string |
No |
Filter by department |
manager_id |
string |
No |
Filter to manager's team |
status |
string |
No |
approved, pending, or all (default: approved) |
top |
integer |
No |
Max results (default: 200, max: 500) |
get_time_off_requests
| Parameter |
Type |
Required |
Description |
user_id |
string |
No |
Filter to employee |
status |
string |
No |
pending, approved, rejected, cancelled, or all (default: pending) |
from_date |
string |
No |
Submitted after date (YYYY-MM-DD) |
top |
integer |
No |
Max results (default: 50, max: 200) |
Hiring & Onboarding Tools
get_open_requisitions
| Parameter |
Type |
Required |
Description |
department |
string |
No |
Filter by department |
hiring_manager_id |
string |
No |
Filter by hiring manager |
location |
string |
No |
Filter by location |
status |
string |
No |
open, filled, closed, or all (default: open) |
top |
integer |
No |
Max results (default: 100, max: 500) |
get_candidate_pipeline
| Parameter |
Type |
Required |
Description |
requisition_id |
string |
Yes |
Job requisition ID |
include_rejected |
boolean |
No |
Include rejected candidates (default: false) |
top |
integer |
No |
Max results (default: 100, max: 500) |
get_new_hires
| Parameter |
Type |
Required |
Description |
start_date_from |
string |
Yes |
Hires on/after date (YYYY-MM-DD) |
start_date_to |
string |
Yes |
Hires on/before date (YYYY-MM-DD) |
department |
string |
No |
Filter by department |
top |
integer |
No |
Max results (default: 100, max: 500) |
Compliance & Reporting Tools
get_terminations
| Parameter |
Type |
Required |
Description |
from_date |
string |
Yes |
Range start (YYYY-MM-DD) |
to_date |
string |
Yes |
Range end (YYYY-MM-DD) |
department |
string |
No |
Filter by department |
top |
integer |
No |
Max results (default: 100, max: 500) |
get_employees_missing_data
| Parameter |
Type |
Required |
Description |
check_fields |
string |
Yes |
Comma-separated: email, phone, address, emergency_contact |
department |
string |
No |
Filter by department |
top |
integer |
No |
Max results (default: 100, max: 500) |
get_anniversary_employees
| Parameter |
Type |
Required |
Description |
from_date |
string |
Yes |
Range start (YYYY-MM-DD) |
to_date |
string |
Yes |
Range end (YYYY-MM-DD) |
milestone_years_only |
boolean |
No |
Only 1, 5, 10, 15, 20, 25+ years (default: false) |
department |
string |
No |
Filter by department |
top |
integer |
No |
Max results (default: 100, max: 500) |
Performance & Compensation Tools
get_performance_review_status
| Parameter |
Type |
Required |
Description |
form_template_id |
string |
No |
Filter by form template |
department |
string |
No |
Filter by department |
manager_id |
string |
No |
Filter by manager |
status |
string |
No |
not_started, in_progress, completed, or "" for all |
top |
integer |
No |
Max results (default: 100, max: 500) |
get_compensation_details
| Parameter |
Type |
Required |
Description |
user_ids |
string |
Yes |
Comma-separated user IDs (max 20) |
effective_date |
string |
No |
Compensation as of date (YYYY-MM-DD) |
Position Management Tools
get_position_details
| Parameter |
Type |
Required |
Description |
position_id |
string |
Yes |
Position ID |
get_vacant_positions
| Parameter |
Type |
Required |
Description |
department |
string |
No |
Filter by department |
location |
string |
No |
Filter by location |
top |
integer |
No |
Max results (default: 100, max: 500) |
get_org_chart
| Parameter |
Type |
Required |
Description |
position_id |
string |
Yes |
Starting position ID |
direction |
string |
No |
down or up (default: down) |
levels |
integer |
No |
Levels to traverse (default: 2, max: 5) |
MDF Object Tools
get_mdf_object_definitions
| Parameter |
Type |
Required |
Description |
object_name |
string |
No |
Specific MDF object (e.g., cust_myObject). Empty = list all. |
query_mdf_object
| Parameter |
Type |
Required |
Description |
object_name |
string |
Yes |
MDF object name (e.g., cust_myObject) |
select |
string |
No |
Comma-separated fields |
filter |
string |
No |
OData filter |
top |
integer |
No |
Max results (default: 100, max: 500) |
skip |
integer |
No |
Pagination offset |
orderby |
string |
No |
Sort order |
effective_date |
string |
No |
Effective date filter (YYYY-MM-DD) |
get_foundation_objects
| Parameter |
Type |
Required |
Description |
object_type |
string |
Yes |
company, department, division, location, cost_center, job_code, job_function, pay_grade, pay_group, business_unit, event_reason, legal_entity |
filter |
string |
No |
Additional OData filter |
top |
integer |
No |
Max results (default: 100, max: 500) |
include_inactive |
boolean |
No |
Include end-dated records (default: false) |
Workflow Tools
get_pending_approvals
| Parameter |
Type |
Required |
Description |
user_id |
string |
No |
Filter to specific approver |
wf_request_id |
string |
No |
Filter to specific workflow request |
top |
integer |
No |
Max results (default: 100, max: 500) |
get_workflow_history
| Parameter |
Type |
Required |
Description |
wf_request_id |
string |
Yes |
Workflow request ID |
top |
integer |
No |
Max results (default: 100, max: 500) |
Monitoring & Admin Tools
get_alert_notifications
| Parameter |
Type |
Required |
Description |
from_date |
string |
No |
Start date (YYYY-MM-DD) |
to_date |
string |
No |
End date (YYYY-MM-DD) |
top |
integer |
No |
Max results (default: 100, max: 500) |
get_scheduled_job_status
| Parameter |
Type |
Required |
Description |
job_name |
string |
No |
Filter by job name |
top |
integer |
No |
Max results (default: 50, max: 500) |
get_integration_center_jobs
| Parameter |
Type |
Required |
Description |
job_name |
string |
No |
Filter by job name |
status |
string |
No |
Filter by status |
top |
integer |
No |
Max results (default: 50, max: 500) |
get_api_quota_status
Returns current rate limit usage for the specified instance.
get_cache_status
Returns cache hit rates, entry counts by category, and memory usage.
clear_cache
| Parameter |
Type |
Required |
Description |
target_instance |
string |
No |
Clear specific instance. Empty = clear all. |
Example Queries
Ask Claude in natural language:
| Query |
Tool Used |
| "Show me all users in the Sales department" |
search_employees |
| "What permissions does jsmith have?" |
get_user_permissions |
| "Compare User config between dev and prod" |
compare_configurations |
| "Who's on vacation next week?" |
get_upcoming_time_off |
| "List all open job requisitions for Engineering" |
get_open_requisitions |
| "How much PTO does jdoe have left?" |
get_time_off_balances |
| "Show me all new hires starting in March" |
get_new_hires |
| "Who has a 10-year anniversary this month?" |
get_anniversary_employees |
| "What are the status of performance reviews for my team?" |
get_performance_review_status |
| "Show John's complete job history" |
get_employee_history |
| "What custom MDF objects exist in our instance?" |
get_mdf_object_definitions |
| "List all departments with their cost centers" |
get_foundation_objects |
| "Are there any pending workflow approvals?" |
get_pending_approvals |
| "Check the status of our integration jobs" |
get_integration_center_jobs |
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.
Troubleshooting
Authentication Errors (HTTP 401)
- Verify credential format: user ID without
@instance
- Confirm the password is correct
- Ensure the API user has proper permissions in SuccessFactors Admin Center
Validation Errors
All inputs are validated to prevent injection attacks:
| Parameter |
Rules |
instance |
Alphanumeric, underscores, hyphens only |
entity |
Valid OData entity name pattern |
filter |
No blocked keywords ($batch, $metadata, <script>, etc.) |
locale |
Format like en-US or de |
select / orderby |
Valid field name patterns |
Server Disconnected (Claude Desktop)
- Verify
uv path in config is correct: which uv
- Check logs:
tail -f ~/Library/Logs/Claude/mcp*.log
- Test manually:
uv run mcp dev main.py
- Ensure Python 3.10+ is installed:
python3 --version
Rate Limit Errors
- The server auto-retries HTTP 429 responses (up to 3 times)
- Use
get_api_quota_status to check current usage
- Increase limits via
SF_RATE_LIMIT environment variable
- Cache responses with
SF_CACHE_TTL_DEFAULT to reduce API calls
Dependencies
| Package |
Version |
Purpose |
| fastmcp |
>=2.0.0 |
Model Context Protocol SDK |
| requests |
>=2.31.0 |
HTTP client with connection pooling |
| defusedxml |
>=0.7.0 |
XXE-safe XML parsing |
| python-dotenv |
>=1.0.0 |
Environment variable loading |
| uvicorn |
>=0.30.0 |
ASGI server for HTTP transport |
Dev dependencies: pytest, ruff, mypy
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature
- Run tests:
uv run pytest tests/ -v
- Run linting:
uv run ruff check .
- Commit your changes
- Open a Pull Request
Changelog
See CHANGELOG.md for release history.
License
This project is licensed under the MIT License — see the LICENSE file for details.
Built with FastMCP ·
Powered by Model Context Protocol