Skip to content

Commit 300d875

Browse files
release: 1.11.2 (#749)
Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com>
1 parent 6c52cce commit 300d875

24 files changed

Lines changed: 73 additions & 217 deletions

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "1.11.1"
2+
".": "1.11.2"
33
}

.stats.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
configured_endpoints: 118
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-132ed160716591bdcd9231c00da8c506d9451a5486b165fc27b2a01d93202082.yml
3-
openapi_spec_hash: c2b44d9e9cda56e32141a7ea3794bbba
4-
config_hash: 3bd89c812b96708c461fb98286ebf0b5
1+
configured_endpoints: 117
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-0568973e19e8af9fa953b2ded109ab2b69e76e90e2b74f33617dbf7092e26274.yml
3+
openapi_spec_hash: 10ba804ce69510d7985e05c77d0ffcf6
4+
config_hash: de99cfce88e2d1f02246dc6c2f43bc6c

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## 1.11.2 (2026-03-19)
4+
5+
Full Changelog: [v1.11.1...v1.11.2](https://github.com/runloopai/api-client-ts/compare/v1.11.1...v1.11.2)
6+
7+
### Chores
8+
9+
* remove create_tunnel endpoint ([5076da2](https://github.com/runloopai/api-client-ts/commit/5076da21a6729b4d288b530f78cc0e16415175d7))
10+
311
## 1.11.1 (2026-03-18)
412

513
Full Changelog: [v1.11.0...v1.11.1](https://github.com/runloopai/api-client-ts/compare/v1.11.0...v1.11.1)

api.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ Types:
114114
- <code><a href="./src/resources/devboxes/devboxes.ts">DevboxSendStdInResult</a></code>
115115
- <code><a href="./src/resources/devboxes/devboxes.ts">DevboxSnapshotListView</a></code>
116116
- <code><a href="./src/resources/devboxes/devboxes.ts">DevboxSnapshotView</a></code>
117-
- <code><a href="./src/resources/devboxes/devboxes.ts">DevboxTunnelView</a></code>
118117
- <code><a href="./src/resources/devboxes/devboxes.ts">DevboxView</a></code>
119118
- <code><a href="./src/resources/devboxes/devboxes.ts">TunnelView</a></code>
120119
- <code><a href="./src/resources/devboxes/devboxes.ts">DevboxCreateSSHKeyResponse</a></code>
@@ -131,7 +130,6 @@ Methods:
131130
- <code title="post /v1/devboxes/{id}">client.devboxes.<a href="./src/resources/devboxes/devboxes.ts">update</a>(id, { ...params }) -> DevboxView</code>
132131
- <code title="get /v1/devboxes">client.devboxes.<a href="./src/resources/devboxes/devboxes.ts">list</a>({ ...params }) -> DevboxViewsDevboxesCursorIDPage</code>
133132
- <code title="post /v1/devboxes/{id}/create_ssh_key">client.devboxes.<a href="./src/resources/devboxes/devboxes.ts">createSSHKey</a>(id) -> DevboxCreateSSHKeyResponse</code>
134-
- <code title="post /v1/devboxes/{id}/create_tunnel">client.devboxes.<a href="./src/resources/devboxes/devboxes.ts">createTunnel</a>(id, { ...params }) -> DevboxTunnelView</code>
135133
- <code title="post /v1/devboxes/disk_snapshots/{id}/delete">client.devboxes.<a href="./src/resources/devboxes/devboxes.ts">deleteDiskSnapshot</a>(id) -> unknown</code>
136134
- <code title="post /v1/devboxes/{id}/download_file">client.devboxes.<a href="./src/resources/devboxes/devboxes.ts">downloadFile</a>(id, { ...params }) -> Response</code>
137135
- <code title="post /v1/devboxes/{id}/enable_tunnel">client.devboxes.<a href="./src/resources/devboxes/devboxes.ts">enableTunnel</a>(id, { ...params }) -> TunnelView</code>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@runloop/api-client",
3-
"version": "1.11.1",
3+
"version": "1.11.2",
44
"description": "The official TypeScript library for the Runloop API",
55
"author": "Runloop <support@runloop.ai>",
66
"types": "dist/sdk.d.ts",

packages/mcp-server/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"dxt_version": "0.2",
33
"name": "@runloop/api-client-mcp",
4-
"version": "1.11.1",
4+
"version": "1.11.2",
55
"description": "The official MCP Server for the Runloop API",
66
"author": {
77
"name": "Runloop",

packages/mcp-server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@runloop/api-client-mcp",
3-
"version": "1.11.1",
3+
"version": "1.11.2",
44
"description": "The official MCP Server for the Runloop API",
55
"author": "Runloop <support@runloop.ai>",
66
"types": "dist/index.d.ts",
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
11
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
22

3-
export function getWorkerPath(): string {
4-
return require.resolve('./code-tool-worker.mjs');
5-
}
3+
export const workerPath = require.resolve('./code-tool-worker.mjs');

packages/mcp-server/src/code-tool.ts

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
22

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';
38
import {
49
ContentBlock,
510
McpRequestContext,
@@ -144,23 +149,19 @@ const remoteStainlessHandler = async ({
144149

145150
const codeModeEndpoint = readEnv('CODE_MODE_ENDPOINT_URL') ?? 'https://api.stainless.com/api/ai/code-tool';
146151

147-
const localClientEnvs = {
148-
RUNLOOP_API_KEY: requireValue(
149-
readEnv('RUNLOOP_API_KEY') ?? client.bearerToken,
150-
'set RUNLOOP_API_KEY environment variable or provide bearerToken client option',
151-
),
152-
RUNLOOP_BASE_URL: readEnv('RUNLOOP_BASE_URL') ?? client.baseURL ?? undefined,
153-
};
154-
// Merge any upstream client envs from the request header, with upstream values taking precedence.
155-
const mergedClientEnvs = { ...localClientEnvs, ...reqContext.upstreamClientEnvs };
156-
157152
// Setting a Stainless API key authenticates requests to the code tool endpoint.
158153
const res = await fetch(codeModeEndpoint, {
159154
method: 'POST',
160155
headers: {
161156
...(reqContext.stainlessApiKey && { Authorization: reqContext.stainlessApiKey }),
162157
'Content-Type': 'application/json',
163-
'x-stainless-mcp-client-envs': JSON.stringify(mergedClientEnvs),
158+
'x-stainless-mcp-client-envs': JSON.stringify({
159+
RUNLOOP_API_KEY: requireValue(
160+
readEnv('RUNLOOP_API_KEY') ?? client.bearerToken,
161+
'set RUNLOOP_API_KEY environment variable or provide bearerToken client option',
162+
),
163+
RUNLOOP_BASE_URL: readEnv('RUNLOOP_BASE_URL') ?? client.baseURL ?? undefined,
164+
}),
164165
},
165166
body: JSON.stringify({
166167
project_name: 'runloop',
@@ -203,13 +204,6 @@ const localDenoHandler = async ({
203204
reqContext: McpRequestContext;
204205
args: unknown;
205206
}): Promise<ToolCallResult> => {
206-
const fs = await import('node:fs');
207-
const path = await import('node:path');
208-
const url = await import('node:url');
209-
const { newDenoHTTPWorker } = await import('@valtown/deno-http-worker');
210-
const { getWorkerPath } = await import('./code-tool-paths.cjs');
211-
const workerPath = getWorkerPath();
212-
213207
const client = reqContext.client;
214208
const baseURLHostname = new URL(client.baseURL).hostname;
215209
const { code } = args as { code: string };
@@ -271,9 +265,6 @@ const localDenoHandler = async ({
271265
printOutput: true,
272266
spawnOptions: {
273267
cwd: path.dirname(workerPath),
274-
// Merge any upstream client envs into the Deno subprocess environment,
275-
// with the upstream env vars taking precedence.
276-
env: { ...process.env, ...reqContext.upstreamClientEnvs },
277268
},
278269
});
279270

@@ -283,17 +274,13 @@ const localDenoHandler = async ({
283274
reject(new Error(`Worker exited with code ${exitCode}`));
284275
});
285276

286-
// Strip null/undefined values so that the worker SDK client can fall back to
287-
// reading from environment variables (including any upstreamClientEnvs).
288-
const opts: ClientOptions = Object.fromEntries(
289-
Object.entries({
290-
baseURL: client.baseURL,
291-
bearerToken: client.bearerToken,
292-
defaultHeaders: {
293-
'X-Stainless-MCP': 'true',
294-
},
295-
}).filter(([_, v]) => v != null),
296-
) as ClientOptions;
277+
const opts: ClientOptions = {
278+
baseURL: client.baseURL,
279+
bearerToken: client.bearerToken,
280+
defaultHeaders: {
281+
'X-Stainless-MCP': 'true',
282+
},
283+
};
297284

298285
const req = worker.request(
299286
'http://localhost',

packages/mcp-server/src/http.ts

Lines changed: 2 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -27,56 +27,14 @@ const newServer = async ({
2727

2828
const authOptions = parseClientAuthHeaders(req, false);
2929

30-
let upstreamClientEnvs: Record<string, string> | undefined;
31-
const clientEnvsHeader = req.headers['x-stainless-mcp-client-envs'];
32-
if (typeof clientEnvsHeader === 'string') {
33-
try {
34-
const parsed = JSON.parse(clientEnvsHeader);
35-
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
36-
upstreamClientEnvs = parsed;
37-
}
38-
} catch {
39-
// Ignore malformed header
40-
}
41-
}
42-
43-
// Parse x-stainless-mcp-client-permissions header to override permission options
44-
//
45-
// Note: Permissions are best-effort and intended to prevent clients from doing unexpected things;
46-
// they're not a hard security boundary, so we allow arbitrary, client-driven overrides.
47-
//
48-
// See the Stainless MCP documentation for more details.
49-
let effectiveMcpOptions = mcpOptions;
50-
const clientPermissionsHeader = req.headers['x-stainless-mcp-client-permissions'];
51-
if (typeof clientPermissionsHeader === 'string') {
52-
try {
53-
const parsed = JSON.parse(clientPermissionsHeader);
54-
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
55-
effectiveMcpOptions = {
56-
...mcpOptions,
57-
...(typeof parsed.allow_http_gets === 'boolean' && { codeAllowHttpGets: parsed.allow_http_gets }),
58-
...(Array.isArray(parsed.allowed_methods) && { codeAllowedMethods: parsed.allowed_methods }),
59-
...(Array.isArray(parsed.blocked_methods) && { codeBlockedMethods: parsed.blocked_methods }),
60-
};
61-
getLogger().info(
62-
{ clientPermissions: parsed },
63-
'Overriding code execution permissions from x-stainless-mcp-client-permissions header',
64-
);
65-
}
66-
} catch (error) {
67-
getLogger().warn({ error }, 'Failed to parse x-stainless-mcp-client-permissions header');
68-
}
69-
}
70-
7130
await initMcpServer({
7231
server: server,
73-
mcpOptions: effectiveMcpOptions,
32+
mcpOptions: mcpOptions,
7433
clientOptions: {
7534
...clientOptions,
7635
...authOptions,
7736
},
7837
stainlessApiKey: stainlessApiKey,
79-
upstreamClientEnvs,
8038
});
8139

8240
return server;
@@ -114,7 +72,7 @@ const del = async (req: express.Request, res: express.Response) => {
11472
};
11573

11674
const redactHeaders = (headers: Record<string, any>) => {
117-
const hiddenHeaders = /auth|cookie|key|token|x-stainless-mcp-client-envs/i;
75+
const hiddenHeaders = /auth|cookie|key|token/i;
11876
const filtered = { ...headers };
11977
Object.keys(filtered).forEach((key) => {
12078
if (hiddenHeaders.test(key)) {

0 commit comments

Comments
 (0)