sap-ai-dev-toolkit 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -4
- package/inventory.md +1 -1
- package/package.json +1 -1
- package/scripts/install-local.mjs +1 -1
- package/scripts/postinstall.mjs +19 -17
- package/src/mcp-proxy.mjs +9 -35
- package/tools.md +0 -3
package/README.md
CHANGED
|
@@ -84,7 +84,7 @@ Use the attached destination-prefixed tools directly in chat. Do not launch `sap
|
|
|
84
84
|
|
|
85
85
|
**Included skills:** `abap-development` · `abap-testing-quality` · `cds-development` · `rap-development` · `abap-debugging` · `abap-runtime-analysis` · `rap-service-delivery` · `sap-standard-api-analysis` · `clean-core-extensibility` · `sap-sdlc-orchestration` · `sap-transport-release` · `hana-cloud-inspection` · `hana-cloud-native-development` · `hana-cloud-validation`
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
Agents and skills install into `$HOME/.copilot` by default during global installation; press Enter to accept or type `n` to skip. In non-interactive installs they are installed automatically. Repository-scoped installation instructions appear below.
|
|
88
88
|
|
|
89
89
|
## ✨ Your SAP development cockpit, inside Copilot Chat
|
|
90
90
|
|
|
@@ -237,10 +237,9 @@ Once the destination server is enabled in Copilot Chat, ask for outcomes instead
|
|
|
237
237
|
| --- | --- |
|
|
238
238
|
| 🎯 **Explicit target** | SAP changes only proceed when the destination and required target details are known. |
|
|
239
239
|
| 🚦 **Explicit state change** | Activation, service publication, and transport creation happen only when requested and authorized. |
|
|
240
|
-
| 👁️ **Optional read-only mode** | `SAP_AI_DEV_TOOLKIT_READ_ONLY=true` removes every write/activate/transport-create tool from the surface and starts VSP with `--transport-read-only`. Recommended for exploration destinations. |
|
|
241
240
|
| 🧪 **Verification first** | The agent uses available lint, syntax, unit-test, ATC, and diagnostics workflows and reports what actually ran. |
|
|
242
241
|
| 🔒 **SAP authorization remains authoritative** | The add-on does not bypass backend SAP permissions. |
|
|
243
|
-
| 🚚 **Curated VSP tool surface** | The proxy exposes
|
|
242
|
+
| 🚚 **Curated VSP tool surface** | The proxy exposes the same curated developer-lifecycle set for every destination, plus local workflow tools; SAP authorizations and VSP safety checks still apply. |
|
|
244
243
|
| 🧱 **Per-destination isolation** | Generated MCP entries are scoped to a single `SAP_AI_DEV_TOOLKIT_DESTINATION`. |
|
|
245
244
|
| 🔑 **No credentials in `mcp.json`** | Authentication material stays in BAS destination configuration rather than MCP config. |
|
|
246
245
|
|
|
@@ -278,6 +277,9 @@ The installer handles VSP provisioning automatically:
|
|
|
278
277
|
|
|
279
278
|
With `H2O_URL` set, an interactive install opens a checkbox picker with no destinations selected by default. Use **Space** to choose destinations and **Enter** to confirm. Press **a** to toggle all destinations (select all if any are unchecked; otherwise clear the selection). Confirming with none selected removes this add-on's managed MCP entries. When the `cf` CLI 8.18 or newer is authenticated to a targeted space, setup first offers an optional import from that space's Destination service; type **y** then **Enter** to include it, or press **Enter** to skip. Accepted CF and BAS destinations appear together in the picker. npm may run its install hook without an interactive terminal, even when the shell is interactive; in that case, selection is skipped without changing MCP config.
|
|
280
279
|
|
|
280
|
+
|
|
281
|
+
The same postinstall installs bundled Copilot agents and skills under `$HOME/.copilot` by default. Press Enter at `[Y/n]` to install or update them; type `n` to leave them unchanged. With no interactive terminal, installation proceeds automatically.
|
|
282
|
+
|
|
281
283
|
Some current npm versions also require install hooks to be approved. If npm reports that `sap-ai-dev-toolkit`'s `postinstall` was blocked, allow it during a fresh install with `npm install --global --allow-scripts=sap-ai-dev-toolkit sap-ai-dev-toolkit`, or run `sap-ai-dev --setup` from an interactive BAS terminal after installation.
|
|
282
284
|
|
|
283
285
|
The setup report uses icons and terminal colors; set `NO_COLOR=1` to disable ANSI colors. The table is a weather report, not a bouncer: green **PASS** means the ADT probe responded, red **FAIL** means it failed, and yellow **SKIPPED** means it was skipped. Probe failures do not block MCP registration or startup for destinations you select.
|
|
@@ -617,8 +619,11 @@ The write and activation tools change SAP state. Confirm the target, package, an
|
|
|
617
619
|
| `GetUserTransports` | Read and group a user's transport requests and tasks; supports organizer filters and source selection. |
|
|
618
620
|
| `GetTransport` | Read a transport request's details, objects, and tasks. |
|
|
619
621
|
| `GetTransportInfo` | Find eligible transports and lock status for an ABAP object or package. |
|
|
622
|
+
| `LockObject` | Lock an ABAP repository object in SAP. |
|
|
623
|
+
| `UnlockObject` | Unlock an ABAP repository object in SAP. |
|
|
620
624
|
| `CreateTransport` | Create a transport request. |
|
|
621
625
|
| `CheckTransportReadiness` | Collect a whitelisted bundle of transport, dependency, inactive-object, ABAP Unit, and ATC evidence. |
|
|
626
|
+
`LockObject` and `UnlockObject` are state-changing VSP tools; the proxy does not retry them after a child crash to avoid duplicate side effects.
|
|
622
627
|
|
|
623
628
|
Transport release and deletion are not exposed by the curated proxy surface; release or delete transports outside this add-on after review.
|
|
624
629
|
|
|
@@ -736,7 +741,6 @@ The response contains a `tools` array. A `RunQuery` entry resembles this excerpt
|
|
|
736
741
|
| `SAP_AI_DEV_TOOLKIT_DISABLE_BAS_RELAY=true` | Disable the built-in BAS destination relay. By default the add-on self-heals `.dest` destinations through a local relay that keeps all access destination-based while handling ADT CSRF fetch/retry behavior before VSP calls SAP. |
|
|
737
742
|
| `SAP_AI_DEV_TOOLKIT_HTTP_PROXY` | Egress proxy for relay and discovery traffic. Takes precedence over `HTTP_PROXY`/`http_proxy`; unset means the default BAS proxy for `.dest` hosts, empty means direct. |
|
|
738
743
|
| `SAP_AI_DEV_TOOLKIT_MAX_CSRF_RETRIES` | Bounded retries after explicit CSRF-session rejection per unsafe request (default 3, maximum 10). Invalid values use the default. |
|
|
739
|
-
| `SAP_AI_DEV_TOOLKIT_READ_ONLY=true` | Read-only mode: hides `WriteSource`, `EditSource`, `Activate`, `ActivateMultiple`, `CreateTransport`, `SetBreakpoint`, and the change-set workflow tools, and starts VSP with `--transport-read-only`. |
|
|
740
744
|
| `SAP_AI_DEV_TOOLKIT_REQUEST_TIMEOUT_MS` | Per-request timeout for calls forwarded to a VSP child (default 600000 = 10 minutes; `0` disables). A stalled request fails with a timeout error; the child is left running. |
|
|
741
745
|
| `SAP_AI_DEV_MCP_CONFIG` | Explicit MCP configuration path; highest precedence. |
|
|
742
746
|
| `SAP_AI_DEV_TOOLKIT_MCP_CONFIG` | Branded compatibility alias for the MCP configuration path. |
|
package/inventory.md
CHANGED
|
@@ -163,7 +163,7 @@ These logical names are exposed through MCP in lowercase snake_case (`lint_abap`
|
|
|
163
163
|
|
|
164
164
|
- Runtime tool names are unprefixed lowercase snake_case (`run_query`) on the normal single-destination server; a `<destination-slug>_` prefix appears only on multi-destination servers. `tools/call` accepts the exact name returned by `tools/list`.
|
|
165
165
|
- The proxy starts VSP with `--enable-transports`; generated MCP entries set `SAP_ALLOW_TRANSPORTABLE_EDITS=true`.
|
|
166
|
-
-
|
|
166
|
+
- The curated VSP tool surface and enabled transport mode are the same for every destination; SAP authorization remains authoritative.
|
|
167
167
|
- `SAP_AI_DEV_TOOLKIT_REQUEST_TIMEOUT_MS` (default 600000) bounds each forwarded call; stalled requests fail without killing the child.
|
|
168
168
|
- Transport release/deletion and the general-purpose `SAP` router are intentionally hidden from direct proxy calls. `GetApplicationLog` is the bounded convenience mapping for the SAP application-log route.
|
|
169
169
|
|
package/package.json
CHANGED
|
@@ -14,7 +14,7 @@ function usage() {
|
|
|
14
14
|
'',
|
|
15
15
|
' (default) Packs the workspace and installs the tarball globally, then',
|
|
16
16
|
' runs the normal postinstall wizard (binary provisioning,',
|
|
17
|
-
' BAS destination setup,
|
|
17
|
+
' BAS destination setup, and default Copilot asset installation).',
|
|
18
18
|
' --link Installs with npm link instead of a tarball; edits to src/',
|
|
19
19
|
' and scripts/ take effect immediately without reinstalling.',
|
|
20
20
|
' --verify Verifies the global sap-ai-dev command resolves to this',
|
package/scripts/postinstall.mjs
CHANGED
|
@@ -68,19 +68,29 @@ async function runInstallSetup() {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
async function runCopilotAssetInstall() {
|
|
71
|
+
const copilotRoot = join(process.env.HOME || homedir(), '.copilot');
|
|
72
|
+
const installAssets = async () => {
|
|
73
|
+
const assets = await installUserCopilotAssets({ root });
|
|
74
|
+
const installed = assets.installed + assets.updated;
|
|
75
|
+
await announce(`Installed ${installed} Copilot files in ${assets.root}; ${assets.unchanged} already current.`, 'success');
|
|
76
|
+
if (assets.conflicts.length > 0) {
|
|
77
|
+
const paths = assets.conflicts.map(path => join(assets.root, path)).join(', ');
|
|
78
|
+
await announce(`Existing Copilot customizations were preserved; review these paths: ${paths}`, 'warning');
|
|
79
|
+
}
|
|
80
|
+
};
|
|
71
81
|
await withInstallTerminal(async terminal => {
|
|
72
82
|
if (!terminal) {
|
|
73
|
-
await announce('
|
|
83
|
+
await announce('Installing bundled agents and skills by default because no interactive terminal is available.', 'progress');
|
|
84
|
+
await installAssets();
|
|
74
85
|
return;
|
|
75
86
|
}
|
|
76
|
-
const copilotRoot = join(process.env.HOME || homedir(), '.copilot');
|
|
77
87
|
await announce([
|
|
78
|
-
'
|
|
88
|
+
'Bundled Copilot agents and skills are installed by default.',
|
|
79
89
|
'',
|
|
80
|
-
'Type
|
|
90
|
+
'Type n then press Enter to skip installing or updating the bundled files.',
|
|
81
91
|
'',
|
|
82
|
-
`${colorText('✅
|
|
83
|
-
`${colorText('⏭️
|
|
92
|
+
`${colorText('✅ Press Enter', 'green', true)} to install or update the bundled agents and all skills.`,
|
|
93
|
+
`${colorText('⏭️ Type n then Enter', 'yellow', true)} to skip this step.`,
|
|
84
94
|
'',
|
|
85
95
|
`${colorText('📁 Target folder:', 'cyan', true)}`,
|
|
86
96
|
` ${copilotRoot}`,
|
|
@@ -89,23 +99,15 @@ async function runCopilotAssetInstall() {
|
|
|
89
99
|
const prompt = createInterface({ input: terminal.input, output: terminal.output });
|
|
90
100
|
let answer;
|
|
91
101
|
try {
|
|
92
|
-
answer = await prompt.question(`${colorText('🤖 Install the bundled agents and all skills?', 'magenta', terminal.output)} ${colorText('[
|
|
102
|
+
answer = await prompt.question(`${colorText('🤖 Install the bundled agents and all skills?', 'magenta', terminal.output)} ${colorText('[Y/n]', 'yellow', terminal.output)} `);
|
|
93
103
|
} finally {
|
|
94
104
|
prompt.close();
|
|
95
105
|
}
|
|
96
|
-
|
|
97
|
-
// every Copilot session on the machine, so it needs an explicit yes.
|
|
98
|
-
if (!/^y(?:es)?$/i.test(answer.trim())) {
|
|
106
|
+
if (/^n(?:o)?$/i.test(answer.trim())) {
|
|
99
107
|
await announce('Copilot agent and skills were skipped. Your files were not changed.', 'info');
|
|
100
108
|
return;
|
|
101
109
|
}
|
|
102
|
-
|
|
103
|
-
const installed = assets.installed + assets.updated;
|
|
104
|
-
await announce(`Installed ${installed} Copilot files in ${assets.root}; ${assets.unchanged} already current.`, 'success');
|
|
105
|
-
if (assets.conflicts.length > 0) {
|
|
106
|
-
const paths = assets.conflicts.map(path => join(assets.root, path)).join(', ');
|
|
107
|
-
await announce(`Existing Copilot customizations were preserved; review these paths: ${paths}`, 'warning');
|
|
108
|
-
}
|
|
110
|
+
await installAssets();
|
|
109
111
|
});
|
|
110
112
|
}
|
|
111
113
|
|
package/src/mcp-proxy.mjs
CHANGED
|
@@ -38,18 +38,6 @@ const APPLICATION_LOG_SCHEMA = {
|
|
|
38
38
|
};
|
|
39
39
|
const APPLICATION_LOG_DESCRIPTION = 'Read SAP application log (SLG1) entries. Results are newest first and limited to 100 by default; set messages=true to include log message details.';
|
|
40
40
|
|
|
41
|
-
// Read-only mode (SAP_AI_DEV_TOOLKIT_READ_ONLY=true) removes every tool that
|
|
42
|
-
// changes SAP state from the public surface and starts VSP with
|
|
43
|
-
// --transport-read-only, so an exploration destination cannot be written to
|
|
44
|
-
// through this proxy even if a chat prompt asks for it.
|
|
45
|
-
const READ_ONLY_HIDDEN_VSP_TOOLS = new Set([
|
|
46
|
-
'Activate',
|
|
47
|
-
'ActivateMultiple',
|
|
48
|
-
'CreateTransport',
|
|
49
|
-
'EditSource',
|
|
50
|
-
'SetBreakpoint',
|
|
51
|
-
'WriteSource'
|
|
52
|
-
]);
|
|
53
41
|
|
|
54
42
|
// Self-healing restarts retry the interrupted tools/call once. Retrying a
|
|
55
43
|
// state-changing tool after a crash can apply the same write twice (the child
|
|
@@ -60,6 +48,8 @@ const NON_RETRIABLE_VSP_TOOLS = new Set([
|
|
|
60
48
|
'ActivateMultiple',
|
|
61
49
|
'CreateTransport',
|
|
62
50
|
'EditSource',
|
|
51
|
+
'LockObject',
|
|
52
|
+
'UnlockObject',
|
|
63
53
|
'WriteSource'
|
|
64
54
|
]);
|
|
65
55
|
|
|
@@ -78,10 +68,6 @@ function requestTimeoutMs(env) {
|
|
|
78
68
|
return parsed > 0 ? Math.floor(parsed) : 0;
|
|
79
69
|
}
|
|
80
70
|
|
|
81
|
-
export function readOnlyMode(env = process.env) {
|
|
82
|
-
const raw = brandedEnvValue(env, 'READ_ONLY');
|
|
83
|
-
return raw !== undefined && ['1', 'true', 'yes'].includes(String(raw).trim().toLowerCase());
|
|
84
|
-
}
|
|
85
71
|
|
|
86
72
|
// Keep the default public VSP surface small enough for developer-lifecycle use.
|
|
87
73
|
// Hidden upstream tools can still be used by local workflow tools when needed.
|
|
@@ -129,6 +115,7 @@ export const PUBLIC_VSP_TOOLS = new Set([
|
|
|
129
115
|
'GrepPackages',
|
|
130
116
|
'ListDependencies',
|
|
131
117
|
'ListTransports',
|
|
118
|
+
'LockObject',
|
|
132
119
|
'PrettyPrint',
|
|
133
120
|
'RunATCCheck',
|
|
134
121
|
'RunQuery',
|
|
@@ -136,15 +123,10 @@ export const PUBLIC_VSP_TOOLS = new Set([
|
|
|
136
123
|
'SearchObject',
|
|
137
124
|
'SetBreakpoint',
|
|
138
125
|
'SyntaxCheck',
|
|
126
|
+
'UnlockObject',
|
|
139
127
|
'WriteSource'
|
|
140
128
|
]);
|
|
141
129
|
|
|
142
|
-
function exposeVspTool(tool, readOnly = false) {
|
|
143
|
-
if (!PUBLIC_VSP_TOOLS.has(tool?.name)) return false;
|
|
144
|
-
// Read-only destinations never expose the write/activate/transport-create
|
|
145
|
-
// surface, even when VSP registers it.
|
|
146
|
-
return !(readOnly && READ_ONLY_HIDDEN_VSP_TOOLS.has(tool.name));
|
|
147
|
-
}
|
|
148
130
|
|
|
149
131
|
// Public tool names are lowercase snake_case. BAS/VS Code chat tool references
|
|
150
132
|
// are lowercase-only, so mixed-case names never bind in the tools picker even
|
|
@@ -210,13 +192,12 @@ function childEnvironment(destination, env) {
|
|
|
210
192
|
|
|
211
193
|
|
|
212
194
|
export function childArguments(destination, env = process.env) {
|
|
213
|
-
// The proxy allowlist
|
|
214
|
-
//
|
|
195
|
+
// The proxy allowlist controls transport operations; source edits are
|
|
196
|
+
// controlled by SAP_ALLOW_TRANSPORTABLE_EDITS and SAP authorizations.
|
|
215
197
|
const mode = brandedEnvValue(env, 'MODE') || 'expert';
|
|
216
198
|
const args = ['--url', destination.url, '--client', destination.client || '001', '--mode', mode];
|
|
217
199
|
if (destination.source !== 'cloud-foundry' || destination.authentication === 'PrincipalPropagation') args.push('--proxy-auth');
|
|
218
|
-
|
|
219
|
-
else args.push('--enable-transports');
|
|
200
|
+
args.push('--enable-transports');
|
|
220
201
|
return args;
|
|
221
202
|
}
|
|
222
203
|
|
|
@@ -394,7 +375,6 @@ export class MCPProxy {
|
|
|
394
375
|
this.log = log;
|
|
395
376
|
this.output = output;
|
|
396
377
|
this.version = version;
|
|
397
|
-
this.readOnly = readOnlyMode(env);
|
|
398
378
|
this.requestTimeoutMs = requestTimeoutMs(env);
|
|
399
379
|
this.children = [];
|
|
400
380
|
this.started = false;
|
|
@@ -663,17 +643,11 @@ export class MCPProxy {
|
|
|
663
643
|
});
|
|
664
644
|
}
|
|
665
645
|
|
|
666
|
-
if (!
|
|
646
|
+
if (!PUBLIC_VSP_TOOLS.has(tool?.name)) continue;
|
|
667
647
|
const name = publicName(tool.name);
|
|
668
648
|
publish(name, { entry, upstream: tool.name }, { ...tool, name, description: `${tool.description || tool.name} [destination: ${entry.destination.name}]` });
|
|
669
649
|
}
|
|
670
|
-
|
|
671
|
-
// read-only mode the hidden write tools must not enable change-set
|
|
672
|
-
// staging either.
|
|
673
|
-
const effectiveUpstream = this.readOnly
|
|
674
|
-
? upstreamTools.filter(tool => !READ_ONLY_HIDDEN_VSP_TOOLS.has(tool.name))
|
|
675
|
-
: upstreamTools;
|
|
676
|
-
for (const localTool of createEngineeringTools(entry, effectiveUpstream, { env: this.env, log: this.log })) {
|
|
650
|
+
for (const localTool of createEngineeringTools(entry, upstreamTools, { env: this.env, log: this.log })) {
|
|
677
651
|
const name = publicName(localTool.definition.name);
|
|
678
652
|
publish(name, { handler: localTool.handler }, {
|
|
679
653
|
...localTool.definition,
|
package/tools.md
CHANGED
|
@@ -77,9 +77,6 @@ The proxy adds local multi-step tools to each destination when their required VS
|
|
|
77
77
|
|
|
78
78
|
`sap-ai-dev --doctor` checks destination probing, VSP startup, the `get_system_info` probe, and MCP tool listing. `sap-ai-dev --demo` runs the sample tools and OData fixtures without contacting SAP; demo writes and transport creation remain in memory until that process exits.
|
|
79
79
|
|
|
80
|
-
### Read-only mode
|
|
81
|
-
|
|
82
|
-
Set `SAP_AI_DEV_TOOLKIT_READ_ONLY=true` (or legacy `BAS_VSP_READ_ONLY`) on a destination server to run it strictly read-only: `WriteSource`, `EditSource`, `Activate`, `ActivateMultiple`, `CreateTransport`, `SetBreakpoint`, and the change-set workflow tools are removed from the surface, and the VSP child starts with `--transport-read-only` so transport writes are rejected upstream as well. Inspection, queries, linting, and checks remain available.
|
|
83
80
|
|
|
84
81
|
### Request timeouts
|
|
85
82
|
|