ARC-1 Deployment Best Practices¶
One Instance Per SAP System¶
ARC-1 follows the one instance per SAP backend pattern. Each ARC-1 deployment connects to exactly one SAP system. This is the same model used by Eclipse ADT, SAP Business Application Studio, and SAP GUI.
Why one-per-system?¶
| Concern | One-per-system | Multi-backend gateway |
|---|---|---|
| Security | Blast radius = one system | One breach = all systems |
| Auth | Clean: one auth flow per instance | N destinations + N auth flows |
| Safety gates | Per-system: readOnly, allowedOps, allowedPackages |
Can't vary per backend |
| Tool descriptions | Tailored to system type (BTP vs on-premise) | Must be generic for all |
| Audit trail | Clear per-system logs | Mixed across systems |
| Scaling | Scale independently | Heavy-use system affects all |
Multi-user within each instance¶
Each ARC-1 instance serves multiple users via principal propagation (on-premise) or JWT Bearer Exchange (BTP). The MCP client authenticates the user, and ARC-1 maps that to a SAP user identity.
┌─────────────────┐
│ MCP Client │
│ (Claude, etc.) │
└──┬──────────┬───┘
│ │
▼ ▼
┌─────────────────────┐ ┌──────────────────────┐
│ arc1-ecc-dev │ │ arc1-btp-dev │
│ on-premise, PP │ │ BTP ABAP, JWT Bearer │
│ readOnly=false │ │ readOnly=false │
│ 50 developers │ │ 50 developers │
└──────┬──────────────┘ └──────┬───────────────┘
▼ ▼
┌──────────────┐ ┌──────────────────┐
│ SAP ECC Dev │ │ BTP ABAP Env │
└──────────────┘ └──────────────────┘
Example: enterprise with multiple SAP systems¶
CF Apps:
┌──────────────────────────────────┐
│ arc1-ecc-dev │ ECC Dev, read+write, PP
│ readOnly=false │
├──────────────────────────────────┤
│ arc1-ecc-prod │ ECC Prod, read-only, PP
│ readOnly=true, blockFreeSQL=true │
├──────────────────────────────────┤
│ arc1-s4-dev │ S/4 Dev, read+write, PP
│ readOnly=false │
├──────────────────────────────────┤
│ arc1-btp-dev │ BTP ABAP, read+write, JWT Bearer
│ SAP_SYSTEM_TYPE=btp │
│ readOnly=false │
└──────────────────────────────────┘
MCP client config for developers:
{
"mcpServers": {
"sap-ecc-dev": {
"url": "https://arc1-ecc-dev.cfapps.us10.hana.ondemand.com/mcp"
},
"sap-ecc-prod": {
"url": "https://arc1-ecc-prod.cfapps.us10.hana.ondemand.com/mcp"
},
"sap-s4-dev": {
"url": "https://arc1-s4-dev.cfapps.us10.hana.ondemand.com/mcp"
},
"sap-btp": {
"url": "https://arc1-btp-dev.cfapps.us10.hana.ondemand.com/mcp"
}
}
}
The LLM sees separate tool sets from each server and picks the right one.
System Type Detection¶
ARC-1 auto-detects whether it's connected to a BTP ABAP Environment or an on-premise system.
How it works¶
On first SAPManage probe, ARC-1 reads /sap/bc/adt/system/components (already called for ABAP release detection — zero extra HTTP requests). If the SAP_CLOUD component is present, the system is BTP. Otherwise, on-premise.
Manual override¶
For immediate correct tool definitions at startup (before the first probe), set:
# Environment variable
SAP_SYSTEM_TYPE=btp # or: onprem, auto (default)
# CLI flag
--system-type btp
When SAP_SYSTEM_TYPE=btp is set, tool definitions are adapted at server startup:
- SAPRead removes PROG, INCL, VIEW, TEXT_ELEMENTS, VARIANTS from the type enum
- SAPWrite removes PROG, INCL, FUNC from the type enum
- SAPQuery description warns about blocked SAP standard tables
- SAPTransport description explains gCTS behavior
- SAPContext removes PROG, FUNC from the type enum
What changes on BTP¶
| Tool | What changes |
|---|---|
| SAPRead | Removes PROG, INCL, VIEW, TEXT_ELEMENTS, VARIANTS, SOBJ. Returns helpful error if LLM tries them anyway. |
| SAPWrite | Only CLAS, INTF. Must use ABAP Cloud syntax, Z/Y namespace. |
| SAPQuery | Warns that SAP standard tables (DD02L, TADIR, etc.) are blocked. Suggests CDS views. |
| SAPSearch | Notes that only released and custom objects are returned. |
| SAPTransport | Explains gCTS: release = Git push, not TMS export. |
| SAPContext | Only CLAS, INTF. Includes released SAP objects (they're the dev API surface on BTP). |
| SAPManage | Returns systemType in probe results. |
| SAPActivate | No change. |
| SAPNavigate | Notes released object scope. |
| SAPLint | No change. |
| SAPDiagnose | No change. |
Authentication Options¶
Local development¶
| Target | Auth | Config |
|---|---|---|
| On-premise SAP | Basic Auth | SAP_URL, SAP_USER, SAP_PASSWORD |
| BTP ABAP Environment | Service Key + Browser OAuth | SAP_BTP_SERVICE_KEY_FILE |
Deployed on BTP Cloud Foundry¶
| Target | Auth | Config |
|---|---|---|
| On-premise SAP (via Cloud Connector) | Principal Propagation | SAP_BTP_DESTINATION, SAP_PP_ENABLED=true |
| BTP ABAP Environment | JWT Bearer Exchange | SAP_BTP_SERVICE_KEY (future) |
Configuration examples¶
Local dev connecting to on-premise:
{
"mcpServers": {
"sap": {
"command": "arc1",
"env": {
"SAP_URL": "http://sap-dev:50000",
"SAP_USER": "DEVELOPER",
"SAP_PASSWORD": "..."
}
}
}
}
Local dev connecting to BTP ABAP:
{
"mcpServers": {
"sap-btp": {
"command": "arc1",
"env": {
"SAP_BTP_SERVICE_KEY_FILE": "~/.config/arc-1/btp-service-key.json",
"SAP_SYSTEM_TYPE": "btp"
}
}
}
}
Deployed on CF connecting to on-premise (multi-user):
# manifest.yml
applications:
- name: arc1-ecc-dev
env:
SAP_BTP_DESTINATION: SAP_ECC_DEV
SAP_PP_ENABLED: true
SAP_PP_STRICT: true
SAP_TRANSPORT: http-streamable
SAP_XSUAA_AUTH: true
Security Recommendations¶
- Use
readOnly=truefor production systems — prevents any write operations - Use
blockFreeSQL=truefor sensitive systems — blocks arbitrary SQL queries - Use
allowedPackages=Z*,Y*— restricts operations to custom code packages - Use
ppStrict=true— ensures every request has a user identity (no fallback to service account) - Deploy separate instances per system — limits blast radius
- Use XSUAA auth for deployed instances — proper OAuth 2.0 with scopes (read/write/admin)
- Set
SAP_SYSTEM_TYPEexplicitly in production — ensures correct tool definitions from startup
Key Files Reference¶
| File | Purpose | Customize? |
|---|---|---|
manifest.yml |
CF deployment manifest (on-premise via Cloud Connector) | Yes — change SAP_URL, destination name, safety flags |
manifest-btp-abap.yml |
CF deployment manifest (BTP ABAP direct) | Yes — service key is set via cf set-env |
Dockerfile |
Multi-stage Alpine build, all env vars documented | Rarely — use env vars for config |
.env.example |
Template for local .env file |
Yes — copy to .env and fill in |
xs-security.json |
XSUAA scopes, roles, redirect URIs | Yes — add redirect URIs for your MCP clients |
bin/arc1.js |
npm global CLI entry point | No |
Deploying Without Docker¶
If the Docker image doesn't fit your needs (custom certs, patching, compliance), deploy as a Node.js app using CF's nodejs_buildpack. See Phase 4: BTP Deployment for the full guide.
Quick summary:
1. git clone + npm ci + npm run build
2. Create a manifest-nodejs.yml with buildpacks: [nodejs_buildpack] and command: node dist/index.js
3. cf push -f manifest-nodejs.yml
4. Set secrets via cf set-env
BTP ABAP Environment Setup¶
See BTP ABAP Environment guide for: - Provisioning the BTP ABAP instance - Running the "Prepare an Account for ABAP Development" booster - Creating the service key - Configuring ARC-1 with the service key - OAuth browser login flow - System type detection and tool adaptation
See Phase 4: BTP Deployment for: - Cloud Foundry deployment with Docker - Destination Service and Cloud Connector setup - Principal Propagation configuration - Deploying without Docker (Node.js buildpack)