@mcp-abap-adt/proxy 4.0.1 → 4.1.0
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/CHANGELOG.md +38 -0
- package/README.md +2 -1
- package/bin/mcp-abap-adt-proxy-mcp.js +5 -1
- package/dist/lib/config.d.ts +12 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +18 -3
- package/dist/mcp/environments.d.ts +36 -0
- package/dist/mcp/environments.d.ts.map +1 -0
- package/dist/mcp/environments.js +108 -0
- package/dist/mcp/tools.d.ts +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +35 -3
- package/docs/CLIENT_SETUP.md +2 -1
- package/docs/USAGE.md +2 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,44 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [4.1.0] - 2026-09-24
|
|
11
|
+
|
|
12
|
+
**The management mode can now say which credentials are available, and start a
|
|
13
|
+
proxy with one.** A config says which service to reach; an environment says what
|
|
14
|
+
to authenticate with. Both are chosen by name, so a client picks them without
|
|
15
|
+
being told any paths.
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **`proxy_environments`** — lists the environments in `sessions/`, one SAP
|
|
20
|
+
system's credentials each, by the name `proxy_start` takes. Variable **names**
|
|
21
|
+
only, never values: this is read to help a client choose, and a value here
|
|
22
|
+
would be a credential in a tool result. `*.env.template` and anything that is
|
|
23
|
+
not a `.env` are left out.
|
|
24
|
+
|
|
25
|
+
- **`environment` on `proxy_start`** — optional, and the reason it exists: a
|
|
26
|
+
config that references `${SAP_LOGIN}` without naming an `envFile:` of its own
|
|
27
|
+
had nowhere to get it from, so `proxy_start` failed on exactly the configs a
|
|
28
|
+
user runs with `--env-file` on the command line. A name, not a path, for the
|
|
29
|
+
same reason `config` is a name: `sessions/` sits beside `proxy/` and
|
|
30
|
+
`service-keys/`.
|
|
31
|
+
|
|
32
|
+
One `--env-file` on the management process would not have served: it overrides
|
|
33
|
+
every config's own `envFile:`, so one system's secrets would reach every other
|
|
34
|
+
system started in that session. Per call, it cannot.
|
|
35
|
+
|
|
36
|
+
- `loadConfig(configPath, envFileOverride)` carries it. Precedence, most
|
|
37
|
+
specific first: this argument, then `--env-file`, then the config's own
|
|
38
|
+
`envFile:`.
|
|
39
|
+
|
|
40
|
+
### Unchanged, and deliberately
|
|
41
|
+
|
|
42
|
+
The management mode speaks **stdio only** — no `--transport`, and it listens on
|
|
43
|
+
no port of its own. That is the whole point: the client runs it as a child
|
|
44
|
+
process, and when the client goes the stdio closes and every proxy it started
|
|
45
|
+
goes with it. Over HTTP it would outlive its client and leave ports and tokens
|
|
46
|
+
held, which would be worse than starting proxies by hand.
|
|
47
|
+
|
|
10
48
|
## [4.0.1] - 2026-09-24
|
|
11
49
|
|
|
12
50
|
**A variable from an env file could be silently lost, and the failure blamed the
|
package/README.md
CHANGED
|
@@ -76,7 +76,8 @@ than travelling through a tool call.
|
|
|
76
76
|
| Tool | What it does |
|
|
77
77
|
|---|---|
|
|
78
78
|
| `proxy_configs` | Lists the configs available, by the name `proxy_start` takes. Call it first — the names cannot be guessed. |
|
|
79
|
-
| `
|
|
79
|
+
| `proxy_environments` | Lists the environments available — one SAP system's credentials each, by the name `proxy_start` takes. Variable NAMES only, never values. |
|
|
80
|
+
| `proxy_start` | Starts a proxy from a config and, when the config needs one, an environment. Returns the URL it bound. The **port is not taken from the config**: a free one is bound instead. |
|
|
80
81
|
| `proxy_stop` | Stops a proxy this session started, freeing its port and releasing its credential. Proxies started by other sessions are never touched. |
|
|
81
82
|
| `proxy_status` | Lists this session's proxies and any others on this machine. Records whose process has died are pruned when read, so it cannot report a ghost. |
|
|
82
83
|
|
|
@@ -37,7 +37,11 @@ Tools offered to the client:
|
|
|
37
37
|
proxy_configs List the proxy configs on this machine, by the name
|
|
38
38
|
proxy_start takes. Call this first — the names cannot be
|
|
39
39
|
guessed.
|
|
40
|
-
|
|
40
|
+
proxy_environments
|
|
41
|
+
List the environments — one SAP system's credentials each,
|
|
42
|
+
from sessions/. Variable NAMES only, never values.
|
|
43
|
+
proxy_start Start a proxy from a config plus, when the config needs one,
|
|
44
|
+
an environment. The config supplies
|
|
41
45
|
the destination, target URL, default headers and timeouts;
|
|
42
46
|
the PORT does not come from it — a free one is bound, so
|
|
43
47
|
several proxies can run at once, and the URL returned is the
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -27,7 +27,18 @@ export interface ProxyConfig {
|
|
|
27
27
|
* - If --config is provided, load ONLY from that file
|
|
28
28
|
* - If --config is NOT provided, load ONLY from command line parameters and environment variables
|
|
29
29
|
*/
|
|
30
|
-
export declare function loadConfig(configPath?: string
|
|
30
|
+
export declare function loadConfig(configPath?: string,
|
|
31
|
+
/**
|
|
32
|
+
* The env file for THIS load, ahead of `--env-file` and the config's own
|
|
33
|
+
* `envFile:`.
|
|
34
|
+
*
|
|
35
|
+
* The MCP mode starts a proxy from a config plus an ENVIRONMENT chosen by
|
|
36
|
+
* name, and has no command line of its own to put `--env-file` on. One flag on
|
|
37
|
+
* the management process would not serve either: it overrides every config's
|
|
38
|
+
* own `envFile:`, so one system's secrets would reach every other system
|
|
39
|
+
* started in that session.
|
|
40
|
+
*/
|
|
41
|
+
envFileOverride?: string): ProxyConfig;
|
|
31
42
|
/**
|
|
32
43
|
* Transport-related fields from config file (not part of ProxyConfig but needed by transportConfig)
|
|
33
44
|
*/
|
package/dist/lib/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IAEjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAGxC,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAG/B,OAAO,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;IACzE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IAEjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAGxC,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAG/B,OAAO,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;IACzE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,UAAU,CAAC,EAAE,MAAM;AACnB;;;;;;;;;GASG;AACH,eAAe,CAAC,EAAE,MAAM,GACvB,WAAW,CAkDb;AAwED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,mBAAmB,CAQrB;AAsCD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAYhC;AAmJD;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,SAAS,CAElD;AAUD;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG;IACnD,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAoDA"}
|
package/dist/lib/config.js
CHANGED
|
@@ -53,7 +53,18 @@ const envInterpolation_js_1 = require("./envInterpolation.js");
|
|
|
53
53
|
* - If --config is provided, load ONLY from that file
|
|
54
54
|
* - If --config is NOT provided, load ONLY from command line parameters and environment variables
|
|
55
55
|
*/
|
|
56
|
-
function loadConfig(configPath
|
|
56
|
+
function loadConfig(configPath,
|
|
57
|
+
/**
|
|
58
|
+
* The env file for THIS load, ahead of `--env-file` and the config's own
|
|
59
|
+
* `envFile:`.
|
|
60
|
+
*
|
|
61
|
+
* The MCP mode starts a proxy from a config plus an ENVIRONMENT chosen by
|
|
62
|
+
* name, and has no command line of its own to put `--env-file` on. One flag on
|
|
63
|
+
* the management process would not serve either: it overrides every config's
|
|
64
|
+
* own `envFile:`, so one system's secrets would reach every other system
|
|
65
|
+
* started in that session.
|
|
66
|
+
*/
|
|
67
|
+
envFileOverride) {
|
|
57
68
|
// Get config path from parameter or command line (--config/-c)
|
|
58
69
|
// Do NOT use environment variable MCP_PROXY_CONFIG - only explicit --config parameter
|
|
59
70
|
const finalConfigPath = configPath || getConfigPath();
|
|
@@ -65,7 +76,7 @@ function loadConfig(configPath) {
|
|
|
65
76
|
throw new Error(`Config file not found: ${finalConfigPath}`);
|
|
66
77
|
}
|
|
67
78
|
const fileConfig = loadConfigFile(finalConfigPath);
|
|
68
|
-
const envFilePath = resolveEnvFilePath(fileConfig, finalConfigPath);
|
|
79
|
+
const envFilePath = resolveEnvFilePath(fileConfig, finalConfigPath, envFileOverride);
|
|
69
80
|
const envFileMap = envFilePath ? (0, envInterpolation_js_1.loadEnvFile)(envFilePath) : {};
|
|
70
81
|
const lookup = (0, envInterpolation_js_1.buildLookup)(envFileMap);
|
|
71
82
|
const keys = Object.keys(envFileMap);
|
|
@@ -174,7 +185,11 @@ function loadConfigFile(filePath) {
|
|
|
174
185
|
* cwd); otherwise the YAML `envFile` field, resolved relative to the config
|
|
175
186
|
* file's directory. Returns undefined when neither is set.
|
|
176
187
|
*/
|
|
177
|
-
function resolveEnvFilePath(rawConfig, configPath) {
|
|
188
|
+
function resolveEnvFilePath(rawConfig, configPath, override) {
|
|
189
|
+
// Most specific first: this call, then the command line, then what the config
|
|
190
|
+
// says about itself.
|
|
191
|
+
if (override !== undefined)
|
|
192
|
+
return path.resolve(override);
|
|
178
193
|
const cliEnvFile = getArgValue('--env-file');
|
|
179
194
|
if (cliEnvFile !== undefined)
|
|
180
195
|
return path.resolve(cliEnvFile);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One environment: a `.env` beside the configs, holding one SAP system's
|
|
3
|
+
* credentials.
|
|
4
|
+
*
|
|
5
|
+
* A config names the service to reach; an environment names the credentials to
|
|
6
|
+
* reach it with. They are separate because several configs commonly point at one
|
|
7
|
+
* system — four of the configs in practice all want `e19` — and one config can
|
|
8
|
+
* be run against different systems.
|
|
9
|
+
*/
|
|
10
|
+
export interface EnvironmentEntry {
|
|
11
|
+
/** The file name without its extension — what a client asks for. */
|
|
12
|
+
name: string;
|
|
13
|
+
file: string;
|
|
14
|
+
/**
|
|
15
|
+
* Which variables it defines. Names only, never values: this is read to help
|
|
16
|
+
* a client choose, and a value here would be a credential in a tool result.
|
|
17
|
+
*/
|
|
18
|
+
variables: string[];
|
|
19
|
+
}
|
|
20
|
+
/** Where the environments live, beside `proxy/` and `service-keys/`. */
|
|
21
|
+
export declare function environmentDir(): string;
|
|
22
|
+
/**
|
|
23
|
+
* The environments on disk.
|
|
24
|
+
*
|
|
25
|
+
* One that cannot be read is still listed, with no variables beside it — hiding
|
|
26
|
+
* it would make "no such environment" the answer for a file sitting right there.
|
|
27
|
+
*/
|
|
28
|
+
export declare function listEnvironments(dir?: string): EnvironmentEntry[];
|
|
29
|
+
/**
|
|
30
|
+
* The file an environment name refers to.
|
|
31
|
+
*
|
|
32
|
+
* A name, never a path: `sessions/` sits beside `proxy/` and `service-keys/`,
|
|
33
|
+
* and the value comes from a language model.
|
|
34
|
+
*/
|
|
35
|
+
export declare function resolveEnvironment(name: string, dir?: string): string;
|
|
36
|
+
//# sourceMappingURL=environments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environments.d.ts","sourceRoot":"","sources":["../../src/mcp/environments.ts"],"names":[],"mappings":"AAKA;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,wEAAwE;AACxE,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,GAAE,MAAyB,GAC7B,gBAAgB,EAAE,CAgCpB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,GAAG,GAAE,MAAyB,GAC7B,MAAM,CAmBR"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.environmentDir = environmentDir;
|
|
37
|
+
exports.listEnvironments = listEnvironments;
|
|
38
|
+
exports.resolveEnvironment = resolveEnvironment;
|
|
39
|
+
// src/mcp/environments.ts
|
|
40
|
+
const node_fs_1 = require("node:fs");
|
|
41
|
+
const path = __importStar(require("node:path"));
|
|
42
|
+
const stores_js_1 = require("../lib/stores.js");
|
|
43
|
+
/** Where the environments live, beside `proxy/` and `service-keys/`. */
|
|
44
|
+
function environmentDir() {
|
|
45
|
+
return (0, stores_js_1.storeDir)('sessions');
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The environments on disk.
|
|
49
|
+
*
|
|
50
|
+
* One that cannot be read is still listed, with no variables beside it — hiding
|
|
51
|
+
* it would make "no such environment" the answer for a file sitting right there.
|
|
52
|
+
*/
|
|
53
|
+
function listEnvironments(dir = environmentDir()) {
|
|
54
|
+
if (!(0, node_fs_1.existsSync)(dir))
|
|
55
|
+
return [];
|
|
56
|
+
const entries = [];
|
|
57
|
+
for (const name of (0, node_fs_1.readdirSync)(dir).sort()) {
|
|
58
|
+
// `.env` exactly: this leaves out `e19.env.template`, whose extension is
|
|
59
|
+
// `.template`, along with notes and anything else kept in the folder.
|
|
60
|
+
if (path.extname(name).toLowerCase() !== '.env')
|
|
61
|
+
continue;
|
|
62
|
+
const file = path.join(dir, name);
|
|
63
|
+
try {
|
|
64
|
+
if (!(0, node_fs_1.statSync)(file).isFile())
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const entry = {
|
|
71
|
+
name: path.basename(name, '.env'),
|
|
72
|
+
file,
|
|
73
|
+
variables: [],
|
|
74
|
+
};
|
|
75
|
+
try {
|
|
76
|
+
for (const line of (0, node_fs_1.readFileSync)(file, 'utf-8').split(/\r?\n/)) {
|
|
77
|
+
const match = line.match(/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=/);
|
|
78
|
+
if (match)
|
|
79
|
+
entry.variables.push(match[1]);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// Listed with no variables. Whoever starts a proxy with it gets the real
|
|
84
|
+
// failure, against a name the caller chose.
|
|
85
|
+
}
|
|
86
|
+
entries.push(entry);
|
|
87
|
+
}
|
|
88
|
+
return entries;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The file an environment name refers to.
|
|
92
|
+
*
|
|
93
|
+
* A name, never a path: `sessions/` sits beside `proxy/` and `service-keys/`,
|
|
94
|
+
* and the value comes from a language model.
|
|
95
|
+
*/
|
|
96
|
+
function resolveEnvironment(name, dir = environmentDir()) {
|
|
97
|
+
if (name.includes('/') || name.includes('\\') || name.includes('..')) {
|
|
98
|
+
throw new Error(`Invalid environment name "${name}": it must be a name from ${dir}, not a path.`);
|
|
99
|
+
}
|
|
100
|
+
const available = listEnvironments(dir);
|
|
101
|
+
const found = available.find((entry) => entry.name === name || path.basename(entry.file) === name);
|
|
102
|
+
if (found)
|
|
103
|
+
return found.file;
|
|
104
|
+
const known = available.map((entry) => entry.name).join(', ');
|
|
105
|
+
throw new Error(known
|
|
106
|
+
? `No environment named "${name}" in ${dir}. Available: ${known}`
|
|
107
|
+
: `No environments found in ${dir}.`);
|
|
108
|
+
}
|
package/dist/mcp/tools.d.ts
CHANGED
|
@@ -24,5 +24,5 @@ export interface ProxyTool {
|
|
|
24
24
|
inputSchema: z.ZodRawShape;
|
|
25
25
|
handler: (args: Record<string, unknown>) => Promise<ToolResult>;
|
|
26
26
|
}
|
|
27
|
-
export declare function createProxyTools(supervisor: ProxySupervisor, configDir?: string): ProxyTool[];
|
|
27
|
+
export declare function createProxyTools(supervisor: ProxySupervisor, configDir?: string, envDir?: string): ProxyTool[];
|
|
28
28
|
//# sourceMappingURL=tools.d.ts.map
|
package/dist/mcp/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAaxB,OAAO,EAA2B,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEhF;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,QAGc,CAAC;AAE7C,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC;IAC3B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;CACjE;AAMD,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,eAAe,EAC3B,SAAS,GAAE,MAAyB,EACpC,MAAM,GAAE,MAAyB,GAChC,SAAS,EAAE,CAmMb"}
|
package/dist/mcp/tools.js
CHANGED
|
@@ -6,6 +6,7 @@ exports.createProxyTools = createProxyTools;
|
|
|
6
6
|
const zod_1 = require("zod");
|
|
7
7
|
const config_js_1 = require("../lib/config.js");
|
|
8
8
|
const configs_js_1 = require("./configs.js");
|
|
9
|
+
const environments_js_1 = require("./environments.js");
|
|
9
10
|
const supervisor_js_1 = require("./supervisor.js");
|
|
10
11
|
/**
|
|
11
12
|
* The thing the client has to keep being told.
|
|
@@ -23,8 +24,30 @@ exports.SHUTDOWN_REMINDER = 'When you are finished with this proxy, call proxy_s
|
|
|
23
24
|
const text = (body) => ({
|
|
24
25
|
content: [{ type: 'text', text: body }],
|
|
25
26
|
});
|
|
26
|
-
function createProxyTools(supervisor, configDir = (0, configs_js_1.proxyConfigDir)()) {
|
|
27
|
+
function createProxyTools(supervisor, configDir = (0, configs_js_1.proxyConfigDir)(), envDir = (0, environments_js_1.environmentDir)()) {
|
|
27
28
|
return [
|
|
29
|
+
{
|
|
30
|
+
name: 'proxy_environments',
|
|
31
|
+
title: 'List the environments available',
|
|
32
|
+
description: 'List the environments on this machine, by the name proxy_start takes. ' +
|
|
33
|
+
'An environment is one SAP system\u2019s credentials; a config says which ' +
|
|
34
|
+
'service to reach, an environment says what to authenticate with. ' +
|
|
35
|
+
'Several configs commonly want the same environment. Variable NAMES are ' +
|
|
36
|
+
'shown, never their values.',
|
|
37
|
+
inputSchema: {},
|
|
38
|
+
handler: async () => {
|
|
39
|
+
const environments = (0, environments_js_1.listEnvironments)(envDir);
|
|
40
|
+
if (environments.length === 0) {
|
|
41
|
+
return text(`No environments found in ${envDir}.`);
|
|
42
|
+
}
|
|
43
|
+
return text([
|
|
44
|
+
`Environments in ${envDir}:`,
|
|
45
|
+
...environments.map((e) => ` ${e.name}${e.variables.length ? ` — ${e.variables.join(', ')}` : ' — (none readable)'}`),
|
|
46
|
+
'',
|
|
47
|
+
'Pass one to proxy_start as "environment" when the config uses ${VAR}.',
|
|
48
|
+
].join('\n'));
|
|
49
|
+
},
|
|
50
|
+
},
|
|
28
51
|
{
|
|
29
52
|
name: 'proxy_configs',
|
|
30
53
|
title: 'List the proxy configs available',
|
|
@@ -56,7 +79,7 @@ function createProxyTools(supervisor, configDir = (0, configs_js_1.proxyConfigDi
|
|
|
56
79
|
{
|
|
57
80
|
name: 'proxy_start',
|
|
58
81
|
title: 'Start an authenticating proxy',
|
|
59
|
-
description: 'Start a local proxy from
|
|
82
|
+
description: 'Start a local proxy from a config and, when the config needs one, an environment. The ' +
|
|
60
83
|
'config supplies the destination, target URL, default headers and ' +
|
|
61
84
|
'timeouts — including any credentials, which stay in the config and ' +
|
|
62
85
|
'are never passed through here. The port is NOT taken from the config: ' +
|
|
@@ -66,6 +89,10 @@ function createProxyTools(supervisor, configDir = (0, configs_js_1.proxyConfigDi
|
|
|
66
89
|
config: zod_1.z
|
|
67
90
|
.string()
|
|
68
91
|
.describe('Name of a proxy config, as proxy_configs lists it (for example "nvcr_d24").'),
|
|
92
|
+
environment: zod_1.z
|
|
93
|
+
.string()
|
|
94
|
+
.optional()
|
|
95
|
+
.describe('Name of an environment, as proxy_environments lists it (for example "e19"). Supplies the ${VAR} values the config references. Needed when the config names no envFile of its own — proxy_configs marks those.'),
|
|
69
96
|
idleTimeoutMs: zod_1.z
|
|
70
97
|
.number()
|
|
71
98
|
.optional()
|
|
@@ -74,14 +101,19 @@ function createProxyTools(supervisor, configDir = (0, configs_js_1.proxyConfigDi
|
|
|
74
101
|
handler: async (args) => {
|
|
75
102
|
const name = String(args.config);
|
|
76
103
|
const file = (0, configs_js_1.resolveProxyConfig)(name, configDir);
|
|
104
|
+
const environment = args.environment;
|
|
105
|
+
const envFile = environment
|
|
106
|
+
? (0, environments_js_1.resolveEnvironment)(environment, envDir)
|
|
107
|
+
: undefined;
|
|
77
108
|
const started = await supervisor.start({
|
|
78
109
|
name,
|
|
79
|
-
config: (0, config_js_1.loadConfig)(file),
|
|
110
|
+
config: (0, config_js_1.loadConfig)(file, envFile),
|
|
80
111
|
idleTimeoutMs: args.idleTimeoutMs,
|
|
81
112
|
});
|
|
82
113
|
return text([
|
|
83
114
|
`Proxy running at ${started.url}`,
|
|
84
115
|
` config: ${started.name}`,
|
|
116
|
+
` environment: ${environment ?? "(the config's own, or the environment)"}`,
|
|
85
117
|
` instanceId: ${started.instanceId}`,
|
|
86
118
|
` destination: ${started.destination}`,
|
|
87
119
|
'',
|
package/docs/CLIENT_SETUP.md
CHANGED
|
@@ -243,7 +243,8 @@ It works from the configs in `~/.config/mcp-abap-adt/proxy/` — the same files
|
|
|
243
243
|
| Tool | |
|
|
244
244
|
|---|---|
|
|
245
245
|
| `proxy_configs` | the names available; call it first, they cannot be guessed |
|
|
246
|
-
| `
|
|
246
|
+
| `proxy_environments` | the environments available — one SAP system's credentials each. Variable names only, never values |
|
|
247
|
+
| `proxy_start` | starts one on a **free port** and returns the URL bound. Takes `environment` when the config uses `${VAR}` and names no `envFile` |
|
|
247
248
|
| `proxy_stop` | frees the port and releases the credential; never touches another session's proxy |
|
|
248
249
|
| `proxy_status` | this session's proxies and everyone else's, dead records pruned on read |
|
|
249
250
|
|
package/docs/USAGE.md
CHANGED
|
@@ -155,7 +155,8 @@ It works from the configs in `~/.config/mcp-abap-adt/proxy/` — the same files
|
|
|
155
155
|
| Tool | |
|
|
156
156
|
|---|---|
|
|
157
157
|
| `proxy_configs` | the names available; call it first, they cannot be guessed |
|
|
158
|
-
| `
|
|
158
|
+
| `proxy_environments` | the environments available — one SAP system's credentials each. Variable names only, never values |
|
|
159
|
+
| `proxy_start` | starts one on a **free port** and returns the URL bound. Takes `environment` when the config uses `${VAR}` and names no `envFile` |
|
|
159
160
|
| `proxy_stop` | frees the port and releases the credential; never touches another session's proxy |
|
|
160
161
|
| `proxy_status` | this session's proxies and everyone else's, dead records pruned on read |
|
|
161
162
|
|
package/package.json
CHANGED