arc-1 0.4.4 → 0.6.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.
Files changed (84) hide show
  1. package/README.md +6 -5
  2. package/dist/adt/client.d.ts +11 -1
  3. package/dist/adt/client.d.ts.map +1 -1
  4. package/dist/adt/client.js +51 -1
  5. package/dist/adt/client.js.map +1 -1
  6. package/dist/adt/codeintel.js +1 -1
  7. package/dist/adt/codeintel.js.map +1 -1
  8. package/dist/adt/crud.d.ts.map +1 -1
  9. package/dist/adt/crud.js +1 -7
  10. package/dist/adt/crud.js.map +1 -1
  11. package/dist/adt/features.d.ts +29 -1
  12. package/dist/adt/features.d.ts.map +1 -1
  13. package/dist/adt/features.js +114 -2
  14. package/dist/adt/features.js.map +1 -1
  15. package/dist/adt/http.d.ts +24 -1
  16. package/dist/adt/http.d.ts.map +1 -1
  17. package/dist/adt/http.js +87 -28
  18. package/dist/adt/http.js.map +1 -1
  19. package/dist/adt/oauth.d.ts +19 -2
  20. package/dist/adt/oauth.d.ts.map +1 -1
  21. package/dist/adt/oauth.js +78 -28
  22. package/dist/adt/oauth.js.map +1 -1
  23. package/dist/adt/safety.d.ts +15 -7
  24. package/dist/adt/safety.d.ts.map +1 -1
  25. package/dist/adt/safety.js +49 -45
  26. package/dist/adt/safety.js.map +1 -1
  27. package/dist/adt/types.d.ts +33 -0
  28. package/dist/adt/types.d.ts.map +1 -1
  29. package/dist/adt/xml-parser.d.ts +10 -1
  30. package/dist/adt/xml-parser.d.ts.map +1 -1
  31. package/dist/adt/xml-parser.js +47 -0
  32. package/dist/adt/xml-parser.js.map +1 -1
  33. package/dist/aff/schemas/bdef-v1.json +62 -0
  34. package/dist/aff/schemas/clas-v1.json +276 -0
  35. package/dist/aff/schemas/ddls-v1.json +144 -0
  36. package/dist/aff/schemas/intf-v1.json +243 -0
  37. package/dist/aff/schemas/prog-v1.json +133 -0
  38. package/dist/aff/schemas/srvb-v1.json +115 -0
  39. package/dist/aff/schemas/srvd-v1.json +108 -0
  40. package/dist/aff/validator.d.ts +14 -0
  41. package/dist/aff/validator.d.ts.map +1 -0
  42. package/dist/aff/validator.js +83 -0
  43. package/dist/aff/validator.js.map +1 -0
  44. package/dist/handlers/hyperfocused.d.ts +1 -0
  45. package/dist/handlers/hyperfocused.d.ts.map +1 -1
  46. package/dist/handlers/hyperfocused.js +7 -6
  47. package/dist/handlers/hyperfocused.js.map +1 -1
  48. package/dist/handlers/intent.d.ts +17 -1
  49. package/dist/handlers/intent.d.ts.map +1 -1
  50. package/dist/handlers/intent.js +369 -27
  51. package/dist/handlers/intent.js.map +1 -1
  52. package/dist/handlers/schemas.d.ts +296 -0
  53. package/dist/handlers/schemas.d.ts.map +1 -0
  54. package/dist/handlers/schemas.js +250 -0
  55. package/dist/handlers/schemas.js.map +1 -0
  56. package/dist/handlers/tools.d.ts +1 -1
  57. package/dist/handlers/tools.d.ts.map +1 -1
  58. package/dist/handlers/tools.js +111 -42
  59. package/dist/handlers/tools.js.map +1 -1
  60. package/dist/handlers/zod-errors.d.ts +20 -0
  61. package/dist/handlers/zod-errors.d.ts.map +1 -0
  62. package/dist/handlers/zod-errors.js +43 -0
  63. package/dist/handlers/zod-errors.js.map +1 -0
  64. package/dist/server/config.d.ts +26 -0
  65. package/dist/server/config.d.ts.map +1 -1
  66. package/dist/server/config.js +156 -7
  67. package/dist/server/config.js.map +1 -1
  68. package/dist/server/http.d.ts +8 -0
  69. package/dist/server/http.d.ts.map +1 -1
  70. package/dist/server/http.js +134 -71
  71. package/dist/server/http.js.map +1 -1
  72. package/dist/server/server.d.ts +13 -2
  73. package/dist/server/server.d.ts.map +1 -1
  74. package/dist/server/server.js +82 -9
  75. package/dist/server/server.js.map +1 -1
  76. package/dist/server/types.d.ts +8 -1
  77. package/dist/server/types.d.ts.map +1 -1
  78. package/dist/server/types.js +2 -2
  79. package/dist/server/types.js.map +1 -1
  80. package/dist/server/xsuaa.d.ts +11 -1
  81. package/dist/server/xsuaa.d.ts.map +1 -1
  82. package/dist/server/xsuaa.js +127 -9
  83. package/dist/server/xsuaa.js.map +1 -1
  84. package/package.json +4 -3
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Format Zod validation errors into LLM-friendly messages.
3
+ *
4
+ * Produces structured error text with field paths and expected values,
5
+ * consistent with the existing errorResult() pattern in intent.ts.
6
+ */
7
+ /**
8
+ * Format a ZodError into an LLM-friendly multi-line string.
9
+ *
10
+ * Example output:
11
+ * Invalid arguments for SAPRead:
12
+ * - "type": expected one of: PROG, CLAS, INTF, ..., got "PROGG"
13
+ * - "maxRows": expected number, got string
14
+ *
15
+ * Hint: Check the tool schema for valid parameter types and values.
16
+ */
17
+ // biome-ignore lint/suspicious/noExplicitAny: accepts any Zod error shape
18
+ export function formatZodError(error, toolName) {
19
+ const issues = error.issues.map((issue) => {
20
+ const path = issue.path.length > 0 ? `"${issue.path.join('.')}"` : 'input';
21
+ // Zod v4 uses 'code' to distinguish issue types
22
+ if (issue.code === 'invalid_value' && issue.values) {
23
+ return `${path}: expected one of: ${issue.values.join(', ')}`;
24
+ }
25
+ if (issue.code === 'invalid_type') {
26
+ if (issue.input === undefined) {
27
+ return `${path}: required (expected ${issue.expected ?? 'value'})`;
28
+ }
29
+ return `${path}: expected ${issue.expected ?? 'value'}, got ${typeof issue.input}`;
30
+ }
31
+ if (issue.code === 'unrecognized_keys' && issue.keys) {
32
+ return `Unknown parameter(s): ${issue.keys.join(', ')}`;
33
+ }
34
+ return `${path}: ${issue.message}`;
35
+ });
36
+ return [
37
+ `Invalid arguments for ${toolName}:`,
38
+ ...issues.map((i) => ` - ${i}`),
39
+ '',
40
+ 'Hint: Check the tool schema for valid parameter types and values.',
41
+ ].join('\n');
42
+ }
43
+ //# sourceMappingURL=zod-errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zod-errors.js","sourceRoot":"","sources":["../../src/handlers/zod-errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;GASG;AACH,0EAA0E;AAC1E,MAAM,UAAU,cAAc,CAAC,KAAqC,EAAE,QAAgB;IACpF,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACxC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;QAE3E,gDAAgD;QAChD,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACnD,OAAO,GAAG,IAAI,sBAAsB,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAChE,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YAClC,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC9B,OAAO,GAAG,IAAI,wBAAwB,KAAK,CAAC,QAAQ,IAAI,OAAO,GAAG,CAAC;YACrE,CAAC;YACD,OAAO,GAAG,IAAI,cAAc,KAAK,CAAC,QAAQ,IAAI,OAAO,SAAS,OAAO,KAAK,CAAC,KAAK,EAAE,CAAC;QACrF,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,mBAAmB,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YACrD,OAAO,yBAAyB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1D,CAAC;QAED,OAAO,GAAG,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,yBAAyB,QAAQ,GAAG;QACpC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,EAAE;QACF,mEAAmE;KACpE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -8,6 +8,27 @@
8
8
  * for drop-in compatibility with existing deployments and documentation.
9
9
  */
10
10
  import type { ServerConfig } from './types.js';
11
+ /**
12
+ * Parse API keys string into structured array.
13
+ * Format: "key1:profile1,key2:profile2"
14
+ * Each entry maps an API key to a named profile.
15
+ */
16
+ export declare function parseApiKeys(raw: string): Array<{
17
+ key: string;
18
+ profile: string;
19
+ }>;
20
+ /**
21
+ * Maps profile names to the scopes they grant.
22
+ * Used when API keys are assigned to profiles — the key inherits these scopes.
23
+ * Kept in sync with PROFILES: each profile's safety flags determine its scopes.
24
+ */
25
+ export declare const PROFILE_SCOPES: Record<string, string[]>;
26
+ /**
27
+ * Named profiles — convenience presets for common safety configurations.
28
+ * Each profile sets a combination of safety flags. Individual CLI flags
29
+ * applied after the profile can override any profile default.
30
+ */
31
+ export declare const PROFILES: Record<string, Partial<ServerConfig>>;
11
32
  /**
12
33
  * Parse CLI arguments and environment variables into a ServerConfig.
13
34
  *
@@ -16,4 +37,9 @@ import type { ServerConfig } from './types.js';
16
37
  * Commander is used for the full CLI (cli.ts), not the server startup.
17
38
  */
18
39
  export declare function parseArgs(args: string[]): ServerConfig;
40
+ /**
41
+ * Validate configuration for internally consistent auth settings.
42
+ * Fails fast at startup for invalid or dangerous config combinations.
43
+ */
44
+ export declare function validateConfig(config: ServerConfig): void;
19
45
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAiB,YAAY,EAAiB,MAAM,YAAY,CAAC;AAG7E;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,YAAY,CA2HtD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAiB,YAAY,EAAiB,MAAM,YAAY,CAAC;AAG7E;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA8BjF;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAOnD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,CAwC1D,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,YAAY,CAiKtD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAkBzD"}
@@ -8,6 +8,98 @@
8
8
  * for drop-in compatibility with existing deployments and documentation.
9
9
  */
10
10
  import { DEFAULT_CONFIG } from './types.js';
11
+ /**
12
+ * Parse API keys string into structured array.
13
+ * Format: "key1:profile1,key2:profile2"
14
+ * Each entry maps an API key to a named profile.
15
+ */
16
+ export function parseApiKeys(raw) {
17
+ const entries = [];
18
+ for (const pair of raw.split(',')) {
19
+ const trimmed = pair.trim();
20
+ if (!trimmed)
21
+ continue;
22
+ // Use LAST colon as separator — keys may contain colons (e.g. base64)
23
+ // but profile names never do
24
+ const colonIdx = trimmed.lastIndexOf(':');
25
+ if (colonIdx === -1) {
26
+ throw new Error(`Invalid API key entry '${trimmed}': expected 'key:profile' format. ` +
27
+ `Valid profiles: ${Object.keys(PROFILES).join(', ')}`);
28
+ }
29
+ const key = trimmed.slice(0, colonIdx);
30
+ const profile = trimmed.slice(colonIdx + 1);
31
+ if (!key) {
32
+ throw new Error('Invalid API key entry: key cannot be empty');
33
+ }
34
+ if (!PROFILES[profile]) {
35
+ throw new Error(`Invalid profile '${profile}' in API key entry. Valid profiles: ${Object.keys(PROFILES).join(', ')}`);
36
+ }
37
+ entries.push({ key, profile });
38
+ }
39
+ if (entries.length === 0) {
40
+ throw new Error('ARC1_API_KEYS is set but contains no valid entries. Format: "key1:profile1,key2:profile2"');
41
+ }
42
+ return entries;
43
+ }
44
+ /**
45
+ * Maps profile names to the scopes they grant.
46
+ * Used when API keys are assigned to profiles — the key inherits these scopes.
47
+ * Kept in sync with PROFILES: each profile's safety flags determine its scopes.
48
+ */
49
+ export const PROFILE_SCOPES = {
50
+ viewer: ['read'],
51
+ 'viewer-data': ['read', 'data'],
52
+ 'viewer-sql': ['read', 'data', 'sql'],
53
+ developer: ['read', 'write'],
54
+ 'developer-data': ['read', 'write', 'data'],
55
+ 'developer-sql': ['read', 'write', 'data', 'sql'],
56
+ };
57
+ /**
58
+ * Named profiles — convenience presets for common safety configurations.
59
+ * Each profile sets a combination of safety flags. Individual CLI flags
60
+ * applied after the profile can override any profile default.
61
+ */
62
+ export const PROFILES = {
63
+ viewer: {
64
+ readOnly: true,
65
+ blockData: true,
66
+ blockFreeSQL: true,
67
+ enableTransports: false,
68
+ },
69
+ 'viewer-data': {
70
+ readOnly: true,
71
+ blockData: false,
72
+ blockFreeSQL: true,
73
+ enableTransports: false,
74
+ },
75
+ 'viewer-sql': {
76
+ readOnly: true,
77
+ blockData: false,
78
+ blockFreeSQL: false,
79
+ enableTransports: false,
80
+ },
81
+ developer: {
82
+ readOnly: false,
83
+ blockData: true,
84
+ blockFreeSQL: true,
85
+ enableTransports: true,
86
+ allowedPackages: ['$TMP'],
87
+ },
88
+ 'developer-data': {
89
+ readOnly: false,
90
+ blockData: false,
91
+ blockFreeSQL: true,
92
+ enableTransports: true,
93
+ allowedPackages: ['$TMP'],
94
+ },
95
+ 'developer-sql': {
96
+ readOnly: false,
97
+ blockData: false,
98
+ blockFreeSQL: false,
99
+ enableTransports: true,
100
+ allowedPackages: ['$TMP'],
101
+ },
102
+ };
11
103
  /**
12
104
  * Parse CLI arguments and environment variables into a ServerConfig.
13
105
  *
@@ -60,15 +152,42 @@ export function parseArgs(args) {
60
152
  const transport = resolve('transport', 'SAP_TRANSPORT', 'stdio');
61
153
  config.transport = (transport === 'http-streamable' ? 'http-streamable' : 'stdio');
62
154
  config.httpAddr = resolve('http-addr', 'SAP_HTTP_ADDR', '0.0.0.0:8080');
63
- // --- Safety ---
64
- config.readOnly = resolveBool('read-only', 'SAP_READ_ONLY', false);
65
- config.blockFreeSQL = resolveBool('block-free-sql', 'SAP_BLOCK_FREE_SQL', false);
155
+ // --- Profile (apply before individual safety flags so flags can override) ---
156
+ const profileName = getFlag('profile') ?? process.env.ARC1_PROFILE;
157
+ if (profileName) {
158
+ const profile = PROFILES[profileName];
159
+ if (!profile) {
160
+ throw new Error(`Unknown profile '${profileName}'. Valid profiles: ${Object.keys(PROFILES).join(', ')}`);
161
+ }
162
+ Object.assign(config, profile);
163
+ }
164
+ // --- Safety (individual flags override profile defaults) ---
165
+ // Only override profile defaults when the flag/env is explicitly set
166
+ const readOnlyExplicit = getFlag('read-only') ?? process.env.SAP_READ_ONLY;
167
+ if (readOnlyExplicit !== undefined)
168
+ config.readOnly = readOnlyExplicit === 'true' || readOnlyExplicit === '1';
169
+ else if (!profileName)
170
+ config.readOnly = false;
171
+ const blockFreeSQLExplicit = getFlag('block-free-sql') ?? process.env.SAP_BLOCK_FREE_SQL;
172
+ if (blockFreeSQLExplicit !== undefined)
173
+ config.blockFreeSQL = blockFreeSQLExplicit === 'true' || blockFreeSQLExplicit === '1';
174
+ else if (!profileName)
175
+ config.blockFreeSQL = false;
176
+ const blockDataExplicit = getFlag('block-data') ?? process.env.SAP_BLOCK_DATA;
177
+ if (blockDataExplicit !== undefined)
178
+ config.blockData = blockDataExplicit === 'true' || blockDataExplicit === '1';
179
+ else if (!profileName)
180
+ config.blockData = false;
66
181
  config.allowedOps = resolve('allowed-ops', 'SAP_ALLOWED_OPS', '');
67
182
  config.disallowedOps = resolve('disallowed-ops', 'SAP_DISALLOWED_OPS', '');
68
- const pkgs = resolve('allowed-packages', 'SAP_ALLOWED_PACKAGES', '');
69
- config.allowedPackages = pkgs ? pkgs.split(',').map((p) => p.trim()) : [];
70
- config.allowTransportableEdits = resolveBool('allow-transportable-edits', 'SAP_ALLOW_TRANSPORTABLE_EDITS', false);
71
- config.enableTransports = resolveBool('enable-transports', 'SAP_ENABLE_TRANSPORTS', false);
183
+ const pkgs = getFlag('allowed-packages') ?? process.env.SAP_ALLOWED_PACKAGES;
184
+ if (pkgs)
185
+ config.allowedPackages = pkgs.split(',').map((p) => p.trim());
186
+ const enableTransportsExplicit = getFlag('enable-transports') ?? process.env.SAP_ENABLE_TRANSPORTS;
187
+ if (enableTransportsExplicit !== undefined)
188
+ config.enableTransports = enableTransportsExplicit === 'true' || enableTransportsExplicit === '1';
189
+ else if (!profileName)
190
+ config.enableTransports = false;
72
191
  // --- Features ---
73
192
  config.featureAbapGit = resolveFeature('feature-abapgit', 'SAP_FEATURE_ABAPGIT');
74
193
  config.featureRap = resolveFeature('feature-rap', 'SAP_FEATURE_RAP');
@@ -81,8 +200,18 @@ export function parseArgs(args) {
81
200
  config.systemType = (['btp', 'onprem'].includes(systemType) ? systemType : 'auto');
82
201
  // --- Authentication (MCP client → ARC-1) ---
83
202
  config.apiKey = getFlag('api-key') ?? process.env.ARC1_API_KEY;
203
+ // Multiple API keys with per-key profiles: "key1:viewer,key2:developer"
204
+ const apiKeysRaw = getFlag('api-keys') ?? process.env.ARC1_API_KEYS;
205
+ if (apiKeysRaw) {
206
+ config.apiKeys = parseApiKeys(apiKeysRaw);
207
+ }
84
208
  config.oidcIssuer = getFlag('oidc-issuer') ?? process.env.SAP_OIDC_ISSUER;
85
209
  config.oidcAudience = getFlag('oidc-audience') ?? process.env.SAP_OIDC_AUDIENCE;
210
+ const clockTolerance = getFlag('oidc-clock-tolerance') ?? process.env.SAP_OIDC_CLOCK_TOLERANCE;
211
+ if (clockTolerance) {
212
+ const parsed = Number.parseInt(clockTolerance, 10);
213
+ config.oidcClockTolerance = Number.isNaN(parsed) ? undefined : parsed;
214
+ }
86
215
  config.xsuaaAuth = resolveBool('xsuaa-auth', 'SAP_XSUAA_AUTH', false);
87
216
  // --- BTP ABAP Environment (direct connection via service key) ---
88
217
  config.btpServiceKey = getFlag('btp-service-key') ?? process.env.SAP_BTP_SERVICE_KEY;
@@ -116,6 +245,26 @@ export function parseArgs(args) {
116
245
  if (config.verbose) {
117
246
  config.logLevel = 'debug';
118
247
  }
248
+ // --- Startup Validation ---
249
+ validateConfig(config);
119
250
  return config;
120
251
  }
252
+ /**
253
+ * Validate configuration for internally consistent auth settings.
254
+ * Fails fast at startup for invalid or dangerous config combinations.
255
+ */
256
+ export function validateConfig(config) {
257
+ // OIDC: audience is required when issuer is set (RFC 9700 §2.3 audience restriction)
258
+ if (config.oidcIssuer && !config.oidcAudience) {
259
+ throw new Error('SAP_OIDC_AUDIENCE is required when SAP_OIDC_ISSUER is set — ' +
260
+ 'audience validation prevents token confusion across services (RFC 9700 §2.3)');
261
+ }
262
+ if (config.oidcAudience && !config.oidcIssuer) {
263
+ throw new Error('SAP_OIDC_ISSUER is required when SAP_OIDC_AUDIENCE is set');
264
+ }
265
+ // PP: ppStrict requires ppEnabled
266
+ if (config.ppStrict && !config.ppEnabled) {
267
+ throw new Error('SAP_PP_STRICT=true requires SAP_PP_ENABLED=true — strict mode has no effect without principal propagation enabled');
268
+ }
269
+ }
121
270
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"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"}
@@ -31,4 +31,12 @@ import type { XsuaaCredentials } from './xsuaa.js';
31
31
  * Start the HTTP Streamable server.
32
32
  */
33
33
  export declare function startHttpServer(serverFactory: () => McpServer, config: ServerConfig, xsuaaCredentials?: XsuaaCredentials): Promise<void>;
34
+ /**
35
+ * Extract scopes from an OIDC JWT payload.
36
+ *
37
+ * Tries `scope` (space-separated string, standard OIDC) then `scp` (array, Azure AD style).
38
+ * Filters to known scopes, applies implied scope expansion, and falls back to read-only
39
+ * when no scope claims are present (safe default for providers that don't emit scopes).
40
+ */
41
+ export declare function extractOidcScopes(payload: Record<string, unknown>): string[];
34
42
  //# sourceMappingURL=http.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/server/http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,2CAA2C,CAAC;AAMrF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA4CnD;;GAEG;AACH,wBAAsB,eAAe,CACnC,aAAa,EAAE,MAAM,SAAS,EAC9B,MAAM,EAAE,YAAY,EACpB,gBAAgB,CAAC,EAAE,gBAAgB,GAClC,OAAO,CAAC,IAAI,CAAC,CAiKf"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/server/http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,2CAA2C,CAAC;AAQrF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAsEnD;;GAEG;AACH,wBAAsB,eAAe,CACnC,aAAa,EAAE,MAAM,SAAS,EAC9B,MAAM,EAAE,YAAY,EACpB,gBAAgB,CAAC,EAAE,gBAAgB,GAClC,OAAO,CAAC,IAAI,CAAC,CAkKf;AA2GD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,CAiC5E"}
@@ -26,8 +26,31 @@
26
26
  */
27
27
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
28
28
  import express from 'express';
29
+ import { expandImpliedScopes } from '../adt/safety.js';
30
+ import { PROFILE_SCOPES } from './config.js';
29
31
  import { logger } from './logger.js';
30
32
  import { VERSION } from './server.js';
33
+ // ─── API Key Matching Helper ─────────────────────────────────────────
34
+ /**
35
+ * Match a token against configured API keys (multi-key with profiles).
36
+ * Returns the matched entry's profile and scopes, or undefined if no match.
37
+ */
38
+ function matchApiKey(token, config) {
39
+ // Multi-key: check apiKeys array first
40
+ if (config.apiKeys) {
41
+ for (const entry of config.apiKeys) {
42
+ if (token === entry.key) {
43
+ const scopes = PROFILE_SCOPES[entry.profile] ?? ['read'];
44
+ return { profile: entry.profile, scopes, clientId: `api-key:${entry.profile}` };
45
+ }
46
+ }
47
+ }
48
+ // Single key: legacy behavior (full scopes)
49
+ if (config.apiKey && token === config.apiKey) {
50
+ return { profile: 'full', scopes: ['read', 'write', 'data', 'sql', 'admin'], clientId: 'api-key' };
51
+ }
52
+ return undefined;
53
+ }
31
54
  // ─── JWKS / JWT types (lazy-loaded from jose) ────────────────────────
32
55
  let joseModule = null;
33
56
  let jwksClient = null;
@@ -166,7 +189,7 @@ export async function startHttpServer(serverFactory, config, xsuaaCredentials) {
166
189
  issuerUrl: new URL(appUrl),
167
190
  baseUrl: new URL(appUrl),
168
191
  resourceServerUrl: new URL(`${appUrl}/mcp`),
169
- scopesSupported: ['read', 'write', 'admin'],
192
+ scopesSupported: ['read', 'write', 'data', 'sql', 'admin'],
170
193
  resourceName: 'ARC-1 SAP MCP Server',
171
194
  }));
172
195
  // Protected MCP endpoint with chained token verification
@@ -181,16 +204,18 @@ export async function startHttpServer(serverFactory, config, xsuaaCredentials) {
181
204
  if (config.oidcIssuer) {
182
205
  await initJwks(config.oidcIssuer);
183
206
  }
184
- // Auth middleware for standard mode
185
- const authMiddleware = async (req, res, next) => {
186
- const authResult = await checkAuth(req, config);
187
- if (!authResult.ok) {
188
- res.status(authResult.status).json({ error: authResult.message });
189
- return;
190
- }
191
- next();
192
- };
193
- app.all('/mcp', authMiddleware, mcpHandler);
207
+ if (config.apiKey || config.apiKeys || config.oidcIssuer) {
208
+ // Use requireBearerAuth so that authInfo is populated on the MCP request context.
209
+ // This enables scope enforcement, per-request safety, and principal propagation.
210
+ const { requireBearerAuth } = await import('@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js');
211
+ const verifier = createStandardVerifier(config);
212
+ const bearerAuth = requireBearerAuth({ verifier: { verifyAccessToken: verifier } });
213
+ app.all('/mcp', bearerAuth, mcpHandler);
214
+ }
215
+ else {
216
+ // No auth configured — open access
217
+ app.all('/mcp', mcpHandler);
218
+ }
194
219
  }
195
220
  // ─── 404 for anything else ─────────────────────────────────
196
221
  app.use((req, res) => {
@@ -202,8 +227,10 @@ export async function startHttpServer(serverFactory, config, xsuaaCredentials) {
202
227
  let authMode = 'NONE (open)';
203
228
  if (config.xsuaaAuth && xsuaaCredentials)
204
229
  authMode = 'XSUAA OAuth proxy';
205
- else if (config.apiKey && config.oidcIssuer)
230
+ else if ((config.apiKey || config.apiKeys) && config.oidcIssuer)
206
231
  authMode = 'API key + OIDC';
232
+ else if (config.apiKeys)
233
+ authMode = `API keys (${config.apiKeys.length} keys)`;
207
234
  else if (config.apiKey)
208
235
  authMode = 'API key';
209
236
  else if (config.oidcIssuer)
@@ -216,6 +243,63 @@ export async function startHttpServer(serverFactory, config, xsuaaCredentials) {
216
243
  });
217
244
  });
218
245
  }
246
+ // ─── Standard Mode Verifier ─────────────────────────────────────────
247
+ /**
248
+ * Create a token verifier for standard auth mode (API key + OIDC).
249
+ * Returns AuthInfo so the MCP SDK populates extra.authInfo on the request,
250
+ * enabling scope enforcement, per-request safety, and principal propagation.
251
+ */
252
+ function createStandardVerifier(config) {
253
+ return async (token) => {
254
+ // Lazy-import SDK error classes so bearerAuth maps them to 401/403
255
+ const { InvalidTokenError } = await import('@modelcontextprotocol/sdk/server/auth/errors.js');
256
+ // API key: match against multi-key map or single key
257
+ const apiKeyMatch = matchApiKey(token, config);
258
+ if (apiKeyMatch) {
259
+ // expiresAt is required by requireBearerAuth — use far-future expiry for static keys
260
+ const ONE_YEAR_SECS = 365 * 24 * 60 * 60;
261
+ return {
262
+ token,
263
+ clientId: apiKeyMatch.clientId,
264
+ scopes: apiKeyMatch.scopes,
265
+ expiresAt: Math.floor(Date.now() / 1000) + ONE_YEAR_SECS,
266
+ };
267
+ }
268
+ // OIDC: validate JWT and extract scopes
269
+ if (config.oidcIssuer) {
270
+ try {
271
+ if (!joseModule || !jwksClient) {
272
+ await initJwks(config.oidcIssuer);
273
+ }
274
+ if (!joseModule || !jwksClient) {
275
+ throw new Error('OIDC not initialized — check SAP_OIDC_ISSUER configuration');
276
+ }
277
+ const { payload } = await joseModule.jwtVerify(token, jwksClient, {
278
+ issuer: config.oidcIssuer,
279
+ audience: config.oidcAudience,
280
+ requiredClaims: ['exp'],
281
+ ...(config.oidcClockTolerance != null ? { clockTolerance: config.oidcClockTolerance } : {}),
282
+ });
283
+ logger.debug('Standard OIDC JWT validated', { sub: payload.sub, iss: payload.iss });
284
+ const scopes = extractOidcScopes(payload);
285
+ return {
286
+ token,
287
+ clientId: payload.azp ?? payload.sub ?? 'oidc-user',
288
+ scopes,
289
+ expiresAt: payload.exp,
290
+ extra: { sub: payload.sub, iss: payload.iss },
291
+ };
292
+ }
293
+ catch (err) {
294
+ // Wrap JWT validation errors as InvalidTokenError so bearerAuth returns 401
295
+ if (err instanceof InvalidTokenError)
296
+ throw err;
297
+ throw new InvalidTokenError(err.message ?? 'Invalid token');
298
+ }
299
+ }
300
+ throw new InvalidTokenError('Authentication failed: invalid token');
301
+ };
302
+ }
219
303
  // ─── OIDC Verifier Factory ───────────────────────────────────────────
220
304
  /**
221
305
  * Create an Entra ID / OIDC token verifier using jose.
@@ -230,66 +314,67 @@ async function createOidcVerifier(config) {
230
314
  const { payload } = await joseModule.jwtVerify(token, jwksClient, {
231
315
  issuer: config.oidcIssuer,
232
316
  audience: config.oidcAudience,
317
+ requiredClaims: ['exp'],
318
+ ...(config.oidcClockTolerance != null ? { clockTolerance: config.oidcClockTolerance } : {}),
233
319
  });
234
320
  logger.debug('OIDC JWT validated', { sub: payload.sub, iss: payload.iss });
321
+ const scopes = extractOidcScopes(payload);
235
322
  return {
236
323
  token,
237
324
  clientId: payload.azp ?? payload.sub ?? 'oidc-user',
238
- scopes: ['read', 'write', 'admin'], // OIDC tokens get full access (scopes managed by OIDC provider)
325
+ scopes,
239
326
  expiresAt: payload.exp,
240
327
  extra: { sub: payload.sub, iss: payload.iss },
241
328
  };
242
329
  };
243
330
  }
331
+ // ─── OIDC Scope Extraction ──────────────────────────────────────────
332
+ const KNOWN_SCOPES = ['read', 'write', 'data', 'sql', 'admin'];
244
333
  /**
245
- * Check authentication for standard mode (API key + OIDC).
246
- * Used when XSUAA auth is NOT enabled.
334
+ * Extract scopes from an OIDC JWT payload.
335
+ *
336
+ * Tries `scope` (space-separated string, standard OIDC) then `scp` (array, Azure AD style).
337
+ * Filters to known scopes, applies implied scope expansion, and falls back to read-only
338
+ * when no scope claims are present (safe default for providers that don't emit scopes).
247
339
  */
248
- async function checkAuth(req, config) {
249
- // No auth configured — allow all
250
- if (!config.apiKey && !config.oidcIssuer) {
251
- return { ok: true, status: 200, message: '' };
340
+ export function extractOidcScopes(payload) {
341
+ let rawScopes;
342
+ // Standard OIDC: space-separated string
343
+ if (typeof payload.scope === 'string') {
344
+ rawScopes = payload.scope.split(' ').filter((s) => s.length > 0);
252
345
  }
253
- const authHeader = req.headers.authorization;
254
- if (!authHeader?.startsWith('Bearer ')) {
255
- return {
256
- ok: false,
257
- status: 401,
258
- message: 'Missing or invalid Authorization header. Expected: Bearer <token>',
259
- };
346
+ // Azure AD / Entra: `scp` as space-delimited string (delegated tokens) or array (app tokens)
347
+ else if (typeof payload.scp === 'string') {
348
+ rawScopes = payload.scp.split(' ').filter((s) => s.length > 0);
260
349
  }
261
- const token = authHeader.slice(7);
262
- // API Key check
263
- if (config.apiKey) {
264
- if (token === config.apiKey) {
265
- return { ok: true, status: 200, message: '' };
266
- }
267
- if (!config.oidcIssuer) {
268
- return { ok: false, status: 403, message: 'Invalid API key' };
269
- }
350
+ else if (Array.isArray(payload.scp)) {
351
+ rawScopes = payload.scp.filter((s) => typeof s === 'string' && s.length > 0);
270
352
  }
271
- // OIDC / JWT validation
272
- if (config.oidcIssuer) {
273
- try {
274
- await validateJwt(token, config);
275
- return { ok: true, status: 200, message: '' };
276
- }
277
- catch (err) {
278
- const msg = err instanceof Error ? err.message : 'JWT validation failed';
279
- logger.debug('JWT validation failed', { error: msg });
280
- return { ok: false, status: 403, message: `Authentication failed: ${msg}` };
281
- }
353
+ // No scope claims at all → read-only (safe default)
354
+ if (rawScopes === undefined) {
355
+ logger.warn('OIDC JWT has no scope/scp claims — granting read-only access. ' +
356
+ 'Configure scope claims in your OIDC provider to grant write/data/sql access.');
357
+ return ['read'];
358
+ }
359
+ // Filter to known scopes
360
+ const filtered = rawScopes.filter((s) => KNOWN_SCOPES.includes(s));
361
+ // If scopes were present but none are known, grant minimum read access
362
+ if (filtered.length === 0) {
363
+ logger.warn('OIDC JWT has scope claims but none match known scopes — granting read-only', { rawScopes });
364
+ return ['read'];
282
365
  }
283
- return { ok: false, status: 403, message: 'Authentication failed' };
366
+ return expandImpliedScopes(filtered);
284
367
  }
285
368
  /**
286
369
  * Initialize JWKS client from OIDC discovery.
287
370
  */
288
371
  async function initJwks(issuer) {
289
- if (joseModule)
372
+ if (joseModule && jwksClient)
290
373
  return;
291
374
  try {
292
- joseModule = await import('jose');
375
+ if (!joseModule) {
376
+ joseModule = await import('jose');
377
+ }
293
378
  const jwksUri = new URL('.well-known/openid-configuration', issuer.endsWith('/') ? issuer : `${issuer}/`);
294
379
  const discoveryResp = await fetch(jwksUri.toString());
295
380
  const discovery = (await discoveryResp.json());
@@ -306,26 +391,4 @@ async function initJwks(issuer) {
306
391
  });
307
392
  }
308
393
  }
309
- /**
310
- * Validate a JWT token against the configured OIDC issuer.
311
- */
312
- async function validateJwt(token, config) {
313
- if (!joseModule || !jwksClient) {
314
- if (config.oidcIssuer) {
315
- await initJwks(config.oidcIssuer);
316
- }
317
- if (!joseModule || !jwksClient) {
318
- throw new Error('OIDC not initialized — check SAP_OIDC_ISSUER configuration');
319
- }
320
- }
321
- const { payload } = await joseModule.jwtVerify(token, jwksClient, {
322
- issuer: config.oidcIssuer,
323
- audience: config.oidcAudience,
324
- });
325
- logger.debug('JWT validated', {
326
- sub: payload.sub,
327
- iss: payload.iss,
328
- exp: payload.exp,
329
- });
330
- }
331
394
  //# sourceMappingURL=http.js.map