Lesson 2 of 7
Connecting Claude Code safely: development only, an agent user, never production
10 min
Listen to this lesson
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.
Before you connect
- Sam (Basis) has created
KENJI_AGTin CMD only; Nadia (security) has assignedZCMC_AGENT_DEV. - 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.
- 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. - 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
| Scope | Stored in | Loads in | Use it for |
|---|---|---|---|
| Local (the default) | ~/.claude.json, under the project's path | This project, for you only | Personal experiments; anything with a literal secret |
| Project | .mcp.json in the repository root | This project, for everyone who clones it | The team's shared ADT server definition, with secrets as variables |
| User | ~/.claude.json | All your projects | Personal 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.
Verify the connection
- Start Claude Code in the repository. In an interactive session it asks you to approve project-scoped servers from
.mcp.jsonbefore using them; approveadt. (claude mcp reset-project-choicesresets those choices.) - Run
/mcp. It shows each server's status and tool count. A failedadtusually 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 listandclaude mcp get adtshow the same status. - Note that
claude -p(headless) runs load project servers without asking. That's one reason lesson 4 uses--barefor 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:
| Prompt | Tool it should call | What you learn |
|---|---|---|
| "List the ABAP destinations you can reach." | mcp__adt__abap_lists_destinations | Only the CMD agent project should appear |
| "Read ZCL_CMC_CORE_DEPOSIT and summarize method calculate." | mcp__adt__abap_read_file | Whether the file tools work on CMD's release |
| "Run the ABAP Unit tests of ZCL_CMC_CORE_DEPOSIT." | mcp__adt__abap_run_unit_tests | Whether 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_result | The 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?
- 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. Contoso wants every developer who clones the core agreement repository to get the same ADT MCP server definition. Which scope fits?
2. If the same server name is defined at local and project scope with different headers, what does Claude Code use?
3. Why does Contoso pin defaultMode to "default" in managed settings?
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?