Skip to content

BTP Cloud Foundry Deployment

This is the canonical administrator runbook for deploying ARC-1 on SAP BTP Cloud Foundry. It uses the repository's SAP Multi-Target Application (MTA) descriptor so XSUAA, Destination, Connectivity, bindings, role collections, health checks, and safe defaults are deployed together.

The first acceptance target is deliberately read-only. Widen a single-target instance only after identity, authorization, audit, and rollback have been proven. Multi-target aggregate and Basic routes remain mutation-free; scoped pinned PP writes require their own complete setup.

Two meanings of multi-target

An SAP Multi-Target Application is the .mtar deployment format built from mta.yaml. ARC-1 multi-target is an experimental runtime mode serving several SAP system/client targets. You use the MTA format for both single- and multi-target ARC-1 deployments.

1. Choose the topology before configuring anything

Topology Public MCP URL SAP identity Capabilities Start here
One general SAP target /mcp Principal Propagation recommended; shared Basic is possible Full ARC-1 feature set, still constrained by instance flags and roles This page — single-PP or single-Basic profile
Many SAP system/clients /<SYSTEM>/<CLIENT>/mcp and /multi/mcp PP recommended; optional shared Basic exception Mutation-free v1: read/search/query/navigate/diagnose/context This page, then Multi-System Setup
One /mcp beside multi-target routes All of the above Configured independently /mcp may be writable; multi routes never are Read side-by-side risks first
BTP ABAP Environment /mcp OAuth2UserTokenExchange Single target BTP ABAP Environment
S/4HANA Public Cloud /mcp SAML/OAuth user exchange Single target S/4HANA Public Cloud

Use separate ARC-1 applications when you need different mutation ceilings, hard target-inventory separation, different capacity limits, writable multi-system access, or separation between Admin diagnostics and a writable /mcp. For a customer beta or cutover, a separate CF space is safer than replacing an existing app in place: the shipped XSUAA application and role-collection names are space-qualified.

Principal Propagation is the normal customer path because SAP receives the human identity. Single-target shared Basic is supported when a reusable technical SAP identity is an accepted trade-off; it must explicitly disable the base MTA's PP settings. The one-process/non-rolling restriction applies only to multi-target mode containing a Basic destination.

2. Assign owners

Deployment crosses several independent control planes. Confirm the handoffs before the change window. The optional worksheet can help record them.

Task Typical owner
Entitlements and subaccount/space BTP subaccount administrator
MTA build, deploy, route, and bindings CF Space Developer
Destination fields and credentials Destination Administrator
XSUAA role collections and users/groups User and Role Administrator
Cloud Connector mapping and resources Cloud Connector administrator
STRUST, CERTRULE, ICM/SICF, SU01, SAP roles SAP Basis/security
MCP client and safe-read acceptance ARC-1 service owner/user

The resources live at different levels:

BTP global account
└── subaccount
    ├── trust and subaccount destinations
    └── Cloud Foundry org
        └── space
            ├── ARC-1 application
            └── XSUAA, Destination, Connectivity service instances

Multi-target discovery uses subaccount destinations. A different CF space in the same subaccount is not a hard destination-inventory boundary. Use separate subaccounts if that inventory itself must be isolated.

3. Prepare the landscape

Prerequisites

  • Cloud Foundry is enabled in the intended BTP subaccount.
  • The subaccount has quota for XSUAA (application), Destination (lite), and Connectivity (lite).
  • Node.js 22.19 or later, npm, CF CLI, CF MultiApps plugin, and MBT are available.
  • The operator is logged in and targeted at the intended org and space.
  • For on-premise SAP, Cloud Connector is connected to this exact subaccount.
  • For PP, the SAP and Cloud Connector administrators can complete the Principal Propagation runbook.
  • A User and Role Administrator can inspect and assign the generated collections.

SAP Business Application Studio can supply the CLI toolchain when an administrator cannot build on a local workstation. Use a controlled Dev Space, clone the reviewed revision, and follow the same commands below.

Preflight

Run these read-only checks in the operator shell:

node --version
npm --version
cf version
cf plugins | grep -E 'multiapps|MultiApps'
mbt --version
cf target
cf services

Stop if cf target names the wrong API endpoint, org, or space. Record the selected values in the deployment ticket. Confirm entitlements in BTP Cockpit rather than discovering missing quota halfway through the deploy.

Read the cf services output before deploying into a space that already runs ARC-1 or shares platform services. arc1-destination and arc1-connectivity are declared as org.cloudfoundry.managed-service, and a managed instance is named after its resource — so a landscape whose instances are named differently gets additional instances rather than reuse.

Because this guide uses subaccount-level destinations, which any Destination instance in the subaccount can resolve, the duplicate usually costs Destination/Connectivity lite quota and landscape clarity rather than function. It does fail the deploy outright on a subaccount already at its quota, and ARC-1 genuinely loses the targets if the shared instance carries instance-level destinations (see Destination level and visibility).

An extension descriptor cannot change a resource's type — mbt validate rejects type in mta.ResourceExt. It can only repoint a managed resource at a specific instance name:

resources:
  - name: arc1-destination
    parameters:
      service-name: my-shared-destination

That binds the named instance, but the resource stays MTA-managed: the deploy creates it if it is absent, and cf undeploy --delete-services would delete it. Use it only when this ARC-1 deployment is meant to own that instance. Binding an instance whose lifecycle belongs to someone else requires org.cloudfoundry.existing-service in mta.yaml itself, which the shipped descriptor does not offer — treat that landscape as needing a reviewed descriptor change, not an extension.

4. Create the landscape extension

mta.yaml owns versioned safe defaults and BTP resource topology. A customer-owned extension owns durable landscape-specific settings. Destinations own target-local connection and identity data.

git clone https://github.com/arc-mcp/arc-1.git
cd arc-1
git checkout <reviewed-tag-or-commit>
npm ci

Choose one profile below from this checkout. If mta-overrides.mtaext already exists, compare and adapt it instead of copying another template over it. The cp -n commands preserve an existing file; a skipped copy does not mean the selected profile was applied.

The real mta-overrides.mtaext is gitignored. Store the reviewed copy in the customer's protected configuration process. Never add secrets to it and never edit generated mtad.yaml.

Single-target read-only shared Basic profile

Use this profile when XSUAA should authenticate MCP callers but every SAP request may use one approved technical user:

cp -n examples/btp/single-basic/profile.mtaext mta-overrides.mtaext

Prepare a private copy of examples/btp/single-basic/basic.destination.json under the ignored .arc1/btp/ directory. Replace the fictional values, supply the credentials through the destination owner's protected process, and update SAP_BTP_DESTINATION in the extension to the same name. The profile explicitly sets both SAP_PP_ENABLED=false and SAP_PP_STRICT=false because the base MTA enables PP.

This initial profile is ADT-only. It disables the gCTS, FLP and UI5 Repository feature probes so the Cloud Connector mapping can expose only /sap/bc/adt with all sub-paths. Add a non-ADT path and re-enable its feature only as one reviewed capability change.

Single-target read-only PP profile

For an on-premise /mcp, the current runtime uses a Basic destination to resolve the startup target and a PP destination for every JWT-backed user request:

cp -n examples/btp/single-pp/profile.mtaext mta-overrides.mtaext

Prepare private copies of examples/btp/single-pp/startup.destination.json and request.destination.json under the ignored .arc1/btp/ directory. Replace the fictional values and update the two destination names in the extension together. The example README explains the startup/request pairing. Its least-privileged startup user is not a PP fallback.

Multi-target PP-only profile

The profile below keeps standard access (standard): every reader may see/try all targets; SAP still decides whether the call is authorized. This is a legitimate setup when everyone may see the shared inventory. For different per-team target lists, consider optional target filtering. It uses IAM assignments, not automatic SAP-account discovery.

cp -n examples/btp/multi-pp/profile.mtaext mta-overrides.mtaext

If opting into filtering, add this one property to the copied extension's existing arc1-mcp-server module under properties:; keep its other settings:

ARC1_MULTI_TARGET_AUTHORIZATION: xsuaa-attribute

Then continue through steps 5–9 on this page. Leave restricted users unassigned until the app is deployed, destinations are active, and enforcement is verified. Step 9 hands off to the target-role procedure; do not start that procedure or another deployment in parallel with this runbook.

Prepare private copies of the two examples/btp/multi-pp/*.destination.json files under .arc1/btp/. Replace the fictional QAS targets with your system/client values; add one file per additional target if needed. These are subaccount-level PP destinations; no startup destination is needed. Keep SAP_BTP_DESTINATION and SAP_BTP_PP_DESTINATION absent, including in existing app env.

Prepare the selected profile

All three examples keep mutation/data/SQL flags off, UI/plugins off and cache none. They also deny ATC/Unit workloads and disable non-ADT gCTS, FLP and UI5 Repository probes for initial acceptance; single-target deployments can enable additional capabilities after acceptance. Multi-target v1 keeps its restricted tool surface, which excludes SAPGit and SAPManage regardless of feature toggles. The PP profiles keep strict PP on, while single-Basic explicitly turns it off. Do not combine the profiles or add UI overlays.

Replace names, virtual URLs, real SID/client and descriptions in your private destination files. Keep clients such as 001 quoted. Add CloudConnectorLocationId only if the Connector owner supplies one. JSON files show the destination fields to create in the cockpit; they do not provision anything or guarantee a particular import format. Keep SAP credentials in the owner's secure process, not in a PR or LLM prompt.

For single-Basic, ask the Connector owner for a principal-type-None mapping with internal HTTPS and only the approved resource paths; then create/review the destination using Destination Reference. For PP, ask the Connector/Basis owners to complete Principal Propagation Setup and create/review the destinations using Destination Reference.

Both single-target profiles require their configured destination data before deployment. Single-Basic resolves its one destination at startup. Single-PP resolves the Basic startup destination at startup and needs the PP request destination for user calls. Multi-PP can start empty, but requires all processes to restart after destinations are added. Then continue to step 5 below.

Multi-target with a shared Basic exception

Use this complete extension profile instead of the PP-only profile, and only after the customer accepts shared SAP attribution, reusable destination credentials, SAP account-lock exposure, downtime for deployment, and no horizontal scaling:

_schema-version: "3.1"
ID: arc1-mcp-overrides
extends: arc1-mcp

modules:
  - name: arc1-mcp-server
    parameters:
      instances: 1
    properties:
      ARC1_MULTI_TARGET_ENDPOINTS: "true"
      ARC1_MULTI_TARGET_ALLOW_BASIC_AUTH: "true"
      ARC1_CACHE: none

This permits Basic destinations; it never converts PP destinations or provides a fallback. Every XSUAA user authorized to call a Basic target acts in SAP as that destination's same technical user. Use a separate principal-type-None Cloud Connector mapping with internal HTTPS and a dedicated, least-privileged technical SAP user. See Shared Basic controls.

Optional: BTP Audit Log sink

ARC-1 always writes audit events to stderr. To also send the supported security/data categories to SAP BTP Audit Log Service, first assign auditlog premium quota and an owner for certificate rotation. The service uses X.509 client authentication; a plain service instance and binding create a client secret that the Audit Log Write API cannot use.

The base mta.yaml contains the complete service-instance and binding configuration but keeps the resource inactive. Add this to the real landscape extension, merging it into an existing resources: block when necessary:

resources:
  - name: arc1-auditlog
    active: true

The base descriptor then supplies both required halves:

  • service-instance configuration with a unique xsappname, X.509 credential type, and client_credentials grant; and
  • module requires.parameters.config with xsuaa.credential-type: x509 and a two-month certificate.

For a reviewed direct-cf push deployment, use SAP's instance and binding commands in Audit Log Write API for Customers, then restage arc1-mcp-server.

A deploy can report Updating service is currently not supported operation when attempting an Audit Log service update. That warning alone does not establish whether the existing instance lacks X.509 configuration, and deployment exit 0 does not prove a usable binding. Inspect the service operation and check cf logs arc1-mcp-server --recent:

  • BTP Audit Log sink enabled confirms the required fields are present. Verify delivery of a known event; if it arrives, no replacement is needed.
  • BTP Audit Log sink disabled with missing X.509 fields means the binding is incomplete. Inspect the instance and binding configuration against the two required halves above. Correct/recreate the binding first if the instance already supports X.509; cf bind-service returning OK alone is insufficient.

Only when an instance needs X.509 configuration that its broker cannot update should its owner plan replacement. For a dedicated, disposable ARC-1 instance, inventory app bindings and service keys, schedule the delivery interruption, then unbind/delete it and redeploy the activated MTA resource. A shared instance needs its owner's migration plan. Verify retained records through the reader before and after replacement; this is not a substitute for a retention/archive policy.

Do not print cf env or binding credentials into tickets: they contain the private key. Startup validation proves neither authentication nor delivery. Follow Audit Log delivery evidence to retrieve a known MCP Tool Call record and account for asynchronous ingestion.

For expiry and rebinding, see Audit Log certificate rotation.

5. Validate, build, and inspect the MTAR

npm run btp:validate
npx mbt validate -e mta-overrides.mtaext
npm run btp:build

npm run btp:validate checks the repository's base and tracked example descriptors. The explicit npx mbt validate -e command checks the customer's actual protected override. Expected result: both checks succeed and MBT creates mta_archives/arc1-mcp_<version>.mtar.

Before a customer deploy, inspect the archive in a protected workspace. Three things make a naive listing useless here:

  • The MTAR is a wrapper. Each deployed module is one nested <module>/data.zip, and the application lives inside it. Listing the MTAR shows you META-INF/ and those nested archives and nothing about their contents. The UI variant (npm run btp:build-ui-ext) ships more than one payload, so inspect every member rather than assuming one.
  • mta_archives/ accumulates every version you have built. A glob matching several archives is a false green: unzip -l treats the second path as a filter inside the first and reports 0 files (exit 11), while PowerShell's OpenRead fails outright. Resolve one archive and echo which one.
  • A gate that cannot find anything must fail, not pass. No archive, no data.zip member, or an unreadable payload has to be an error; otherwise a broken workspace reports a clean release.
  • No module needs a packaged .npmrc. AppRouter 23.3 no longer uses the local decoder compatibility bridge, so the checks below deny npm configuration in every payload.
inspect_mtar() (
  set -o pipefail
  deny='\.env|\.npmrc|service-key|\.(key|pem|p12|pfx|pse|jks|keystore)$'
  mtar=$(ls -t mta_archives/*.mtar 2>/dev/null | head -1)
  [ -n "$mtar" ] || { echo 'FAIL: no archive in mta_archives/'; return 1; }
  echo "$mtar"
  unzip -l "$mtar" || { echo 'FAIL: unreadable archive'; return 1; }
  members=$(unzip -Z1 "$mtar" | grep '/data\.zip$') ||
    { echo 'FAIL: no <module>/data.zip member'; return 1; }
  tmp=$(mktemp -d) || return 1
  trap 'rm -rf "$tmp"' EXIT
  while IFS= read -r member; do
    unzip -p "$mtar" "$member" > "$tmp/payload.zip" || { echo "FAIL: cannot extract $member"; return 1; }
    entries=$(unzip -Z1 "$tmp/payload.zip") || { echo "FAIL: cannot read $member"; return 1; }
    n=$(printf '%s\n' "$entries" | wc -l) || { echo "FAIL: cannot count $member"; return 1; }
    echo "-- $member: $n entries"
    bad=$(printf '%s\n' "$entries" | grep -Ei "$deny" || true)
    [ -z "$bad" ] || { printf '%s\n' "$bad"; echo "FAIL: denied path in $member"; return 1; }
  done <<< "$members"
  echo 'PASS: every payload inspected, no denied paths or unreviewed npm config'
)
inspect_mtar

It returns zero only after inspecting every payload successfully, so it is safe to run unattended. The function body is a subshell, so pipefail and the cleanup trap do not leak into your session.

Read a full listing too — the pattern covers today's known names, and the point of the gate is to catch a file type no denylist anticipated. Take the member names from the wrapper listing above:

MTAR="mta_archives/arc1-mcp_$(node -p "require('./package.json').version").mtar"
inspect_dir=$(mktemp -d)
unzip -p "$MTAR" '<module>/data.zip' > "$inspect_dir/payload.zip" &&
  unzip -l "$inspect_dir/payload.zip" | less
rm -rf "$inspect_dir"

On Windows, Expand-Archive needs a .zip extension, so copy first:

$ErrorActionPreference = 'Stop'
$deny = '\.env|\.npmrc|service-key|\.(key|pem|p12|pfx|pse|jks|keystore)$'
$mtar = Get-ChildItem mta_archives\*.mtar | Sort-Object LastWriteTime -Descending | Select-Object -First 1
if (-not $mtar) { throw 'FAIL: no archive in mta_archives/' }
$mtar.FullName
$tmp = Join-Path $env:TEMP ([guid]::NewGuid())
try {
  Copy-Item $mtar.FullName "$tmp.zip"
  Expand-Archive "$tmp.zip" "$tmp-outer"
  $members = @(Get-ChildItem "$tmp-outer" -Recurse -Filter data.zip -File)
  if ($members.Count -eq 0) { throw "FAIL: no <module>/data.zip member in $($mtar.Name)" }
  $bad = @()
  foreach ($member in $members) {
    $dest = Join-Path "$tmp-payload" $member.Directory.Name
    Expand-Archive $member.FullName $dest
    $files = @(Get-ChildItem $dest -Recurse -File)
    if ($files.Count -eq 0) { throw "FAIL: empty payload $($member.Directory.Name)" }
    "-- $($member.Directory.Name): $($files.Count) files"
    $bad += $files | Where-Object { $_.Name -match $deny }
  }
  if ($bad) { $bad.FullName; throw 'FAIL: denied path in payload' }
  'PASS: every payload inspected, no denied paths or unreviewed npm config'
} finally {
  Remove-Item "$tmp.zip","$tmp-outer","$tmp-payload" -Recurse -Force -ErrorAction SilentlyContinue
}

A checksum is not a substitute: it proves the archive did not change, not that no secret was packaged.

The application payload must not contain .env*, service-key exports, customer .mtaext files, private keys, certificates, local MCP configuration, source tests, operator artifacts, or any .npmrc. The MTA build has an explicit denylist and CI coverage for critical names; archive inspection is still a release gate because a future file type can evade a denylist.

6. Deploy the MTA

Run from the reviewed checkout as the CF Space Developer:

npm run btp:deploy-ext

Or build and deploy together:

npm run btp:build-deploy-ext

The deployment creates/updates:

  • arc1-mcp-server, one 512 MB process by default;
  • XSUAA with ARC-1 scopes, templates, and eight space-qualified role collections (seven functional collections plus the unassigned ARC-1 All Targets collection), and exact backend /oauth/callback and /oauth/logged-out URLs;
  • Destination and Connectivity service instances and bindings;
  • the Audit Log premium instance and X.509 binding only when arc1-auditlog is activated; and
  • a health check on /health.

The default backend route needs no callback setting. For a custom public URL or explicit backend routes:, follow Custom public URL before deployment. When updating an existing installation, first check the callback upgrade table, including preservation of an existing optional UI URL.

The unconfigured base application and multi-target mode can start with no SAP targets. The two single-target profiles are different: their configured destination data must already exist, as checked in step 4.

Verify platform state:

cf app arc1-mcp-server
cf services
cf logs arc1-mcp-server --recent

Expected result: one healthy process, bound arc1-xsuaa, arc1-destination, and arc1-connectivity services, and no startup validation error. A multi-target registry with zero targets is healthy-but-unconfigured, not ready for users.

7. Set the stable OAuth DCR key

Do this once in a protected operator shell:

cf set-env arc1-mcp-server ARC1_DCR_SIGNING_SECRET "$(openssl rand -base64 48)"
cf restage arc1-mcp-server

The dedicated key keeps stateless MCP client registrations valid when an XSUAA binding secret rotates during later MTA deployments. Never commit the value, put it in the extension/MTAR, paste it into support material, or expose unredacted cf env output. Store it in the customer's approved secret process. Rotating it intentionally revokes every cached DCR registration.

See BTP Administration for lifecycle and limitations.

8. Verify role collections before assigning users

As User and Role Administrator:

  1. Open BTP Cockpit → Security → Role Collections.
  2. Find the seven functional collections for the CF space, for example ARC-1 Viewer (dev) through ARC-1 Admin (dev). The eighth is ARC-1 All Targets (dev).
  3. Open each collection and confirm its Roles tab contains the expected current arc1-mcp-<space>!t... application role.
  4. Single target or standard multi-target access: assign ARC-1 Viewer (<space>) to the initial test user before their first login. Target-filtered multi-target access: leave the restricted user unassigned here and continue to step 9. That step hands off to role setup after destinations are ready; verify enforcement before assigning the restricted user's target role collection.

Leave ARC-1 All Targets (<space>) unassigned unless explicitly approved: it grants read and literal *, including future targets. It is not a harmless catalog-viewer role.

Do not stop after seeing the role templates under Roles. Older/recreated XSUAA deployments can have missing or orphaned collections. A collection with an empty Roles tab grants nothing. See XSUAA role administration for repair and IdP-origin details.

9. Configure SAP connectivity and destinations

If step 4 already prepared the destinations and PP mapping, verify those settings here; do not recreate them. Otherwise complete the setup now (multi-target can start with an empty catalog).

The deployment owner can hand off these stable values now:

  • BTP subaccount and CF org/space;
  • ARC-1 route from cf app arc1-mcp-server;
  • selected topology and client number(s);
  • Cloud Connector virtual host/port convention;
  • destination names for /mcp, or destination marker contract for multi-target; and
  • initial role collection and acceptance user.

For on-premise PP, complete Principal Propagation Setup. It is the only canonical Cloud Connector/SAP certificate procedure. Expose /sap/bc/adt and required subpaths, not /; preserve backend TLS verification; and prove issuer-restricted certificate mapping in CERTRULE before testing ARC-1.

Then create the destinations using BTP Destination Reference:

  • single target with shared Basic: the one explicitly named Basic destination in the extension;
  • single target with PP: the explicitly named startup and PP destinations in the extension;
  • multi-target: one subaccount destination per SAP system/client, normally PP, with sap-sysid, sap-client, Description, and arc1.enabled=true.

Restart after multi-target destination additions or non-secret changes:

cf restart arc1-mcp-server

For a discovered multi-target Basic destination only, User/Password rotation is request-time and needs no restart. A single-target SAP_BTP_DESTINATION is resolved at startup, so credential changes require restarting every app instance. Every non-secret multi-target field belongs to the immutable startup registry.

Target-filtered deployments: now complete the minimal static role setup, then return to step 10 below. The app/descriptor and destinations are already prepared: do not redeploy from the start. The guide checks them, creates the unassigned cohort, verifies enforcement and active targets, and only then assigns the pilot user. Standard-access deployments continue directly below.

10. Verify the service in layers

Process and OAuth metadata

ROUTE="https://<route-from-cf-app>"
curl -fsS "$ROUTE/health" | jq .
curl -fsS "$ROUTE/.well-known/oauth-authorization-server" | jq .

/health only proves process health. It does not prove that a destination is active, a user can map through PP, or SAP authorizes ADT.

Sign in and perform a safe read

Configure the client with exactly one selected endpoint:

Mode URL
Single target https://<route>/mcp
Pinned target https://<route>/A4H/100/mcp
Aggregate multi-target https://<route>/multi/mcp

Use the read-only pilot identity (ordinary Viewer for standard access; the exact-target collection for target-filtered access). After OAuth:

  1. confirm the expected mutation-free/read-only tool catalog;
  2. for aggregate mode, call SAPTargets when there is more than one active target visible to that reader; with filtering this means granted active targets, not the whole registry. With one, use the target in the other tools' schemas; with zero grants the tool list is empty. An Admin connection can inspect SAPTargets with zero, one, or many grants;
  3. call SAPRead with type: "SYSTEM";
  4. call SAPRead with type: "COMPONENTS"; and
  5. call SAPSearch for one known object.

These calls establish safe-read access, not the backend login identity: SYSTEM.user can come from configuration or token claims. Follow backend identity verification with Basis and record that result separately. For shared Basic, verify the intended technical user in the backend evidence. For discovered multi-target Basic destinations, Admin SAPTargets also labels the identity as shared; single-target /mcp has no SAPTargets tool.

For the multi-only example, verify that /mcp is unavailable and pinned routes do not expose SAPTargets. The aggregate catalog is configuration inventory, not proof of the user's SAP access. For each PP target, use an owner-approved negative identity to verify that failed mapping or SAP authorization does not become shared-user access. Do not change working users or grant Admin just to manufacture a test. Repository metadata alone does not prove client isolation; keep any separate client-data check unverified until approved rather than enabling data/SQL for the smoke test.

As Admin on multi-target, call SAPTargets and review zero/one/many behavior, registry revision, quarantined/disabled entries, duplicate/shadow warnings, and instance policy narrowing. There is no public or standalone /targets endpoint.

Add capability only after acceptance

For a single-target instance, widen the application ceiling in the reviewed .mtaext, redeploy, assign the least-privilege XSUAA collection, and retest the negative boundary. Data, SQL, writes, transports, Git, and package scope are independent decisions.

For multi-target v1, data preview and SQL require both application ceilings and target-local destination opt-ins. The reviewed tool/action surface also includes offline lint, read-only transport inspection, ATC and ABAP Unit. ATC/Unit execute SAP workloads: keep them out of routine deployment smoke tests, and deny their actions when not approved. For scoped CLAS/INTF writes and whole-owner activation, complete the separate pinned PP write setup after this read-only acceptance. Aggregate and Basic routes remain mutation-free. Transport/Git management, SAP-backed formatter/settings actions, plugins, UI and hyperfocused mode remain unavailable.

When data preview or SQL is enabled, keep the shipped 2 MiB cumulative response allowance and two process-wide data-result slots initially. Wide rows can reach the byte ceiling below the 10,000-row request cap. If an approved batch/file consumer needs more, set ARC1_MAX_DATAPREVIEW_RESPONSE_BYTES and ARC1_MAX_CONCURRENT_DATA_RESULTS together in the extension, benchmark peak RSS, and normally reduce concurrency as the byte allowance rises. Both values are positive integers; 0 is rejected at startup. Use the BTP data-preview RAM sizing table to change the two limits and the module's parameters.memory value as one reviewed deployment decision.

The base MTA also sets OPTIMIZE_MEMORY=true; do not replace its exec sh ./bin/start-cf.sh launcher with a fixed node --max-old-space-size=... command in the extension. The launcher validates the buildpack-provided MEMORY_AVAILABLE, derives old-space from the durable CF allocation (384 MiB at 512 MiB, 768 MiB at 1 GiB), and execs Node so CF's SIGTERM reaches ARC-1. The sh prefix also matters on its own: a reported Windows-built MTAR lost the script executable bit despite its Git mode. Starting that script directly (./bin/start-cf.sh) caused Permission denied, exit 126; invoking it through sh avoids depending on the archive's executable bit. Verify the Runtime memory envelope and Data-result safety envelope startup logs after every memory or limit change.

11. Handover and ongoing operation

Before customer users connect, complete the pre-customer acceptance checklist. Record:

  • the reviewed Git revision and .mtaext desired state;
  • exact route, org/space, services, mode, instance count, target ownership, and role assignments;
  • DCR-key backup/rotation owner without recording the value in the ticket;
  • SAP/Cloud Connector evidence and the first successful safe reads;
  • concurrency/rate decisions and monitoring owner; and
  • the prior MTAR and mode-appropriate rollback procedure.

Use BTP Administration for change/restart decisions, upgrades, role lifecycle, scaling, logging, incidents, and rollback. Multi-target registry/status codes and Basic lockout behavior remain in Multi-Target Administration.

Advanced deployment alternatives

The MTA path above is the supported BTP administrator journey because it keeps application and BTP service topology together. Docker and direct buildpack deployment can be useful for a custom base image, corporate CA bundle, or an organization with its own CF release pipeline, but then that pipeline owns service creation, bindings, route, role collections, health checks, exact version pinning, secret exclusion, and mode-specific scaling. Do not copy a generic /mcp manifest into a multi-target deployment without reproducing every startup invariant.

For a container pipeline, start from Docker Deployment. Pin an exact ARC-1 version, not :latest, and use a dedicated customer manifest rather than treating the repository MTA and a manifest as two simultaneous desired-state sources.

Deploying Without Docker (Node.js Buildpack)

The shipped MTA already deploys a Node.js buildpack module; it does not require Docker. If you mean a manual cf push without MTA, build the runtime first and provide the same services/properties in a customer-owned manifest:

npm ci
npm run build
cf push -f <reviewed-customer-manifest.yml>

This is an advanced alternative. Validate it against mta.yaml, xs-security.json, the selected single/multi startup contract, the MTAR secret exclusions, and the acceptance checklist. A raw buildpack push does not create the MTA role collections for you (seven functional plus the unassigned All Targets collection).

Troubleshooting deployment

Symptom Check
MTA lifecycle type cannot change Existing app was deployed through another lifecycle; use a separate beta space or an approved migration/rollback plan
App has no target but is healthy Expected for target-free base; configure explicit /mcp destinations or marked multi destinations
Multi-target startup exits Check XSUAA, Destination, Connectivity bindings and required mode invariants (ARC1_CACHE=none, standard tools, UI/plugins off)
Multi-target is ready with zero active targets Call Admin SAPTargets; health is not SAP readiness
Role collection missing/empty Perform full MTA deploy, inspect roles, remove/recreate orphaned collection if needed, then reassign
OAuth invalid_client after deploy Restore the intended DCR signing key or re-register clients; do not invent a new key on every deploy
OAuth invalid_scope after a grant First check the scope/assignment decision table. If the eligible failure page offers Role assigned? Refresh access, use it, then start a new MCP sign-in; reconnect alone can reuse stale grants.
SAP 401 through PP Check generated user certificate, STRUST, trusted proxy, ICF logon, CERTRULE, and SU01; for Basic startup + PP, check the Cloud Connector system-certificate logon setting
SAP 502 not mutually authenticated through PP Check that the effective HTTPS port requests a client certificate (VCLIENT=1) and its active SSL Server PSE trusts the system certificate's direct issuer; see Certificate trust (STRUST)
Crash loop Permission denied, exit 126 The launcher was replaced by a direct script call; check the executable bit in the archive and invoke scripts through sh as the base exec sh ./bin/start-cf.sh does
Non-interactive cf deploy prints nothing and never finishes Check for an earlier operation awaiting a decision with cf mta-ops; stop only the identified stalled local process and inspect the server-side operation before retrying
SAP 403 after PP login Check the actual propagated user's SAP authorizations
Destination change appears ignored Restart every ARC-1 instance; only discovered multi-target Basic username/password fields are hot
BTP Audit Log sink disabled at startup The selected premium binding is incomplete; recreate/rebind it with the X.509 instance and binding parameters from step 4
Updating service "arc1-auditlog" failed … Updating service is currently not supported operation during cf deploy The warning alone does not justify replacement. Check startup binding validation and known-event delivery; follow step 4 only if configuration repair is needed
Sink enabled, but no MCP Tool Call record in the Audit Log Viewer Allow for asynchronous ingestion, then query the Retrieval API; check that the binding is x509 and its certificate has not expired
Repeated BTP Audit Log delivery failed warning Check certificate validity, token/API reachability, and service health; rotate the binding before retrying

Official references