Now accepting guest editorial from SAP, Oracle, Workday and ServiceNow practitioners.Pitch a guide
The Sign-Off Table

Lesson 2 of 7

Connecting Claude Code safely: development only, an agent user, never production

10 min

Listen to this lesson

0:00 / 10:15

Three rules come before any configuration file. Development only: Claude Code connects to CMD, never to CMQ or CMP, and never to the legacy ECC systems. An agent user: the ADT project the MCP server uses logs on as the developer's agent user, such as KENJI_AGT with role ZCMC_AGENT_DEV, so SAP's version history and Security Audit Log tell agent work from human work. Never production: not for reading, not for "just one query". The design of agent users and roles is covered in sap-aid-302, lesson 2; this lesson wires Claude Code to that design.

ReachThe agent laptop has no ADT project or SAP Logon entry for CMQ or CMP; what can't be reached can't be damaged
IdentityThe ADT project logs on to CMD client 100 as KENJI_AGT with role ZCMC_AGENT_DEV: package-limited changes, no transport release
ADT MCP access restrictionsOn (the default); project = the CMD agent project; writable package = ZCMC_CORE_AGREEMENT only
Claude Code settingsManual mode, deny and ask rules for ADT tools, bypass disabled, token in an environment variable
ReviewReviewed diff, ATC and ABAP Unit before a person releases the request
Five layers between Claude Code and the SAP system; the first two hold even if every client-side setting fails.
The Sign-Off Table · thesignofftable.com/academy/sap-aid-203

Before you connect

  1. Sam (Basis) has created KENJI_AGT in CMD only; Nadia (security) has assigned ZCMC_AGENT_DEV.
  2. In ADT for VS Code (or Eclipse), Kenji adds a second destination for CMD client 100 that logs on as KENJI_AGT. His normal destination stays for his own work.
  3. He enables the ADT MCP server (VS Code default port 2236; Eclipse default 2234), keeps access restrictions on, lists only the agent project and the package ZCMC_CORE_AGREEMENT, and leaves the edit file tool off for the first session.
  4. He copies the generated token into an environment variable, ADT_MCP_TOKEN, in his shell profile or secrets manager. The token never goes into a file in the repository.

Where Claude Code stores MCP servers

ScopeStored inLoads inUse it for
Local (the default)~/.claude.json, under the project's pathThis project, for you onlyPersonal experiments; anything with a literal secret
Project.mcp.json in the repository rootThis project, for everyone who clones itThe team's shared ADT server definition, with secrets as variables
User~/.claude.jsonAll your projectsPersonal tools you use everywhere; rarely right for SAP systems

Claude Code MCP scopes, per Anthropic's MCP documentation (October 2026).

When the same server name exists in several scopes, Claude Code uses the whole entry from the highest one, local before project before user; fields aren't merged across scopes. An organization can also provide servers through managed settings, which rank above all of these.

Contoso's .mcp.json

The repository for the core agreement package carries one shared definition. Claude Code expands ${VAR} and ${VAR:-default} in a server's command, args, env, url and headers, so the file can be committed without the token:

If ADT_MCP_TOKEN isn't set, Claude Code still loads the file with a warning and sends the literal text, so the server rejects the call. That failure is safe and easy to spot in /mcp. The command-line alternative, claude mcp add --transport http --scope local adt http://localhost:2236/mcp --header "Authorization: Bearer $ADT_MCP_TOKEN", works too, but your shell expands the variable when you run it, so the token value is written into ~/.claude.json. That's acceptable for local scope on an encrypted laptop; never do it with --scope project. Remember that the token changes whenever someone regenerates it in the IDE.

Each call passes three gates before it reaches source code: the bearer token, the IDE's access restrictions and the agent user's SAP authorizations.
The Sign-Off Table · thesignofftable.com/academy/sap-aid-203

Verify the connection

  • Start Claude Code in the repository. In an interactive session it asks you to approve project-scoped servers from .mcp.json before using them; approve adt. (claude mcp reset-project-choices resets those choices.)
  • Run /mcp. It shows each server's status and tool count. A failed adt usually means the IDE isn't running, the server isn't enabled, the port differs or the token variable is missing.
  • Outside a session, claude mcp list and claude mcp get adt show the same status.
  • Note that claude -p (headless) runs load project servers without asking. That's one reason lesson 4 uses --bare for scripted runs.

Pin the permission mode

Anthropic's security page says auto mode, in which a classifier reviews actions instead of you, is now the built-in starting mode for interactive terminal and VS Code sessions. For SAP work Contoso wants a person to approve each change, so it pins permissions.defaultMode: "default" (labeled Manual) in managed settings. That matters because the VS Code extension ignores project settings for the starting mode; it reads its own claudeCode.initialPermissionMode setting, then managed or user settings. The repository's .claude/settings.json repeats "defaultMode": "default" for terminal sessions and disables bypass mode. sap-aid-302 covers the managed layer. Use plan mode when you only want analysis: Claude reads and explores but doesn't edit source files. Lesson 4 builds the full settings file.

The smoke test

The first session changes nothing. It answers one practical question: which ADT tools work against your backend? Give Claude Code read-only tasks and watch which tools it calls:

PromptTool it should callWhat you learn
"List the ABAP destinations you can reach."mcp__adt__abap_lists_destinationsOnly the CMD agent project should appear
"Read ZCL_CMC_CORE_DEPOSIT and summarize method calculate."mcp__adt__abap_read_fileWhether the file tools work on CMD's release
"Run the ABAP Unit tests of ZCL_CMC_CORE_DEPOSIT."mcp__adt__abap_run_unit_testsWhether test results come back as structured output
"Run ATC with variant ZCMC_CLASSIC_DEV on that class and show the findings."mcp__adt__abap_run_atc, then abap_atc_get_resultThe asynchronous ATC pattern and the finding format

Kenji's smoke test decides whether edits go through Route A or Route B.

What would you do?

A developer commits <code>.mcp.json</code> with the literal bearer token in the Authorization header, because "the repository is private". Kenji notices it in the pull request. What should happen?

Key points
  • Development only, an agent user, never production: settle these before any configuration.
  • Use project scope (.mcp.json) for the shared ADT server, with the token as ${ADT_MCP_TOKEN}; scopes don't merge, and local wins.
  • Name the server adt so its tools appear as mcp__adt__abap_*.
  • Verify with /mcp; pin Manual mode because auto is now the default starting mode.
  • A read-only smoke test shows which ADT tools work on your backend before you plan edits.

Check your understanding · not graded

Lesson check

  1. 1. Contoso wants every developer who clones the core agreement repository to get the same ADT MCP server definition. Which scope fits?

  2. 2. If the same server name is defined at local and project scope with different headers, what does Claude Code use?

  3. 3. Why does Contoso pin defaultMode to "default" in managed settings?

  4. 4. In the smoke test, Claude Code cannot call abap_read_file against CMD, but search, ABAP Unit and ATC tools work. What is the sensible conclusion?