Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
51ed091
chore(internal): make generated MCP servers compatible with Cloudflar…
stainless-app[bot] Mar 14, 2026
f152521
chore(internal): support x-stainless-mcp-client-envs header in MCP se…
stainless-app[bot] Mar 14, 2026
9b5fa46
chore(internal): tweak CI branches
stainless-app[bot] Mar 17, 2026
b714f03
chore(internal): support x-stainless-mcp-client-permissions headers i…
stainless-app[bot] Mar 17, 2026
5054afe
fix: escape MCP `instructions` backticks as necessary
stainless-app[bot] Mar 18, 2026
215316c
refactor(tests): switch from prism to steady
stainless-app[bot] Mar 20, 2026
21244db
chore(tests): bump steady to v0.19.4
stainless-app[bot] Mar 21, 2026
afd0423
chore(tests): bump steady to v0.19.5
stainless-app[bot] Mar 21, 2026
701eec1
chore(internal): update gitignore
stainless-app[bot] Mar 24, 2026
39f92ad
chore(internal): fix MCP server TS errors that occur with required cl…
stainless-app[bot] Mar 24, 2026
9226701
chore(tests): bump steady to v0.19.6
stainless-app[bot] Mar 24, 2026
c829f2e
chore(ci): skip lint on metadata-only changes
stainless-app[bot] Mar 25, 2026
e681061
chore(tests): bump steady to v0.19.7
stainless-app[bot] Mar 25, 2026
961ebc9
codegen metadata
stainless-app[bot] Mar 25, 2026
600a5dd
codegen metadata
stainless-app[bot] Mar 25, 2026
d4a125e
chore: update SDK settings
stainless-app[bot] Mar 25, 2026
d137743
chore(internal): update multipart form array serialization
stainless-app[bot] Mar 27, 2026
8888fc6
chore(internal): support custom-instructions-path flag in MCP servers
stainless-app[bot] Mar 27, 2026
5152f44
chore(internal): codegen related update
stainless-app[bot] Mar 28, 2026
7e09d80
chore(internal): support local docs search in MCP servers
stainless-app[bot] Mar 28, 2026
542eb4d
chore(ci): escape input path in publish-npm workflow
stainless-app[bot] Mar 28, 2026
1bb26fb
chore(mcp-server): add support for session id, forward client info
stainless-app[bot] Mar 31, 2026
2627f4e
chore(internal): improve local docs search for MCP servers
stainless-app[bot] Mar 31, 2026
812a0fd
chore(tests): bump steady to v0.20.1
stainless-app[bot] Apr 1, 2026
b0c172b
chore(internal): improve local docs search for MCP servers
stainless-app[bot] Apr 1, 2026
4ed5379
fix(internal): gitignore generated `oidc` dir
stainless-app[bot] Apr 1, 2026
64f4360
chore(tests): bump steady to v0.20.2
stainless-app[bot] Apr 1, 2026
dad62ee
chore(internal): support type annotations when running MCP in local e…
stainless-app[bot] Apr 2, 2026
8fce23c
chore(internal): codegen related update
stainless-app[bot] Apr 2, 2026
1a44cd2
chore(mcp-server): log client info
stainless-app[bot] Apr 3, 2026
5a05063
chore(internal): use link instead of file in MCP server package.json …
stainless-app[bot] Apr 3, 2026
60ccb25
chore(internal): fix MCP docker image builds in yarn projects
stainless-app[bot] Apr 3, 2026
ff62447
release: 4.7.1
stainless-app[bot] Apr 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
name: CI
on:
push:
branches-ignore:
- 'generated'
- 'codegen/**'
- 'integrated/**'
- 'stl-preview-head/**'
- 'stl-preview-base/**'
branches:
- '**'
- '!integrated/**'
- '!stl-preview-head/**'
- '!stl-preview-base/**'
- '!generated'
- '!codegen/**'
- 'codegen/stl/**'
pull_request:
branches-ignore:
- 'stl-preview-head/**'
Expand All @@ -17,7 +19,7 @@ jobs:
timeout-minutes: 10
name: lint
runs-on: ${{ github.repository == 'stainless-sdks/beeper-desktop-api-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata')
steps:
- uses: actions/checkout@v6

Expand All @@ -36,7 +38,7 @@ jobs:
timeout-minutes: 5
name: build
runs-on: ${{ github.repository == 'stainless-sdks/beeper-desktop-api-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata')
permissions:
contents: read
id-token: write
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/publish-npm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write

steps:
- uses: actions/checkout@v6
Expand All @@ -33,14 +34,14 @@ jobs:

- name: Publish to NPM
run: |
if [ -n "${{ github.event.inputs.path }}" ]; then
PATHS_RELEASED='[\"${{ github.event.inputs.path }}\"]'
if [ -n "$INPUT_PATH" ]; then
PATHS_RELEASED="[\"$INPUT_PATH\"]"
else
PATHS_RELEASED='[\".\", \"packages/mcp-server\"]'
fi
yarn tsn scripts/publish-packages.ts "{ \"paths_released\": \"$PATHS_RELEASED\" }"
env:
NPM_TOKEN: ${{ secrets.BEEPER_DESKTOP_NPM_TOKEN || secrets.NPM_TOKEN }}
INPUT_PATH: ${{ github.event.inputs.path }}

- name: Upload MCP Server DXT GitHub release asset
run: |
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/release-doctor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,4 @@ jobs:
- name: Check release environment
run: |
bash ./bin/check-release-environment
env:
NPM_TOKEN: ${{ secrets.BEEPER_DESKTOP_NPM_TOKEN || secrets.NPM_TOKEN }}

2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.prism.log
.stdy.log
node_modules
yarn-error.log
codegen.log
Expand All @@ -10,3 +11,4 @@ dist-deno
.eslintcache
dist-bundle
*.mcpb
oidc
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "4.7.0"
".": "4.7.1"
}
2 changes: 1 addition & 1 deletion .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 23
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper%2Fbeeper-desktop-api-5a8ac7b545c48dc892e5c680303e305254921554dabee848e40a808659dbcf1e.yml
openapi_spec_hash: 0103975601aac1445d3a4ef418c5d17a
config_hash: ca148af6be59ec54295b2c5f852a38d1
config_hash: 7d85c0b454fc78a59db6474c5c4d73c6
45 changes: 45 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,50 @@
# Changelog

## 4.7.1 (2026-04-03)

Full Changelog: [v4.7.0...v4.7.1](https://github.com/beeper/desktop-api-js/compare/v4.7.0...v4.7.1)

### Bug Fixes

* escape MCP `instructions` backticks as necessary ([5054afe](https://github.com/beeper/desktop-api-js/commit/5054afe374e27b9aec675a7d53d30dcaf0a7a351))
* **internal:** gitignore generated `oidc` dir ([4ed5379](https://github.com/beeper/desktop-api-js/commit/4ed5379638ea7b0d9f8ee38b7c085088f9ee77d1))


### Chores

* **ci:** escape input path in publish-npm workflow ([542eb4d](https://github.com/beeper/desktop-api-js/commit/542eb4d6449db180fe9cd7d4bbc48fe67275c5a2))
* **ci:** skip lint on metadata-only changes ([c829f2e](https://github.com/beeper/desktop-api-js/commit/c829f2e95c7ff077a9bf30a0ca31256313d28e28))
* **internal:** codegen related update ([8fce23c](https://github.com/beeper/desktop-api-js/commit/8fce23c041ec6b450ab34dabaf96c913dbc3ad5e))
* **internal:** codegen related update ([5152f44](https://github.com/beeper/desktop-api-js/commit/5152f44ac234096181c741ce83c2e93c96a76702))
* **internal:** fix MCP docker image builds in yarn projects ([60ccb25](https://github.com/beeper/desktop-api-js/commit/60ccb2538c55d36737c0800fb1c29be21bfad1c3))
* **internal:** fix MCP server TS errors that occur with required client options ([39f92ad](https://github.com/beeper/desktop-api-js/commit/39f92ad78be85d04b893d23d2c9cf5c655176fdc))
* **internal:** improve local docs search for MCP servers ([b0c172b](https://github.com/beeper/desktop-api-js/commit/b0c172b07c42f07ed9ed7d8c7eb6ed838d44926c))
* **internal:** improve local docs search for MCP servers ([2627f4e](https://github.com/beeper/desktop-api-js/commit/2627f4eba72b3859c2c8ea7f86ae43595b9ca4c2))
* **internal:** make generated MCP servers compatible with Cloudflare worker environments ([51ed091](https://github.com/beeper/desktop-api-js/commit/51ed09114417dd970167ef9e02663f729cc3ffa8))
* **internal:** support custom-instructions-path flag in MCP servers ([8888fc6](https://github.com/beeper/desktop-api-js/commit/8888fc6c71cc76c2153e8d6f11960b522153a9b8))
* **internal:** support local docs search in MCP servers ([7e09d80](https://github.com/beeper/desktop-api-js/commit/7e09d80e2309890331d4a3e5c4ae006ef911e369))
* **internal:** support type annotations when running MCP in local execution mode ([dad62ee](https://github.com/beeper/desktop-api-js/commit/dad62ee551a6ad54e08c670beef89d91534f4ae2))
* **internal:** support x-stainless-mcp-client-envs header in MCP servers ([f152521](https://github.com/beeper/desktop-api-js/commit/f152521d3d12eebf07826d8494e619f22a856eb5))
* **internal:** support x-stainless-mcp-client-permissions headers in MCP servers ([b714f03](https://github.com/beeper/desktop-api-js/commit/b714f0318bfde5ccdf2ef1f9e9679d2d6267a926))
* **internal:** tweak CI branches ([9b5fa46](https://github.com/beeper/desktop-api-js/commit/9b5fa462f35e2476f528a8b5b432e870651b4ae9))
* **internal:** update gitignore ([701eec1](https://github.com/beeper/desktop-api-js/commit/701eec1214e0ef23d92a4dbfb6f9bc660e93f79c))
* **internal:** update multipart form array serialization ([d137743](https://github.com/beeper/desktop-api-js/commit/d137743aa7ccfc9a3a0b51580a098210ab42b592))
* **internal:** use link instead of file in MCP server package.json files ([5a05063](https://github.com/beeper/desktop-api-js/commit/5a050630b6b6850ed634045a906e5f6929b66714))
* **mcp-server:** add support for session id, forward client info ([1bb26fb](https://github.com/beeper/desktop-api-js/commit/1bb26fbea126c85c3ae80704b536ce0322319081))
* **mcp-server:** log client info ([1a44cd2](https://github.com/beeper/desktop-api-js/commit/1a44cd28811d29a94d18274c8a9bebd750bbc1f2))
* **tests:** bump steady to v0.19.4 ([21244db](https://github.com/beeper/desktop-api-js/commit/21244db3761dd06eef1cbd431ee988dafed9e0b9))
* **tests:** bump steady to v0.19.5 ([afd0423](https://github.com/beeper/desktop-api-js/commit/afd0423f3fe2664e660ada160f79b111947cefb9))
* **tests:** bump steady to v0.19.6 ([9226701](https://github.com/beeper/desktop-api-js/commit/9226701faed2318b21d08d2d89208639628e3307))
* **tests:** bump steady to v0.19.7 ([e681061](https://github.com/beeper/desktop-api-js/commit/e681061239598ef4cb16a05ff80406b54934bfad))
* **tests:** bump steady to v0.20.1 ([812a0fd](https://github.com/beeper/desktop-api-js/commit/812a0fd7e4f7c45b8cc94da84fc7a1afbafc94e2))
* **tests:** bump steady to v0.20.2 ([64f4360](https://github.com/beeper/desktop-api-js/commit/64f4360bcf2a11212c64ddad4921b6cc3a2c48be))
* update SDK settings ([d4a125e](https://github.com/beeper/desktop-api-js/commit/d4a125ec0947b1e2f95d56ee9293254c6225118f))


### Refactors

* **tests:** switch from prism to steady ([215316c](https://github.com/beeper/desktop-api-js/commit/215316c820ab2067a629b325e87f99bc4352f163))

## 4.7.0 (2026-03-13)

Full Changelog: [v4.6.0...v4.7.0](https://github.com/beeper/desktop-api-js/compare/v4.6.0...v4.7.0)
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ $ pnpm link --global @beeper/desktop-api

## Running tests

Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests.
Most tests require you to [set up a mock server](https://github.com/dgellow/steady) against the OpenAPI spec to run the tests.

```sh
$ ./scripts/mock
Expand Down
4 changes: 0 additions & 4 deletions bin/check-release-environment
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@

errors=()

if [ -z "${NPM_TOKEN}" ]; then
errors+=("The NPM_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets")
fi

lenErrors=${#errors[@]}

if [[ lenErrors -gt 0 ]]; then
Expand Down
13 changes: 11 additions & 2 deletions bin/publish-npm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

set -eux

npm config set '//registry.npmjs.org/:_authToken' "$NPM_TOKEN"
if [[ ${NPM_TOKEN:-} ]]; then
npm config set '//registry.npmjs.org/:_authToken' "$NPM_TOKEN"
elif [[ ! ${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-} ]]; then
echo "ERROR: NPM_TOKEN must be set if not running in a Github Action with id-token permission"
exit 1
fi

yarn build
cd dist
Expand Down Expand Up @@ -57,5 +62,9 @@ else
TAG="latest"
fi

# Install OIDC compatible npm version
npm install --prefix ../oidc/ npm@11.6.2

# Publish with the appropriate tag
yarn publish --tag "$TAG"
export npm_config_registry='https://registry.npmjs.org'
../oidc/node_modules/.bin/npm publish --tag "$TAG"
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@beeper/desktop-api",
"version": "4.7.0",
"version": "4.7.1",
"description": "The official TypeScript library for the Beeper Desktop API",
"author": "Beeper Desktop <help@beeper.com>",
"types": "dist/index.d.ts",
Expand Down
4 changes: 3 additions & 1 deletion packages/mcp-server/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ COPY . .

# Install all dependencies and build everything
RUN yarn install --frozen-lockfile && \
yarn build
yarn build && \
# Remove the symlink to the SDK so it doesn't interfere with the explicit COPY below
rm -Rf packages/mcp-server/node_modules/@beeper/desktop-api

FROM denoland/deno:alpine-2.7.1

Expand Down
2 changes: 1 addition & 1 deletion packages/mcp-server/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"dxt_version": "0.2",
"name": "@beeper/desktop-mcp",
"version": "4.7.0",
"version": "4.7.1",
"description": "The official MCP Server for the Beeper Desktop API",
"author": {
"name": "Beeper Desktop",
Expand Down
5 changes: 3 additions & 2 deletions packages/mcp-server/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@beeper/desktop-mcp",
"version": "4.7.0",
"version": "4.7.1",
"description": "The official MCP Server for the Beeper Desktop API",
"author": "Beeper Desktop <help@beeper.com>",
"types": "dist/index.d.ts",
Expand Down Expand Up @@ -30,7 +30,7 @@
"fix": "eslint --fix ."
},
"dependencies": {
"@beeper/desktop-api": "file:../../dist/",
"@beeper/desktop-api": "link:../../dist/",
"ajv": "^8.18.0",
"@cloudflare/cabidela": "^0.2.4",
"@hono/node-server": "^1.19.10",
Expand All @@ -41,6 +41,7 @@
"cors": "^2.8.5",
"express": "^5.1.0",
"fuse.js": "^7.1.0",
"minisearch": "^7.2.0",
"jq-web": "https://github.com/stainless-api/jq-web/releases/download/v0.8.8/jq-web.tar.gz",
"pino": "^10.3.1",
"pino-http": "^11.0.0",
Expand Down
4 changes: 3 additions & 1 deletion packages/mcp-server/src/code-tool-paths.cts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

export const workerPath = require.resolve('./code-tool-worker.mjs');
export function getWorkerPath(): string {
return require.resolve('./code-tool-worker.mjs');
}
12 changes: 10 additions & 2 deletions packages/mcp-server/src/code-tool-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import ts from 'typescript';
import { WorkerOutput } from './code-tool-types';
import { BeeperDesktop, ClientOptions } from '@beeper/desktop-api';

async function tseval(code: string) {
return import('data:application/typescript;charset=utf-8;base64,' + Buffer.from(code).toString('base64'));
}

function getRunFunctionSource(code: string): {
type: 'declaration' | 'expression';
client: string | undefined;
Expand Down Expand Up @@ -259,7 +263,9 @@ const fetch = async (req: Request): Promise<Response> => {

const log_lines: string[] = [];
const err_lines: string[] = [];
const console = {
const originalConsole = globalThis.console;
globalThis.console = {
...originalConsole,
log: (...args: unknown[]) => {
log_lines.push(util.format(...args));
},
Expand All @@ -269,7 +275,7 @@ const fetch = async (req: Request): Promise<Response> => {
};
try {
let run_ = async (client: any) => {};
eval(`${code}\nrun_ = run;`);
run_ = (await tseval(`${code}\nexport default run;`)).default;
const result = await run_(makeSdkProxy(client, { path: ['client'] }));
return Response.json({
is_error: false,
Expand All @@ -287,6 +293,8 @@ const fetch = async (req: Request): Promise<Response> => {
} satisfies WorkerOutput,
{ status: 400, statusText: 'Code execution error' },
);
} finally {
globalThis.console = originalConsole;
}
};

Expand Down
43 changes: 27 additions & 16 deletions packages/mcp-server/src/code-tool.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

import fs from 'node:fs';
import path from 'node:path';
import url from 'node:url';
import { newDenoHTTPWorker } from '@valtown/deno-http-worker';
import { workerPath } from './code-tool-paths.cjs';
import {
ContentBlock,
McpRequestContext,
Expand Down Expand Up @@ -154,19 +149,23 @@ const remoteStainlessHandler = async ({

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

const localClientEnvs = {
BEEPER_ACCESS_TOKEN: requireValue(
readEnv('BEEPER_ACCESS_TOKEN') ?? client.accessToken,
'set BEEPER_ACCESS_TOKEN environment variable or provide accessToken client option',
),
BEEPER_DESKTOP_BASE_URL: readEnv('BEEPER_DESKTOP_BASE_URL') ?? client.baseURL ?? undefined,
};
// Merge any upstream client envs from the request header, with upstream values taking precedence.
const mergedClientEnvs = { ...localClientEnvs, ...reqContext.upstreamClientEnvs };

// Setting a Stainless API key authenticates requests to the code tool endpoint.
const res = await fetch(codeModeEndpoint, {
method: 'POST',
headers: {
...(reqContext.stainlessApiKey && { Authorization: reqContext.stainlessApiKey }),
'Content-Type': 'application/json',
'x-stainless-mcp-client-envs': JSON.stringify({
BEEPER_ACCESS_TOKEN: requireValue(
readEnv('BEEPER_ACCESS_TOKEN') ?? client.accessToken,
'set BEEPER_ACCESS_TOKEN environment variable or provide accessToken client option',
),
BEEPER_DESKTOP_BASE_URL: readEnv('BEEPER_DESKTOP_BASE_URL') ?? client.baseURL ?? undefined,
}),
'x-stainless-mcp-client-envs': JSON.stringify(mergedClientEnvs),
},
body: JSON.stringify({
project_name: 'beeper-desktop-api',
Expand Down Expand Up @@ -209,6 +208,13 @@ const localDenoHandler = async ({
reqContext: McpRequestContext;
args: unknown;
}): Promise<ToolCallResult> => {
const fs = await import('node:fs');
const path = await import('node:path');
const url = await import('node:url');
const { newDenoHTTPWorker } = await import('@valtown/deno-http-worker');
const { getWorkerPath } = await import('./code-tool-paths.cjs');
const workerPath = getWorkerPath();

const client = reqContext.client;
const baseURLHostname = new URL(client.baseURL).hostname;
const { code } = args as { code: string };
Expand Down Expand Up @@ -270,6 +276,9 @@ const localDenoHandler = async ({
printOutput: true,
spawnOptions: {
cwd: path.dirname(workerPath),
// Merge any upstream client envs into the Deno subprocess environment,
// with the upstream env vars taking precedence.
env: { ...process.env, ...reqContext.upstreamClientEnvs },
},
});

Expand All @@ -279,13 +288,15 @@ const localDenoHandler = async ({
reject(new Error(`Worker exited with code ${exitCode}`));
});

const opts: ClientOptions = {
baseURL: client.baseURL,
accessToken: client.accessToken,
// Strip null/undefined values so that the worker SDK client can fall back to
// reading from environment variables (including any upstreamClientEnvs).
const opts = {
...(client.baseURL != null ? { baseURL: client.baseURL } : undefined),
...(client.accessToken != null ? { accessToken: client.accessToken } : undefined),
defaultHeaders: {
'X-Stainless-MCP': 'true',
},
};
} satisfies Partial<ClientOptions> as ClientOptions;

const req = worker.request(
'http://localhost',
Expand Down
Loading
Loading