@metronome/mcp 3.4.1 → 3.5.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 (92) hide show
  1. package/README.md +3 -3
  2. package/code-tool-paths.cjs +4 -2
  3. package/code-tool-paths.cjs.map +1 -1
  4. package/code-tool-paths.d.cts +1 -1
  5. package/code-tool-paths.d.cts.map +1 -1
  6. package/code-tool-worker.d.mts.map +1 -1
  7. package/code-tool-worker.d.ts.map +1 -1
  8. package/code-tool-worker.js +45 -3
  9. package/code-tool-worker.js.map +1 -1
  10. package/code-tool-worker.mjs +12 -3
  11. package/code-tool-worker.mjs.map +1 -1
  12. package/code-tool.d.mts.map +1 -1
  13. package/code-tool.d.ts.map +1 -1
  14. package/code-tool.js +31 -25
  15. package/code-tool.js.map +1 -1
  16. package/code-tool.mjs +22 -13
  17. package/code-tool.mjs.map +1 -1
  18. package/docs-search-tool.d.mts +2 -0
  19. package/docs-search-tool.d.mts.map +1 -1
  20. package/docs-search-tool.d.ts +2 -0
  21. package/docs-search-tool.d.ts.map +1 -1
  22. package/docs-search-tool.js +32 -2
  23. package/docs-search-tool.js.map +1 -1
  24. package/docs-search-tool.mjs +31 -2
  25. package/docs-search-tool.mjs.map +1 -1
  26. package/http.d.mts.map +1 -1
  27. package/http.d.ts.map +1 -1
  28. package/http.js +65 -3
  29. package/http.js.map +1 -1
  30. package/http.mjs +65 -3
  31. package/http.mjs.map +1 -1
  32. package/instructions.d.mts +4 -1
  33. package/instructions.d.mts.map +1 -1
  34. package/instructions.d.ts +4 -1
  35. package/instructions.d.ts.map +1 -1
  36. package/instructions.js +29 -14
  37. package/instructions.js.map +1 -1
  38. package/instructions.mjs +26 -14
  39. package/instructions.mjs.map +1 -1
  40. package/local-docs-search.d.mts +28 -0
  41. package/local-docs-search.d.mts.map +1 -0
  42. package/local-docs-search.d.ts +28 -0
  43. package/local-docs-search.d.ts.map +1 -0
  44. package/local-docs-search.js +4780 -0
  45. package/local-docs-search.js.map +1 -0
  46. package/local-docs-search.mjs +4740 -0
  47. package/local-docs-search.mjs.map +1 -0
  48. package/options.d.mts +3 -0
  49. package/options.d.mts.map +1 -1
  50. package/options.d.ts +3 -0
  51. package/options.d.ts.map +1 -1
  52. package/options.js +19 -0
  53. package/options.js.map +1 -1
  54. package/options.mjs +19 -0
  55. package/options.mjs.map +1 -1
  56. package/package.json +13 -2
  57. package/server.d.mts +10 -1
  58. package/server.d.mts.map +1 -1
  59. package/server.d.ts +10 -1
  60. package/server.d.ts.map +1 -1
  61. package/server.js +13 -3
  62. package/server.js.map +1 -1
  63. package/server.mjs +13 -3
  64. package/server.mjs.map +1 -1
  65. package/src/code-tool-paths.cts +3 -1
  66. package/src/code-tool-worker.ts +12 -3
  67. package/src/code-tool.ts +29 -18
  68. package/src/docs-search-tool.ts +46 -8
  69. package/src/http.ts +71 -3
  70. package/src/instructions.ts +33 -15
  71. package/src/local-docs-search.ts +5674 -0
  72. package/src/options.ts +24 -0
  73. package/src/server.ts +23 -3
  74. package/src/stdio.ts +4 -1
  75. package/src/types.ts +3 -0
  76. package/src/util.ts +2 -2
  77. package/stdio.d.mts.map +1 -1
  78. package/stdio.d.ts.map +1 -1
  79. package/stdio.js +4 -1
  80. package/stdio.js.map +1 -1
  81. package/stdio.mjs +4 -1
  82. package/stdio.mjs.map +1 -1
  83. package/types.d.mts +6 -0
  84. package/types.d.mts.map +1 -1
  85. package/types.d.ts +6 -0
  86. package/types.d.ts.map +1 -1
  87. package/types.js.map +1 -1
  88. package/types.mjs.map +1 -1
  89. package/util.js +2 -2
  90. package/util.js.map +1 -1
  91. package/util.mjs +2 -2
  92. package/util.mjs.map +1 -1
package/server.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"server.mjs","sourceRoot":"","sources":["src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.mjs","sourceRoot":"","sources":["src/server.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,5 @@
1
1
  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
- export const workerPath = require.resolve('./code-tool-worker.mjs');
3
+ export function getWorkerPath(): string {
4
+ return require.resolve('./code-tool-worker.mjs');
5
+ }
@@ -7,6 +7,10 @@ import ts from 'typescript';
7
7
  import { WorkerOutput } from './code-tool-types';
8
8
  import { Metronome, ClientOptions } from '@metronome/sdk';
9
9
 
10
+ async function tseval(code: string) {
11
+ return import('data:application/typescript;charset=utf-8;base64,' + Buffer.from(code).toString('base64'));
12
+ }
13
+
10
14
  function getRunFunctionSource(code: string): {
11
15
  type: 'declaration' | 'expression';
12
16
  client: string | undefined;
@@ -297,7 +301,8 @@ function makeSdkProxy<T extends object>(obj: T, { path, isBelievedBad = false }:
297
301
 
298
302
  function parseError(code: string, error: unknown): string | undefined {
299
303
  if (!(error instanceof Error)) return;
300
- const message = error.name ? `${error.name}: ${error.message}` : error.message;
304
+ const cause = error.cause instanceof Error ? `: ${error.cause.message}` : '';
305
+ const message = error.name ? `${error.name}: ${error.message}${cause}` : `${error.message}${cause}`;
301
306
  try {
302
307
  // Deno uses V8; the first "<anonymous>:LINE:COLUMN" is the top of stack.
303
308
  const lineNumber = error.stack?.match(/<anonymous>:([0-9]+):[0-9]+/)?.[1];
@@ -353,7 +358,9 @@ const fetch = async (req: Request): Promise<Response> => {
353
358
 
354
359
  const log_lines: string[] = [];
355
360
  const err_lines: string[] = [];
356
- const console = {
361
+ const originalConsole = globalThis.console;
362
+ globalThis.console = {
363
+ ...originalConsole,
357
364
  log: (...args: unknown[]) => {
358
365
  log_lines.push(util.format(...args));
359
366
  },
@@ -363,7 +370,7 @@ const fetch = async (req: Request): Promise<Response> => {
363
370
  };
364
371
  try {
365
372
  let run_ = async (client: any) => {};
366
- eval(`${code}\nrun_ = run;`);
373
+ run_ = (await tseval(`${code}\nexport default run;`)).default;
367
374
  const result = await run_(makeSdkProxy(client, { path: ['client'] }));
368
375
  return Response.json({
369
376
  is_error: false,
@@ -381,6 +388,8 @@ const fetch = async (req: Request): Promise<Response> => {
381
388
  } satisfies WorkerOutput,
382
389
  { status: 400, statusText: 'Code execution error' },
383
390
  );
391
+ } finally {
392
+ globalThis.console = originalConsole;
384
393
  }
385
394
  };
386
395
 
package/src/code-tool.ts CHANGED
@@ -1,10 +1,5 @@
1
1
  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
- import fs from 'node:fs';
4
- import path from 'node:path';
5
- import url from 'node:url';
6
- import { newDenoHTTPWorker } from '@valtown/deno-http-worker';
7
- import { workerPath } from './code-tool-paths.cjs';
8
3
  import {
9
4
  ContentBlock,
10
5
  McpRequestContext,
@@ -157,20 +152,24 @@ const remoteStainlessHandler = async ({
157
152
 
158
153
  const codeModeEndpoint = readEnv('CODE_MODE_ENDPOINT_URL') ?? 'https://api.stainless.com/api/ai/code-tool';
159
154
 
155
+ const localClientEnvs = {
156
+ METRONOME_BEARER_TOKEN: requireValue(
157
+ readEnv('METRONOME_BEARER_TOKEN') ?? client.bearerToken,
158
+ 'set METRONOME_BEARER_TOKEN environment variable or provide bearerToken client option',
159
+ ),
160
+ METRONOME_WEBHOOK_SECRET: readEnv('METRONOME_WEBHOOK_SECRET') ?? client.webhookSecret ?? undefined,
161
+ METRONOME_BASE_URL: readEnv('METRONOME_BASE_URL') ?? client.baseURL ?? undefined,
162
+ };
163
+ // Merge any upstream client envs from the request header, with upstream values taking precedence.
164
+ const mergedClientEnvs = { ...localClientEnvs, ...reqContext.upstreamClientEnvs };
165
+
160
166
  // Setting a Stainless API key authenticates requests to the code tool endpoint.
161
167
  const res = await fetch(codeModeEndpoint, {
162
168
  method: 'POST',
163
169
  headers: {
164
170
  ...(reqContext.stainlessApiKey && { Authorization: reqContext.stainlessApiKey }),
165
171
  'Content-Type': 'application/json',
166
- 'x-stainless-mcp-client-envs': JSON.stringify({
167
- METRONOME_BEARER_TOKEN: requireValue(
168
- readEnv('METRONOME_BEARER_TOKEN') ?? client.bearerToken,
169
- 'set METRONOME_BEARER_TOKEN environment variable or provide bearerToken client option',
170
- ),
171
- METRONOME_WEBHOOK_SECRET: readEnv('METRONOME_WEBHOOK_SECRET') ?? client.webhookSecret ?? undefined,
172
- METRONOME_BASE_URL: readEnv('METRONOME_BASE_URL') ?? client.baseURL ?? undefined,
173
- }),
172
+ 'x-stainless-mcp-client-envs': JSON.stringify(mergedClientEnvs),
174
173
  },
175
174
  body: JSON.stringify({
176
175
  project_name: 'metronome',
@@ -213,6 +212,13 @@ const localDenoHandler = async ({
213
212
  reqContext: McpRequestContext;
214
213
  args: unknown;
215
214
  }): Promise<ToolCallResult> => {
215
+ const fs = await import('node:fs');
216
+ const path = await import('node:path');
217
+ const url = await import('node:url');
218
+ const { newDenoHTTPWorker } = await import('@valtown/deno-http-worker');
219
+ const { getWorkerPath } = await import('./code-tool-paths.cjs');
220
+ const workerPath = getWorkerPath();
221
+
216
222
  const client = reqContext.client;
217
223
  const baseURLHostname = new URL(client.baseURL).hostname;
218
224
  const { code } = args as { code: string };
@@ -274,6 +280,9 @@ const localDenoHandler = async ({
274
280
  printOutput: true,
275
281
  spawnOptions: {
276
282
  cwd: path.dirname(workerPath),
283
+ // Merge any upstream client envs into the Deno subprocess environment,
284
+ // with the upstream env vars taking precedence.
285
+ env: { ...process.env, ...reqContext.upstreamClientEnvs },
277
286
  },
278
287
  });
279
288
 
@@ -283,14 +292,16 @@ const localDenoHandler = async ({
283
292
  reject(new Error(`Worker exited with code ${exitCode}`));
284
293
  });
285
294
 
286
- const opts: ClientOptions = {
287
- baseURL: client.baseURL,
288
- bearerToken: client.bearerToken,
289
- webhookSecret: client.webhookSecret,
295
+ // Strip null/undefined values so that the worker SDK client can fall back to
296
+ // reading from environment variables (including any upstreamClientEnvs).
297
+ const opts = {
298
+ ...(client.baseURL != null ? { baseURL: client.baseURL } : undefined),
299
+ ...(client.bearerToken != null ? { bearerToken: client.bearerToken } : undefined),
300
+ ...(client.webhookSecret != null ? { webhookSecret: client.webhookSecret } : undefined),
290
301
  defaultHeaders: {
291
302
  'X-Stainless-MCP': 'true',
292
303
  },
293
- };
304
+ } satisfies Partial<ClientOptions> as ClientOptions;
294
305
 
295
306
  const req = worker.request(
296
307
  'http://localhost',
@@ -3,6 +3,7 @@
3
3
  import { Tool } from '@modelcontextprotocol/sdk/types.js';
4
4
  import { Metadata, McpRequestContext, asTextContentResult } from './types';
5
5
  import { getLogger } from './logger';
6
+ import type { LocalDocsSearch } from './local-docs-search';
6
7
 
7
8
  export const metadata: Metadata = {
8
9
  resource: 'all',
@@ -43,13 +44,30 @@ export const tool: Tool = {
43
44
  const docsSearchURL =
44
45
  process.env['DOCS_SEARCH_URL'] || 'https://api.stainless.com/api/projects/metronome/docs/search';
45
46
 
46
- export const handler = async ({
47
- reqContext,
48
- args,
49
- }: {
50
- reqContext: McpRequestContext;
51
- args: Record<string, unknown> | undefined;
52
- }) => {
47
+ let _localSearch: LocalDocsSearch | undefined;
48
+
49
+ export function setLocalSearch(search: LocalDocsSearch): void {
50
+ _localSearch = search;
51
+ }
52
+
53
+ async function searchLocal(args: Record<string, unknown>): Promise<unknown> {
54
+ if (!_localSearch) {
55
+ throw new Error('Local search not initialized');
56
+ }
57
+
58
+ const query = (args['query'] as string) ?? '';
59
+ const language = (args['language'] as string) ?? 'typescript';
60
+ const detail = (args['detail'] as string) ?? 'default';
61
+
62
+ return _localSearch.search({
63
+ query,
64
+ language,
65
+ detail,
66
+ maxResults: 10,
67
+ }).results;
68
+ }
69
+
70
+ async function searchRemote(args: Record<string, unknown>, reqContext: McpRequestContext): Promise<unknown> {
53
71
  const body = args as any;
54
72
  const query = new URLSearchParams(body).toString();
55
73
 
@@ -57,6 +75,10 @@ export const handler = async ({
57
75
  const result = await fetch(`${docsSearchURL}?${query}`, {
58
76
  headers: {
59
77
  ...(reqContext.stainlessApiKey && { Authorization: reqContext.stainlessApiKey }),
78
+ ...(reqContext.mcpSessionId && { 'x-stainless-mcp-session-id': reqContext.mcpSessionId }),
79
+ ...(reqContext.mcpClientInfo && {
80
+ 'x-stainless-mcp-client-info': JSON.stringify(reqContext.mcpClientInfo),
81
+ }),
60
82
  },
61
83
  });
62
84
 
@@ -94,7 +116,23 @@ export const handler = async ({
94
116
  },
95
117
  'Got docs search result',
96
118
  );
97
- return asTextContentResult(resultBody);
119
+ return resultBody;
120
+ }
121
+
122
+ export const handler = async ({
123
+ reqContext,
124
+ args,
125
+ }: {
126
+ reqContext: McpRequestContext;
127
+ args: Record<string, unknown> | undefined;
128
+ }) => {
129
+ const body = args ?? {};
130
+
131
+ if (_localSearch) {
132
+ return asTextContentResult(await searchLocal(body));
133
+ }
134
+
135
+ return asTextContentResult(await searchRemote(body, reqContext));
98
136
  };
99
137
 
100
138
  export default { metadata, tool, handler };
package/src/http.ts CHANGED
@@ -23,20 +23,74 @@ const newServer = async ({
23
23
  res: express.Response;
24
24
  }): Promise<McpServer | null> => {
25
25
  const stainlessApiKey = getStainlessApiKey(req, mcpOptions);
26
- const server = await newMcpServer(stainlessApiKey);
26
+ const customInstructionsPath = mcpOptions.customInstructionsPath;
27
+ const server = await newMcpServer({ stainlessApiKey, customInstructionsPath });
27
28
 
28
29
  const authOptions = parseClientAuthHeaders(req, false);
29
30
 
31
+ let upstreamClientEnvs: Record<string, string> | undefined;
32
+ const clientEnvsHeader = req.headers['x-stainless-mcp-client-envs'];
33
+ if (typeof clientEnvsHeader === 'string') {
34
+ try {
35
+ const parsed = JSON.parse(clientEnvsHeader);
36
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
37
+ upstreamClientEnvs = parsed;
38
+ }
39
+ } catch {
40
+ // Ignore malformed header
41
+ }
42
+ }
43
+
44
+ // Parse x-stainless-mcp-client-permissions header to override permission options
45
+ //
46
+ // Note: Permissions are best-effort and intended to prevent clients from doing unexpected things;
47
+ // they're not a hard security boundary, so we allow arbitrary, client-driven overrides.
48
+ //
49
+ // See the Stainless MCP documentation for more details.
50
+ let effectiveMcpOptions = mcpOptions;
51
+ const clientPermissionsHeader = req.headers['x-stainless-mcp-client-permissions'];
52
+ if (typeof clientPermissionsHeader === 'string') {
53
+ try {
54
+ const parsed = JSON.parse(clientPermissionsHeader);
55
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
56
+ effectiveMcpOptions = {
57
+ ...mcpOptions,
58
+ ...(typeof parsed.allow_http_gets === 'boolean' && { codeAllowHttpGets: parsed.allow_http_gets }),
59
+ ...(Array.isArray(parsed.allowed_methods) && { codeAllowedMethods: parsed.allowed_methods }),
60
+ ...(Array.isArray(parsed.blocked_methods) && { codeBlockedMethods: parsed.blocked_methods }),
61
+ };
62
+ getLogger().info(
63
+ { clientPermissions: parsed },
64
+ 'Overriding code execution permissions from x-stainless-mcp-client-permissions header',
65
+ );
66
+ }
67
+ } catch (error) {
68
+ getLogger().warn({ error }, 'Failed to parse x-stainless-mcp-client-permissions header');
69
+ }
70
+ }
71
+
72
+ const mcpClientInfo =
73
+ typeof req.body?.params?.clientInfo?.name === 'string' ?
74
+ { name: req.body.params.clientInfo.name, version: String(req.body.params.clientInfo.version ?? '') }
75
+ : undefined;
76
+
30
77
  await initMcpServer({
31
78
  server: server,
32
- mcpOptions: mcpOptions,
79
+ mcpOptions: effectiveMcpOptions,
33
80
  clientOptions: {
34
81
  ...clientOptions,
35
82
  ...authOptions,
36
83
  },
37
84
  stainlessApiKey: stainlessApiKey,
85
+ upstreamClientEnvs,
86
+ mcpSessionId: (req as any).mcpSessionId,
87
+ mcpClientInfo,
38
88
  });
39
89
 
90
+ if (mcpClientInfo) {
91
+ getLogger().info({ mcpSessionId: (req as any).mcpSessionId, mcpClientInfo }, 'MCP client connected');
92
+ }
93
+
40
94
  return server;
41
95
  };
42
96
 
@@ -72,7 +126,7 @@ const del = async (req: express.Request, res: express.Response) => {
72
126
  };
73
127
 
74
128
  const redactHeaders = (headers: Record<string, any>) => {
75
- const hiddenHeaders = /auth|cookie|key|token/i;
129
+ const hiddenHeaders = /auth|cookie|key|token|x-stainless-mcp-client-envs/i;
76
130
  const filtered = { ...headers };
77
131
  Object.keys(filtered).forEach((key) => {
78
132
  if (hiddenHeaders.test(key)) {
@@ -92,9 +146,23 @@ export const streamableHTTPApp = ({
92
146
  const app = express();
93
147
  app.set('query parser', 'extended');
94
148
  app.use(express.json());
149
+ app.use((req: express.Request, res: express.Response, next: express.NextFunction) => {
150
+ const existing = req.headers['mcp-session-id'];
151
+ const sessionId = (Array.isArray(existing) ? existing[0] : existing) || crypto.randomUUID();
152
+ (req as any).mcpSessionId = sessionId;
153
+ const origWriteHead = res.writeHead.bind(res);
154
+ res.writeHead = function (statusCode: number, ...rest: any[]) {
155
+ res.setHeader('mcp-session-id', sessionId);
156
+ return origWriteHead(statusCode, ...rest);
157
+ } as typeof res.writeHead;
158
+ next();
159
+ });
95
160
  app.use(
96
161
  pinoHttp({
97
162
  logger: getLogger(),
163
+ customProps: (req) => ({
164
+ mcpSessionId: (req as any).mcpSessionId,
165
+ }),
98
166
  customLogLevel: (req, res) => {
99
167
  if (res.statusCode >= 500) {
100
168
  return 'error';
@@ -1,7 +1,8 @@
1
1
  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
- import { readEnv } from './util';
3
+ import fs from 'fs/promises';
4
4
  import { getLogger } from './logger';
5
+ import { readEnv } from './util';
5
6
 
6
7
  const INSTRUCTIONS_CACHE_TTL_MS = 15 * 60 * 1000; // 15 minutes
7
8
 
@@ -12,33 +13,50 @@ interface InstructionsCacheEntry {
12
13
 
13
14
  const instructionsCache = new Map<string, InstructionsCacheEntry>();
14
15
 
15
- // Periodically evict stale entries so the cache doesn't grow unboundedly.
16
- const _cacheCleanupInterval = setInterval(() => {
16
+ export async function getInstructions({
17
+ stainlessApiKey,
18
+ customInstructionsPath,
19
+ }: {
20
+ stainlessApiKey?: string | undefined;
21
+ customInstructionsPath?: string | undefined;
22
+ }): Promise<string> {
17
23
  const now = Date.now();
24
+ const cacheKey = customInstructionsPath ?? stainlessApiKey ?? '';
25
+ const cached = instructionsCache.get(cacheKey);
26
+
27
+ if (cached && now - cached.fetchedAt <= INSTRUCTIONS_CACHE_TTL_MS) {
28
+ return cached.fetchedInstructions;
29
+ }
30
+
31
+ // Evict stale entries so the cache doesn't grow unboundedly.
18
32
  for (const [key, entry] of instructionsCache) {
19
33
  if (now - entry.fetchedAt > INSTRUCTIONS_CACHE_TTL_MS) {
20
34
  instructionsCache.delete(key);
21
35
  }
22
36
  }
23
- }, INSTRUCTIONS_CACHE_TTL_MS);
24
37
 
25
- // Don't keep the process alive just for cleanup.
26
- _cacheCleanupInterval.unref();
38
+ let fetchedInstructions: string;
27
39
 
28
- export async function getInstructions(stainlessApiKey: string | undefined): Promise<string> {
29
- const cacheKey = stainlessApiKey ?? '';
30
- const cached = instructionsCache.get(cacheKey);
31
-
32
- if (cached && Date.now() - cached.fetchedAt <= INSTRUCTIONS_CACHE_TTL_MS) {
33
- return cached.fetchedInstructions;
40
+ if (customInstructionsPath) {
41
+ fetchedInstructions = await fetchLatestInstructionsFromFile(customInstructionsPath);
42
+ } else {
43
+ fetchedInstructions = await fetchLatestInstructionsFromApi(stainlessApiKey);
34
44
  }
35
45
 
36
- const fetchedInstructions = await fetchLatestInstructions(stainlessApiKey);
37
- instructionsCache.set(cacheKey, { fetchedInstructions, fetchedAt: Date.now() });
46
+ instructionsCache.set(cacheKey, { fetchedInstructions, fetchedAt: now });
38
47
  return fetchedInstructions;
39
48
  }
40
49
 
41
- async function fetchLatestInstructions(stainlessApiKey: string | undefined): Promise<string> {
50
+ async function fetchLatestInstructionsFromFile(path: string): Promise<string> {
51
+ try {
52
+ return await fs.readFile(path, 'utf-8');
53
+ } catch (error) {
54
+ getLogger().error({ error, path }, 'Error fetching instructions from file');
55
+ throw error;
56
+ }
57
+ }
58
+
59
+ async function fetchLatestInstructionsFromApi(stainlessApiKey: string | undefined): Promise<string> {
42
60
  // Setting the stainless API key is optional, but may be required
43
61
  // to authenticate requests to the Stainless API.
44
62
  const response = await fetch(