Sap Support
FreeNot checkedAn MCP server over Streamable HTTP that exposes two SAP help-desk operations to an AI agent: sap_reset_password and sap_unlock_users.
About
An MCP server over Streamable HTTP that exposes two SAP help-desk operations to an AI agent: sap_reset_password and sap_unlock_users.
README
An MCP server over Streamable HTTP that exposes two SAP help-desk operations to an AI agent:
| Tool | What it does |
|---|---|
sap_reset_password |
Sets a user's password to a generated temporary value via BAPI_USER_CHANGE. The password is stored as initial, so SAP forces the user to choose a new one at next logon. |
sap_unlock_users |
Clears the administrator lock and resets the failed-logon counter for 1–25 users via BAPI_USER_UNLOCK. |
The two are deliberately separate, because SAP treats them separately: unlocking does not
change a password, and resetting a password does not clear a lock. A user who is locked
and has forgotten their password needs both. sap_reset_password detects this case and
says so in its response.
How it talks to SAP
Calls go over plain HTTP to the ABAP system's SOAP RFC service
(/sap/bc/soap/rfc) with basic authentication — no SAP NetWeaver RFC SDK, no native
binaries, so the server runs anywhere Node does.
MCP client ──Streamable HTTP──▶ sap-support-mcp ──SOAP/HTTPS──▶ /sap/bc/soap/rfc ──▶ BAPI_USER_*
Three function modules are used: BAPI_USER_GET_DETAIL (existence + lock state),
BAPI_USER_CHANGE (password), BAPI_USER_UNLOCK (locks).
Each SOAP RFC call is its own stateless session, so a follow-up
BAPI_TRANSACTION_COMMIT would land in a different LUW and do nothing. That is fine
here: the BAPI_USER_* modules commit internally. Do not extend this server with BAPIs
that require an explicit commit without first moving to a stateful transport.
Setup
npm install
cp .env.example .env
Generate the bearer token clients will use:
node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"
Fill in .env, then:
npm run dev
For production:
npm run build && npm start
SAP-side prerequisites
- The SOAP RFC service must be active in
SICFat/sap/bc/soap/rfc. - Create a dedicated technical user (type Communications) for
SAP_USER. It needs:S_RFC— activity 16, function groupsSUSRandSU_USER(or the specific modulesBAPI_USER_GET_DETAIL,BAPI_USER_CHANGE,BAPI_USER_UNLOCK).S_USER_GRP—ACTVT02 (change) and 05 (lock/unlock), withCLASSrestricted to the user groups the help desk is allowed to serve. This is the strongest control available — the allow/deny lists in this server are defence in depth on top of it, not a replacement for it.
- Do not give the technical user
S_USER_GRPover theSUPERgroup.
Configuration
Every setting is an environment variable; see .env.example for the full list with comments. The ones that matter most:
| Variable | Purpose |
|---|---|
MCP_AUTH_TOKEN |
Bearer token required on every MCP request. No unauthenticated mode exists. Minimum 16 characters. |
SAP_BASE_URL, SAP_CLIENT, SAP_USER, SAP_PASSWORD |
The target system and the technical user. |
USER_ALLOW_LIST |
If set, only matching users can be targeted. Supports *, e.g. SUPPORT_*,BUSINESS_*. |
USER_DENY_LIST |
Merged on top of the built-in deny list. Deny always beats allow. |
AUDIT_LOG_FILE |
JSONL audit trail. Defaults to audit/sap-support-mcp.audit.jsonl. |
SAP_REJECT_UNAUTHORIZED |
Leave true. Set false only for a sandbox with a self-signed certificate. |
Guardrails
Bearer auth. Every request to MCP_PATH needs Authorization: Bearer <token>,
compared with a timing-safe equality check. /healthz is the only unauthenticated route
and reveals nothing about SAP.
Allow / deny lists. SAP*, DDIC, SAPCPIC, EARLYWATCH, TMSADM, SAPSUPPORT,
ADS_AGENT and ADSUSER are denied unconditionally — adding * to the allow list
cannot expose them. Patterns are anchored, so SUPPORT_* does not match XSUPPORT_1.
A denied user is rejected before any call reaches SAP.
Dry run. Both tools take dryRun: true, which checks the policy and confirms the
user exists and reports its current lock state, without changing anything.
Audit trail. Append-only JSONL. Each operation writes an attempt record before
touching SAP and a terminal record (success / failed / denied / dry_run)
afterwards, sharing one correlationId, so a crash mid-call still leaves evidence:
{"ts":"2026-07-31T08:18:49.261Z","correlationId":"ed66d93a…","operation":"unlock_user","outcome":"attempt","targetUser":"JDOE","sapClient":"100","reason":"INC-SMOKE-1","sessionId":"9b85a10a…","clientIp":"127.0.0.1"}
Every tool call requires a reason (ticket number or justification) which is recorded.
Generated passwords are never written to the audit trail — AuditLog has no field that
could carry one, and a test asserts the password does not appear in the file.
Connecting a client
{
"mcpServers": {
"sap-support": {
"type": "http",
"url": "http://127.0.0.1:3000/mcp",
"headers": { "Authorization": "Bearer YOUR_TOKEN_HERE" }
}
}
}
Sessions are stateful: the server issues an Mcp-Session-Id on initialize, and each
session gets its own McpServer instance so caller identity stays isolated in the audit
trail.
Security notes worth reading before you deploy this
- The temporary password passes through the model's context.
sap_reset_passwordreturns it in the tool result, so it is visible to the LLM and to whatever transcript store sits behind it. That is inherent to handing a password back through MCP. If your threat model cannot accept it, changeresetPassword.tsto deliver the password out of band (email the user, push to a vault) and return only a confirmation. HOSTdefaults to127.0.0.1. Binding to0.0.0.0puts SAP password resets on your network; put it behind TLS and a reverse proxy if you do.- Everything the caller supplies is XML-escaped before it enters the SOAP envelope, and usernames are additionally validated against SAP's character rules, so a crafted username cannot inject extra RFC parameters.
- The deny list protects against a confused agent, not a hostile one holding the
bearer token.
S_USER_GRPon the SAP side is the real boundary.
Tests
npm test
43 tests, no SAP system required. test/mockSap.ts is a stand-in for /sap/bc/soap/rfc
that reproduces SAP's real response shapes — including message class 01/124 for an
unknown user, HTTP 401 for bad credentials, SOAP faults, and the fact that
BAPI_USER_UNLOCK clears an administrator lock but not a CUA global lock. The
end-to-end tests drive the real Express app through a real MCP client over Streamable
HTTP.
Layout
src/
index.ts entry point: config, wiring, graceful shutdown
config.ts env schema + built-in deny list
http/
server.ts Express app, Streamable HTTP transport, session registry
auth.ts bearer token middleware
mcp/
server.ts McpServer construction + instructions
tools/
resetPassword.ts sap_reset_password
unlockUsers.ts sap_unlock_users
sap/
soap.ts SOAP envelope building, XML escaping, fault handling
userService.ts the three BAPIs + RETURN-table interpretation
security/
policy.ts allow/deny evaluation
audit.ts append-only JSONL audit trail
util/
password.ts temporary password generation
Installing Sap Support
This server has no published package — it is built from source. Open the repository and follow its README.
▸ github.com/arief135/sap-support-mcpFAQ
Is Sap Support MCP free?
Yes, Sap Support MCP is free — one-click install via Unyly at no cost.
Does Sap Support need an API key?
No, Sap Support runs without API keys or environment variables.
Is Sap Support hosted or self-hosted?
A hosted option is available: Unyly runs the server in the cloud, no local setup required.
How do I install Sap Support in Claude Desktop, Claude Code or Cursor?
Open Sap Support on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
Fetch
Web content fetching and conversion for efficient LLM usage.
AWS KB Retrieval
Retrieval from AWS Knowledge Base using Bedrock Agent Runtime.
by modelcontextprotocolSpring AI MCP Server
Provides auto-configuration for setting up an MCP server in Spring Boot applications.
llm-analysis-assistant
A very streamlined mcp client that supports calling and monitoring stdio/sse/streamableHttp, and can also view request responses through the /logs page. It also
by xuzexin-hzCompare Sap Support with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All ai MCPs
