Skip to main content
Glama
lingcSun

mcp-bw-adt-api

by lingcSun

mcp-bw-adt-api

An MCP (Model Context Protocol) server that exposes the bw-adt-api library — SAP BW/4HANA ADT (ABAP Developer Tools) operations — to LLM clients such as ZCode, Claude Desktop, or any MCP-compatible client.

It wraps the ~100 public methods of BWAdtClient (ADSO, Transformation, DTP, DataSource, Process Chain, InfoObject, DDIC tables, search, dataflow lineage, transports, …) as MCP tools, with a local-file buffering layer that keeps large XML payloads and table data out of the LLM context window.


Why a buffering layer?

bw-adt-api payloads are large — measured on real systems:

Payload

Typical size

Object XML (PUT request body)

15–80 KB

DDIC table data, 100 rows × 20 cols

~68 KB

DDIC table data, 10 000 rows

~6.7 MB

Process chain logs, 200 entries

~39 KB

Pushing these through the LLM context window is wasteful or fatal. This server solves it two ways:

Mechanism A — large request bodies via local files (POST/PUT)

Every tool that takes a large string body (object XML, SQL statement, ABAP source) accepts two fields:

  • <label>Content — inline string

  • <label>Path — path to a file under the workdir (takes precedence)

So instead of the LLM having to generate or hold a 50 KB XML, it reads the current XML to a file, edits it (or uses an atomic-edit tool), then references the file by path.

Mechanism B — large responses via outputPath

Most read tools accept an optional outputPath. When set, the full result is written to that file and the tool returns only a small summary envelope:

{ "ok": true, "outputPath": "/abs/path/big.json", "bytes": 723908, "summary": "object with key(s): tableName, rows, …" }
  • Objects / arrays are written as JSON.

  • Raw XML strings (from bw_*_get_xml with outputPath) are written as plain text, so the same path can be reused as xmlPath in a later save call.

Without outputPath, the result is returned inline (with table data paginated to a soft cap and truncated/hint flags set when needed).

Workdir sandbox

All file paths resolve under the workdir and are confined to its subtree (.. escapes and out-of-tree absolute paths are rejected). By default the workdir is <cwd>/.mcp-bw-out (a scratch folder under the server process working directory) so buffered files do not land on project source. Override with BW_MCP_WORKDIR if you need a different root (e.g. the workspace root).


Related MCP server: sapmcp

Quick start

# 1. Install + build
npm install
npm run build

# 2. Configure connection (copy & edit)
cp .env.example .env
#   multi-env: BW_PROFILES + BW_<NAME>_*  (or legacy BW_BASE_URL / …)

# 3. Inspect the tool catalog (no BW connection needed)
npm run list-tools

Variable

Required

Description

BW_PROFILES

yes*

Comma-separated profile names, e.g. test,prod

BW_DEFAULT

no

Startup profile (default = first in BW_PROFILES)

BW_<NAME>_BASE_URL

yes*

BW server URL for that profile

BW_<NAME>_USERNAME

yes*

SAP logon user

BW_<NAME>_PASSWORD

yes*

Password (never exposed to the LLM)

BW_<NAME>_CLIENT

no

SAP logon client, e.g. 100

BW_<NAME>_LANGUAGE

no

Language key, e.g. ZH

BW_<NAME>_READONLY

no

true → reject mutating tools on this profile

BW_<NAME>_ALLOW_UNAUTHORIZED

no

true to accept self-signed certs

BW_MCP_WORKDIR

no

Root for file buffering (default = <cwd>/.mcp-bw-out)

* Or use the legacy single-env vars (BW_BASE_URL, BW_USERNAME, BW_PASSWORD, optional BW_CLIENT / BW_LANGUAGE / BW_READONLY / BW_ALLOW_UNAUTHORIZED) when BW_PROFILES is unset — they become a profile named default.

Switch at runtime with bw_env_list / bw_env_switch. The active profile’s client auto-logs-in on its first request; bw_disconnect drops only the current profile’s session.

Read-only profiles: mutating tools are omitted from tools/list, and the server emits notifications/tools/list_changed when readOnly visibility changes. Host support for mid-session refresh is incomplete (Cursor / Claude Code may keep a stale list until MCP reconnect or a new chat) — the server still rejects mutating tools/call as a hard guard.


Registering in an MCP client

Add the server to your client's MCP config. Examples:

ZCode (.zcode/mcp.json in the workspace, or user-level)

{
  "mcpServers": {
    "bw-adt": {
      "command": "node",
      "args": ["E:/04-code/02-personnal/mcp-bw-adt-api/build/index.js"],
      "env": {
        "BW_PROFILES": "test,prod",
        "BW_DEFAULT": "test",
        "BW_TEST_BASE_URL": "http://your-bw-test:8000",
        "BW_TEST_USERNAME": "developer",
        "BW_TEST_PASSWORD": "secret",
        "BW_TEST_CLIENT": "100",
        "BW_TEST_LANGUAGE": "ZH",
        "BW_TEST_READONLY": "false",
        "BW_PROD_BASE_URL": "http://your-bw-prod:8000",
        "BW_PROD_USERNAME": "developer",
        "BW_PROD_PASSWORD": "secret",
        "BW_PROD_CLIENT": "100",
        "BW_PROD_LANGUAGE": "ZH",
        "BW_PROD_READONLY": "true"
        // "BW_MCP_WORKDIR": "C:/path/to/workspace"
      }
    }
  }
}

The server inherits the client process's cwd, so BW_MCP_WORKDIR usually does not need to be set — files are buffered into the workspace that owns the MCP server.

Claude Desktop (claude_desktop_config.json)

Same shape under "mcpServers".


Tool catalog

Tools are named bw_<domain>_<action>. Run npm run list-tools for the full list with input schemas. Domains:

Domain

Prefix

Example tools

System / env

bw_system_*, bw_env_*, bw_disconnect

bw_env_list, bw_env_switch, bw_system_status

Search

bw_search_*, bw_quick_search

bw_search_objects, bw_quick_search

Dataflow / lineage

bw_dataflow_*

bw_dataflow_get, bw_dataflow_lineage

Generic CRUD

bw_object_*

bw_object_create/update/delete/activate

ADSO

bw_adso_*

bw_adso_get_xml, bw_adso_save_and_activate, bw_adso_add_field

Transformation

bw_trfn_*

bw_trfn_save_and_activate, bw_trfn_add_rules_and_save, bw_trfn_auto_map_and_save

DTP

bw_dtp_*

bw_dtp_execute, bw_dtp_save_and_activate

DataSource

bw_datasource_*

bw_datasource_save_and_activate, bw_datasource_merge_proposal

Replication

bw_replication_*

bw_replication_replicate_full

Process Chain

bw_processchain_*

bw_processchain_execute, bw_processchain_logs

InfoObject

bw_infoobject_*

bw_infoobject_get

DDIC tables / data

bw_table_*

bw_table_get_data, bw_table_query_sql

BICS reporting / preview

bw_reporting_*

bw_reporting_preview, bw_reporting_initial_view

Transport / CTS

bw_transport_*

bw_transport_check, bw_transport_create

Note: Transformation creation is unsupported server-side (SAP JCo limitation) and bw_object_create with objectType: "trfn" returns an error. All other TRFN operations work.


Typical workflows

Read-modify-write an ADSO (no large XML held by the LLM)

1. bw_adso_get_xml   { id: "ZL_FID40", format: "summary", outputPath: "adso.xml" }
   → LLM sees a small envelope; the full XML is on disk under the workdir.

2. bw_adso_add_field { id: "ZL_FID40", name: "ZZFLAG", dataType: "CHAR", length: 1 }
   → atomic edit: reads current XML, adds the field, saves+activates.
   (Or the LLM edits adso.xml directly, then:)

3. bw_adso_save_and_activate { id: "ZL_FID40", xmlPath: "adso.xml" }
   → writes the file's XML back, one-stop lock→PUT→activate→unlock.

Query a large table without flooding context

bw_table_get_data { table: "/BIC/AZL_FID402", maxRows: 1000, outputPath: "data.json" }
→ { ok: true, outputPath: "…/data.json", bytes: 680000, summary: "…: 1000 row(s)…" }

The LLM can then run a follow-up script/tool to inspect data.json instead of ingesting it.

Inspect process chain logs safely

bw_processchain_logs { id: "ZPC_FID", limit: 50, offset: 0 }
→ inline, capped. Use outputPath for the full log set.

Architecture

src/
├── index.ts        stdio entry; --list-tools catalog dump
├── server.ts       MCP Server + tools/list + tools/call (outputPath interception)
├── session.ts      singleton BWAdtClient from env (auto-login)
├── errors.ts       AdtException → MCP error result mapping
├── fileio.ts       workdir sandbox, readInput (mechanism A), writeOutput (mechanism B)
├── response.ts     pagination, projection, summaries
├── tool.ts         ToolDef + zod→JSON Schema + largeInput/outputPathField helpers
└── tools/          one file per domain, each exporting ToolDef[]
  • Credentials are read once from env at startup and never surfaced to the LLM.

  • Write operations (delete, activate, execute) are exposed directly, no extra confirmation layer — rely on your MCP client's tool-approval prompt.

  • Pagination: table tools default maxRows to 50 and cap inline returns; logs default to 100 with limit/offset.

Development

npm run build      # tsc → build/
npm run watch      # tsc -w
npm start          # run the server (stdio)
npm run list-tools # dump the tool catalog as JSON

The server depends on bw-adt-api via a local file: link during development. Once published, switch the dependency to "bw-adt-api": "^0.1.0".

License

MIT

F
license - not found
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/lingcSun/mcp-bw-adt-api'

If you have feedback or need assistance with the MCP directory API, please join our Discord server