Skip to content

Commit cc9a88d

Browse files
feat(api): update via SDK Studio
1 parent d12d86e commit cc9a88d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+9096
-8
lines changed

.github/workflows/ci.yml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
- name: Set up Node
2525
uses: actions/setup-node@v4
2626
with:
27-
node-version: '20'
27+
node-version: '22'
2828

2929
- name: Bootstrap
3030
run: ./scripts/bootstrap
@@ -46,7 +46,7 @@ jobs:
4646
- name: Set up Node
4747
uses: actions/setup-node@v4
4848
with:
49-
node-version: '20'
49+
node-version: '22'
5050

5151
- name: Bootstrap
5252
run: ./scripts/bootstrap
@@ -68,6 +68,15 @@ jobs:
6868
AUTH: ${{ steps.github-oidc.outputs.github_token }}
6969
SHA: ${{ github.sha }}
7070
run: ./scripts/utils/upload-artifact.sh
71+
72+
- name: Upload MCP Server tarball
73+
if: github.repository == 'stainless-sdks/beeper-desktop-api-typescript'
74+
env:
75+
URL: https://pkg.stainless.com/s?subpackage=mcp-server
76+
AUTH: ${{ steps.github-oidc.outputs.github_token }}
77+
SHA: ${{ github.sha }}
78+
BUILD_PATH: packages/mcp-server/dist
79+
run: ./scripts/utils/upload-artifact.sh
7180
test:
7281
timeout-minutes: 10
7382
name: test
@@ -79,10 +88,13 @@ jobs:
7988
- name: Set up Node
8089
uses: actions/setup-node@v4
8190
with:
82-
node-version: '20'
91+
node-version: '22'
8392

8493
- name: Bootstrap
8594
run: ./scripts/bootstrap
8695

96+
- name: Build
97+
run: ./scripts/build
98+
8799
- name: Run tests
88100
run: ./scripts/test

.github/workflows/publish-npm.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
name: Publish NPM
55
on:
66
workflow_dispatch:
7+
inputs:
8+
path:
9+
description: The path to run the release in, e.g. '.' or 'packages/mcp-server'
10+
required: true
711

812
release:
913
types: [published]
@@ -27,6 +31,11 @@ jobs:
2731
2832
- name: Publish to NPM
2933
run: |
30-
bash ./bin/publish-npm
34+
if [ -n "${{ github.event.inputs.path }}" ]; then
35+
PATHS_RELEASED='[\"${{ github.event.inputs.path }}\"]'
36+
else
37+
PATHS_RELEASED='[\".\", \"packages/mcp-server\"]'
38+
fi
39+
yarn tsn scripts/publish-packages.ts "{ \"paths_released\": \"$PATHS_RELEASED\" }"
3140
env:
3241
NPM_TOKEN: ${{ secrets.BEEPER-DESKTOP_NPM_TOKEN || secrets.NPM_TOKEN }}

.prettierignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ CHANGELOG.md
44
/deno
55

66
# don't format tsc output, will break source maps
7-
/dist
7+
dist

.stats.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
configured_endpoints: 13
22
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper%2Fbeeper-desktop-api-10508b7bd52381c216ed2584b7b0894f70fcc97fbd7f86792e78f72d108157c5.yml
33
openapi_spec_hash: d5f07fd2a363877f4c72da1187b8aaf1
4-
config_hash: a8d561a8c61cf63e15937fa7cbbd2c46
4+
config_hash: ee676f5f5342918d6bf4fde9e77d1c5c

eslint.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export default tseslint.config(
3434
},
3535
},
3636
{
37-
files: ['tests/**', 'examples/**'],
37+
files: ['tests/**', 'examples/**', 'packages/**'],
3838
rules: {
3939
'no-restricted-imports': 'off',
4040
},

packages/mcp-server/README.md

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
# Beeper Desktop TypeScript MCP Server
2+
3+
It is generated with [Stainless](https://www.stainless.com/).
4+
5+
## Installation
6+
7+
### Direct invocation
8+
9+
You can run the MCP Server directly via `npx`:
10+
11+
```sh
12+
export BEEPER_ACCESS_TOKEN="My Access Token"
13+
npx -y beeper/desktop-api-typescript-mcp@latest
14+
```
15+
16+
### Via MCP Client
17+
18+
There is a partial list of existing clients at [modelcontextprotocol.io](https://modelcontextprotocol.io/clients). If you already
19+
have a client, consult their documentation to install the MCP server.
20+
21+
For clients with a configuration JSON, it might look something like this:
22+
23+
```json
24+
{
25+
"mcpServers": {
26+
"desktop_api_typescript_api": {
27+
"command": "npx",
28+
"args": ["-y", "beeper/desktop-api-typescript-mcp", "--client=claude", "--tools=all"],
29+
"env": {
30+
"BEEPER_ACCESS_TOKEN": "My Access Token"
31+
}
32+
}
33+
}
34+
}
35+
```
36+
37+
## Exposing endpoints to your MCP Client
38+
39+
There are two ways to expose endpoints as tools in the MCP server:
40+
41+
1. Exposing one tool per endpoint, and filtering as necessary
42+
2. Exposing a set of tools to dynamically discover and invoke endpoints from the API
43+
44+
### Filtering endpoints and tools
45+
46+
You can run the package on the command line to discover and filter the set of tools that are exposed by the
47+
MCP Server. This can be helpful for large APIs where including all endpoints at once is too much for your AI's
48+
context window.
49+
50+
You can filter by multiple aspects:
51+
52+
- `--tool` includes a specific tool by name
53+
- `--resource` includes all tools under a specific resource, and can have wildcards, e.g. `my.resource*`
54+
- `--operation` includes just read (get/list) or just write operations
55+
56+
### Dynamic tools
57+
58+
If you specify `--tools=dynamic` to the MCP server, instead of exposing one tool per endpoint in the API, it will
59+
expose the following tools:
60+
61+
1. `list_api_endpoints` - Discovers available endpoints, with optional filtering by search query
62+
2. `get_api_endpoint_schema` - Gets detailed schema information for a specific endpoint
63+
3. `invoke_api_endpoint` - Executes any endpoint with the appropriate parameters
64+
65+
This allows you to have the full set of API endpoints available to your MCP Client, while not requiring that all
66+
of their schemas be loaded into context at once. Instead, the LLM will automatically use these tools together to
67+
search for, look up, and invoke endpoints dynamically. However, due to the indirect nature of the schemas, it
68+
can struggle to provide the correct properties a bit more than when tools are imported explicitly. Therefore,
69+
you can opt-in to explicit tools, the dynamic tools, or both.
70+
71+
See more information with `--help`.
72+
73+
All of these command-line options can be repeated, combined together, and have corresponding exclusion versions (e.g. `--no-tool`).
74+
75+
Use `--list` to see the list of available tools, or see below.
76+
77+
### Specifying the MCP Client
78+
79+
Different clients have varying abilities to handle arbitrary tools and schemas.
80+
81+
You can specify the client you are using with the `--client` argument, and the MCP server will automatically
82+
serve tools and schemas that are more compatible with that client.
83+
84+
- `--client=<type>`: Set all capabilities based on a known MCP client
85+
86+
- Valid values: `openai-agents`, `claude`, `claude-code`, `cursor`
87+
- Example: `--client=cursor`
88+
89+
Additionally, if you have a client not on the above list, or the client has gotten better
90+
over time, you can manually enable or disable certain capabilities:
91+
92+
- `--capability=<name>`: Specify individual client capabilities
93+
- Available capabilities:
94+
- `top-level-unions`: Enable support for top-level unions in tool schemas
95+
- `valid-json`: Enable JSON string parsing for arguments
96+
- `refs`: Enable support for $ref pointers in schemas
97+
- `unions`: Enable support for union types (anyOf) in schemas
98+
- `formats`: Enable support for format validations in schemas (e.g. date-time, email)
99+
- `tool-name-length=N`: Set maximum tool name length to N characters
100+
- Example: `--capability=top-level-unions --capability=tool-name-length=40`
101+
- Example: `--capability=top-level-unions,tool-name-length=40`
102+
103+
### Examples
104+
105+
1. Filter for read operations on cards:
106+
107+
```bash
108+
--resource=cards --operation=read
109+
```
110+
111+
2. Exclude specific tools while including others:
112+
113+
```bash
114+
--resource=cards --no-tool=create_cards
115+
```
116+
117+
3. Configure for Cursor client with custom max tool name length:
118+
119+
```bash
120+
--client=cursor --capability=tool-name-length=40
121+
```
122+
123+
4. Complex filtering with multiple criteria:
124+
125+
```bash
126+
--resource=cards,accounts --operation=read --tag=kyc --no-tool=create_cards
127+
```
128+
129+
## Running remotely
130+
131+
Launching the client with `--transport=http` launches the server as a remote server using Streamable HTTP transport. The `--port` setting can choose the port it will run on, and the `--socket` setting allows it to run on a Unix socket.
132+
133+
Authorization can be provided via the `Authorization` header using the Bearer scheme.
134+
135+
Additionally, authorization can be provided via the following headers:
136+
| Header | Equivalent client option | Security scheme |
137+
| ----------------------- | ------------------------ | --------------- |
138+
| `x-beeper-access-token` | `accessToken` | bearerAuth |
139+
140+
A configuration JSON for this server might look like this, assuming the server is hosted at `http://localhost:3000`:
141+
142+
```json
143+
{
144+
"mcpServers": {
145+
"desktop_api_typescript_api": {
146+
"url": "http://localhost:3000",
147+
"headers": {
148+
"Authorization": "Bearer <auth value>"
149+
}
150+
}
151+
}
152+
}
153+
```
154+
155+
The command-line arguments for filtering tools and specifying clients can also be used as query parameters in the URL.
156+
For example, to exclude specific tools while including others, use the URL:
157+
158+
```
159+
http://localhost:3000?resource=cards&resource=accounts&no_tool=create_cards
160+
```
161+
162+
Or, to configure for the Cursor client, with a custom max tool name length, use the URL:
163+
164+
```
165+
http://localhost:3000?client=cursor&capability=tool-name-length%3D40
166+
```
167+
168+
## Importing the tools and server individually
169+
170+
```js
171+
// Import the server, generated endpoints, or the init function
172+
import { server, endpoints, init } from "beeper/desktop-api-typescript-mcp/server";
173+
174+
// import a specific tool
175+
import listAccounts from "beeper/desktop-api-typescript-mcp/tools/accounts/list-accounts";
176+
177+
// initialize the server and all endpoints
178+
init({ server, endpoints });
179+
180+
// manually start server
181+
const transport = new StdioServerTransport();
182+
await server.connect(transport);
183+
184+
// or initialize your own server with specific tools
185+
const myServer = new McpServer(...);
186+
187+
// define your own endpoint
188+
const myCustomEndpoint = {
189+
tool: {
190+
name: 'my_custom_tool',
191+
description: 'My custom tool',
192+
inputSchema: zodToJsonSchema(z.object({ a_property: z.string() })),
193+
},
194+
handler: async (client: client, args: any) => {
195+
return { myResponse: 'Hello world!' };
196+
})
197+
};
198+
199+
// initialize the server with your custom endpoints
200+
init({ server: myServer, endpoints: [listAccounts, myCustomEndpoint] });
201+
```
202+
203+
## Available Tools
204+
205+
The following tools are available in this MCP server.
206+
207+
### Resource `accounts`:
208+
209+
- `list_accounts` (`read`): List connected Beeper accounts available on this device.
210+
- When to use: select account context before account-scoped operations.
211+
- Scope: only accounts currently Connected on this device are included.
212+
Returns: connected accounts.
213+
214+
### Resource `app`:
215+
216+
- `focus_app` (`write`): Bring Beeper Desktop to the foreground on this device. Optionally focuses a specific chat if chatID is provided.
217+
- When to use: open Beeper, or jump to a specific chat.
218+
- Constraints: requires Beeper Desktop running locally; no-op in headless environments.
219+
- Idempotent: safe to call repeatedly. Returns an error if chatID is not found.
220+
Returns: success.
221+
222+
### Resource `messages`:
223+
224+
- `draft_messages` (`write`): Draft a message in a specific chat. This will be placed in the message input field without sending
225+
- `search_messages` (`read`): Search messages across chats using Beeper's message index.
226+
- When to use: find messages by text and/or filters (chatIDs, accountIDs, chatType, media type filters, sender, date ranges).
227+
- CRITICAL: Query is LITERAL WORD MATCHING, NOT semantic search! Only finds messages containing these EXACT words.
228+
• ✅ RIGHT: query="dinner" or query="sick" or query="error" (single words users type)
229+
• ❌ WRONG: query="dinner plans tonight" or query="health issues" (phrases/concepts)
230+
• The query matches ALL words provided (in any order). Example: query="flight booking" finds messages with both "flight" AND "booking".
231+
- Media filters: Use onlyWithMedia for any media, or specific filters like onlyWithVideo, onlyWithImage, onlyWithLink, onlyWithFile for specific types.
232+
- Pagination: use 'oldestCursor' + direction='before' for older; 'newestCursor' + direction='after' for newer.
233+
- Performance: provide chatIDs/accountIDs when known. Omitted 'query' returns results based on filters only. Partial matches enabled; 'excludeLowPriority' defaults to true.
234+
- Workflow tip: To search messages in specific conversations: 1) Use find-chats to get chatIDs, 2) Use search-messages with those chatIDs.
235+
- IMPORTANT: Chat names vary widely. ASK the user for clarification:
236+
• "Which chat do you mean by family?" (could be "The Smiths", "Mom Dad Kids", etc.)
237+
• "What's the name of your work chat?" (could be "Team", company name, project name)
238+
• "Who are the participants?" (use participantQuery in find-chats)
239+
Returns: matching messages and referenced chats.
240+
- `send_messages` (`write`): Send a text message to a specific chat. Supports replying to existing messages. Returns the sent message ID and a deeplink to the chat
241+
242+
### Resource `chats`:
243+
244+
- `retrieve_chats` (`read`): Retrieve chat details: metadata, participants (limited), and latest message.
245+
- When to use: fetch a complete view of a chat beyond what search returns.
246+
- Constraints: not available for iMessage chats ('imsg##'). Participants limited by 'maxParticipantCount' (default 20, max 500).
247+
Returns: chat details.Agents: ALWAYS use linkToChat to make clickable links in your response
248+
- `archive_chats` (`write`): Archive or unarchive a chat. Set archived=true to move to archive, archived=false to move back to inbox
249+
- `find_chats` (`read`): Search and filter conversations across all messaging accounts.
250+
- When to use: browse chats by inbox (primary/low-priority/archive), type, unread status, or search terms.
251+
- Pagination: use cursor + direction for pagination.
252+
- Performance: provide accountIDs when known for faster filtering.
253+
Returns: matching chats with pagination.
254+
Agents: ALWAYS use linkToChat to make clickable links in your response
255+
- `get_link_chats` (`write`): Generate a deep link to a specific chat or message. This link can be used to open the chat directly in the Beeper app.
256+
257+
### Resource `reminders`:
258+
259+
- `clear_reminders` (`write`): Clear an existing reminder from a chat
260+
- `set_reminders` (`write`): Set a reminder for a chat at a specific time
261+
262+
### Resource `oauth`:
263+
264+
- `get_user_info_oauth` (`read`): Returns information about the authenticated user/token
265+
- `revoke_token_oauth` (`write`): Revoke an access token or refresh token (RFC 7009)

packages/mcp-server/build

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/usr/bin/env bash
2+
set -exuo pipefail
3+
4+
rm -rf dist; mkdir dist
5+
6+
# Copy src to dist/src and build from dist/src into dist, so that
7+
# the source map for index.js.map will refer to ./src/index.ts etc
8+
cp -rp src README.md dist
9+
10+
for file in LICENSE; do
11+
if [ -e "../../${file}" ]; then cp "../../${file}" dist; fi
12+
done
13+
14+
for file in CHANGELOG.md; do
15+
if [ -e "${file}" ]; then cp "${file}" dist; fi
16+
done
17+
18+
# this converts the export map paths for the dist directory
19+
# and does a few other minor things
20+
PKG_JSON_PATH=../../packages/mcp-server/package.json node ../../scripts/utils/make-dist-package-json.cjs > dist/package.json
21+
22+
# updates the `desktop-api-typescript` dependency to point to NPM
23+
node scripts/postprocess-dist-package-json.cjs
24+
25+
# build to .js/.mjs/.d.ts files
26+
./node_modules/.bin/tsc-multi
27+
28+
cp tsconfig.dist-src.json dist/src/tsconfig.json
29+
30+
chmod +x dist/index.js
31+
32+
DIST_PATH=./dist PKG_IMPORT_PATH=beeper/desktop-api-typescript-mcp/ node ../../scripts/utils/postprocess-files.cjs

0 commit comments

Comments
 (0)