From 7944dbcad7e324e6c3e368f59f5099efdf5f8b9e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 02:35:40 +0000 Subject: [PATCH 001/138] chore: update SDK settings --- .github/workflows/release-doctor.yml | 20 ++++++++ .release-please-manifest.json | 3 ++ .stats.yml | 2 +- CONTRIBUTING.md | 6 +-- README.md | 4 +- bin/check-release-environment | 18 +++++++ package.json | 2 +- packages/mcp-server/README.md | 6 +-- packages/mcp-server/package.json | 4 +- release-please-config.json | 73 ++++++++++++++++++++++++++++ src/version.ts | 2 +- 11 files changed, 127 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/release-doctor.yml create mode 100644 .release-please-manifest.json create mode 100644 bin/check-release-environment create mode 100644 release-please-config.json diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml new file mode 100644 index 00000000..82139915 --- /dev/null +++ b/.github/workflows/release-doctor.yml @@ -0,0 +1,20 @@ +name: Release Doctor +on: + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + release_doctor: + name: release doctor + runs-on: ubuntu-latest + if: github.repository == 'corgi-tech/beagle-sdks' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') + + steps: + - uses: actions/checkout@v4 + + - name: Check release environment + run: | + bash ./bin/check-release-environment + env: diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 00000000..67dcd73f --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.0.1-alpha.0" +} diff --git a/.stats.yml b/.stats.yml index a7322dc8..aea6d83b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-908d2651f3ed6cddeba543bca341006e4bd15ff2f1bb1fd4442b896d7c66c547.yml openapi_spec_hash: 33e9e4dc59e701afb846264d6fa1915e -config_hash: 4309531b38d4521cda66ab537f120fd5 +config_hash: e8db5aa0739167f6270d7b6f6d5eb4f4 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1eabc7ff..80b6ef42 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,15 +42,15 @@ If you’d like to use the repository from source, you can either install from g To install via git: ```sh -$ npm install git+ssh://git@github.com:stainless-sdks/beagle-typescript.git +$ npm install git+ssh://git@github.com:corgi-tech/beagle-sdks.git ``` Alternatively, to link a local copy of the repo: ```sh # Clone -$ git clone https://www.github.com/stainless-sdks/beagle-typescript -$ cd beagle-typescript +$ git clone https://www.github.com/corgi-tech/beagle-sdks +$ cd beagle-sdks # With yarn $ yarn link diff --git a/README.md b/README.md index cc92e62e..c819b63d 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ It is generated with [Stainless](https://www.stainless.com/). ## Installation ```sh -npm install git+ssh://git@github.com:stainless-sdks/beagle-typescript.git +npm install git+ssh://git@github.com:corgi-tech/beagle-sdks.git ``` > [!NOTE] @@ -366,7 +366,7 @@ This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) con We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience. -We are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/beagle-typescript/issues) with questions, bugs, or suggestions. +We are keen for your feedback; please open an [issue](https://www.github.com/corgi-tech/beagle-sdks/issues) with questions, bugs, or suggestions. ## Requirements diff --git a/bin/check-release-environment b/bin/check-release-environment new file mode 100644 index 00000000..6b43775a --- /dev/null +++ b/bin/check-release-environment @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +errors=() + +lenErrors=${#errors[@]} + +if [[ lenErrors -gt 0 ]]; then + echo -e "Found the following errors in the release environment:\n" + + for error in "${errors[@]}"; do + echo -e "- $error\n" + done + + exit 1 +fi + +echo "The environment is ready to push releases!" + diff --git a/package.json b/package.json index b71aebcc..ee7198af 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "types": "dist/index.d.ts", "main": "dist/index.js", "type": "commonjs", - "repository": "github:stainless-sdks/beagle-typescript", + "repository": "github:corgi-tech/beagle-sdks", "license": "Apache-2.0", "packageManager": "yarn@1.22.22", "files": [ diff --git a/packages/mcp-server/README.md b/packages/mcp-server/README.md index e5f69c74..3d54d5b7 100644 --- a/packages/mcp-server/README.md +++ b/packages/mcp-server/README.md @@ -9,8 +9,8 @@ It is generated with [Stainless](https://www.stainless.com/). Because it's not published yet, clone the repo and build it: ```sh -git clone git@github.com:stainless-sdks/beagle-typescript.git -cd beagle-typescript +git clone git@github.com:corgi-tech/beagle-sdks.git +cd beagle-sdks ./scripts/bootstrap ./scripts/build ``` @@ -41,7 +41,7 @@ For clients with a configuration JSON, it might look something like this: "mcpServers": { "beagle_api": { "command": "node", - "args": ["/path/to/local/beagle-typescript/packages/mcp-server", "--client=claude", "--tools=dynamic"], + "args": ["/path/to/local/beagle-sdks/packages/mcp-server", "--client=claude", "--tools=dynamic"], "env": { "BEAGLE_API_KEY": "My API Key", "BEAGLE_ENVIRONMENT": "production" diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 7c5896af..e2101433 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -8,10 +8,10 @@ "type": "commonjs", "repository": { "type": "git", - "url": "git+https://github.com/stainless-sdks/beagle-typescript.git", + "url": "git+https://github.com/corgi-tech/beagle-sdks.git", "directory": "packages/mcp-server" }, - "homepage": "https://github.com/stainless-sdks/beagle-typescript/tree/main/packages/mcp-server#readme", + "homepage": "https://github.com/corgi-tech/beagle-sdks/tree/main/packages/mcp-server#readme", "license": "Apache-2.0", "packageManager": "yarn@1.22.22", "private": false, diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 00000000..b1909804 --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,73 @@ +{ + "packages": { + ".": {} + }, + "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json", + "include-v-in-tag": true, + "include-component-in-tag": false, + "versioning": "prerelease", + "prerelease": true, + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": false, + "pull-request-header": "Automated Release PR", + "pull-request-title-pattern": "release: ${version}", + "changelog-sections": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "perf", + "section": "Performance Improvements" + }, + { + "type": "revert", + "section": "Reverts" + }, + { + "type": "chore", + "section": "Chores" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "style", + "section": "Styles" + }, + { + "type": "refactor", + "section": "Refactors" + }, + { + "type": "test", + "section": "Tests", + "hidden": true + }, + { + "type": "build", + "section": "Build System" + }, + { + "type": "ci", + "section": "Continuous Integration", + "hidden": true + } + ], + "release-type": "node", + "extra-files": [ + "src/version.ts", + "README.md", + "packages/mcp-server/yarn.lock", + { + "type": "json", + "path": "packages/mcp-server/package.json", + "jsonpath": "$.version" + } + ] +} diff --git a/src/version.ts b/src/version.ts index 55a1a527..db692bc9 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.0.1-alpha.0'; +export const VERSION = '0.0.1-alpha.0'; // x-release-please-version From 296405deb7599b4067ce68a0d3e59952d5e3a606 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 02:36:29 +0000 Subject: [PATCH 002/138] chore: update SDK settings --- .github/workflows/publish-npm.yml | 41 +++++++++++++++++++ .github/workflows/release-doctor.yml | 1 + .stats.yml | 2 +- CONTRIBUTING.md | 18 +++++++- README.md | 25 +++++------ bin/check-release-environment | 4 ++ eslint.config.mjs | 2 +- jest.config.ts | 4 +- package.json | 6 +-- packages/mcp-server/README.md | 27 +++--------- packages/mcp-server/build | 2 +- packages/mcp-server/package.json | 2 +- .../scripts/postprocess-dist-package-json.cjs | 2 +- packages/mcp-server/src/dynamic-tools.ts | 2 +- packages/mcp-server/src/server.ts | 8 ++-- .../tools/enrollments/create-enrollments.ts | 2 +- .../tools/enrollments/lapse-enrollments.ts | 2 +- .../src/tools/enrollments/list-enrollments.ts | 2 +- .../tools/enrollments/retrieve-enrollments.ts | 2 +- .../verify-insurance-verification.ts | 2 +- .../mcp-server/src/tools/plans/list-plans.ts | 2 +- .../src/tools/plans/retrieve-plans.ts | 2 +- .../create-property-managers.ts | 2 +- .../delete-property-managers.ts | 2 +- .../list-property-managers.ts | 2 +- .../retrieve-property-managers.ts | 2 +- .../update-property-managers.ts | 2 +- .../src/tools/tenants/create-tenants.ts | 2 +- .../src/tools/tenants/delete-tenants.ts | 2 +- .../src/tools/tenants/list-tenants.ts | 2 +- .../src/tools/tenants/retrieve-tenants.ts | 2 +- .../src/tools/tenants/update-tenants.ts | 2 +- packages/mcp-server/src/tools/types.ts | 2 +- .../endpoints/create-webhook-endpoints.ts | 2 +- .../endpoints/delete-webhook-endpoints.ts | 2 +- .../endpoints/list-webhook-endpoints.ts | 2 +- .../endpoints/retrieve-webhook-endpoints.ts | 2 +- .../endpoints/update-webhook-endpoints.ts | 2 +- scripts/build | 6 +-- tests/api-resources/enrollments.test.ts | 2 +- .../insurance-verification.test.ts | 2 +- tests/api-resources/plans.test.ts | 2 +- tests/api-resources/property-managers.test.ts | 2 +- tests/api-resources/tenants.test.ts | 2 +- tests/api-resources/webhook/endpoints.test.ts | 2 +- tests/base64.test.ts | 2 +- tests/buildHeaders.test.ts | 2 +- tests/form.test.ts | 4 +- tests/index.test.ts | 6 +-- tests/path.test.ts | 2 +- tests/stringifyQuery.test.ts | 2 +- tests/uploads.test.ts | 6 +-- tsconfig.build.json | 4 +- tsconfig.json | 4 +- 54 files changed, 142 insertions(+), 100 deletions(-) create mode 100644 .github/workflows/publish-npm.yml diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml new file mode 100644 index 00000000..0f09c9c4 --- /dev/null +++ b/.github/workflows/publish-npm.yml @@ -0,0 +1,41 @@ +# This workflow is triggered when a GitHub release is created. +# It can also be run manually to re-publish to NPM in case it failed for some reason. +# You can run this workflow by navigating to https://www.github.com/corgi-tech/beagle-sdks/actions/workflows/publish-npm.yml +name: Publish NPM +on: + workflow_dispatch: + inputs: + path: + description: The path to run the release in, e.g. '.' or 'packages/mcp-server' + required: true + + release: + types: [published] + +jobs: + publish: + name: publish + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Node + uses: actions/setup-node@v3 + with: + node-version: '20' + + - name: Install dependencies + run: | + yarn install + + - name: Publish to NPM + run: | + if [ -n "${{ github.event.inputs.path }}" ]; then + PATHS_RELEASED='[\"${{ github.event.inputs.path }}\"]' + else + PATHS_RELEASED='[\".\", \"packages/mcp-server\"]' + fi + yarn tsn scripts/publish-packages.ts "{ \"paths_released\": \"$PATHS_RELEASED\" }" + env: + NPM_TOKEN: ${{ secrets.BEAGLE_NPM_TOKEN || secrets.NPM_TOKEN }} diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 82139915..31f5d5ee 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -18,3 +18,4 @@ jobs: run: | bash ./bin/check-release-environment env: + NPM_TOKEN: ${{ secrets.BEAGLE_NPM_TOKEN || secrets.NPM_TOKEN }} diff --git a/.stats.yml b/.stats.yml index aea6d83b..80af9cc4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-908d2651f3ed6cddeba543bca341006e4bd15ff2f1bb1fd4442b896d7c66c547.yml openapi_spec_hash: 33e9e4dc59e701afb846264d6fa1915e -config_hash: e8db5aa0739167f6270d7b6f6d5eb4f4 +config_hash: d63f662e216ecc51eccc05b8a4b5198e diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 80b6ef42..547acc18 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,12 +55,12 @@ $ cd beagle-sdks # With yarn $ yarn link $ cd ../my-package -$ yarn link beagle +$ yarn link @corgi-tech/beagle # With pnpm $ pnpm link --global $ cd ../my-package -$ pnpm link -—global beagle +$ pnpm link -—global @corgi-tech/beagle ``` ## Running tests @@ -91,3 +91,17 @@ To format and fix all lint issues automatically: ```sh $ yarn fix ``` + +## Publishing and releases + +Changes made to this repository via the automated release PR pipeline should publish to npm automatically. If +the changes aren't made through the automated pipeline, you may want to make releases manually. + +### Publish with a GitHub workflow + +You can release to package managers by using [the `Publish NPM` GitHub action](https://www.github.com/corgi-tech/beagle-sdks/actions/workflows/publish-npm.yml). This requires a setup organization or repository secret to be set up. + +### Publish manually + +If you need to manually release a package, you can run the `bin/publish-npm` script with an `NPM_TOKEN` set on +the environment. diff --git a/README.md b/README.md index c819b63d..2cfecce8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Beagle TypeScript API Library -[![NPM version]()](https://npmjs.org/package/beagle) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/beagle) +[![NPM version]()](https://npmjs.org/package/@corgi-tech/beagle) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@corgi-tech/beagle) This library provides convenient access to the Beagle REST API from server-side TypeScript or JavaScript. @@ -11,19 +11,16 @@ It is generated with [Stainless](https://www.stainless.com/). ## Installation ```sh -npm install git+ssh://git@github.com:corgi-tech/beagle-sdks.git +npm install @corgi-tech/beagle ``` -> [!NOTE] -> Once this package is [published to npm](https://www.stainless.com/docs/guides/publish), this will become: `npm install beagle` - ## Usage The full API of this library can be found in [api.md](api.md). ```js -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; const client = new Beagle({ apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted @@ -39,7 +36,7 @@ This library includes TypeScript definitions for all request params and response ```ts -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; const client = new Beagle({ apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted @@ -193,7 +190,7 @@ The log level can be configured in two ways: 2. Using the `logLevel` client option (overrides the environment variable if set) ```ts -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; const client = new Beagle({ logLevel: 'debug', // Show all log messages @@ -221,7 +218,7 @@ When providing a custom logger, the `logLevel` option still controls which messa below the configured level will not be sent to your logger. ```ts -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; import pino from 'pino'; const logger = pino(); @@ -290,7 +287,7 @@ globalThis.fetch = fetch; Or pass it to the client: ```ts -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; import fetch from 'my-fetch'; const client = new Beagle({ fetch }); @@ -301,7 +298,7 @@ const client = new Beagle({ fetch }); If you want to set custom `fetch` options without overriding the `fetch` function, you can provide a `fetchOptions` object when instantiating the client or making a request. (Request-specific options override client options.) ```ts -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; const client = new Beagle({ fetchOptions: { @@ -318,7 +315,7 @@ options to requests: **Node** [[docs](https://github.com/nodejs/undici/blob/main/docs/docs/api/ProxyAgent.md#example---proxyagent-with-fetch)] ```ts -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; import * as undici from 'undici'; const proxyAgent = new undici.ProxyAgent('http://localhost:8888'); @@ -332,7 +329,7 @@ const client = new Beagle({ **Bun** [[docs](https://bun.sh/guides/http/proxy)] ```ts -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; const client = new Beagle({ fetchOptions: { @@ -344,7 +341,7 @@ const client = new Beagle({ **Deno** [[docs](https://docs.deno.com/api/deno/~/Deno.createHttpClient)] ```ts -import Beagle from 'npm:beagle'; +import Beagle from 'npm:@corgi-tech/beagle'; const httpClient = Deno.createHttpClient({ proxy: { url: 'http://localhost:8888' } }); const client = new Beagle({ diff --git a/bin/check-release-environment b/bin/check-release-environment index 6b43775a..e4b6d58e 100644 --- a/bin/check-release-environment +++ b/bin/check-release-environment @@ -2,6 +2,10 @@ 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 diff --git a/eslint.config.mjs b/eslint.config.mjs index e9f86434..6c7b5e3a 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -25,7 +25,7 @@ export default tseslint.config( { patterns: [ { - regex: '^beagle(/.*)?', + regex: '^@corgi-tech/beagle(/.*)?', message: 'Use a relative import, not a package import.', }, ], diff --git a/jest.config.ts b/jest.config.ts index d5629a6d..af2930e4 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -7,8 +7,8 @@ const config: JestConfigWithTsJest = { '^.+\\.(t|j)sx?$': ['@swc/jest', { sourceMaps: 'inline' }], }, moduleNameMapper: { - '^beagle$': '/src/index.ts', - '^beagle/(.*)$': '/src/$1', + '^@corgi-tech/beagle$': '/src/index.ts', + '^@corgi-tech/beagle/(.*)$': '/src/$1', }, modulePathIgnorePatterns: [ '/ecosystem-tests/', diff --git a/package.json b/package.json index ee7198af..7b57e5a0 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "beagle", + "name": "@corgi-tech/beagle", "version": "0.0.1-alpha.0", "description": "The official TypeScript library for the Beagle API", "author": "Beagle <>", @@ -47,8 +47,8 @@ "typescript": "5.8.3" }, "imports": { - "beagle": ".", - "beagle/*": "./src/*" + "@corgi-tech/beagle": ".", + "@corgi-tech/beagle/*": "./src/*" }, "exports": { ".": { diff --git a/packages/mcp-server/README.md b/packages/mcp-server/README.md index 3d54d5b7..550d1e50 100644 --- a/packages/mcp-server/README.md +++ b/packages/mcp-server/README.md @@ -4,33 +4,18 @@ It is generated with [Stainless](https://www.stainless.com/). ## Installation -### Building +### Direct invocation -Because it's not published yet, clone the repo and build it: +You can run the MCP Server directly via `npx`: ```sh -git clone git@github.com:corgi-tech/beagle-sdks.git -cd beagle-sdks -./scripts/bootstrap -./scripts/build -``` - -### Running - -```sh -# set env vars as needed export BEAGLE_API_KEY="My API Key" export BEAGLE_ENVIRONMENT="production" -node ./packages/mcp-server/dist/index.js +npx -y beagle-mcp@latest ``` -> [!NOTE] -> Once this package is [published to npm](https://www.stainless.com/docs/guides/publish), this will become: `npx -y beagle-mcp` - ### Via MCP Client -[Build the project](#building) as mentioned above. - There is a partial list of existing clients at [modelcontextprotocol.io](https://modelcontextprotocol.io/clients). If you already have a client, consult their documentation to install the MCP server. @@ -39,9 +24,9 @@ For clients with a configuration JSON, it might look something like this: ```json { "mcpServers": { - "beagle_api": { - "command": "node", - "args": ["/path/to/local/beagle-sdks/packages/mcp-server", "--client=claude", "--tools=dynamic"], + "corgi_tech_beagle_api": { + "command": "npx", + "args": ["-y", "beagle-mcp", "--client=claude", "--tools=dynamic"], "env": { "BEAGLE_API_KEY": "My API Key", "BEAGLE_ENVIRONMENT": "production" diff --git a/packages/mcp-server/build b/packages/mcp-server/build index c5a4e871..e8b240ca 100644 --- a/packages/mcp-server/build +++ b/packages/mcp-server/build @@ -19,7 +19,7 @@ done # and does a few other minor things PKG_JSON_PATH=../../packages/mcp-server/package.json node ../../scripts/utils/make-dist-package-json.cjs > dist/package.json -# updates the `beagle` dependency to point to NPM +# updates the `@corgi-tech/beagle` dependency to point to NPM node scripts/postprocess-dist-package-json.cjs # build to .js/.mjs/.d.ts files diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index e2101433..d787bdee 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -27,7 +27,7 @@ "fix": "eslint --fix --ext ts,js ." }, "dependencies": { - "beagle": "file:../../dist/", + "@corgi-tech/beagle": "file:../../dist/", "@modelcontextprotocol/sdk": "^1.11.5", "yargs": "^17.7.2", "@cloudflare/cabidela": "^0.2.4", diff --git a/packages/mcp-server/scripts/postprocess-dist-package-json.cjs b/packages/mcp-server/scripts/postprocess-dist-package-json.cjs index 9716d19b..b2c9fb38 100644 --- a/packages/mcp-server/scripts/postprocess-dist-package-json.cjs +++ b/packages/mcp-server/scripts/postprocess-dist-package-json.cjs @@ -4,7 +4,7 @@ const parentPkgJson = require('../../../package.json'); for (const dep in pkgJson.dependencies) { // ensure we point to NPM instead of a local directory - if (dep === 'beagle') { + if (dep === '@corgi-tech/beagle') { pkgJson.dependencies[dep] = '^' + parentPkgJson.version; } } diff --git a/packages/mcp-server/src/dynamic-tools.ts b/packages/mcp-server/src/dynamic-tools.ts index 1657a5f3..6b226e3c 100644 --- a/packages/mcp-server/src/dynamic-tools.ts +++ b/packages/mcp-server/src/dynamic-tools.ts @@ -1,4 +1,4 @@ -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; import { Endpoint, asTextContentResult, ToolCallResult } from './tools/types'; import { zodToJsonSchema } from 'zod-to-json-schema'; import { z } from 'zod'; diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index eb90312a..00f9c654 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -4,8 +4,8 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { Endpoint, endpoints, HandlerFunction, query } from './tools'; import { CallToolRequestSchema, ListToolsRequestSchema, Tool } from '@modelcontextprotocol/sdk/types.js'; -import { ClientOptions } from 'beagle'; -import Beagle from 'beagle'; +import { ClientOptions } from '@corgi-tech/beagle'; +import Beagle from '@corgi-tech/beagle'; import { applyCompatibilityTransformations, ClientCapabilities, @@ -19,13 +19,13 @@ import { McpOptions } from './options'; export { McpOptions } from './options'; export { ClientType } from './compat'; export { Filter } from './tools'; -export { ClientOptions } from 'beagle'; +export { ClientOptions } from '@corgi-tech/beagle'; export { endpoints } from './tools'; // Create server instance export const server = new McpServer( { - name: 'beagle_api', + name: 'corgi_tech_beagle_api', version: '0.0.1-alpha.0', }, { diff --git a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts index da244936..9f00583b 100644 --- a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'enrollments', diff --git a/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts b/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts index d9448fd1..ed4812a2 100644 --- a/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'enrollments', diff --git a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts index dbbaf68e..cd974f44 100644 --- a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'enrollments', diff --git a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts index a8c7de7d..afc597e1 100644 --- a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'enrollments', diff --git a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts index bd2b0de8..fd6ab6d6 100644 --- a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts +++ b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'insurance_verification', diff --git a/packages/mcp-server/src/tools/plans/list-plans.ts b/packages/mcp-server/src/tools/plans/list-plans.ts index 81eef257..716e7c71 100644 --- a/packages/mcp-server/src/tools/plans/list-plans.ts +++ b/packages/mcp-server/src/tools/plans/list-plans.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'plans', diff --git a/packages/mcp-server/src/tools/plans/retrieve-plans.ts b/packages/mcp-server/src/tools/plans/retrieve-plans.ts index dfdd90c3..139d5f87 100644 --- a/packages/mcp-server/src/tools/plans/retrieve-plans.ts +++ b/packages/mcp-server/src/tools/plans/retrieve-plans.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'plans', diff --git a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts index 6859dbb8..cba8b7e1 100644 --- a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'property_managers', diff --git a/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts b/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts index f0cc53af..245fd18c 100644 --- a/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'property_managers', diff --git a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts index 7e8f8a93..8ab6daba 100644 --- a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'property_managers', diff --git a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts index 9f92d67f..fd0679df 100644 --- a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'property_managers', diff --git a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts index a84df734..6828e9f2 100644 --- a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'property_managers', diff --git a/packages/mcp-server/src/tools/tenants/create-tenants.ts b/packages/mcp-server/src/tools/tenants/create-tenants.ts index 468ce5d9..c615eedc 100644 --- a/packages/mcp-server/src/tools/tenants/create-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/create-tenants.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'tenants', diff --git a/packages/mcp-server/src/tools/tenants/delete-tenants.ts b/packages/mcp-server/src/tools/tenants/delete-tenants.ts index ce21e419..dc2afc99 100644 --- a/packages/mcp-server/src/tools/tenants/delete-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/delete-tenants.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'tenants', diff --git a/packages/mcp-server/src/tools/tenants/list-tenants.ts b/packages/mcp-server/src/tools/tenants/list-tenants.ts index daf97ca6..ef715463 100644 --- a/packages/mcp-server/src/tools/tenants/list-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/list-tenants.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'tenants', diff --git a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts b/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts index d01cd975..fbe6392b 100644 --- a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'tenants', diff --git a/packages/mcp-server/src/tools/tenants/update-tenants.ts b/packages/mcp-server/src/tools/tenants/update-tenants.ts index d73c472d..df99f9d4 100644 --- a/packages/mcp-server/src/tools/tenants/update-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/update-tenants.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'tenants', diff --git a/packages/mcp-server/src/tools/types.ts b/packages/mcp-server/src/tools/types.ts index 009c4212..e25cc99c 100644 --- a/packages/mcp-server/src/tools/types.ts +++ b/packages/mcp-server/src/tools/types.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; type TextContentBlock = { diff --git a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts index baded88d..8cc998ec 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'webhook.endpoints', diff --git a/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts index 8dd99609..9c6f1ac9 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'webhook.endpoints', diff --git a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts index 6f623693..2243dc12 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'webhook.endpoints', diff --git a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts index bddb2361..f786cf67 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'webhook.endpoints', diff --git a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts index 01232d18..de6fe8aa 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts @@ -4,7 +4,7 @@ import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Metadata } from '../../'; -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { resource: 'webhook.endpoints', diff --git a/scripts/build b/scripts/build index 84506808..d66231b0 100755 --- a/scripts/build +++ b/scripts/build @@ -8,7 +8,7 @@ node scripts/utils/check-version.cjs # Build into dist and will publish the package from there, # so that src/resources/foo.ts becomes /resources/foo.js -# This way importing from `"beagle/resources/foo"` works +# This way importing from `"@corgi-tech/beagle/resources/foo"` works # even with `"moduleResolution": "node"` rm -rf dist; mkdir dist @@ -42,8 +42,8 @@ node scripts/utils/postprocess-files.cjs # make sure that nothing crashes when we require the output CJS or # import the output ESM -(cd dist && node -e 'require("beagle")') -(cd dist && node -e 'import("beagle")' --input-type=module) +(cd dist && node -e 'require("@corgi-tech/beagle")') +(cd dist && node -e 'import("@corgi-tech/beagle")' --input-type=module) if [ -e ./scripts/build-deno ] then diff --git a/tests/api-resources/enrollments.test.ts b/tests/api-resources/enrollments.test.ts index 48f121b4..72607467 100644 --- a/tests/api-resources/enrollments.test.ts +++ b/tests/api-resources/enrollments.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; const client = new Beagle({ apiKey: 'My API Key', diff --git a/tests/api-resources/insurance-verification.test.ts b/tests/api-resources/insurance-verification.test.ts index b35b20c0..c266a0d9 100644 --- a/tests/api-resources/insurance-verification.test.ts +++ b/tests/api-resources/insurance-verification.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; const client = new Beagle({ apiKey: 'My API Key', diff --git a/tests/api-resources/plans.test.ts b/tests/api-resources/plans.test.ts index f0afb10e..d089594f 100644 --- a/tests/api-resources/plans.test.ts +++ b/tests/api-resources/plans.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; const client = new Beagle({ apiKey: 'My API Key', diff --git a/tests/api-resources/property-managers.test.ts b/tests/api-resources/property-managers.test.ts index d833da9f..f4d50fb9 100644 --- a/tests/api-resources/property-managers.test.ts +++ b/tests/api-resources/property-managers.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; const client = new Beagle({ apiKey: 'My API Key', diff --git a/tests/api-resources/tenants.test.ts b/tests/api-resources/tenants.test.ts index c7953d5b..9d47ced4 100644 --- a/tests/api-resources/tenants.test.ts +++ b/tests/api-resources/tenants.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; const client = new Beagle({ apiKey: 'My API Key', diff --git a/tests/api-resources/webhook/endpoints.test.ts b/tests/api-resources/webhook/endpoints.test.ts index 9af27790..9059bae9 100644 --- a/tests/api-resources/webhook/endpoints.test.ts +++ b/tests/api-resources/webhook/endpoints.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Beagle from 'beagle'; +import Beagle from '@corgi-tech/beagle'; const client = new Beagle({ apiKey: 'My API Key', diff --git a/tests/base64.test.ts b/tests/base64.test.ts index 7c63aebf..4c73b5a0 100644 --- a/tests/base64.test.ts +++ b/tests/base64.test.ts @@ -1,4 +1,4 @@ -import { fromBase64, toBase64 } from 'beagle/internal/utils/base64'; +import { fromBase64, toBase64 } from '@corgi-tech/beagle/internal/utils/base64'; describe.each(['Buffer', 'atob'])('with %s', (mode) => { let originalBuffer: BufferConstructor; diff --git a/tests/buildHeaders.test.ts b/tests/buildHeaders.test.ts index eb1df780..aa7667cf 100644 --- a/tests/buildHeaders.test.ts +++ b/tests/buildHeaders.test.ts @@ -1,5 +1,5 @@ import { inspect } from 'node:util'; -import { buildHeaders, type HeadersLike, type NullableHeaders } from 'beagle/internal/headers'; +import { buildHeaders, type HeadersLike, type NullableHeaders } from '@corgi-tech/beagle/internal/headers'; function inspectNullableHeaders(headers: NullableHeaders) { return `NullableHeaders {${[ diff --git a/tests/form.test.ts b/tests/form.test.ts index f9487cde..778bee4c 100644 --- a/tests/form.test.ts +++ b/tests/form.test.ts @@ -1,5 +1,5 @@ -import { multipartFormRequestOptions, createForm } from 'beagle/internal/uploads'; -import { toFile } from 'beagle/core/uploads'; +import { multipartFormRequestOptions, createForm } from '@corgi-tech/beagle/internal/uploads'; +import { toFile } from '@corgi-tech/beagle/core/uploads'; describe('form data validation', () => { test('valid values do not error', async () => { diff --git a/tests/index.test.ts b/tests/index.test.ts index 345b9411..45645381 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -1,10 +1,10 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIPromise } from 'beagle/core/api-promise'; +import { APIPromise } from '@corgi-tech/beagle/core/api-promise'; import util from 'node:util'; -import Beagle from 'beagle'; -import { APIUserAbortError } from 'beagle'; +import Beagle from '@corgi-tech/beagle'; +import { APIUserAbortError } from '@corgi-tech/beagle'; const defaultFetch = fetch; describe('instantiate client', () => { diff --git a/tests/path.test.ts b/tests/path.test.ts index 38937362..d53718b9 100644 --- a/tests/path.test.ts +++ b/tests/path.test.ts @@ -1,4 +1,4 @@ -import { createPathTagFunction, encodeURIPath } from 'beagle/internal/utils/path'; +import { createPathTagFunction, encodeURIPath } from '@corgi-tech/beagle/internal/utils/path'; import { inspect } from 'node:util'; import { runInNewContext } from 'node:vm'; diff --git a/tests/stringifyQuery.test.ts b/tests/stringifyQuery.test.ts index 01cba3b5..6f93dfdd 100644 --- a/tests/stringifyQuery.test.ts +++ b/tests/stringifyQuery.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Beagle } from 'beagle'; +import { Beagle } from '@corgi-tech/beagle'; const { stringifyQuery } = Beagle.prototype as any; diff --git a/tests/uploads.test.ts b/tests/uploads.test.ts index a548f670..c8befc47 100644 --- a/tests/uploads.test.ts +++ b/tests/uploads.test.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import type { ResponseLike } from 'beagle/internal/to-file'; -import { toFile } from 'beagle/core/uploads'; +import type { ResponseLike } from '@corgi-tech/beagle/internal/to-file'; +import { toFile } from '@corgi-tech/beagle/core/uploads'; import { File } from 'node:buffer'; class MyClass { @@ -97,7 +97,7 @@ describe('missing File error message', () => { }); test('is thrown', async () => { - const uploads = await import('beagle/core/uploads'); + const uploads = await import('@corgi-tech/beagle/core/uploads'); await expect( uploads.toFile(mockResponse({ url: 'https://example.com/my/audio.mp3' })), ).rejects.toMatchInlineSnapshot( diff --git a/tsconfig.build.json b/tsconfig.build.json index 0674d58f..4af3724f 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -5,8 +5,8 @@ "compilerOptions": { "rootDir": "./dist/src", "paths": { - "beagle/*": ["dist/src/*"], - "beagle": ["dist/src/index.ts"] + "@corgi-tech/beagle/*": ["dist/src/*"], + "@corgi-tech/beagle": ["dist/src/index.ts"] }, "noEmit": false, "declaration": true, diff --git a/tsconfig.json b/tsconfig.json index 29727585..56dcb13a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,8 +9,8 @@ "esModuleInterop": true, "baseUrl": "./", "paths": { - "beagle/*": ["src/*"], - "beagle": ["src/index.ts"] + "@corgi-tech/beagle/*": ["src/*"], + "@corgi-tech/beagle": ["src/index.ts"] }, "noEmit": true, From c6848aafc6dc2370566e06c54734140661f13c38 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 02:36:56 +0000 Subject: [PATCH 003/138] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 80af9cc4..b4760d4c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-908d2651f3ed6cddeba543bca341006e4bd15ff2f1bb1fd4442b896d7c66c547.yml -openapi_spec_hash: 33e9e4dc59e701afb846264d6fa1915e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-55e2c475fba1a969f73f7679e68a776e962352dc584f6ee83368947d35d3c96d.yml +openapi_spec_hash: f3b4f7afe0ef02a9054be3c705f75ab3 config_hash: d63f662e216ecc51eccc05b8a4b5198e From 03dca37a869de6f32a9ea7db5a3478fd2fbcc2e4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 10 Jul 2025 04:55:33 +0000 Subject: [PATCH 004/138] chore: make some internal functions async --- src/client.ts | 25 ++++++++++++++----------- tests/index.test.ts | 30 +++++++++++++++--------------- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/client.ts b/src/client.ts index 9b6ee2ea..0e557325 100644 --- a/src/client.ts +++ b/src/client.ts @@ -243,7 +243,7 @@ export class Beagle { * Create a new client instance re-using the same options given to the current client with optional overriding. */ withOptions(options: Partial): this { - return new (this.constructor as any as new (props: ClientOptions) => typeof this)({ + const client = new (this.constructor as any as new (props: ClientOptions) => typeof this)({ ...this._options, environment: options.environment ? options.environment : undefined, baseURL: options.environment ? undefined : this.baseURL, @@ -256,6 +256,7 @@ export class Beagle { apiKey: this.apiKey, ...options, }); + return client; } /** @@ -273,7 +274,7 @@ export class Beagle { return; } - protected authHeaders(opts: FinalRequestOptions): NullableHeaders | undefined { + protected async authHeaders(opts: FinalRequestOptions): Promise { return buildHeaders([{ 'x-api-key': this.apiKey }]); } @@ -405,7 +406,9 @@ export class Beagle { await this.prepareOptions(options); - const { req, url, timeout } = this.buildRequest(options, { retryCount: maxRetries - retriesRemaining }); + const { req, url, timeout } = await this.buildRequest(options, { + retryCount: maxRetries - retriesRemaining, + }); await this.prepareRequest(req, { url, options }); @@ -483,7 +486,7 @@ export class Beagle { } with status ${response.status} in ${headersTime - startTime}ms`; if (!response.ok) { - const shouldRetry = this.shouldRetry(response); + const shouldRetry = await this.shouldRetry(response); if (retriesRemaining && shouldRetry) { const retryMessage = `retrying, ${retriesRemaining} attempts remaining`; @@ -601,7 +604,7 @@ export class Beagle { } } - private shouldRetry(response: Response): boolean { + private async shouldRetry(response: Response): Promise { // Note this is not a standard header. const shouldRetryHeader = response.headers.get('x-should-retry'); @@ -678,10 +681,10 @@ export class Beagle { return sleepSeconds * jitter * 1000; } - buildRequest( + async buildRequest( inputOptions: FinalRequestOptions, { retryCount = 0 }: { retryCount?: number } = {}, - ): { req: FinalizedRequestInit; url: string; timeout: number } { + ): Promise<{ req: FinalizedRequestInit; url: string; timeout: number }> { const options = { ...inputOptions }; const { method, path, query, defaultBaseURL } = options; @@ -689,7 +692,7 @@ export class Beagle { if ('timeout' in options) validatePositiveInteger('timeout', options.timeout); options.timeout = options.timeout ?? this.timeout; const { bodyHeaders, body } = this.buildBody({ options }); - const reqHeaders = this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount }); + const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount }); const req: FinalizedRequestInit = { method, @@ -705,7 +708,7 @@ export class Beagle { return { req, url, timeout: options.timeout }; } - private buildHeaders({ + private async buildHeaders({ options, method, bodyHeaders, @@ -715,7 +718,7 @@ export class Beagle { method: HTTPMethod; bodyHeaders: HeadersLike; retryCount: number; - }): Headers { + }): Promise { let idempotencyHeaders: HeadersLike = {}; if (this.idempotencyHeader && method !== 'get') { if (!options.idempotencyKey) options.idempotencyKey = this.defaultIdempotencyKey(); @@ -731,7 +734,7 @@ export class Beagle { ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}), ...getPlatformHeaders(), }, - this.authHeaders(options), + await this.authHeaders(options), this._options.defaultHeaders, bodyHeaders, options.headers, diff --git a/tests/index.test.ts b/tests/index.test.ts index 45645381..34842826 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -26,13 +26,13 @@ describe('instantiate client', () => { apiKey: 'My API Key', }); - test('they are used in the request', () => { - const { req } = client.buildRequest({ path: '/foo', method: 'post' }); + test('they are used in the request', async () => { + const { req } = await client.buildRequest({ path: '/foo', method: 'post' }); expect(req.headers.get('x-my-default-header')).toEqual('2'); }); - test('can ignore `undefined` and leave the default', () => { - const { req } = client.buildRequest({ + test('can ignore `undefined` and leave the default', async () => { + const { req } = await client.buildRequest({ path: '/foo', method: 'post', headers: { 'X-My-Default-Header': undefined }, @@ -40,8 +40,8 @@ describe('instantiate client', () => { expect(req.headers.get('x-my-default-header')).toEqual('2'); }); - test('can be removed with `null`', () => { - const { req } = client.buildRequest({ + test('can be removed with `null`', async () => { + const { req } = await client.buildRequest({ path: '/foo', method: 'post', headers: { 'X-My-Default-Header': null }, @@ -357,7 +357,7 @@ describe('instantiate client', () => { }); describe('withOptions', () => { - test('creates a new client with overridden options', () => { + test('creates a new client with overridden options', async () => { const client = new Beagle({ baseURL: 'http://localhost:5000/', maxRetries: 3, apiKey: 'My API Key' }); const newClient = client.withOptions({ @@ -378,7 +378,7 @@ describe('instantiate client', () => { expect(newClient.constructor).toBe(client.constructor); }); - test('inherits options from the parent client', () => { + test('inherits options from the parent client', async () => { const client = new Beagle({ baseURL: 'http://localhost:5000/', defaultHeaders: { 'X-Test-Header': 'test-value' }, @@ -393,7 +393,7 @@ describe('instantiate client', () => { // Test inherited options remain the same expect(newClient.buildURL('/foo', null)).toEqual('http://localhost:5001/foo?test-param=test-value'); - const { req } = newClient.buildRequest({ path: '/foo', method: 'get' }); + const { req } = await newClient.buildRequest({ path: '/foo', method: 'get' }); expect(req.headers.get('x-test-header')).toEqual('test-value'); }); @@ -443,8 +443,8 @@ describe('request building', () => { const client = new Beagle({ apiKey: 'My API Key' }); describe('custom headers', () => { - test('handles undefined', () => { - const { req } = client.buildRequest({ + test('handles undefined', async () => { + const { req } = await client.buildRequest({ path: '/foo', method: 'post', body: { value: 'hello' }, @@ -479,8 +479,8 @@ describe('default encoder', () => { } } for (const jsonValue of [{}, [], { __proto__: null }, new Serializable(), new Collection(['item'])]) { - test(`serializes ${util.inspect(jsonValue)} as json`, () => { - const { req } = client.buildRequest({ + test(`serializes ${util.inspect(jsonValue)} as json`, async () => { + const { req } = await client.buildRequest({ path: '/foo', method: 'post', body: jsonValue, @@ -503,7 +503,7 @@ describe('default encoder', () => { asyncIterable, ]) { test(`converts ${util.inspect(streamValue)} to ReadableStream`, async () => { - const { req } = client.buildRequest({ + const { req } = await client.buildRequest({ path: '/foo', method: 'post', body: streamValue, @@ -516,7 +516,7 @@ describe('default encoder', () => { } test(`can set content-type for ReadableStream`, async () => { - const { req } = client.buildRequest({ + const { req } = await client.buildRequest({ path: '/foo', method: 'post', body: new Response('a\nb\nc\n').body, From f4996f0ebfe928dbb382e1adfb3de2e56644be80 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 11 Jul 2025 02:14:41 +0000 Subject: [PATCH 005/138] feat(mcp): support filtering tool results by a jq expression --- packages/mcp-server/package.json | 1 + packages/mcp-server/src/filtering.ts | 13 +++++++++++++ .../src/tools/enrollments/create-enrollments.ts | 12 ++++++++++-- .../src/tools/enrollments/lapse-enrollments.ts | 8 +++++++- .../src/tools/enrollments/list-enrollments.ts | 12 ++++++++++-- .../src/tools/enrollments/retrieve-enrollments.ts | 12 ++++++++++-- .../verify-insurance-verification.ts | 12 ++++++++++-- packages/mcp-server/src/tools/plans/list-plans.ts | 14 +++++++++++--- .../mcp-server/src/tools/plans/retrieve-plans.ts | 12 ++++++++++-- .../property-managers/create-property-managers.ts | 12 ++++++++++-- .../property-managers/delete-property-managers.ts | 9 ++++++++- .../property-managers/list-property-managers.ts | 13 +++++++++++-- .../retrieve-property-managers.ts | 12 ++++++++++-- .../property-managers/update-property-managers.ts | 11 +++++++++-- .../mcp-server/src/tools/tenants/create-tenants.ts | 12 ++++++++++-- .../mcp-server/src/tools/tenants/delete-tenants.ts | 9 ++++++++- .../mcp-server/src/tools/tenants/list-tenants.ts | 12 ++++++++++-- .../src/tools/tenants/retrieve-tenants.ts | 12 ++++++++++-- .../mcp-server/src/tools/tenants/update-tenants.ts | 12 ++++++++++-- .../webhook/endpoints/create-webhook-endpoints.ts | 12 ++++++++++-- .../webhook/endpoints/delete-webhook-endpoints.ts | 9 ++++++++- .../webhook/endpoints/list-webhook-endpoints.ts | 12 ++++++++++-- .../endpoints/retrieve-webhook-endpoints.ts | 12 ++++++++++-- .../webhook/endpoints/update-webhook-endpoints.ts | 12 ++++++++++-- 24 files changed, 226 insertions(+), 41 deletions(-) create mode 100644 packages/mcp-server/src/filtering.ts diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index d787bdee..22cd7b93 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -29,6 +29,7 @@ "dependencies": { "@corgi-tech/beagle": "file:../../dist/", "@modelcontextprotocol/sdk": "^1.11.5", + "jq-web": "^0.6.2", "yargs": "^17.7.2", "@cloudflare/cabidela": "^0.2.4", "zod": "^3.25.20", diff --git a/packages/mcp-server/src/filtering.ts b/packages/mcp-server/src/filtering.ts new file mode 100644 index 00000000..e560736f --- /dev/null +++ b/packages/mcp-server/src/filtering.ts @@ -0,0 +1,13 @@ +export async function maybeFilter(args: Record | undefined, response: any): Promise { + const jqFilter = args?.['jq_filter']; + if (jqFilter && typeof jqFilter === 'string') { + return await jq(response, jqFilter); + } else { + return response; + } +} + +var jqWeb = require('jq-web'); +async function jq(json: any, jqFilter: string) { + return (await jqWeb).json(json, jqFilter); +} diff --git a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts index 9f00583b..c5f7645a 100644 --- a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import { maybeFilter } from 'beagle-mcp/filtering'; import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -17,7 +18,8 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'create_enrollments', - description: 'create a new enrollment for a tenant.', + description: + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ncreate a new enrollment for a tenant.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/enrollment',\n $defs: {\n enrollment: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n effectiveDate: {\n type: 'string',\n description: 'the date the enrollment will begin, note enrollments cannot begin in the past'\n },\n plan: {\n type: 'string',\n description: 'the plan name/code'\n },\n propertyManagerId: {\n type: 'number'\n },\n tenantId: {\n type: 'number'\n },\n note: {\n type: 'string',\n description: 'an optional note field, this can be used for easily appending metadata to enrollments'\n }\n },\n required: [ 'id',\n 'effectiveDate',\n 'plan',\n 'propertyManagerId',\n 'tenantId'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { @@ -39,13 +41,19 @@ export const tool: Tool = { type: 'string', description: 'an optional note field, this can be used for easily appending metadata to enrollments', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, }, }; export const handler = async (client: Beagle, args: Record | undefined) => { const body = args as any; - return asTextContentResult(await client.enrollments.create(body)); + return asTextContentResult(await maybeFilter(args, await client.enrollments.create(body))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts b/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts index ed4812a2..09fe5ee1 100644 --- a/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts @@ -18,13 +18,19 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'lapse_enrollments', description: - 'lapses a specific enrollment for a tenant, note that if a tenant has multiple enrollments (e.g., SDR and TLL), each must be lapsed individually', + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlapses a specific enrollment for a tenant, note that if a tenant has multiple enrollments (e.g., SDR and TLL), each must be lapsed individually\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {}\n}\n```", inputSchema: { type: 'object', properties: { id: { type: 'number', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, }, }; diff --git a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts index cd974f44..6209b177 100644 --- a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import { maybeFilter } from 'beagle-mcp/filtering'; import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -18,7 +19,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'list_enrollments', description: - 'list all enrollments, this endpoint is paginated and allows for queries by individual property manager.', + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlist all enrollments, this endpoint is paginated and allows for queries by individual property manager.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n enrollments: {\n type: 'array',\n items: {\n $ref: '#/$defs/enrollment'\n }\n },\n pagination: {\n $ref: '#/$defs/pagination'\n }\n },\n required: [ 'enrollments',\n 'pagination'\n ],\n $defs: {\n enrollment: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n effectiveDate: {\n type: 'string',\n description: 'the date the enrollment will begin, note enrollments cannot begin in the past'\n },\n plan: {\n type: 'string',\n description: 'the plan name/code'\n },\n propertyManagerId: {\n type: 'number'\n },\n tenantId: {\n type: 'number'\n },\n note: {\n type: 'string',\n description: 'an optional note field, this can be used for easily appending metadata to enrollments'\n }\n },\n required: [ 'id',\n 'effectiveDate',\n 'plan',\n 'propertyManagerId',\n 'tenantId'\n ]\n },\n pagination: {\n type: 'object',\n properties: {\n page: {\n type: 'number',\n description: 'Current page number.'\n },\n pages: {\n type: 'number',\n description: 'Total number of pages.'\n },\n records: {\n type: 'number',\n description: 'Total number of records.'\n },\n size: {\n type: 'number',\n description: 'Number of items per page.'\n }\n },\n required: [ 'page',\n 'pages',\n 'records',\n 'size'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { @@ -33,13 +34,20 @@ export const tool: Tool = { type: 'number', description: 'Number of items per page.', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, }, }; export const handler = async (client: Beagle, args: Record | undefined) => { const body = args as any; - return asTextContentResult(await client.enrollments.list(body)); + const response = await client.enrollments.list(body).asResponse(); + return asTextContentResult(await maybeFilter(args, await response.json())); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts index afc597e1..4e1cbacd 100644 --- a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import { maybeFilter } from 'beagle-mcp/filtering'; import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -17,20 +18,27 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'retrieve_enrollments', - description: 'get a specific enrollment by its id.', + description: + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nget a specific enrollment by its id.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/enrollment',\n $defs: {\n enrollment: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n effectiveDate: {\n type: 'string',\n description: 'the date the enrollment will begin, note enrollments cannot begin in the past'\n },\n plan: {\n type: 'string',\n description: 'the plan name/code'\n },\n propertyManagerId: {\n type: 'number'\n },\n tenantId: {\n type: 'number'\n },\n note: {\n type: 'string',\n description: 'an optional note field, this can be used for easily appending metadata to enrollments'\n }\n },\n required: [ 'id',\n 'effectiveDate',\n 'plan',\n 'propertyManagerId',\n 'tenantId'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { id: { type: 'number', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, }, }; export const handler = async (client: Beagle, args: Record | undefined) => { const { id, ...body } = args as any; - return asTextContentResult(await client.enrollments.retrieve(id)); + return asTextContentResult(await maybeFilter(args, await client.enrollments.retrieve(id))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts index fd6ab6d6..91c3c269 100644 --- a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts +++ b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import { maybeFilter } from 'beagle-mcp/filtering'; import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -17,7 +18,8 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'verify_insurance_verification', - description: 'trigger a job to parse a tenants insurance document(s)', + description: + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ntrigger a job to parse a tenants insurance document(s)\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n message: {\n type: 'string',\n enum: [ 'insurance verification job scheduled'\n ]\n }\n },\n required: [ 'message'\n ]\n}\n```", inputSchema: { type: 'object', properties: { @@ -34,13 +36,19 @@ export const tool: Tool = { type: 'string', }, }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, }, }; export const handler = async (client: Beagle, args: Record | undefined) => { const body = args as any; - return asTextContentResult(await client.insuranceVerification.verify(body)); + return asTextContentResult(await maybeFilter(args, await client.insuranceVerification.verify(body))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/plans/list-plans.ts b/packages/mcp-server/src/tools/plans/list-plans.ts index 716e7c71..e8f62db3 100644 --- a/packages/mcp-server/src/tools/plans/list-plans.ts +++ b/packages/mcp-server/src/tools/plans/list-plans.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import { maybeFilter } from 'beagle-mcp/filtering'; import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -18,15 +19,22 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'list_plans', description: - 'list all available plans, note this endpoint is currently unpaginated unlike all other list endpoints.', + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlist all available plans, note this endpoint is currently unpaginated unlike all other list endpoints.\n\n# Response Schema\n```json\n{\n type: 'array',\n items: {\n $ref: '#/$defs/plan'\n },\n $defs: {\n plan: {\n type: 'object',\n properties: {\n description: {\n type: 'string'\n },\n name: {\n type: 'string',\n description: 'the plans name/code, this is used when creating enrollments.'\n },\n rate: {\n type: 'number',\n description: 'the price of the plan'\n },\n contents: {\n type: 'number',\n description: 'value of contents replacement, note this is only on some TLL plans.'\n },\n liability: {\n type: 'number',\n description: 'value of liability waived, note this is only on TLL plans.'\n },\n value: {\n type: 'number',\n description: 'general value field, this is currently used for SDR and SDD plans for the replacement or discount value.'\n }\n },\n required: [ 'description',\n 'name',\n 'rate'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', - properties: {}, + properties: { + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, + }, }, }; export const handler = async (client: Beagle, args: Record | undefined) => { - return asTextContentResult(await client.plans.list()); + return asTextContentResult(await maybeFilter(args, await client.plans.list())); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/plans/retrieve-plans.ts b/packages/mcp-server/src/tools/plans/retrieve-plans.ts index 139d5f87..4bae495a 100644 --- a/packages/mcp-server/src/tools/plans/retrieve-plans.ts +++ b/packages/mcp-server/src/tools/plans/retrieve-plans.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import { maybeFilter } from 'beagle-mcp/filtering'; import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -17,20 +18,27 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'retrieve_plans', - description: 'retrieve a specific plans details by its code.', + description: + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nretrieve a specific plans details by its code.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/plan',\n $defs: {\n plan: {\n type: 'object',\n properties: {\n description: {\n type: 'string'\n },\n name: {\n type: 'string',\n description: 'the plans name/code, this is used when creating enrollments.'\n },\n rate: {\n type: 'number',\n description: 'the price of the plan'\n },\n contents: {\n type: 'number',\n description: 'value of contents replacement, note this is only on some TLL plans.'\n },\n liability: {\n type: 'number',\n description: 'value of liability waived, note this is only on TLL plans.'\n },\n value: {\n type: 'number',\n description: 'general value field, this is currently used for SDR and SDD plans for the replacement or discount value.'\n }\n },\n required: [ 'description',\n 'name',\n 'rate'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { code: { type: 'string', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, }, }; export const handler = async (client: Beagle, args: Record | undefined) => { const { code, ...body } = args as any; - return asTextContentResult(await client.plans.retrieve(code)); + return asTextContentResult(await maybeFilter(args, await client.plans.retrieve(code))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts index cba8b7e1..fd62d8e5 100644 --- a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import { maybeFilter } from 'beagle-mcp/filtering'; import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -17,7 +18,8 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'create_property_managers', - description: 'create a new property manager.', + description: + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ncreate a new property manager.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/property_manager',\n $defs: {\n property_manager: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n addresses: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/address'\n }\n ]\n }\n },\n contacts: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/contact'\n }\n ]\n }\n },\n name: {\n type: 'string',\n description: 'name of the property manager'\n }\n },\n required: [ 'id',\n 'addresses',\n 'contacts',\n 'name'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { @@ -45,6 +47,12 @@ export const tool: Tool = { type: 'string', description: 'name of the property manager', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, $defs: { address: { @@ -100,7 +108,7 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const body = args as any; - return asTextContentResult(await client.propertyManagers.create(body)); + return asTextContentResult(await maybeFilter(args, await client.propertyManagers.create(body))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts b/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts index 245fd18c..44a9fa9e 100644 --- a/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts @@ -17,13 +17,20 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'delete_property_managers', - description: 'delete a property manager by id.', + description: + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ndelete a property manager by id.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {}\n}\n```", inputSchema: { type: 'object', properties: { id: { type: 'number', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, }, }; diff --git a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts index 8ab6daba..907a0f93 100644 --- a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import { maybeFilter } from 'beagle-mcp/filtering'; import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -17,7 +18,8 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'list_property_managers', - description: 'list all property managers, note this endpoint is paginated.', + description: + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlist all property managers, note this endpoint is paginated.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n pagination: {\n $ref: '#/$defs/pagination'\n },\n propertyManagers: {\n type: 'array',\n items: {\n $ref: '#/$defs/property_manager'\n }\n }\n },\n required: [ 'pagination',\n 'propertyManagers'\n ],\n $defs: {\n pagination: {\n type: 'object',\n properties: {\n page: {\n type: 'number',\n description: 'Current page number.'\n },\n pages: {\n type: 'number',\n description: 'Total number of pages.'\n },\n records: {\n type: 'number',\n description: 'Total number of records.'\n },\n size: {\n type: 'number',\n description: 'Number of items per page.'\n }\n },\n required: [ 'page',\n 'pages',\n 'records',\n 'size'\n ]\n },\n property_manager: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n addresses: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/address'\n }\n ]\n }\n },\n contacts: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/contact'\n }\n ]\n }\n },\n name: {\n type: 'string',\n description: 'name of the property manager'\n }\n },\n required: [ 'id',\n 'addresses',\n 'contacts',\n 'name'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { @@ -29,13 +31,20 @@ export const tool: Tool = { type: 'number', description: 'Number of items per page.', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, }, }; export const handler = async (client: Beagle, args: Record | undefined) => { const body = args as any; - return asTextContentResult(await client.propertyManagers.list(body)); + const response = await client.propertyManagers.list(body).asResponse(); + return asTextContentResult(await maybeFilter(args, await response.json())); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts index fd0679df..c2790b2d 100644 --- a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import { maybeFilter } from 'beagle-mcp/filtering'; import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -17,20 +18,27 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'retrieve_property_managers', - description: 'get a property manager by id.', + description: + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nget a property manager by id.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/property_manager',\n $defs: {\n property_manager: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n addresses: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/address'\n }\n ]\n }\n },\n contacts: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/contact'\n }\n ]\n }\n },\n name: {\n type: 'string',\n description: 'name of the property manager'\n }\n },\n required: [ 'id',\n 'addresses',\n 'contacts',\n 'name'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { id: { type: 'number', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, }, }; export const handler = async (client: Beagle, args: Record | undefined) => { const { id, ...body } = args as any; - return asTextContentResult(await client.propertyManagers.retrieve(id)); + return asTextContentResult(await maybeFilter(args, await client.propertyManagers.retrieve(id))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts index 6828e9f2..c7c580c2 100644 --- a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import { maybeFilter } from 'beagle-mcp/filtering'; import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -18,7 +19,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'update_property_managers', description: - 'update an existing property manager by id, note that when updating contacts or addresses you need to send the whole array you want to replace them with.', + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nupdate an existing property manager by id, note that when updating contacts or addresses you need to send the whole array you want to replace them with.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/property_manager',\n $defs: {\n property_manager: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n addresses: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/address'\n }\n ]\n }\n },\n contacts: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/contact'\n }\n ]\n }\n },\n name: {\n type: 'string',\n description: 'name of the property manager'\n }\n },\n required: [ 'id',\n 'addresses',\n 'contacts',\n 'name'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { @@ -49,6 +50,12 @@ export const tool: Tool = { type: 'string', description: 'name of the property manager', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, $defs: { address: { @@ -104,7 +111,7 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { id, ...body } = args as any; - return asTextContentResult(await client.propertyManagers.update(id, body)); + return asTextContentResult(await maybeFilter(args, await client.propertyManagers.update(id, body))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/tenants/create-tenants.ts b/packages/mcp-server/src/tools/tenants/create-tenants.ts index c615eedc..ee98f8e4 100644 --- a/packages/mcp-server/src/tools/tenants/create-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/create-tenants.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import { maybeFilter } from 'beagle-mcp/filtering'; import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -17,7 +18,8 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'create_tenants', - description: 'create a new tenant.', + description: + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ncreate a new tenant.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/tenant',\n $defs: {\n tenant: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n address: {\n $ref: '#/$defs/address'\n },\n contact: {\n $ref: '#/$defs/contact'\n }\n },\n required: [ 'id',\n 'address',\n 'contact'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { @@ -30,6 +32,12 @@ export const tool: Tool = { propertyManagerId: { type: 'number', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, $defs: { address: { @@ -85,7 +93,7 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const body = args as any; - return asTextContentResult(await client.tenants.create(body)); + return asTextContentResult(await maybeFilter(args, await client.tenants.create(body))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/tenants/delete-tenants.ts b/packages/mcp-server/src/tools/tenants/delete-tenants.ts index dc2afc99..7d26cb97 100644 --- a/packages/mcp-server/src/tools/tenants/delete-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/delete-tenants.ts @@ -17,13 +17,20 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'delete_tenants', - description: 'delete an existing tenant by their id.', + description: + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ndelete an existing tenant by their id.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {}\n}\n```", inputSchema: { type: 'object', properties: { id: { type: 'number', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, }, }; diff --git a/packages/mcp-server/src/tools/tenants/list-tenants.ts b/packages/mcp-server/src/tools/tenants/list-tenants.ts index ef715463..88811f5b 100644 --- a/packages/mcp-server/src/tools/tenants/list-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/list-tenants.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import { maybeFilter } from 'beagle-mcp/filtering'; import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -18,7 +19,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'list_tenants', description: - 'list all tenants, this endpoint is paginated and allows for queries by individual property manager.', + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlist all tenants, this endpoint is paginated and allows for queries by individual property manager.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n pagination: {\n $ref: '#/$defs/pagination'\n },\n tenants: {\n type: 'array',\n items: {\n $ref: '#/$defs/tenant'\n }\n }\n },\n required: [ 'pagination',\n 'tenants'\n ],\n $defs: {\n pagination: {\n type: 'object',\n properties: {\n page: {\n type: 'number',\n description: 'Current page number.'\n },\n pages: {\n type: 'number',\n description: 'Total number of pages.'\n },\n records: {\n type: 'number',\n description: 'Total number of records.'\n },\n size: {\n type: 'number',\n description: 'Number of items per page.'\n }\n },\n required: [ 'page',\n 'pages',\n 'records',\n 'size'\n ]\n },\n tenant: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n address: {\n $ref: '#/$defs/address'\n },\n contact: {\n $ref: '#/$defs/contact'\n }\n },\n required: [ 'id',\n 'address',\n 'contact'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { @@ -33,13 +34,20 @@ export const tool: Tool = { type: 'number', description: 'Number of items per page.', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, }, }; export const handler = async (client: Beagle, args: Record | undefined) => { const body = args as any; - return asTextContentResult(await client.tenants.list(body)); + const response = await client.tenants.list(body).asResponse(); + return asTextContentResult(await maybeFilter(args, await response.json())); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts b/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts index fbe6392b..06e7bccf 100644 --- a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import { maybeFilter } from 'beagle-mcp/filtering'; import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -17,20 +18,27 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'retrieve_tenants', - description: 'retrieve a single tenant by their id.', + description: + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nretrieve a single tenant by their id.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/tenant',\n $defs: {\n tenant: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n address: {\n $ref: '#/$defs/address'\n },\n contact: {\n $ref: '#/$defs/contact'\n }\n },\n required: [ 'id',\n 'address',\n 'contact'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { id: { type: 'number', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, }, }; export const handler = async (client: Beagle, args: Record | undefined) => { const { id, ...body } = args as any; - return asTextContentResult(await client.tenants.retrieve(id)); + return asTextContentResult(await maybeFilter(args, await client.tenants.retrieve(id))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/tenants/update-tenants.ts b/packages/mcp-server/src/tools/tenants/update-tenants.ts index df99f9d4..c9f7452c 100644 --- a/packages/mcp-server/src/tools/tenants/update-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/update-tenants.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import { maybeFilter } from 'beagle-mcp/filtering'; import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -17,7 +18,8 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'update_tenants', - description: 'update an existing tenant by their id.', + description: + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nupdate an existing tenant by their id.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/tenant',\n $defs: {\n tenant: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n address: {\n $ref: '#/$defs/address'\n },\n contact: {\n $ref: '#/$defs/contact'\n }\n },\n required: [ 'id',\n 'address',\n 'contact'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { @@ -30,6 +32,12 @@ export const tool: Tool = { contact: { $ref: '#/$defs/contact', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, $defs: { address: { @@ -85,7 +93,7 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { id, ...body } = args as any; - return asTextContentResult(await client.tenants.update(id, body)); + return asTextContentResult(await maybeFilter(args, await client.tenants.update(id, body))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts index 8cc998ec..55515036 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import { maybeFilter } from 'beagle-mcp/filtering'; import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -17,7 +18,8 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'create_webhook_endpoints', - description: 'creates a new webhook target.', + description: + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ncreates a new webhook target.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n active: {\n type: 'boolean'\n },\n companyId: {\n type: 'number'\n },\n createdAt: {\n type: 'string'\n },\n updatedAt: {\n type: 'string'\n },\n url: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'active',\n 'companyId',\n 'createdAt',\n 'updatedAt',\n 'url'\n ]\n}\n```", inputSchema: { type: 'object', properties: { @@ -30,13 +32,19 @@ export const tool: Tool = { active: { type: 'boolean', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, }, }; export const handler = async (client: Beagle, args: Record | undefined) => { const body = args as any; - return asTextContentResult(await client.webhook.endpoints.create(body)); + return asTextContentResult(await maybeFilter(args, await client.webhook.endpoints.create(body))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts index 9c6f1ac9..ce91bcb1 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts @@ -17,13 +17,20 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'delete_webhook_endpoints', - description: 'delete an existing webhook endpoint by its id.', + description: + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ndelete an existing webhook endpoint by its id.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {}\n}\n```", inputSchema: { type: 'object', properties: { id: { type: 'number', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, }, }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts index 2243dc12..9d2fb38c 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import { maybeFilter } from 'beagle-mcp/filtering'; import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -18,7 +19,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'list_webhook_endpoints', description: - 'list all webhook endpoints, this endpoint is paginated and allows for queries by individual property manager.', + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlist all webhook endpoints, this endpoint is paginated and allows for queries by individual property manager.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n endpoints: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n active: {\n type: 'boolean'\n },\n companyId: {\n type: 'number'\n },\n createdAt: {\n type: 'string'\n },\n updatedAt: {\n type: 'string'\n },\n url: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'active',\n 'companyId',\n 'createdAt',\n 'updatedAt',\n 'url'\n ]\n }\n },\n pagination: {\n $ref: '#/$defs/pagination'\n }\n },\n required: [ 'endpoints',\n 'pagination'\n ],\n $defs: {\n pagination: {\n type: 'object',\n properties: {\n page: {\n type: 'number',\n description: 'Current page number.'\n },\n pages: {\n type: 'number',\n description: 'Total number of pages.'\n },\n records: {\n type: 'number',\n description: 'Total number of records.'\n },\n size: {\n type: 'number',\n description: 'Number of items per page.'\n }\n },\n required: [ 'page',\n 'pages',\n 'records',\n 'size'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { @@ -30,13 +31,20 @@ export const tool: Tool = { type: 'number', description: 'Number of items per page.', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, }, }; export const handler = async (client: Beagle, args: Record | undefined) => { const body = args as any; - return asTextContentResult(await client.webhook.endpoints.list(body)); + const response = await client.webhook.endpoints.list(body).asResponse(); + return asTextContentResult(await maybeFilter(args, await response.json())); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts index f786cf67..99435fd6 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import { maybeFilter } from 'beagle-mcp/filtering'; import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -17,20 +18,27 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'retrieve_webhook_endpoints', - description: 'retrieve a single webhook endpoint by its id.', + description: + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nretrieve a single webhook endpoint by its id.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n active: {\n type: 'boolean'\n },\n companyId: {\n type: 'number'\n },\n createdAt: {\n type: 'string'\n },\n updatedAt: {\n type: 'string'\n },\n url: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'active',\n 'companyId',\n 'createdAt',\n 'updatedAt',\n 'url'\n ]\n}\n```", inputSchema: { type: 'object', properties: { id: { type: 'number', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, }, }; export const handler = async (client: Beagle, args: Record | undefined) => { const { id, ...body } = args as any; - return asTextContentResult(await client.webhook.endpoints.retrieve(id)); + return asTextContentResult(await maybeFilter(args, await client.webhook.endpoints.retrieve(id))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts index de6fe8aa..4f5d0917 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import { maybeFilter } from 'beagle-mcp/filtering'; import { asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -17,7 +18,8 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'update_webhook_endpoints', - description: 'update an existing webhook endpoint by its id.', + description: + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nupdate an existing webhook endpoint by its id.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n active: {\n type: 'boolean'\n },\n companyId: {\n type: 'number'\n },\n createdAt: {\n type: 'string'\n },\n updatedAt: {\n type: 'string'\n },\n url: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'active',\n 'companyId',\n 'createdAt',\n 'updatedAt',\n 'url'\n ]\n}\n```", inputSchema: { type: 'object', properties: { @@ -33,13 +35,19 @@ export const tool: Tool = { active: { type: 'boolean', }, + jq_filter: { + type: 'string', + title: 'jq Filter', + description: + 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', + }, }, }, }; export const handler = async (client: Beagle, args: Record | undefined) => { const { id, ...body } = args as any; - return asTextContentResult(await client.webhook.endpoints.update(id, body)); + return asTextContentResult(await maybeFilter(args, await client.webhook.endpoints.update(id, body))); }; export default { metadata, tool, handler }; From 0fc1bad413b3171b03e941df0f7fc0efe9d77f42 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 11 Jul 2025 03:47:32 +0000 Subject: [PATCH 006/138] fix(mcp): relax input type for asTextContextResult --- packages/mcp-server/src/tools/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mcp-server/src/tools/types.ts b/packages/mcp-server/src/tools/types.ts index e25cc99c..9baf238e 100644 --- a/packages/mcp-server/src/tools/types.ts +++ b/packages/mcp-server/src/tools/types.ts @@ -47,7 +47,7 @@ export type HandlerFunction = ( args: Record | undefined, ) => Promise; -export function asTextContentResult(result: Object): ToolCallResult { +export function asTextContentResult(result: unknown): ToolCallResult { return { content: [ { From 180be3d22bc81db6ed84550dfa768c6959611d39 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 16 Jul 2025 03:35:28 +0000 Subject: [PATCH 007/138] fix(mcp): support jq filtering on cloudflare workers --- packages/mcp-server/package.json | 2 +- packages/mcp-server/src/filtering.ts | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 22cd7b93..15114192 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -29,7 +29,7 @@ "dependencies": { "@corgi-tech/beagle": "file:../../dist/", "@modelcontextprotocol/sdk": "^1.11.5", - "jq-web": "^0.6.2", + "jq-web": "https://github.com/stainless-api/jq-web/releases/download/v0.8.2/jq-web.tar.gz", "yargs": "^17.7.2", "@cloudflare/cabidela": "^0.2.4", "zod": "^3.25.20", diff --git a/packages/mcp-server/src/filtering.ts b/packages/mcp-server/src/filtering.ts index e560736f..87eab2de 100644 --- a/packages/mcp-server/src/filtering.ts +++ b/packages/mcp-server/src/filtering.ts @@ -1,3 +1,6 @@ +// @ts-nocheck +import initJq from 'jq-web'; + export async function maybeFilter(args: Record | undefined, response: any): Promise { const jqFilter = args?.['jq_filter']; if (jqFilter && typeof jqFilter === 'string') { @@ -7,7 +10,6 @@ export async function maybeFilter(args: Record | undefined, res } } -var jqWeb = require('jq-web'); async function jq(json: any, jqFilter: string) { - return (await jqWeb).json(json, jqFilter); + return (await initJq).json(json, jqFilter); } From 9d6e556504b526cb6b76cb190f0ee7fe01f68711 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 16 Jul 2025 03:56:32 +0000 Subject: [PATCH 008/138] chore(mcp): rework imports in tools --- .../mcp-server/src/tools/enrollments/create-enrollments.ts | 3 +-- packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts | 3 +-- packages/mcp-server/src/tools/enrollments/list-enrollments.ts | 3 +-- .../mcp-server/src/tools/enrollments/retrieve-enrollments.ts | 3 +-- .../insurance-verification/verify-insurance-verification.ts | 3 +-- packages/mcp-server/src/tools/plans/list-plans.ts | 3 +-- packages/mcp-server/src/tools/plans/retrieve-plans.ts | 3 +-- .../src/tools/property-managers/create-property-managers.ts | 3 +-- .../src/tools/property-managers/delete-property-managers.ts | 3 +-- .../src/tools/property-managers/list-property-managers.ts | 3 +-- .../src/tools/property-managers/retrieve-property-managers.ts | 3 +-- .../src/tools/property-managers/update-property-managers.ts | 3 +-- packages/mcp-server/src/tools/tenants/create-tenants.ts | 3 +-- packages/mcp-server/src/tools/tenants/delete-tenants.ts | 3 +-- packages/mcp-server/src/tools/tenants/list-tenants.ts | 3 +-- packages/mcp-server/src/tools/tenants/retrieve-tenants.ts | 3 +-- packages/mcp-server/src/tools/tenants/update-tenants.ts | 3 +-- .../src/tools/webhook/endpoints/create-webhook-endpoints.ts | 3 +-- .../src/tools/webhook/endpoints/delete-webhook-endpoints.ts | 3 +-- .../src/tools/webhook/endpoints/list-webhook-endpoints.ts | 3 +-- .../src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts | 3 +-- .../src/tools/webhook/endpoints/update-webhook-endpoints.ts | 3 +-- 22 files changed, 22 insertions(+), 44 deletions(-) diff --git a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts index c5f7645a..6e14fe80 100644 --- a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts @@ -1,10 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { maybeFilter } from 'beagle-mcp/filtering'; -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts b/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts index 09fe5ee1..99928167 100644 --- a/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts @@ -1,9 +1,8 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts index 6209b177..04927cb0 100644 --- a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts @@ -1,10 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { maybeFilter } from 'beagle-mcp/filtering'; -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts index 4e1cbacd..1a404457 100644 --- a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts @@ -1,10 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { maybeFilter } from 'beagle-mcp/filtering'; -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts index 91c3c269..1f13cc21 100644 --- a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts +++ b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts @@ -1,10 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { maybeFilter } from 'beagle-mcp/filtering'; -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/plans/list-plans.ts b/packages/mcp-server/src/tools/plans/list-plans.ts index e8f62db3..c0985d34 100644 --- a/packages/mcp-server/src/tools/plans/list-plans.ts +++ b/packages/mcp-server/src/tools/plans/list-plans.ts @@ -1,10 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { maybeFilter } from 'beagle-mcp/filtering'; -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/plans/retrieve-plans.ts b/packages/mcp-server/src/tools/plans/retrieve-plans.ts index 4bae495a..47c83df0 100644 --- a/packages/mcp-server/src/tools/plans/retrieve-plans.ts +++ b/packages/mcp-server/src/tools/plans/retrieve-plans.ts @@ -1,10 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { maybeFilter } from 'beagle-mcp/filtering'; -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts index fd62d8e5..c980cba4 100644 --- a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts @@ -1,10 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { maybeFilter } from 'beagle-mcp/filtering'; -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts b/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts index 44a9fa9e..2f69d855 100644 --- a/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts @@ -1,9 +1,8 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts index 907a0f93..57e4323f 100644 --- a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts @@ -1,10 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { maybeFilter } from 'beagle-mcp/filtering'; -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts index c2790b2d..cbb1f56e 100644 --- a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts @@ -1,10 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { maybeFilter } from 'beagle-mcp/filtering'; -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts index c7c580c2..e745ba95 100644 --- a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts @@ -1,10 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { maybeFilter } from 'beagle-mcp/filtering'; -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/tenants/create-tenants.ts b/packages/mcp-server/src/tools/tenants/create-tenants.ts index ee98f8e4..38e3b451 100644 --- a/packages/mcp-server/src/tools/tenants/create-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/create-tenants.ts @@ -1,10 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { maybeFilter } from 'beagle-mcp/filtering'; -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/tenants/delete-tenants.ts b/packages/mcp-server/src/tools/tenants/delete-tenants.ts index 7d26cb97..0e81c1d1 100644 --- a/packages/mcp-server/src/tools/tenants/delete-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/delete-tenants.ts @@ -1,9 +1,8 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/tenants/list-tenants.ts b/packages/mcp-server/src/tools/tenants/list-tenants.ts index 88811f5b..70dad994 100644 --- a/packages/mcp-server/src/tools/tenants/list-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/list-tenants.ts @@ -1,10 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { maybeFilter } from 'beagle-mcp/filtering'; -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts b/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts index 06e7bccf..3b586e00 100644 --- a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts @@ -1,10 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { maybeFilter } from 'beagle-mcp/filtering'; -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/tenants/update-tenants.ts b/packages/mcp-server/src/tools/tenants/update-tenants.ts index c9f7452c..0df65302 100644 --- a/packages/mcp-server/src/tools/tenants/update-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/update-tenants.ts @@ -1,10 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { maybeFilter } from 'beagle-mcp/filtering'; -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts index 55515036..4db88ddf 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts @@ -1,10 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { maybeFilter } from 'beagle-mcp/filtering'; -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts index ce91bcb1..2b02496c 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts @@ -1,9 +1,8 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts index 9d2fb38c..431784be 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts @@ -1,10 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { maybeFilter } from 'beagle-mcp/filtering'; -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts index 99435fd6..17881c51 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts @@ -1,10 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { maybeFilter } from 'beagle-mcp/filtering'; -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { diff --git a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts index 4f5d0917..aa3b1891 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts @@ -1,10 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { maybeFilter } from 'beagle-mcp/filtering'; -import { asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import type { Metadata } from '../../'; import Beagle from '@corgi-tech/beagle'; export const metadata: Metadata = { From cae3b820bd235b08a073ea4a5f19e84e8dfda76f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 17 Jul 2025 03:24:25 +0000 Subject: [PATCH 009/138] chore(ts): reorder package.json imports --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7b57e5a0..03ae8580 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "@swc/jest": "^0.2.29", "@types/jest": "^29.4.0", "@types/node": "^20.17.6", - "typescript-eslint": "8.31.1", "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", "eslint": "^9.20.1", @@ -44,7 +43,8 @@ "ts-node": "^10.5.0", "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz", "tsconfig-paths": "^4.0.0", - "typescript": "5.8.3" + "typescript": "5.8.3", + "typescript-eslint": "8.31.1" }, "imports": { "@corgi-tech/beagle": ".", From 96e93b33f65a890973af7ef80ee18052d60163a4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 17 Jul 2025 03:48:04 +0000 Subject: [PATCH 010/138] chore(mcp): formatting --- packages/mcp-server/src/server.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 00f9c654..d01229d4 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -28,11 +28,7 @@ export const server = new McpServer( name: 'corgi_tech_beagle_api', version: '0.0.1-alpha.0', }, - { - capabilities: { - tools: {}, - }, - }, + { capabilities: { tools: {} } }, ); /** From e9ffc0ed916dfe1d31e71e716106c828812e7059 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 18 Jul 2025 03:07:04 +0000 Subject: [PATCH 011/138] fix(mcp): include required section for top-level properties and support naming transformations --- packages/mcp-server/src/tools/enrollments/create-enrollments.ts | 1 + packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts | 1 + packages/mcp-server/src/tools/enrollments/list-enrollments.ts | 1 + .../mcp-server/src/tools/enrollments/retrieve-enrollments.ts | 1 + .../insurance-verification/verify-insurance-verification.ts | 1 + packages/mcp-server/src/tools/plans/list-plans.ts | 1 + packages/mcp-server/src/tools/plans/retrieve-plans.ts | 1 + .../src/tools/property-managers/create-property-managers.ts | 1 + .../src/tools/property-managers/delete-property-managers.ts | 1 + .../src/tools/property-managers/list-property-managers.ts | 1 + .../src/tools/property-managers/retrieve-property-managers.ts | 1 + .../src/tools/property-managers/update-property-managers.ts | 1 + packages/mcp-server/src/tools/tenants/create-tenants.ts | 1 + packages/mcp-server/src/tools/tenants/delete-tenants.ts | 1 + packages/mcp-server/src/tools/tenants/list-tenants.ts | 1 + packages/mcp-server/src/tools/tenants/retrieve-tenants.ts | 1 + packages/mcp-server/src/tools/tenants/update-tenants.ts | 1 + .../src/tools/webhook/endpoints/create-webhook-endpoints.ts | 1 + .../src/tools/webhook/endpoints/delete-webhook-endpoints.ts | 1 + .../src/tools/webhook/endpoints/list-webhook-endpoints.ts | 1 + .../src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts | 1 + .../src/tools/webhook/endpoints/update-webhook-endpoints.ts | 1 + 22 files changed, 22 insertions(+) diff --git a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts index 6e14fe80..bf428460 100644 --- a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts @@ -47,6 +47,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: ['effectiveDate', 'plan', 'propertyManagerId', 'tenantId'], }, }; diff --git a/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts b/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts index 99928167..42451172 100644 --- a/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts @@ -31,6 +31,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: ['id'], }, }; diff --git a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts index 04927cb0..073ac2d5 100644 --- a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts @@ -40,6 +40,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: [], }, }; diff --git a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts index 1a404457..f961abed 100644 --- a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts @@ -32,6 +32,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: ['id'], }, }; diff --git a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts index 1f13cc21..f210d99e 100644 --- a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts +++ b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts @@ -42,6 +42,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: ['propertyManagerId', 'tenantId', 'urls'], }, }; diff --git a/packages/mcp-server/src/tools/plans/list-plans.ts b/packages/mcp-server/src/tools/plans/list-plans.ts index c0985d34..d768334c 100644 --- a/packages/mcp-server/src/tools/plans/list-plans.ts +++ b/packages/mcp-server/src/tools/plans/list-plans.ts @@ -29,6 +29,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: [], }, }; diff --git a/packages/mcp-server/src/tools/plans/retrieve-plans.ts b/packages/mcp-server/src/tools/plans/retrieve-plans.ts index 47c83df0..c8fb055d 100644 --- a/packages/mcp-server/src/tools/plans/retrieve-plans.ts +++ b/packages/mcp-server/src/tools/plans/retrieve-plans.ts @@ -32,6 +32,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: ['code'], }, }; diff --git a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts index c980cba4..cd14ba03 100644 --- a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts @@ -53,6 +53,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: ['addresses', 'contacts', 'name'], $defs: { address: { type: 'object', diff --git a/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts b/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts index 2f69d855..0dc1e4e8 100644 --- a/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts @@ -31,6 +31,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: ['id'], }, }; diff --git a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts index 57e4323f..e25b2ba1 100644 --- a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts @@ -37,6 +37,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: [], }, }; diff --git a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts index cbb1f56e..84ae5336 100644 --- a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts @@ -32,6 +32,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: ['id'], }, }; diff --git a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts index e745ba95..c745e4ca 100644 --- a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts @@ -56,6 +56,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: ['id'], $defs: { address: { type: 'object', diff --git a/packages/mcp-server/src/tools/tenants/create-tenants.ts b/packages/mcp-server/src/tools/tenants/create-tenants.ts index 38e3b451..18ea6bd3 100644 --- a/packages/mcp-server/src/tools/tenants/create-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/create-tenants.ts @@ -38,6 +38,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: ['address', 'contact', 'propertyManagerId'], $defs: { address: { type: 'object', diff --git a/packages/mcp-server/src/tools/tenants/delete-tenants.ts b/packages/mcp-server/src/tools/tenants/delete-tenants.ts index 0e81c1d1..2a06fba2 100644 --- a/packages/mcp-server/src/tools/tenants/delete-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/delete-tenants.ts @@ -31,6 +31,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: ['id'], }, }; diff --git a/packages/mcp-server/src/tools/tenants/list-tenants.ts b/packages/mcp-server/src/tools/tenants/list-tenants.ts index 70dad994..d947a954 100644 --- a/packages/mcp-server/src/tools/tenants/list-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/list-tenants.ts @@ -40,6 +40,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: [], }, }; diff --git a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts b/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts index 3b586e00..adc4af94 100644 --- a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts @@ -32,6 +32,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: ['id'], }, }; diff --git a/packages/mcp-server/src/tools/tenants/update-tenants.ts b/packages/mcp-server/src/tools/tenants/update-tenants.ts index 0df65302..2664a42c 100644 --- a/packages/mcp-server/src/tools/tenants/update-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/update-tenants.ts @@ -38,6 +38,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: ['id'], $defs: { address: { type: 'object', diff --git a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts index 4db88ddf..f638eaee 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts @@ -38,6 +38,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: ['secret', 'url'], }, }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts index 2b02496c..a9011f1e 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts @@ -31,6 +31,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: ['id'], }, }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts index 431784be..4aea6733 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts @@ -37,6 +37,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: [], }, }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts index 17881c51..65533744 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts @@ -32,6 +32,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: ['id'], }, }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts index aa3b1891..c7e95656 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts @@ -41,6 +41,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, + required: ['id', 'secret', 'url'], }, }; From 2bb87b26625aac745e42fc2ef606ad6acce5e6a8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 20:25:00 +0000 Subject: [PATCH 012/138] feat(api): api update --- .stats.yml | 4 ++-- .../tools/enrollments/create-enrollments.ts | 17 ++++++++++++++-- .../src/tools/enrollments/list-enrollments.ts | 2 +- .../tools/enrollments/retrieve-enrollments.ts | 2 +- src/resources/enrollments.ts | 20 +++++++++++++++++++ tests/api-resources/enrollments.test.ts | 2 ++ 6 files changed, 41 insertions(+), 6 deletions(-) diff --git a/.stats.yml b/.stats.yml index b4760d4c..fc50d334 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-55e2c475fba1a969f73f7679e68a776e962352dc584f6ee83368947d35d3c96d.yml -openapi_spec_hash: f3b4f7afe0ef02a9054be3c705f75ab3 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-2edadee34a317889c9d854eb566c42649fb0f53ce572927a42cd873421d86486.yml +openapi_spec_hash: ebc55666c40434190b539cd87761635b config_hash: d63f662e216ecc51eccc05b8a4b5198e diff --git a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts index bf428460..b2376e7b 100644 --- a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'create_enrollments', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ncreate a new enrollment for a tenant.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/enrollment',\n $defs: {\n enrollment: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n effectiveDate: {\n type: 'string',\n description: 'the date the enrollment will begin, note enrollments cannot begin in the past'\n },\n plan: {\n type: 'string',\n description: 'the plan name/code'\n },\n propertyManagerId: {\n type: 'number'\n },\n tenantId: {\n type: 'number'\n },\n note: {\n type: 'string',\n description: 'an optional note field, this can be used for easily appending metadata to enrollments'\n }\n },\n required: [ 'id',\n 'effectiveDate',\n 'plan',\n 'propertyManagerId',\n 'tenantId'\n ]\n }\n }\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ncreate a new enrollment for a tenant.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/enrollment',\n $defs: {\n enrollment: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n effectiveDate: {\n type: 'string',\n description: 'the date the enrollment will begin, note enrollments cannot begin in the past'\n },\n plan: {\n type: 'string',\n description: 'the plan name/code'\n },\n propertyManagerId: {\n type: 'number'\n },\n status: {\n type: 'string',\n enum: [ 'Premium Paying',\n 'Issued, Not Paid',\n 'Expired',\n 'Lapsed',\n 'Suspended',\n 'Cancelled',\n 'Not taken',\n 'Declined'\n ]\n },\n tenantId: {\n type: 'number'\n },\n note: {\n type: 'string',\n description: 'an optional note field, this can be used for easily appending metadata to enrollments'\n }\n },\n required: [ 'id',\n 'effectiveDate',\n 'plan',\n 'propertyManagerId',\n 'status',\n 'tenantId'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { @@ -33,6 +33,19 @@ export const tool: Tool = { propertyManagerId: { type: 'number', }, + status: { + type: 'string', + enum: [ + 'Premium Paying', + 'Issued, Not Paid', + 'Expired', + 'Lapsed', + 'Suspended', + 'Cancelled', + 'Not taken', + 'Declined', + ], + }, tenantId: { type: 'number', }, @@ -47,7 +60,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, - required: ['effectiveDate', 'plan', 'propertyManagerId', 'tenantId'], + required: ['effectiveDate', 'plan', 'propertyManagerId', 'status', 'tenantId'], }, }; diff --git a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts index 073ac2d5..7c562232 100644 --- a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'list_enrollments', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlist all enrollments, this endpoint is paginated and allows for queries by individual property manager.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n enrollments: {\n type: 'array',\n items: {\n $ref: '#/$defs/enrollment'\n }\n },\n pagination: {\n $ref: '#/$defs/pagination'\n }\n },\n required: [ 'enrollments',\n 'pagination'\n ],\n $defs: {\n enrollment: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n effectiveDate: {\n type: 'string',\n description: 'the date the enrollment will begin, note enrollments cannot begin in the past'\n },\n plan: {\n type: 'string',\n description: 'the plan name/code'\n },\n propertyManagerId: {\n type: 'number'\n },\n tenantId: {\n type: 'number'\n },\n note: {\n type: 'string',\n description: 'an optional note field, this can be used for easily appending metadata to enrollments'\n }\n },\n required: [ 'id',\n 'effectiveDate',\n 'plan',\n 'propertyManagerId',\n 'tenantId'\n ]\n },\n pagination: {\n type: 'object',\n properties: {\n page: {\n type: 'number',\n description: 'Current page number.'\n },\n pages: {\n type: 'number',\n description: 'Total number of pages.'\n },\n records: {\n type: 'number',\n description: 'Total number of records.'\n },\n size: {\n type: 'number',\n description: 'Number of items per page.'\n }\n },\n required: [ 'page',\n 'pages',\n 'records',\n 'size'\n ]\n }\n }\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlist all enrollments, this endpoint is paginated and allows for queries by individual property manager.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n enrollments: {\n type: 'array',\n items: {\n $ref: '#/$defs/enrollment'\n }\n },\n pagination: {\n $ref: '#/$defs/pagination'\n }\n },\n required: [ 'enrollments',\n 'pagination'\n ],\n $defs: {\n enrollment: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n effectiveDate: {\n type: 'string',\n description: 'the date the enrollment will begin, note enrollments cannot begin in the past'\n },\n plan: {\n type: 'string',\n description: 'the plan name/code'\n },\n propertyManagerId: {\n type: 'number'\n },\n status: {\n type: 'string',\n enum: [ 'Premium Paying',\n 'Issued, Not Paid',\n 'Expired',\n 'Lapsed',\n 'Suspended',\n 'Cancelled',\n 'Not taken',\n 'Declined'\n ]\n },\n tenantId: {\n type: 'number'\n },\n note: {\n type: 'string',\n description: 'an optional note field, this can be used for easily appending metadata to enrollments'\n }\n },\n required: [ 'id',\n 'effectiveDate',\n 'plan',\n 'propertyManagerId',\n 'status',\n 'tenantId'\n ]\n },\n pagination: {\n type: 'object',\n properties: {\n page: {\n type: 'number',\n description: 'Current page number.'\n },\n pages: {\n type: 'number',\n description: 'Total number of pages.'\n },\n records: {\n type: 'number',\n description: 'Total number of records.'\n },\n size: {\n type: 'number',\n description: 'Number of items per page.'\n }\n },\n required: [ 'page',\n 'pages',\n 'records',\n 'size'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { diff --git a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts index f961abed..7ab84e25 100644 --- a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'retrieve_enrollments', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nget a specific enrollment by its id.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/enrollment',\n $defs: {\n enrollment: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n effectiveDate: {\n type: 'string',\n description: 'the date the enrollment will begin, note enrollments cannot begin in the past'\n },\n plan: {\n type: 'string',\n description: 'the plan name/code'\n },\n propertyManagerId: {\n type: 'number'\n },\n tenantId: {\n type: 'number'\n },\n note: {\n type: 'string',\n description: 'an optional note field, this can be used for easily appending metadata to enrollments'\n }\n },\n required: [ 'id',\n 'effectiveDate',\n 'plan',\n 'propertyManagerId',\n 'tenantId'\n ]\n }\n }\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nget a specific enrollment by its id.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/enrollment',\n $defs: {\n enrollment: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n effectiveDate: {\n type: 'string',\n description: 'the date the enrollment will begin, note enrollments cannot begin in the past'\n },\n plan: {\n type: 'string',\n description: 'the plan name/code'\n },\n propertyManagerId: {\n type: 'number'\n },\n status: {\n type: 'string',\n enum: [ 'Premium Paying',\n 'Issued, Not Paid',\n 'Expired',\n 'Lapsed',\n 'Suspended',\n 'Cancelled',\n 'Not taken',\n 'Declined'\n ]\n },\n tenantId: {\n type: 'number'\n },\n note: {\n type: 'string',\n description: 'an optional note field, this can be used for easily appending metadata to enrollments'\n }\n },\n required: [ 'id',\n 'effectiveDate',\n 'plan',\n 'propertyManagerId',\n 'status',\n 'tenantId'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { diff --git a/src/resources/enrollments.ts b/src/resources/enrollments.ts index bb710ad3..e341e765 100644 --- a/src/resources/enrollments.ts +++ b/src/resources/enrollments.ts @@ -65,6 +65,16 @@ export interface Enrollment { propertyManagerId: number; + status: + | 'Premium Paying' + | 'Issued, Not Paid' + | 'Expired' + | 'Lapsed' + | 'Suspended' + | 'Cancelled' + | 'Not taken' + | 'Declined'; + tenantId: number; /** @@ -87,6 +97,16 @@ export interface EnrollmentCreateParams { propertyManagerId: number; + status: + | 'Premium Paying' + | 'Issued, Not Paid' + | 'Expired' + | 'Lapsed' + | 'Suspended' + | 'Cancelled' + | 'Not taken' + | 'Declined'; + tenantId: number; /** diff --git a/tests/api-resources/enrollments.test.ts b/tests/api-resources/enrollments.test.ts index 72607467..c4a9b76f 100644 --- a/tests/api-resources/enrollments.test.ts +++ b/tests/api-resources/enrollments.test.ts @@ -14,6 +14,7 @@ describe('resource enrollments', () => { effectiveDate: 'effectiveDate', plan: 'plan', propertyManagerId: 0, + status: 'Premium Paying', tenantId: 0, }); const rawResponse = await responsePromise.asResponse(); @@ -31,6 +32,7 @@ describe('resource enrollments', () => { effectiveDate: 'effectiveDate', plan: 'plan', propertyManagerId: 0, + status: 'Premium Paying', tenantId: 0, note: 'note', }); From 394b04426e6469324b8bc42a1ad94b70b64666a1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 24 Jul 2025 03:50:36 +0000 Subject: [PATCH 013/138] chore(internal): codegen related update --- .../mcp-server/src/tools/enrollments/create-enrollments.ts | 1 + packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts | 3 +++ packages/mcp-server/src/tools/enrollments/list-enrollments.ts | 3 +++ .../mcp-server/src/tools/enrollments/retrieve-enrollments.ts | 3 +++ .../insurance-verification/verify-insurance-verification.ts | 1 + packages/mcp-server/src/tools/plans/list-plans.ts | 3 +++ packages/mcp-server/src/tools/plans/retrieve-plans.ts | 3 +++ .../src/tools/property-managers/create-property-managers.ts | 1 + .../src/tools/property-managers/delete-property-managers.ts | 3 +++ .../src/tools/property-managers/list-property-managers.ts | 3 +++ .../src/tools/property-managers/retrieve-property-managers.ts | 3 +++ .../src/tools/property-managers/update-property-managers.ts | 1 + packages/mcp-server/src/tools/tenants/create-tenants.ts | 1 + packages/mcp-server/src/tools/tenants/delete-tenants.ts | 3 +++ packages/mcp-server/src/tools/tenants/list-tenants.ts | 3 +++ packages/mcp-server/src/tools/tenants/retrieve-tenants.ts | 3 +++ packages/mcp-server/src/tools/tenants/update-tenants.ts | 1 + .../src/tools/webhook/endpoints/create-webhook-endpoints.ts | 1 + .../src/tools/webhook/endpoints/delete-webhook-endpoints.ts | 3 +++ .../src/tools/webhook/endpoints/list-webhook-endpoints.ts | 3 +++ .../src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts | 3 +++ .../src/tools/webhook/endpoints/update-webhook-endpoints.ts | 1 + 22 files changed, 50 insertions(+) diff --git a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts index b2376e7b..ecbdaebf 100644 --- a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts @@ -62,6 +62,7 @@ export const tool: Tool = { }, required: ['effectiveDate', 'plan', 'propertyManagerId', 'status', 'tenantId'], }, + annotations: {}, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts b/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts index 42451172..1800dd79 100644 --- a/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts @@ -33,6 +33,9 @@ export const tool: Tool = { }, required: ['id'], }, + annotations: { + idempotentHint: true, + }, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts index 7c562232..0f5a8e28 100644 --- a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts @@ -42,6 +42,9 @@ export const tool: Tool = { }, required: [], }, + annotations: { + readOnlyHint: true, + }, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts index 7ab84e25..e67f1d09 100644 --- a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts @@ -34,6 +34,9 @@ export const tool: Tool = { }, required: ['id'], }, + annotations: { + readOnlyHint: true, + }, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts index f210d99e..c7b3b885 100644 --- a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts +++ b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts @@ -44,6 +44,7 @@ export const tool: Tool = { }, required: ['propertyManagerId', 'tenantId', 'urls'], }, + annotations: {}, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/plans/list-plans.ts b/packages/mcp-server/src/tools/plans/list-plans.ts index d768334c..ddd4c25f 100644 --- a/packages/mcp-server/src/tools/plans/list-plans.ts +++ b/packages/mcp-server/src/tools/plans/list-plans.ts @@ -31,6 +31,9 @@ export const tool: Tool = { }, required: [], }, + annotations: { + readOnlyHint: true, + }, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/plans/retrieve-plans.ts b/packages/mcp-server/src/tools/plans/retrieve-plans.ts index c8fb055d..9bc04228 100644 --- a/packages/mcp-server/src/tools/plans/retrieve-plans.ts +++ b/packages/mcp-server/src/tools/plans/retrieve-plans.ts @@ -34,6 +34,9 @@ export const tool: Tool = { }, required: ['code'], }, + annotations: { + readOnlyHint: true, + }, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts index cd14ba03..2ac1c5d8 100644 --- a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts @@ -104,6 +104,7 @@ export const tool: Tool = { }, }, }, + annotations: {}, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts b/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts index 0dc1e4e8..9cdab9c5 100644 --- a/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts @@ -33,6 +33,9 @@ export const tool: Tool = { }, required: ['id'], }, + annotations: { + idempotentHint: true, + }, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts index e25b2ba1..2055d935 100644 --- a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts @@ -39,6 +39,9 @@ export const tool: Tool = { }, required: [], }, + annotations: { + readOnlyHint: true, + }, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts index 84ae5336..eacbe04f 100644 --- a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts @@ -34,6 +34,9 @@ export const tool: Tool = { }, required: ['id'], }, + annotations: { + readOnlyHint: true, + }, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts index c745e4ca..a8d8f65e 100644 --- a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts @@ -107,6 +107,7 @@ export const tool: Tool = { }, }, }, + annotations: {}, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/tenants/create-tenants.ts b/packages/mcp-server/src/tools/tenants/create-tenants.ts index 18ea6bd3..bd694e43 100644 --- a/packages/mcp-server/src/tools/tenants/create-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/create-tenants.ts @@ -89,6 +89,7 @@ export const tool: Tool = { }, }, }, + annotations: {}, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/tenants/delete-tenants.ts b/packages/mcp-server/src/tools/tenants/delete-tenants.ts index 2a06fba2..0006c304 100644 --- a/packages/mcp-server/src/tools/tenants/delete-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/delete-tenants.ts @@ -33,6 +33,9 @@ export const tool: Tool = { }, required: ['id'], }, + annotations: { + idempotentHint: true, + }, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/tenants/list-tenants.ts b/packages/mcp-server/src/tools/tenants/list-tenants.ts index d947a954..54c1678f 100644 --- a/packages/mcp-server/src/tools/tenants/list-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/list-tenants.ts @@ -42,6 +42,9 @@ export const tool: Tool = { }, required: [], }, + annotations: { + readOnlyHint: true, + }, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts b/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts index adc4af94..7ec0f60b 100644 --- a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts @@ -34,6 +34,9 @@ export const tool: Tool = { }, required: ['id'], }, + annotations: { + readOnlyHint: true, + }, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/tenants/update-tenants.ts b/packages/mcp-server/src/tools/tenants/update-tenants.ts index 2664a42c..84f18bc7 100644 --- a/packages/mcp-server/src/tools/tenants/update-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/update-tenants.ts @@ -89,6 +89,7 @@ export const tool: Tool = { }, }, }, + annotations: {}, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts index f638eaee..57b2443e 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts @@ -40,6 +40,7 @@ export const tool: Tool = { }, required: ['secret', 'url'], }, + annotations: {}, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts index a9011f1e..f7b2a9f6 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts @@ -33,6 +33,9 @@ export const tool: Tool = { }, required: ['id'], }, + annotations: { + idempotentHint: true, + }, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts index 4aea6733..919bd059 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts @@ -39,6 +39,9 @@ export const tool: Tool = { }, required: [], }, + annotations: { + readOnlyHint: true, + }, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts index 65533744..405589e6 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts @@ -34,6 +34,9 @@ export const tool: Tool = { }, required: ['id'], }, + annotations: { + readOnlyHint: true, + }, }; export const handler = async (client: Beagle, args: Record | undefined) => { diff --git a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts index c7e95656..cbc0c326 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts @@ -43,6 +43,7 @@ export const tool: Tool = { }, required: ['id', 'secret', 'url'], }, + annotations: {}, }; export const handler = async (client: Beagle, args: Record | undefined) => { From 00033c0b2ea16c042bdc0d2ce1405875f833b10a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 30 Jul 2025 04:18:36 +0000 Subject: [PATCH 014/138] chore(internal): remove redundant imports config --- package.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/package.json b/package.json index 03ae8580..818db4b3 100644 --- a/package.json +++ b/package.json @@ -46,10 +46,6 @@ "typescript": "5.8.3", "typescript-eslint": "8.31.1" }, - "imports": { - "@corgi-tech/beagle": ".", - "@corgi-tech/beagle/*": "./src/*" - }, "exports": { ".": { "import": "./dist/index.mjs", From bd146b56ffd0cde779cfc7d8ed67ac730599a916 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 05:00:28 +0000 Subject: [PATCH 015/138] fix(mcp): reverse validJson capability option and limit scope --- packages/mcp-server/src/compat.ts | 7 +- packages/mcp-server/src/server.ts | 2 +- packages/mcp-server/tests/options.test.ts | 133 ++++++++++++++++++++++ 3 files changed, 139 insertions(+), 3 deletions(-) diff --git a/packages/mcp-server/src/compat.ts b/packages/mcp-server/src/compat.ts index ff0d6d40..7afd77fd 100644 --- a/packages/mcp-server/src/compat.ts +++ b/packages/mcp-server/src/compat.ts @@ -70,8 +70,11 @@ export function parseEmbeddedJSON(args: Record, schema: Record< if (typeof value === 'string') { try { const parsed = JSON.parse(value); - newArgs[key] = parsed; - updated = true; + // Only parse if result is a plain object (not array, null, or primitive) + if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) { + newArgs[key] = parsed; + updated = true; + } } catch (e) { // Not valid JSON, leave as is } diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index d01229d4..1f43c62a 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -122,7 +122,7 @@ export async function executeHandler( compatibilityOptions?: Partial, ) { const options = { ...defaultClientCapabilities, ...compatibilityOptions }; - if (options.validJson && args) { + if (!options.validJson && args) { args = parseEmbeddedJSON(args, tool.inputSchema); } return await handler(client, args || {}); diff --git a/packages/mcp-server/tests/options.test.ts b/packages/mcp-server/tests/options.test.ts index f7661d68..264aca55 100644 --- a/packages/mcp-server/tests/options.test.ts +++ b/packages/mcp-server/tests/options.test.ts @@ -1,5 +1,6 @@ import { parseOptions } from '../src/options'; import { Filter } from '../src/tools'; +import { parseEmbeddedJSON } from '../src/compat'; // Mock process.argv const mockArgv = (args: string[]) => { @@ -184,3 +185,135 @@ describe('parseOptions', () => { cleanup(); }); }); + +describe('parseEmbeddedJSON', () => { + it('should not change non-string values', () => { + const args = { + numberProp: 42, + booleanProp: true, + objectProp: { nested: 'value' }, + arrayProp: [1, 2, 3], + nullProp: null, + undefinedProp: undefined, + }; + const schema = {}; + + const result = parseEmbeddedJSON(args, schema); + + expect(result).toBe(args); // Should return original object since no changes made + expect(result['numberProp']).toBe(42); + expect(result['booleanProp']).toBe(true); + expect(result['objectProp']).toEqual({ nested: 'value' }); + expect(result['arrayProp']).toEqual([1, 2, 3]); + expect(result['nullProp']).toBe(null); + expect(result['undefinedProp']).toBe(undefined); + }); + + it('should parse valid JSON objects in string properties', () => { + const args = { + jsonObjectString: '{"key": "value", "number": 123}', + regularString: 'not json', + }; + const schema = {}; + + const result = parseEmbeddedJSON(args, schema); + + expect(result).not.toBe(args); // Should return new object since changes were made + expect(result['jsonObjectString']).toEqual({ key: 'value', number: 123 }); + expect(result['regularString']).toBe('not json'); + }); + + it('should leave invalid JSON in string properties unchanged', () => { + const args = { + invalidJson1: '{"key": value}', // Missing quotes around value + invalidJson2: '{key: "value"}', // Missing quotes around key + invalidJson3: '{"key": "value",}', // Trailing comma + invalidJson4: 'just a regular string', + emptyString: '', + }; + const schema = {}; + + const result = parseEmbeddedJSON(args, schema); + + expect(result).toBe(args); // Should return original object since no changes made + expect(result['invalidJson1']).toBe('{"key": value}'); + expect(result['invalidJson2']).toBe('{key: "value"}'); + expect(result['invalidJson3']).toBe('{"key": "value",}'); + expect(result['invalidJson4']).toBe('just a regular string'); + expect(result['emptyString']).toBe(''); + }); + + it('should not parse JSON primitives in string properties', () => { + const args = { + numberString: '123', + floatString: '45.67', + negativeNumberString: '-89', + booleanTrueString: 'true', + booleanFalseString: 'false', + nullString: 'null', + jsonArrayString: '[1, 2, 3, "test"]', + regularString: 'not json', + }; + const schema = {}; + + const result = parseEmbeddedJSON(args, schema); + + expect(result).toBe(args); // Should return original object since no changes made + expect(result['numberString']).toBe('123'); + expect(result['floatString']).toBe('45.67'); + expect(result['negativeNumberString']).toBe('-89'); + expect(result['booleanTrueString']).toBe('true'); + expect(result['booleanFalseString']).toBe('false'); + expect(result['nullString']).toBe('null'); + expect(result['jsonArrayString']).toBe('[1, 2, 3, "test"]'); + expect(result['regularString']).toBe('not json'); + }); + + it('should handle mixed valid objects and other JSON types', () => { + const args = { + validObject: '{"success": true}', + invalidObject: '{"missing": quote}', + validNumber: '42', + validArray: '[1, 2, 3]', + keepAsString: 'hello world', + nonString: 123, + }; + const schema = {}; + + const result = parseEmbeddedJSON(args, schema); + + expect(result).not.toBe(args); // Should return new object since some changes were made + expect(result['validObject']).toEqual({ success: true }); + expect(result['invalidObject']).toBe('{"missing": quote}'); + expect(result['validNumber']).toBe('42'); // Not parsed, remains string + expect(result['validArray']).toBe('[1, 2, 3]'); // Not parsed, remains string + expect(result['keepAsString']).toBe('hello world'); + expect(result['nonString']).toBe(123); + }); + + it('should return original object when no strings are present', () => { + const args = { + number: 42, + boolean: true, + object: { key: 'value' }, + }; + const schema = {}; + + const result = parseEmbeddedJSON(args, schema); + + expect(result).toBe(args); // Should return original object since no changes made + }); + + it('should return original object when all strings are invalid JSON', () => { + const args = { + string1: 'hello', + string2: 'world', + string3: 'not json at all', + }; + const schema = {}; + + const result = parseEmbeddedJSON(args, schema); + + expect(result).toBe(args); // Should return original object since no changes made + }); +}); From 1f865ceabad29ea8ea696c4553ddd096b3a26c19 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 05:01:51 +0000 Subject: [PATCH 016/138] fix(mcp): avoid sending `jq_filter` to base API --- .../src/tools/enrollments/create-enrollments.ts | 4 ++-- .../src/tools/enrollments/lapse-enrollments.ts | 8 +------- .../mcp-server/src/tools/enrollments/list-enrollments.ts | 4 ++-- .../src/tools/enrollments/retrieve-enrollments.ts | 4 ++-- .../verify-insurance-verification.ts | 4 ++-- packages/mcp-server/src/tools/plans/list-plans.ts | 3 ++- packages/mcp-server/src/tools/plans/retrieve-plans.ts | 4 ++-- .../tools/property-managers/create-property-managers.ts | 4 ++-- .../tools/property-managers/delete-property-managers.ts | 9 +-------- .../tools/property-managers/list-property-managers.ts | 4 ++-- .../property-managers/retrieve-property-managers.ts | 4 ++-- .../tools/property-managers/update-property-managers.ts | 4 ++-- packages/mcp-server/src/tools/tenants/create-tenants.ts | 4 ++-- packages/mcp-server/src/tools/tenants/delete-tenants.ts | 9 +-------- packages/mcp-server/src/tools/tenants/list-tenants.ts | 4 ++-- .../mcp-server/src/tools/tenants/retrieve-tenants.ts | 4 ++-- packages/mcp-server/src/tools/tenants/update-tenants.ts | 4 ++-- .../tools/webhook/endpoints/create-webhook-endpoints.ts | 4 ++-- .../tools/webhook/endpoints/delete-webhook-endpoints.ts | 9 +-------- .../tools/webhook/endpoints/list-webhook-endpoints.ts | 4 ++-- .../webhook/endpoints/retrieve-webhook-endpoints.ts | 4 ++-- .../tools/webhook/endpoints/update-webhook-endpoints.ts | 4 ++-- 22 files changed, 40 insertions(+), 66 deletions(-) diff --git a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts index ecbdaebf..535ea80d 100644 --- a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts @@ -66,8 +66,8 @@ export const tool: Tool = { }; export const handler = async (client: Beagle, args: Record | undefined) => { - const body = args as any; - return asTextContentResult(await maybeFilter(args, await client.enrollments.create(body))); + const { jq_filter, ...body } = args as any; + return asTextContentResult(await maybeFilter(jq_filter, await client.enrollments.create(body))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts b/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts index 1800dd79..af16ae8d 100644 --- a/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts @@ -17,19 +17,13 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'lapse_enrollments', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlapses a specific enrollment for a tenant, note that if a tenant has multiple enrollments (e.g., SDR and TLL), each must be lapsed individually\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {}\n}\n```", + 'lapses a specific enrollment for a tenant, note that if a tenant has multiple enrollments (e.g., SDR and TLL), each must be lapsed individually', inputSchema: { type: 'object', properties: { id: { type: 'number', }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, }, required: ['id'], }, diff --git a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts index 0f5a8e28..607f372f 100644 --- a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts @@ -48,9 +48,9 @@ export const tool: Tool = { }; export const handler = async (client: Beagle, args: Record | undefined) => { - const body = args as any; + const { jq_filter, ...body } = args as any; const response = await client.enrollments.list(body).asResponse(); - return asTextContentResult(await maybeFilter(args, await response.json())); + return asTextContentResult(await maybeFilter(jq_filter, await response.json())); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts index e67f1d09..0a2e5063 100644 --- a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts @@ -40,8 +40,8 @@ export const tool: Tool = { }; export const handler = async (client: Beagle, args: Record | undefined) => { - const { id, ...body } = args as any; - return asTextContentResult(await maybeFilter(args, await client.enrollments.retrieve(id))); + const { id, jq_filter, ...body } = args as any; + return asTextContentResult(await maybeFilter(jq_filter, await client.enrollments.retrieve(id))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts index c7b3b885..393dd079 100644 --- a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts +++ b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts @@ -48,8 +48,8 @@ export const tool: Tool = { }; export const handler = async (client: Beagle, args: Record | undefined) => { - const body = args as any; - return asTextContentResult(await maybeFilter(args, await client.insuranceVerification.verify(body))); + const { jq_filter, ...body } = args as any; + return asTextContentResult(await maybeFilter(jq_filter, await client.insuranceVerification.verify(body))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/plans/list-plans.ts b/packages/mcp-server/src/tools/plans/list-plans.ts index ddd4c25f..ed732fa5 100644 --- a/packages/mcp-server/src/tools/plans/list-plans.ts +++ b/packages/mcp-server/src/tools/plans/list-plans.ts @@ -37,7 +37,8 @@ export const tool: Tool = { }; export const handler = async (client: Beagle, args: Record | undefined) => { - return asTextContentResult(await maybeFilter(args, await client.plans.list())); + const { jq_filter } = args as any; + return asTextContentResult(await maybeFilter(jq_filter, await client.plans.list())); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/plans/retrieve-plans.ts b/packages/mcp-server/src/tools/plans/retrieve-plans.ts index 9bc04228..2a1743de 100644 --- a/packages/mcp-server/src/tools/plans/retrieve-plans.ts +++ b/packages/mcp-server/src/tools/plans/retrieve-plans.ts @@ -40,8 +40,8 @@ export const tool: Tool = { }; export const handler = async (client: Beagle, args: Record | undefined) => { - const { code, ...body } = args as any; - return asTextContentResult(await maybeFilter(args, await client.plans.retrieve(code))); + const { code, jq_filter, ...body } = args as any; + return asTextContentResult(await maybeFilter(jq_filter, await client.plans.retrieve(code))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts index 2ac1c5d8..b1153f27 100644 --- a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts @@ -108,8 +108,8 @@ export const tool: Tool = { }; export const handler = async (client: Beagle, args: Record | undefined) => { - const body = args as any; - return asTextContentResult(await maybeFilter(args, await client.propertyManagers.create(body))); + const { jq_filter, ...body } = args as any; + return asTextContentResult(await maybeFilter(jq_filter, await client.propertyManagers.create(body))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts b/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts index 9cdab9c5..b6bceea5 100644 --- a/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts @@ -16,20 +16,13 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'delete_property_managers', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ndelete a property manager by id.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {}\n}\n```", + description: 'delete a property manager by id.', inputSchema: { type: 'object', properties: { id: { type: 'number', }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, }, required: ['id'], }, diff --git a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts index 2055d935..4a6d2cf4 100644 --- a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts @@ -45,9 +45,9 @@ export const tool: Tool = { }; export const handler = async (client: Beagle, args: Record | undefined) => { - const body = args as any; + const { jq_filter, ...body } = args as any; const response = await client.propertyManagers.list(body).asResponse(); - return asTextContentResult(await maybeFilter(args, await response.json())); + return asTextContentResult(await maybeFilter(jq_filter, await response.json())); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts index eacbe04f..d41ee401 100644 --- a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts @@ -40,8 +40,8 @@ export const tool: Tool = { }; export const handler = async (client: Beagle, args: Record | undefined) => { - const { id, ...body } = args as any; - return asTextContentResult(await maybeFilter(args, await client.propertyManagers.retrieve(id))); + const { id, jq_filter, ...body } = args as any; + return asTextContentResult(await maybeFilter(jq_filter, await client.propertyManagers.retrieve(id))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts index a8d8f65e..7a21218e 100644 --- a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts @@ -111,8 +111,8 @@ export const tool: Tool = { }; export const handler = async (client: Beagle, args: Record | undefined) => { - const { id, ...body } = args as any; - return asTextContentResult(await maybeFilter(args, await client.propertyManagers.update(id, body))); + const { id, jq_filter, ...body } = args as any; + return asTextContentResult(await maybeFilter(jq_filter, await client.propertyManagers.update(id, body))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/tenants/create-tenants.ts b/packages/mcp-server/src/tools/tenants/create-tenants.ts index bd694e43..d318049b 100644 --- a/packages/mcp-server/src/tools/tenants/create-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/create-tenants.ts @@ -93,8 +93,8 @@ export const tool: Tool = { }; export const handler = async (client: Beagle, args: Record | undefined) => { - const body = args as any; - return asTextContentResult(await maybeFilter(args, await client.tenants.create(body))); + const { jq_filter, ...body } = args as any; + return asTextContentResult(await maybeFilter(jq_filter, await client.tenants.create(body))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/tenants/delete-tenants.ts b/packages/mcp-server/src/tools/tenants/delete-tenants.ts index 0006c304..3f64f3f3 100644 --- a/packages/mcp-server/src/tools/tenants/delete-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/delete-tenants.ts @@ -16,20 +16,13 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'delete_tenants', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ndelete an existing tenant by their id.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {}\n}\n```", + description: 'delete an existing tenant by their id.', inputSchema: { type: 'object', properties: { id: { type: 'number', }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, }, required: ['id'], }, diff --git a/packages/mcp-server/src/tools/tenants/list-tenants.ts b/packages/mcp-server/src/tools/tenants/list-tenants.ts index 54c1678f..1c67a70f 100644 --- a/packages/mcp-server/src/tools/tenants/list-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/list-tenants.ts @@ -48,9 +48,9 @@ export const tool: Tool = { }; export const handler = async (client: Beagle, args: Record | undefined) => { - const body = args as any; + const { jq_filter, ...body } = args as any; const response = await client.tenants.list(body).asResponse(); - return asTextContentResult(await maybeFilter(args, await response.json())); + return asTextContentResult(await maybeFilter(jq_filter, await response.json())); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts b/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts index 7ec0f60b..bc66fd93 100644 --- a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts @@ -40,8 +40,8 @@ export const tool: Tool = { }; export const handler = async (client: Beagle, args: Record | undefined) => { - const { id, ...body } = args as any; - return asTextContentResult(await maybeFilter(args, await client.tenants.retrieve(id))); + const { id, jq_filter, ...body } = args as any; + return asTextContentResult(await maybeFilter(jq_filter, await client.tenants.retrieve(id))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/tenants/update-tenants.ts b/packages/mcp-server/src/tools/tenants/update-tenants.ts index 84f18bc7..9f8a3363 100644 --- a/packages/mcp-server/src/tools/tenants/update-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/update-tenants.ts @@ -93,8 +93,8 @@ export const tool: Tool = { }; export const handler = async (client: Beagle, args: Record | undefined) => { - const { id, ...body } = args as any; - return asTextContentResult(await maybeFilter(args, await client.tenants.update(id, body))); + const { id, jq_filter, ...body } = args as any; + return asTextContentResult(await maybeFilter(jq_filter, await client.tenants.update(id, body))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts index 57b2443e..8563861f 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts @@ -44,8 +44,8 @@ export const tool: Tool = { }; export const handler = async (client: Beagle, args: Record | undefined) => { - const body = args as any; - return asTextContentResult(await maybeFilter(args, await client.webhook.endpoints.create(body))); + const { jq_filter, ...body } = args as any; + return asTextContentResult(await maybeFilter(jq_filter, await client.webhook.endpoints.create(body))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts index f7b2a9f6..17f35b27 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts @@ -16,20 +16,13 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'delete_webhook_endpoints', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ndelete an existing webhook endpoint by its id.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {}\n}\n```", + description: 'delete an existing webhook endpoint by its id.', inputSchema: { type: 'object', properties: { id: { type: 'number', }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, }, required: ['id'], }, diff --git a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts index 919bd059..16dce57a 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts @@ -45,9 +45,9 @@ export const tool: Tool = { }; export const handler = async (client: Beagle, args: Record | undefined) => { - const body = args as any; + const { jq_filter, ...body } = args as any; const response = await client.webhook.endpoints.list(body).asResponse(); - return asTextContentResult(await maybeFilter(args, await response.json())); + return asTextContentResult(await maybeFilter(jq_filter, await response.json())); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts index 405589e6..4f15de28 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts @@ -40,8 +40,8 @@ export const tool: Tool = { }; export const handler = async (client: Beagle, args: Record | undefined) => { - const { id, ...body } = args as any; - return asTextContentResult(await maybeFilter(args, await client.webhook.endpoints.retrieve(id))); + const { id, jq_filter, ...body } = args as any; + return asTextContentResult(await maybeFilter(jq_filter, await client.webhook.endpoints.retrieve(id))); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts index cbc0c326..9fca496a 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts @@ -47,8 +47,8 @@ export const tool: Tool = { }; export const handler = async (client: Beagle, args: Record | undefined) => { - const { id, ...body } = args as any; - return asTextContentResult(await maybeFilter(args, await client.webhook.endpoints.update(id, body))); + const { id, jq_filter, ...body } = args as any; + return asTextContentResult(await maybeFilter(jq_filter, await client.webhook.endpoints.update(id, body))); }; export default { metadata, tool, handler }; From 845ad086e76de9a3e4e5bd5cdca12771c51c02f6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 2 Aug 2025 05:54:50 +0000 Subject: [PATCH 017/138] feat(mcp): add logging when environment variable is set --- packages/mcp-server/src/server.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 1f43c62a..d4b79fff 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -28,7 +28,7 @@ export const server = new McpServer( name: 'corgi_tech_beagle_api', version: '0.0.1-alpha.0', }, - { capabilities: { tools: {} } }, + { capabilities: { tools: {}, logging: {} } }, ); /** @@ -61,11 +61,28 @@ export function init(params: { const endpointMap = Object.fromEntries(providedEndpoints.map((endpoint) => [endpoint.tool.name, endpoint])); + const logAtLevel = + (level: 'debug' | 'info' | 'warning' | 'error') => + (message: string, ...rest: unknown[]) => { + console.error(message, ...rest); + void server.sendLoggingMessage({ + level, + data: { message, rest }, + }); + }; + const logger = { + debug: logAtLevel('debug'), + info: logAtLevel('info'), + warn: logAtLevel('warning'), + error: logAtLevel('error'), + }; + const client = params.client || new Beagle({ environment: (readEnv('BEAGLE_ENVIRONMENT') || undefined) as any, defaultHeaders: { 'X-Stainless-MCP': 'true' }, + logger: logger, }); server.setRequestHandler(ListToolsRequestSchema, async () => { From 08c8116423ba4e0fe4f8f73c64de5ac45ea0aea2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 5 Aug 2025 07:44:50 +0000 Subject: [PATCH 018/138] feat(mcp): remote server with passthru auth --- packages/mcp-server/package.json | 2 + packages/mcp-server/src/headers.ts | 11 ++++ packages/mcp-server/src/http.ts | 85 ++++++++++++++++++++++++++++++ packages/mcp-server/src/index.ts | 26 +++++---- packages/mcp-server/src/options.ts | 16 ++++++ packages/mcp-server/src/server.ts | 19 ++++--- packages/mcp-server/src/stdio.ts | 14 +++++ 7 files changed, 154 insertions(+), 19 deletions(-) create mode 100644 packages/mcp-server/src/headers.ts create mode 100644 packages/mcp-server/src/http.ts create mode 100644 packages/mcp-server/src/stdio.ts diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 15114192..aa94a73d 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -29,6 +29,7 @@ "dependencies": { "@corgi-tech/beagle": "file:../../dist/", "@modelcontextprotocol/sdk": "^1.11.5", + "express": "^5.1.0", "jq-web": "https://github.com/stainless-api/jq-web/releases/download/v0.8.2/jq-web.tar.gz", "yargs": "^17.7.2", "@cloudflare/cabidela": "^0.2.4", @@ -40,6 +41,7 @@ }, "devDependencies": { "@types/jest": "^29.4.0", + "@types/express": "^5.0.3", "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", "eslint": "^8.49.0", diff --git a/packages/mcp-server/src/headers.ts b/packages/mcp-server/src/headers.ts new file mode 100644 index 00000000..f7a45d90 --- /dev/null +++ b/packages/mcp-server/src/headers.ts @@ -0,0 +1,11 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { type ClientOptions } from '@corgi-tech/beagle/client'; + +import { IncomingMessage } from 'node:http'; + +export const parseAuthHeaders = (req: IncomingMessage): Partial => { + const apiKey = + req.headers['x-api-key'] instanceof Array ? req.headers['x-api-key'][0] : req.headers['x-api-key']; + return { apiKey }; +}; diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts new file mode 100644 index 00000000..be3864c1 --- /dev/null +++ b/packages/mcp-server/src/http.ts @@ -0,0 +1,85 @@ +import { McpServer } from '@modelcontextprotocol/sdk/server/mcp'; +import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; + +import express from 'express'; +import { McpOptions } from './options'; +import { initMcpServer, newMcpServer } from './server'; +import { parseAuthHeaders } from './headers'; +import { Endpoint } from './tools'; + +const newServer = (mcpOptions: McpOptions, req: express.Request, res: express.Response): McpServer | null => { + const server = newMcpServer(); + try { + const authOptions = parseAuthHeaders(req); + initMcpServer({ + server: server, + clientOptions: { + ...authOptions, + defaultHeaders: { + 'X-Stainless-MCP': 'true', + }, + }, + mcpOptions, + }); + } catch { + res.status(401).json({ + jsonrpc: '2.0', + error: { + code: -32000, + message: 'Unauthorized', + }, + }); + return null; + } + + return server; +}; + +const post = (defaultOptions: McpOptions) => async (req: express.Request, res: express.Response) => { + const server = newServer(defaultOptions, req, res); + // If we return null, we already set the authorization error. + if (server === null) return; + const transport = new StreamableHTTPServerTransport({ + // Stateless server + sessionIdGenerator: undefined, + }); + await server.connect(transport); + await transport.handleRequest(req, res, req.body); +}; + +const get = async (req: express.Request, res: express.Response) => { + res.status(405).json({ + jsonrpc: '2.0', + error: { + code: -32000, + message: 'Method not supported', + }, + }); +}; + +const del = async (req: express.Request, res: express.Response) => { + res.status(405).json({ + jsonrpc: '2.0', + error: { + code: -32000, + message: 'Method not supported', + }, + }); +}; + +export const launchStreamableHTTPServer = async ( + options: McpOptions, + endpoints: Endpoint[], + port: number | undefined, +) => { + const app = express(); + app.use(express.json()); + + app.get('/', get); + app.post('/', post(options)); + app.delete('/', del); + + console.error(`MCP Server running on streamable HTTP on port ${port}`); + + app.listen(port); +}; diff --git a/packages/mcp-server/src/index.ts b/packages/mcp-server/src/index.ts index 06213572..7a4f1380 100644 --- a/packages/mcp-server/src/index.ts +++ b/packages/mcp-server/src/index.ts @@ -1,9 +1,10 @@ #!/usr/bin/env node -import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; -import { init, selectTools, server } from './server'; +import { selectTools } from './server'; import { Endpoint, endpoints } from './tools'; import { McpOptions, parseOptions } from './options'; +import { launchStdioServer } from './stdio'; +import { launchStreamableHTTPServer } from './http'; async function main() { const options = parseOptionsOrError(); @@ -13,18 +14,21 @@ async function main() { return; } - const includedTools = selectToolsOrError(endpoints, options); + const selectedTools = selectToolsOrError(endpoints, options); console.error( - `MCP Server starting with ${includedTools.length} tools:`, - includedTools.map((e) => e.tool.name), + `MCP Server starting with ${selectedTools.length} tools:`, + selectedTools.map((e) => e.tool.name), ); - init({ server, endpoints: includedTools }); - - const transport = new StdioServerTransport(); - await server.connect(transport); - console.error('MCP Server running on stdio'); + switch (options.transport) { + case 'stdio': + await launchStdioServer(options, selectedTools); + break; + case 'http': + await launchStreamableHTTPServer(options, selectedTools, options.port); + break; + } } if (require.main === module) { @@ -43,7 +47,7 @@ function parseOptionsOrError() { } } -function selectToolsOrError(endpoints: Endpoint[], options: McpOptions) { +function selectToolsOrError(endpoints: Endpoint[], options: McpOptions): Endpoint[] { try { const includedTools = selectTools(endpoints, options); if (includedTools.length === 0) { diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index c0751018..daf58380 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -5,6 +5,8 @@ import { ClientCapabilities, knownClients, ClientType } from './compat'; export type CLIOptions = McpOptions & { list: boolean; + transport: 'stdio' | 'http'; + port: number | undefined; }; export type McpOptions = { @@ -129,6 +131,16 @@ export function parseOptions(): CLIOptions { type: 'boolean', description: 'Print detailed explanation of client capabilities and exit', }) + .option('transport', { + type: 'string', + choices: ['stdio', 'http'], + default: 'stdio', + description: 'What transport to use; stdio for local servers or http for remote servers', + }) + .option('port', { + type: 'number', + description: 'Port to serve on if using http transport', + }) .help(); for (const [command, desc] of examples()) { @@ -238,6 +250,8 @@ export function parseOptions(): CLIOptions { const includeAllTools = explicitTools ? argv.tools?.includes('all') && !argv.noTools?.includes('all') : undefined; + const transport = argv.transport as 'stdio' | 'http'; + const client = argv.client as ClientType; return { client: client && knownClients[client] ? client : undefined, @@ -246,6 +260,8 @@ export function parseOptions(): CLIOptions { filters, capabilities: clientCapabilities, list: argv.list || false, + transport, + port: argv.port, }; } diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index d4b79fff..730d892d 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -22,14 +22,17 @@ export { Filter } from './tools'; export { ClientOptions } from '@corgi-tech/beagle'; export { endpoints } from './tools'; +export const newMcpServer = () => + new McpServer( + { + name: 'corgi_tech_beagle_api', + version: '0.0.1-alpha.0', + }, + { capabilities: { tools: {}, logging: {} } }, + ); + // Create server instance -export const server = new McpServer( - { - name: 'corgi_tech_beagle_api', - version: '0.0.1-alpha.0', - }, - { capabilities: { tools: {}, logging: {} } }, -); +export const server = newMcpServer(); /** * Initializes the provided MCP Server with the given tools and handlers. @@ -105,7 +108,7 @@ export function init(params: { /** * Selects the tools to include in the MCP Server based on the provided options. */ -export function selectTools(endpoints: Endpoint[], options: McpOptions) { +export function selectTools(endpoints: Endpoint[], options: McpOptions): Endpoint[] { const filteredEndpoints = query(options.filters, endpoints); let includedTools = filteredEndpoints; diff --git a/packages/mcp-server/src/stdio.ts b/packages/mcp-server/src/stdio.ts new file mode 100644 index 00000000..b2691635 --- /dev/null +++ b/packages/mcp-server/src/stdio.ts @@ -0,0 +1,14 @@ +import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; +import { init, newMcpServer } from './server'; +import { Endpoint } from './tools'; +import { McpOptions } from './options'; + +export const launchStdioServer = async (options: McpOptions, endpoints: Endpoint[]) => { + const server = newMcpServer(); + + init({ server, endpoints }); + + const transport = new StdioServerTransport(); + await server.connect(transport); + console.error('MCP Server running on stdio'); +}; From b5d9c06694a66d1c3785238ee392a9576b7dbcf8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 7 Aug 2025 04:16:34 +0000 Subject: [PATCH 019/138] chore(internal): move publish config --- bin/publish-npm | 2 +- package.json | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/bin/publish-npm b/bin/publish-npm index fa2243d2..45e8aa80 100644 --- a/bin/publish-npm +++ b/bin/publish-npm @@ -58,4 +58,4 @@ else fi # Publish with the appropriate tag -yarn publish --access public --tag "$TAG" +yarn publish --tag "$TAG" diff --git a/package.json b/package.json index 818db4b3..a40f6dcb 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,9 @@ "**/*" ], "private": false, + "publishConfig": { + "access": "public" + }, "scripts": { "test": "./scripts/test", "build": "./scripts/build", From 5667ecd222a0c35e996521a08e995d18ce0d5be3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 7 Aug 2025 04:19:05 +0000 Subject: [PATCH 020/138] chore(mcp): refactor streamable http transport --- packages/mcp-server/src/http.ts | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index be3864c1..d64f723d 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -1,3 +1,5 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + import { McpServer } from '@modelcontextprotocol/sdk/server/mcp'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; @@ -67,11 +69,7 @@ const del = async (req: express.Request, res: express.Response) => { }); }; -export const launchStreamableHTTPServer = async ( - options: McpOptions, - endpoints: Endpoint[], - port: number | undefined, -) => { +export const streamableHTTPApp = (options: McpOptions) => { const app = express(); app.use(express.json()); @@ -79,7 +77,23 @@ export const launchStreamableHTTPServer = async ( app.post('/', post(options)); app.delete('/', del); - console.error(`MCP Server running on streamable HTTP on port ${port}`); + return app; +}; + +export const launchStreamableHTTPServer = async ( + options: McpOptions, + endpoints: Endpoint[], + port: number | undefined, +) => { + const app = streamableHTTPApp(options); + const server = app.listen(port); + const address = server.address(); - app.listen(port); + if (typeof address === 'string') { + console.error(`MCP Server running on streamable HTTP at ${address}`); + } else if (address !== null) { + console.error(`MCP Server running on streamable HTTP on port ${address.port}`); + } else { + console.error(`MCP Server running on streamable HTTP on port ${port}`); + } }; From 9b0fb4c376c1d5909bb956dca146532574744d7d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 7 Aug 2025 04:21:23 +0000 Subject: [PATCH 021/138] feat(mcp): add unix socket option for remote MCP --- packages/mcp-server/src/http.ts | 2 +- packages/mcp-server/src/index.ts | 2 +- packages/mcp-server/src/options.ts | 6 ++++++ packages/mcp-server/src/server.ts | 1 - 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index d64f723d..900e1319 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -83,7 +83,7 @@ export const streamableHTTPApp = (options: McpOptions) => { export const launchStreamableHTTPServer = async ( options: McpOptions, endpoints: Endpoint[], - port: number | undefined, + port: number | string | undefined, ) => { const app = streamableHTTPApp(options); const server = app.listen(port); diff --git a/packages/mcp-server/src/index.ts b/packages/mcp-server/src/index.ts index 7a4f1380..4c71a3bc 100644 --- a/packages/mcp-server/src/index.ts +++ b/packages/mcp-server/src/index.ts @@ -26,7 +26,7 @@ async function main() { await launchStdioServer(options, selectedTools); break; case 'http': - await launchStreamableHTTPServer(options, selectedTools, options.port); + await launchStreamableHTTPServer(options, selectedTools, options.port ?? options.socket); break; } } diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index daf58380..c290ca50 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -7,6 +7,7 @@ export type CLIOptions = McpOptions & { list: boolean; transport: 'stdio' | 'http'; port: number | undefined; + socket: string | undefined; }; export type McpOptions = { @@ -141,6 +142,10 @@ export function parseOptions(): CLIOptions { type: 'number', description: 'Port to serve on if using http transport', }) + .option('socket', { + type: 'string', + description: 'Unix socket to serve on if using http transport', + }) .help(); for (const [command, desc] of examples()) { @@ -262,6 +267,7 @@ export function parseOptions(): CLIOptions { list: argv.list || false, transport, port: argv.port, + socket: argv.socket, }; } diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 730d892d..ff532b96 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -67,7 +67,6 @@ export function init(params: { const logAtLevel = (level: 'debug' | 'info' | 'warning' | 'error') => (message: string, ...rest: unknown[]) => { - console.error(message, ...rest); void server.sendLoggingMessage({ level, data: { message, rest }, From 8010fd881bd4714255779795cf55a4f04fb6f71d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 9 Aug 2025 05:34:32 +0000 Subject: [PATCH 022/138] chore: update @stainless-api/prism-cli to v5.15.0 --- scripts/mock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/mock b/scripts/mock index d2814ae6..0b28f6ea 100755 --- a/scripts/mock +++ b/scripts/mock @@ -21,7 +21,7 @@ echo "==> Starting mock server with URL ${URL}" # Run prism mock on the given spec if [ "$1" == "--daemon" ]; then - npm exec --package=@stainless-api/prism-cli@5.8.5 -- prism mock "$URL" &> .prism.log & + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & # Wait for server to come online echo -n "Waiting for server" @@ -37,5 +37,5 @@ if [ "$1" == "--daemon" ]; then echo else - npm exec --package=@stainless-api/prism-cli@5.8.5 -- prism mock "$URL" + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" fi From 23b9927106007dbe0f20607802049ba138b87df0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 9 Aug 2025 05:37:44 +0000 Subject: [PATCH 023/138] chore(internal): update comment in script --- scripts/test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test b/scripts/test index 2049e31b..7bce0516 100755 --- a/scripts/test +++ b/scripts/test @@ -43,7 +43,7 @@ elif ! prism_is_running ; then echo -e "To run the server, pass in the path or url of your OpenAPI" echo -e "spec to the prism command:" echo - echo -e " \$ ${YELLOW}npm exec --package=@stoplight/prism-cli@~5.3.2 -- prism mock path/to/your.openapi.yml${NC}" + echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}" echo exit 1 From 26017f0bd142599771f2e63665bf317131db31bb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 02:19:57 +0000 Subject: [PATCH 024/138] chore(internal): codegen related update --- packages/mcp-server/package.json | 2 +- packages/mcp-server/src/filtering.ts | 3 +-- tests/api-resources/enrollments.test.ts | 12 ++++++------ .../api-resources/insurance-verification.test.ts | 4 ++-- tests/api-resources/plans.test.ts | 4 ++-- tests/api-resources/property-managers.test.ts | 14 +++++++------- tests/api-resources/tenants.test.ts | 14 +++++++------- tests/api-resources/webhook/endpoints.test.ts | 16 ++++++++-------- 8 files changed, 34 insertions(+), 35 deletions(-) diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index aa94a73d..67490eb0 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -30,7 +30,7 @@ "@corgi-tech/beagle": "file:../../dist/", "@modelcontextprotocol/sdk": "^1.11.5", "express": "^5.1.0", - "jq-web": "https://github.com/stainless-api/jq-web/releases/download/v0.8.2/jq-web.tar.gz", + "jq-web": "https://github.com/stainless-api/jq-web/releases/download/v0.8.6/jq-web.tar.gz", "yargs": "^17.7.2", "@cloudflare/cabidela": "^0.2.4", "zod": "^3.25.20", diff --git a/packages/mcp-server/src/filtering.ts b/packages/mcp-server/src/filtering.ts index 87eab2de..1aa9a40c 100644 --- a/packages/mcp-server/src/filtering.ts +++ b/packages/mcp-server/src/filtering.ts @@ -1,8 +1,7 @@ // @ts-nocheck import initJq from 'jq-web'; -export async function maybeFilter(args: Record | undefined, response: any): Promise { - const jqFilter = args?.['jq_filter']; +export async function maybeFilter(jqFilter: unknown | undefined, response: any): Promise { if (jqFilter && typeof jqFilter === 'string') { return await jq(response, jqFilter); } else { diff --git a/tests/api-resources/enrollments.test.ts b/tests/api-resources/enrollments.test.ts index c4a9b76f..68f133df 100644 --- a/tests/api-resources/enrollments.test.ts +++ b/tests/api-resources/enrollments.test.ts @@ -8,7 +8,7 @@ const client = new Beagle({ }); describe('resource enrollments', () => { - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.enrollments.create({ effectiveDate: 'effectiveDate', @@ -26,7 +26,7 @@ describe('resource enrollments', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('create: required and optional params', async () => { const response = await client.enrollments.create({ effectiveDate: 'effectiveDate', @@ -38,7 +38,7 @@ describe('resource enrollments', () => { }); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('retrieve', async () => { const responsePromise = client.enrollments.retrieve(42); const rawResponse = await responsePromise.asResponse(); @@ -50,7 +50,7 @@ describe('resource enrollments', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('list', async () => { const responsePromise = client.enrollments.list(); const rawResponse = await responsePromise.asResponse(); @@ -62,7 +62,7 @@ describe('resource enrollments', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('list: request options and params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( @@ -73,7 +73,7 @@ describe('resource enrollments', () => { ).rejects.toThrow(Beagle.NotFoundError); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('lapse', async () => { const responsePromise = client.enrollments.lapse(42); const rawResponse = await responsePromise.asResponse(); diff --git a/tests/api-resources/insurance-verification.test.ts b/tests/api-resources/insurance-verification.test.ts index c266a0d9..49f7a2fd 100644 --- a/tests/api-resources/insurance-verification.test.ts +++ b/tests/api-resources/insurance-verification.test.ts @@ -8,7 +8,7 @@ const client = new Beagle({ }); describe('resource insuranceVerification', () => { - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('verify: only required params', async () => { const responsePromise = client.insuranceVerification.verify({ propertyManagerId: 0, @@ -24,7 +24,7 @@ describe('resource insuranceVerification', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('verify: required and optional params', async () => { const response = await client.insuranceVerification.verify({ propertyManagerId: 0, diff --git a/tests/api-resources/plans.test.ts b/tests/api-resources/plans.test.ts index d089594f..9216bf73 100644 --- a/tests/api-resources/plans.test.ts +++ b/tests/api-resources/plans.test.ts @@ -8,7 +8,7 @@ const client = new Beagle({ }); describe('resource plans', () => { - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('retrieve', async () => { const responsePromise = client.plans.retrieve('code'); const rawResponse = await responsePromise.asResponse(); @@ -20,7 +20,7 @@ describe('resource plans', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('list', async () => { const responsePromise = client.plans.list(); const rawResponse = await responsePromise.asResponse(); diff --git a/tests/api-resources/property-managers.test.ts b/tests/api-resources/property-managers.test.ts index f4d50fb9..0469e702 100644 --- a/tests/api-resources/property-managers.test.ts +++ b/tests/api-resources/property-managers.test.ts @@ -8,7 +8,7 @@ const client = new Beagle({ }); describe('resource propertyManagers', () => { - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.propertyManagers.create({ addresses: [{ city: 'city', state: 'xx', street1: 'street1', zip: '60513', kind: 'billing' }], @@ -24,7 +24,7 @@ describe('resource propertyManagers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('create: required and optional params', async () => { const response = await client.propertyManagers.create({ addresses: [ @@ -42,7 +42,7 @@ describe('resource propertyManagers', () => { }); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('retrieve', async () => { const responsePromise = client.propertyManagers.retrieve(42); const rawResponse = await responsePromise.asResponse(); @@ -54,7 +54,7 @@ describe('resource propertyManagers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('update', async () => { const responsePromise = client.propertyManagers.update(42, {}); const rawResponse = await responsePromise.asResponse(); @@ -66,7 +66,7 @@ describe('resource propertyManagers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('list', async () => { const responsePromise = client.propertyManagers.list(); const rawResponse = await responsePromise.asResponse(); @@ -78,7 +78,7 @@ describe('resource propertyManagers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('list: request options and params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( @@ -86,7 +86,7 @@ describe('resource propertyManagers', () => { ).rejects.toThrow(Beagle.NotFoundError); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('delete', async () => { const responsePromise = client.propertyManagers.delete(42); const rawResponse = await responsePromise.asResponse(); diff --git a/tests/api-resources/tenants.test.ts b/tests/api-resources/tenants.test.ts index 9d47ced4..7fed1449 100644 --- a/tests/api-resources/tenants.test.ts +++ b/tests/api-resources/tenants.test.ts @@ -8,7 +8,7 @@ const client = new Beagle({ }); describe('resource tenants', () => { - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.tenants.create({ address: { city: 'city', state: 'xx', street1: 'street1', zip: '60513' }, @@ -24,7 +24,7 @@ describe('resource tenants', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('create: required and optional params', async () => { const response = await client.tenants.create({ address: { city: 'city', state: 'xx', street1: 'street1', zip: '60513', street2: 'street2' }, @@ -33,7 +33,7 @@ describe('resource tenants', () => { }); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('retrieve', async () => { const responsePromise = client.tenants.retrieve(42); const rawResponse = await responsePromise.asResponse(); @@ -45,7 +45,7 @@ describe('resource tenants', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('update', async () => { const responsePromise = client.tenants.update(42, {}); const rawResponse = await responsePromise.asResponse(); @@ -57,7 +57,7 @@ describe('resource tenants', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('list', async () => { const responsePromise = client.tenants.list(); const rawResponse = await responsePromise.asResponse(); @@ -69,7 +69,7 @@ describe('resource tenants', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('list: request options and params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( @@ -77,7 +77,7 @@ describe('resource tenants', () => { ).rejects.toThrow(Beagle.NotFoundError); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('delete', async () => { const responsePromise = client.tenants.delete(42); const rawResponse = await responsePromise.asResponse(); diff --git a/tests/api-resources/webhook/endpoints.test.ts b/tests/api-resources/webhook/endpoints.test.ts index 9059bae9..eedc632b 100644 --- a/tests/api-resources/webhook/endpoints.test.ts +++ b/tests/api-resources/webhook/endpoints.test.ts @@ -8,7 +8,7 @@ const client = new Beagle({ }); describe('resource endpoints', () => { - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.webhook.endpoints.create({ secret: 'secret', url: 'https://example.com' }); const rawResponse = await responsePromise.asResponse(); @@ -20,7 +20,7 @@ describe('resource endpoints', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('create: required and optional params', async () => { const response = await client.webhook.endpoints.create({ secret: 'secret', @@ -29,7 +29,7 @@ describe('resource endpoints', () => { }); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('retrieve', async () => { const responsePromise = client.webhook.endpoints.retrieve(42); const rawResponse = await responsePromise.asResponse(); @@ -41,7 +41,7 @@ describe('resource endpoints', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('update: only required params', async () => { const responsePromise = client.webhook.endpoints.update(42, { secret: 'secret', @@ -56,7 +56,7 @@ describe('resource endpoints', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('update: required and optional params', async () => { const response = await client.webhook.endpoints.update(42, { secret: 'secret', @@ -65,7 +65,7 @@ describe('resource endpoints', () => { }); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('list', async () => { const responsePromise = client.webhook.endpoints.list(); const rawResponse = await responsePromise.asResponse(); @@ -77,7 +77,7 @@ describe('resource endpoints', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('list: request options and params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( @@ -85,7 +85,7 @@ describe('resource endpoints', () => { ).rejects.toThrow(Beagle.NotFoundError); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('delete', async () => { const responsePromise = client.webhook.endpoints.delete(42); const rawResponse = await responsePromise.asResponse(); From e8a08021d50b3988cd70f0580d4d42422f5b47ea Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 14 Aug 2025 04:57:05 +0000 Subject: [PATCH 025/138] chore(mcp): minor cleanup of types and package.json --- packages/mcp-server/package.json | 1 + packages/mcp-server/src/http.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 67490eb0..0ba9b0de 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -42,6 +42,7 @@ "devDependencies": { "@types/jest": "^29.4.0", "@types/express": "^5.0.3", + "@types/yargs": "^17.0.8", "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", "eslint": "^8.49.0", diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index 900e1319..e188c9ed 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -69,7 +69,7 @@ const del = async (req: express.Request, res: express.Response) => { }); }; -export const streamableHTTPApp = (options: McpOptions) => { +export const streamableHTTPApp = (options: McpOptions): express.Express => { const app = express(); app.use(express.json()); From 03fd93c9d0ca98f782ebc099daed25817249b434 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 03:38:05 +0000 Subject: [PATCH 026/138] chore(mcp): document remote server in README.md --- packages/mcp-server/README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/packages/mcp-server/README.md b/packages/mcp-server/README.md index 550d1e50..543ff01e 100644 --- a/packages/mcp-server/README.md +++ b/packages/mcp-server/README.md @@ -128,6 +128,30 @@ over time, you can manually enable or disable certain capabilities: --resource=cards,accounts --operation=read --tag=kyc --no-tool=create_cards ``` +## Running remotely + +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. + +Authorization can be provided via the following headers: +| Header | Equivalent client option | Security scheme | +| ----------- | ------------------------ | --------------- | +| `x-api-key` | `apiKey` | apiKey | + +A configuration JSON for this server might look like this: + +```json +{ + "mcpServers": { + "corgi_tech_beagle_api": { + "url": "http://localhost:3000", # or wherever the server is hosted + "headers": { + 'x-api-key': 'My API Key' + } + } + } +} +``` + ## Importing the tools and server individually ```js From f1f23d5d2ef771d8ee07eccef54fce0091923bf3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 16 Aug 2025 03:59:38 +0000 Subject: [PATCH 027/138] chore(deps): update dependency @types/node to v20.17.58 --- yarn.lock | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index 58c08d5f..fd164dcf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -938,11 +938,11 @@ undici-types "~5.26.4" "@types/node@^20.17.6": - version "20.17.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.6.tgz#6e4073230c180d3579e8c60141f99efdf5df0081" - integrity sha512-VEI7OdvK2wP7XHnsuXbAJnEpEkF6NjSN45QJlL4VGqZSXsnicpesdTWsg9RISeSdYd3yeRj/y3k5KGjUXYnFwQ== + version "20.19.11" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.11.tgz#728cab53092bd5f143beed7fbba7ba99de3c16c4" + integrity sha512-uug3FEEGv0r+jrecvUUpbY8lLisvIjg6AAic6a2bSP5OEOLeJsDSnvhCDov7ipFFMXS3orMpzlmi0ZcuGkBbow== dependencies: - undici-types "~6.19.2" + undici-types "~6.21.0" "@types/stack-utils@^2.0.0": version "2.0.3" @@ -3285,6 +3285,7 @@ ts-node@^10.5.0: "tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz": version "1.1.8" + uid f544b359b8f05e607771ffacc280e58201476b04 resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz#f544b359b8f05e607771ffacc280e58201476b04" dependencies: debug "^4.3.7" @@ -3353,10 +3354,10 @@ undici-types@~5.26.4: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== -undici-types@~6.19.2: - version "6.19.8" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" - integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== unicode-emoji-modifier-base@^1.0.0: version "1.0.0" From 5c2b02cc28ea854c4203099f5e1e0cdeb89c29fd Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 16 Aug 2025 04:01:37 +0000 Subject: [PATCH 028/138] chore(mcp): update README --- packages/mcp-server/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/mcp-server/README.md b/packages/mcp-server/README.md index 543ff01e..078f01e5 100644 --- a/packages/mcp-server/README.md +++ b/packages/mcp-server/README.md @@ -137,15 +137,15 @@ Authorization can be provided via the following headers: | ----------- | ------------------------ | --------------- | | `x-api-key` | `apiKey` | apiKey | -A configuration JSON for this server might look like this: +A configuration JSON for this server might look like this, assuming the server is hosted at `http://localhost:3000`: ```json { "mcpServers": { "corgi_tech_beagle_api": { - "url": "http://localhost:3000", # or wherever the server is hosted + "url": "http://localhost:3000", "headers": { - 'x-api-key': 'My API Key' + "x-api-key": "My API Key" } } } From 15c4306447ee4b4c5ca0e56d6ca29c21f5b6b81c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 16 Aug 2025 04:06:27 +0000 Subject: [PATCH 029/138] chore(internal): formatting change --- src/client.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/client.ts b/src/client.ts index 0e557325..ad8c0c28 100644 --- a/src/client.ts +++ b/src/client.ts @@ -808,12 +808,14 @@ export class Beagle { insuranceVerification: API.InsuranceVerification = new API.InsuranceVerification(this); webhook: API.Webhook = new API.Webhook(this); } + Beagle.Plans = Plans; Beagle.PropertyManagers = PropertyManagers; Beagle.Tenants = Tenants; Beagle.Enrollments = Enrollments; Beagle.InsuranceVerification = InsuranceVerification; Beagle.Webhook = Webhook; + export declare namespace Beagle { export type RequestOptions = Opts.RequestOptions; From 913561f27fbaa093f44c8b7a32c2b921d8bb621a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 19 Aug 2025 02:57:12 +0000 Subject: [PATCH 030/138] feat(mcp): parse query string as mcp client options in mcp server --- packages/mcp-server/README.md | 13 ++ packages/mcp-server/package.json | 8 +- packages/mcp-server/src/compat.ts | 4 +- packages/mcp-server/src/http.ts | 25 ++- packages/mcp-server/src/index.ts | 4 +- packages/mcp-server/src/options.ts | 121 ++++++++++- packages/mcp-server/tests/options.test.ts | 240 +++++++++++++++++++++- packages/mcp-server/yarn.lock | 116 +++++++++-- 8 files changed, 499 insertions(+), 32 deletions(-) diff --git a/packages/mcp-server/README.md b/packages/mcp-server/README.md index 078f01e5..663b6583 100644 --- a/packages/mcp-server/README.md +++ b/packages/mcp-server/README.md @@ -152,6 +152,19 @@ A configuration JSON for this server might look like this, assuming the server i } ``` +The command-line arguments for filtering tools and specifying clients can also be used as query parameters in the URL. +For example, to exclude specific tools while including others, use the URL: + +``` +http://localhost:3000?resource=cards&resource=accounts&no_tool=create_cards +``` + +Or, to configure for the Cursor client, with a custom max tool name length, use the URL: + +``` +http://localhost:3000?client=cursor&capability=tool-name-length%3D40 +``` + ## Importing the tools and server individually ```js diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 0ba9b0de..21b7f6d8 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -28,20 +28,22 @@ }, "dependencies": { "@corgi-tech/beagle": "file:../../dist/", + "@cloudflare/cabidela": "^0.2.4", "@modelcontextprotocol/sdk": "^1.11.5", "express": "^5.1.0", "jq-web": "https://github.com/stainless-api/jq-web/releases/download/v0.8.6/jq-web.tar.gz", + "qs": "^6.14.0", "yargs": "^17.7.2", - "@cloudflare/cabidela": "^0.2.4", "zod": "^3.25.20", - "zod-to-json-schema": "^3.24.5" + "zod-to-json-schema": "^3.24.5", + "zod-validation-error": "^4.0.1" }, "bin": { "mcp-server": "dist/index.js" }, "devDependencies": { - "@types/jest": "^29.4.0", "@types/express": "^5.0.3", + "@types/jest": "^29.4.0", "@types/yargs": "^17.0.8", "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", diff --git a/packages/mcp-server/src/compat.ts b/packages/mcp-server/src/compat.ts index 7afd77fd..1df7a7aa 100644 --- a/packages/mcp-server/src/compat.ts +++ b/packages/mcp-server/src/compat.ts @@ -1,4 +1,5 @@ import { Tool } from '@modelcontextprotocol/sdk/types.js'; +import { z } from 'zod'; import { Endpoint } from './tools'; export interface ClientCapabilities { @@ -19,7 +20,8 @@ export const defaultClientCapabilities: ClientCapabilities = { toolNameLength: undefined, }; -export type ClientType = 'openai-agents' | 'claude' | 'claude-code' | 'cursor'; +export const ClientType = z.enum(['openai-agents', 'claude', 'claude-code', 'cursor']); +export type ClientType = z.infer; // Client presets for compatibility // Note that these could change over time as models get better, so this is diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index e188c9ed..ca6d3d25 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -4,13 +4,33 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; import express from 'express'; -import { McpOptions } from './options'; +import { fromError } from 'zod-validation-error/v3'; +import { McpOptions, parseQueryOptions } from './options'; import { initMcpServer, newMcpServer } from './server'; import { parseAuthHeaders } from './headers'; import { Endpoint } from './tools'; -const newServer = (mcpOptions: McpOptions, req: express.Request, res: express.Response): McpServer | null => { +const newServer = ( + defaultMcpOptions: McpOptions, + req: express.Request, + res: express.Response, +): McpServer | null => { const server = newMcpServer(); + + let mcpOptions: McpOptions; + try { + mcpOptions = parseQueryOptions(defaultMcpOptions, req.query); + } catch (error) { + res.status(400).json({ + jsonrpc: '2.0', + error: { + code: -32000, + message: `Invalid request: ${fromError(error)}`, + }, + }); + return null; + } + try { const authOptions = parseAuthHeaders(req); initMcpServer({ @@ -71,6 +91,7 @@ const del = async (req: express.Request, res: express.Response) => { export const streamableHTTPApp = (options: McpOptions): express.Express => { const app = express(); + app.set('query parser', 'extended'); app.use(express.json()); app.get('/', get); diff --git a/packages/mcp-server/src/index.ts b/packages/mcp-server/src/index.ts index 4c71a3bc..05b2ba63 100644 --- a/packages/mcp-server/src/index.ts +++ b/packages/mcp-server/src/index.ts @@ -2,7 +2,7 @@ import { selectTools } from './server'; import { Endpoint, endpoints } from './tools'; -import { McpOptions, parseOptions } from './options'; +import { McpOptions, parseCLIOptions } from './options'; import { launchStdioServer } from './stdio'; import { launchStreamableHTTPServer } from './http'; @@ -40,7 +40,7 @@ if (require.main === module) { function parseOptionsOrError() { try { - return parseOptions(); + return parseCLIOptions(); } catch (error) { console.error('Error parsing options:', error); process.exit(1); diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index c290ca50..0768d931 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -1,5 +1,7 @@ +import qs from 'qs'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; +import z from 'zod'; import { endpoints, Filter } from './tools'; import { ClientCapabilities, knownClients, ClientType } from './compat'; @@ -47,7 +49,7 @@ function parseCapabilityValue(cap: string): { name: Capability; value?: number } return { name: cap as Capability }; } -export function parseOptions(): CLIOptions { +export function parseCLIOptions(): CLIOptions { const opts = yargs(hideBin(process.argv)) .option('tools', { type: 'string', @@ -271,6 +273,123 @@ export function parseOptions(): CLIOptions { }; } +const coerceArray = (zodType: T) => + z.preprocess( + (val) => + Array.isArray(val) ? val + : val ? [val] + : val, + z.array(zodType).optional(), + ); + +const QueryOptions = z.object({ + tools: coerceArray(z.enum(['dynamic', 'all'])).describe('Use dynamic tools or all tools'), + no_tools: coerceArray(z.enum(['dynamic', 'all'])).describe('Do not use dynamic tools or all tools'), + tool: coerceArray(z.string()).describe('Include tools matching the specified names'), + resource: coerceArray(z.string()).describe('Include tools matching the specified resources'), + operation: coerceArray(z.enum(['read', 'write'])).describe( + 'Include tools matching the specified operations', + ), + tag: coerceArray(z.string()).describe('Include tools with the specified tags'), + no_tool: coerceArray(z.string()).describe('Exclude tools matching the specified names'), + no_resource: coerceArray(z.string()).describe('Exclude tools matching the specified resources'), + no_operation: coerceArray(z.enum(['read', 'write'])).describe( + 'Exclude tools matching the specified operations', + ), + no_tag: coerceArray(z.string()).describe('Exclude tools with the specified tags'), + client: ClientType.optional().describe('Specify the MCP client being used'), + capability: coerceArray(z.string()).describe('Specify client capabilities'), + no_capability: coerceArray(z.enum(CAPABILITY_CHOICES)).describe('Unset client capabilities'), +}); + +export function parseQueryOptions(defaultOptions: McpOptions, query: unknown): McpOptions { + const queryObject = typeof query === 'string' ? qs.parse(query) : query; + const queryOptions = QueryOptions.parse(queryObject); + + const filters: Filter[] = [...defaultOptions.filters]; + + for (const resource of queryOptions.resource || []) { + filters.push({ type: 'resource', op: 'include', value: resource }); + } + for (const operation of queryOptions.operation || []) { + filters.push({ type: 'operation', op: 'include', value: operation }); + } + for (const tag of queryOptions.tag || []) { + filters.push({ type: 'tag', op: 'include', value: tag }); + } + for (const tool of queryOptions.tool || []) { + filters.push({ type: 'tool', op: 'include', value: tool }); + } + for (const resource of queryOptions.no_resource || []) { + filters.push({ type: 'resource', op: 'exclude', value: resource }); + } + for (const operation of queryOptions.no_operation || []) { + filters.push({ type: 'operation', op: 'exclude', value: operation }); + } + for (const tag of queryOptions.no_tag || []) { + filters.push({ type: 'tag', op: 'exclude', value: tag }); + } + for (const tool of queryOptions.no_tool || []) { + filters.push({ type: 'tool', op: 'exclude', value: tool }); + } + + // Parse client capabilities + const clientCapabilities: ClientCapabilities = { + topLevelUnions: true, + validJson: true, + refs: true, + unions: true, + formats: true, + toolNameLength: undefined, + ...defaultOptions.capabilities, + }; + + for (const cap of queryOptions.capability || []) { + const parsed = parseCapabilityValue(cap); + if (parsed.name === 'top-level-unions') { + clientCapabilities.topLevelUnions = true; + } else if (parsed.name === 'valid-json') { + clientCapabilities.validJson = true; + } else if (parsed.name === 'refs') { + clientCapabilities.refs = true; + } else if (parsed.name === 'unions') { + clientCapabilities.unions = true; + } else if (parsed.name === 'formats') { + clientCapabilities.formats = true; + } else if (parsed.name === 'tool-name-length') { + clientCapabilities.toolNameLength = parsed.value; + } + } + + for (const cap of queryOptions.no_capability || []) { + if (cap === 'top-level-unions') { + clientCapabilities.topLevelUnions = false; + } else if (cap === 'valid-json') { + clientCapabilities.validJson = false; + } else if (cap === 'refs') { + clientCapabilities.refs = false; + } else if (cap === 'unions') { + clientCapabilities.unions = false; + } else if (cap === 'formats') { + clientCapabilities.formats = false; + } else if (cap === 'tool-name-length') { + clientCapabilities.toolNameLength = undefined; + } + } + + return { + client: queryOptions.client ?? defaultOptions.client, + includeDynamicTools: + defaultOptions.includeDynamicTools ?? + (queryOptions.tools?.includes('dynamic') && !queryOptions.no_tools?.includes('dynamic')), + includeAllTools: + defaultOptions.includeAllTools ?? + (queryOptions.tools?.includes('all') && !queryOptions.no_tools?.includes('all')), + filters, + capabilities: clientCapabilities, + }; +} + function getCapabilitiesExplanation(): string { return ` Client Capabilities Explanation: diff --git a/packages/mcp-server/tests/options.test.ts b/packages/mcp-server/tests/options.test.ts index 264aca55..08ea1f18 100644 --- a/packages/mcp-server/tests/options.test.ts +++ b/packages/mcp-server/tests/options.test.ts @@ -1,4 +1,4 @@ -import { parseOptions } from '../src/options'; +import { parseCLIOptions, parseQueryOptions } from '../src/options'; import { Filter } from '../src/tools'; import { parseEmbeddedJSON } from '../src/compat'; @@ -11,7 +11,7 @@ const mockArgv = (args: string[]) => { }; }; -describe('parseOptions', () => { +describe('parseCLIOptions', () => { it('should parse basic filter options', () => { const cleanup = mockArgv([ '--tool=test-tool', @@ -20,7 +20,7 @@ describe('parseOptions', () => { '--tag=test-tag', ]); - const result = parseOptions(); + const result = parseCLIOptions(); expect(result.filters).toEqual([ { type: 'tag', op: 'include', value: 'test-tag' }, @@ -52,7 +52,7 @@ describe('parseOptions', () => { '--no-tag=exclude-tag', ]); - const result = parseOptions(); + const result = parseCLIOptions(); expect(result.filters).toEqual([ { type: 'tag', op: 'exclude', value: 'exclude-tag' }, @@ -76,7 +76,7 @@ describe('parseOptions', () => { it('should parse client presets', () => { const cleanup = mockArgv(['--client=openai-agents']); - const result = parseOptions(); + const result = parseCLIOptions(); expect(result.client).toEqual('openai-agents'); @@ -92,7 +92,7 @@ describe('parseOptions', () => { '--capability=tool-name-length=40', ]); - const result = parseOptions(); + const result = parseCLIOptions(); expect(result.capabilities).toEqual({ topLevelUnions: true, @@ -109,7 +109,7 @@ describe('parseOptions', () => { it('should handle list option', () => { const cleanup = mockArgv(['--list']); - const result = parseOptions(); + const result = parseCLIOptions(); expect(result.list).toBe(true); @@ -119,7 +119,7 @@ describe('parseOptions', () => { it('should handle multiple filters of the same type', () => { const cleanup = mockArgv(['--tool=tool1', '--tool=tool2', '--resource=res1', '--resource=res2']); - const result = parseOptions(); + const result = parseCLIOptions(); expect(result.filters).toEqual([ { type: 'resource', op: 'include', value: 'res1' }, @@ -138,7 +138,7 @@ describe('parseOptions', () => { '--capability=top-level-unions,valid-json,unions', ]); - const result = parseOptions(); + const result = parseCLIOptions(); expect(result.filters).toEqual([ { type: 'resource', op: 'include', value: 'res1' }, @@ -166,7 +166,7 @@ describe('parseOptions', () => { const originalError = console.error; console.error = jest.fn(); - expect(() => parseOptions()).toThrow(); + expect(() => parseCLIOptions()).toThrow(); console.error = originalError; cleanup(); @@ -179,13 +179,231 @@ describe('parseOptions', () => { const originalError = console.error; console.error = jest.fn(); - expect(() => parseOptions()).toThrow(); + expect(() => parseCLIOptions()).toThrow(); console.error = originalError; cleanup(); }); }); +describe('parseQueryOptions', () => { + const defaultOptions = { + client: undefined, + includeDynamicTools: undefined, + includeAllTools: undefined, + filters: [], + capabilities: { + topLevelUnions: true, + validJson: true, + refs: true, + unions: true, + formats: true, + toolNameLength: undefined, + }, + }; + + it('should parse basic filter options from query string', () => { + const query = 'tool=test-tool&resource=test-resource&operation=read&tag=test-tag'; + const result = parseQueryOptions(defaultOptions, query); + + expect(result.filters).toEqual([ + { type: 'resource', op: 'include', value: 'test-resource' }, + { type: 'operation', op: 'include', value: 'read' }, + { type: 'tag', op: 'include', value: 'test-tag' }, + { type: 'tool', op: 'include', value: 'test-tool' }, + ]); + + expect(result.capabilities).toEqual({ + topLevelUnions: true, + validJson: true, + refs: true, + unions: true, + formats: true, + toolNameLength: undefined, + }); + }); + + it('should parse exclusion filters from query string', () => { + const query = 'no_tool=exclude-tool&no_resource=exclude-resource&no_operation=write&no_tag=exclude-tag'; + const result = parseQueryOptions(defaultOptions, query); + + expect(result.filters).toEqual([ + { type: 'resource', op: 'exclude', value: 'exclude-resource' }, + { type: 'operation', op: 'exclude', value: 'write' }, + { type: 'tag', op: 'exclude', value: 'exclude-tag' }, + { type: 'tool', op: 'exclude', value: 'exclude-tool' }, + ]); + }); + + it('should parse client option from query string', () => { + const query = 'client=openai-agents'; + const result = parseQueryOptions(defaultOptions, query); + + expect(result.client).toBe('openai-agents'); + }); + + it('should parse client capabilities from query string', () => { + const query = 'capability=top-level-unions&capability=valid-json&capability=tool-name-length%3D40'; + const result = parseQueryOptions(defaultOptions, query); + + expect(result.capabilities).toEqual({ + topLevelUnions: true, + validJson: true, + refs: true, + unions: true, + formats: true, + toolNameLength: 40, + }); + }); + + it('should parse no-capability options from query string', () => { + const query = 'no_capability=top-level-unions&no_capability=refs&no_capability=formats'; + const result = parseQueryOptions(defaultOptions, query); + + expect(result.capabilities).toEqual({ + topLevelUnions: false, + validJson: true, + refs: false, + unions: true, + formats: false, + toolNameLength: undefined, + }); + }); + + it('should parse tools options from query string', () => { + const query = 'tools=dynamic&tools=all'; + const result = parseQueryOptions(defaultOptions, query); + + expect(result.includeDynamicTools).toBe(true); + expect(result.includeAllTools).toBe(true); + }); + + it('should parse no-tools options from query string', () => { + const query = 'tools=dynamic&tools=all&no_tools=dynamic'; + const result = parseQueryOptions(defaultOptions, query); + + expect(result.includeDynamicTools).toBe(false); + expect(result.includeAllTools).toBe(true); + }); + + it('should handle array values in query string', () => { + const query = 'tool[]=tool1&tool[]=tool2&resource[]=res1&resource[]=res2'; + const result = parseQueryOptions(defaultOptions, query); + + expect(result.filters).toEqual([ + { type: 'resource', op: 'include', value: 'res1' }, + { type: 'resource', op: 'include', value: 'res2' }, + { type: 'tool', op: 'include', value: 'tool1' }, + { type: 'tool', op: 'include', value: 'tool2' }, + ]); + }); + + it('should merge with default options', () => { + const defaultWithFilters = { + ...defaultOptions, + filters: [{ type: 'tag' as const, op: 'include' as const, value: 'existing-tag' }], + client: 'cursor' as const, + includeDynamicTools: true, + }; + + const query = 'tool=new-tool&resource=new-resource'; + const result = parseQueryOptions(defaultWithFilters, query); + + expect(result.filters).toEqual([ + { type: 'tag', op: 'include', value: 'existing-tag' }, + { type: 'resource', op: 'include', value: 'new-resource' }, + { type: 'tool', op: 'include', value: 'new-tool' }, + ]); + + expect(result.client).toBe('cursor'); + expect(result.includeDynamicTools).toBe(true); + }); + + it('should override client from default options', () => { + const defaultWithClient = { + ...defaultOptions, + client: 'cursor' as const, + }; + + const query = 'client=openai-agents'; + const result = parseQueryOptions(defaultWithClient, query); + + expect(result.client).toBe('openai-agents'); + }); + + it('should merge capabilities with default options', () => { + const defaultWithCapabilities = { + ...defaultOptions, + capabilities: { + topLevelUnions: false, + validJson: false, + refs: true, + unions: true, + formats: true, + toolNameLength: 30, + }, + }; + + const query = 'capability=top-level-unions&no_capability=refs'; + const result = parseQueryOptions(defaultWithCapabilities, query); + + expect(result.capabilities).toEqual({ + topLevelUnions: true, + validJson: false, + refs: false, + unions: true, + formats: true, + toolNameLength: 30, + }); + }); + + it('should handle empty query string', () => { + const query = ''; + const result = parseQueryOptions(defaultOptions, query); + + expect(result).toEqual(defaultOptions); + }); + + it('should handle invalid query string gracefully', () => { + const query = 'invalid=value&operation=invalid-operation'; + + // Should throw due to Zod validation for invalid operation + expect(() => parseQueryOptions(defaultOptions, query)).toThrow(); + }); + + it('should preserve default undefined values when not specified', () => { + const defaultWithUndefined = { + ...defaultOptions, + client: undefined, + includeDynamicTools: undefined, + includeAllTools: undefined, + }; + + const query = 'tool=test-tool'; + const result = parseQueryOptions(defaultWithUndefined, query); + + expect(result.client).toBeUndefined(); + expect(result.includeDynamicTools).toBeFalsy(); + expect(result.includeAllTools).toBeFalsy(); + }); + + it('should handle complex query with mixed include and exclude filters', () => { + const query = + 'tool=include-tool&no_tool=exclude-tool&resource=include-res&no_resource=exclude-res&operation=read&tag=include-tag&no_tag=exclude-tag'; + const result = parseQueryOptions(defaultOptions, query); + + expect(result.filters).toEqual([ + { type: 'resource', op: 'include', value: 'include-res' }, + { type: 'operation', op: 'include', value: 'read' }, + { type: 'tag', op: 'include', value: 'include-tag' }, + { type: 'tool', op: 'include', value: 'include-tool' }, + { type: 'resource', op: 'exclude', value: 'exclude-res' }, + { type: 'tag', op: 'exclude', value: 'exclude-tag' }, + { type: 'tool', op: 'exclude', value: 'exclude-tool' }, + ]); + }); +}); + describe('parseEmbeddedJSON', () => { it('should not change non-string values', () => { const args = { diff --git a/packages/mcp-server/yarn.lock b/packages/mcp-server/yarn.lock index 9970ec32..707a2de8 100644 --- a/packages/mcp-server/yarn.lock +++ b/packages/mcp-server/yarn.lock @@ -584,15 +584,17 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@modelcontextprotocol/sdk@^1.6.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.11.1.tgz#c7f4a1432872ef10130f5d9b0072060c17a3946b" - integrity sha512-9LfmxKTb1v+vUS1/emSk1f5ePmTLkb9Le9AxOB5T0XM59EUumwcS45z05h7aiZx3GI0Bl7mjb3FMEglYj+acuQ== +"@modelcontextprotocol/sdk@^1.11.5": + version "1.17.3" + resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.17.3.tgz#cf92354220f0183d28179e96a9bf3a8f6d3211ae" + integrity sha512-JPwUKWSsbzx+DLFznf/QZ32Qa+ptfbUlHhRLrBQBAFu9iI1iYvizM4p+zhhRDceSsPutXp4z+R/HPVphlIiclg== dependencies: + ajv "^6.12.6" content-type "^1.0.5" cors "^2.8.5" - cross-spawn "^7.0.3" + cross-spawn "^7.0.5" eventsource "^3.0.2" + eventsource-parser "^3.0.0" express "^5.0.1" express-rate-limit "^7.5.0" pkce-challenge "^5.0.0" @@ -708,6 +710,40 @@ dependencies: "@babel/types" "^7.20.7" +"@types/body-parser@*": + version "1.19.6" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.6.tgz#1859bebb8fd7dac9918a45d54c1971ab8b5af474" + integrity sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/connect@*": + version "3.4.38" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" + integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== + dependencies: + "@types/node" "*" + +"@types/express-serve-static-core@^5.0.0": + version "5.0.7" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz#2fa94879c9d46b11a5df4c74ac75befd6b283de6" + integrity sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + "@types/send" "*" + +"@types/express@^5.0.3": + version "5.0.3" + resolved "https://registry.yarnpkg.com/@types/express/-/express-5.0.3.tgz#6c4bc6acddc2e2a587142e1d8be0bce20757e956" + integrity sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^5.0.0" + "@types/serve-static" "*" + "@types/graceful-fs@^4.1.3": version "4.1.9" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" @@ -715,6 +751,11 @@ dependencies: "@types/node" "*" +"@types/http-errors@*": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.5.tgz#5b749ab2b16ba113423feb1a64a95dcd30398472" + integrity sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg== + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.6" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" @@ -742,6 +783,11 @@ expect "^29.0.0" pretty-format "^29.0.0" +"@types/mime@^1": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" + integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== + "@types/node@*": version "22.15.17" resolved "https://registry.yarnpkg.com/@types/node/-/node-22.15.17.tgz#355ccec95f705b664e4332bb64a7f07db30b7055" @@ -749,6 +795,33 @@ dependencies: undici-types "~6.21.0" +"@types/qs@*": + version "6.14.0" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.14.0.tgz#d8b60cecf62f2db0fb68e5e006077b9178b85de5" + integrity sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ== + +"@types/range-parser@*": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" + integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== + +"@types/send@*": + version "0.17.5" + resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.5.tgz#d991d4f2b16f2b1ef497131f00a9114290791e74" + integrity sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + +"@types/serve-static@*": + version "1.15.8" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.8.tgz#8180c3fbe4a70e8f00b9f70b9ba7f08f35987877" + integrity sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg== + dependencies: + "@types/http-errors" "*" + "@types/node" "*" + "@types/send" "*" + "@types/stack-utils@^2.0.0": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" @@ -885,7 +958,7 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^6.12.4: +ajv@^6.12.4, ajv@^6.12.6: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -1246,7 +1319,7 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.2, cross-spawn@^7.0.3, cross-spawn@^7.0.5: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== @@ -1514,6 +1587,11 @@ etag@^1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== +eventsource-parser@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-3.0.3.tgz#e9af1d40b77e6268cdcbc767321e8b9f066adea8" + integrity sha512-nVpZkTMM9rF6AQ9gPJpFsNAMt48wIzB5TQgiTLdHiuO8XEDhUgZEhqKlZWXbIzo9VmJ/HvysHqEaVeD5v9TPvA== + eventsource-parser@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-3.0.1.tgz#5e358dba9a55ba64ca90da883c4ca35bd82467bd" @@ -1562,7 +1640,7 @@ express-rate-limit@^7.5.0: resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-7.5.0.tgz#6a67990a724b4fbbc69119419feef50c51e8b28f" integrity sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg== -express@^5.0.1: +express@^5.0.1, express@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/express/-/express-5.1.0.tgz#d31beaf715a0016f0d53f47d3b4d7acf28c75cc9" integrity sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA== @@ -2404,6 +2482,10 @@ jest@^29.4.0: import-local "^3.0.2" jest-cli "^29.7.0" +"jq-web@https://github.com/stainless-api/jq-web/releases/download/v0.8.6/jq-web.tar.gz": + version "0.8.6" + resolved "https://github.com/stainless-api/jq-web/releases/download/v0.8.6/jq-web.tar.gz#14d0e126987736e82e964d675c3838b5944faa6f" + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -3305,9 +3387,9 @@ ts-node@^10.5.0: v8-compile-cache-lib "^3.0.1" yn "3.1.1" -"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.7/tsc-multi.tgz": - version "1.1.7" - resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.7/tsc-multi.tgz#52f40adf8b808bd0b633346d11cc4a8aeea465cd" +"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz": + version "1.1.8" + resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz#f544b359b8f05e607771ffacc280e58201476b04" dependencies: debug "^4.3.7" fast-glob "^3.3.2" @@ -3508,7 +3590,17 @@ zod-to-json-schema@^3.24.1, zod-to-json-schema@^3.24.5: resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz#d1095440b147fb7c2093812a53c54df8d5df50a3" integrity sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g== -zod@^3.23.8, zod@^3.24.4: +zod-validation-error@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/zod-validation-error/-/zod-validation-error-4.0.1.tgz#a105723eb40299578a6a38cb86647068f6d005b1" + integrity sha512-F3rdaCOHs5ViJ5YTz5zzRtfkQdMdIeKudJAoxy7yB/2ZMEHw73lmCAcQw11r7++20MyGl4WV59EVh7A9rNAyog== + +zod@^3.23.8: version "3.24.4" resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.4.tgz#e2e2cca5faaa012d76e527d0d36622e0a90c315f" integrity sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg== + +zod@^3.25.20: + version "3.25.76" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.76.tgz#26841c3f6fd22a6a2760e7ccb719179768471e34" + integrity sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ== From e7213041b460d7fd3cafb0c30aa32a9cf5222d67 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 19 Aug 2025 03:00:01 +0000 Subject: [PATCH 031/138] chore(internal): refactor array check --- packages/mcp-server/src/headers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mcp-server/src/headers.ts b/packages/mcp-server/src/headers.ts index f7a45d90..248f94d9 100644 --- a/packages/mcp-server/src/headers.ts +++ b/packages/mcp-server/src/headers.ts @@ -6,6 +6,6 @@ import { IncomingMessage } from 'node:http'; export const parseAuthHeaders = (req: IncomingMessage): Partial => { const apiKey = - req.headers['x-api-key'] instanceof Array ? req.headers['x-api-key'][0] : req.headers['x-api-key']; + Array.isArray(req.headers['x-api-key']) ? req.headers['x-api-key'][0] : req.headers['x-api-key']; return { apiKey }; }; From 2810aabc88f2ea8693242e1a64448eb776b7c549 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 20 Aug 2025 06:38:53 +0000 Subject: [PATCH 032/138] chore(mcp): add cors to oauth metadata route --- packages/mcp-server/package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 21b7f6d8..772781ff 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -30,6 +30,7 @@ "@corgi-tech/beagle": "file:../../dist/", "@cloudflare/cabidela": "^0.2.4", "@modelcontextprotocol/sdk": "^1.11.5", + "cors": "^2.8.5", "express": "^5.1.0", "jq-web": "https://github.com/stainless-api/jq-web/releases/download/v0.8.6/jq-web.tar.gz", "qs": "^6.14.0", @@ -42,6 +43,7 @@ "mcp-server": "dist/index.js" }, "devDependencies": { + "@types/cors": "^2.8.19", "@types/express": "^5.0.3", "@types/jest": "^29.4.0", "@types/yargs": "^17.0.8", From 1269066e553182727ad21f6458022e6d83f35cab Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 20 Aug 2025 06:42:32 +0000 Subject: [PATCH 033/138] feat(mcp): add code execution tool --- package.json | 2 +- packages/mcp-server/package.json | 3 +- packages/mcp-server/src/code-tool-paths.cts | 3 + packages/mcp-server/src/code-tool-types.ts | 14 ++ packages/mcp-server/src/code-tool-worker.ts | 46 ++++++ packages/mcp-server/src/code-tool.ts | 146 ++++++++++++++++++++ packages/mcp-server/src/options.ts | 18 ++- packages/mcp-server/src/server.ts | 3 + yarn.lock | 7 +- 9 files changed, 230 insertions(+), 12 deletions(-) create mode 100644 packages/mcp-server/src/code-tool-paths.cts create mode 100644 packages/mcp-server/src/code-tool-types.ts create mode 100644 packages/mcp-server/src/code-tool-worker.ts create mode 100644 packages/mcp-server/src/code-tool.ts diff --git a/package.json b/package.json index a40f6dcb..0775f076 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "publint": "^0.2.12", "ts-jest": "^29.1.0", "ts-node": "^10.5.0", - "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz", + "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz", "tsconfig-paths": "^4.0.0", "typescript": "5.8.3", "typescript-eslint": "8.31.1" diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 772781ff..7fc99021 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -30,6 +30,7 @@ "@corgi-tech/beagle": "file:../../dist/", "@cloudflare/cabidela": "^0.2.4", "@modelcontextprotocol/sdk": "^1.11.5", + "@valtown/deno-http-worker": "^0.0.21", "cors": "^2.8.5", "express": "^5.1.0", "jq-web": "https://github.com/stainless-api/jq-web/releases/download/v0.8.6/jq-web.tar.gz", @@ -57,7 +58,7 @@ "ts-jest": "^29.1.0", "ts-morph": "^19.0.0", "ts-node": "^10.5.0", - "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz", + "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz", "tsconfig-paths": "^4.0.0", "typescript": "5.8.3" }, diff --git a/packages/mcp-server/src/code-tool-paths.cts b/packages/mcp-server/src/code-tool-paths.cts new file mode 100644 index 00000000..15ce7f55 --- /dev/null +++ b/packages/mcp-server/src/code-tool-paths.cts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export const workerPath = require.resolve('./code-tool-worker.mjs'); diff --git a/packages/mcp-server/src/code-tool-types.ts b/packages/mcp-server/src/code-tool-types.ts new file mode 100644 index 00000000..ccc59467 --- /dev/null +++ b/packages/mcp-server/src/code-tool-types.ts @@ -0,0 +1,14 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { type ClientOptions } from '@corgi-tech/beagle/client'; + +export type WorkerInput = { + opts: ClientOptions; + code: string; +}; +export type WorkerSuccess = { + result: unknown | null; + logLines: string[]; + errLines: string[]; +}; +export type WorkerError = { message: string | undefined }; diff --git a/packages/mcp-server/src/code-tool-worker.ts b/packages/mcp-server/src/code-tool-worker.ts new file mode 100644 index 00000000..39f83c97 --- /dev/null +++ b/packages/mcp-server/src/code-tool-worker.ts @@ -0,0 +1,46 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import util from 'node:util'; +import { WorkerInput, WorkerSuccess, WorkerError } from './code-tool-types'; +import { Beagle } from '@corgi-tech/beagle'; + +const fetch = async (req: Request): Promise => { + const { opts, code } = (await req.json()) as WorkerInput; + const client = new Beagle({ + ...opts, + }); + + const logLines: string[] = []; + const errLines: string[] = []; + const console = { + log: (...args: unknown[]) => { + logLines.push(util.format(...args)); + }, + error: (...args: unknown[]) => { + errLines.push(util.format(...args)); + }, + }; + try { + let run_ = async (client: any) => {}; + eval(` + ${code} + run_ = run; + `); + const result = await run_(client); + return Response.json({ + result, + logLines, + errLines, + } satisfies WorkerSuccess); + } catch (e) { + const message = e instanceof Error ? e.message : undefined; + return Response.json( + { + message, + } satisfies WorkerError, + { status: 400, statusText: 'Code execution error' }, + ); + } +}; + +export default { fetch }; diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts new file mode 100644 index 00000000..c1c9a74c --- /dev/null +++ b/packages/mcp-server/src/code-tool.ts @@ -0,0 +1,146 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { type ClientOptions } from '@corgi-tech/beagle/client'; + +import { dirname } from 'node:path'; +import { pathToFileURL } from 'node:url'; +import Beagle from '@corgi-tech/beagle'; +import { Endpoint, ContentBlock, Metadata } from './tools/types'; + +import { Tool } from '@modelcontextprotocol/sdk/types.js'; + +import { newDenoHTTPWorker } from '@valtown/deno-http-worker'; +import { WorkerInput, WorkerError, WorkerSuccess } from './code-tool-types'; +import { workerPath } from './code-tool-paths.cjs'; + +/** + * A tool that runs code against a copy of the SDK. + * + * Instead of exposing every endpoint as it's own tool, which uses up too many tokens for LLMs to use at once, + * we expose a single tool that can be used to search for endpoints by name, resource, operation, or tag, and then + * a generic endpoint that can be used to invoke any endpoint with the provided arguments. + * + * @param endpoints - The endpoints to include in the list. + */ +export function codeTool(): Endpoint { + const metadata: Metadata = { resource: 'all', operation: 'write', tags: [] }; + const tool: Tool = { + name: 'execute', + description: + 'Runs Typescript code to interact with the API.\nYou are a skilled programmer writing code to interface with the service.\nDefine an async function named "run" that takes a single parameter of an initialized client, and it will be run.\nDo not initialize a client, but instead use the client that you are given as a parameter.\nYou will be returned anything that your function returns, plus the results of any console.log statements.\nIf any code triggers an error, the tool will return an error response, so you do not need to add error handling unless you want to output something more helpful than the raw error.\nIt is not necessary to add comments to code, unless by adding those comments you believe that you can generate better code.\nThis code will run in a container, and you will not be able to use fetch or otherwise interact with the network calls other than through the client you are given.\nAny variables you define won\'t live between successive uses of this call, so make sure to return or log any data you might need later.', + inputSchema: { type: 'object', properties: { code: { type: 'string' } } }, + }; + + const handler = async (client: Beagle, args: unknown) => { + const baseURLHostname = new URL(client.baseURL).hostname; + const { code } = args as { code: string }; + + const worker = await newDenoHTTPWorker(pathToFileURL(workerPath), { + runFlags: [ + `--node-modules-dir=manual`, + `--allow-read=code-tool-worker.mjs,${workerPath.replace(/([\/\\]node_modules)[\/\\].+$/, '$1')}/`, + `--allow-net=${baseURLHostname}`, + // Allow environment variables because instantiating the client will try to read from them, + // even though they are not set. + '--allow-env', + ], + printOutput: true, + spawnOptions: { + cwd: dirname(workerPath), + }, + }); + + try { + const resp = await new Promise((resolve, reject) => { + worker.addEventListener('exit', (exitCode) => { + reject(new Error(`Worker exited with code ${exitCode}`)); + }); + + const opts: ClientOptions = { + baseURL: client.baseURL, + apiKey: client.apiKey, + defaultHeaders: { + 'X-Stainless-MCP': 'true', + }, + }; + + const req = worker.request( + 'http://localhost', + { + headers: { + 'content-type': 'application/json', + }, + method: 'POST', + }, + (resp) => { + const body: Uint8Array[] = []; + resp.on('error', (err) => { + reject(err); + }); + resp.on('data', (chunk) => { + body.push(chunk); + }); + resp.on('end', () => { + resolve( + new Response(Buffer.concat(body).toString(), { + status: resp.statusCode ?? 200, + headers: resp.headers as any, + }), + ); + }); + }, + ); + + const body = JSON.stringify({ + opts, + code, + } satisfies WorkerInput); + + req.write(body, (err) => { + if (err !== null && err !== undefined) { + reject(err); + } + }); + + req.end(); + }); + + if (resp.status === 200) { + const { result, logLines, errLines } = (await resp.json()) as WorkerSuccess; + const returnOutput: ContentBlock | null = + result === null ? null + : result === undefined ? null + : { + type: 'text', + text: typeof result === 'string' ? (result as string) : JSON.stringify(result), + }; + const logOutput: ContentBlock | null = + logLines.length === 0 ? + null + : { + type: 'text', + text: logLines.join('\n'), + }; + const errOutput: ContentBlock | null = + errLines.length === 0 ? + null + : { + type: 'text', + text: 'Error output:\n' + errLines.join('\n'), + }; + return { + content: [returnOutput, logOutput, errOutput].filter((block) => block !== null), + }; + } else { + const { message } = (await resp.json()) as WorkerError; + throw new Error(message); + } + } catch (e) { + throw e; + } finally { + worker.terminate(); + } + }; + + return { metadata, tool, handler }; +} diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index 0768d931..a1745912 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -16,6 +16,7 @@ export type McpOptions = { client: ClientType | undefined; includeDynamicTools: boolean | undefined; includeAllTools: boolean | undefined; + includeCodeTools: boolean | undefined; filters: Filter[]; capabilities?: Partial; }; @@ -54,13 +55,13 @@ export function parseCLIOptions(): CLIOptions { .option('tools', { type: 'string', array: true, - choices: ['dynamic', 'all'], + choices: ['dynamic', 'all', 'code'], description: 'Use dynamic tools or all tools', }) .option('no-tools', { type: 'string', array: true, - choices: ['dynamic', 'all'], + choices: ['dynamic', 'all', 'code'], description: 'Do not use any dynamic or all tools', }) .option('tool', { @@ -251,11 +252,13 @@ export function parseCLIOptions(): CLIOptions { } } + const shouldIncludeToolType = (toolType: 'dynamic' | 'all' | 'code') => + explicitTools ? argv.tools?.includes(toolType) && !argv.noTools?.includes(toolType) : undefined; + const explicitTools = Boolean(argv.tools || argv.noTools); - const includeDynamicTools = - explicitTools ? argv.tools?.includes('dynamic') && !argv.noTools?.includes('dynamic') : undefined; - const includeAllTools = - explicitTools ? argv.tools?.includes('all') && !argv.noTools?.includes('all') : undefined; + const includeDynamicTools = shouldIncludeToolType('dynamic'); + const includeAllTools = shouldIncludeToolType('all'); + const includeCodeTools = shouldIncludeToolType('code'); const transport = argv.transport as 'stdio' | 'http'; @@ -264,6 +267,7 @@ export function parseCLIOptions(): CLIOptions { client: client && knownClients[client] ? client : undefined, includeDynamicTools, includeAllTools, + includeCodeTools, filters, capabilities: clientCapabilities, list: argv.list || false, @@ -385,6 +389,8 @@ export function parseQueryOptions(defaultOptions: McpOptions, query: unknown): M includeAllTools: defaultOptions.includeAllTools ?? (queryOptions.tools?.includes('all') && !queryOptions.no_tools?.includes('all')), + // Never include code tools on remote server. + includeCodeTools: undefined, filters, capabilities: clientCapabilities, }; diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index ff532b96..8c93b6e0 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -14,6 +14,7 @@ import { parseEmbeddedJSON, } from './compat'; import { dynamicTools } from './dynamic-tools'; +import { codeTool } from './code-tool'; import { McpOptions } from './options'; export { McpOptions } from './options'; @@ -121,6 +122,8 @@ export function selectTools(endpoints: Endpoint[], options: McpOptions): Endpoin includedTools = endpoints; } else if (options.includeDynamicTools) { includedTools = dynamicTools(endpoints); + } else if (options.includeCodeTools) { + includedTools = [codeTool()]; } else { includedTools = endpoints; } diff --git a/yarn.lock b/yarn.lock index fd164dcf..8311caf5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3283,10 +3283,9 @@ ts-node@^10.5.0: v8-compile-cache-lib "^3.0.0" yn "3.1.1" -"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz": - version "1.1.8" - uid f544b359b8f05e607771ffacc280e58201476b04 - resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz#f544b359b8f05e607771ffacc280e58201476b04" +"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz": + version "1.1.9" + resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz#777f6f5d9e26bf0e94e5170990dd3a841d6707cd" dependencies: debug "^4.3.7" fast-glob "^3.3.2" From 4ea87dae173727b8986c870617f082cb9f05d239 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 21 Aug 2025 06:04:41 +0000 Subject: [PATCH 034/138] chore(internal): make mcp-server publishing public by defaut --- packages/mcp-server/package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 7fc99021..767ca7a4 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -15,6 +15,9 @@ "license": "Apache-2.0", "packageManager": "yarn@1.22.22", "private": false, + "publishConfig": { + "access": "public" + }, "scripts": { "test": "jest", "build": "bash ./build", From 1aa1c092c2892d5ccf86f67936b847e6b1900ca9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 21 Aug 2025 06:20:36 +0000 Subject: [PATCH 035/138] feat(mcp): add option to infer mcp client --- packages/mcp-server/src/compat.ts | 4 +- packages/mcp-server/src/http.ts | 7 +- packages/mcp-server/src/index.ts | 4 +- packages/mcp-server/src/options.ts | 46 ++++-------- packages/mcp-server/src/server.ts | 91 +++++++++++++---------- packages/mcp-server/src/stdio.ts | 7 +- packages/mcp-server/tests/options.test.ts | 25 +------ 7 files changed, 79 insertions(+), 105 deletions(-) diff --git a/packages/mcp-server/src/compat.ts b/packages/mcp-server/src/compat.ts index 1df7a7aa..f84053c7 100644 --- a/packages/mcp-server/src/compat.ts +++ b/packages/mcp-server/src/compat.ts @@ -20,13 +20,13 @@ export const defaultClientCapabilities: ClientCapabilities = { toolNameLength: undefined, }; -export const ClientType = z.enum(['openai-agents', 'claude', 'claude-code', 'cursor']); +export const ClientType = z.enum(['openai-agents', 'claude', 'claude-code', 'cursor', 'infer']); export type ClientType = z.infer; // Client presets for compatibility // Note that these could change over time as models get better, so this is // a best effort. -export const knownClients: Record = { +export const knownClients: Record, ClientCapabilities> = { 'openai-agents': { topLevelUnions: false, validJson: true, diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index ca6d3d25..c11185b7 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -8,7 +8,6 @@ import { fromError } from 'zod-validation-error/v3'; import { McpOptions, parseQueryOptions } from './options'; import { initMcpServer, newMcpServer } from './server'; import { parseAuthHeaders } from './headers'; -import { Endpoint } from './tools'; const newServer = ( defaultMcpOptions: McpOptions, @@ -101,11 +100,7 @@ export const streamableHTTPApp = (options: McpOptions): express.Express => { return app; }; -export const launchStreamableHTTPServer = async ( - options: McpOptions, - endpoints: Endpoint[], - port: number | string | undefined, -) => { +export const launchStreamableHTTPServer = async (options: McpOptions, port: number | string | undefined) => { const app = streamableHTTPApp(options); const server = app.listen(port); const address = server.address(); diff --git a/packages/mcp-server/src/index.ts b/packages/mcp-server/src/index.ts index 05b2ba63..c450e4bb 100644 --- a/packages/mcp-server/src/index.ts +++ b/packages/mcp-server/src/index.ts @@ -23,10 +23,10 @@ async function main() { switch (options.transport) { case 'stdio': - await launchStdioServer(options, selectedTools); + await launchStdioServer(options); break; case 'http': - await launchStreamableHTTPServer(options, selectedTools, options.port ?? options.socket); + await launchStreamableHTTPServer(options, options.port ?? options.socket); break; } } diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index a1745912..9eb00b48 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -13,12 +13,12 @@ export type CLIOptions = McpOptions & { }; export type McpOptions = { - client: ClientType | undefined; - includeDynamicTools: boolean | undefined; - includeAllTools: boolean | undefined; - includeCodeTools: boolean | undefined; - filters: Filter[]; - capabilities?: Partial; + client?: ClientType | undefined; + includeDynamicTools?: boolean | undefined; + includeAllTools?: boolean | undefined; + includeCodeTools?: boolean | undefined; + filters?: Filter[] | undefined; + capabilities?: Partial | undefined; }; const CAPABILITY_CHOICES = [ @@ -204,14 +204,7 @@ export function parseCLIOptions(): CLIOptions { } // Parse client capabilities - const clientCapabilities: ClientCapabilities = { - topLevelUnions: true, - validJson: true, - refs: true, - unions: true, - formats: true, - toolNameLength: undefined, - }; + const clientCapabilities: Partial = {}; // Apply individual capability overrides if (Array.isArray(argv.capability)) { @@ -264,7 +257,7 @@ export function parseCLIOptions(): CLIOptions { const client = argv.client as ClientType; return { - client: client && knownClients[client] ? client : undefined, + client: client && client !== 'infer' && knownClients[client] ? client : undefined, includeDynamicTools, includeAllTools, includeCodeTools, @@ -310,7 +303,7 @@ export function parseQueryOptions(defaultOptions: McpOptions, query: unknown): M const queryObject = typeof query === 'string' ? qs.parse(query) : query; const queryOptions = QueryOptions.parse(queryObject); - const filters: Filter[] = [...defaultOptions.filters]; + const filters: Filter[] = [...(defaultOptions.filters ?? [])]; for (const resource of queryOptions.resource || []) { filters.push({ type: 'resource', op: 'include', value: resource }); @@ -338,15 +331,7 @@ export function parseQueryOptions(defaultOptions: McpOptions, query: unknown): M } // Parse client capabilities - const clientCapabilities: ClientCapabilities = { - topLevelUnions: true, - validJson: true, - refs: true, - unions: true, - formats: true, - toolNameLength: undefined, - ...defaultOptions.capabilities, - }; + const clientCapabilities: Partial = { ...defaultOptions.capabilities }; for (const cap of queryOptions.capability || []) { const parsed = parseCapabilityValue(cap); @@ -384,12 +369,13 @@ export function parseQueryOptions(defaultOptions: McpOptions, query: unknown): M return { client: queryOptions.client ?? defaultOptions.client, includeDynamicTools: - defaultOptions.includeDynamicTools ?? - (queryOptions.tools?.includes('dynamic') && !queryOptions.no_tools?.includes('dynamic')), + defaultOptions.includeDynamicTools === false ? + false + : queryOptions.tools?.includes('dynamic') && !queryOptions.no_tools?.includes('dynamic'), includeAllTools: - defaultOptions.includeAllTools ?? - (queryOptions.tools?.includes('all') && !queryOptions.no_tools?.includes('all')), - // Never include code tools on remote server. + defaultOptions.includeAllTools === false ? + false + : queryOptions.tools?.includes('all') && !queryOptions.no_tools?.includes('all'), includeCodeTools: undefined, filters, capabilities: clientCapabilities, diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 8c93b6e0..e46dac38 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -3,7 +3,12 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { Endpoint, endpoints, HandlerFunction, query } from './tools'; -import { CallToolRequestSchema, ListToolsRequestSchema, Tool } from '@modelcontextprotocol/sdk/types.js'; +import { + CallToolRequestSchema, + Implementation, + ListToolsRequestSchema, + Tool, +} from '@modelcontextprotocol/sdk/types.js'; import { ClientOptions } from '@corgi-tech/beagle'; import Beagle from '@corgi-tech/beagle'; import { @@ -41,29 +46,29 @@ export const server = newMcpServer(); */ export function initMcpServer(params: { server: Server | McpServer; - clientOptions: ClientOptions; - mcpOptions: McpOptions; - endpoints?: { tool: Tool; handler: HandlerFunction }[]; -}) { - const transformedEndpoints = selectTools(endpoints, params.mcpOptions); - const client = new Beagle(params.clientOptions); - const capabilities = { - ...defaultClientCapabilities, - ...(params.mcpOptions.client ? knownClients[params.mcpOptions.client] : params.mcpOptions.capabilities), - }; - init({ server: params.server, client, endpoints: transformedEndpoints, capabilities }); -} - -export function init(params: { - server: Server | McpServer; - client?: Beagle; - endpoints?: { tool: Tool; handler: HandlerFunction }[]; - capabilities?: Partial; + clientOptions?: ClientOptions; + mcpOptions?: McpOptions; }) { const server = params.server instanceof McpServer ? params.server.server : params.server; - const providedEndpoints = params.endpoints || endpoints; - - const endpointMap = Object.fromEntries(providedEndpoints.map((endpoint) => [endpoint.tool.name, endpoint])); + const mcpOptions = params.mcpOptions ?? {}; + + let providedEndpoints: Endpoint[] | null = null; + let endpointMap: Record | null = null; + + const initTools = (implementation?: Implementation) => { + if (implementation && (!mcpOptions.client || mcpOptions.client === 'infer')) { + mcpOptions.client = + implementation.name.toLowerCase().includes('claude') ? 'claude' + : implementation.name.toLowerCase().includes('cursor') ? 'cursor' + : undefined; + mcpOptions.capabilities = { + ...(mcpOptions.client && knownClients[mcpOptions.client]), + ...mcpOptions.capabilities, + }; + } + providedEndpoints = selectTools(endpoints, mcpOptions); + endpointMap = Object.fromEntries(providedEndpoints.map((endpoint) => [endpoint.tool.name, endpoint])); + }; const logAtLevel = (level: 'debug' | 'info' | 'warning' | 'error') => @@ -80,56 +85,64 @@ export function init(params: { error: logAtLevel('error'), }; - const client = - params.client || - new Beagle({ - environment: (readEnv('BEAGLE_ENVIRONMENT') || undefined) as any, - defaultHeaders: { 'X-Stainless-MCP': 'true' }, - logger: logger, - }); + const client = new Beagle({ + ...{ environment: (readEnv('BEAGLE_ENVIRONMENT') || undefined) as any }, + logger, + ...params.clientOptions, + defaultHeaders: { + ...params.clientOptions?.defaultHeaders, + 'X-Stainless-MCP': 'true', + }, + }); server.setRequestHandler(ListToolsRequestSchema, async () => { + if (providedEndpoints === null) { + initTools(server.getClientVersion()); + } return { - tools: providedEndpoints.map((endpoint) => endpoint.tool), + tools: providedEndpoints!.map((endpoint) => endpoint.tool), }; }); server.setRequestHandler(CallToolRequestSchema, async (request) => { + if (endpointMap === null) { + initTools(server.getClientVersion()); + } const { name, arguments: args } = request.params; - const endpoint = endpointMap[name]; + const endpoint = endpointMap![name]; if (!endpoint) { throw new Error(`Unknown tool: ${name}`); } - return executeHandler(endpoint.tool, endpoint.handler, client, args, params.capabilities); + return executeHandler(endpoint.tool, endpoint.handler, client, args, mcpOptions.capabilities); }); } /** * Selects the tools to include in the MCP Server based on the provided options. */ -export function selectTools(endpoints: Endpoint[], options: McpOptions): Endpoint[] { - const filteredEndpoints = query(options.filters, endpoints); +export function selectTools(endpoints: Endpoint[], options?: McpOptions): Endpoint[] { + const filteredEndpoints = query(options?.filters ?? [], endpoints); let includedTools = filteredEndpoints; if (includedTools.length > 0) { - if (options.includeDynamicTools) { + if (options?.includeDynamicTools) { includedTools = dynamicTools(includedTools); } } else { - if (options.includeAllTools) { + if (options?.includeAllTools) { includedTools = endpoints; - } else if (options.includeDynamicTools) { + } else if (options?.includeDynamicTools) { includedTools = dynamicTools(endpoints); - } else if (options.includeCodeTools) { + } else if (options?.includeCodeTools) { includedTools = [codeTool()]; } else { includedTools = endpoints; } } - const capabilities = { ...defaultClientCapabilities, ...options.capabilities }; + const capabilities = { ...defaultClientCapabilities, ...options?.capabilities }; return applyCompatibilityTransformations(includedTools, capabilities); } diff --git a/packages/mcp-server/src/stdio.ts b/packages/mcp-server/src/stdio.ts index b2691635..d902a5bb 100644 --- a/packages/mcp-server/src/stdio.ts +++ b/packages/mcp-server/src/stdio.ts @@ -1,12 +1,11 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; -import { init, newMcpServer } from './server'; -import { Endpoint } from './tools'; +import { initMcpServer, newMcpServer } from './server'; import { McpOptions } from './options'; -export const launchStdioServer = async (options: McpOptions, endpoints: Endpoint[]) => { +export const launchStdioServer = async (options: McpOptions) => { const server = newMcpServer(); - init({ server, endpoints }); + initMcpServer({ server, mcpOptions: options }); const transport = new StdioServerTransport(); await server.connect(transport); diff --git a/packages/mcp-server/tests/options.test.ts b/packages/mcp-server/tests/options.test.ts index 08ea1f18..24604b84 100644 --- a/packages/mcp-server/tests/options.test.ts +++ b/packages/mcp-server/tests/options.test.ts @@ -29,15 +29,7 @@ describe('parseCLIOptions', () => { { type: 'operation', op: 'include', value: 'read' }, ] as Filter[]); - // Default client capabilities - expect(result.capabilities).toEqual({ - topLevelUnions: true, - validJson: true, - refs: true, - unions: true, - formats: true, - toolNameLength: undefined, - }); + expect(result.capabilities).toEqual({}); expect(result.list).toBe(false); @@ -61,14 +53,7 @@ describe('parseCLIOptions', () => { { type: 'operation', op: 'exclude', value: 'write' }, ] as Filter[]); - expect(result.capabilities).toEqual({ - topLevelUnions: true, - validJson: true, - refs: true, - unions: true, - formats: true, - toolNameLength: undefined, - }); + expect(result.capabilities).toEqual({}); cleanup(); }); @@ -99,7 +84,6 @@ describe('parseCLIOptions', () => { validJson: true, refs: true, unions: true, - formats: true, toolNameLength: 40, }); @@ -150,10 +134,7 @@ describe('parseCLIOptions', () => { expect(result.capabilities).toEqual({ topLevelUnions: true, validJson: true, - refs: true, unions: true, - formats: true, - toolNameLength: undefined, }); cleanup(); @@ -316,7 +297,7 @@ describe('parseQueryOptions', () => { ]); expect(result.client).toBe('cursor'); - expect(result.includeDynamicTools).toBe(true); + expect(result.includeDynamicTools).toBe(undefined); }); it('should override client from default options', () => { From e99397d9130edff0386eb934326798ba27d328a9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 07:01:31 +0000 Subject: [PATCH 036/138] chore(mcp): update package.json --- packages/mcp-server/package.json | 1 + packages/mcp-server/src/headers.ts | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 767ca7a4..23172d5b 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -50,6 +50,7 @@ "@types/cors": "^2.8.19", "@types/express": "^5.0.3", "@types/jest": "^29.4.0", + "@types/qs": "^6.14.0", "@types/yargs": "^17.0.8", "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", diff --git a/packages/mcp-server/src/headers.ts b/packages/mcp-server/src/headers.ts index 248f94d9..d909a484 100644 --- a/packages/mcp-server/src/headers.ts +++ b/packages/mcp-server/src/headers.ts @@ -1,8 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { type ClientOptions } from '@corgi-tech/beagle/client'; - import { IncomingMessage } from 'node:http'; +import { ClientOptions } from '@corgi-tech/beagle'; export const parseAuthHeaders = (req: IncomingMessage): Partial => { const apiKey = From 5be8de2a75dde75febba09c8e1465e820863dc8a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 07:02:38 +0000 Subject: [PATCH 037/138] chore(mcp): update types --- packages/mcp-server/src/code-tool-types.ts | 2 +- packages/mcp-server/src/code-tool.ts | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/mcp-server/src/code-tool-types.ts b/packages/mcp-server/src/code-tool-types.ts index ccc59467..ab0f0c1d 100644 --- a/packages/mcp-server/src/code-tool-types.ts +++ b/packages/mcp-server/src/code-tool-types.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { type ClientOptions } from '@corgi-tech/beagle/client'; +import { ClientOptions } from '@corgi-tech/beagle'; export type WorkerInput = { opts: ClientOptions; diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index c1c9a74c..cd304ea1 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -1,10 +1,8 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { type ClientOptions } from '@corgi-tech/beagle/client'; - import { dirname } from 'node:path'; import { pathToFileURL } from 'node:url'; -import Beagle from '@corgi-tech/beagle'; +import Beagle, { ClientOptions } from '@corgi-tech/beagle'; import { Endpoint, ContentBlock, Metadata } from './tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; From 0f2b02d59a17e84238fdedffae2e880dfb6984e4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 07:04:58 +0000 Subject: [PATCH 038/138] chore: add package to package.json --- package.json | 1 + scripts/bootstrap | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 0775f076..184c451a 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "ts-node": "^10.5.0", "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz", "tsconfig-paths": "^4.0.0", + "tslib": "^2.8.1", "typescript": "5.8.3", "typescript-eslint": "8.31.1" }, diff --git a/scripts/bootstrap b/scripts/bootstrap index 0af58e25..062a0349 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -15,4 +15,4 @@ echo "==> Installing Node dependencies…" PACKAGE_MANAGER=$(command -v yarn >/dev/null 2>&1 && echo "yarn" || echo "npm") -$PACKAGE_MANAGER install +$PACKAGE_MANAGER install "$@" From 4eb7b49c60ac79cd3e0270ca2c43eac0444bda94 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 07:09:13 +0000 Subject: [PATCH 039/138] chore(internal): codegen related update --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5eba6aef..09b9fc59 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: - name: Set up Node uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' - name: Bootstrap run: ./scripts/bootstrap @@ -46,7 +46,7 @@ jobs: - name: Set up Node uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' - name: Bootstrap run: ./scripts/bootstrap From bca52b4ab63b8ad10207c10e3b91bf745e842919 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 07:14:50 +0000 Subject: [PATCH 040/138] chore(client): qualify global Blob --- src/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.ts b/src/client.ts index ad8c0c28..19139572 100644 --- a/src/client.ts +++ b/src/client.ts @@ -762,7 +762,7 @@ export class Beagle { // Preserve legacy string encoding behavior for now headers.values.has('content-type')) || // `Blob` is superset of `File` - body instanceof Blob || + ((globalThis as any).Blob && body instanceof (globalThis as any).Blob) || // `FormData` -> `multipart/form-data` body instanceof FormData || // `URLSearchParams` -> `application/x-www-form-urlencoded` From c045122557e3da1c7a19264db20607e8e3d5d5f8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 23 Aug 2025 05:23:03 +0000 Subject: [PATCH 041/138] chore: update CI script --- .github/workflows/ci.yml | 9 +++++++++ scripts/utils/upload-artifact.sh | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 09b9fc59..f57f1b40 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,6 +68,15 @@ jobs: AUTH: ${{ steps.github-oidc.outputs.github_token }} SHA: ${{ github.sha }} run: ./scripts/utils/upload-artifact.sh + + - name: Upload MCP Server tarball + if: github.repository == 'stainless-sdks/beagle-typescript' + env: + URL: https://pkg.stainless.com/s?subpackage=mcp-server + AUTH: ${{ steps.github-oidc.outputs.github_token }} + SHA: ${{ github.sha }} + BUILD_PATH: packages/mcp-server/dist + run: ./scripts/utils/upload-artifact.sh test: timeout-minutes: 10 name: test diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh index 84276dec..2f43c9d1 100755 --- a/scripts/utils/upload-artifact.sh +++ b/scripts/utils/upload-artifact.sh @@ -12,7 +12,7 @@ if [[ "$SIGNED_URL" == "null" ]]; then exit 1 fi -UPLOAD_RESPONSE=$(tar -cz dist | curl -v -X PUT \ +UPLOAD_RESPONSE=$(tar -cz "${BUILD_PATH:-dist}" | curl -v -X PUT \ -H "Content-Type: application/gzip" \ --data-binary @- "$SIGNED_URL" 2>&1) From c9154b5f6fba930499648e4b8669e2d13916c6b8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 24 Aug 2025 02:45:19 +0000 Subject: [PATCH 042/138] chore(internal): codegen related update --- packages/mcp-server/src/options.ts | 20 ++++++++++++-------- packages/mcp-server/tests/options.test.ts | 2 +- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index 9eb00b48..2100cf58 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -366,16 +366,20 @@ export function parseQueryOptions(defaultOptions: McpOptions, query: unknown): M } } + let dynamicTools: boolean | undefined = + queryOptions.no_tools && !queryOptions.no_tools?.includes('dynamic') ? false + : queryOptions.tools?.includes('dynamic') ? true + : defaultOptions.includeDynamicTools; + + let allTools: boolean | undefined = + queryOptions.no_tools && !queryOptions.no_tools?.includes('all') ? false + : queryOptions.tools?.includes('all') ? true + : defaultOptions.includeAllTools; + return { client: queryOptions.client ?? defaultOptions.client, - includeDynamicTools: - defaultOptions.includeDynamicTools === false ? - false - : queryOptions.tools?.includes('dynamic') && !queryOptions.no_tools?.includes('dynamic'), - includeAllTools: - defaultOptions.includeAllTools === false ? - false - : queryOptions.tools?.includes('all') && !queryOptions.no_tools?.includes('all'), + includeDynamicTools: dynamicTools, + includeAllTools: allTools, includeCodeTools: undefined, filters, capabilities: clientCapabilities, diff --git a/packages/mcp-server/tests/options.test.ts b/packages/mcp-server/tests/options.test.ts index 24604b84..a8a5b81a 100644 --- a/packages/mcp-server/tests/options.test.ts +++ b/packages/mcp-server/tests/options.test.ts @@ -297,7 +297,7 @@ describe('parseQueryOptions', () => { ]); expect(result.client).toBe('cursor'); - expect(result.includeDynamicTools).toBe(undefined); + expect(result.includeDynamicTools).toBe(true); }); it('should override client from default options', () => { From b34cc40199fbf95a29f862317c8cbd8c17f4be8b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 24 Aug 2025 05:03:05 +0000 Subject: [PATCH 043/138] feat(api): manual updates --- .stats.yml | 4 +- api.md | 1 + packages/mcp-server/README.md | 1 + .../retrieve-certificate-enrollments.ts | 39 +++++++++++++++++++ packages/mcp-server/src/tools/index.ts | 2 + src/resources/enrollments.ts | 11 ++++++ 6 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 packages/mcp-server/src/tools/enrollments/retrieve-certificate-enrollments.ts diff --git a/.stats.yml b/.stats.yml index fc50d334..c1c3fae9 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 22 +configured_endpoints: 23 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-2edadee34a317889c9d854eb566c42649fb0f53ce572927a42cd873421d86486.yml openapi_spec_hash: ebc55666c40434190b539cd87761635b -config_hash: d63f662e216ecc51eccc05b8a4b5198e +config_hash: 7241a3f956f7baa4191c50960d622a26 diff --git a/api.md b/api.md index 23ce7325..3b23350a 100644 --- a/api.md +++ b/api.md @@ -53,6 +53,7 @@ Methods: - client.enrollments.retrieve(id) -> Enrollment - client.enrollments.list({ ...params }) -> EnrollmentsEnrollmentsPagination - client.enrollments.lapse(id) -> void +- client.enrollments.retrieveCertificate(id) -> Response # InsuranceVerification diff --git a/packages/mcp-server/README.md b/packages/mcp-server/README.md index 663b6583..a656a243 100644 --- a/packages/mcp-server/README.md +++ b/packages/mcp-server/README.md @@ -231,6 +231,7 @@ The following tools are available in this MCP server. - `retrieve_enrollments` (`read`): get a specific enrollment by its id. - `list_enrollments` (`read`): list all enrollments, this endpoint is paginated and allows for queries by individual property manager. - `lapse_enrollments` (`write`): lapses a specific enrollment for a tenant, note that if a tenant has multiple enrollments (e.g., SDR and TLL), each must be lapsed individually +- `retrieve_certificate_enrollments` (`read`): get the certificate of enrollment for a given enrollment ### Resource `insurance_verification`: diff --git a/packages/mcp-server/src/tools/enrollments/retrieve-certificate-enrollments.ts b/packages/mcp-server/src/tools/enrollments/retrieve-certificate-enrollments.ts new file mode 100644 index 00000000..abf62a31 --- /dev/null +++ b/packages/mcp-server/src/tools/enrollments/retrieve-certificate-enrollments.ts @@ -0,0 +1,39 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { Metadata, asBinaryContentResult } from 'beagle-mcp/tools/types'; + +import { Tool } from '@modelcontextprotocol/sdk/types.js'; +import Beagle from '@corgi-tech/beagle'; + +export const metadata: Metadata = { + resource: 'enrollments', + operation: 'read', + tags: [], + httpMethod: 'get', + httpPath: '/api/enrollments/{id}/certificate', + operationId: 'getEnrollmentCertificate', +}; + +export const tool: Tool = { + name: 'retrieve_certificate_enrollments', + description: 'get the certificate of enrollment for a given enrollment', + inputSchema: { + type: 'object', + properties: { + id: { + type: 'number', + }, + }, + required: ['id'], + }, + annotations: { + readOnlyHint: true, + }, +}; + +export const handler = async (client: Beagle, args: Record | undefined) => { + const { id, ...body } = args as any; + return asBinaryContentResult(await client.enrollments.retrieveCertificate(id)); +}; + +export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/index.ts b/packages/mcp-server/src/tools/index.ts index 39ab480c..d9640613 100644 --- a/packages/mcp-server/src/tools/index.ts +++ b/packages/mcp-server/src/tools/index.ts @@ -20,6 +20,7 @@ import create_enrollments from './enrollments/create-enrollments'; import retrieve_enrollments from './enrollments/retrieve-enrollments'; import list_enrollments from './enrollments/list-enrollments'; import lapse_enrollments from './enrollments/lapse-enrollments'; +import retrieve_certificate_enrollments from './enrollments/retrieve-certificate-enrollments'; import verify_insurance_verification from './insurance-verification/verify-insurance-verification'; import create_webhook_endpoints from './webhook/endpoints/create-webhook-endpoints'; import retrieve_webhook_endpoints from './webhook/endpoints/retrieve-webhook-endpoints'; @@ -49,6 +50,7 @@ addEndpoint(create_enrollments); addEndpoint(retrieve_enrollments); addEndpoint(list_enrollments); addEndpoint(lapse_enrollments); +addEndpoint(retrieve_certificate_enrollments); addEndpoint(verify_insurance_verification); addEndpoint(create_webhook_endpoints); addEndpoint(retrieve_webhook_endpoints); diff --git a/src/resources/enrollments.ts b/src/resources/enrollments.ts index e341e765..1ffee073 100644 --- a/src/resources/enrollments.ts +++ b/src/resources/enrollments.ts @@ -46,6 +46,17 @@ export class Enrollments extends APIResource { headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), }); } + + /** + * get the certificate of enrollment for a given enrollment + */ + retrieveCertificate(id: number | null, options?: RequestOptions): APIPromise { + return this._client.get(path`/api/enrollments/${id}/certificate`, { + ...options, + headers: buildHeaders([{ Accept: 'application/pdf' }, options?.headers]), + __binaryResponse: true, + }); + } } export type EnrollmentsEnrollmentsPagination = EnrollmentsPagination; From b9ee2140c2996771561ce50b616249cba930cf0b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 24 Aug 2025 05:04:46 +0000 Subject: [PATCH 044/138] chore: configure new SDK language --- .stats.yml | 2 +- packages/mcp-server/README.md | 8 ++++---- packages/mcp-server/build | 2 +- packages/mcp-server/jest.config.ts | 4 ++-- packages/mcp-server/package.json | 6 +++--- .../src/tools/enrollments/create-enrollments.ts | 4 ++-- .../mcp-server/src/tools/enrollments/lapse-enrollments.ts | 2 +- .../mcp-server/src/tools/enrollments/list-enrollments.ts | 4 ++-- .../tools/enrollments/retrieve-certificate-enrollments.ts | 2 +- .../src/tools/enrollments/retrieve-enrollments.ts | 4 ++-- .../verify-insurance-verification.ts | 4 ++-- packages/mcp-server/src/tools/plans/list-plans.ts | 4 ++-- packages/mcp-server/src/tools/plans/retrieve-plans.ts | 4 ++-- .../tools/property-managers/create-property-managers.ts | 4 ++-- .../tools/property-managers/delete-property-managers.ts | 2 +- .../src/tools/property-managers/list-property-managers.ts | 4 ++-- .../tools/property-managers/retrieve-property-managers.ts | 4 ++-- .../tools/property-managers/update-property-managers.ts | 4 ++-- packages/mcp-server/src/tools/tenants/create-tenants.ts | 4 ++-- packages/mcp-server/src/tools/tenants/delete-tenants.ts | 2 +- packages/mcp-server/src/tools/tenants/list-tenants.ts | 4 ++-- packages/mcp-server/src/tools/tenants/retrieve-tenants.ts | 4 ++-- packages/mcp-server/src/tools/tenants/update-tenants.ts | 4 ++-- .../tools/webhook/endpoints/create-webhook-endpoints.ts | 4 ++-- .../tools/webhook/endpoints/delete-webhook-endpoints.ts | 2 +- .../src/tools/webhook/endpoints/list-webhook-endpoints.ts | 4 ++-- .../tools/webhook/endpoints/retrieve-webhook-endpoints.ts | 4 ++-- .../tools/webhook/endpoints/update-webhook-endpoints.ts | 4 ++-- packages/mcp-server/tsconfig.build.json | 4 ++-- packages/mcp-server/tsconfig.json | 4 ++-- 30 files changed, 56 insertions(+), 56 deletions(-) diff --git a/.stats.yml b/.stats.yml index c1c3fae9..218c538d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 23 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-2edadee34a317889c9d854eb566c42649fb0f53ce572927a42cd873421d86486.yml openapi_spec_hash: ebc55666c40434190b539cd87761635b -config_hash: 7241a3f956f7baa4191c50960d622a26 +config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/packages/mcp-server/README.md b/packages/mcp-server/README.md index a656a243..1f1b192a 100644 --- a/packages/mcp-server/README.md +++ b/packages/mcp-server/README.md @@ -11,7 +11,7 @@ You can run the MCP Server directly via `npx`: ```sh export BEAGLE_API_KEY="My API Key" export BEAGLE_ENVIRONMENT="production" -npx -y beagle-mcp@latest +npx -y @corgi-tech/beagle-mcp@latest ``` ### Via MCP Client @@ -26,7 +26,7 @@ For clients with a configuration JSON, it might look something like this: "mcpServers": { "corgi_tech_beagle_api": { "command": "npx", - "args": ["-y", "beagle-mcp", "--client=claude", "--tools=dynamic"], + "args": ["-y", "@corgi-tech/beagle-mcp", "--client=claude", "--tools=dynamic"], "env": { "BEAGLE_API_KEY": "My API Key", "BEAGLE_ENVIRONMENT": "production" @@ -169,10 +169,10 @@ http://localhost:3000?client=cursor&capability=tool-name-length%3D40 ```js // Import the server, generated endpoints, or the init function -import { server, endpoints, init } from "beagle-mcp/server"; +import { server, endpoints, init } from "@corgi-tech/beagle-mcp/server"; // import a specific tool -import retrievePlans from "beagle-mcp/tools/plans/retrieve-plans"; +import retrievePlans from "@corgi-tech/beagle-mcp/tools/plans/retrieve-plans"; // initialize the server and all endpoints init({ server, endpoints }); diff --git a/packages/mcp-server/build b/packages/mcp-server/build index e8b240ca..92e99791 100644 --- a/packages/mcp-server/build +++ b/packages/mcp-server/build @@ -29,4 +29,4 @@ cp tsconfig.dist-src.json dist/src/tsconfig.json chmod +x dist/index.js -DIST_PATH=./dist PKG_IMPORT_PATH=beagle-mcp/ node ../../scripts/utils/postprocess-files.cjs +DIST_PATH=./dist PKG_IMPORT_PATH=@corgi-tech/beagle-mcp/ node ../../scripts/utils/postprocess-files.cjs diff --git a/packages/mcp-server/jest.config.ts b/packages/mcp-server/jest.config.ts index 1b4ac3c8..f213efaa 100644 --- a/packages/mcp-server/jest.config.ts +++ b/packages/mcp-server/jest.config.ts @@ -7,8 +7,8 @@ const config: JestConfigWithTsJest = { '^.+\\.(t|j)sx?$': ['@swc/jest', { sourceMaps: 'inline' }], }, moduleNameMapper: { - '^beagle-mcp$': '/src/index.ts', - '^beagle-mcp/(.*)$': '/src/$1', + '^@corgi-tech/beagle-mcp$': '/src/index.ts', + '^@corgi-tech/beagle-mcp/(.*)$': '/src/$1', }, modulePathIgnorePatterns: ['/dist/'], testPathIgnorePatterns: ['scripts'], diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 23172d5b..c3348883 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -1,5 +1,5 @@ { - "name": "beagle-mcp", + "name": "@corgi-tech/beagle-mcp", "version": "0.0.1-alpha.0", "description": "The official MCP Server for the Beagle API", "author": "Beagle <>", @@ -67,8 +67,8 @@ "typescript": "5.8.3" }, "imports": { - "beagle-mcp": ".", - "beagle-mcp/*": "./src/*" + "@corgi-tech/beagle-mcp": ".", + "@corgi-tech/beagle-mcp/*": "./src/*" }, "exports": { ".": { diff --git a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts index 535ea80d..734b1654 100644 --- a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from 'beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts b/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts index af16ae8d..1f58c0ca 100644 --- a/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts index 607f372f..96c28d73 100644 --- a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from 'beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/enrollments/retrieve-certificate-enrollments.ts b/packages/mcp-server/src/tools/enrollments/retrieve-certificate-enrollments.ts index abf62a31..680e7ec9 100644 --- a/packages/mcp-server/src/tools/enrollments/retrieve-certificate-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/retrieve-certificate-enrollments.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Metadata, asBinaryContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asBinaryContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts index 0a2e5063..f17a691a 100644 --- a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from 'beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts index 393dd079..1ac13afb 100644 --- a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts +++ b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from 'beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/plans/list-plans.ts b/packages/mcp-server/src/tools/plans/list-plans.ts index ed732fa5..490892e1 100644 --- a/packages/mcp-server/src/tools/plans/list-plans.ts +++ b/packages/mcp-server/src/tools/plans/list-plans.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from 'beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/plans/retrieve-plans.ts b/packages/mcp-server/src/tools/plans/retrieve-plans.ts index 2a1743de..c388d98c 100644 --- a/packages/mcp-server/src/tools/plans/retrieve-plans.ts +++ b/packages/mcp-server/src/tools/plans/retrieve-plans.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from 'beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts index b1153f27..b2eed925 100644 --- a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from 'beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts b/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts index b6bceea5..c2aafee6 100644 --- a/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts index 4a6d2cf4..c32c3b28 100644 --- a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from 'beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts index d41ee401..cb07e3a8 100644 --- a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from 'beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts index 7a21218e..1fb524dc 100644 --- a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from 'beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/tenants/create-tenants.ts b/packages/mcp-server/src/tools/tenants/create-tenants.ts index d318049b..08fea80a 100644 --- a/packages/mcp-server/src/tools/tenants/create-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/create-tenants.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from 'beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/tenants/delete-tenants.ts b/packages/mcp-server/src/tools/tenants/delete-tenants.ts index 3f64f3f3..89273d02 100644 --- a/packages/mcp-server/src/tools/tenants/delete-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/delete-tenants.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/tenants/list-tenants.ts b/packages/mcp-server/src/tools/tenants/list-tenants.ts index 1c67a70f..25e49579 100644 --- a/packages/mcp-server/src/tools/tenants/list-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/list-tenants.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from 'beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts b/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts index bc66fd93..280c63a4 100644 --- a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from 'beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/tenants/update-tenants.ts b/packages/mcp-server/src/tools/tenants/update-tenants.ts index 9f8a3363..e63e96b7 100644 --- a/packages/mcp-server/src/tools/tenants/update-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/update-tenants.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from 'beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts index 8563861f..f3054b7d 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from 'beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts index 17f35b27..4804e3e0 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts index 16dce57a..903dfe03 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from 'beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts index 4f15de28..9257bc58 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from 'beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts index 9fca496a..b60f4862 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from 'beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from 'beagle-mcp/tools/types'; +import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/tsconfig.build.json b/packages/mcp-server/tsconfig.build.json index 85c4e8fa..9c01cf3c 100644 --- a/packages/mcp-server/tsconfig.build.json +++ b/packages/mcp-server/tsconfig.build.json @@ -5,8 +5,8 @@ "compilerOptions": { "rootDir": "./dist/src", "paths": { - "beagle-mcp/*": ["dist/src/*"], - "beagle-mcp": ["dist/src/index.ts"] + "@corgi-tech/beagle-mcp/*": ["dist/src/*"], + "@corgi-tech/beagle-mcp": ["dist/src/index.ts"] }, "noEmit": false, "declaration": true, diff --git a/packages/mcp-server/tsconfig.json b/packages/mcp-server/tsconfig.json index ec3fb0a9..663ec745 100644 --- a/packages/mcp-server/tsconfig.json +++ b/packages/mcp-server/tsconfig.json @@ -9,8 +9,8 @@ "esModuleInterop": true, "baseUrl": "./", "paths": { - "beagle-mcp/*": ["src/*"], - "beagle-mcp": ["src/index.ts"] + "@corgi-tech/beagle-mcp/*": ["src/*"], + "@corgi-tech/beagle-mcp": ["src/index.ts"] }, "noEmit": true, From f2029a0d8e693520ead61b89b9e8516f5956f93f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 29 Aug 2025 03:49:19 +0000 Subject: [PATCH 045/138] chore(internal): update global Error reference --- src/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.ts b/src/client.ts index 19139572..b7bf3cf1 100644 --- a/src/client.ts +++ b/src/client.ts @@ -436,7 +436,7 @@ export class Beagle { const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError); const headersTime = Date.now(); - if (response instanceof Error) { + if (response instanceof globalThis.Error) { const retryMessage = `retrying, ${retriesRemaining} attempts remaining`; if (options.signal?.aborted) { throw new Errors.APIUserAbortError(); From 9b6b5ee4ca24115f8723fb85733a1137d2e042f4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 3 Sep 2025 03:49:59 +0000 Subject: [PATCH 046/138] feat(mcp): expose client options in `streamableHTTPApp` --- packages/mcp-server/src/http.ts | 58 ++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index c11185b7..ec34ab47 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -6,14 +6,20 @@ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/ import express from 'express'; import { fromError } from 'zod-validation-error/v3'; import { McpOptions, parseQueryOptions } from './options'; -import { initMcpServer, newMcpServer } from './server'; +import { ClientOptions, initMcpServer, newMcpServer } from './server'; import { parseAuthHeaders } from './headers'; -const newServer = ( - defaultMcpOptions: McpOptions, - req: express.Request, - res: express.Response, -): McpServer | null => { +const newServer = ({ + clientOptions, + mcpOptions: defaultMcpOptions, + req, + res, +}: { + clientOptions: ClientOptions; + mcpOptions: McpOptions; + req: express.Request; + res: express.Response; +}): McpServer | null => { const server = newMcpServer(); let mcpOptions: McpOptions; @@ -35,10 +41,8 @@ const newServer = ( initMcpServer({ server: server, clientOptions: { + ...clientOptions, ...authOptions, - defaultHeaders: { - 'X-Stainless-MCP': 'true', - }, }, mcpOptions, }); @@ -56,17 +60,19 @@ const newServer = ( return server; }; -const post = (defaultOptions: McpOptions) => async (req: express.Request, res: express.Response) => { - const server = newServer(defaultOptions, req, res); - // If we return null, we already set the authorization error. - if (server === null) return; - const transport = new StreamableHTTPServerTransport({ - // Stateless server - sessionIdGenerator: undefined, - }); - await server.connect(transport); - await transport.handleRequest(req, res, req.body); -}; +const post = + (options: { clientOptions: ClientOptions; mcpOptions: McpOptions }) => + async (req: express.Request, res: express.Response) => { + const server = newServer({ ...options, req, res }); + // If we return null, we already set the authorization error. + if (server === null) return; + const transport = new StreamableHTTPServerTransport({ + // Stateless server + sessionIdGenerator: undefined, + }); + await server.connect(transport); + await transport.handleRequest(req, res, req.body); + }; const get = async (req: express.Request, res: express.Response) => { res.status(405).json({ @@ -88,20 +94,26 @@ const del = async (req: express.Request, res: express.Response) => { }); }; -export const streamableHTTPApp = (options: McpOptions): express.Express => { +export const streamableHTTPApp = ({ + clientOptions = {}, + mcpOptions = {}, +}: { + clientOptions?: ClientOptions; + mcpOptions?: McpOptions; +}): express.Express => { const app = express(); app.set('query parser', 'extended'); app.use(express.json()); app.get('/', get); - app.post('/', post(options)); + app.post('/', post({ clientOptions, mcpOptions })); app.delete('/', del); return app; }; export const launchStreamableHTTPServer = async (options: McpOptions, port: number | string | undefined) => { - const app = streamableHTTPApp(options); + const app = streamableHTTPApp({ mcpOptions: options }); const server = app.listen(port); const address = server.address(); From a10002e54a632b7f5d0cd01d5c53314f7883f3c2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 3 Sep 2025 03:52:25 +0000 Subject: [PATCH 047/138] chore(internal): codegen related update --- packages/mcp-server/src/code-tool.ts | 8 +++++--- packages/mcp-server/src/index.ts | 6 +++--- packages/mcp-server/src/server.ts | 14 +++++++------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index cd304ea1..51859ce3 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -7,9 +7,7 @@ import { Endpoint, ContentBlock, Metadata } from './tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import { newDenoHTTPWorker } from '@valtown/deno-http-worker'; import { WorkerInput, WorkerError, WorkerSuccess } from './code-tool-types'; -import { workerPath } from './code-tool-paths.cjs'; /** * A tool that runs code against a copy of the SDK. @@ -20,7 +18,7 @@ import { workerPath } from './code-tool-paths.cjs'; * * @param endpoints - The endpoints to include in the list. */ -export function codeTool(): Endpoint { +export async function codeTool(): Promise { const metadata: Metadata = { resource: 'all', operation: 'write', tags: [] }; const tool: Tool = { name: 'execute', @@ -29,6 +27,10 @@ export function codeTool(): Endpoint { inputSchema: { type: 'object', properties: { code: { type: 'string' } } }, }; + // Import dynamically to avoid failing at import time in cases where the environment is not well-supported. + const { newDenoHTTPWorker } = await import('@valtown/deno-http-worker'); + const { workerPath } = await import('./code-tool-paths.cjs'); + const handler = async (client: Beagle, args: unknown) => { const baseURLHostname = new URL(client.baseURL).hostname; const { code } = args as { code: string }; diff --git a/packages/mcp-server/src/index.ts b/packages/mcp-server/src/index.ts index c450e4bb..4850a0e2 100644 --- a/packages/mcp-server/src/index.ts +++ b/packages/mcp-server/src/index.ts @@ -14,7 +14,7 @@ async function main() { return; } - const selectedTools = selectToolsOrError(endpoints, options); + const selectedTools = await selectToolsOrError(endpoints, options); console.error( `MCP Server starting with ${selectedTools.length} tools:`, @@ -47,9 +47,9 @@ function parseOptionsOrError() { } } -function selectToolsOrError(endpoints: Endpoint[], options: McpOptions): Endpoint[] { +async function selectToolsOrError(endpoints: Endpoint[], options: McpOptions): Promise { try { - const includedTools = selectTools(endpoints, options); + const includedTools = await selectTools(endpoints, options); if (includedTools.length === 0) { console.error('No tools match the provided filters.'); process.exit(1); diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index e46dac38..b46f1782 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -55,7 +55,7 @@ export function initMcpServer(params: { let providedEndpoints: Endpoint[] | null = null; let endpointMap: Record | null = null; - const initTools = (implementation?: Implementation) => { + const initTools = async (implementation?: Implementation) => { if (implementation && (!mcpOptions.client || mcpOptions.client === 'infer')) { mcpOptions.client = implementation.name.toLowerCase().includes('claude') ? 'claude' @@ -66,8 +66,8 @@ export function initMcpServer(params: { ...mcpOptions.capabilities, }; } - providedEndpoints = selectTools(endpoints, mcpOptions); - endpointMap = Object.fromEntries(providedEndpoints.map((endpoint) => [endpoint.tool.name, endpoint])); + providedEndpoints ??= await selectTools(endpoints, mcpOptions); + endpointMap ??= Object.fromEntries(providedEndpoints.map((endpoint) => [endpoint.tool.name, endpoint])); }; const logAtLevel = @@ -97,7 +97,7 @@ export function initMcpServer(params: { server.setRequestHandler(ListToolsRequestSchema, async () => { if (providedEndpoints === null) { - initTools(server.getClientVersion()); + await initTools(server.getClientVersion()); } return { tools: providedEndpoints!.map((endpoint) => endpoint.tool), @@ -106,7 +106,7 @@ export function initMcpServer(params: { server.setRequestHandler(CallToolRequestSchema, async (request) => { if (endpointMap === null) { - initTools(server.getClientVersion()); + await initTools(server.getClientVersion()); } const { name, arguments: args } = request.params; const endpoint = endpointMap![name]; @@ -121,7 +121,7 @@ export function initMcpServer(params: { /** * Selects the tools to include in the MCP Server based on the provided options. */ -export function selectTools(endpoints: Endpoint[], options?: McpOptions): Endpoint[] { +export async function selectTools(endpoints: Endpoint[], options?: McpOptions): Promise { const filteredEndpoints = query(options?.filters ?? [], endpoints); let includedTools = filteredEndpoints; @@ -136,7 +136,7 @@ export function selectTools(endpoints: Endpoint[], options?: McpOptions): Endpoi } else if (options?.includeDynamicTools) { includedTools = dynamicTools(endpoints); } else if (options?.includeCodeTools) { - includedTools = [codeTool()]; + includedTools = [await codeTool()]; } else { includedTools = endpoints; } From 1a551d182e06c6d83d5b5a56abfecbf53728b195 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 3 Sep 2025 03:54:36 +0000 Subject: [PATCH 048/138] feat(mcp): allow setting logging level --- packages/mcp-server/src/server.ts | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index b46f1782..b39e21ef 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -5,8 +5,9 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { Endpoint, endpoints, HandlerFunction, query } from './tools'; import { CallToolRequestSchema, - Implementation, ListToolsRequestSchema, + SetLevelRequestSchema, + Implementation, Tool, } from '@modelcontextprotocol/sdk/types.js'; import { ClientOptions } from '@corgi-tech/beagle'; @@ -85,7 +86,7 @@ export function initMcpServer(params: { error: logAtLevel('error'), }; - const client = new Beagle({ + let client = new Beagle({ ...{ environment: (readEnv('BEAGLE_ENVIRONMENT') || undefined) as any }, logger, ...params.clientOptions, @@ -116,6 +117,29 @@ export function initMcpServer(params: { return executeHandler(endpoint.tool, endpoint.handler, client, args, mcpOptions.capabilities); }); + + server.setRequestHandler(SetLevelRequestSchema, async (request) => { + const { level } = request.params; + switch (level) { + case 'debug': + client = client.withOptions({ logLevel: 'debug' }); + break; + case 'info': + client = client.withOptions({ logLevel: 'info' }); + break; + case 'notice': + case 'warning': + client = client.withOptions({ logLevel: 'warn' }); + break; + case 'error': + client = client.withOptions({ logLevel: 'error' }); + break; + default: + client = client.withOptions({ logLevel: 'off' }); + break; + } + return {}; + }); } /** From e17398f8d36c6a5f4d4f1cda0f47957b2f9aa76b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 00:26:19 +0000 Subject: [PATCH 049/138] feat(api): api update --- .stats.yml | 4 ++-- .../src/tools/enrollments/create-enrollments.ts | 15 +-------------- src/resources/enrollments.ts | 10 ---------- tests/api-resources/enrollments.test.ts | 2 -- 4 files changed, 3 insertions(+), 28 deletions(-) diff --git a/.stats.yml b/.stats.yml index 218c538d..ae201744 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 23 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-2edadee34a317889c9d854eb566c42649fb0f53ce572927a42cd873421d86486.yml -openapi_spec_hash: ebc55666c40434190b539cd87761635b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-3a87a1cacdb259999db9faee3bf96e2533b58fac685f572be8fc99b154941403.yml +openapi_spec_hash: 212fb2066535de06799c12a5d5096ee5 config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts index 734b1654..e46d0271 100644 --- a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts @@ -33,19 +33,6 @@ export const tool: Tool = { propertyManagerId: { type: 'number', }, - status: { - type: 'string', - enum: [ - 'Premium Paying', - 'Issued, Not Paid', - 'Expired', - 'Lapsed', - 'Suspended', - 'Cancelled', - 'Not taken', - 'Declined', - ], - }, tenantId: { type: 'number', }, @@ -60,7 +47,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, - required: ['effectiveDate', 'plan', 'propertyManagerId', 'status', 'tenantId'], + required: ['effectiveDate', 'plan', 'propertyManagerId', 'tenantId'], }, annotations: {}, }; diff --git a/src/resources/enrollments.ts b/src/resources/enrollments.ts index 1ffee073..2359ba7d 100644 --- a/src/resources/enrollments.ts +++ b/src/resources/enrollments.ts @@ -108,16 +108,6 @@ export interface EnrollmentCreateParams { propertyManagerId: number; - status: - | 'Premium Paying' - | 'Issued, Not Paid' - | 'Expired' - | 'Lapsed' - | 'Suspended' - | 'Cancelled' - | 'Not taken' - | 'Declined'; - tenantId: number; /** diff --git a/tests/api-resources/enrollments.test.ts b/tests/api-resources/enrollments.test.ts index 68f133df..3456da4d 100644 --- a/tests/api-resources/enrollments.test.ts +++ b/tests/api-resources/enrollments.test.ts @@ -14,7 +14,6 @@ describe('resource enrollments', () => { effectiveDate: 'effectiveDate', plan: 'plan', propertyManagerId: 0, - status: 'Premium Paying', tenantId: 0, }); const rawResponse = await responsePromise.asResponse(); @@ -32,7 +31,6 @@ describe('resource enrollments', () => { effectiveDate: 'effectiveDate', plan: 'plan', propertyManagerId: 0, - status: 'Premium Paying', tenantId: 0, note: 'note', }); From ef25521707cb8fa31d9df40ce441eef11ccd105e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 04:28:01 +0000 Subject: [PATCH 050/138] chore(internal): codegen related update --- .gitignore | 3 +- packages/mcp-server/build | 24 ++ packages/mcp-server/manifest.json | 42 +++ packages/mcp-server/package.json | 1 + .../mcp-server/scripts/copy-bundle-files.cjs | 36 ++ packages/mcp-server/yarn.lock | 326 +++++++++++++++++- 6 files changed, 423 insertions(+), 9 deletions(-) create mode 100644 packages/mcp-server/manifest.json create mode 100644 packages/mcp-server/scripts/copy-bundle-files.cjs diff --git a/.gitignore b/.gitignore index d98d51a8..4b27d0fc 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ dist dist-deno /*.tgz .idea/ - +dist-bundle +*.dxt diff --git a/packages/mcp-server/build b/packages/mcp-server/build index 92e99791..c6837d3b 100644 --- a/packages/mcp-server/build +++ b/packages/mcp-server/build @@ -30,3 +30,27 @@ cp tsconfig.dist-src.json dist/src/tsconfig.json chmod +x dist/index.js DIST_PATH=./dist PKG_IMPORT_PATH=@corgi-tech/beagle-mcp/ node ../../scripts/utils/postprocess-files.cjs + +# mcp bundle +rm -rf dist-bundle corgi_tech_beagle_api.dxt; mkdir dist-bundle + +# copy package.json +PKG_JSON_PATH=../../packages/mcp-server/package.json node ../../scripts/utils/make-dist-package-json.cjs > dist-bundle/package.json + +# copy files +node scripts/copy-bundle-files.cjs + +# install runtime deps +cd dist-bundle +npm install +cd .. + +# pack bundle +cp manifest.json dist-bundle + +npx dxt pack dist-bundle corgi_tech_beagle_api.dxt + +npx dxt sign corgi_tech_beagle_api.dxt --self-signed + +# clean up +rm -rf dist-bundle diff --git a/packages/mcp-server/manifest.json b/packages/mcp-server/manifest.json new file mode 100644 index 00000000..dcee4d01 --- /dev/null +++ b/packages/mcp-server/manifest.json @@ -0,0 +1,42 @@ +{ + "dxt_version": "0.1", + "name": "@corgi-tech/beagle-mcp", + "version": "0.0.1-alpha.0", + "description": "The official MCP Server for the Beagle API", + "author": { + "name": "Beagle", + "email": "" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/corgi-tech/beagle-sdks.git" + }, + "homepage": "https://github.com/corgi-tech/beagle-sdks/tree/main/packages/mcp-server#readme", + "documentation": "", + "server": { + "type": "node", + "entry_point": "${__dirname}/index.js", + "mcp_config": { + "command": "node", + "args": ["${__dirname}/index.js"], + "env": { + "BEAGLE_API_KEY": "${user_config.BEAGLE_API_KEY}" + } + } + }, + "user_config": { + "BEAGLE_API_KEY": { + "title": "api_key", + "description": "", + "required": true, + "type": "string" + } + }, + "tools_generated": true, + "compatibility": { + "runtimes": { + "node": ">=18.0.0" + } + }, + "keywords": ["api"] +} diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index c3348883..7c6fc076 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -47,6 +47,7 @@ "mcp-server": "dist/index.js" }, "devDependencies": { + "@anthropic-ai/dxt": "^0.2.6", "@types/cors": "^2.8.19", "@types/express": "^5.0.3", "@types/jest": "^29.4.0", diff --git a/packages/mcp-server/scripts/copy-bundle-files.cjs b/packages/mcp-server/scripts/copy-bundle-files.cjs new file mode 100644 index 00000000..ac026dbd --- /dev/null +++ b/packages/mcp-server/scripts/copy-bundle-files.cjs @@ -0,0 +1,36 @@ +const fs = require('fs'); +const path = require('path'); +const pkgJson = require('../dist-bundle/package.json'); + +const distDir = path.resolve(__dirname, '..', 'dist'); +const distBundleDir = path.resolve(__dirname, '..', 'dist-bundle'); +const distBundlePkgJson = path.join(distBundleDir, 'package.json'); + +async function* walk(dir) { + for await (const d of await fs.promises.opendir(dir)) { + const entry = path.join(dir, d.name); + if (d.isDirectory()) yield* walk(entry); + else if (d.isFile()) yield entry; + } +} + +async function copyFiles() { + // copy runtime files + for await (const file of walk(distDir)) { + if (!/[cm]?js$/.test(file)) continue; + const dest = path.join(distBundleDir, path.relative(distDir, file)); + await fs.promises.mkdir(path.dirname(dest), { recursive: true }); + await fs.promises.copyFile(file, dest); + } + + // replace package.json reference with local reference + for (const dep in pkgJson.dependencies) { + if (dep === '@corgi-tech/beagle') { + pkgJson.dependencies[dep] = 'file:../../../dist/'; + } + } + + await fs.promises.writeFile(distBundlePkgJson, JSON.stringify(pkgJson, null, 2)); +} + +copyFiles(); diff --git a/packages/mcp-server/yarn.lock b/packages/mcp-server/yarn.lock index 707a2de8..ad819835 100644 --- a/packages/mcp-server/yarn.lock +++ b/packages/mcp-server/yarn.lock @@ -10,6 +10,20 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" +"@anthropic-ai/dxt@^0.2.6": + version "0.2.6" + resolved "https://registry.yarnpkg.com/@anthropic-ai/dxt/-/dxt-0.2.6.tgz#636197c3d083c9136ac3b5a11d2ba82477fdc2c6" + integrity sha512-5VSqKRpkytTYh5UJz9jOaI8zLXNCe4Gc+ArKGFV6IeWnEPP0Qnd0k+V3pO8cYzp92Puf/+Cgo0xc4haE0azTXg== + dependencies: + "@inquirer/prompts" "^6.0.1" + commander "^13.1.0" + fflate "^0.8.2" + galactus "^1.0.0" + ignore "^7.0.5" + node-forge "^1.3.1" + pretty-bytes "^5.6.0" + zod "^3.25.67" + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.27.1": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" @@ -336,6 +350,144 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== +"@inquirer/checkbox@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/checkbox/-/checkbox-3.0.1.tgz#0a57f704265f78c36e17f07e421b98efb4b9867b" + integrity sha512-0hm2nrToWUdD6/UHnel/UKGdk1//ke5zGUpHIvk5ZWmaKezlGxZkOJXNSWsdxO/rEqTkbB3lNC2J6nBElV2aAQ== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/figures" "^1.0.6" + "@inquirer/type" "^2.0.0" + ansi-escapes "^4.3.2" + yoctocolors-cjs "^2.1.2" + +"@inquirer/confirm@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-4.0.1.tgz#9106d6bffa0b2fdd0e4f60319b6f04f2e06e6e25" + integrity sha512-46yL28o2NJ9doViqOy0VDcoTzng7rAb6yPQKU7VDLqkmbCaH4JqK4yk4XqlzNWy9PVC5pG1ZUXPBQv+VqnYs2w== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/type" "^2.0.0" + +"@inquirer/core@^9.2.1": + version "9.2.1" + resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-9.2.1.tgz#677c49dee399c9063f31e0c93f0f37bddc67add1" + integrity sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg== + dependencies: + "@inquirer/figures" "^1.0.6" + "@inquirer/type" "^2.0.0" + "@types/mute-stream" "^0.0.4" + "@types/node" "^22.5.5" + "@types/wrap-ansi" "^3.0.0" + ansi-escapes "^4.3.2" + cli-width "^4.1.0" + mute-stream "^1.0.0" + signal-exit "^4.1.0" + strip-ansi "^6.0.1" + wrap-ansi "^6.2.0" + yoctocolors-cjs "^2.1.2" + +"@inquirer/editor@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/editor/-/editor-3.0.1.tgz#d109f21e050af6b960725388cb1c04214ed7c7bc" + integrity sha512-VA96GPFaSOVudjKFraokEEmUQg/Lub6OXvbIEZU1SDCmBzRkHGhxoFAVaF30nyiB4m5cEbDgiI2QRacXZ2hw9Q== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/type" "^2.0.0" + external-editor "^3.1.0" + +"@inquirer/expand@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/expand/-/expand-3.0.1.tgz#aed9183cac4d12811be47a4a895ea8e82a17e22c" + integrity sha512-ToG8d6RIbnVpbdPdiN7BCxZGiHOTomOX94C2FaT5KOHupV40tKEDozp12res6cMIfRKrXLJyexAZhWVHgbALSQ== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/type" "^2.0.0" + yoctocolors-cjs "^2.1.2" + +"@inquirer/figures@^1.0.6": + version "1.0.13" + resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.13.tgz#ad0afd62baab1c23175115a9b62f511b6a751e45" + integrity sha512-lGPVU3yO9ZNqA7vTYz26jny41lE7yoQansmqdMLBEfqaGsmdg7V3W9mK9Pvb5IL4EVZ9GnSDGMO/cJXud5dMaw== + +"@inquirer/input@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/input/-/input-3.0.1.tgz#de63d49e516487388508d42049deb70f2cb5f28e" + integrity sha512-BDuPBmpvi8eMCxqC5iacloWqv+5tQSJlUafYWUe31ow1BVXjW2a5qe3dh4X/Z25Wp22RwvcaLCc2siHobEOfzg== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/type" "^2.0.0" + +"@inquirer/number@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/number/-/number-2.0.1.tgz#b9863080d02ab7dc2e56e16433d83abea0f2a980" + integrity sha512-QpR8jPhRjSmlr/mD2cw3IR8HRO7lSVOnqUvQa8scv1Lsr3xoAMMworcYW3J13z3ppjBFBD2ef1Ci6AE5Qn8goQ== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/type" "^2.0.0" + +"@inquirer/password@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/password/-/password-3.0.1.tgz#2a9a9143591088336bbd573bcb05d5bf080dbf87" + integrity sha512-haoeEPUisD1NeE2IanLOiFr4wcTXGWrBOyAyPZi1FfLJuXOzNmxCJPgUrGYKVh+Y8hfGJenIfz5Wb/DkE9KkMQ== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/type" "^2.0.0" + ansi-escapes "^4.3.2" + +"@inquirer/prompts@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/prompts/-/prompts-6.0.1.tgz#43f5c0ed35c5ebfe52f1d43d46da2d363d950071" + integrity sha512-yl43JD/86CIj3Mz5mvvLJqAOfIup7ncxfJ0Btnl0/v5TouVUyeEdcpknfgc+yMevS/48oH9WAkkw93m7otLb/A== + dependencies: + "@inquirer/checkbox" "^3.0.1" + "@inquirer/confirm" "^4.0.1" + "@inquirer/editor" "^3.0.1" + "@inquirer/expand" "^3.0.1" + "@inquirer/input" "^3.0.1" + "@inquirer/number" "^2.0.1" + "@inquirer/password" "^3.0.1" + "@inquirer/rawlist" "^3.0.1" + "@inquirer/search" "^2.0.1" + "@inquirer/select" "^3.0.1" + +"@inquirer/rawlist@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/rawlist/-/rawlist-3.0.1.tgz#729def358419cc929045f264131878ed379e0af3" + integrity sha512-VgRtFIwZInUzTiPLSfDXK5jLrnpkuSOh1ctfaoygKAdPqjcjKYmGh6sCY1pb0aGnCGsmhUxoqLDUAU0ud+lGXQ== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/type" "^2.0.0" + yoctocolors-cjs "^2.1.2" + +"@inquirer/search@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/search/-/search-2.0.1.tgz#69b774a0a826de2e27b48981d01bc5ad81e73721" + integrity sha512-r5hBKZk3g5MkIzLVoSgE4evypGqtOannnB3PKTG9NRZxyFRKcfzrdxXXPcoJQsxJPzvdSU2Rn7pB7lw0GCmGAg== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/figures" "^1.0.6" + "@inquirer/type" "^2.0.0" + yoctocolors-cjs "^2.1.2" + +"@inquirer/select@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/select/-/select-3.0.1.tgz#1df9ed27fb85a5f526d559ac5ce7cc4e9dc4e7ec" + integrity sha512-lUDGUxPhdWMkN/fHy1Lk7pF3nK1fh/gqeyWXmctefhxLYxlDsc7vsPBEpxrfVGDsVdyYJsiJoD4bJ1b623cV1Q== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/figures" "^1.0.6" + "@inquirer/type" "^2.0.0" + ansi-escapes "^4.3.2" + yoctocolors-cjs "^2.1.2" + +"@inquirer/type@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-2.0.0.tgz#08fa513dca2cb6264fe1b0a2fabade051444e3f6" + integrity sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag== + dependencies: + mute-stream "^1.0.0" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -725,6 +877,13 @@ dependencies: "@types/node" "*" +"@types/cors@^2.8.19": + version "2.8.19" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.19.tgz#d93ea2673fd8c9f697367f5eeefc2bbfa94f0342" + integrity sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg== + dependencies: + "@types/node" "*" + "@types/express-serve-static-core@^5.0.0": version "5.0.7" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz#2fa94879c9d46b11a5df4c74ac75befd6b283de6" @@ -788,6 +947,13 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== +"@types/mute-stream@^0.0.4": + version "0.0.4" + resolved "https://registry.yarnpkg.com/@types/mute-stream/-/mute-stream-0.0.4.tgz#77208e56a08767af6c5e1237be8888e2f255c478" + integrity sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow== + dependencies: + "@types/node" "*" + "@types/node@*": version "22.15.17" resolved "https://registry.yarnpkg.com/@types/node/-/node-22.15.17.tgz#355ccec95f705b664e4332bb64a7f07db30b7055" @@ -795,7 +961,14 @@ dependencies: undici-types "~6.21.0" -"@types/qs@*": +"@types/node@^22.5.5": + version "22.18.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.18.0.tgz#9e4709be4f104e3568f7dd1c71e2949bf147a47b" + integrity sha512-m5ObIqwsUp6BZzyiy4RdZpzWGub9bqLJMvZDD0QMXhxjqMHMENlj+SqF5QxoUwaQNFe+8kz8XM8ZQhqkQPTgMQ== + dependencies: + undici-types "~6.21.0" + +"@types/qs@*", "@types/qs@^6.14.0": version "6.14.0" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.14.0.tgz#d8b60cecf62f2db0fb68e5e006077b9178b85de5" integrity sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ== @@ -827,6 +1000,11 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== +"@types/wrap-ansi@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz#18b97a972f94f60a679fd5c796d96421b9abb9fd" + integrity sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g== + "@types/yargs-parser@*": version "21.0.3" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" @@ -925,6 +1103,11 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== +"@valtown/deno-http-worker@^0.0.21": + version "0.0.21" + resolved "https://registry.yarnpkg.com/@valtown/deno-http-worker/-/deno-http-worker-0.0.21.tgz#9ce3b5c1d0db211fe7ea8297881fe551838474ad" + integrity sha512-16kFuUykann75lNytnXXIQlmpzreZjzdyT27ebT3yNGCS3kKaS1iZYWHc3Si9An54Cphwr4qEcviChQkEeJBlA== + accepts@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/accepts/-/accepts-2.0.0.tgz#bbcf4ba5075467f3f2131eab3cffc73c2f5d7895" @@ -968,7 +1151,7 @@ ajv@^6.12.4, ajv@^6.12.6: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ansi-escapes@^4.2.1: +ansi-escapes@^4.2.1, ansi-escapes@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== @@ -1210,6 +1393,11 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + ci-info@^3.2.0: version "3.9.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" @@ -1225,6 +1413,11 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +cli-width@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5" + integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ== + cliui@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" @@ -1261,6 +1454,11 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +commander@^13.1.0: + version "13.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-13.1.0.tgz#776167db68c78f38dcce1f9b8d7b8b9a488abf46" + integrity sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1673,6 +1871,15 @@ express@^5.0.1, express@^5.1.0: type-is "^2.0.1" vary "^1.1.2" +external-editor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -1718,6 +1925,11 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +fflate@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" + integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -1781,6 +1993,14 @@ flatted@^3.2.9: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== +flora-colossus@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/flora-colossus/-/flora-colossus-2.0.0.tgz#af1e85db0a8256ef05f3fb531c1235236c97220a" + integrity sha512-dz4HxH6pOvbUzZpZ/yXhafjbR2I8cenK5xL0KtBFb7U2ADsR+OwXifnxZjij/pZWF775uSCMzWVd+jDik2H2IA== + dependencies: + debug "^4.3.4" + fs-extra "^10.1.0" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -1791,6 +2011,15 @@ fresh@^2.0.0: resolved "https://registry.yarnpkg.com/fresh/-/fresh-2.0.0.tgz#8dd7df6a1b3a1b3a5cf186c05a5dd267622635a4" integrity sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A== +fs-extra@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -1806,6 +2035,15 @@ function-bind@^1.1.2: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== +galactus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/galactus/-/galactus-1.0.0.tgz#c2615182afa0c6d0859b92e56ae36d052827db7e" + integrity sha512-R1fam6D4CyKQGNlvJne4dkNF+PvUUl7TAJInvTGa9fti9qAv95quQz29GXapA4d8Ec266mJJxFVh82M4GIIGDQ== + dependencies: + debug "^4.3.4" + flora-colossus "^2.0.0" + fs-extra "^10.1.0" + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -1898,7 +2136,7 @@ gopd@^1.2.0: resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== -graceful-fs@^4.2.9: +graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -1953,11 +2191,23 @@ iconv-lite@0.6.3, iconv-lite@^0.6.3: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" +iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + ignore@^5.2.0, ignore@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== +ignore@^7.0.5: + version "7.0.5" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9" + integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg== + import-fresh@^3.2.1: version "3.3.1" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" @@ -2536,6 +2786,15 @@ json5@^2.2.2, json5@^2.2.3: resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== +jsonfile@^6.0.1: + version "6.2.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.2.0.tgz#7c265bd1b65de6977478300087c99f1c84383f62" + integrity sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -2709,6 +2968,11 @@ ms@^2.1.3: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +mute-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e" + integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -2719,6 +2983,11 @@ negotiator@^1.0.0: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a" integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg== +node-forge@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -2784,6 +3053,11 @@ optionator@^0.9.3: type-check "^0.4.0" word-wrap "^1.2.5" +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + p-all@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-all/-/p-all-3.0.0.tgz#077c023c37e75e760193badab2bad3ccd5782bfb" @@ -2927,6 +3201,11 @@ prettier@^3.0.0: resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.5.3.tgz#4fc2ce0d657e7a02e602549f053b239cb7dfe1b5" integrity sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw== +pretty-bytes@^5.6.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" + integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== + pretty-format@^29.0.0, pretty-format@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" @@ -3074,7 +3353,7 @@ safe-buffer@5.2.1, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -"safer-buffer@>= 2.1.2 < 3.0.0": +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -3178,6 +3457,11 @@ signal-exit@^3.0.3, signal-exit@^3.0.7: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +signal-exit@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -3322,6 +3606,13 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" @@ -3387,9 +3678,9 @@ ts-node@^10.5.0: v8-compile-cache-lib "^3.0.1" yn "3.1.1" -"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz": - version "1.1.8" - resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz#f544b359b8f05e607771ffacc280e58201476b04" +"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz": + version "1.1.9" + resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz#777f6f5d9e26bf0e94e5170990dd3a841d6707cd" dependencies: debug "^4.3.7" fast-glob "^3.3.2" @@ -3462,6 +3753,11 @@ undici-types@~6.21.0: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + unpipe@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -3525,6 +3821,15 @@ word-wrap@^1.2.5: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -3585,6 +3890,11 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +yoctocolors-cjs@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz#7e4964ea8ec422b7a40ac917d3a344cfd2304baa" + integrity sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw== + zod-to-json-schema@^3.24.1, zod-to-json-schema@^3.24.5: version "3.24.5" resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz#d1095440b147fb7c2093812a53c54df8d5df50a3" @@ -3600,7 +3910,7 @@ zod@^3.23.8: resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.4.tgz#e2e2cca5faaa012d76e527d0d36622e0a90c315f" integrity sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg== -zod@^3.25.20: +zod@^3.25.20, zod@^3.25.67: version "3.25.76" resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.76.tgz#26841c3f6fd22a6a2760e7ccb719179768471e34" integrity sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ== From c24a15020445287f2bbbc840d0cd5367079a8587 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 6 Sep 2025 05:07:10 +0000 Subject: [PATCH 051/138] chore: ci build action --- .github/workflows/ci.yml | 2 +- scripts/utils/upload-artifact.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f57f1b40..19c17968 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,7 +75,7 @@ jobs: URL: https://pkg.stainless.com/s?subpackage=mcp-server AUTH: ${{ steps.github-oidc.outputs.github_token }} SHA: ${{ github.sha }} - BUILD_PATH: packages/mcp-server/dist + BASE_PATH: packages/mcp-server run: ./scripts/utils/upload-artifact.sh test: timeout-minutes: 10 diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh index 2f43c9d1..8d2f68c3 100755 --- a/scripts/utils/upload-artifact.sh +++ b/scripts/utils/upload-artifact.sh @@ -12,7 +12,7 @@ if [[ "$SIGNED_URL" == "null" ]]; then exit 1 fi -UPLOAD_RESPONSE=$(tar -cz "${BUILD_PATH:-dist}" | curl -v -X PUT \ +UPLOAD_RESPONSE=$(tar "${BASE_PATH:+-C$BASE_PATH}" -cz "${ARTIFACT_PATH:-dist}" | curl -v -X PUT \ -H "Content-Type: application/gzip" \ --data-binary @- "$SIGNED_URL" 2>&1) From 98aac60cf6ad782f8fd720d59e4edf8938409eb5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 6 Sep 2025 05:22:41 +0000 Subject: [PATCH 052/138] chore(internal): codegen related update --- packages/mcp-server/src/options.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index 2100cf58..ecc9f10e 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -367,12 +367,12 @@ export function parseQueryOptions(defaultOptions: McpOptions, query: unknown): M } let dynamicTools: boolean | undefined = - queryOptions.no_tools && !queryOptions.no_tools?.includes('dynamic') ? false + queryOptions.no_tools && queryOptions.no_tools?.includes('dynamic') ? false : queryOptions.tools?.includes('dynamic') ? true : defaultOptions.includeDynamicTools; let allTools: boolean | undefined = - queryOptions.no_tools && !queryOptions.no_tools?.includes('all') ? false + queryOptions.no_tools && queryOptions.no_tools?.includes('all') ? false : queryOptions.tools?.includes('all') ? true : defaultOptions.includeAllTools; From 6700d42958cc9db8ce4e13667d6e960b035a813c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 23 Oct 2025 02:27:22 +0000 Subject: [PATCH 053/138] feat(api): api update --- .github/workflows/publish-npm.yml | 9 + .gitignore | 3 +- .stats.yml | 4 +- packages/mcp-server/build | 6 +- packages/mcp-server/manifest.json | 9 +- packages/mcp-server/package.json | 2 +- packages/mcp-server/src/docs-search-tool.ts | 48 +++ packages/mcp-server/src/options.ts | 24 +- packages/mcp-server/src/server.ts | 11 +- .../tools/enrollments/create-enrollments.ts | 15 +- .../verify-insurance-verification.ts | 2 +- .../mcp-server/src/tools/plans/list-plans.ts | 2 +- .../endpoints/create-webhook-endpoints.ts | 2 +- .../endpoints/list-webhook-endpoints.ts | 2 +- .../endpoints/retrieve-webhook-endpoints.ts | 2 +- .../endpoints/update-webhook-endpoints.ts | 2 +- packages/mcp-server/tsconfig.build.json | 4 +- packages/mcp-server/tsconfig.json | 5 +- packages/mcp-server/yarn.lock | 306 +----------------- scripts/bootstrap | 14 +- scripts/fast-format | 40 +++ scripts/utils/upload-artifact.sh | 6 +- src/core/pagination.ts | 8 +- src/internal/to-file.ts | 2 +- src/internal/utils/values.ts | 6 +- src/resources/enrollments.ts | 10 + tests/api-resources/enrollments.test.ts | 2 + tsconfig.build.json | 4 +- tsconfig.json | 5 +- 29 files changed, 200 insertions(+), 355 deletions(-) create mode 100644 packages/mcp-server/src/docs-search-tool.ts create mode 100755 scripts/fast-format diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 0f09c9c4..5053ad90 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -16,6 +16,8 @@ jobs: publish: name: publish runs-on: ubuntu-latest + permissions: + contents: write steps: - uses: actions/checkout@v4 @@ -39,3 +41,10 @@ jobs: yarn tsn scripts/publish-packages.ts "{ \"paths_released\": \"$PATHS_RELEASED\" }" env: NPM_TOKEN: ${{ secrets.BEAGLE_NPM_TOKEN || secrets.NPM_TOKEN }} + + - name: Upload MCP Server DXT GitHub release asset + run: | + gh release upload ${{ github.event.release.tag_name }} \ + packages/mcp-server/corgi_tech_beagle_api.mcpb + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 4b27d0fc..d62bea50 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,6 @@ dist dist-deno /*.tgz .idea/ +.eslintcache dist-bundle -*.dxt +*.mcpb diff --git a/.stats.yml b/.stats.yml index ae201744..5781b246 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 23 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-3a87a1cacdb259999db9faee3bf96e2533b58fac685f572be8fc99b154941403.yml -openapi_spec_hash: 212fb2066535de06799c12a5d5096ee5 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-e02fb0cc53e6898f4a4a265645714517d5df273782e178a0221d5f6afdfecf6a.yml +openapi_spec_hash: acfb45a1223d482c5c48164bb1365959 config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/packages/mcp-server/build b/packages/mcp-server/build index c6837d3b..5dfe5145 100644 --- a/packages/mcp-server/build +++ b/packages/mcp-server/build @@ -32,7 +32,7 @@ chmod +x dist/index.js DIST_PATH=./dist PKG_IMPORT_PATH=@corgi-tech/beagle-mcp/ node ../../scripts/utils/postprocess-files.cjs # mcp bundle -rm -rf dist-bundle corgi_tech_beagle_api.dxt; mkdir dist-bundle +rm -rf dist-bundle corgi_tech_beagle_api.mcpb; mkdir dist-bundle # copy package.json PKG_JSON_PATH=../../packages/mcp-server/package.json node ../../scripts/utils/make-dist-package-json.cjs > dist-bundle/package.json @@ -48,9 +48,9 @@ cd .. # pack bundle cp manifest.json dist-bundle -npx dxt pack dist-bundle corgi_tech_beagle_api.dxt +npx mcpb pack dist-bundle corgi_tech_beagle_api.mcpb -npx dxt sign corgi_tech_beagle_api.dxt --self-signed +npx mcpb sign corgi_tech_beagle_api.mcpb --self-signed # clean up rm -rf dist-bundle diff --git a/packages/mcp-server/manifest.json b/packages/mcp-server/manifest.json index dcee4d01..02df4f75 100644 --- a/packages/mcp-server/manifest.json +++ b/packages/mcp-server/manifest.json @@ -1,21 +1,19 @@ { - "dxt_version": "0.1", + "dxt_version": "0.2", "name": "@corgi-tech/beagle-mcp", "version": "0.0.1-alpha.0", "description": "The official MCP Server for the Beagle API", "author": { - "name": "Beagle", - "email": "" + "name": "Beagle" }, "repository": { "type": "git", "url": "git+https://github.com/corgi-tech/beagle-sdks.git" }, "homepage": "https://github.com/corgi-tech/beagle-sdks/tree/main/packages/mcp-server#readme", - "documentation": "", "server": { "type": "node", - "entry_point": "${__dirname}/index.js", + "entry_point": "index.js", "mcp_config": { "command": "node", "args": ["${__dirname}/index.js"], @@ -32,6 +30,7 @@ "type": "string" } }, + "tools": [], "tools_generated": true, "compatibility": { "runtimes": { diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 7c6fc076..06aafbc8 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -47,7 +47,7 @@ "mcp-server": "dist/index.js" }, "devDependencies": { - "@anthropic-ai/dxt": "^0.2.6", + "@anthropic-ai/mcpb": "^1.1.0", "@types/cors": "^2.8.19", "@types/express": "^5.0.3", "@types/jest": "^29.4.0", diff --git a/packages/mcp-server/src/docs-search-tool.ts b/packages/mcp-server/src/docs-search-tool.ts new file mode 100644 index 00000000..dca82a8e --- /dev/null +++ b/packages/mcp-server/src/docs-search-tool.ts @@ -0,0 +1,48 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { Metadata, asTextContentResult } from './tools/types'; + +import { Tool } from '@modelcontextprotocol/sdk/types.js'; + +export const metadata: Metadata = { + resource: 'all', + operation: 'read', + tags: [], + httpMethod: 'get', +}; + +export const tool: Tool = { + name: 'search_docs', + description: + 'Search for documentation for how to use the client to interact with the API.\nThe tool will return an array of Markdown-formatted documentation pages.', + inputSchema: { + type: 'object', + properties: { + query: { + type: 'string', + description: 'The query to search for.', + }, + language: { + type: 'string', + description: 'The language for the SDK to search for.', + enum: ['http', 'python', 'go', 'typescript', 'terraform', 'ruby', 'java', 'kotlin'], + }, + }, + required: ['query', 'language'], + }, + annotations: { + readOnlyHint: true, + }, +}; + +const docsSearchURL = + process.env['DOCS_SEARCH_URL'] || 'https://api.stainless.com/api/projects/beagle/docs/search'; + +export const handler = async (_: unknown, args: Record | undefined) => { + const body = args as any; + const query = new URLSearchParams(body).toString(); + const result = await fetch(`${docsSearchURL}?${query}`); + return asTextContentResult(await result.json()); +}; + +export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index ecc9f10e..4fe3b987 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -17,6 +17,7 @@ export type McpOptions = { includeDynamicTools?: boolean | undefined; includeAllTools?: boolean | undefined; includeCodeTools?: boolean | undefined; + includeDocsTools?: boolean | undefined; filters?: Filter[] | undefined; capabilities?: Partial | undefined; }; @@ -55,13 +56,13 @@ export function parseCLIOptions(): CLIOptions { .option('tools', { type: 'string', array: true, - choices: ['dynamic', 'all', 'code'], + choices: ['dynamic', 'all', 'code', 'docs'], description: 'Use dynamic tools or all tools', }) .option('no-tools', { type: 'string', array: true, - choices: ['dynamic', 'all', 'code'], + choices: ['dynamic', 'all', 'code', 'docs'], description: 'Do not use any dynamic or all tools', }) .option('tool', { @@ -245,13 +246,15 @@ export function parseCLIOptions(): CLIOptions { } } - const shouldIncludeToolType = (toolType: 'dynamic' | 'all' | 'code') => - explicitTools ? argv.tools?.includes(toolType) && !argv.noTools?.includes(toolType) : undefined; + const shouldIncludeToolType = (toolType: 'dynamic' | 'all' | 'code' | 'docs') => + argv.noTools?.includes(toolType) ? false + : argv.tools?.includes(toolType) ? true + : undefined; - const explicitTools = Boolean(argv.tools || argv.noTools); const includeDynamicTools = shouldIncludeToolType('dynamic'); const includeAllTools = shouldIncludeToolType('all'); const includeCodeTools = shouldIncludeToolType('code'); + const includeDocsTools = shouldIncludeToolType('docs'); const transport = argv.transport as 'stdio' | 'http'; @@ -261,6 +264,7 @@ export function parseCLIOptions(): CLIOptions { includeDynamicTools, includeAllTools, includeCodeTools, + includeDocsTools, filters, capabilities: clientCapabilities, list: argv.list || false, @@ -280,8 +284,8 @@ const coerceArray = (zodType: T) => ); const QueryOptions = z.object({ - tools: coerceArray(z.enum(['dynamic', 'all'])).describe('Use dynamic tools or all tools'), - no_tools: coerceArray(z.enum(['dynamic', 'all'])).describe('Do not use dynamic tools or all tools'), + tools: coerceArray(z.enum(['dynamic', 'all', 'docs'])).describe('Use dynamic tools or all tools'), + no_tools: coerceArray(z.enum(['dynamic', 'all', 'docs'])).describe('Do not use dynamic tools or all tools'), tool: coerceArray(z.string()).describe('Include tools matching the specified names'), resource: coerceArray(z.string()).describe('Include tools matching the specified resources'), operation: coerceArray(z.enum(['read', 'write'])).describe( @@ -376,11 +380,17 @@ export function parseQueryOptions(defaultOptions: McpOptions, query: unknown): M : queryOptions.tools?.includes('all') ? true : defaultOptions.includeAllTools; + let docsTools: boolean | undefined = + queryOptions.no_tools && queryOptions.no_tools?.includes('docs') ? false + : queryOptions.tools?.includes('docs') ? true + : defaultOptions.includeDocsTools; + return { client: queryOptions.client ?? defaultOptions.client, includeDynamicTools: dynamicTools, includeAllTools: allTools, includeCodeTools: undefined, + includeDocsTools: docsTools, filters, capabilities: clientCapabilities, }; diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index b39e21ef..b2452cf4 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -21,6 +21,7 @@ import { } from './compat'; import { dynamicTools } from './dynamic-tools'; import { codeTool } from './code-tool'; +import docsSearchTool from './docs-search-tool'; import { McpOptions } from './options'; export { McpOptions } from './options'; @@ -148,7 +149,7 @@ export function initMcpServer(params: { export async function selectTools(endpoints: Endpoint[], options?: McpOptions): Promise { const filteredEndpoints = query(options?.filters ?? [], endpoints); - let includedTools = filteredEndpoints; + let includedTools = filteredEndpoints.slice(); if (includedTools.length > 0) { if (options?.includeDynamicTools) { @@ -156,16 +157,18 @@ export async function selectTools(endpoints: Endpoint[], options?: McpOptions): } } else { if (options?.includeAllTools) { - includedTools = endpoints; + includedTools = endpoints.slice(); } else if (options?.includeDynamicTools) { includedTools = dynamicTools(endpoints); } else if (options?.includeCodeTools) { includedTools = [await codeTool()]; } else { - includedTools = endpoints; + includedTools = endpoints.slice(); } } - + if (options?.includeDocsTools ?? true) { + includedTools.push(docsSearchTool); + } const capabilities = { ...defaultClientCapabilities, ...options?.capabilities }; return applyCompatibilityTransformations(includedTools, capabilities); } diff --git a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts index e46d0271..734b1654 100644 --- a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts @@ -33,6 +33,19 @@ export const tool: Tool = { propertyManagerId: { type: 'number', }, + status: { + type: 'string', + enum: [ + 'Premium Paying', + 'Issued, Not Paid', + 'Expired', + 'Lapsed', + 'Suspended', + 'Cancelled', + 'Not taken', + 'Declined', + ], + }, tenantId: { type: 'number', }, @@ -47,7 +60,7 @@ export const tool: Tool = { 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', }, }, - required: ['effectiveDate', 'plan', 'propertyManagerId', 'tenantId'], + required: ['effectiveDate', 'plan', 'propertyManagerId', 'status', 'tenantId'], }, annotations: {}, }; diff --git a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts index 1ac13afb..21185cf8 100644 --- a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts +++ b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'verify_insurance_verification', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ntrigger a job to parse a tenants insurance document(s)\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n message: {\n type: 'string',\n enum: [ 'insurance verification job scheduled'\n ]\n }\n },\n required: [ 'message'\n ]\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ntrigger a job to parse a tenants insurance document(s)\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/insurance_verification_verify_response',\n $defs: {\n insurance_verification_verify_response: {\n type: 'object',\n properties: {\n message: {\n type: 'string',\n enum: [ 'insurance verification job scheduled'\n ]\n }\n },\n required: [ 'message'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { diff --git a/packages/mcp-server/src/tools/plans/list-plans.ts b/packages/mcp-server/src/tools/plans/list-plans.ts index 490892e1..6f672500 100644 --- a/packages/mcp-server/src/tools/plans/list-plans.ts +++ b/packages/mcp-server/src/tools/plans/list-plans.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'list_plans', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlist all available plans, note this endpoint is currently unpaginated unlike all other list endpoints.\n\n# Response Schema\n```json\n{\n type: 'array',\n items: {\n $ref: '#/$defs/plan'\n },\n $defs: {\n plan: {\n type: 'object',\n properties: {\n description: {\n type: 'string'\n },\n name: {\n type: 'string',\n description: 'the plans name/code, this is used when creating enrollments.'\n },\n rate: {\n type: 'number',\n description: 'the price of the plan'\n },\n contents: {\n type: 'number',\n description: 'value of contents replacement, note this is only on some TLL plans.'\n },\n liability: {\n type: 'number',\n description: 'value of liability waived, note this is only on TLL plans.'\n },\n value: {\n type: 'number',\n description: 'general value field, this is currently used for SDR and SDD plans for the replacement or discount value.'\n }\n },\n required: [ 'description',\n 'name',\n 'rate'\n ]\n }\n }\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlist all available plans, note this endpoint is currently unpaginated unlike all other list endpoints.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/plan_list_response',\n $defs: {\n plan_list_response: {\n type: 'array',\n items: {\n $ref: '#/$defs/plan'\n }\n },\n plan: {\n type: 'object',\n properties: {\n description: {\n type: 'string'\n },\n name: {\n type: 'string',\n description: 'the plans name/code, this is used when creating enrollments.'\n },\n rate: {\n type: 'number',\n description: 'the price of the plan'\n },\n contents: {\n type: 'number',\n description: 'value of contents replacement, note this is only on some TLL plans.'\n },\n liability: {\n type: 'number',\n description: 'value of liability waived, note this is only on TLL plans.'\n },\n value: {\n type: 'number',\n description: 'general value field, this is currently used for SDR and SDD plans for the replacement or discount value.'\n }\n },\n required: [ 'description',\n 'name',\n 'rate'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { diff --git a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts index f3054b7d..e65f1d13 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'create_webhook_endpoints', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ncreates a new webhook target.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n active: {\n type: 'boolean'\n },\n companyId: {\n type: 'number'\n },\n createdAt: {\n type: 'string'\n },\n updatedAt: {\n type: 'string'\n },\n url: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'active',\n 'companyId',\n 'createdAt',\n 'updatedAt',\n 'url'\n ]\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ncreates a new webhook target.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/endpoint_create_response',\n $defs: {\n endpoint_create_response: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n active: {\n type: 'boolean'\n },\n companyId: {\n type: 'number'\n },\n createdAt: {\n type: 'string'\n },\n updatedAt: {\n type: 'string'\n },\n url: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'active',\n 'companyId',\n 'createdAt',\n 'updatedAt',\n 'url'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { diff --git a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts index 903dfe03..3a5936ad 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'list_webhook_endpoints', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlist all webhook endpoints, this endpoint is paginated and allows for queries by individual property manager.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n endpoints: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n active: {\n type: 'boolean'\n },\n companyId: {\n type: 'number'\n },\n createdAt: {\n type: 'string'\n },\n updatedAt: {\n type: 'string'\n },\n url: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'active',\n 'companyId',\n 'createdAt',\n 'updatedAt',\n 'url'\n ]\n }\n },\n pagination: {\n $ref: '#/$defs/pagination'\n }\n },\n required: [ 'endpoints',\n 'pagination'\n ],\n $defs: {\n pagination: {\n type: 'object',\n properties: {\n page: {\n type: 'number',\n description: 'Current page number.'\n },\n pages: {\n type: 'number',\n description: 'Total number of pages.'\n },\n records: {\n type: 'number',\n description: 'Total number of records.'\n },\n size: {\n type: 'number',\n description: 'Number of items per page.'\n }\n },\n required: [ 'page',\n 'pages',\n 'records',\n 'size'\n ]\n }\n }\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlist all webhook endpoints, this endpoint is paginated and allows for queries by individual property manager.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n endpoints: {\n type: 'array',\n items: {\n $ref: '#/$defs/endpoint_list_response'\n }\n },\n pagination: {\n $ref: '#/$defs/pagination'\n }\n },\n required: [ 'endpoints',\n 'pagination'\n ],\n $defs: {\n endpoint_list_response: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n active: {\n type: 'boolean'\n },\n companyId: {\n type: 'number'\n },\n createdAt: {\n type: 'string'\n },\n updatedAt: {\n type: 'string'\n },\n url: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'active',\n 'companyId',\n 'createdAt',\n 'updatedAt',\n 'url'\n ]\n },\n pagination: {\n type: 'object',\n properties: {\n page: {\n type: 'number',\n description: 'Current page number.'\n },\n pages: {\n type: 'number',\n description: 'Total number of pages.'\n },\n records: {\n type: 'number',\n description: 'Total number of records.'\n },\n size: {\n type: 'number',\n description: 'Number of items per page.'\n }\n },\n required: [ 'page',\n 'pages',\n 'records',\n 'size'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { diff --git a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts index 9257bc58..794fbdf9 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'retrieve_webhook_endpoints', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nretrieve a single webhook endpoint by its id.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n active: {\n type: 'boolean'\n },\n companyId: {\n type: 'number'\n },\n createdAt: {\n type: 'string'\n },\n updatedAt: {\n type: 'string'\n },\n url: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'active',\n 'companyId',\n 'createdAt',\n 'updatedAt',\n 'url'\n ]\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nretrieve a single webhook endpoint by its id.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/endpoint_retrieve_response',\n $defs: {\n endpoint_retrieve_response: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n active: {\n type: 'boolean'\n },\n companyId: {\n type: 'number'\n },\n createdAt: {\n type: 'string'\n },\n updatedAt: {\n type: 'string'\n },\n url: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'active',\n 'companyId',\n 'createdAt',\n 'updatedAt',\n 'url'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { diff --git a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts index b60f4862..fe0f3777 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'update_webhook_endpoints', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nupdate an existing webhook endpoint by its id.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n active: {\n type: 'boolean'\n },\n companyId: {\n type: 'number'\n },\n createdAt: {\n type: 'string'\n },\n updatedAt: {\n type: 'string'\n },\n url: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'active',\n 'companyId',\n 'createdAt',\n 'updatedAt',\n 'url'\n ]\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nupdate an existing webhook endpoint by its id.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/endpoint_update_response',\n $defs: {\n endpoint_update_response: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n active: {\n type: 'boolean'\n },\n companyId: {\n type: 'number'\n },\n createdAt: {\n type: 'string'\n },\n updatedAt: {\n type: 'string'\n },\n url: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'active',\n 'companyId',\n 'createdAt',\n 'updatedAt',\n 'url'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { diff --git a/packages/mcp-server/tsconfig.build.json b/packages/mcp-server/tsconfig.build.json index 9c01cf3c..544c7ddf 100644 --- a/packages/mcp-server/tsconfig.build.json +++ b/packages/mcp-server/tsconfig.build.json @@ -5,8 +5,8 @@ "compilerOptions": { "rootDir": "./dist/src", "paths": { - "@corgi-tech/beagle-mcp/*": ["dist/src/*"], - "@corgi-tech/beagle-mcp": ["dist/src/index.ts"] + "@corgi-tech/beagle-mcp/*": ["./dist/src/*"], + "@corgi-tech/beagle-mcp": ["./dist/src/index.ts"] }, "noEmit": false, "declaration": true, diff --git a/packages/mcp-server/tsconfig.json b/packages/mcp-server/tsconfig.json index 663ec745..ee8fd2fe 100644 --- a/packages/mcp-server/tsconfig.json +++ b/packages/mcp-server/tsconfig.json @@ -7,10 +7,9 @@ "module": "commonjs", "moduleResolution": "node", "esModuleInterop": true, - "baseUrl": "./", "paths": { - "@corgi-tech/beagle-mcp/*": ["src/*"], - "@corgi-tech/beagle-mcp": ["src/index.ts"] + "@corgi-tech/beagle-mcp/*": ["./src/*"], + "@corgi-tech/beagle-mcp": ["./src/index.ts"] }, "noEmit": true, diff --git a/packages/mcp-server/yarn.lock b/packages/mcp-server/yarn.lock index ad819835..966d0575 100644 --- a/packages/mcp-server/yarn.lock +++ b/packages/mcp-server/yarn.lock @@ -10,20 +10,6 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" -"@anthropic-ai/dxt@^0.2.6": - version "0.2.6" - resolved "https://registry.yarnpkg.com/@anthropic-ai/dxt/-/dxt-0.2.6.tgz#636197c3d083c9136ac3b5a11d2ba82477fdc2c6" - integrity sha512-5VSqKRpkytTYh5UJz9jOaI8zLXNCe4Gc+ArKGFV6IeWnEPP0Qnd0k+V3pO8cYzp92Puf/+Cgo0xc4haE0azTXg== - dependencies: - "@inquirer/prompts" "^6.0.1" - commander "^13.1.0" - fflate "^0.8.2" - galactus "^1.0.0" - ignore "^7.0.5" - node-forge "^1.3.1" - pretty-bytes "^5.6.0" - zod "^3.25.67" - "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.27.1": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" @@ -350,144 +336,6 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== -"@inquirer/checkbox@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@inquirer/checkbox/-/checkbox-3.0.1.tgz#0a57f704265f78c36e17f07e421b98efb4b9867b" - integrity sha512-0hm2nrToWUdD6/UHnel/UKGdk1//ke5zGUpHIvk5ZWmaKezlGxZkOJXNSWsdxO/rEqTkbB3lNC2J6nBElV2aAQ== - dependencies: - "@inquirer/core" "^9.2.1" - "@inquirer/figures" "^1.0.6" - "@inquirer/type" "^2.0.0" - ansi-escapes "^4.3.2" - yoctocolors-cjs "^2.1.2" - -"@inquirer/confirm@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-4.0.1.tgz#9106d6bffa0b2fdd0e4f60319b6f04f2e06e6e25" - integrity sha512-46yL28o2NJ9doViqOy0VDcoTzng7rAb6yPQKU7VDLqkmbCaH4JqK4yk4XqlzNWy9PVC5pG1ZUXPBQv+VqnYs2w== - dependencies: - "@inquirer/core" "^9.2.1" - "@inquirer/type" "^2.0.0" - -"@inquirer/core@^9.2.1": - version "9.2.1" - resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-9.2.1.tgz#677c49dee399c9063f31e0c93f0f37bddc67add1" - integrity sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg== - dependencies: - "@inquirer/figures" "^1.0.6" - "@inquirer/type" "^2.0.0" - "@types/mute-stream" "^0.0.4" - "@types/node" "^22.5.5" - "@types/wrap-ansi" "^3.0.0" - ansi-escapes "^4.3.2" - cli-width "^4.1.0" - mute-stream "^1.0.0" - signal-exit "^4.1.0" - strip-ansi "^6.0.1" - wrap-ansi "^6.2.0" - yoctocolors-cjs "^2.1.2" - -"@inquirer/editor@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@inquirer/editor/-/editor-3.0.1.tgz#d109f21e050af6b960725388cb1c04214ed7c7bc" - integrity sha512-VA96GPFaSOVudjKFraokEEmUQg/Lub6OXvbIEZU1SDCmBzRkHGhxoFAVaF30nyiB4m5cEbDgiI2QRacXZ2hw9Q== - dependencies: - "@inquirer/core" "^9.2.1" - "@inquirer/type" "^2.0.0" - external-editor "^3.1.0" - -"@inquirer/expand@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@inquirer/expand/-/expand-3.0.1.tgz#aed9183cac4d12811be47a4a895ea8e82a17e22c" - integrity sha512-ToG8d6RIbnVpbdPdiN7BCxZGiHOTomOX94C2FaT5KOHupV40tKEDozp12res6cMIfRKrXLJyexAZhWVHgbALSQ== - dependencies: - "@inquirer/core" "^9.2.1" - "@inquirer/type" "^2.0.0" - yoctocolors-cjs "^2.1.2" - -"@inquirer/figures@^1.0.6": - version "1.0.13" - resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.13.tgz#ad0afd62baab1c23175115a9b62f511b6a751e45" - integrity sha512-lGPVU3yO9ZNqA7vTYz26jny41lE7yoQansmqdMLBEfqaGsmdg7V3W9mK9Pvb5IL4EVZ9GnSDGMO/cJXud5dMaw== - -"@inquirer/input@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@inquirer/input/-/input-3.0.1.tgz#de63d49e516487388508d42049deb70f2cb5f28e" - integrity sha512-BDuPBmpvi8eMCxqC5iacloWqv+5tQSJlUafYWUe31ow1BVXjW2a5qe3dh4X/Z25Wp22RwvcaLCc2siHobEOfzg== - dependencies: - "@inquirer/core" "^9.2.1" - "@inquirer/type" "^2.0.0" - -"@inquirer/number@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@inquirer/number/-/number-2.0.1.tgz#b9863080d02ab7dc2e56e16433d83abea0f2a980" - integrity sha512-QpR8jPhRjSmlr/mD2cw3IR8HRO7lSVOnqUvQa8scv1Lsr3xoAMMworcYW3J13z3ppjBFBD2ef1Ci6AE5Qn8goQ== - dependencies: - "@inquirer/core" "^9.2.1" - "@inquirer/type" "^2.0.0" - -"@inquirer/password@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@inquirer/password/-/password-3.0.1.tgz#2a9a9143591088336bbd573bcb05d5bf080dbf87" - integrity sha512-haoeEPUisD1NeE2IanLOiFr4wcTXGWrBOyAyPZi1FfLJuXOzNmxCJPgUrGYKVh+Y8hfGJenIfz5Wb/DkE9KkMQ== - dependencies: - "@inquirer/core" "^9.2.1" - "@inquirer/type" "^2.0.0" - ansi-escapes "^4.3.2" - -"@inquirer/prompts@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@inquirer/prompts/-/prompts-6.0.1.tgz#43f5c0ed35c5ebfe52f1d43d46da2d363d950071" - integrity sha512-yl43JD/86CIj3Mz5mvvLJqAOfIup7ncxfJ0Btnl0/v5TouVUyeEdcpknfgc+yMevS/48oH9WAkkw93m7otLb/A== - dependencies: - "@inquirer/checkbox" "^3.0.1" - "@inquirer/confirm" "^4.0.1" - "@inquirer/editor" "^3.0.1" - "@inquirer/expand" "^3.0.1" - "@inquirer/input" "^3.0.1" - "@inquirer/number" "^2.0.1" - "@inquirer/password" "^3.0.1" - "@inquirer/rawlist" "^3.0.1" - "@inquirer/search" "^2.0.1" - "@inquirer/select" "^3.0.1" - -"@inquirer/rawlist@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@inquirer/rawlist/-/rawlist-3.0.1.tgz#729def358419cc929045f264131878ed379e0af3" - integrity sha512-VgRtFIwZInUzTiPLSfDXK5jLrnpkuSOh1ctfaoygKAdPqjcjKYmGh6sCY1pb0aGnCGsmhUxoqLDUAU0ud+lGXQ== - dependencies: - "@inquirer/core" "^9.2.1" - "@inquirer/type" "^2.0.0" - yoctocolors-cjs "^2.1.2" - -"@inquirer/search@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@inquirer/search/-/search-2.0.1.tgz#69b774a0a826de2e27b48981d01bc5ad81e73721" - integrity sha512-r5hBKZk3g5MkIzLVoSgE4evypGqtOannnB3PKTG9NRZxyFRKcfzrdxXXPcoJQsxJPzvdSU2Rn7pB7lw0GCmGAg== - dependencies: - "@inquirer/core" "^9.2.1" - "@inquirer/figures" "^1.0.6" - "@inquirer/type" "^2.0.0" - yoctocolors-cjs "^2.1.2" - -"@inquirer/select@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@inquirer/select/-/select-3.0.1.tgz#1df9ed27fb85a5f526d559ac5ce7cc4e9dc4e7ec" - integrity sha512-lUDGUxPhdWMkN/fHy1Lk7pF3nK1fh/gqeyWXmctefhxLYxlDsc7vsPBEpxrfVGDsVdyYJsiJoD4bJ1b623cV1Q== - dependencies: - "@inquirer/core" "^9.2.1" - "@inquirer/figures" "^1.0.6" - "@inquirer/type" "^2.0.0" - ansi-escapes "^4.3.2" - yoctocolors-cjs "^2.1.2" - -"@inquirer/type@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-2.0.0.tgz#08fa513dca2cb6264fe1b0a2fabade051444e3f6" - integrity sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag== - dependencies: - mute-stream "^1.0.0" - "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -947,13 +795,6 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== -"@types/mute-stream@^0.0.4": - version "0.0.4" - resolved "https://registry.yarnpkg.com/@types/mute-stream/-/mute-stream-0.0.4.tgz#77208e56a08767af6c5e1237be8888e2f255c478" - integrity sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow== - dependencies: - "@types/node" "*" - "@types/node@*": version "22.15.17" resolved "https://registry.yarnpkg.com/@types/node/-/node-22.15.17.tgz#355ccec95f705b664e4332bb64a7f07db30b7055" @@ -961,13 +802,6 @@ dependencies: undici-types "~6.21.0" -"@types/node@^22.5.5": - version "22.18.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.18.0.tgz#9e4709be4f104e3568f7dd1c71e2949bf147a47b" - integrity sha512-m5ObIqwsUp6BZzyiy4RdZpzWGub9bqLJMvZDD0QMXhxjqMHMENlj+SqF5QxoUwaQNFe+8kz8XM8ZQhqkQPTgMQ== - dependencies: - undici-types "~6.21.0" - "@types/qs@*", "@types/qs@^6.14.0": version "6.14.0" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.14.0.tgz#d8b60cecf62f2db0fb68e5e006077b9178b85de5" @@ -1000,11 +834,6 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== -"@types/wrap-ansi@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz#18b97a972f94f60a679fd5c796d96421b9abb9fd" - integrity sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g== - "@types/yargs-parser@*": version "21.0.3" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" @@ -1151,7 +980,7 @@ ajv@^6.12.4, ajv@^6.12.6: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ansi-escapes@^4.2.1, ansi-escapes@^4.3.2: +ansi-escapes@^4.2.1: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== @@ -1393,11 +1222,6 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - ci-info@^3.2.0: version "3.9.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" @@ -1413,11 +1237,6 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== -cli-width@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5" - integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ== - cliui@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" @@ -1454,11 +1273,6 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -commander@^13.1.0: - version "13.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-13.1.0.tgz#776167db68c78f38dcce1f9b8d7b8b9a488abf46" - integrity sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1871,15 +1685,6 @@ express@^5.0.1, express@^5.1.0: type-is "^2.0.1" vary "^1.1.2" -external-editor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -1925,11 +1730,6 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" -fflate@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" - integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== - file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -1993,14 +1793,6 @@ flatted@^3.2.9: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== -flora-colossus@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/flora-colossus/-/flora-colossus-2.0.0.tgz#af1e85db0a8256ef05f3fb531c1235236c97220a" - integrity sha512-dz4HxH6pOvbUzZpZ/yXhafjbR2I8cenK5xL0KtBFb7U2ADsR+OwXifnxZjij/pZWF775uSCMzWVd+jDik2H2IA== - dependencies: - debug "^4.3.4" - fs-extra "^10.1.0" - forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -2011,15 +1803,6 @@ fresh@^2.0.0: resolved "https://registry.yarnpkg.com/fresh/-/fresh-2.0.0.tgz#8dd7df6a1b3a1b3a5cf186c05a5dd267622635a4" integrity sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A== -fs-extra@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" - integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -2035,15 +1818,6 @@ function-bind@^1.1.2: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== -galactus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/galactus/-/galactus-1.0.0.tgz#c2615182afa0c6d0859b92e56ae36d052827db7e" - integrity sha512-R1fam6D4CyKQGNlvJne4dkNF+PvUUl7TAJInvTGa9fti9qAv95quQz29GXapA4d8Ec266mJJxFVh82M4GIIGDQ== - dependencies: - debug "^4.3.4" - flora-colossus "^2.0.0" - fs-extra "^10.1.0" - gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -2136,7 +1910,7 @@ gopd@^1.2.0: resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== -graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.9: +graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -2191,23 +1965,11 @@ iconv-lite@0.6.3, iconv-lite@^0.6.3: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" -iconv-lite@^0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - ignore@^5.2.0, ignore@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== -ignore@^7.0.5: - version "7.0.5" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9" - integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg== - import-fresh@^3.2.1: version "3.3.1" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" @@ -2786,15 +2548,6 @@ json5@^2.2.2, json5@^2.2.3: resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== -jsonfile@^6.0.1: - version "6.2.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.2.0.tgz#7c265bd1b65de6977478300087c99f1c84383f62" - integrity sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg== - dependencies: - universalify "^2.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -2968,11 +2721,6 @@ ms@^2.1.3: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -mute-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e" - integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA== - natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -2983,11 +2731,6 @@ negotiator@^1.0.0: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a" integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg== -node-forge@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" - integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== - node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -3053,11 +2796,6 @@ optionator@^0.9.3: type-check "^0.4.0" word-wrap "^1.2.5" -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== - p-all@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-all/-/p-all-3.0.0.tgz#077c023c37e75e760193badab2bad3ccd5782bfb" @@ -3201,11 +2939,6 @@ prettier@^3.0.0: resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.5.3.tgz#4fc2ce0d657e7a02e602549f053b239cb7dfe1b5" integrity sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw== -pretty-bytes@^5.6.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" - integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== - pretty-format@^29.0.0, pretty-format@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" @@ -3353,7 +3086,7 @@ safe-buffer@5.2.1, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": +"safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -3457,11 +3190,6 @@ signal-exit@^3.0.3, signal-exit@^3.0.7: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -signal-exit@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" - integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== - sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -3606,13 +3334,6 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" @@ -3753,11 +3474,6 @@ undici-types@~6.21.0: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== -universalify@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" - integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== - unpipe@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -3821,15 +3537,6 @@ word-wrap@^1.2.5: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -3890,11 +3597,6 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -yoctocolors-cjs@^2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz#7e4964ea8ec422b7a40ac917d3a344cfd2304baa" - integrity sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw== - zod-to-json-schema@^3.24.1, zod-to-json-schema@^3.24.5: version "3.24.5" resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz#d1095440b147fb7c2093812a53c54df8d5df50a3" @@ -3910,7 +3612,7 @@ zod@^3.23.8: resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.4.tgz#e2e2cca5faaa012d76e527d0d36622e0a90c315f" integrity sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg== -zod@^3.25.20, zod@^3.25.67: +zod@^3.25.20: version "3.25.76" resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.76.tgz#26841c3f6fd22a6a2760e7ccb719179768471e34" integrity sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ== diff --git a/scripts/bootstrap b/scripts/bootstrap index 062a0349..a8b69ff3 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,10 +4,18 @@ set -e cd "$(dirname "$0")/.." -if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { - echo "==> Installing Homebrew dependencies…" - brew bundle + echo -n "==> Install Homebrew dependencies? (y/N): " + read -r response + case "$response" in + [yY][eE][sS]|[yY]) + brew bundle + ;; + *) + ;; + esac + echo } fi diff --git a/scripts/fast-format b/scripts/fast-format new file mode 100755 index 00000000..53721ac0 --- /dev/null +++ b/scripts/fast-format @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +set -euo pipefail + +echo "Script started with $# arguments" +echo "Arguments: $*" +echo "Script location: $(dirname "$0")" + +cd "$(dirname "$0")/.." +echo "Changed to directory: $(pwd)" + +if [ $# -eq 0 ]; then + echo "Usage: $0 [additional-formatter-args...]" + echo "The file should contain one file path per line" + exit 1 +fi + +FILE_LIST="$1" + +echo "Looking for file: $FILE_LIST" + +if [ ! -f "$FILE_LIST" ]; then + echo "Error: File '$FILE_LIST' not found" + exit 1 +fi + +echo "==> Running eslint --fix" +ESLINT_FILES="$(grep '\.ts$' "$FILE_LIST" || true)" +if ! [ -z "$ESLINT_FILES" ]; then + echo "$ESLINT_FILES" | xargs ./node_modules/.bin/eslint --cache --fix +fi + +echo "==> Running prettier --write" +# format things eslint didn't +PRETTIER_FILES="$(grep '\.\(js\|json\)$' "$FILE_LIST" || true)" +if ! [ -z "$PRETTIER_FILES" ]; then + echo "$PRETTIER_FILES" | xargs ./node_modules/.bin/prettier \ + --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern \ + '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' +fi diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh index 8d2f68c3..09791ec8 100755 --- a/scripts/utils/upload-artifact.sh +++ b/scripts/utils/upload-artifact.sh @@ -12,9 +12,11 @@ if [[ "$SIGNED_URL" == "null" ]]; then exit 1 fi -UPLOAD_RESPONSE=$(tar "${BASE_PATH:+-C$BASE_PATH}" -cz "${ARTIFACT_PATH:-dist}" | curl -v -X PUT \ +TARBALL=$(cd dist && npm pack --silent) + +UPLOAD_RESPONSE=$(curl -v -X PUT \ -H "Content-Type: application/gzip" \ - --data-binary @- "$SIGNED_URL" 2>&1) + --data-binary "@dist/$TARBALL" "$SIGNED_URL" 2>&1) if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then echo -e "\033[32mUploaded build to Stainless storage.\033[0m" diff --git a/src/core/pagination.ts b/src/core/pagination.ts index d23529e0..aa09f157 100644 --- a/src/core/pagination.ts +++ b/src/core/pagination.ts @@ -164,7 +164,7 @@ export class PropertyManagersPagination } nextPageRequestOptions(): PageRequestOptions | null { - const currentPage = this.pagination?.page; + const currentPage = this.pagination?.page ?? 1; if (currentPage >= this.pagination?.pages) { return null; @@ -234,7 +234,7 @@ export class TenantsPagination extends AbstractPage implements Tenan } nextPageRequestOptions(): PageRequestOptions | null { - const currentPage = this.pagination?.page; + const currentPage = this.pagination?.page ?? 1; if (currentPage >= this.pagination?.pages) { return null; @@ -307,7 +307,7 @@ export class EnrollmentsPagination } nextPageRequestOptions(): PageRequestOptions | null { - const currentPage = this.pagination?.page; + const currentPage = this.pagination?.page ?? 1; if (currentPage >= this.pagination?.pages) { return null; @@ -380,7 +380,7 @@ export class WebhookEndpointsPagination } nextPageRequestOptions(): PageRequestOptions | null { - const currentPage = this.pagination?.page; + const currentPage = this.pagination?.page ?? 1; if (currentPage >= this.pagination?.pages) { return null; diff --git a/src/internal/to-file.ts b/src/internal/to-file.ts index 245e8493..30eada32 100644 --- a/src/internal/to-file.ts +++ b/src/internal/to-file.ts @@ -73,7 +73,7 @@ export type ToFileInput = /** * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats - * @param value the raw content of the file. Can be an {@link Uploadable}, {@link BlobLikePart}, or {@link AsyncIterable} of {@link BlobLikePart}s + * @param value the raw content of the file. Can be an {@link Uploadable}, BlobLikePart, or AsyncIterable of BlobLikeParts * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible * @param {Object=} options additional properties * @param {string=} options.type the MIME type of the content diff --git a/src/internal/utils/values.ts b/src/internal/utils/values.ts index 549111a6..2b5a832e 100644 --- a/src/internal/utils/values.ts +++ b/src/internal/utils/values.ts @@ -76,21 +76,21 @@ export const coerceBoolean = (value: unknown): boolean => { }; export const maybeCoerceInteger = (value: unknown): number | undefined => { - if (value === undefined) { + if (value == null) { return undefined; } return coerceInteger(value); }; export const maybeCoerceFloat = (value: unknown): number | undefined => { - if (value === undefined) { + if (value == null) { return undefined; } return coerceFloat(value); }; export const maybeCoerceBoolean = (value: unknown): boolean | undefined => { - if (value === undefined) { + if (value == null) { return undefined; } return coerceBoolean(value); diff --git a/src/resources/enrollments.ts b/src/resources/enrollments.ts index 2359ba7d..1ffee073 100644 --- a/src/resources/enrollments.ts +++ b/src/resources/enrollments.ts @@ -108,6 +108,16 @@ export interface EnrollmentCreateParams { propertyManagerId: number; + status: + | 'Premium Paying' + | 'Issued, Not Paid' + | 'Expired' + | 'Lapsed' + | 'Suspended' + | 'Cancelled' + | 'Not taken' + | 'Declined'; + tenantId: number; /** diff --git a/tests/api-resources/enrollments.test.ts b/tests/api-resources/enrollments.test.ts index 3456da4d..68f133df 100644 --- a/tests/api-resources/enrollments.test.ts +++ b/tests/api-resources/enrollments.test.ts @@ -14,6 +14,7 @@ describe('resource enrollments', () => { effectiveDate: 'effectiveDate', plan: 'plan', propertyManagerId: 0, + status: 'Premium Paying', tenantId: 0, }); const rawResponse = await responsePromise.asResponse(); @@ -31,6 +32,7 @@ describe('resource enrollments', () => { effectiveDate: 'effectiveDate', plan: 'plan', propertyManagerId: 0, + status: 'Premium Paying', tenantId: 0, note: 'note', }); diff --git a/tsconfig.build.json b/tsconfig.build.json index 4af3724f..c5a55ec2 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -5,8 +5,8 @@ "compilerOptions": { "rootDir": "./dist/src", "paths": { - "@corgi-tech/beagle/*": ["dist/src/*"], - "@corgi-tech/beagle": ["dist/src/index.ts"] + "@corgi-tech/beagle/*": ["./dist/src/*"], + "@corgi-tech/beagle": ["./dist/src/index.ts"] }, "noEmit": false, "declaration": true, diff --git a/tsconfig.json b/tsconfig.json index 56dcb13a..2eab4fa2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,10 +7,9 @@ "module": "commonjs", "moduleResolution": "node", "esModuleInterop": true, - "baseUrl": "./", "paths": { - "@corgi-tech/beagle/*": ["src/*"], - "@corgi-tech/beagle": ["src/index.ts"] + "@corgi-tech/beagle/*": ["./src/*"], + "@corgi-tech/beagle": ["./src/index.ts"] }, "noEmit": true, From 7477c2dbdd36f8ab00abb2dc0b34864417a09558 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Oct 2025 20:27:22 +0000 Subject: [PATCH 054/138] feat(api): api update --- .stats.yml | 4 ++-- .../src/tools/property-managers/create-property-managers.ts | 5 ++++- .../src/tools/property-managers/list-property-managers.ts | 2 +- .../tools/property-managers/retrieve-property-managers.ts | 2 +- .../src/tools/property-managers/update-property-managers.ts | 5 ++++- src/resources/property-managers.ts | 6 ++++++ tests/api-resources/property-managers.test.ts | 1 + 7 files changed, 19 insertions(+), 6 deletions(-) diff --git a/.stats.yml b/.stats.yml index 5781b246..d9bd89b4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 23 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-e02fb0cc53e6898f4a4a265645714517d5df273782e178a0221d5f6afdfecf6a.yml -openapi_spec_hash: acfb45a1223d482c5c48164bb1365959 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-d1482c73aaf0ee32c7bc9e8a8155ea5ef0c26a8947e54d57a95cfc396fe2e5ee.yml +openapi_spec_hash: cbee5e1d7eefcb7f445139055c448ab6 config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts index b2eed925..c4d819a1 100644 --- a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'create_property_managers', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ncreate a new property manager.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/property_manager',\n $defs: {\n property_manager: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n addresses: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/address'\n }\n ]\n }\n },\n contacts: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/contact'\n }\n ]\n }\n },\n name: {\n type: 'string',\n description: 'name of the property manager'\n }\n },\n required: [ 'id',\n 'addresses',\n 'contacts',\n 'name'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ncreate a new property manager.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/property_manager',\n $defs: {\n property_manager: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n addresses: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/address'\n }\n ]\n }\n },\n contacts: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/contact'\n }\n ]\n }\n },\n name: {\n type: 'string',\n description: 'name of the property manager'\n },\n clickWrapAt: {\n type: 'number'\n }\n },\n required: [ 'id',\n 'addresses',\n 'contacts',\n 'name'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { @@ -46,6 +46,9 @@ export const tool: Tool = { type: 'string', description: 'name of the property manager', }, + clickWrapAt: { + type: 'number', + }, jq_filter: { type: 'string', title: 'jq Filter', diff --git a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts index c32c3b28..126b6bd9 100644 --- a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'list_property_managers', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlist all property managers, note this endpoint is paginated.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n pagination: {\n $ref: '#/$defs/pagination'\n },\n propertyManagers: {\n type: 'array',\n items: {\n $ref: '#/$defs/property_manager'\n }\n }\n },\n required: [ 'pagination',\n 'propertyManagers'\n ],\n $defs: {\n pagination: {\n type: 'object',\n properties: {\n page: {\n type: 'number',\n description: 'Current page number.'\n },\n pages: {\n type: 'number',\n description: 'Total number of pages.'\n },\n records: {\n type: 'number',\n description: 'Total number of records.'\n },\n size: {\n type: 'number',\n description: 'Number of items per page.'\n }\n },\n required: [ 'page',\n 'pages',\n 'records',\n 'size'\n ]\n },\n property_manager: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n addresses: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/address'\n }\n ]\n }\n },\n contacts: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/contact'\n }\n ]\n }\n },\n name: {\n type: 'string',\n description: 'name of the property manager'\n }\n },\n required: [ 'id',\n 'addresses',\n 'contacts',\n 'name'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlist all property managers, note this endpoint is paginated.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n pagination: {\n $ref: '#/$defs/pagination'\n },\n propertyManagers: {\n type: 'array',\n items: {\n $ref: '#/$defs/property_manager'\n }\n }\n },\n required: [ 'pagination',\n 'propertyManagers'\n ],\n $defs: {\n pagination: {\n type: 'object',\n properties: {\n page: {\n type: 'number',\n description: 'Current page number.'\n },\n pages: {\n type: 'number',\n description: 'Total number of pages.'\n },\n records: {\n type: 'number',\n description: 'Total number of records.'\n },\n size: {\n type: 'number',\n description: 'Number of items per page.'\n }\n },\n required: [ 'page',\n 'pages',\n 'records',\n 'size'\n ]\n },\n property_manager: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n addresses: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/address'\n }\n ]\n }\n },\n contacts: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/contact'\n }\n ]\n }\n },\n name: {\n type: 'string',\n description: 'name of the property manager'\n },\n clickWrapAt: {\n type: 'number'\n }\n },\n required: [ 'id',\n 'addresses',\n 'contacts',\n 'name'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { diff --git a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts index cb07e3a8..a52fd678 100644 --- a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'retrieve_property_managers', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nget a property manager by id.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/property_manager',\n $defs: {\n property_manager: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n addresses: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/address'\n }\n ]\n }\n },\n contacts: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/contact'\n }\n ]\n }\n },\n name: {\n type: 'string',\n description: 'name of the property manager'\n }\n },\n required: [ 'id',\n 'addresses',\n 'contacts',\n 'name'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nget a property manager by id.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/property_manager',\n $defs: {\n property_manager: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n addresses: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/address'\n }\n ]\n }\n },\n contacts: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/contact'\n }\n ]\n }\n },\n name: {\n type: 'string',\n description: 'name of the property manager'\n },\n clickWrapAt: {\n type: 'number'\n }\n },\n required: [ 'id',\n 'addresses',\n 'contacts',\n 'name'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { diff --git a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts index 1fb524dc..8fe9f605 100644 --- a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'update_property_managers', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nupdate an existing property manager by id, note that when updating contacts or addresses you need to send the whole array you want to replace them with.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/property_manager',\n $defs: {\n property_manager: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n addresses: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/address'\n }\n ]\n }\n },\n contacts: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/contact'\n }\n ]\n }\n },\n name: {\n type: 'string',\n description: 'name of the property manager'\n }\n },\n required: [ 'id',\n 'addresses',\n 'contacts',\n 'name'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nupdate an existing property manager by id, note that when updating contacts or addresses you need to send the whole array you want to replace them with.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/property_manager',\n $defs: {\n property_manager: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n addresses: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/address'\n }\n ]\n }\n },\n contacts: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/contact'\n }\n ]\n }\n },\n name: {\n type: 'string',\n description: 'name of the property manager'\n },\n clickWrapAt: {\n type: 'number'\n }\n },\n required: [ 'id',\n 'addresses',\n 'contacts',\n 'name'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { @@ -35,6 +35,9 @@ export const tool: Tool = { ], }, }, + clickWrapAt: { + type: 'number', + }, contacts: { type: 'array', items: { diff --git a/src/resources/property-managers.ts b/src/resources/property-managers.ts index 4853bc80..d620bb30 100644 --- a/src/resources/property-managers.ts +++ b/src/resources/property-managers.ts @@ -98,6 +98,8 @@ export interface PropertyManager { * name of the property manager */ name: string; + + clickWrapAt?: number; } export namespace PropertyManager { @@ -119,6 +121,8 @@ export interface PropertyManagerCreateParams { * name of the property manager */ name: string; + + clickWrapAt?: number; } export namespace PropertyManagerCreateParams { @@ -134,6 +138,8 @@ export namespace PropertyManagerCreateParams { export interface PropertyManagerUpdateParams { addresses?: Array; + clickWrapAt?: number; + contacts?: Array; /** diff --git a/tests/api-resources/property-managers.test.ts b/tests/api-resources/property-managers.test.ts index 0469e702..84d2e598 100644 --- a/tests/api-resources/property-managers.test.ts +++ b/tests/api-resources/property-managers.test.ts @@ -39,6 +39,7 @@ describe('resource propertyManagers', () => { }, ], name: 'name', + clickWrapAt: 0, }); }); From 16d3d7bcc7a5220540f4aa8e83212e84da468713 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 31 Oct 2025 04:03:27 +0000 Subject: [PATCH 055/138] chore(internal): codegen related update --- packages/mcp-server/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 06aafbc8..9e296070 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -47,7 +47,7 @@ "mcp-server": "dist/index.js" }, "devDependencies": { - "@anthropic-ai/mcpb": "^1.1.0", + "@anthropic-ai/mcpb": "1.1.0", "@types/cors": "^2.8.19", "@types/express": "^5.0.3", "@types/jest": "^29.4.0", From 4077f6d678b4bfdf8744a00eece23c95ac55dc16 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 4 Nov 2025 05:53:13 +0000 Subject: [PATCH 056/138] chore(internal): codegen related update --- packages/mcp-server/src/code-tool.ts | 27 ++++++++++++------------ packages/mcp-server/src/dynamic-tools.ts | 2 +- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 51859ce3..15179a06 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -3,7 +3,7 @@ import { dirname } from 'node:path'; import { pathToFileURL } from 'node:url'; import Beagle, { ClientOptions } from '@corgi-tech/beagle'; -import { Endpoint, ContentBlock, Metadata } from './tools/types'; +import { ContentBlock, Endpoint, Metadata, ToolCallResult } from './tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -12,7 +12,7 @@ import { WorkerInput, WorkerError, WorkerSuccess } from './code-tool-types'; /** * A tool that runs code against a copy of the SDK. * - * Instead of exposing every endpoint as it's own tool, which uses up too many tokens for LLMs to use at once, + * Instead of exposing every endpoint as its own tool, which uses up too many tokens for LLMs to use at once, * we expose a single tool that can be used to search for endpoints by name, resource, operation, or tag, and then * a generic endpoint that can be used to invoke any endpoint with the provided arguments. * @@ -23,7 +23,7 @@ export async function codeTool(): Promise { const tool: Tool = { name: 'execute', description: - 'Runs Typescript code to interact with the API.\nYou are a skilled programmer writing code to interface with the service.\nDefine an async function named "run" that takes a single parameter of an initialized client, and it will be run.\nDo not initialize a client, but instead use the client that you are given as a parameter.\nYou will be returned anything that your function returns, plus the results of any console.log statements.\nIf any code triggers an error, the tool will return an error response, so you do not need to add error handling unless you want to output something more helpful than the raw error.\nIt is not necessary to add comments to code, unless by adding those comments you believe that you can generate better code.\nThis code will run in a container, and you will not be able to use fetch or otherwise interact with the network calls other than through the client you are given.\nAny variables you define won\'t live between successive uses of this call, so make sure to return or log any data you might need later.', + 'Runs TypeScript code to interact with the API.\nYou are a skilled programmer writing code to interface with the service.\nDefine an async function named "run" that takes a single parameter of an initialized client, and it will be run.\nDo not initialize a client, but instead use the client that you are given as a parameter.\nYou will be returned anything that your function returns, plus the results of any console.log statements.\nIf any code triggers an error, the tool will return an error response, so you do not need to add error handling unless you want to output something more helpful than the raw error.\nIt is not necessary to add comments to code, unless by adding those comments you believe that you can generate better code.\nThis code will run in a container, and you will not be able to use fetch or otherwise interact with the network calls other than through the client you are given.\nAny variables you define won\'t live between successive uses of this call, so make sure to return or log any data you might need later.', inputSchema: { type: 'object', properties: { code: { type: 'string' } } }, }; @@ -31,7 +31,7 @@ export async function codeTool(): Promise { const { newDenoHTTPWorker } = await import('@valtown/deno-http-worker'); const { workerPath } = await import('./code-tool-paths.cjs'); - const handler = async (client: Beagle, args: unknown) => { + const handler = async (client: Beagle, args: unknown): Promise => { const baseURLHostname = new URL(client.baseURL).hostname; const { code } = args as { code: string }; @@ -97,7 +97,7 @@ export async function codeTool(): Promise { } satisfies WorkerInput); req.write(body, (err) => { - if (err !== null && err !== undefined) { + if (err != null) { reject(err); } }); @@ -108,12 +108,12 @@ export async function codeTool(): Promise { if (resp.status === 200) { const { result, logLines, errLines } = (await resp.json()) as WorkerSuccess; const returnOutput: ContentBlock | null = - result === null ? null - : result === undefined ? null - : { + result == null ? null : ( + { type: 'text', - text: typeof result === 'string' ? (result as string) : JSON.stringify(result), - }; + text: typeof result === 'string' ? result : JSON.stringify(result), + } + ); const logOutput: ContentBlock | null = logLines.length === 0 ? null @@ -133,10 +133,11 @@ export async function codeTool(): Promise { }; } else { const { message } = (await resp.json()) as WorkerError; - throw new Error(message); + return { + content: message == null ? [] : [{ type: 'text', text: message }], + isError: true, + }; } - } catch (e) { - throw e; } finally { worker.terminate(); } diff --git a/packages/mcp-server/src/dynamic-tools.ts b/packages/mcp-server/src/dynamic-tools.ts index 6b226e3c..12310045 100644 --- a/packages/mcp-server/src/dynamic-tools.ts +++ b/packages/mcp-server/src/dynamic-tools.ts @@ -14,7 +14,7 @@ function zodToInputSchema(schema: z.ZodSchema) { /** * A list of tools that expose all the endpoints in the API dynamically. * - * Instead of exposing every endpoint as it's own tool, which uses up too many tokens for LLMs to use at once, + * Instead of exposing every endpoint as its own tool, which uses up too many tokens for LLMs to use at once, * we expose a single tool that can be used to search for endpoints by name, resource, operation, or tag, and then * a generic endpoint that can be used to invoke any endpoint with the provided arguments. * From a880b1a570f52404fab4d0fcc47f4dc4867e89eb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 5 Nov 2025 05:30:46 +0000 Subject: [PATCH 057/138] chore(internal): codegen related update --- packages/mcp-server/package.json | 4 +- packages/mcp-server/src/code-tool-worker.ts | 47 +++++++++++++++++++++ packages/mcp-server/src/options.ts | 13 ++++-- packages/mcp-server/tests/options.test.ts | 22 ++++++++++ 4 files changed, 81 insertions(+), 5 deletions(-) diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 9e296070..f8511864 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -38,6 +38,7 @@ "express": "^5.1.0", "jq-web": "https://github.com/stainless-api/jq-web/releases/download/v0.8.6/jq-web.tar.gz", "qs": "^6.14.0", + "typescript": "5.8.3", "yargs": "^17.7.2", "zod": "^3.25.20", "zod-to-json-schema": "^3.24.5", @@ -64,8 +65,7 @@ "ts-morph": "^19.0.0", "ts-node": "^10.5.0", "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz", - "tsconfig-paths": "^4.0.0", - "typescript": "5.8.3" + "tsconfig-paths": "^4.0.0" }, "imports": { "@corgi-tech/beagle-mcp": ".", diff --git a/packages/mcp-server/src/code-tool-worker.ts b/packages/mcp-server/src/code-tool-worker.ts index 39f83c97..9f8c0c50 100644 --- a/packages/mcp-server/src/code-tool-worker.ts +++ b/packages/mcp-server/src/code-tool-worker.ts @@ -1,11 +1,58 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import util from 'node:util'; + +import ts from 'typescript'; + import { WorkerInput, WorkerSuccess, WorkerError } from './code-tool-types'; import { Beagle } from '@corgi-tech/beagle'; +function getRunFunctionNode( + code: string, +): ts.FunctionDeclaration | ts.FunctionExpression | ts.ArrowFunction | null { + const sourceFile = ts.createSourceFile('code.ts', code, ts.ScriptTarget.Latest, true); + + for (const statement of sourceFile.statements) { + // Check for top-level function declarations + if (ts.isFunctionDeclaration(statement)) { + if (statement.name?.text === 'run') { + return statement; + } + } + + // Check for variable declarations: const run = () => {} or const run = function() {} + if (ts.isVariableStatement(statement)) { + for (const declaration of statement.declarationList.declarations) { + if (ts.isIdentifier(declaration.name) && declaration.name.text === 'run') { + // Check if it's initialized with a function + if ( + declaration.initializer && + (ts.isFunctionExpression(declaration.initializer) || ts.isArrowFunction(declaration.initializer)) + ) { + return declaration.initializer; + } + } + } + } + } + + return null; +} + const fetch = async (req: Request): Promise => { const { opts, code } = (await req.json()) as WorkerInput; + + const runFunctionNode = getRunFunctionNode(code); + if (!runFunctionNode) { + return Response.json( + { + message: + 'The code is missing a top-level `run` function. Write code within this template:\n\n```\nasync function run(client) {\n // Fill this out\n}\n```', + } satisfies WorkerError, + { status: 400, statusText: 'Code execution error' }, + ); + } + const client = new Beagle({ ...opts, }); diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index 4fe3b987..b6ff5976 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -284,8 +284,10 @@ const coerceArray = (zodType: T) => ); const QueryOptions = z.object({ - tools: coerceArray(z.enum(['dynamic', 'all', 'docs'])).describe('Use dynamic tools or all tools'), - no_tools: coerceArray(z.enum(['dynamic', 'all', 'docs'])).describe('Do not use dynamic tools or all tools'), + tools: coerceArray(z.enum(['dynamic', 'all', 'code', 'docs'])).describe('Specify which MCP tools to use'), + no_tools: coerceArray(z.enum(['dynamic', 'all', 'code', 'docs'])).describe( + 'Specify which MCP tools to not use.', + ), tool: coerceArray(z.string()).describe('Include tools matching the specified names'), resource: coerceArray(z.string()).describe('Include tools matching the specified resources'), operation: coerceArray(z.enum(['read', 'write'])).describe( @@ -385,11 +387,16 @@ export function parseQueryOptions(defaultOptions: McpOptions, query: unknown): M : queryOptions.tools?.includes('docs') ? true : defaultOptions.includeDocsTools; + let codeTools: boolean | undefined = + queryOptions.no_tools && queryOptions.no_tools?.includes('code') ? false + : queryOptions.tools?.includes('code') && defaultOptions.includeCodeTools ? true + : defaultOptions.includeCodeTools; + return { client: queryOptions.client ?? defaultOptions.client, includeDynamicTools: dynamicTools, includeAllTools: allTools, - includeCodeTools: undefined, + includeCodeTools: codeTools, includeDocsTools: docsTools, filters, capabilities: clientCapabilities, diff --git a/packages/mcp-server/tests/options.test.ts b/packages/mcp-server/tests/options.test.ts index a8a5b81a..4d9b60ca 100644 --- a/packages/mcp-server/tests/options.test.ts +++ b/packages/mcp-server/tests/options.test.ts @@ -171,6 +171,7 @@ describe('parseQueryOptions', () => { const defaultOptions = { client: undefined, includeDynamicTools: undefined, + includeCodeTools: undefined, includeAllTools: undefined, filters: [], capabilities: { @@ -383,6 +384,27 @@ describe('parseQueryOptions', () => { { type: 'tool', op: 'exclude', value: 'exclude-tool' }, ]); }); + + it('code tools are enabled on http servers with default option set', () => { + const query = 'tools=code'; + const result = parseQueryOptions({ ...defaultOptions, includeCodeTools: true }, query); + + expect(result.includeCodeTools).toBe(true); + }); + + it('code tools are prevented on http servers when no default option set', () => { + const query = 'tools=code'; + const result = parseQueryOptions(defaultOptions, query); + + expect(result.includeCodeTools).toBe(undefined); + }); + + it('code tools are prevented on http servers when default option is explicitly false', () => { + const query = 'tools=code'; + const result = parseQueryOptions({ ...defaultOptions, includeCodeTools: false }, query); + + expect(result.includeCodeTools).toBe(false); + }); }); describe('parseEmbeddedJSON', () => { From c51b5357383a5a86f6592d8af2b9ccd3e357c29e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 6 Nov 2025 05:44:58 +0000 Subject: [PATCH 058/138] chore(internal): codegen related update --- packages/mcp-server/README.md | 22 +++- packages/mcp-server/package.json | 1 + packages/mcp-server/src/code-tool-worker.ts | 138 +++++++++++++++++++- packages/mcp-server/src/code-tool.ts | 2 +- 4 files changed, 154 insertions(+), 9 deletions(-) diff --git a/packages/mcp-server/README.md b/packages/mcp-server/README.md index 1f1b192a..817d91fc 100644 --- a/packages/mcp-server/README.md +++ b/packages/mcp-server/README.md @@ -36,12 +36,20 @@ For clients with a configuration JSON, it might look something like this: } ``` +### Cursor + +If you use Cursor, you can install the MCP server by using the button below. You will need to set your environment variables +in Cursor's `mcp.json`, which can be found in Cursor Settings > Tools & MCP > New MCP Server. + +[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=@corgi-tech/beagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiU2V0IHlvdXIgQkVBR0xFX0FQSV9LRVkgaGVyZS4ifX0) + ## Exposing endpoints to your MCP Client -There are two ways to expose endpoints as tools in the MCP server: +There are three ways to expose endpoints as tools in the MCP server: 1. Exposing one tool per endpoint, and filtering as necessary 2. Exposing a set of tools to dynamically discover and invoke endpoints from the API +3. Exposing a docs search tool and a code execution tool, allowing the client to write code to be executed against the TypeScript client ### Filtering endpoints and tools @@ -76,6 +84,18 @@ All of these command-line options can be repeated, combined together, and have c Use `--list` to see the list of available tools, or see below. +### Code execution + +If you specify `--tools=code` to the MCP server, it will expose just two tools: + +- `search_docs` - Searches the API documentation and returns a list of markdown results +- `execute` - Runs code against the TypeScript client + +This allows the LLM to implement more complex logic by chaining together many API calls without loading +intermediary results into its context window. + +The code execution itself happens in a Deno sandbox that has network access only to the base URL for the API. + ### Specifying the MCP Client Different clients have varying abilities to handle arbitrary tools and schemas. diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index f8511864..c4eaf223 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -36,6 +36,7 @@ "@valtown/deno-http-worker": "^0.0.21", "cors": "^2.8.5", "express": "^5.1.0", + "fuse.js": "^7.1.0", "jq-web": "https://github.com/stainless-api/jq-web/releases/download/v0.8.6/jq-web.tar.gz", "qs": "^6.14.0", "typescript": "5.8.3", diff --git a/packages/mcp-server/src/code-tool-worker.ts b/packages/mcp-server/src/code-tool-worker.ts index 9f8c0c50..0dbe46fc 100644 --- a/packages/mcp-server/src/code-tool-worker.ts +++ b/packages/mcp-server/src/code-tool-worker.ts @@ -2,6 +2,7 @@ import util from 'node:util'; +import Fuse from 'fuse.js'; import ts from 'typescript'; import { WorkerInput, WorkerSuccess, WorkerError } from './code-tool-types'; @@ -39,8 +40,135 @@ function getRunFunctionNode( return null; } +const fuse = new Fuse( + [ + 'client.plans.list', + 'client.plans.retrieve', + 'client.propertyManagers.create', + 'client.propertyManagers.delete', + 'client.propertyManagers.list', + 'client.propertyManagers.retrieve', + 'client.propertyManagers.update', + 'client.tenants.create', + 'client.tenants.delete', + 'client.tenants.list', + 'client.tenants.retrieve', + 'client.tenants.update', + 'client.enrollments.create', + 'client.enrollments.lapse', + 'client.enrollments.list', + 'client.enrollments.retrieve', + 'client.enrollments.retrieveCertificate', + 'client.insuranceVerification.verify', + 'client.webhook.endpoints.create', + 'client.webhook.endpoints.delete', + 'client.webhook.endpoints.list', + 'client.webhook.endpoints.retrieve', + 'client.webhook.endpoints.update', + ], + { threshold: 1, shouldSort: true }, +); + +function getMethodSuggestions(fullyQualifiedMethodName: string): string[] { + return fuse + .search(fullyQualifiedMethodName) + .map(({ item }) => item) + .slice(0, 5); +} + +const proxyToObj = new WeakMap(); +const objToProxy = new WeakMap(); + +type ClientProxyConfig = { + path: string[]; + isBelievedBad?: boolean; +}; + +function makeSdkProxy(obj: T, { path, isBelievedBad = false }: ClientProxyConfig): T { + let proxy: T = objToProxy.get(obj); + + if (!proxy) { + proxy = new Proxy(obj, { + get(target, prop, receiver) { + const propPath = [...path, String(prop)]; + const value = Reflect.get(target, prop, receiver); + + if (isBelievedBad || (!(prop in target) && value === undefined)) { + // If we're accessing a path that doesn't exist, it will probably eventually error. + // Let's proxy it and mark it bad so that we can control the error message. + // We proxy an empty class so that an invocation or construction attempt is possible. + return makeSdkProxy(class {}, { path: propPath, isBelievedBad: true }); + } + + if (value !== null && (typeof value === 'object' || typeof value === 'function')) { + return makeSdkProxy(value, { path: propPath, isBelievedBad }); + } + + return value; + }, + + apply(target, thisArg, args) { + if (isBelievedBad || typeof target !== 'function') { + const fullyQualifiedMethodName = path.join('.'); + const suggestions = getMethodSuggestions(fullyQualifiedMethodName); + throw new Error( + `${fullyQualifiedMethodName} is not a function. Did you mean: ${suggestions.join(', ')}`, + ); + } + + return Reflect.apply(target, proxyToObj.get(thisArg) ?? thisArg, args); + }, + + construct(target, args, newTarget) { + if (isBelievedBad || typeof target !== 'function') { + const fullyQualifiedMethodName = path.join('.'); + const suggestions = getMethodSuggestions(fullyQualifiedMethodName); + throw new Error( + `${fullyQualifiedMethodName} is not a constructor. Did you mean: ${suggestions.join(', ')}`, + ); + } + + return Reflect.construct(target, args, newTarget); + }, + }); + + objToProxy.set(obj, proxy); + proxyToObj.set(proxy, obj); + } + + return proxy; +} + +function parseError(code: string, error: unknown): string | undefined { + if (!(error instanceof Error)) return; + const message = error.name ? `${error.name}: ${error.message}` : error.message; + try { + // Deno uses V8; the first ":LINE:COLUMN" is the top of stack. + const lineNumber = error.stack?.match(/:([0-9]+):[0-9]+/)?.[1]; + // -1 for the zero-based indexing + const line = + lineNumber && + code + .split('\n') + .at(parseInt(lineNumber, 10) - 1) + ?.trim(); + return line ? `${message}\n at line ${lineNumber}\n ${line}` : message; + } catch { + return message; + } +} + const fetch = async (req: Request): Promise => { const { opts, code } = (await req.json()) as WorkerInput; + if (code == null) { + return Response.json( + { + message: + 'The code param is missing. Provide one containing a top-level `run` function. Write code within this template:\n\n```\nasync function run(client) {\n // Fill this out\n}\n```', + } satisfies WorkerError, + { status: 400, statusText: 'Code execution error' }, + ); + } const runFunctionNode = getRunFunctionNode(code); if (!runFunctionNode) { @@ -69,21 +197,17 @@ const fetch = async (req: Request): Promise => { }; try { let run_ = async (client: any) => {}; - eval(` - ${code} - run_ = run; - `); - const result = await run_(client); + eval(`${code}\nrun_ = run;`); + const result = await run_(makeSdkProxy(client, { path: ['client'] })); return Response.json({ result, logLines, errLines, } satisfies WorkerSuccess); } catch (e) { - const message = e instanceof Error ? e.message : undefined; return Response.json( { - message, + message: parseError(code, e), } satisfies WorkerError, { status: 400, statusText: 'Code execution error' }, ); diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 15179a06..8fb1da7a 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -23,7 +23,7 @@ export async function codeTool(): Promise { const tool: Tool = { name: 'execute', description: - 'Runs TypeScript code to interact with the API.\nYou are a skilled programmer writing code to interface with the service.\nDefine an async function named "run" that takes a single parameter of an initialized client, and it will be run.\nDo not initialize a client, but instead use the client that you are given as a parameter.\nYou will be returned anything that your function returns, plus the results of any console.log statements.\nIf any code triggers an error, the tool will return an error response, so you do not need to add error handling unless you want to output something more helpful than the raw error.\nIt is not necessary to add comments to code, unless by adding those comments you believe that you can generate better code.\nThis code will run in a container, and you will not be able to use fetch or otherwise interact with the network calls other than through the client you are given.\nAny variables you define won\'t live between successive uses of this call, so make sure to return or log any data you might need later.', + 'Runs TypeScript code to interact with the API.\n\nYou are a skilled programmer writing code to interface with the service.\nDefine an async function named "run" that takes a single parameter of an initialized client named "client", and it will be run.\nWrite code within this template:\n\n```\nasync function run(client) {\n // Fill this out\n}\n```\n\nYou will be returned anything that your function returns, plus the results of any console.log statements.\nIf any code triggers an error, the tool will return an error response, so you do not need to add error handling unless you want to output something more helpful than the raw error.\nIt is not necessary to add comments to code, unless by adding those comments you believe that you can generate better code.\nThis code will run in a container, and you will not be able to use fetch or otherwise interact with the network calls other than through the client you are given.\nAny variables you define won\'t live between successive uses of this call, so make sure to return or log any data you might need later.', inputSchema: { type: 'object', properties: { code: { type: 'string' } } }, }; From cb1b2de75afc69765dc42d832b5a6cac991061b0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 7 Nov 2025 03:57:00 +0000 Subject: [PATCH 059/138] chore(internal): codegen related update --- packages/mcp-server/README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/mcp-server/README.md b/packages/mcp-server/README.md index 817d91fc..dbcca8ff 100644 --- a/packages/mcp-server/README.md +++ b/packages/mcp-server/README.md @@ -43,6 +43,22 @@ in Cursor's `mcp.json`, which can be found in Cursor Settings > Tools & MCP > Ne [![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=@corgi-tech/beagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiU2V0IHlvdXIgQkVBR0xFX0FQSV9LRVkgaGVyZS4ifX0) +### VS Code + +If you use MCP, you can install the MCP server by clicking the link below. You will need to set your environment variables +in VS Code's `mcp.json`, which can be found via Command Palette > MCP: Open User Configuration. + +[Open VS Code](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22Set%20your%20BEAGLE_API_KEY%20here.%22%7D%7D) + +### Claude Code + +If you use Claude Code, you can install the MCP server by running the command below in your terminal. You will need to set your +environment variables in Claude Code's `.claude.json`, which can be found in your home directory. + +``` +claude mcp add --transport stdio corgi_tech_beagle_api --env BEAGLE_API_KEY="Your BEAGLE_API_KEY here." -- npx -y @corgi-tech/beagle-mcp +``` + ## Exposing endpoints to your MCP Client There are three ways to expose endpoints as tools in the MCP server: From 473747085794925217e3c7e9e78acb21319cd87e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 8 Nov 2025 10:28:18 +0000 Subject: [PATCH 060/138] chore(internal): codegen related update --- packages/mcp-server/src/code-tool.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 8fb1da7a..e448e9b4 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -23,7 +23,7 @@ export async function codeTool(): Promise { const tool: Tool = { name: 'execute', description: - 'Runs TypeScript code to interact with the API.\n\nYou are a skilled programmer writing code to interface with the service.\nDefine an async function named "run" that takes a single parameter of an initialized client named "client", and it will be run.\nWrite code within this template:\n\n```\nasync function run(client) {\n // Fill this out\n}\n```\n\nYou will be returned anything that your function returns, plus the results of any console.log statements.\nIf any code triggers an error, the tool will return an error response, so you do not need to add error handling unless you want to output something more helpful than the raw error.\nIt is not necessary to add comments to code, unless by adding those comments you believe that you can generate better code.\nThis code will run in a container, and you will not be able to use fetch or otherwise interact with the network calls other than through the client you are given.\nAny variables you define won\'t live between successive uses of this call, so make sure to return or log any data you might need later.', + 'Runs JavaScript code to interact with the API.\n\nYou are a skilled programmer writing code to interface with the service.\nDefine an async function named "run" that takes a single parameter of an initialized client named "client", and it will be run.\nWrite code within this template:\n\n```\nasync function run(client) {\n // Fill this out\n}\n```\n\nYou will be returned anything that your function returns, plus the results of any console.log statements.\nIf any code triggers an error, the tool will return an error response, so you do not need to add error handling unless you want to output something more helpful than the raw error.\nIt is not necessary to add comments to code, unless by adding those comments you believe that you can generate better code.\nThis code will run in a container, and you will not be able to use fetch or otherwise interact with the network calls other than through the client you are given.\nAny variables you define won\'t live between successive uses of this call, so make sure to return or log any data you might need later.', inputSchema: { type: 'object', properties: { code: { type: 'string' } } }, }; From 198914f82467d8c6500b9f93f899d873c07550ff Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 11 Nov 2025 05:40:38 +0000 Subject: [PATCH 061/138] chore(internal): codegen related update --- packages/mcp-server/src/http.ts | 4 ++-- .../src/tools/enrollments/retrieve-certificate-enrollments.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index ec34ab47..84517003 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -46,12 +46,12 @@ const newServer = ({ }, mcpOptions, }); - } catch { + } catch (error) { res.status(401).json({ jsonrpc: '2.0', error: { code: -32000, - message: 'Unauthorized', + message: `Unauthorized: ${error instanceof Error ? error.message : error}`, }, }); return null; diff --git a/packages/mcp-server/src/tools/enrollments/retrieve-certificate-enrollments.ts b/packages/mcp-server/src/tools/enrollments/retrieve-certificate-enrollments.ts index 680e7ec9..1cef506a 100644 --- a/packages/mcp-server/src/tools/enrollments/retrieve-certificate-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/retrieve-certificate-enrollments.ts @@ -33,7 +33,7 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { id, ...body } = args as any; - return asBinaryContentResult(await client.enrollments.retrieveCertificate(id)); + return asBinaryContentResult(await client.enrollments.retrieveCertificate(id).asResponse()); }; export default { metadata, tool, handler }; From d4672351a7941a0395c9b23baaff9cacc179b93e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 11 Nov 2025 22:27:15 +0000 Subject: [PATCH 062/138] feat(api): api update --- .stats.yml | 4 +- src/resources/enrollments.ts | 38 ++++++++++++++ src/resources/plans.ts | 10 ++++ src/resources/property-managers.ts | 49 +++++++++++++++++++ src/resources/tenants.ts | 40 +++++++++++++++ tests/api-resources/enrollments.test.ts | 4 +- tests/api-resources/property-managers.test.ts | 6 +-- tests/api-resources/tenants.test.ts | 6 +-- tests/api-resources/webhook/endpoints.test.ts | 8 +-- 9 files changed, 151 insertions(+), 14 deletions(-) diff --git a/.stats.yml b/.stats.yml index d9bd89b4..6dc2ec4c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 23 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-d1482c73aaf0ee32c7bc9e8a8155ea5ef0c26a8947e54d57a95cfc396fe2e5ee.yml -openapi_spec_hash: cbee5e1d7eefcb7f445139055c448ab6 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-efa14cecc8a1594ca65d6987b7091cbfe7310b290eee8dcbc00875809993d4f0.yml +openapi_spec_hash: 09eea0dc2832424a2a46de36b0cc1bad config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/src/resources/enrollments.ts b/src/resources/enrollments.ts index 1ffee073..c8ba101d 100644 --- a/src/resources/enrollments.ts +++ b/src/resources/enrollments.ts @@ -10,6 +10,17 @@ import { path } from '../internal/utils/path'; export class Enrollments extends APIResource { /** * create a new enrollment for a tenant. + * + * @example + * ```ts + * const enrollment = await client.enrollments.create({ + * effectiveDate: 'effectiveDate', + * plan: 'plan', + * propertyManagerId: 0, + * status: 'Premium Paying', + * tenantId: 0, + * }); + * ``` */ create(body: EnrollmentCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/api/enrollments', { body, ...options }); @@ -17,6 +28,11 @@ export class Enrollments extends APIResource { /** * get a specific enrollment by its id. + * + * @example + * ```ts + * const enrollment = await client.enrollments.retrieve(123); + * ``` */ retrieve(id: number | null, options?: RequestOptions): APIPromise { return this._client.get(path`/api/enrollments/${id}`, options); @@ -25,6 +41,14 @@ export class Enrollments extends APIResource { /** * list all enrollments, this endpoint is paginated and allows for queries by * individual property manager. + * + * @example + * ```ts + * // Automatically fetches more pages as needed. + * for await (const enrollment of client.enrollments.list()) { + * // ... + * } + * ``` */ list( query: EnrollmentListParams | null | undefined = {}, @@ -39,6 +63,11 @@ export class Enrollments extends APIResource { /** * lapses a specific enrollment for a tenant, note that if a tenant has multiple * enrollments (e.g., SDR and TLL), each must be lapsed individually + * + * @example + * ```ts + * await client.enrollments.lapse(123); + * ``` */ lapse(id: number | null, options?: RequestOptions): APIPromise { return this._client.delete(path`/api/enrollments/${id}`, { @@ -49,6 +78,15 @@ export class Enrollments extends APIResource { /** * get the certificate of enrollment for a given enrollment + * + * @example + * ```ts + * const response = + * await client.enrollments.retrieveCertificate(123); + * + * const content = await response.blob(); + * console.log(content); + * ``` */ retrieveCertificate(id: number | null, options?: RequestOptions): APIPromise { return this._client.get(path`/api/enrollments/${id}/certificate`, { diff --git a/src/resources/plans.ts b/src/resources/plans.ts index bc18e96f..a61a3811 100644 --- a/src/resources/plans.ts +++ b/src/resources/plans.ts @@ -8,6 +8,11 @@ import { path } from '../internal/utils/path'; export class Plans extends APIResource { /** * retrieve a specific plans details by its code. + * + * @example + * ```ts + * const plan = await client.plans.retrieve('code'); + * ``` */ retrieve(code: string, options?: RequestOptions): APIPromise { return this._client.get(path`/api/plans/${code}`, options); @@ -16,6 +21,11 @@ export class Plans extends APIResource { /** * list all available plans, note this endpoint is currently unpaginated unlike all * other list endpoints. + * + * @example + * ```ts + * const plans = await client.plans.list(); + * ``` */ list(options?: RequestOptions): APIPromise { return this._client.get('/api/plans', options); diff --git a/src/resources/property-managers.ts b/src/resources/property-managers.ts index d620bb30..60333ecf 100644 --- a/src/resources/property-managers.ts +++ b/src/resources/property-managers.ts @@ -15,6 +15,30 @@ import { path } from '../internal/utils/path'; export class PropertyManagers extends APIResource { /** * create a new property manager. + * + * @example + * ```ts + * const propertyManager = + * await client.propertyManagers.create({ + * addresses: [ + * { + * city: 'city', + * state: 'xx', + * street1: 'street1', + * zip: '60513', + * kind: 'billing', + * }, + * ], + * contacts: [ + * { + * email: 'dev@stainless.com', + * name: { first: 'first', last: 'last' }, + * kind: 'agreements', + * }, + * ], + * name: 'name', + * }); + * ``` */ create(body: PropertyManagerCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/api/property-managers', { body, ...options }); @@ -22,6 +46,12 @@ export class PropertyManagers extends APIResource { /** * get a property manager by id. + * + * @example + * ```ts + * const propertyManager = + * await client.propertyManagers.retrieve(123); + * ``` */ retrieve(id: number | null, options?: RequestOptions): APIPromise { return this._client.get(path`/api/property-managers/${id}`, options); @@ -30,6 +60,12 @@ export class PropertyManagers extends APIResource { /** * update an existing property manager by id, note that when updating contacts or * addresses you need to send the whole array you want to replace them with. + * + * @example + * ```ts + * const propertyManager = + * await client.propertyManagers.update(123); + * ``` */ update( id: number | null, @@ -41,6 +77,14 @@ export class PropertyManagers extends APIResource { /** * list all property managers, note this endpoint is paginated. + * + * @example + * ```ts + * // Automatically fetches more pages as needed. + * for await (const propertyManager of client.propertyManagers.list()) { + * // ... + * } + * ``` */ list( query: PropertyManagerListParams | null | undefined = {}, @@ -54,6 +98,11 @@ export class PropertyManagers extends APIResource { /** * delete a property manager by id. + * + * @example + * ```ts + * await client.propertyManagers.delete(123); + * ``` */ delete(id: number | null, options?: RequestOptions): APIPromise { return this._client.delete(path`/api/property-managers/${id}`, { diff --git a/src/resources/tenants.ts b/src/resources/tenants.ts index 23ef673e..487dbce7 100644 --- a/src/resources/tenants.ts +++ b/src/resources/tenants.ts @@ -10,6 +10,23 @@ import { path } from '../internal/utils/path'; export class Tenants extends APIResource { /** * create a new tenant. + * + * @example + * ```ts + * const tenant = await client.tenants.create({ + * address: { + * city: 'city', + * state: 'xx', + * street1: 'street1', + * zip: '60513', + * }, + * contact: { + * email: 'dev@stainless.com', + * name: { first: 'first', last: 'last' }, + * }, + * propertyManagerId: 0, + * }); + * ``` */ create(body: TenantCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/api/tenants', { body, ...options }); @@ -17,6 +34,11 @@ export class Tenants extends APIResource { /** * retrieve a single tenant by their id. + * + * @example + * ```ts + * const tenant = await client.tenants.retrieve(123); + * ``` */ retrieve(id: number | null, options?: RequestOptions): APIPromise { return this._client.get(path`/api/tenants/${id}`, options); @@ -24,6 +46,11 @@ export class Tenants extends APIResource { /** * update an existing tenant by their id. + * + * @example + * ```ts + * const tenant = await client.tenants.update(123); + * ``` */ update(id: number | null, body: TenantUpdateParams, options?: RequestOptions): APIPromise { return this._client.patch(path`/api/tenants/${id}`, { body, ...options }); @@ -32,6 +59,14 @@ export class Tenants extends APIResource { /** * list all tenants, this endpoint is paginated and allows for queries by * individual property manager. + * + * @example + * ```ts + * // Automatically fetches more pages as needed. + * for await (const tenant of client.tenants.list()) { + * // ... + * } + * ``` */ list( query: TenantListParams | null | undefined = {}, @@ -42,6 +77,11 @@ export class Tenants extends APIResource { /** * delete an existing tenant by their id. + * + * @example + * ```ts + * await client.tenants.delete(123); + * ``` */ delete(id: number | null, options?: RequestOptions): APIPromise { return this._client.delete(path`/api/tenants/${id}`, { diff --git a/tests/api-resources/enrollments.test.ts b/tests/api-resources/enrollments.test.ts index 68f133df..73c108d9 100644 --- a/tests/api-resources/enrollments.test.ts +++ b/tests/api-resources/enrollments.test.ts @@ -40,7 +40,7 @@ describe('resource enrollments', () => { // Prism tests are disabled test.skip('retrieve', async () => { - const responsePromise = client.enrollments.retrieve(42); + const responsePromise = client.enrollments.retrieve(123); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -75,7 +75,7 @@ describe('resource enrollments', () => { // Prism tests are disabled test.skip('lapse', async () => { - const responsePromise = client.enrollments.lapse(42); + const responsePromise = client.enrollments.lapse(123); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; diff --git a/tests/api-resources/property-managers.test.ts b/tests/api-resources/property-managers.test.ts index 84d2e598..28de7542 100644 --- a/tests/api-resources/property-managers.test.ts +++ b/tests/api-resources/property-managers.test.ts @@ -45,7 +45,7 @@ describe('resource propertyManagers', () => { // Prism tests are disabled test.skip('retrieve', async () => { - const responsePromise = client.propertyManagers.retrieve(42); + const responsePromise = client.propertyManagers.retrieve(123); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -57,7 +57,7 @@ describe('resource propertyManagers', () => { // Prism tests are disabled test.skip('update', async () => { - const responsePromise = client.propertyManagers.update(42, {}); + const responsePromise = client.propertyManagers.update(123, {}); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -89,7 +89,7 @@ describe('resource propertyManagers', () => { // Prism tests are disabled test.skip('delete', async () => { - const responsePromise = client.propertyManagers.delete(42); + const responsePromise = client.propertyManagers.delete(123); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; diff --git a/tests/api-resources/tenants.test.ts b/tests/api-resources/tenants.test.ts index 7fed1449..ea1eb026 100644 --- a/tests/api-resources/tenants.test.ts +++ b/tests/api-resources/tenants.test.ts @@ -35,7 +35,7 @@ describe('resource tenants', () => { // Prism tests are disabled test.skip('retrieve', async () => { - const responsePromise = client.tenants.retrieve(42); + const responsePromise = client.tenants.retrieve(123); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -47,7 +47,7 @@ describe('resource tenants', () => { // Prism tests are disabled test.skip('update', async () => { - const responsePromise = client.tenants.update(42, {}); + const responsePromise = client.tenants.update(123, {}); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -79,7 +79,7 @@ describe('resource tenants', () => { // Prism tests are disabled test.skip('delete', async () => { - const responsePromise = client.tenants.delete(42); + const responsePromise = client.tenants.delete(123); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; diff --git a/tests/api-resources/webhook/endpoints.test.ts b/tests/api-resources/webhook/endpoints.test.ts index eedc632b..4f03592d 100644 --- a/tests/api-resources/webhook/endpoints.test.ts +++ b/tests/api-resources/webhook/endpoints.test.ts @@ -31,7 +31,7 @@ describe('resource endpoints', () => { // Prism tests are disabled test.skip('retrieve', async () => { - const responsePromise = client.webhook.endpoints.retrieve(42); + const responsePromise = client.webhook.endpoints.retrieve(123); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -43,7 +43,7 @@ describe('resource endpoints', () => { // Prism tests are disabled test.skip('update: only required params', async () => { - const responsePromise = client.webhook.endpoints.update(42, { + const responsePromise = client.webhook.endpoints.update(123, { secret: 'secret', url: 'https://example.com', }); @@ -58,7 +58,7 @@ describe('resource endpoints', () => { // Prism tests are disabled test.skip('update: required and optional params', async () => { - const response = await client.webhook.endpoints.update(42, { + const response = await client.webhook.endpoints.update(123, { secret: 'secret', url: 'https://example.com', active: true, @@ -87,7 +87,7 @@ describe('resource endpoints', () => { // Prism tests are disabled test.skip('delete', async () => { - const responsePromise = client.webhook.endpoints.delete(42); + const responsePromise = client.webhook.endpoints.delete(123); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; From b346b4a57a5aaf2b7531daf166e5ba375c98e2f9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 13 Nov 2025 05:08:42 +0000 Subject: [PATCH 063/138] chore(internal): codegen related update --- packages/mcp-server/package.json | 2 +- packages/mcp-server/src/filtering.ts | 4 ++++ .../src/tools/enrollments/create-enrollments.ts | 13 ++++++++++--- .../src/tools/enrollments/list-enrollments.ts | 13 ++++++++++--- .../src/tools/enrollments/retrieve-enrollments.ts | 13 ++++++++++--- .../verify-insurance-verification.ts | 13 ++++++++++--- packages/mcp-server/src/tools/plans/list-plans.ts | 13 ++++++++++--- .../mcp-server/src/tools/plans/retrieve-plans.ts | 13 ++++++++++--- .../property-managers/create-property-managers.ts | 13 ++++++++++--- .../property-managers/list-property-managers.ts | 13 ++++++++++--- .../property-managers/retrieve-property-managers.ts | 13 ++++++++++--- .../property-managers/update-property-managers.ts | 13 ++++++++++--- .../mcp-server/src/tools/tenants/create-tenants.ts | 13 ++++++++++--- .../mcp-server/src/tools/tenants/list-tenants.ts | 13 ++++++++++--- .../src/tools/tenants/retrieve-tenants.ts | 13 ++++++++++--- .../mcp-server/src/tools/tenants/update-tenants.ts | 13 ++++++++++--- packages/mcp-server/src/tools/types.ts | 12 ++++++++++++ .../webhook/endpoints/create-webhook-endpoints.ts | 13 ++++++++++--- .../webhook/endpoints/list-webhook-endpoints.ts | 13 ++++++++++--- .../webhook/endpoints/retrieve-webhook-endpoints.ts | 13 ++++++++++--- .../webhook/endpoints/update-webhook-endpoints.ts | 13 ++++++++++--- packages/mcp-server/yarn.lock | 6 +++--- 22 files changed, 200 insertions(+), 58 deletions(-) diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index c4eaf223..8402437b 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -37,7 +37,7 @@ "cors": "^2.8.5", "express": "^5.1.0", "fuse.js": "^7.1.0", - "jq-web": "https://github.com/stainless-api/jq-web/releases/download/v0.8.6/jq-web.tar.gz", + "jq-web": "https://github.com/stainless-api/jq-web/releases/download/v0.8.8/jq-web.tar.gz", "qs": "^6.14.0", "typescript": "5.8.3", "yargs": "^17.7.2", diff --git a/packages/mcp-server/src/filtering.ts b/packages/mcp-server/src/filtering.ts index 1aa9a40c..eaae0fcf 100644 --- a/packages/mcp-server/src/filtering.ts +++ b/packages/mcp-server/src/filtering.ts @@ -12,3 +12,7 @@ export async function maybeFilter(jqFilter: unknown | undefined, response: any): async function jq(json: any, jqFilter: string) { return (await initJq).json(json, jqFilter); } + +export function isJqError(error: any): error is Error { + return error instanceof Error && 'stderr' in error; +} diff --git a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts index 734b1654..f4a6d1a1 100644 --- a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; +import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; @@ -67,7 +67,14 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.enrollments.create(body))); + try { + return asTextContentResult(await maybeFilter(jq_filter, await client.enrollments.create(body))); + } catch (error) { + if (isJqError(error)) { + return asErrorResult(error.message); + } + throw error; + } }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts index 96c28d73..5cbed8fb 100644 --- a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; +import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; @@ -50,7 +50,14 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { jq_filter, ...body } = args as any; const response = await client.enrollments.list(body).asResponse(); - return asTextContentResult(await maybeFilter(jq_filter, await response.json())); + try { + return asTextContentResult(await maybeFilter(jq_filter, await response.json())); + } catch (error) { + if (isJqError(error)) { + return asErrorResult(error.message); + } + throw error; + } }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts index f17a691a..1a4c1e8d 100644 --- a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; +import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; @@ -41,7 +41,14 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { id, jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.enrollments.retrieve(id))); + try { + return asTextContentResult(await maybeFilter(jq_filter, await client.enrollments.retrieve(id))); + } catch (error) { + if (isJqError(error)) { + return asErrorResult(error.message); + } + throw error; + } }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts index 21185cf8..d822ebf7 100644 --- a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts +++ b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; +import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; @@ -49,7 +49,14 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.insuranceVerification.verify(body))); + try { + return asTextContentResult(await maybeFilter(jq_filter, await client.insuranceVerification.verify(body))); + } catch (error) { + if (isJqError(error)) { + return asErrorResult(error.message); + } + throw error; + } }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/plans/list-plans.ts b/packages/mcp-server/src/tools/plans/list-plans.ts index 6f672500..a12a3a62 100644 --- a/packages/mcp-server/src/tools/plans/list-plans.ts +++ b/packages/mcp-server/src/tools/plans/list-plans.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; +import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; @@ -38,7 +38,14 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { jq_filter } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.plans.list())); + try { + return asTextContentResult(await maybeFilter(jq_filter, await client.plans.list())); + } catch (error) { + if (isJqError(error)) { + return asErrorResult(error.message); + } + throw error; + } }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/plans/retrieve-plans.ts b/packages/mcp-server/src/tools/plans/retrieve-plans.ts index c388d98c..7a3c9898 100644 --- a/packages/mcp-server/src/tools/plans/retrieve-plans.ts +++ b/packages/mcp-server/src/tools/plans/retrieve-plans.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; +import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; @@ -41,7 +41,14 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { code, jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.plans.retrieve(code))); + try { + return asTextContentResult(await maybeFilter(jq_filter, await client.plans.retrieve(code))); + } catch (error) { + if (isJqError(error)) { + return asErrorResult(error.message); + } + throw error; + } }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts index c4d819a1..3c15cc72 100644 --- a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; +import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; @@ -112,7 +112,14 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.propertyManagers.create(body))); + try { + return asTextContentResult(await maybeFilter(jq_filter, await client.propertyManagers.create(body))); + } catch (error) { + if (isJqError(error)) { + return asErrorResult(error.message); + } + throw error; + } }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts index 126b6bd9..24a54c63 100644 --- a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; +import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; @@ -47,7 +47,14 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { jq_filter, ...body } = args as any; const response = await client.propertyManagers.list(body).asResponse(); - return asTextContentResult(await maybeFilter(jq_filter, await response.json())); + try { + return asTextContentResult(await maybeFilter(jq_filter, await response.json())); + } catch (error) { + if (isJqError(error)) { + return asErrorResult(error.message); + } + throw error; + } }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts index a52fd678..e3c092ff 100644 --- a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; +import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; @@ -41,7 +41,14 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { id, jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.propertyManagers.retrieve(id))); + try { + return asTextContentResult(await maybeFilter(jq_filter, await client.propertyManagers.retrieve(id))); + } catch (error) { + if (isJqError(error)) { + return asErrorResult(error.message); + } + throw error; + } }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts index 8fe9f605..52cb1c15 100644 --- a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; +import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; @@ -115,7 +115,14 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { id, jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.propertyManagers.update(id, body))); + try { + return asTextContentResult(await maybeFilter(jq_filter, await client.propertyManagers.update(id, body))); + } catch (error) { + if (isJqError(error)) { + return asErrorResult(error.message); + } + throw error; + } }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/tenants/create-tenants.ts b/packages/mcp-server/src/tools/tenants/create-tenants.ts index 08fea80a..1b7c2ca4 100644 --- a/packages/mcp-server/src/tools/tenants/create-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/create-tenants.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; +import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; @@ -94,7 +94,14 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.tenants.create(body))); + try { + return asTextContentResult(await maybeFilter(jq_filter, await client.tenants.create(body))); + } catch (error) { + if (isJqError(error)) { + return asErrorResult(error.message); + } + throw error; + } }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/tenants/list-tenants.ts b/packages/mcp-server/src/tools/tenants/list-tenants.ts index 25e49579..606946c5 100644 --- a/packages/mcp-server/src/tools/tenants/list-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/list-tenants.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; +import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; @@ -50,7 +50,14 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { jq_filter, ...body } = args as any; const response = await client.tenants.list(body).asResponse(); - return asTextContentResult(await maybeFilter(jq_filter, await response.json())); + try { + return asTextContentResult(await maybeFilter(jq_filter, await response.json())); + } catch (error) { + if (isJqError(error)) { + return asErrorResult(error.message); + } + throw error; + } }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts b/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts index 280c63a4..ed4fa11e 100644 --- a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; +import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; @@ -41,7 +41,14 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { id, jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.tenants.retrieve(id))); + try { + return asTextContentResult(await maybeFilter(jq_filter, await client.tenants.retrieve(id))); + } catch (error) { + if (isJqError(error)) { + return asErrorResult(error.message); + } + throw error; + } }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/tenants/update-tenants.ts b/packages/mcp-server/src/tools/tenants/update-tenants.ts index e63e96b7..215423b3 100644 --- a/packages/mcp-server/src/tools/tenants/update-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/update-tenants.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; +import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; @@ -94,7 +94,14 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { id, jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.tenants.update(id, body))); + try { + return asTextContentResult(await maybeFilter(jq_filter, await client.tenants.update(id, body))); + } catch (error) { + if (isJqError(error)) { + return asErrorResult(error.message); + } + throw error; + } }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/types.ts b/packages/mcp-server/src/tools/types.ts index 9baf238e..1661b689 100644 --- a/packages/mcp-server/src/tools/types.ts +++ b/packages/mcp-server/src/tools/types.ts @@ -87,6 +87,18 @@ export async function asBinaryContentResult(response: Response): Promise | undefined) => { const { jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.webhook.endpoints.create(body))); + try { + return asTextContentResult(await maybeFilter(jq_filter, await client.webhook.endpoints.create(body))); + } catch (error) { + if (isJqError(error)) { + return asErrorResult(error.message); + } + throw error; + } }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts index 3a5936ad..f521b2f6 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; +import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; @@ -47,7 +47,14 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { jq_filter, ...body } = args as any; const response = await client.webhook.endpoints.list(body).asResponse(); - return asTextContentResult(await maybeFilter(jq_filter, await response.json())); + try { + return asTextContentResult(await maybeFilter(jq_filter, await response.json())); + } catch (error) { + if (isJqError(error)) { + return asErrorResult(error.message); + } + throw error; + } }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts index 794fbdf9..bcb6425a 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; +import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; @@ -41,7 +41,14 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { id, jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.webhook.endpoints.retrieve(id))); + try { + return asTextContentResult(await maybeFilter(jq_filter, await client.webhook.endpoints.retrieve(id))); + } catch (error) { + if (isJqError(error)) { + return asErrorResult(error.message); + } + throw error; + } }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts index fe0f3777..e443f9d3 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; +import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; +import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import Beagle from '@corgi-tech/beagle'; @@ -48,7 +48,14 @@ export const tool: Tool = { export const handler = async (client: Beagle, args: Record | undefined) => { const { id, jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.webhook.endpoints.update(id, body))); + try { + return asTextContentResult(await maybeFilter(jq_filter, await client.webhook.endpoints.update(id, body))); + } catch (error) { + if (isJqError(error)) { + return asErrorResult(error.message); + } + throw error; + } }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/yarn.lock b/packages/mcp-server/yarn.lock index 966d0575..2bb21c66 100644 --- a/packages/mcp-server/yarn.lock +++ b/packages/mcp-server/yarn.lock @@ -2494,9 +2494,9 @@ jest@^29.4.0: import-local "^3.0.2" jest-cli "^29.7.0" -"jq-web@https://github.com/stainless-api/jq-web/releases/download/v0.8.6/jq-web.tar.gz": - version "0.8.6" - resolved "https://github.com/stainless-api/jq-web/releases/download/v0.8.6/jq-web.tar.gz#14d0e126987736e82e964d675c3838b5944faa6f" +"jq-web@https://github.com/stainless-api/jq-web/releases/download/v0.8.8/jq-web.tar.gz": + version "0.8.8" + resolved "https://github.com/stainless-api/jq-web/releases/download/v0.8.8/jq-web.tar.gz#7849ef64bdfc28f70cbfc9888f886860e96da10d" js-tokens@^4.0.0: version "4.0.0" From f141204909ece06b927458df3dc99c23d3f0a3ee Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 26 Nov 2025 05:58:12 +0000 Subject: [PATCH 064/138] chore(internal): codegen related update --- packages/mcp-server/src/docs-search-tool.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/mcp-server/src/docs-search-tool.ts b/packages/mcp-server/src/docs-search-tool.ts index dca82a8e..bb450d09 100644 --- a/packages/mcp-server/src/docs-search-tool.ts +++ b/packages/mcp-server/src/docs-search-tool.ts @@ -13,8 +13,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'search_docs', - description: - 'Search for documentation for how to use the client to interact with the API.\nThe tool will return an array of Markdown-formatted documentation pages.', + description: 'Search for documentation for how to use the client to interact with the API.', inputSchema: { type: 'object', properties: { @@ -25,7 +24,12 @@ export const tool: Tool = { language: { type: 'string', description: 'The language for the SDK to search for.', - enum: ['http', 'python', 'go', 'typescript', 'terraform', 'ruby', 'java', 'kotlin'], + enum: ['http', 'python', 'go', 'typescript', 'javascript', 'terraform', 'ruby', 'java', 'kotlin'], + }, + detail: { + type: 'string', + description: 'The amount of detail to return.', + enum: ['default', 'verbose'], }, }, required: ['query', 'language'], From e54e04f77fc224bd3488ac7ef09738788af68071 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 07:00:37 +0000 Subject: [PATCH 065/138] chore(internal): codegen related update --- packages/mcp-server/src/code-tool-types.ts | 6 ++++- packages/mcp-server/src/code-tool-worker.ts | 6 +++++ packages/mcp-server/src/code-tool.ts | 25 +++++++++++++++++-- .../tools/enrollments/create-enrollments.ts | 2 +- .../src/tools/enrollments/list-enrollments.ts | 2 +- .../tools/enrollments/retrieve-enrollments.ts | 2 +- .../verify-insurance-verification.ts | 2 +- .../mcp-server/src/tools/plans/list-plans.ts | 2 +- .../src/tools/plans/retrieve-plans.ts | 2 +- .../create-property-managers.ts | 2 +- .../list-property-managers.ts | 2 +- .../retrieve-property-managers.ts | 2 +- .../update-property-managers.ts | 2 +- .../src/tools/tenants/create-tenants.ts | 2 +- .../src/tools/tenants/list-tenants.ts | 2 +- .../src/tools/tenants/retrieve-tenants.ts | 2 +- .../src/tools/tenants/update-tenants.ts | 2 +- .../endpoints/create-webhook-endpoints.ts | 2 +- .../endpoints/list-webhook-endpoints.ts | 2 +- .../endpoints/retrieve-webhook-endpoints.ts | 2 +- .../endpoints/update-webhook-endpoints.ts | 2 +- src/client.ts | 2 +- 22 files changed, 53 insertions(+), 22 deletions(-) diff --git a/packages/mcp-server/src/code-tool-types.ts b/packages/mcp-server/src/code-tool-types.ts index ab0f0c1d..6ab80a26 100644 --- a/packages/mcp-server/src/code-tool-types.ts +++ b/packages/mcp-server/src/code-tool-types.ts @@ -11,4 +11,8 @@ export type WorkerSuccess = { logLines: string[]; errLines: string[]; }; -export type WorkerError = { message: string | undefined }; +export type WorkerError = { + message: string | undefined; + logLines: string[]; + errLines: string[]; +}; diff --git a/packages/mcp-server/src/code-tool-worker.ts b/packages/mcp-server/src/code-tool-worker.ts index 0dbe46fc..ed1a6129 100644 --- a/packages/mcp-server/src/code-tool-worker.ts +++ b/packages/mcp-server/src/code-tool-worker.ts @@ -165,6 +165,8 @@ const fetch = async (req: Request): Promise => { { message: 'The code param is missing. Provide one containing a top-level `run` function. Write code within this template:\n\n```\nasync function run(client) {\n // Fill this out\n}\n```', + logLines: [], + errLines: [], } satisfies WorkerError, { status: 400, statusText: 'Code execution error' }, ); @@ -176,6 +178,8 @@ const fetch = async (req: Request): Promise => { { message: 'The code is missing a top-level `run` function. Write code within this template:\n\n```\nasync function run(client) {\n // Fill this out\n}\n```', + logLines: [], + errLines: [], } satisfies WorkerError, { status: 400, statusText: 'Code execution error' }, ); @@ -208,6 +212,8 @@ const fetch = async (req: Request): Promise => { return Response.json( { message: parseError(code, e), + logLines, + errLines, } satisfies WorkerError, { status: 400, statusText: 'Code execution error' }, ); diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index e448e9b4..470e378b 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -132,9 +132,30 @@ export async function codeTool(): Promise { content: [returnOutput, logOutput, errOutput].filter((block) => block !== null), }; } else { - const { message } = (await resp.json()) as WorkerError; + const { message, logLines, errLines } = (await resp.json()) as WorkerError; + const messageOutput: ContentBlock | null = + message == null ? null : ( + { + type: 'text', + text: message, + } + ); + const logOutput: ContentBlock | null = + logLines.length === 0 ? + null + : { + type: 'text', + text: logLines.join('\n'), + }; + const errOutput: ContentBlock | null = + errLines.length === 0 ? + null + : { + type: 'text', + text: 'Error output:\n' + errLines.join('\n'), + }; return { - content: message == null ? [] : [{ type: 'text', text: message }], + content: [messageOutput, logOutput, errOutput].filter((block) => block !== null), isError: true, }; } diff --git a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts index f4a6d1a1..9ab1960e 100644 --- a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts @@ -70,7 +70,7 @@ export const handler = async (client: Beagle, args: Record | un try { return asTextContentResult(await maybeFilter(jq_filter, await client.enrollments.create(body))); } catch (error) { - if (isJqError(error)) { + if (error instanceof Beagle.APIError || isJqError(error)) { return asErrorResult(error.message); } throw error; diff --git a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts index 5cbed8fb..838be244 100644 --- a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts @@ -53,7 +53,7 @@ export const handler = async (client: Beagle, args: Record | un try { return asTextContentResult(await maybeFilter(jq_filter, await response.json())); } catch (error) { - if (isJqError(error)) { + if (error instanceof Beagle.APIError || isJqError(error)) { return asErrorResult(error.message); } throw error; diff --git a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts index 1a4c1e8d..574e8264 100644 --- a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts +++ b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts @@ -44,7 +44,7 @@ export const handler = async (client: Beagle, args: Record | un try { return asTextContentResult(await maybeFilter(jq_filter, await client.enrollments.retrieve(id))); } catch (error) { - if (isJqError(error)) { + if (error instanceof Beagle.APIError || isJqError(error)) { return asErrorResult(error.message); } throw error; diff --git a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts index d822ebf7..36b30a6c 100644 --- a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts +++ b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts @@ -52,7 +52,7 @@ export const handler = async (client: Beagle, args: Record | un try { return asTextContentResult(await maybeFilter(jq_filter, await client.insuranceVerification.verify(body))); } catch (error) { - if (isJqError(error)) { + if (error instanceof Beagle.APIError || isJqError(error)) { return asErrorResult(error.message); } throw error; diff --git a/packages/mcp-server/src/tools/plans/list-plans.ts b/packages/mcp-server/src/tools/plans/list-plans.ts index a12a3a62..3c359a7b 100644 --- a/packages/mcp-server/src/tools/plans/list-plans.ts +++ b/packages/mcp-server/src/tools/plans/list-plans.ts @@ -41,7 +41,7 @@ export const handler = async (client: Beagle, args: Record | un try { return asTextContentResult(await maybeFilter(jq_filter, await client.plans.list())); } catch (error) { - if (isJqError(error)) { + if (error instanceof Beagle.APIError || isJqError(error)) { return asErrorResult(error.message); } throw error; diff --git a/packages/mcp-server/src/tools/plans/retrieve-plans.ts b/packages/mcp-server/src/tools/plans/retrieve-plans.ts index 7a3c9898..565640f4 100644 --- a/packages/mcp-server/src/tools/plans/retrieve-plans.ts +++ b/packages/mcp-server/src/tools/plans/retrieve-plans.ts @@ -44,7 +44,7 @@ export const handler = async (client: Beagle, args: Record | un try { return asTextContentResult(await maybeFilter(jq_filter, await client.plans.retrieve(code))); } catch (error) { - if (isJqError(error)) { + if (error instanceof Beagle.APIError || isJqError(error)) { return asErrorResult(error.message); } throw error; diff --git a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts index 3c15cc72..94b00903 100644 --- a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts @@ -115,7 +115,7 @@ export const handler = async (client: Beagle, args: Record | un try { return asTextContentResult(await maybeFilter(jq_filter, await client.propertyManagers.create(body))); } catch (error) { - if (isJqError(error)) { + if (error instanceof Beagle.APIError || isJqError(error)) { return asErrorResult(error.message); } throw error; diff --git a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts index 24a54c63..25f4407a 100644 --- a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts @@ -50,7 +50,7 @@ export const handler = async (client: Beagle, args: Record | un try { return asTextContentResult(await maybeFilter(jq_filter, await response.json())); } catch (error) { - if (isJqError(error)) { + if (error instanceof Beagle.APIError || isJqError(error)) { return asErrorResult(error.message); } throw error; diff --git a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts index e3c092ff..46a021ae 100644 --- a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts @@ -44,7 +44,7 @@ export const handler = async (client: Beagle, args: Record | un try { return asTextContentResult(await maybeFilter(jq_filter, await client.propertyManagers.retrieve(id))); } catch (error) { - if (isJqError(error)) { + if (error instanceof Beagle.APIError || isJqError(error)) { return asErrorResult(error.message); } throw error; diff --git a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts index 52cb1c15..19e93b04 100644 --- a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts +++ b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts @@ -118,7 +118,7 @@ export const handler = async (client: Beagle, args: Record | un try { return asTextContentResult(await maybeFilter(jq_filter, await client.propertyManagers.update(id, body))); } catch (error) { - if (isJqError(error)) { + if (error instanceof Beagle.APIError || isJqError(error)) { return asErrorResult(error.message); } throw error; diff --git a/packages/mcp-server/src/tools/tenants/create-tenants.ts b/packages/mcp-server/src/tools/tenants/create-tenants.ts index 1b7c2ca4..5ab34358 100644 --- a/packages/mcp-server/src/tools/tenants/create-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/create-tenants.ts @@ -97,7 +97,7 @@ export const handler = async (client: Beagle, args: Record | un try { return asTextContentResult(await maybeFilter(jq_filter, await client.tenants.create(body))); } catch (error) { - if (isJqError(error)) { + if (error instanceof Beagle.APIError || isJqError(error)) { return asErrorResult(error.message); } throw error; diff --git a/packages/mcp-server/src/tools/tenants/list-tenants.ts b/packages/mcp-server/src/tools/tenants/list-tenants.ts index 606946c5..cd3f4bda 100644 --- a/packages/mcp-server/src/tools/tenants/list-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/list-tenants.ts @@ -53,7 +53,7 @@ export const handler = async (client: Beagle, args: Record | un try { return asTextContentResult(await maybeFilter(jq_filter, await response.json())); } catch (error) { - if (isJqError(error)) { + if (error instanceof Beagle.APIError || isJqError(error)) { return asErrorResult(error.message); } throw error; diff --git a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts b/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts index ed4fa11e..0d796a20 100644 --- a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts @@ -44,7 +44,7 @@ export const handler = async (client: Beagle, args: Record | un try { return asTextContentResult(await maybeFilter(jq_filter, await client.tenants.retrieve(id))); } catch (error) { - if (isJqError(error)) { + if (error instanceof Beagle.APIError || isJqError(error)) { return asErrorResult(error.message); } throw error; diff --git a/packages/mcp-server/src/tools/tenants/update-tenants.ts b/packages/mcp-server/src/tools/tenants/update-tenants.ts index 215423b3..d42c6589 100644 --- a/packages/mcp-server/src/tools/tenants/update-tenants.ts +++ b/packages/mcp-server/src/tools/tenants/update-tenants.ts @@ -97,7 +97,7 @@ export const handler = async (client: Beagle, args: Record | un try { return asTextContentResult(await maybeFilter(jq_filter, await client.tenants.update(id, body))); } catch (error) { - if (isJqError(error)) { + if (error instanceof Beagle.APIError || isJqError(error)) { return asErrorResult(error.message); } throw error; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts index 5c5baa92..7fa0b8be 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts @@ -48,7 +48,7 @@ export const handler = async (client: Beagle, args: Record | un try { return asTextContentResult(await maybeFilter(jq_filter, await client.webhook.endpoints.create(body))); } catch (error) { - if (isJqError(error)) { + if (error instanceof Beagle.APIError || isJqError(error)) { return asErrorResult(error.message); } throw error; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts index f521b2f6..1878dcd0 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts @@ -50,7 +50,7 @@ export const handler = async (client: Beagle, args: Record | un try { return asTextContentResult(await maybeFilter(jq_filter, await response.json())); } catch (error) { - if (isJqError(error)) { + if (error instanceof Beagle.APIError || isJqError(error)) { return asErrorResult(error.message); } throw error; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts index bcb6425a..77acb182 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts @@ -44,7 +44,7 @@ export const handler = async (client: Beagle, args: Record | un try { return asTextContentResult(await maybeFilter(jq_filter, await client.webhook.endpoints.retrieve(id))); } catch (error) { - if (isJqError(error)) { + if (error instanceof Beagle.APIError || isJqError(error)) { return asErrorResult(error.message); } throw error; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts index e443f9d3..588ba2ce 100644 --- a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts +++ b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts @@ -51,7 +51,7 @@ export const handler = async (client: Beagle, args: Record | un try { return asTextContentResult(await maybeFilter(jq_filter, await client.webhook.endpoints.update(id, body))); } catch (error) { - if (isJqError(error)) { + if (error instanceof Beagle.APIError || isJqError(error)) { return asErrorResult(error.message); } throw error; diff --git a/src/client.ts b/src/client.ts index b7bf3cf1..93fcd308 100644 --- a/src/client.ts +++ b/src/client.ts @@ -173,7 +173,7 @@ export class Beagle { baseURL: string; maxRetries: number; timeout: number; - logger: Logger | undefined; + logger: Logger; logLevel: LogLevel | undefined; fetchOptions: MergedRequestInit | undefined; From 3c63419f86cd723812abc2984d6ca518f32d8ad4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 3 Dec 2025 06:51:38 +0000 Subject: [PATCH 066/138] chore(internal): codegen related update --- package.json | 2 +- yarn.lock | 150 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 89 insertions(+), 63 deletions(-) diff --git a/package.json b/package.json index 184c451a..bd1ab12d 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "@types/node": "^20.17.6", "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", - "eslint": "^9.20.1", + "eslint": "^9.39.1", "eslint-plugin-prettier": "^5.4.1", "eslint-plugin-unused-imports": "^4.1.4", "iconv-lite": "^0.6.3", diff --git a/yarn.lock b/yarn.lock index 8311caf5..5f56a201 100644 --- a/yarn.lock +++ b/yarn.lock @@ -350,45 +350,52 @@ dependencies: "@cspotcode/source-map-consumer" "0.8.0" -"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": +"@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== dependencies: eslint-visitor-keys "^3.3.0" +"@eslint-community/eslint-utils@^4.8.0": + version "4.9.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz#7308df158e064f0dd8b8fdb58aa14fa2a7f913b3" + integrity sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g== + dependencies: + eslint-visitor-keys "^3.4.3" + "@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1": version "4.12.1" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== -"@eslint/config-array@^0.19.0": - version "0.19.2" - resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.19.2.tgz#3060b809e111abfc97adb0bb1172778b90cb46aa" - integrity sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w== +"@eslint/config-array@^0.21.1": + version "0.21.1" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.21.1.tgz#7d1b0060fea407f8301e932492ba8c18aff29713" + integrity sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA== dependencies: - "@eslint/object-schema" "^2.1.6" + "@eslint/object-schema" "^2.1.7" debug "^4.3.1" minimatch "^3.1.2" -"@eslint/core@^0.10.0": - version "0.10.0" - resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.10.0.tgz#23727063c21b335f752dbb3a16450f6f9cbc9091" - integrity sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw== +"@eslint/config-helpers@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.4.2.tgz#1bd006ceeb7e2e55b2b773ab318d300e1a66aeda" + integrity sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw== dependencies: - "@types/json-schema" "^7.0.15" + "@eslint/core" "^0.17.0" -"@eslint/core@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.11.0.tgz#7a9226e850922e42cbd2ba71361eacbe74352a12" - integrity sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA== +"@eslint/core@^0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.17.0.tgz#77225820413d9617509da9342190a2019e78761c" + integrity sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ== dependencies: "@types/json-schema" "^7.0.15" -"@eslint/eslintrc@^3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.2.0.tgz#57470ac4e2e283a6bf76044d63281196e370542c" - integrity sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w== +"@eslint/eslintrc@^3.3.1": + version "3.3.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.3.tgz#26393a0806501b5e2b6a43aa588a4d8df67880ac" + integrity sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ== dependencies: ajv "^6.12.4" debug "^4.3.2" @@ -396,26 +403,26 @@ globals "^14.0.0" ignore "^5.2.0" import-fresh "^3.2.1" - js-yaml "^4.1.0" + js-yaml "^4.1.1" minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@9.20.0": - version "9.20.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.20.0.tgz#7421bcbe74889fcd65d1be59f00130c289856eb4" - integrity sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ== +"@eslint/js@9.39.1": + version "9.39.1" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.39.1.tgz#0dd59c3a9f40e3f1882975c321470969243e0164" + integrity sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw== -"@eslint/object-schema@^2.1.6": - version "2.1.6" - resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" - integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== +"@eslint/object-schema@^2.1.7": + version "2.1.7" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.7.tgz#6e2126a1347e86a4dedf8706ec67ff8e107ebbad" + integrity sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA== -"@eslint/plugin-kit@^0.2.5": - version "0.2.5" - resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz#ee07372035539e7847ef834e3f5e7b79f09e3a81" - integrity sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A== +"@eslint/plugin-kit@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz#9779e3fd9b7ee33571a57435cf4335a1794a6cb2" + integrity sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA== dependencies: - "@eslint/core" "^0.10.0" + "@eslint/core" "^0.17.0" levn "^0.4.1" "@humanfs/core@^0.19.1": @@ -441,10 +448,10 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== -"@humanwhocodes/retry@^0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.1.tgz#9a96ce501bc62df46c4031fbd970e3cc6b10f07b" - integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA== +"@humanwhocodes/retry@^0.4.2": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.3.tgz#c2b9d2e374ee62c586d3adbea87199b1d7a7a6ba" + integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" @@ -1057,6 +1064,11 @@ acorn@^8.14.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== +acorn@^8.15.0: + version "8.15.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== + acorn@^8.4.1: version "8.7.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" @@ -1560,15 +1572,15 @@ eslint-plugin-unused-imports@^4.1.4: resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz#62ddc7446ccbf9aa7b6f1f0b00a980423cda2738" integrity sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ== -eslint-scope@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.2.0.tgz#377aa6f1cb5dc7592cfd0b7f892fd0cf352ce442" - integrity sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A== +eslint-scope@^8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.4.0.tgz#88e646a207fad61436ffa39eb505147200655c82" + integrity sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-visitor-keys@^3.3.0: +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== @@ -1578,31 +1590,36 @@ eslint-visitor-keys@^4.2.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== -eslint@^9.20.1: - version "9.20.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.20.1.tgz#923924c078f5226832449bac86662dd7e53c91d6" - integrity sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g== +eslint-visitor-keys@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" + integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== + +eslint@^9.39.1: + version "9.39.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.39.1.tgz#be8bf7c6de77dcc4252b5a8dcb31c2efff74a6e5" + integrity sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g== dependencies: - "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/eslint-utils" "^4.8.0" "@eslint-community/regexpp" "^4.12.1" - "@eslint/config-array" "^0.19.0" - "@eslint/core" "^0.11.0" - "@eslint/eslintrc" "^3.2.0" - "@eslint/js" "9.20.0" - "@eslint/plugin-kit" "^0.2.5" + "@eslint/config-array" "^0.21.1" + "@eslint/config-helpers" "^0.4.2" + "@eslint/core" "^0.17.0" + "@eslint/eslintrc" "^3.3.1" + "@eslint/js" "9.39.1" + "@eslint/plugin-kit" "^0.4.1" "@humanfs/node" "^0.16.6" "@humanwhocodes/module-importer" "^1.0.1" - "@humanwhocodes/retry" "^0.4.1" + "@humanwhocodes/retry" "^0.4.2" "@types/estree" "^1.0.6" - "@types/json-schema" "^7.0.15" ajv "^6.12.4" chalk "^4.0.0" cross-spawn "^7.0.6" debug "^4.3.2" escape-string-regexp "^4.0.0" - eslint-scope "^8.2.0" - eslint-visitor-keys "^4.2.0" - espree "^10.3.0" + eslint-scope "^8.4.0" + eslint-visitor-keys "^4.2.1" + espree "^10.4.0" esquery "^1.5.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" @@ -1618,7 +1635,7 @@ eslint@^9.20.1: natural-compare "^1.4.0" optionator "^0.9.3" -espree@^10.0.1, espree@^10.3.0: +espree@^10.0.1: version "10.3.0" resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a" integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg== @@ -1627,6 +1644,15 @@ espree@^10.0.1, espree@^10.3.0: acorn-jsx "^5.3.2" eslint-visitor-keys "^4.2.0" +espree@^10.4.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.4.0.tgz#d54f4949d4629005a1fa168d937c3ff1f7e2a837" + integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ== + dependencies: + acorn "^8.15.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.2.1" + esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" @@ -2440,10 +2466,10 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== +js-yaml@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" + integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== dependencies: argparse "^2.0.1" From 6cfc7a2759e7509d7b58253a835629598da380a2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 5 Dec 2025 05:26:24 +0000 Subject: [PATCH 067/138] chore(internal): codegen related update --- packages/mcp-server/package.json | 2 +- packages/mcp-server/src/code-tool-worker.ts | 107 ++++++++++++++++---- packages/mcp-server/src/code-tool.ts | 16 ++- 3 files changed, 101 insertions(+), 24 deletions(-) diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 8402437b..fddb332a 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -32,7 +32,7 @@ "dependencies": { "@corgi-tech/beagle": "file:../../dist/", "@cloudflare/cabidela": "^0.2.4", - "@modelcontextprotocol/sdk": "^1.11.5", + "@modelcontextprotocol/sdk": "^1.24.0", "@valtown/deno-http-worker": "^0.0.21", "cors": "^2.8.5", "express": "^5.1.0", diff --git a/packages/mcp-server/src/code-tool-worker.ts b/packages/mcp-server/src/code-tool-worker.ts index ed1a6129..10d91f24 100644 --- a/packages/mcp-server/src/code-tool-worker.ts +++ b/packages/mcp-server/src/code-tool-worker.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import path from 'node:path'; import util from 'node:util'; import Fuse from 'fuse.js'; @@ -8,30 +9,41 @@ import ts from 'typescript'; import { WorkerInput, WorkerSuccess, WorkerError } from './code-tool-types'; import { Beagle } from '@corgi-tech/beagle'; -function getRunFunctionNode( - code: string, -): ts.FunctionDeclaration | ts.FunctionExpression | ts.ArrowFunction | null { +function getRunFunctionSource(code: string): { + type: 'declaration' | 'expression'; + client: string | undefined; + code: string; +} | null { const sourceFile = ts.createSourceFile('code.ts', code, ts.ScriptTarget.Latest, true); + const printer = ts.createPrinter(); for (const statement of sourceFile.statements) { // Check for top-level function declarations if (ts.isFunctionDeclaration(statement)) { if (statement.name?.text === 'run') { - return statement; + return { + type: 'declaration', + client: statement.parameters[0]?.name.getText(), + code: printer.printNode(ts.EmitHint.Unspecified, statement.body!, sourceFile), + }; } } // Check for variable declarations: const run = () => {} or const run = function() {} if (ts.isVariableStatement(statement)) { for (const declaration of statement.declarationList.declarations) { - if (ts.isIdentifier(declaration.name) && declaration.name.text === 'run') { + if ( + ts.isIdentifier(declaration.name) && + declaration.name.text === 'run' && // Check if it's initialized with a function - if ( - declaration.initializer && - (ts.isFunctionExpression(declaration.initializer) || ts.isArrowFunction(declaration.initializer)) - ) { - return declaration.initializer; - } + declaration.initializer && + (ts.isFunctionExpression(declaration.initializer) || ts.isArrowFunction(declaration.initializer)) + ) { + return { + type: 'expression', + client: declaration.initializer.parameters[0]?.name.getText(), + code: printer.printNode(ts.EmitHint.Unspecified, declaration.initializer, sourceFile), + }; } } } @@ -40,6 +52,61 @@ function getRunFunctionNode( return null; } +function getTSDiagnostics(code: string): string[] { + const functionSource = getRunFunctionSource(code)!; + const codeWithImport = [ + 'import { Beagle } from "@corgi-tech/beagle";', + functionSource.type === 'declaration' ? + `async function run(${functionSource.client}: Beagle)` + : `const run: (${functionSource.client}: Beagle) => Promise =`, + functionSource.code, + ].join('\n'); + const sourcePath = path.resolve('code.ts'); + const ast = ts.createSourceFile(sourcePath, codeWithImport, ts.ScriptTarget.Latest, true); + const options = ts.getDefaultCompilerOptions(); + options.target = ts.ScriptTarget.Latest; + options.module = ts.ModuleKind.NodeNext; + options.moduleResolution = ts.ModuleResolutionKind.NodeNext; + const host = ts.createCompilerHost(options, true); + const newHost: typeof host = { + ...host, + getSourceFile: (...args) => { + if (path.resolve(args[0]) === sourcePath) { + return ast; + } + return host.getSourceFile(...args); + }, + readFile: (...args) => { + if (path.resolve(args[0]) === sourcePath) { + return codeWithImport; + } + return host.readFile(...args); + }, + fileExists: (...args) => { + if (path.resolve(args[0]) === sourcePath) { + return true; + } + return host.fileExists(...args); + }, + }; + const program = ts.createProgram({ + options, + rootNames: [sourcePath], + host: newHost, + }); + const diagnostics = ts.getPreEmitDiagnostics(program, ast); + return diagnostics.map((d) => { + const message = ts.flattenDiagnosticMessageText(d.messageText, '\n'); + if (!d.file || !d.start) return `- ${message}`; + const { line: tsLine } = ts.getLineAndCharacterOfPosition(d.file, d.start); + // We add two lines in the beginning, for the client import and the function declaration. + // So the actual (zero-based) line number is tsLine - 2. + const lineNumber = tsLine - 2; + const line = code.split('\n').at(lineNumber)?.trim(); + return line ? `- ${message}\n at line ${lineNumber + 1}\n ${line}` : `- ${message}`; + }); +} + const fuse = new Fuse( [ 'client.plans.list', @@ -160,11 +227,16 @@ function parseError(code: string, error: unknown): string | undefined { const fetch = async (req: Request): Promise => { const { opts, code } = (await req.json()) as WorkerInput; - if (code == null) { + + const runFunctionSource = code ? getRunFunctionSource(code) : null; + if (!runFunctionSource) { + const message = + code ? + 'The code is missing a top-level `run` function.' + : 'The code argument is missing. Provide one containing a top-level `run` function.'; return Response.json( { - message: - 'The code param is missing. Provide one containing a top-level `run` function. Write code within this template:\n\n```\nasync function run(client) {\n // Fill this out\n}\n```', + message: `${message} Write code within this template:\n\n\`\`\`\nasync function run(client) {\n // Fill this out\n}\n\`\`\``, logLines: [], errLines: [], } satisfies WorkerError, @@ -172,12 +244,11 @@ const fetch = async (req: Request): Promise => { ); } - const runFunctionNode = getRunFunctionNode(code); - if (!runFunctionNode) { + const diagnostics = getTSDiagnostics(code); + if (diagnostics.length > 0) { return Response.json( { - message: - 'The code is missing a top-level `run` function. Write code within this template:\n\n```\nasync function run(client) {\n // Fill this out\n}\n```', + message: `The code contains TypeScript diagnostics:\n${diagnostics.join('\n')}`, logLines: [], errLines: [], } satisfies WorkerError, diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 470e378b..31142697 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { dirname } from 'node:path'; -import { pathToFileURL } from 'node:url'; +import path from 'node:path'; +import url from 'node:url'; import Beagle, { ClientOptions } from '@corgi-tech/beagle'; import { ContentBlock, Endpoint, Metadata, ToolCallResult } from './tools/types'; @@ -35,10 +35,16 @@ export async function codeTool(): Promise { const baseURLHostname = new URL(client.baseURL).hostname; const { code } = args as { code: string }; - const worker = await newDenoHTTPWorker(pathToFileURL(workerPath), { + const allowRead = [ + 'code-tool-worker.mjs', + `${workerPath.replace(/([\/\\]node_modules)[\/\\].+$/, '$1')}/`, + path.resolve(path.dirname(workerPath), '..'), + ].join(','); + + const worker = await newDenoHTTPWorker(url.pathToFileURL(workerPath), { runFlags: [ `--node-modules-dir=manual`, - `--allow-read=code-tool-worker.mjs,${workerPath.replace(/([\/\\]node_modules)[\/\\].+$/, '$1')}/`, + `--allow-read=${allowRead}`, `--allow-net=${baseURLHostname}`, // Allow environment variables because instantiating the client will try to read from them, // even though they are not set. @@ -46,7 +52,7 @@ export async function codeTool(): Promise { ], printOutput: true, spawnOptions: { - cwd: dirname(workerPath), + cwd: path.dirname(workerPath), }, }); From 0051b46e8c6000d1938afea968f748d4941b08f7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 05:14:48 +0000 Subject: [PATCH 068/138] chore(internal): codegen related update --- packages/mcp-server/src/code-tool-paths.cts | 3 - packages/mcp-server/src/code-tool-worker.ts | 294 -------------------- packages/mcp-server/src/code-tool.ts | 180 +++--------- packages/mcp-server/src/docs-search-tool.ts | 7 + 4 files changed, 39 insertions(+), 445 deletions(-) delete mode 100644 packages/mcp-server/src/code-tool-paths.cts delete mode 100644 packages/mcp-server/src/code-tool-worker.ts diff --git a/packages/mcp-server/src/code-tool-paths.cts b/packages/mcp-server/src/code-tool-paths.cts deleted file mode 100644 index 15ce7f55..00000000 --- a/packages/mcp-server/src/code-tool-paths.cts +++ /dev/null @@ -1,3 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export const workerPath = require.resolve('./code-tool-worker.mjs'); diff --git a/packages/mcp-server/src/code-tool-worker.ts b/packages/mcp-server/src/code-tool-worker.ts deleted file mode 100644 index 10d91f24..00000000 --- a/packages/mcp-server/src/code-tool-worker.ts +++ /dev/null @@ -1,294 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import path from 'node:path'; -import util from 'node:util'; - -import Fuse from 'fuse.js'; -import ts from 'typescript'; - -import { WorkerInput, WorkerSuccess, WorkerError } from './code-tool-types'; -import { Beagle } from '@corgi-tech/beagle'; - -function getRunFunctionSource(code: string): { - type: 'declaration' | 'expression'; - client: string | undefined; - code: string; -} | null { - const sourceFile = ts.createSourceFile('code.ts', code, ts.ScriptTarget.Latest, true); - const printer = ts.createPrinter(); - - for (const statement of sourceFile.statements) { - // Check for top-level function declarations - if (ts.isFunctionDeclaration(statement)) { - if (statement.name?.text === 'run') { - return { - type: 'declaration', - client: statement.parameters[0]?.name.getText(), - code: printer.printNode(ts.EmitHint.Unspecified, statement.body!, sourceFile), - }; - } - } - - // Check for variable declarations: const run = () => {} or const run = function() {} - if (ts.isVariableStatement(statement)) { - for (const declaration of statement.declarationList.declarations) { - if ( - ts.isIdentifier(declaration.name) && - declaration.name.text === 'run' && - // Check if it's initialized with a function - declaration.initializer && - (ts.isFunctionExpression(declaration.initializer) || ts.isArrowFunction(declaration.initializer)) - ) { - return { - type: 'expression', - client: declaration.initializer.parameters[0]?.name.getText(), - code: printer.printNode(ts.EmitHint.Unspecified, declaration.initializer, sourceFile), - }; - } - } - } - } - - return null; -} - -function getTSDiagnostics(code: string): string[] { - const functionSource = getRunFunctionSource(code)!; - const codeWithImport = [ - 'import { Beagle } from "@corgi-tech/beagle";', - functionSource.type === 'declaration' ? - `async function run(${functionSource.client}: Beagle)` - : `const run: (${functionSource.client}: Beagle) => Promise =`, - functionSource.code, - ].join('\n'); - const sourcePath = path.resolve('code.ts'); - const ast = ts.createSourceFile(sourcePath, codeWithImport, ts.ScriptTarget.Latest, true); - const options = ts.getDefaultCompilerOptions(); - options.target = ts.ScriptTarget.Latest; - options.module = ts.ModuleKind.NodeNext; - options.moduleResolution = ts.ModuleResolutionKind.NodeNext; - const host = ts.createCompilerHost(options, true); - const newHost: typeof host = { - ...host, - getSourceFile: (...args) => { - if (path.resolve(args[0]) === sourcePath) { - return ast; - } - return host.getSourceFile(...args); - }, - readFile: (...args) => { - if (path.resolve(args[0]) === sourcePath) { - return codeWithImport; - } - return host.readFile(...args); - }, - fileExists: (...args) => { - if (path.resolve(args[0]) === sourcePath) { - return true; - } - return host.fileExists(...args); - }, - }; - const program = ts.createProgram({ - options, - rootNames: [sourcePath], - host: newHost, - }); - const diagnostics = ts.getPreEmitDiagnostics(program, ast); - return diagnostics.map((d) => { - const message = ts.flattenDiagnosticMessageText(d.messageText, '\n'); - if (!d.file || !d.start) return `- ${message}`; - const { line: tsLine } = ts.getLineAndCharacterOfPosition(d.file, d.start); - // We add two lines in the beginning, for the client import and the function declaration. - // So the actual (zero-based) line number is tsLine - 2. - const lineNumber = tsLine - 2; - const line = code.split('\n').at(lineNumber)?.trim(); - return line ? `- ${message}\n at line ${lineNumber + 1}\n ${line}` : `- ${message}`; - }); -} - -const fuse = new Fuse( - [ - 'client.plans.list', - 'client.plans.retrieve', - 'client.propertyManagers.create', - 'client.propertyManagers.delete', - 'client.propertyManagers.list', - 'client.propertyManagers.retrieve', - 'client.propertyManagers.update', - 'client.tenants.create', - 'client.tenants.delete', - 'client.tenants.list', - 'client.tenants.retrieve', - 'client.tenants.update', - 'client.enrollments.create', - 'client.enrollments.lapse', - 'client.enrollments.list', - 'client.enrollments.retrieve', - 'client.enrollments.retrieveCertificate', - 'client.insuranceVerification.verify', - 'client.webhook.endpoints.create', - 'client.webhook.endpoints.delete', - 'client.webhook.endpoints.list', - 'client.webhook.endpoints.retrieve', - 'client.webhook.endpoints.update', - ], - { threshold: 1, shouldSort: true }, -); - -function getMethodSuggestions(fullyQualifiedMethodName: string): string[] { - return fuse - .search(fullyQualifiedMethodName) - .map(({ item }) => item) - .slice(0, 5); -} - -const proxyToObj = new WeakMap(); -const objToProxy = new WeakMap(); - -type ClientProxyConfig = { - path: string[]; - isBelievedBad?: boolean; -}; - -function makeSdkProxy(obj: T, { path, isBelievedBad = false }: ClientProxyConfig): T { - let proxy: T = objToProxy.get(obj); - - if (!proxy) { - proxy = new Proxy(obj, { - get(target, prop, receiver) { - const propPath = [...path, String(prop)]; - const value = Reflect.get(target, prop, receiver); - - if (isBelievedBad || (!(prop in target) && value === undefined)) { - // If we're accessing a path that doesn't exist, it will probably eventually error. - // Let's proxy it and mark it bad so that we can control the error message. - // We proxy an empty class so that an invocation or construction attempt is possible. - return makeSdkProxy(class {}, { path: propPath, isBelievedBad: true }); - } - - if (value !== null && (typeof value === 'object' || typeof value === 'function')) { - return makeSdkProxy(value, { path: propPath, isBelievedBad }); - } - - return value; - }, - - apply(target, thisArg, args) { - if (isBelievedBad || typeof target !== 'function') { - const fullyQualifiedMethodName = path.join('.'); - const suggestions = getMethodSuggestions(fullyQualifiedMethodName); - throw new Error( - `${fullyQualifiedMethodName} is not a function. Did you mean: ${suggestions.join(', ')}`, - ); - } - - return Reflect.apply(target, proxyToObj.get(thisArg) ?? thisArg, args); - }, - - construct(target, args, newTarget) { - if (isBelievedBad || typeof target !== 'function') { - const fullyQualifiedMethodName = path.join('.'); - const suggestions = getMethodSuggestions(fullyQualifiedMethodName); - throw new Error( - `${fullyQualifiedMethodName} is not a constructor. Did you mean: ${suggestions.join(', ')}`, - ); - } - - return Reflect.construct(target, args, newTarget); - }, - }); - - objToProxy.set(obj, proxy); - proxyToObj.set(proxy, obj); - } - - return proxy; -} - -function parseError(code: string, error: unknown): string | undefined { - if (!(error instanceof Error)) return; - const message = error.name ? `${error.name}: ${error.message}` : error.message; - try { - // Deno uses V8; the first ":LINE:COLUMN" is the top of stack. - const lineNumber = error.stack?.match(/:([0-9]+):[0-9]+/)?.[1]; - // -1 for the zero-based indexing - const line = - lineNumber && - code - .split('\n') - .at(parseInt(lineNumber, 10) - 1) - ?.trim(); - return line ? `${message}\n at line ${lineNumber}\n ${line}` : message; - } catch { - return message; - } -} - -const fetch = async (req: Request): Promise => { - const { opts, code } = (await req.json()) as WorkerInput; - - const runFunctionSource = code ? getRunFunctionSource(code) : null; - if (!runFunctionSource) { - const message = - code ? - 'The code is missing a top-level `run` function.' - : 'The code argument is missing. Provide one containing a top-level `run` function.'; - return Response.json( - { - message: `${message} Write code within this template:\n\n\`\`\`\nasync function run(client) {\n // Fill this out\n}\n\`\`\``, - logLines: [], - errLines: [], - } satisfies WorkerError, - { status: 400, statusText: 'Code execution error' }, - ); - } - - const diagnostics = getTSDiagnostics(code); - if (diagnostics.length > 0) { - return Response.json( - { - message: `The code contains TypeScript diagnostics:\n${diagnostics.join('\n')}`, - logLines: [], - errLines: [], - } satisfies WorkerError, - { status: 400, statusText: 'Code execution error' }, - ); - } - - const client = new Beagle({ - ...opts, - }); - - const logLines: string[] = []; - const errLines: string[] = []; - const console = { - log: (...args: unknown[]) => { - logLines.push(util.format(...args)); - }, - error: (...args: unknown[]) => { - errLines.push(util.format(...args)); - }, - }; - try { - let run_ = async (client: any) => {}; - eval(`${code}\nrun_ = run;`); - const result = await run_(makeSdkProxy(client, { path: ['client'] })); - return Response.json({ - result, - logLines, - errLines, - } satisfies WorkerSuccess); - } catch (e) { - return Response.json( - { - message: parseError(code, e), - logLines, - errLines, - } satisfies WorkerError, - { status: 400, statusText: 'Code execution error' }, - ); - } -}; - -export default { fetch }; diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 31142697..199c7928 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -1,14 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import path from 'node:path'; -import url from 'node:url'; -import Beagle, { ClientOptions } from '@corgi-tech/beagle'; -import { ContentBlock, Endpoint, Metadata, ToolCallResult } from './tools/types'; - +import { Metadata, ToolCallResult, asTextContentResult } from './tools/types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; - -import { WorkerInput, WorkerError, WorkerSuccess } from './code-tool-types'; - +import { readEnv } from './server'; +import { WorkerSuccess } from './code-tool-types'; /** * A tool that runs code against a copy of the SDK. * @@ -18,156 +13,45 @@ import { WorkerInput, WorkerError, WorkerSuccess } from './code-tool-types'; * * @param endpoints - The endpoints to include in the list. */ -export async function codeTool(): Promise { +export async function codeTool() { const metadata: Metadata = { resource: 'all', operation: 'write', tags: [] }; const tool: Tool = { name: 'execute', description: - 'Runs JavaScript code to interact with the API.\n\nYou are a skilled programmer writing code to interface with the service.\nDefine an async function named "run" that takes a single parameter of an initialized client named "client", and it will be run.\nWrite code within this template:\n\n```\nasync function run(client) {\n // Fill this out\n}\n```\n\nYou will be returned anything that your function returns, plus the results of any console.log statements.\nIf any code triggers an error, the tool will return an error response, so you do not need to add error handling unless you want to output something more helpful than the raw error.\nIt is not necessary to add comments to code, unless by adding those comments you believe that you can generate better code.\nThis code will run in a container, and you will not be able to use fetch or otherwise interact with the network calls other than through the client you are given.\nAny variables you define won\'t live between successive uses of this call, so make sure to return or log any data you might need later.', + 'Runs JavaScript code to interact with the API.\n\nYou are a skilled programmer writing code to interface with the service.\nDefine an async function named "run" that takes a single parameter of an initialized SDK client and it will be run.\nWrite code within this template:\n\n```\nasync function run(client) {\n // Fill this out\n}\n```\n\nYou will be returned anything that your function returns, plus the results of any console.log statements.\nIf any code triggers an error, the tool will return an error response, so you do not need to add error handling unless you want to output something more helpful than the raw error.\nIt is not necessary to add comments to code, unless by adding those comments you believe that you can generate better code.\nThis code will run in a container, and you will not be able to use fetch or otherwise interact with the network calls other than through the client you are given.\nAny variables you define won\'t live between successive uses of this call, so make sure to return or log any data you might need later.', inputSchema: { type: 'object', properties: { code: { type: 'string' } } }, }; - - // Import dynamically to avoid failing at import time in cases where the environment is not well-supported. - const { newDenoHTTPWorker } = await import('@valtown/deno-http-worker'); - const { workerPath } = await import('./code-tool-paths.cjs'); - - const handler = async (client: Beagle, args: unknown): Promise => { - const baseURLHostname = new URL(client.baseURL).hostname; - const { code } = args as { code: string }; - - const allowRead = [ - 'code-tool-worker.mjs', - `${workerPath.replace(/([\/\\]node_modules)[\/\\].+$/, '$1')}/`, - path.resolve(path.dirname(workerPath), '..'), - ].join(','); - - const worker = await newDenoHTTPWorker(url.pathToFileURL(workerPath), { - runFlags: [ - `--node-modules-dir=manual`, - `--allow-read=${allowRead}`, - `--allow-net=${baseURLHostname}`, - // Allow environment variables because instantiating the client will try to read from them, - // even though they are not set. - '--allow-env', - ], - printOutput: true, - spawnOptions: { - cwd: path.dirname(workerPath), + const handler = async (_: unknown, args: any): Promise => { + const code = args.code as string; + + // this is not required, but passing a Stainless API key for the matching project_name + // will allow you to run code-mode queries against non-published versions of your SDK. + const stainlessAPIKey = readEnv('STAINLESS_API_KEY'); + const codeModeEndpoint = + readEnv('CODE_MODE_ENDPOINT_URL') ?? 'https://api.stainless.com/api/ai/code-tool'; + + const res = await fetch(codeModeEndpoint, { + method: 'POST', + headers: { + ...(stainlessAPIKey && { Authorization: stainlessAPIKey }), + 'Content-Type': 'application/json', + client_envs: JSON.stringify({ BEAGLE_API_KEY: readEnv('BEAGLE_API_KEY') }), }, + body: JSON.stringify({ + project_name: 'beagle', + code, + }), }); - try { - const resp = await new Promise((resolve, reject) => { - worker.addEventListener('exit', (exitCode) => { - reject(new Error(`Worker exited with code ${exitCode}`)); - }); - - const opts: ClientOptions = { - baseURL: client.baseURL, - apiKey: client.apiKey, - defaultHeaders: { - 'X-Stainless-MCP': 'true', - }, - }; - - const req = worker.request( - 'http://localhost', - { - headers: { - 'content-type': 'application/json', - }, - method: 'POST', - }, - (resp) => { - const body: Uint8Array[] = []; - resp.on('error', (err) => { - reject(err); - }); - resp.on('data', (chunk) => { - body.push(chunk); - }); - resp.on('end', () => { - resolve( - new Response(Buffer.concat(body).toString(), { - status: resp.statusCode ?? 200, - headers: resp.headers as any, - }), - ); - }); - }, - ); - - const body = JSON.stringify({ - opts, - code, - } satisfies WorkerInput); - - req.write(body, (err) => { - if (err != null) { - reject(err); - } - }); - - req.end(); - }); - - if (resp.status === 200) { - const { result, logLines, errLines } = (await resp.json()) as WorkerSuccess; - const returnOutput: ContentBlock | null = - result == null ? null : ( - { - type: 'text', - text: typeof result === 'string' ? result : JSON.stringify(result), - } - ); - const logOutput: ContentBlock | null = - logLines.length === 0 ? - null - : { - type: 'text', - text: logLines.join('\n'), - }; - const errOutput: ContentBlock | null = - errLines.length === 0 ? - null - : { - type: 'text', - text: 'Error output:\n' + errLines.join('\n'), - }; - return { - content: [returnOutput, logOutput, errOutput].filter((block) => block !== null), - }; - } else { - const { message, logLines, errLines } = (await resp.json()) as WorkerError; - const messageOutput: ContentBlock | null = - message == null ? null : ( - { - type: 'text', - text: message, - } - ); - const logOutput: ContentBlock | null = - logLines.length === 0 ? - null - : { - type: 'text', - text: logLines.join('\n'), - }; - const errOutput: ContentBlock | null = - errLines.length === 0 ? - null - : { - type: 'text', - text: 'Error output:\n' + errLines.join('\n'), - }; - return { - content: [messageOutput, logOutput, errOutput].filter((block) => block !== null), - isError: true, - }; - } - } finally { - worker.terminate(); + if (!res.ok) { + throw new Error( + `${res.status}: ${ + res.statusText + } error when trying to contact Code Tool server. Details: ${await res.text()}`, + ); } + + return asTextContentResult((await res.json()) as WorkerSuccess); }; return { metadata, tool, handler }; diff --git a/packages/mcp-server/src/docs-search-tool.ts b/packages/mcp-server/src/docs-search-tool.ts index bb450d09..6d482a49 100644 --- a/packages/mcp-server/src/docs-search-tool.ts +++ b/packages/mcp-server/src/docs-search-tool.ts @@ -46,6 +46,13 @@ export const handler = async (_: unknown, args: Record | undefi const body = args as any; const query = new URLSearchParams(body).toString(); const result = await fetch(`${docsSearchURL}?${query}`); + + if (!result.ok) { + throw new Error( + `${result.status}: ${result.statusText} when using doc search tool. Details: ${await result.text()}`, + ); + } + return asTextContentResult(await result.json()); }; From 8bd9741143afb8665684c198b15d08ae54c5d6a1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 11 Dec 2025 05:58:40 +0000 Subject: [PATCH 069/138] chore(internal): codegen related update --- packages/mcp-server/src/code-tool.ts | 1 + packages/mcp-server/yarn.lock | 381 +++++++++++++++++++++++++-- 2 files changed, 365 insertions(+), 17 deletions(-) diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 199c7928..6f0c029f 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -39,6 +39,7 @@ export async function codeTool() { }, body: JSON.stringify({ project_name: 'beagle', + client_opts: { environment: (readEnv('BEAGLE_ENVIRONMENT') || undefined) as any }, code, }), }); diff --git a/packages/mcp-server/yarn.lock b/packages/mcp-server/yarn.lock index 2bb21c66..38be884f 100644 --- a/packages/mcp-server/yarn.lock +++ b/packages/mcp-server/yarn.lock @@ -10,6 +10,20 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" +"@anthropic-ai/mcpb@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@anthropic-ai/mcpb/-/mcpb-1.1.0.tgz#1af18de2ab9499d321d6310d0be095f5fef5161b" + integrity sha512-nOnhG1eNpGKSIDv6lt3xsI3w2p2k0D/rPTMGXXugLovCEaJ7svh8XMfCe145vs8qo384t8wKbokWAvx9PkQMDA== + dependencies: + "@inquirer/prompts" "^6.0.1" + commander "^13.1.0" + fflate "^0.8.2" + galactus "^1.0.0" + ignore "^7.0.5" + node-forge "^1.3.1" + pretty-bytes "^5.6.0" + zod "^3.25.67" + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.27.1": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" @@ -336,6 +350,144 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== +"@inquirer/checkbox@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/checkbox/-/checkbox-3.0.1.tgz#0a57f704265f78c36e17f07e421b98efb4b9867b" + integrity sha512-0hm2nrToWUdD6/UHnel/UKGdk1//ke5zGUpHIvk5ZWmaKezlGxZkOJXNSWsdxO/rEqTkbB3lNC2J6nBElV2aAQ== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/figures" "^1.0.6" + "@inquirer/type" "^2.0.0" + ansi-escapes "^4.3.2" + yoctocolors-cjs "^2.1.2" + +"@inquirer/confirm@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-4.0.1.tgz#9106d6bffa0b2fdd0e4f60319b6f04f2e06e6e25" + integrity sha512-46yL28o2NJ9doViqOy0VDcoTzng7rAb6yPQKU7VDLqkmbCaH4JqK4yk4XqlzNWy9PVC5pG1ZUXPBQv+VqnYs2w== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/type" "^2.0.0" + +"@inquirer/core@^9.2.1": + version "9.2.1" + resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-9.2.1.tgz#677c49dee399c9063f31e0c93f0f37bddc67add1" + integrity sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg== + dependencies: + "@inquirer/figures" "^1.0.6" + "@inquirer/type" "^2.0.0" + "@types/mute-stream" "^0.0.4" + "@types/node" "^22.5.5" + "@types/wrap-ansi" "^3.0.0" + ansi-escapes "^4.3.2" + cli-width "^4.1.0" + mute-stream "^1.0.0" + signal-exit "^4.1.0" + strip-ansi "^6.0.1" + wrap-ansi "^6.2.0" + yoctocolors-cjs "^2.1.2" + +"@inquirer/editor@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/editor/-/editor-3.0.1.tgz#d109f21e050af6b960725388cb1c04214ed7c7bc" + integrity sha512-VA96GPFaSOVudjKFraokEEmUQg/Lub6OXvbIEZU1SDCmBzRkHGhxoFAVaF30nyiB4m5cEbDgiI2QRacXZ2hw9Q== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/type" "^2.0.0" + external-editor "^3.1.0" + +"@inquirer/expand@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/expand/-/expand-3.0.1.tgz#aed9183cac4d12811be47a4a895ea8e82a17e22c" + integrity sha512-ToG8d6RIbnVpbdPdiN7BCxZGiHOTomOX94C2FaT5KOHupV40tKEDozp12res6cMIfRKrXLJyexAZhWVHgbALSQ== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/type" "^2.0.0" + yoctocolors-cjs "^2.1.2" + +"@inquirer/figures@^1.0.6": + version "1.0.15" + resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.15.tgz#dbb49ed80df11df74268023b496ac5d9acd22b3a" + integrity sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g== + +"@inquirer/input@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/input/-/input-3.0.1.tgz#de63d49e516487388508d42049deb70f2cb5f28e" + integrity sha512-BDuPBmpvi8eMCxqC5iacloWqv+5tQSJlUafYWUe31ow1BVXjW2a5qe3dh4X/Z25Wp22RwvcaLCc2siHobEOfzg== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/type" "^2.0.0" + +"@inquirer/number@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/number/-/number-2.0.1.tgz#b9863080d02ab7dc2e56e16433d83abea0f2a980" + integrity sha512-QpR8jPhRjSmlr/mD2cw3IR8HRO7lSVOnqUvQa8scv1Lsr3xoAMMworcYW3J13z3ppjBFBD2ef1Ci6AE5Qn8goQ== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/type" "^2.0.0" + +"@inquirer/password@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/password/-/password-3.0.1.tgz#2a9a9143591088336bbd573bcb05d5bf080dbf87" + integrity sha512-haoeEPUisD1NeE2IanLOiFr4wcTXGWrBOyAyPZi1FfLJuXOzNmxCJPgUrGYKVh+Y8hfGJenIfz5Wb/DkE9KkMQ== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/type" "^2.0.0" + ansi-escapes "^4.3.2" + +"@inquirer/prompts@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/prompts/-/prompts-6.0.1.tgz#43f5c0ed35c5ebfe52f1d43d46da2d363d950071" + integrity sha512-yl43JD/86CIj3Mz5mvvLJqAOfIup7ncxfJ0Btnl0/v5TouVUyeEdcpknfgc+yMevS/48oH9WAkkw93m7otLb/A== + dependencies: + "@inquirer/checkbox" "^3.0.1" + "@inquirer/confirm" "^4.0.1" + "@inquirer/editor" "^3.0.1" + "@inquirer/expand" "^3.0.1" + "@inquirer/input" "^3.0.1" + "@inquirer/number" "^2.0.1" + "@inquirer/password" "^3.0.1" + "@inquirer/rawlist" "^3.0.1" + "@inquirer/search" "^2.0.1" + "@inquirer/select" "^3.0.1" + +"@inquirer/rawlist@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/rawlist/-/rawlist-3.0.1.tgz#729def358419cc929045f264131878ed379e0af3" + integrity sha512-VgRtFIwZInUzTiPLSfDXK5jLrnpkuSOh1ctfaoygKAdPqjcjKYmGh6sCY1pb0aGnCGsmhUxoqLDUAU0ud+lGXQ== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/type" "^2.0.0" + yoctocolors-cjs "^2.1.2" + +"@inquirer/search@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/search/-/search-2.0.1.tgz#69b774a0a826de2e27b48981d01bc5ad81e73721" + integrity sha512-r5hBKZk3g5MkIzLVoSgE4evypGqtOannnB3PKTG9NRZxyFRKcfzrdxXXPcoJQsxJPzvdSU2Rn7pB7lw0GCmGAg== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/figures" "^1.0.6" + "@inquirer/type" "^2.0.0" + yoctocolors-cjs "^2.1.2" + +"@inquirer/select@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@inquirer/select/-/select-3.0.1.tgz#1df9ed27fb85a5f526d559ac5ce7cc4e9dc4e7ec" + integrity sha512-lUDGUxPhdWMkN/fHy1Lk7pF3nK1fh/gqeyWXmctefhxLYxlDsc7vsPBEpxrfVGDsVdyYJsiJoD4bJ1b623cV1Q== + dependencies: + "@inquirer/core" "^9.2.1" + "@inquirer/figures" "^1.0.6" + "@inquirer/type" "^2.0.0" + ansi-escapes "^4.3.2" + yoctocolors-cjs "^2.1.2" + +"@inquirer/type@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-2.0.0.tgz#08fa513dca2cb6264fe1b0a2fabade051444e3f6" + integrity sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag== + dependencies: + mute-stream "^1.0.0" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -584,12 +736,13 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@modelcontextprotocol/sdk@^1.11.5": - version "1.17.3" - resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.17.3.tgz#cf92354220f0183d28179e96a9bf3a8f6d3211ae" - integrity sha512-JPwUKWSsbzx+DLFznf/QZ32Qa+ptfbUlHhRLrBQBAFu9iI1iYvizM4p+zhhRDceSsPutXp4z+R/HPVphlIiclg== +"@modelcontextprotocol/sdk@^1.24.0": + version "1.24.3" + resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.24.3.tgz#81a3fcc919cb4ce8630e2bcecf59759176eb331a" + integrity sha512-YgSHW29fuzKKAHTGe9zjNoo+yF8KaQPzDC2W9Pv41E7/57IfY+AMGJ/aDFlgTLcVVELoggKE4syABCE75u3NCw== dependencies: - ajv "^6.12.6" + ajv "^8.17.1" + ajv-formats "^3.0.1" content-type "^1.0.5" cors "^2.8.5" cross-spawn "^7.0.5" @@ -597,10 +750,11 @@ eventsource-parser "^3.0.0" express "^5.0.1" express-rate-limit "^7.5.0" + jose "^6.1.1" pkce-challenge "^5.0.0" raw-body "^3.0.0" - zod "^3.23.8" - zod-to-json-schema "^3.24.1" + zod "^3.25 || ^4.0" + zod-to-json-schema "^3.25.0" "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -795,6 +949,13 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== +"@types/mute-stream@^0.0.4": + version "0.0.4" + resolved "https://registry.yarnpkg.com/@types/mute-stream/-/mute-stream-0.0.4.tgz#77208e56a08767af6c5e1237be8888e2f255c478" + integrity sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow== + dependencies: + "@types/node" "*" + "@types/node@*": version "22.15.17" resolved "https://registry.yarnpkg.com/@types/node/-/node-22.15.17.tgz#355ccec95f705b664e4332bb64a7f07db30b7055" @@ -802,6 +963,13 @@ dependencies: undici-types "~6.21.0" +"@types/node@^22.5.5": + version "22.19.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.19.2.tgz#2f0956fba46518aaf7578c84e37bddab55f85d01" + integrity sha512-LPM2G3Syo1GLzXLGJAKdqoU35XvrWzGJ21/7sgZTUpbkBaOasTj8tjwn6w+hCkqaa1TfJ/w67rJSwYItlJ2mYw== + dependencies: + undici-types "~6.21.0" + "@types/qs@*", "@types/qs@^6.14.0": version "6.14.0" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.14.0.tgz#d8b60cecf62f2db0fb68e5e006077b9178b85de5" @@ -834,6 +1002,11 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== +"@types/wrap-ansi@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz#18b97a972f94f60a679fd5c796d96421b9abb9fd" + integrity sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g== + "@types/yargs-parser@*": version "21.0.3" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" @@ -970,7 +1143,14 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^6.12.4, ajv@^6.12.6: +ajv-formats@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-3.0.1.tgz#3d5dc762bca17679c3c2ea7e90ad6b7532309578" + integrity sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ== + dependencies: + ajv "^8.0.0" + +ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -980,7 +1160,17 @@ ajv@^6.12.4, ajv@^6.12.6: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ansi-escapes@^4.2.1: +ajv@^8.0.0, ajv@^8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + +ansi-escapes@^4.2.1, ansi-escapes@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== @@ -1222,6 +1412,11 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + ci-info@^3.2.0: version "3.9.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" @@ -1237,6 +1432,11 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +cli-width@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5" + integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ== + cliui@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" @@ -1273,6 +1473,11 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +commander@^13.1.0: + version "13.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-13.1.0.tgz#776167db68c78f38dcce1f9b8d7b8b9a488abf46" + integrity sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1685,6 +1890,15 @@ express@^5.0.1, express@^5.1.0: type-is "^2.0.1" vary "^1.1.2" +external-editor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -1716,6 +1930,11 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-uri@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa" + integrity sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA== + fastq@^1.6.0: version "1.19.1" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" @@ -1730,6 +1949,11 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +fflate@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" + integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -1793,6 +2017,14 @@ flatted@^3.2.9: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== +flora-colossus@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/flora-colossus/-/flora-colossus-2.0.0.tgz#af1e85db0a8256ef05f3fb531c1235236c97220a" + integrity sha512-dz4HxH6pOvbUzZpZ/yXhafjbR2I8cenK5xL0KtBFb7U2ADsR+OwXifnxZjij/pZWF775uSCMzWVd+jDik2H2IA== + dependencies: + debug "^4.3.4" + fs-extra "^10.1.0" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -1803,6 +2035,15 @@ fresh@^2.0.0: resolved "https://registry.yarnpkg.com/fresh/-/fresh-2.0.0.tgz#8dd7df6a1b3a1b3a5cf186c05a5dd267622635a4" integrity sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A== +fs-extra@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -1818,6 +2059,20 @@ function-bind@^1.1.2: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== +fuse.js@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-7.1.0.tgz#306228b4befeee11e05b027087c2744158527d09" + integrity sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ== + +galactus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/galactus/-/galactus-1.0.0.tgz#c2615182afa0c6d0859b92e56ae36d052827db7e" + integrity sha512-R1fam6D4CyKQGNlvJne4dkNF+PvUUl7TAJInvTGa9fti9qAv95quQz29GXapA4d8Ec266mJJxFVh82M4GIIGDQ== + dependencies: + debug "^4.3.4" + flora-colossus "^2.0.0" + fs-extra "^10.1.0" + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -1910,7 +2165,7 @@ gopd@^1.2.0: resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== -graceful-fs@^4.2.9: +graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -1965,11 +2220,23 @@ iconv-lite@0.6.3, iconv-lite@^0.6.3: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" +iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + ignore@^5.2.0, ignore@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== +ignore@^7.0.5: + version "7.0.5" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9" + integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg== + import-fresh@^3.2.1: version "3.3.1" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" @@ -2494,6 +2761,11 @@ jest@^29.4.0: import-local "^3.0.2" jest-cli "^29.7.0" +jose@^6.1.1: + version "6.1.3" + resolved "https://registry.yarnpkg.com/jose/-/jose-6.1.3.tgz#8453d7be88af7bb7d64a0481d6a35a0145ba3ea5" + integrity sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ== + "jq-web@https://github.com/stainless-api/jq-web/releases/download/v0.8.8/jq-web.tar.gz": version "0.8.8" resolved "https://github.com/stainless-api/jq-web/releases/download/v0.8.8/jq-web.tar.gz#7849ef64bdfc28f70cbfc9888f886860e96da10d" @@ -2538,6 +2810,11 @@ json-schema-traverse@^0.4.1: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" @@ -2548,6 +2825,15 @@ json5@^2.2.2, json5@^2.2.3: resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== +jsonfile@^6.0.1: + version "6.2.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.2.0.tgz#7c265bd1b65de6977478300087c99f1c84383f62" + integrity sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -2721,6 +3007,11 @@ ms@^2.1.3: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +mute-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e" + integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -2731,6 +3022,11 @@ negotiator@^1.0.0: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a" integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg== +node-forge@^1.3.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.3.tgz#0ad80f6333b3a0045e827ac20b7f735f93716751" + integrity sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg== + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -2796,6 +3092,11 @@ optionator@^0.9.3: type-check "^0.4.0" word-wrap "^1.2.5" +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + p-all@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-all/-/p-all-3.0.0.tgz#077c023c37e75e760193badab2bad3ccd5782bfb" @@ -2939,6 +3240,11 @@ prettier@^3.0.0: resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.5.3.tgz#4fc2ce0d657e7a02e602549f053b239cb7dfe1b5" integrity sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw== +pretty-bytes@^5.6.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" + integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== + pretty-format@^29.0.0, pretty-format@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" @@ -3020,6 +3326,11 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" @@ -3086,7 +3397,7 @@ safe-buffer@5.2.1, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -"safer-buffer@>= 2.1.2 < 3.0.0": +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -3190,6 +3501,11 @@ signal-exit@^3.0.3, signal-exit@^3.0.7: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +signal-exit@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -3334,6 +3650,13 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" @@ -3474,6 +3797,11 @@ undici-types@~6.21.0: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + unpipe@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -3537,6 +3865,15 @@ word-wrap@^1.2.5: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -3597,22 +3934,32 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -zod-to-json-schema@^3.24.1, zod-to-json-schema@^3.24.5: +yoctocolors-cjs@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz#7e4964ea8ec422b7a40ac917d3a344cfd2304baa" + integrity sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw== + +zod-to-json-schema@^3.24.5: version "3.24.5" resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz#d1095440b147fb7c2093812a53c54df8d5df50a3" integrity sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g== +zod-to-json-schema@^3.25.0: + version "3.25.0" + resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.25.0.tgz#df504c957c4fb0feff467c74d03e6aab0b013e1c" + integrity sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ== + zod-validation-error@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/zod-validation-error/-/zod-validation-error-4.0.1.tgz#a105723eb40299578a6a38cb86647068f6d005b1" integrity sha512-F3rdaCOHs5ViJ5YTz5zzRtfkQdMdIeKudJAoxy7yB/2ZMEHw73lmCAcQw11r7++20MyGl4WV59EVh7A9rNAyog== -zod@^3.23.8: - version "3.24.4" - resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.4.tgz#e2e2cca5faaa012d76e527d0d36622e0a90c315f" - integrity sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg== +"zod@^3.25 || ^4.0": + version "4.1.13" + resolved "https://registry.yarnpkg.com/zod/-/zod-4.1.13.tgz#93699a8afe937ba96badbb0ce8be6033c0a4b6b1" + integrity sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig== -zod@^3.25.20: +zod@^3.25.20, zod@^3.25.67: version "3.25.76" resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.76.tgz#26841c3f6fd22a6a2760e7ccb719179768471e34" integrity sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ== From 1757c430c970516be9002d1f6c341e123193a54a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 01:25:37 +0000 Subject: [PATCH 070/138] feat(api): api update --- .stats.yml | 4 +- LICENSE | 2 +- README.md | 9 + packages/mcp-server/README.md | 211 +-- packages/mcp-server/package.json | 6 +- packages/mcp-server/src/code-tool-types.ts | 16 +- packages/mcp-server/src/code-tool.ts | 68 +- packages/mcp-server/src/compat.ts | 483 ------- packages/mcp-server/src/docs-search-tool.ts | 2 +- packages/mcp-server/src/dynamic-tools.ts | 153 --- packages/mcp-server/src/filtering.ts | 18 - packages/mcp-server/src/http.ts | 27 +- packages/mcp-server/src/index.ts | 57 +- packages/mcp-server/src/options.ts | 395 +----- packages/mcp-server/src/server.ts | 82 +- packages/mcp-server/src/stdio.ts | 5 +- packages/mcp-server/src/tools.ts | 1 - .../tools/enrollments/create-enrollments.ts | 80 -- .../tools/enrollments/lapse-enrollments.ts | 41 - .../src/tools/enrollments/list-enrollments.ts | 63 - .../retrieve-certificate-enrollments.ts | 39 - .../tools/enrollments/retrieve-enrollments.ts | 54 - packages/mcp-server/src/tools/index.ts | 115 -- .../verify-insurance-verification.ts | 62 - .../mcp-server/src/tools/plans/list-plans.ts | 51 - .../src/tools/plans/retrieve-plans.ts | 54 - .../create-property-managers.ts | 125 -- .../delete-property-managers.ts | 40 - .../list-property-managers.ts | 60 - .../retrieve-property-managers.ts | 54 - .../update-property-managers.ts | 128 -- .../src/tools/tenants/create-tenants.ts | 107 -- .../src/tools/tenants/delete-tenants.ts | 40 - .../src/tools/tenants/list-tenants.ts | 63 - .../src/tools/tenants/retrieve-tenants.ts | 54 - .../src/tools/tenants/update-tenants.ts | 107 -- .../endpoints/create-webhook-endpoints.ts | 58 - .../endpoints/delete-webhook-endpoints.ts | 40 - .../endpoints/list-webhook-endpoints.ts | 60 - .../endpoints/retrieve-webhook-endpoints.ts | 54 - .../endpoints/update-webhook-endpoints.ts | 61 - packages/mcp-server/src/{tools => }/types.ts | 2 +- packages/mcp-server/tests/compat.test.ts | 1166 ----------------- .../mcp-server/tests/dynamic-tools.test.ts | 185 --- packages/mcp-server/tests/options.test.ts | 514 +------- packages/mcp-server/tests/tools.test.ts | 225 ---- packages/mcp-server/yarn.lock | 888 +++++++------ src/resources/plans.ts | 5 +- tests/api-resources/enrollments.test.ts | 6 +- tests/api-resources/property-managers.test.ts | 27 +- tests/api-resources/tenants.test.ts | 35 +- tests/index.test.ts | 72 +- yarn.lock | 556 ++++---- 53 files changed, 946 insertions(+), 5884 deletions(-) delete mode 100644 packages/mcp-server/src/compat.ts delete mode 100644 packages/mcp-server/src/dynamic-tools.ts delete mode 100644 packages/mcp-server/src/filtering.ts delete mode 100644 packages/mcp-server/src/tools.ts delete mode 100644 packages/mcp-server/src/tools/enrollments/create-enrollments.ts delete mode 100644 packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts delete mode 100644 packages/mcp-server/src/tools/enrollments/list-enrollments.ts delete mode 100644 packages/mcp-server/src/tools/enrollments/retrieve-certificate-enrollments.ts delete mode 100644 packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts delete mode 100644 packages/mcp-server/src/tools/index.ts delete mode 100644 packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts delete mode 100644 packages/mcp-server/src/tools/plans/list-plans.ts delete mode 100644 packages/mcp-server/src/tools/plans/retrieve-plans.ts delete mode 100644 packages/mcp-server/src/tools/property-managers/create-property-managers.ts delete mode 100644 packages/mcp-server/src/tools/property-managers/delete-property-managers.ts delete mode 100644 packages/mcp-server/src/tools/property-managers/list-property-managers.ts delete mode 100644 packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts delete mode 100644 packages/mcp-server/src/tools/property-managers/update-property-managers.ts delete mode 100644 packages/mcp-server/src/tools/tenants/create-tenants.ts delete mode 100644 packages/mcp-server/src/tools/tenants/delete-tenants.ts delete mode 100644 packages/mcp-server/src/tools/tenants/list-tenants.ts delete mode 100644 packages/mcp-server/src/tools/tenants/retrieve-tenants.ts delete mode 100644 packages/mcp-server/src/tools/tenants/update-tenants.ts delete mode 100644 packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts delete mode 100644 packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts delete mode 100644 packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts delete mode 100644 packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts delete mode 100644 packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts rename packages/mcp-server/src/{tools => }/types.ts (98%) delete mode 100644 packages/mcp-server/tests/compat.test.ts delete mode 100644 packages/mcp-server/tests/dynamic-tools.test.ts delete mode 100644 packages/mcp-server/tests/tools.test.ts diff --git a/.stats.yml b/.stats.yml index 6dc2ec4c..2fa4d986 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 23 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-efa14cecc8a1594ca65d6987b7091cbfe7310b290eee8dcbc00875809993d4f0.yml -openapi_spec_hash: 09eea0dc2832424a2a46de36b0cc1bad +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-31b09d79d346937b987ae9132a4bb1200ef2aefdfaa4eda5bd9800ad20293f1a.yml +openapi_spec_hash: 85a9e4ac6a6000b79c6b7685f1630bc2 config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/LICENSE b/LICENSE index 70f57606..ffaf6d8c 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2025 Beagle + Copyright 2026 Beagle Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 2cfecce8..c294f7b5 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,15 @@ The full API of this library can be found in [api.md](api.md). It is generated with [Stainless](https://www.stainless.com/). +## MCP Server + +Use the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application. + +[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXX0) +[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%7D) + +> Note: You may need to set environment variables in your MCP client. + ## Installation ```sh diff --git a/packages/mcp-server/README.md b/packages/mcp-server/README.md index dbcca8ff..c720b961 100644 --- a/packages/mcp-server/README.md +++ b/packages/mcp-server/README.md @@ -26,7 +26,7 @@ For clients with a configuration JSON, it might look something like this: "mcpServers": { "corgi_tech_beagle_api": { "command": "npx", - "args": ["-y", "@corgi-tech/beagle-mcp", "--client=claude", "--tools=dynamic"], + "args": ["-y", "@corgi-tech/beagle-mcp"], "env": { "BEAGLE_API_KEY": "My API Key", "BEAGLE_ENVIRONMENT": "production" @@ -41,7 +41,7 @@ For clients with a configuration JSON, it might look something like this: If you use Cursor, you can install the MCP server by using the button below. You will need to set your environment variables in Cursor's `mcp.json`, which can be found in Cursor Settings > Tools & MCP > New MCP Server. -[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=@corgi-tech/beagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiU2V0IHlvdXIgQkVBR0xFX0FQSV9LRVkgaGVyZS4ifX0) +[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiU2V0IHlvdXIgQkVBR0xFX0FQSV9LRVkgaGVyZS4ifX0) ### VS Code @@ -56,113 +56,25 @@ If you use Claude Code, you can install the MCP server by running the command be environment variables in Claude Code's `.claude.json`, which can be found in your home directory. ``` -claude mcp add --transport stdio corgi_tech_beagle_api --env BEAGLE_API_KEY="Your BEAGLE_API_KEY here." -- npx -y @corgi-tech/beagle-mcp +claude mcp add corgi_tech_beagle_mcp_api --env BEAGLE_API_KEY="Your BEAGLE_API_KEY here." -- npx -y @corgi-tech/beagle-mcp ``` -## Exposing endpoints to your MCP Client +## Code Mode -There are three ways to expose endpoints as tools in the MCP server: +This MCP server is built on the "Code Mode" tool scheme. In this MCP Server, +your agent will write code against the TypeScript SDK, which will then be executed in an +isolated sandbox. To accomplish this, the server will expose two tools to your agent: -1. Exposing one tool per endpoint, and filtering as necessary -2. Exposing a set of tools to dynamically discover and invoke endpoints from the API -3. Exposing a docs search tool and a code execution tool, allowing the client to write code to be executed against the TypeScript client +- The first tool is a docs search tool, which can be used to generically query for + documentation about your API/SDK. -### Filtering endpoints and tools +- The second tool is a code tool, where the agent can write code against the TypeScript SDK. + The code will be executed in a sandbox environment without web or filesystem access. Then, + anything the code returns or prints will be returned to the agent as the result of the + tool call. -You can run the package on the command line to discover and filter the set of tools that are exposed by the -MCP Server. This can be helpful for large APIs where including all endpoints at once is too much for your AI's -context window. - -You can filter by multiple aspects: - -- `--tool` includes a specific tool by name -- `--resource` includes all tools under a specific resource, and can have wildcards, e.g. `my.resource*` -- `--operation` includes just read (get/list) or just write operations - -### Dynamic tools - -If you specify `--tools=dynamic` to the MCP server, instead of exposing one tool per endpoint in the API, it will -expose the following tools: - -1. `list_api_endpoints` - Discovers available endpoints, with optional filtering by search query -2. `get_api_endpoint_schema` - Gets detailed schema information for a specific endpoint -3. `invoke_api_endpoint` - Executes any endpoint with the appropriate parameters - -This allows you to have the full set of API endpoints available to your MCP Client, while not requiring that all -of their schemas be loaded into context at once. Instead, the LLM will automatically use these tools together to -search for, look up, and invoke endpoints dynamically. However, due to the indirect nature of the schemas, it -can struggle to provide the correct properties a bit more than when tools are imported explicitly. Therefore, -you can opt-in to explicit tools, the dynamic tools, or both. - -See more information with `--help`. - -All of these command-line options can be repeated, combined together, and have corresponding exclusion versions (e.g. `--no-tool`). - -Use `--list` to see the list of available tools, or see below. - -### Code execution - -If you specify `--tools=code` to the MCP server, it will expose just two tools: - -- `search_docs` - Searches the API documentation and returns a list of markdown results -- `execute` - Runs code against the TypeScript client - -This allows the LLM to implement more complex logic by chaining together many API calls without loading -intermediary results into its context window. - -The code execution itself happens in a Deno sandbox that has network access only to the base URL for the API. - -### Specifying the MCP Client - -Different clients have varying abilities to handle arbitrary tools and schemas. - -You can specify the client you are using with the `--client` argument, and the MCP server will automatically -serve tools and schemas that are more compatible with that client. - -- `--client=`: Set all capabilities based on a known MCP client - - - Valid values: `openai-agents`, `claude`, `claude-code`, `cursor` - - Example: `--client=cursor` - -Additionally, if you have a client not on the above list, or the client has gotten better -over time, you can manually enable or disable certain capabilities: - -- `--capability=`: Specify individual client capabilities - - Available capabilities: - - `top-level-unions`: Enable support for top-level unions in tool schemas - - `valid-json`: Enable JSON string parsing for arguments - - `refs`: Enable support for $ref pointers in schemas - - `unions`: Enable support for union types (anyOf) in schemas - - `formats`: Enable support for format validations in schemas (e.g. date-time, email) - - `tool-name-length=N`: Set maximum tool name length to N characters - - Example: `--capability=top-level-unions --capability=tool-name-length=40` - - Example: `--capability=top-level-unions,tool-name-length=40` - -### Examples - -1. Filter for read operations on cards: - -```bash ---resource=cards --operation=read -``` - -2. Exclude specific tools while including others: - -```bash ---resource=cards --no-tool=create_cards -``` - -3. Configure for Cursor client with custom max tool name length: - -```bash ---client=cursor --capability=tool-name-length=40 -``` - -4. Complex filtering with multiple criteria: - -```bash ---resource=cards,accounts --operation=read --tag=kyc --no-tool=create_cards -``` +Using this scheme, agents are capable of performing very complex tasks deterministically +and repeatably. ## Running remotely @@ -187,96 +99,3 @@ A configuration JSON for this server might look like this, assuming the server i } } ``` - -The command-line arguments for filtering tools and specifying clients can also be used as query parameters in the URL. -For example, to exclude specific tools while including others, use the URL: - -``` -http://localhost:3000?resource=cards&resource=accounts&no_tool=create_cards -``` - -Or, to configure for the Cursor client, with a custom max tool name length, use the URL: - -``` -http://localhost:3000?client=cursor&capability=tool-name-length%3D40 -``` - -## Importing the tools and server individually - -```js -// Import the server, generated endpoints, or the init function -import { server, endpoints, init } from "@corgi-tech/beagle-mcp/server"; - -// import a specific tool -import retrievePlans from "@corgi-tech/beagle-mcp/tools/plans/retrieve-plans"; - -// initialize the server and all endpoints -init({ server, endpoints }); - -// manually start server -const transport = new StdioServerTransport(); -await server.connect(transport); - -// or initialize your own server with specific tools -const myServer = new McpServer(...); - -// define your own endpoint -const myCustomEndpoint = { - tool: { - name: 'my_custom_tool', - description: 'My custom tool', - inputSchema: zodToJsonSchema(z.object({ a_property: z.string() })), - }, - handler: async (client: client, args: any) => { - return { myResponse: 'Hello world!' }; - }) -}; - -// initialize the server with your custom endpoints -init({ server: myServer, endpoints: [retrievePlans, myCustomEndpoint] }); -``` - -## Available Tools - -The following tools are available in this MCP server. - -### Resource `plans`: - -- `retrieve_plans` (`read`): retrieve a specific plans details by its code. -- `list_plans` (`read`): list all available plans, note this endpoint is currently unpaginated unlike all other list endpoints. - -### Resource `property_managers`: - -- `create_property_managers` (`write`): create a new property manager. -- `retrieve_property_managers` (`read`): get a property manager by id. -- `update_property_managers` (`write`): update an existing property manager by id, note that when updating contacts or addresses you need to send the whole array you want to replace them with. -- `list_property_managers` (`read`): list all property managers, note this endpoint is paginated. -- `delete_property_managers` (`write`): delete a property manager by id. - -### Resource `tenants`: - -- `create_tenants` (`write`): create a new tenant. -- `retrieve_tenants` (`read`): retrieve a single tenant by their id. -- `update_tenants` (`write`): update an existing tenant by their id. -- `list_tenants` (`read`): list all tenants, this endpoint is paginated and allows for queries by individual property manager. -- `delete_tenants` (`write`): delete an existing tenant by their id. - -### Resource `enrollments`: - -- `create_enrollments` (`write`): create a new enrollment for a tenant. -- `retrieve_enrollments` (`read`): get a specific enrollment by its id. -- `list_enrollments` (`read`): list all enrollments, this endpoint is paginated and allows for queries by individual property manager. -- `lapse_enrollments` (`write`): lapses a specific enrollment for a tenant, note that if a tenant has multiple enrollments (e.g., SDR and TLL), each must be lapsed individually -- `retrieve_certificate_enrollments` (`read`): get the certificate of enrollment for a given enrollment - -### Resource `insurance_verification`: - -- `verify_insurance_verification` (`write`): trigger a job to parse a tenants insurance document(s) - -### Resource `webhook.endpoints`: - -- `create_webhook_endpoints` (`write`): creates a new webhook target. -- `retrieve_webhook_endpoints` (`read`): retrieve a single webhook endpoint by its id. -- `update_webhook_endpoints` (`write`): update an existing webhook endpoint by its id. -- `list_webhook_endpoints` (`read`): list all webhook endpoints, this endpoint is paginated and allows for queries by individual property manager. -- `delete_webhook_endpoints` (`write`): delete an existing webhook endpoint by its id. diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index fddb332a..6f5ead4a 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -32,13 +32,13 @@ "dependencies": { "@corgi-tech/beagle": "file:../../dist/", "@cloudflare/cabidela": "^0.2.4", - "@modelcontextprotocol/sdk": "^1.24.0", + "@modelcontextprotocol/sdk": "^1.25.2", "@valtown/deno-http-worker": "^0.0.21", "cors": "^2.8.5", "express": "^5.1.0", "fuse.js": "^7.1.0", "jq-web": "https://github.com/stainless-api/jq-web/releases/download/v0.8.8/jq-web.tar.gz", - "qs": "^6.14.0", + "qs": "^6.14.1", "typescript": "5.8.3", "yargs": "^17.7.2", "zod": "^3.25.20", @@ -49,7 +49,7 @@ "mcp-server": "dist/index.js" }, "devDependencies": { - "@anthropic-ai/mcpb": "1.1.0", + "@anthropic-ai/mcpb": "^2.1.2", "@types/cors": "^2.8.19", "@types/express": "^5.0.3", "@types/jest": "^29.4.0", diff --git a/packages/mcp-server/src/code-tool-types.ts b/packages/mcp-server/src/code-tool-types.ts index 6ab80a26..9dca2664 100644 --- a/packages/mcp-server/src/code-tool-types.ts +++ b/packages/mcp-server/src/code-tool-types.ts @@ -3,16 +3,14 @@ import { ClientOptions } from '@corgi-tech/beagle'; export type WorkerInput = { - opts: ClientOptions; + project_name: string; code: string; + client_opts: ClientOptions; + intent?: string | undefined; }; -export type WorkerSuccess = { +export type WorkerOutput = { + is_error: boolean; result: unknown | null; - logLines: string[]; - errLines: string[]; -}; -export type WorkerError = { - message: string | undefined; - logLines: string[]; - errLines: string[]; + log_lines: string[]; + err_lines: string[]; }; diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 6f0c029f..2e80fdcf 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -1,9 +1,28 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Metadata, ToolCallResult, asTextContentResult } from './tools/types'; +import { McpTool, Metadata, ToolCallResult, asErrorResult, asTextContentResult } from './types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import { readEnv } from './server'; -import { WorkerSuccess } from './code-tool-types'; +import { readEnv, readEnvOrError } from './server'; +import { WorkerInput, WorkerOutput } from './code-tool-types'; + +const prompt = `Runs JavaScript code to interact with the Beagle API. + +You are a skilled programmer writing code to interface with the service. +Define an async function named "run" that takes a single parameter of an initialized SDK client and it will be run. +For example: + +\`\`\` +async function run(client) { + const plans = await client.plans.list(); +} +\`\`\` + +You will be returned anything that your function returns, plus the results of any console.log statements. +Do not add try-catch blocks for single API calls. The tool will handle errors for you. +Do not add comments unless necessary for generating better code. +Code will run in a container, and cannot interact with the network outside of the given SDK client. +Variables will not persist between calls, so make sure to return or log any data you might need later.`; + /** * A tool that runs code against a copy of the SDK. * @@ -13,16 +32,29 @@ import { WorkerSuccess } from './code-tool-types'; * * @param endpoints - The endpoints to include in the list. */ -export async function codeTool() { +export function codeTool(): McpTool { const metadata: Metadata = { resource: 'all', operation: 'write', tags: [] }; const tool: Tool = { name: 'execute', - description: - 'Runs JavaScript code to interact with the API.\n\nYou are a skilled programmer writing code to interface with the service.\nDefine an async function named "run" that takes a single parameter of an initialized SDK client and it will be run.\nWrite code within this template:\n\n```\nasync function run(client) {\n // Fill this out\n}\n```\n\nYou will be returned anything that your function returns, plus the results of any console.log statements.\nIf any code triggers an error, the tool will return an error response, so you do not need to add error handling unless you want to output something more helpful than the raw error.\nIt is not necessary to add comments to code, unless by adding those comments you believe that you can generate better code.\nThis code will run in a container, and you will not be able to use fetch or otherwise interact with the network calls other than through the client you are given.\nAny variables you define won\'t live between successive uses of this call, so make sure to return or log any data you might need later.', - inputSchema: { type: 'object', properties: { code: { type: 'string' } } }, + description: prompt, + inputSchema: { + type: 'object', + properties: { + code: { + type: 'string', + description: 'Code to execute.', + }, + intent: { + type: 'string', + description: 'Task you are trying to perform. Used for improving the service.', + }, + }, + required: ['code'], + }, }; const handler = async (_: unknown, args: any): Promise => { const code = args.code as string; + const intent = args.intent as string | undefined; // this is not required, but passing a Stainless API key for the matching project_name // will allow you to run code-mode queries against non-published versions of your SDK. @@ -35,13 +67,17 @@ export async function codeTool() { headers: { ...(stainlessAPIKey && { Authorization: stainlessAPIKey }), 'Content-Type': 'application/json', - client_envs: JSON.stringify({ BEAGLE_API_KEY: readEnv('BEAGLE_API_KEY') }), + client_envs: JSON.stringify({ + BEAGLE_API_KEY: readEnvOrError('BEAGLE_API_KEY'), + BEAGLE_BASE_URL: readEnv('BEAGLE_BASE_URL'), + }), }, body: JSON.stringify({ project_name: 'beagle', - client_opts: { environment: (readEnv('BEAGLE_ENVIRONMENT') || undefined) as any }, code, - }), + intent, + client_opts: { environment: (readEnv('BEAGLE_ENVIRONMENT') || undefined) as any }, + } satisfies WorkerInput), }); if (!res.ok) { @@ -52,7 +88,17 @@ export async function codeTool() { ); } - return asTextContentResult((await res.json()) as WorkerSuccess); + const { is_error, result, log_lines, err_lines } = (await res.json()) as WorkerOutput; + const hasLogs = log_lines.length > 0 || err_lines.length > 0; + const output = { + result, + ...(log_lines.length > 0 && { log_lines }), + ...(err_lines.length > 0 && { err_lines }), + }; + if (is_error) { + return asErrorResult(typeof result === 'string' && !hasLogs ? result : JSON.stringify(output, null, 2)); + } + return asTextContentResult(output); }; return { metadata, tool, handler }; diff --git a/packages/mcp-server/src/compat.ts b/packages/mcp-server/src/compat.ts deleted file mode 100644 index f84053c7..00000000 --- a/packages/mcp-server/src/compat.ts +++ /dev/null @@ -1,483 +0,0 @@ -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import { z } from 'zod'; -import { Endpoint } from './tools'; - -export interface ClientCapabilities { - topLevelUnions: boolean; - validJson: boolean; - refs: boolean; - unions: boolean; - formats: boolean; - toolNameLength: number | undefined; -} - -export const defaultClientCapabilities: ClientCapabilities = { - topLevelUnions: true, - validJson: true, - refs: true, - unions: true, - formats: true, - toolNameLength: undefined, -}; - -export const ClientType = z.enum(['openai-agents', 'claude', 'claude-code', 'cursor', 'infer']); -export type ClientType = z.infer; - -// Client presets for compatibility -// Note that these could change over time as models get better, so this is -// a best effort. -export const knownClients: Record, ClientCapabilities> = { - 'openai-agents': { - topLevelUnions: false, - validJson: true, - refs: true, - unions: true, - formats: true, - toolNameLength: undefined, - }, - claude: { - topLevelUnions: true, - validJson: false, - refs: true, - unions: true, - formats: true, - toolNameLength: undefined, - }, - 'claude-code': { - topLevelUnions: false, - validJson: true, - refs: true, - unions: true, - formats: true, - toolNameLength: undefined, - }, - cursor: { - topLevelUnions: false, - validJson: true, - refs: false, - unions: false, - formats: false, - toolNameLength: 50, - }, -}; - -/** - * Attempts to parse strings into JSON objects - */ -export function parseEmbeddedJSON(args: Record, schema: Record) { - let updated = false; - const newArgs: Record = Object.assign({}, args); - - for (const [key, value] of Object.entries(newArgs)) { - if (typeof value === 'string') { - try { - const parsed = JSON.parse(value); - // Only parse if result is a plain object (not array, null, or primitive) - if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) { - newArgs[key] = parsed; - updated = true; - } - } catch (e) { - // Not valid JSON, leave as is - } - } - } - - if (updated) { - return newArgs; - } - - return args; -} - -export type JSONSchema = { - type?: string; - properties?: Record; - required?: string[]; - anyOf?: JSONSchema[]; - $ref?: string; - $defs?: Record; - [key: string]: any; -}; - -/** - * Truncates tool names to the specified length while ensuring uniqueness. - * If truncation would cause duplicate names, appends a number to make them unique. - */ -export function truncateToolNames(names: string[], maxLength: number): Map { - if (maxLength <= 0) { - return new Map(); - } - - const renameMap = new Map(); - const usedNames = new Set(); - - const toTruncate = names.filter((name) => name.length > maxLength); - - if (toTruncate.length === 0) { - return renameMap; - } - - const willCollide = - new Set(toTruncate.map((name) => name.slice(0, maxLength - 1))).size < toTruncate.length; - - if (!willCollide) { - for (const name of toTruncate) { - const truncatedName = name.slice(0, maxLength); - renameMap.set(name, truncatedName); - } - } else { - const baseLength = maxLength - 1; - - for (const name of toTruncate) { - const baseName = name.slice(0, baseLength); - let counter = 1; - - while (usedNames.has(baseName + counter)) { - counter++; - } - - const finalName = baseName + counter; - renameMap.set(name, finalName); - usedNames.add(finalName); - } - } - - return renameMap; -} - -/** - * Removes top-level unions from a tool by splitting it into multiple tools, - * one for each variant in the union. - */ -export function removeTopLevelUnions(tool: Tool): Tool[] { - const inputSchema = tool.inputSchema as JSONSchema; - const variants = inputSchema.anyOf; - - if (!variants || !Array.isArray(variants) || variants.length === 0) { - return [tool]; - } - - const defs = inputSchema.$defs || {}; - - return variants.map((variant, index) => { - const variantSchema: JSONSchema = { - ...inputSchema, - ...variant, - type: 'object', - properties: { - ...(inputSchema.properties || {}), - ...(variant.properties || {}), - }, - }; - - delete variantSchema.anyOf; - - if (!variantSchema['description']) { - variantSchema['description'] = tool.description; - } - - const usedDefs = findUsedDefs(variant, defs); - if (Object.keys(usedDefs).length > 0) { - variantSchema.$defs = usedDefs; - } else { - delete variantSchema.$defs; - } - - return { - ...tool, - name: `${tool.name}_${toSnakeCase(variant['title'] || `variant${index + 1}`)}`, - description: variant['description'] || tool.description, - inputSchema: variantSchema, - } as Tool; - }); -} - -function findUsedDefs( - schema: JSONSchema, - defs: Record, - visited: Set = new Set(), -): Record { - const usedDefs: Record = {}; - - if (typeof schema !== 'object' || schema === null) { - return usedDefs; - } - - if (schema.$ref) { - const refParts = schema.$ref.split('/'); - if (refParts[0] === '#' && refParts[1] === '$defs' && refParts[2]) { - const defName = refParts[2]; - const def = defs[defName]; - if (def && !visited.has(schema.$ref)) { - usedDefs[defName] = def; - visited.add(schema.$ref); - Object.assign(usedDefs, findUsedDefs(def, defs, visited)); - visited.delete(schema.$ref); - } - } - return usedDefs; - } - - for (const key in schema) { - if (key !== '$defs' && typeof schema[key] === 'object' && schema[key] !== null) { - Object.assign(usedDefs, findUsedDefs(schema[key] as JSONSchema, defs, visited)); - } - } - - return usedDefs; -} - -// Export for testing -export { findUsedDefs }; - -/** - * Inlines all $refs in a schema, eliminating $defs. - * If a circular reference is detected, the circular property is removed. - */ -export function inlineRefs(schema: JSONSchema): JSONSchema { - if (!schema || typeof schema !== 'object') { - return schema; - } - - const clonedSchema = { ...schema }; - const defs: Record = schema.$defs || {}; - - delete clonedSchema.$defs; - - const result = inlineRefsRecursive(clonedSchema, defs, new Set()); - // The top level can never be null - return result === null ? {} : result; -} - -function inlineRefsRecursive( - schema: JSONSchema, - defs: Record, - refPath: Set, -): JSONSchema | null { - if (!schema || typeof schema !== 'object') { - return schema; - } - - if (Array.isArray(schema)) { - return schema.map((item) => { - const processed = inlineRefsRecursive(item, defs, refPath); - return processed === null ? {} : processed; - }) as JSONSchema; - } - - const result = { ...schema }; - - if ('$ref' in result && typeof result.$ref === 'string') { - if (result.$ref.startsWith('#/$defs/')) { - const refName = result.$ref.split('/').pop() as string; - const def = defs[refName]; - - // If we've already seen this ref in our path, we have a circular reference - if (refPath.has(result.$ref)) { - // For circular references, we completely remove the property - // by returning null. The parent will remove it. - return null; - } - - if (def) { - const newRefPath = new Set(refPath); - newRefPath.add(result.$ref); - - const inlinedDef = inlineRefsRecursive({ ...def }, defs, newRefPath); - - if (inlinedDef === null) { - return { ...result }; - } - - // Merge the inlined definition with the original schema's properties - // but preserve things like description, etc. - const { $ref, ...rest } = result; - return { ...inlinedDef, ...rest }; - } - } - - // Keep external refs as-is - return result; - } - - for (const key in result) { - if (result[key] && typeof result[key] === 'object') { - const processed = inlineRefsRecursive(result[key] as JSONSchema, defs, refPath); - if (processed === null) { - // Remove properties that would cause circular references - delete result[key]; - } else { - result[key] = processed; - } - } - } - - return result; -} - -/** - * Removes anyOf fields from a schema, using only the first variant. - */ -export function removeAnyOf(schema: JSONSchema): JSONSchema { - if (!schema || typeof schema !== 'object') { - return schema; - } - - if (Array.isArray(schema)) { - return schema.map((item) => removeAnyOf(item)) as JSONSchema; - } - - const result = { ...schema }; - - if ('anyOf' in result && Array.isArray(result.anyOf) && result.anyOf.length > 0) { - const firstVariant = result.anyOf[0]; - - if (firstVariant && typeof firstVariant === 'object') { - // Special handling for properties to ensure deep merge - if (firstVariant.properties && result.properties) { - result.properties = { - ...result.properties, - ...(firstVariant.properties as Record), - }; - } else if (firstVariant.properties) { - result.properties = { ...firstVariant.properties }; - } - - for (const key in firstVariant) { - if (key !== 'properties') { - result[key] = firstVariant[key]; - } - } - } - - delete result.anyOf; - } - - for (const key in result) { - if (result[key] && typeof result[key] === 'object') { - result[key] = removeAnyOf(result[key] as JSONSchema); - } - } - - return result; -} - -/** - * Removes format fields from a schema and appends them to the description. - */ -export function removeFormats(schema: JSONSchema, formatsCapability: boolean): JSONSchema { - if (formatsCapability) { - return schema; - } - - if (!schema || typeof schema !== 'object') { - return schema; - } - - if (Array.isArray(schema)) { - return schema.map((item) => removeFormats(item, formatsCapability)) as JSONSchema; - } - - const result = { ...schema }; - - if ('format' in result && typeof result['format'] === 'string') { - const formatStr = `(format: "${result['format']}")`; - - if ('description' in result && typeof result['description'] === 'string') { - result['description'] = `${result['description']} ${formatStr}`; - } else { - result['description'] = formatStr; - } - - delete result['format']; - } - - for (const key in result) { - if (result[key] && typeof result[key] === 'object') { - result[key] = removeFormats(result[key] as JSONSchema, formatsCapability); - } - } - - return result; -} - -/** - * Applies all compatibility transformations to the endpoints based on the provided capabilities. - */ -export function applyCompatibilityTransformations( - endpoints: Endpoint[], - capabilities: ClientCapabilities, -): Endpoint[] { - let transformedEndpoints = [...endpoints]; - - // Handle top-level unions first as this changes tool names - if (!capabilities.topLevelUnions) { - const newEndpoints: Endpoint[] = []; - - for (const endpoint of transformedEndpoints) { - const variantTools = removeTopLevelUnions(endpoint.tool); - - if (variantTools.length === 1) { - newEndpoints.push(endpoint); - } else { - for (const variantTool of variantTools) { - newEndpoints.push({ - ...endpoint, - tool: variantTool, - }); - } - } - } - - transformedEndpoints = newEndpoints; - } - - if (capabilities.toolNameLength) { - const toolNames = transformedEndpoints.map((endpoint) => endpoint.tool.name); - const renameMap = truncateToolNames(toolNames, capabilities.toolNameLength); - - transformedEndpoints = transformedEndpoints.map((endpoint) => ({ - ...endpoint, - tool: { - ...endpoint.tool, - name: renameMap.get(endpoint.tool.name) ?? endpoint.tool.name, - }, - })); - } - - if (!capabilities.refs || !capabilities.unions || !capabilities.formats) { - transformedEndpoints = transformedEndpoints.map((endpoint) => { - let schema = endpoint.tool.inputSchema as JSONSchema; - - if (!capabilities.refs) { - schema = inlineRefs(schema); - } - - if (!capabilities.unions) { - schema = removeAnyOf(schema); - } - - if (!capabilities.formats) { - schema = removeFormats(schema, capabilities.formats); - } - - return { - ...endpoint, - tool: { - ...endpoint.tool, - inputSchema: schema as typeof endpoint.tool.inputSchema, - }, - }; - }); - } - - return transformedEndpoints; -} - -function toSnakeCase(str: string): string { - return str - .replace(/\s+/g, '_') - .replace(/([a-z])([A-Z])/g, '$1_$2') - .toLowerCase(); -} diff --git a/packages/mcp-server/src/docs-search-tool.ts b/packages/mcp-server/src/docs-search-tool.ts index 6d482a49..d4a4fc8d 100644 --- a/packages/mcp-server/src/docs-search-tool.ts +++ b/packages/mcp-server/src/docs-search-tool.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Metadata, asTextContentResult } from './tools/types'; +import { Metadata, asTextContentResult } from './types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; diff --git a/packages/mcp-server/src/dynamic-tools.ts b/packages/mcp-server/src/dynamic-tools.ts deleted file mode 100644 index 12310045..00000000 --- a/packages/mcp-server/src/dynamic-tools.ts +++ /dev/null @@ -1,153 +0,0 @@ -import Beagle from '@corgi-tech/beagle'; -import { Endpoint, asTextContentResult, ToolCallResult } from './tools/types'; -import { zodToJsonSchema } from 'zod-to-json-schema'; -import { z } from 'zod'; -import { Cabidela } from '@cloudflare/cabidela'; - -function zodToInputSchema(schema: z.ZodSchema) { - return { - type: 'object' as const, - ...(zodToJsonSchema(schema) as any), - }; -} - -/** - * A list of tools that expose all the endpoints in the API dynamically. - * - * Instead of exposing every endpoint as its own tool, which uses up too many tokens for LLMs to use at once, - * we expose a single tool that can be used to search for endpoints by name, resource, operation, or tag, and then - * a generic endpoint that can be used to invoke any endpoint with the provided arguments. - * - * @param endpoints - The endpoints to include in the list. - */ -export function dynamicTools(endpoints: Endpoint[]): Endpoint[] { - const listEndpointsSchema = z.object({ - search_query: z - .string() - .optional() - .describe( - 'An optional search query to filter the endpoints by. Provide a partial name, resource, operation, or tag to filter the endpoints returned.', - ), - }); - - const listEndpointsTool = { - metadata: { - resource: 'dynamic_tools', - operation: 'read' as const, - tags: [], - }, - tool: { - name: 'list_api_endpoints', - description: 'List or search for all endpoints in the Beagle TypeScript API', - inputSchema: zodToInputSchema(listEndpointsSchema), - }, - handler: async (client: Beagle, args: Record | undefined): Promise => { - const query = args && listEndpointsSchema.parse(args).search_query?.trim(); - - const filteredEndpoints = - query && query.length > 0 ? - endpoints.filter((endpoint) => { - const fieldsToMatch = [ - endpoint.tool.name, - endpoint.tool.description, - endpoint.metadata.resource, - endpoint.metadata.operation, - ...endpoint.metadata.tags, - ]; - return fieldsToMatch.some((field) => field && field.toLowerCase().includes(query.toLowerCase())); - }) - : endpoints; - - return asTextContentResult({ - tools: filteredEndpoints.map(({ tool, metadata }) => ({ - name: tool.name, - description: tool.description, - resource: metadata.resource, - operation: metadata.operation, - tags: metadata.tags, - })), - }); - }, - }; - - const getEndpointSchema = z.object({ - endpoint: z.string().describe('The name of the endpoint to get the schema for.'), - }); - const getEndpointTool = { - metadata: { - resource: 'dynamic_tools', - operation: 'read' as const, - tags: [], - }, - tool: { - name: 'get_api_endpoint_schema', - description: - 'Get the schema for an endpoint in the Beagle TypeScript API. You can use the schema returned by this tool to invoke an endpoint with the `invoke_api_endpoint` tool.', - inputSchema: zodToInputSchema(getEndpointSchema), - }, - handler: async (client: Beagle, args: Record | undefined) => { - if (!args) { - throw new Error('No endpoint provided'); - } - const endpointName = getEndpointSchema.parse(args).endpoint; - - const endpoint = endpoints.find((e) => e.tool.name === endpointName); - if (!endpoint) { - throw new Error(`Endpoint ${endpointName} not found`); - } - return asTextContentResult(endpoint.tool); - }, - }; - - const invokeEndpointSchema = z.object({ - endpoint_name: z.string().describe('The name of the endpoint to invoke.'), - args: z - .record(z.string(), z.any()) - .describe( - 'The arguments to pass to the endpoint. This must match the schema returned by the `get_api_endpoint_schema` tool.', - ), - }); - - const invokeEndpointTool = { - metadata: { - resource: 'dynamic_tools', - operation: 'write' as const, - tags: [], - }, - tool: { - name: 'invoke_api_endpoint', - description: - 'Invoke an endpoint in the Beagle TypeScript API. Note: use the `list_api_endpoints` tool to get the list of endpoints and `get_api_endpoint_schema` tool to get the schema for an endpoint.', - inputSchema: zodToInputSchema(invokeEndpointSchema), - }, - handler: async (client: Beagle, args: Record | undefined): Promise => { - if (!args) { - throw new Error('No endpoint provided'); - } - const { success, data, error } = invokeEndpointSchema.safeParse(args); - if (!success) { - throw new Error(`Invalid arguments for endpoint. ${error?.format()}`); - } - const { endpoint_name, args: endpointArgs } = data; - - const endpoint = endpoints.find((e) => e.tool.name === endpoint_name); - if (!endpoint) { - throw new Error( - `Endpoint ${endpoint_name} not found. Use the \`list_api_endpoints\` tool to get the list of available endpoints.`, - ); - } - - try { - // Try to validate the arguments for a better error message - const cabidela = new Cabidela(endpoint.tool.inputSchema, { fullErrors: true }); - cabidela.validate(endpointArgs); - } catch (error) { - throw new Error(`Invalid arguments for endpoint ${endpoint_name}:\n${error}`); - } - - return await endpoint.handler(client, endpointArgs); - }, - }; - - return [getEndpointTool, listEndpointsTool, invokeEndpointTool]; -} diff --git a/packages/mcp-server/src/filtering.ts b/packages/mcp-server/src/filtering.ts deleted file mode 100644 index eaae0fcf..00000000 --- a/packages/mcp-server/src/filtering.ts +++ /dev/null @@ -1,18 +0,0 @@ -// @ts-nocheck -import initJq from 'jq-web'; - -export async function maybeFilter(jqFilter: unknown | undefined, response: any): Promise { - if (jqFilter && typeof jqFilter === 'string') { - return await jq(response, jqFilter); - } else { - return response; - } -} - -async function jq(json: any, jqFilter: string) { - return (await initJq).json(json, jqFilter); -} - -export function isJqError(error: any): error is Error { - return error instanceof Error && 'stderr' in error; -} diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index 84517003..dcfeba6a 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -4,38 +4,21 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; import express from 'express'; -import { fromError } from 'zod-validation-error/v3'; -import { McpOptions, parseQueryOptions } from './options'; +import { McpOptions } from './options'; import { ClientOptions, initMcpServer, newMcpServer } from './server'; import { parseAuthHeaders } from './headers'; const newServer = ({ clientOptions, - mcpOptions: defaultMcpOptions, req, res, }: { clientOptions: ClientOptions; - mcpOptions: McpOptions; req: express.Request; res: express.Response; }): McpServer | null => { const server = newMcpServer(); - let mcpOptions: McpOptions; - try { - mcpOptions = parseQueryOptions(defaultMcpOptions, req.query); - } catch (error) { - res.status(400).json({ - jsonrpc: '2.0', - error: { - code: -32000, - message: `Invalid request: ${fromError(error)}`, - }, - }); - return null; - } - try { const authOptions = parseAuthHeaders(req); initMcpServer({ @@ -44,7 +27,6 @@ const newServer = ({ ...clientOptions, ...authOptions, }, - mcpOptions, }); } catch (error) { res.status(401).json({ @@ -66,11 +48,8 @@ const post = const server = newServer({ ...options, req, res }); // If we return null, we already set the authorization error. if (server === null) return; - const transport = new StreamableHTTPServerTransport({ - // Stateless server - sessionIdGenerator: undefined, - }); - await server.connect(transport); + const transport = new StreamableHTTPServerTransport(); + await server.connect(transport as any); await transport.handleRequest(req, res, req.body); }; diff --git a/packages/mcp-server/src/index.ts b/packages/mcp-server/src/index.ts index 4850a0e2..0f6dd426 100644 --- a/packages/mcp-server/src/index.ts +++ b/packages/mcp-server/src/index.ts @@ -1,20 +1,15 @@ #!/usr/bin/env node import { selectTools } from './server'; -import { Endpoint, endpoints } from './tools'; import { McpOptions, parseCLIOptions } from './options'; import { launchStdioServer } from './stdio'; import { launchStreamableHTTPServer } from './http'; +import type { McpTool } from './types'; async function main() { const options = parseOptionsOrError(); - if (options.list) { - listAllTools(); - return; - } - - const selectedTools = await selectToolsOrError(endpoints, options); + const selectedTools = await selectToolsOrError(options); console.error( `MCP Server starting with ${selectedTools.length} tools:`, @@ -23,7 +18,7 @@ async function main() { switch (options.transport) { case 'stdio': - await launchStdioServer(options); + await launchStdioServer(); break; case 'http': await launchStreamableHTTPServer(options, options.port ?? options.socket); @@ -47,9 +42,9 @@ function parseOptionsOrError() { } } -async function selectToolsOrError(endpoints: Endpoint[], options: McpOptions): Promise { +async function selectToolsOrError(options: McpOptions): Promise { try { - const includedTools = await selectTools(endpoints, options); + const includedTools = selectTools(options); if (includedTools.length === 0) { console.error('No tools match the provided filters.'); process.exit(1); @@ -64,45 +59,3 @@ async function selectToolsOrError(endpoints: Endpoint[], options: McpOptions): P process.exit(1); } } - -function listAllTools() { - if (endpoints.length === 0) { - console.log('No tools available.'); - return; - } - console.log('Available tools:\n'); - - // Group endpoints by resource - const resourceGroups = new Map(); - - for (const endpoint of endpoints) { - const resource = endpoint.metadata.resource; - if (!resourceGroups.has(resource)) { - resourceGroups.set(resource, []); - } - resourceGroups.get(resource)!.push(endpoint); - } - - // Sort resources alphabetically - const sortedResources = Array.from(resourceGroups.keys()).sort(); - - // Display hierarchically by resource - for (const resource of sortedResources) { - console.log(`Resource: ${resource}`); - - const resourceEndpoints = resourceGroups.get(resource)!; - // Sort endpoints by tool name - resourceEndpoints.sort((a, b) => a.tool.name.localeCompare(b.tool.name)); - - for (const endpoint of resourceEndpoints) { - const { - tool, - metadata: { operation, tags }, - } = endpoint; - - console.log(` - ${tool.name} (${operation}) ${tags.length > 0 ? `tags: ${tags.join(', ')}` : ''}`); - console.log(` Description: ${tool.description}`); - } - console.log(''); - } -} diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index b6ff5976..c66ad8ce 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -2,140 +2,31 @@ import qs from 'qs'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; import z from 'zod'; -import { endpoints, Filter } from './tools'; -import { ClientCapabilities, knownClients, ClientType } from './compat'; export type CLIOptions = McpOptions & { - list: boolean; transport: 'stdio' | 'http'; port: number | undefined; socket: string | undefined; }; export type McpOptions = { - client?: ClientType | undefined; - includeDynamicTools?: boolean | undefined; - includeAllTools?: boolean | undefined; - includeCodeTools?: boolean | undefined; includeDocsTools?: boolean | undefined; - filters?: Filter[] | undefined; - capabilities?: Partial | undefined; }; -const CAPABILITY_CHOICES = [ - 'top-level-unions', - 'valid-json', - 'refs', - 'unions', - 'formats', - 'tool-name-length', -] as const; - -type Capability = (typeof CAPABILITY_CHOICES)[number]; - -function parseCapabilityValue(cap: string): { name: Capability; value?: number } { - if (cap.startsWith('tool-name-length=')) { - const parts = cap.split('='); - if (parts.length === 2) { - const length = parseInt(parts[1]!, 10); - if (!isNaN(length)) { - return { name: 'tool-name-length', value: length }; - } - throw new Error(`Invalid tool-name-length value: ${parts[1]}. Expected a number.`); - } - throw new Error(`Invalid format for tool-name-length. Expected tool-name-length=N.`); - } - if (!CAPABILITY_CHOICES.includes(cap as Capability)) { - throw new Error(`Unknown capability: ${cap}. Valid capabilities are: ${CAPABILITY_CHOICES.join(', ')}`); - } - return { name: cap as Capability }; -} - export function parseCLIOptions(): CLIOptions { const opts = yargs(hideBin(process.argv)) .option('tools', { type: 'string', array: true, - choices: ['dynamic', 'all', 'code', 'docs'], + choices: ['code', 'docs'], description: 'Use dynamic tools or all tools', }) .option('no-tools', { type: 'string', array: true, - choices: ['dynamic', 'all', 'code', 'docs'], + choices: ['code', 'docs'], description: 'Do not use any dynamic or all tools', }) - .option('tool', { - type: 'string', - array: true, - description: 'Include tools matching the specified names', - }) - .option('resource', { - type: 'string', - array: true, - description: 'Include tools matching the specified resources', - }) - .option('operation', { - type: 'string', - array: true, - choices: ['read', 'write'], - description: 'Include tools matching the specified operations', - }) - .option('tag', { - type: 'string', - array: true, - description: 'Include tools with the specified tags', - }) - .option('no-tool', { - type: 'string', - array: true, - description: 'Exclude tools matching the specified names', - }) - .option('no-resource', { - type: 'string', - array: true, - description: 'Exclude tools matching the specified resources', - }) - .option('no-operation', { - type: 'string', - array: true, - description: 'Exclude tools matching the specified operations', - }) - .option('no-tag', { - type: 'string', - array: true, - description: 'Exclude tools with the specified tags', - }) - .option('list', { - type: 'boolean', - description: 'List all tools and exit', - }) - .option('client', { - type: 'string', - choices: Object.keys(knownClients), - description: 'Specify the MCP client being used', - }) - .option('capability', { - type: 'string', - array: true, - description: 'Specify client capabilities', - coerce: (values: string[]) => { - return values.flatMap((v) => v.split(',')); - }, - }) - .option('no-capability', { - type: 'string', - array: true, - description: 'Unset client capabilities', - choices: CAPABILITY_CHOICES, - coerce: (values: string[]) => { - return values.flatMap((v) => v.split(',')); - }, - }) - .option('describe-capabilities', { - type: 'boolean', - description: 'Print detailed explanation of client capabilities and exit', - }) .option('transport', { type: 'string', choices: ['stdio', 'http'], @@ -152,122 +43,19 @@ export function parseCLIOptions(): CLIOptions { }) .help(); - for (const [command, desc] of examples()) { - opts.example(command, desc); - } - const argv = opts.parseSync(); - // Handle describe-capabilities flag - if (argv.describeCapabilities) { - console.log(getCapabilitiesExplanation()); - process.exit(0); - } - - const filters: Filter[] = []; - - // Helper function to support comma-separated values - const splitValues = (values: string[] | undefined): string[] => { - if (!values) return []; - return values.flatMap((v) => v.split(',')); - }; - - for (const tag of splitValues(argv.tag)) { - filters.push({ type: 'tag', op: 'include', value: tag }); - } - - for (const tag of splitValues(argv.noTag)) { - filters.push({ type: 'tag', op: 'exclude', value: tag }); - } - - for (const resource of splitValues(argv.resource)) { - filters.push({ type: 'resource', op: 'include', value: resource }); - } - - for (const resource of splitValues(argv.noResource)) { - filters.push({ type: 'resource', op: 'exclude', value: resource }); - } - - for (const tool of splitValues(argv.tool)) { - filters.push({ type: 'tool', op: 'include', value: tool }); - } - - for (const tool of splitValues(argv.noTool)) { - filters.push({ type: 'tool', op: 'exclude', value: tool }); - } - - for (const operation of splitValues(argv.operation)) { - filters.push({ type: 'operation', op: 'include', value: operation }); - } - - for (const operation of splitValues(argv.noOperation)) { - filters.push({ type: 'operation', op: 'exclude', value: operation }); - } - - // Parse client capabilities - const clientCapabilities: Partial = {}; - - // Apply individual capability overrides - if (Array.isArray(argv.capability)) { - for (const cap of argv.capability) { - const parsedCap = parseCapabilityValue(cap); - if (parsedCap.name === 'top-level-unions') { - clientCapabilities.topLevelUnions = true; - } else if (parsedCap.name === 'valid-json') { - clientCapabilities.validJson = true; - } else if (parsedCap.name === 'refs') { - clientCapabilities.refs = true; - } else if (parsedCap.name === 'unions') { - clientCapabilities.unions = true; - } else if (parsedCap.name === 'formats') { - clientCapabilities.formats = true; - } else if (parsedCap.name === 'tool-name-length') { - clientCapabilities.toolNameLength = parsedCap.value; - } - } - } - - // Handle no-capability options to unset capabilities - if (Array.isArray(argv.noCapability)) { - for (const cap of argv.noCapability) { - if (cap === 'top-level-unions') { - clientCapabilities.topLevelUnions = false; - } else if (cap === 'valid-json') { - clientCapabilities.validJson = false; - } else if (cap === 'refs') { - clientCapabilities.refs = false; - } else if (cap === 'unions') { - clientCapabilities.unions = false; - } else if (cap === 'formats') { - clientCapabilities.formats = false; - } else if (cap === 'tool-name-length') { - clientCapabilities.toolNameLength = undefined; - } - } - } - - const shouldIncludeToolType = (toolType: 'dynamic' | 'all' | 'code' | 'docs') => + const shouldIncludeToolType = (toolType: 'code' | 'docs') => argv.noTools?.includes(toolType) ? false : argv.tools?.includes(toolType) ? true : undefined; - const includeDynamicTools = shouldIncludeToolType('dynamic'); - const includeAllTools = shouldIncludeToolType('all'); - const includeCodeTools = shouldIncludeToolType('code'); const includeDocsTools = shouldIncludeToolType('docs'); const transport = argv.transport as 'stdio' | 'http'; - const client = argv.client as ClientType; return { - client: client && client !== 'infer' && knownClients[client] ? client : undefined, - includeDynamicTools, - includeAllTools, - includeCodeTools, - includeDocsTools, - filters, - capabilities: clientCapabilities, - list: argv.list || false, + ...(includeDocsTools !== undefined && { includeDocsTools }), transport, port: argv.port, socket: argv.socket, @@ -284,190 +72,21 @@ const coerceArray = (zodType: T) => ); const QueryOptions = z.object({ - tools: coerceArray(z.enum(['dynamic', 'all', 'code', 'docs'])).describe('Specify which MCP tools to use'), - no_tools: coerceArray(z.enum(['dynamic', 'all', 'code', 'docs'])).describe( - 'Specify which MCP tools to not use.', - ), + tools: coerceArray(z.enum(['code', 'docs'])).describe('Specify which MCP tools to use'), + no_tools: coerceArray(z.enum(['code', 'docs'])).describe('Specify which MCP tools to not use.'), tool: coerceArray(z.string()).describe('Include tools matching the specified names'), - resource: coerceArray(z.string()).describe('Include tools matching the specified resources'), - operation: coerceArray(z.enum(['read', 'write'])).describe( - 'Include tools matching the specified operations', - ), - tag: coerceArray(z.string()).describe('Include tools with the specified tags'), - no_tool: coerceArray(z.string()).describe('Exclude tools matching the specified names'), - no_resource: coerceArray(z.string()).describe('Exclude tools matching the specified resources'), - no_operation: coerceArray(z.enum(['read', 'write'])).describe( - 'Exclude tools matching the specified operations', - ), - no_tag: coerceArray(z.string()).describe('Exclude tools with the specified tags'), - client: ClientType.optional().describe('Specify the MCP client being used'), - capability: coerceArray(z.string()).describe('Specify client capabilities'), - no_capability: coerceArray(z.enum(CAPABILITY_CHOICES)).describe('Unset client capabilities'), }); export function parseQueryOptions(defaultOptions: McpOptions, query: unknown): McpOptions { const queryObject = typeof query === 'string' ? qs.parse(query) : query; const queryOptions = QueryOptions.parse(queryObject); - const filters: Filter[] = [...(defaultOptions.filters ?? [])]; - - for (const resource of queryOptions.resource || []) { - filters.push({ type: 'resource', op: 'include', value: resource }); - } - for (const operation of queryOptions.operation || []) { - filters.push({ type: 'operation', op: 'include', value: operation }); - } - for (const tag of queryOptions.tag || []) { - filters.push({ type: 'tag', op: 'include', value: tag }); - } - for (const tool of queryOptions.tool || []) { - filters.push({ type: 'tool', op: 'include', value: tool }); - } - for (const resource of queryOptions.no_resource || []) { - filters.push({ type: 'resource', op: 'exclude', value: resource }); - } - for (const operation of queryOptions.no_operation || []) { - filters.push({ type: 'operation', op: 'exclude', value: operation }); - } - for (const tag of queryOptions.no_tag || []) { - filters.push({ type: 'tag', op: 'exclude', value: tag }); - } - for (const tool of queryOptions.no_tool || []) { - filters.push({ type: 'tool', op: 'exclude', value: tool }); - } - - // Parse client capabilities - const clientCapabilities: Partial = { ...defaultOptions.capabilities }; - - for (const cap of queryOptions.capability || []) { - const parsed = parseCapabilityValue(cap); - if (parsed.name === 'top-level-unions') { - clientCapabilities.topLevelUnions = true; - } else if (parsed.name === 'valid-json') { - clientCapabilities.validJson = true; - } else if (parsed.name === 'refs') { - clientCapabilities.refs = true; - } else if (parsed.name === 'unions') { - clientCapabilities.unions = true; - } else if (parsed.name === 'formats') { - clientCapabilities.formats = true; - } else if (parsed.name === 'tool-name-length') { - clientCapabilities.toolNameLength = parsed.value; - } - } - - for (const cap of queryOptions.no_capability || []) { - if (cap === 'top-level-unions') { - clientCapabilities.topLevelUnions = false; - } else if (cap === 'valid-json') { - clientCapabilities.validJson = false; - } else if (cap === 'refs') { - clientCapabilities.refs = false; - } else if (cap === 'unions') { - clientCapabilities.unions = false; - } else if (cap === 'formats') { - clientCapabilities.formats = false; - } else if (cap === 'tool-name-length') { - clientCapabilities.toolNameLength = undefined; - } - } - - let dynamicTools: boolean | undefined = - queryOptions.no_tools && queryOptions.no_tools?.includes('dynamic') ? false - : queryOptions.tools?.includes('dynamic') ? true - : defaultOptions.includeDynamicTools; - - let allTools: boolean | undefined = - queryOptions.no_tools && queryOptions.no_tools?.includes('all') ? false - : queryOptions.tools?.includes('all') ? true - : defaultOptions.includeAllTools; - let docsTools: boolean | undefined = queryOptions.no_tools && queryOptions.no_tools?.includes('docs') ? false : queryOptions.tools?.includes('docs') ? true : defaultOptions.includeDocsTools; - let codeTools: boolean | undefined = - queryOptions.no_tools && queryOptions.no_tools?.includes('code') ? false - : queryOptions.tools?.includes('code') && defaultOptions.includeCodeTools ? true - : defaultOptions.includeCodeTools; - return { - client: queryOptions.client ?? defaultOptions.client, - includeDynamicTools: dynamicTools, - includeAllTools: allTools, - includeCodeTools: codeTools, - includeDocsTools: docsTools, - filters, - capabilities: clientCapabilities, + ...(docsTools !== undefined && { includeDocsTools: docsTools }), }; } - -function getCapabilitiesExplanation(): string { - return ` -Client Capabilities Explanation: - -Different Language Models (LLMs) and the MCP clients that use them have varying limitations in how they handle tool schemas. Capability flags allow you to inform the MCP server about these limitations. - -When a capability flag is set to false, the MCP server will automatically adjust the tool schemas to work around that limitation, ensuring broader compatibility. - -Available Capabilities: - -# top-level-unions -Some clients/LLMs do not support JSON schemas with a union type (anyOf) at the root level. If a client lacks this capability, the MCP server splits tools with top-level unions into multiple separate tools, one for each variant in the union. - -# refs -Some clients/LLMs do not support $ref pointers for schema reuse. If a client lacks this capability, the MCP server automatically inlines all references ($defs) directly into the schema. Properties that would cause circular references are removed during this process. - -# valid-json -Some clients/LLMs may incorrectly send arguments as a JSON-encoded string instead of a proper JSON object. If a client *has* this capability, the MCP server will attempt to parse string values as JSON if the initial validation against the schema fails. - -# unions -Some clients/LLMs do not support union types (anyOf) in JSON schemas. If a client lacks this capability, the MCP server removes all anyOf fields and uses only the first variant as the schema. - -# formats -Some clients/LLMs do not support the 'format' keyword in JSON Schema specifications. If a client lacks this capability, the MCP server removes all format fields and appends the format information to the field's description in parentheses. - -# tool-name-length=N -Some clients/LLMs impose a maximum length on tool names. If this capability is set, the MCP server will automatically truncate tool names exceeding the specified length (N), ensuring uniqueness by appending numbers if necessary. - -Client Presets (--client): -Presets like '--client=openai-agents' or '--client=cursor' automatically configure these capabilities based on current known limitations of those clients, simplifying setup. - -Current presets: -${JSON.stringify(knownClients, null, 2)} - `; -} - -function examples(): [string, string][] { - const firstEndpoint = endpoints[0]!; - const secondEndpoint = - endpoints.find((e) => e.metadata.resource !== firstEndpoint.metadata.resource) || endpoints[1]; - const tag = endpoints.find((e) => e.metadata.tags.length > 0)?.metadata.tags[0]; - const otherEndpoint = secondEndpoint || firstEndpoint; - - return [ - [ - `--tool="${firstEndpoint.tool.name}" ${secondEndpoint ? `--tool="${secondEndpoint.tool.name}"` : ''}`, - 'Include tools by name', - ], - [ - `--resource="${firstEndpoint.metadata.resource}" --operation="read"`, - 'Filter by resource and operation', - ], - [ - `--resource="${otherEndpoint.metadata.resource}*" --no-tool="${otherEndpoint.tool.name}"`, - 'Use resource wildcards and exclusions', - ], - [`--client="cursor"`, 'Adjust schemas to be more compatible with Cursor'], - [ - `--capability="top-level-unions" --capability="tool-name-length=40"`, - 'Specify individual client capabilities', - ], - [ - `--client="cursor" --no-capability="tool-name-length"`, - 'Use cursor client preset but remove tool name length limit', - ], - ...(tag ? [[`--tag="${tag}"`, 'Filter based on tags'] as [string, string]] : []), - ]; -} diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index b2452cf4..da656fa4 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -2,33 +2,20 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; -import { Endpoint, endpoints, HandlerFunction, query } from './tools'; import { CallToolRequestSchema, ListToolsRequestSchema, SetLevelRequestSchema, - Implementation, - Tool, } from '@modelcontextprotocol/sdk/types.js'; import { ClientOptions } from '@corgi-tech/beagle'; import Beagle from '@corgi-tech/beagle'; -import { - applyCompatibilityTransformations, - ClientCapabilities, - defaultClientCapabilities, - knownClients, - parseEmbeddedJSON, -} from './compat'; -import { dynamicTools } from './dynamic-tools'; import { codeTool } from './code-tool'; import docsSearchTool from './docs-search-tool'; import { McpOptions } from './options'; +import { HandlerFunction, McpTool } from './types'; export { McpOptions } from './options'; -export { ClientType } from './compat'; -export { Filter } from './tools'; export { ClientOptions } from '@corgi-tech/beagle'; -export { endpoints } from './tools'; export const newMcpServer = () => new McpServer( @@ -52,25 +39,6 @@ export function initMcpServer(params: { mcpOptions?: McpOptions; }) { const server = params.server instanceof McpServer ? params.server.server : params.server; - const mcpOptions = params.mcpOptions ?? {}; - - let providedEndpoints: Endpoint[] | null = null; - let endpointMap: Record | null = null; - - const initTools = async (implementation?: Implementation) => { - if (implementation && (!mcpOptions.client || mcpOptions.client === 'infer')) { - mcpOptions.client = - implementation.name.toLowerCase().includes('claude') ? 'claude' - : implementation.name.toLowerCase().includes('cursor') ? 'cursor' - : undefined; - mcpOptions.capabilities = { - ...(mcpOptions.client && knownClients[mcpOptions.client]), - ...mcpOptions.capabilities, - }; - } - providedEndpoints ??= await selectTools(endpoints, mcpOptions); - endpointMap ??= Object.fromEntries(providedEndpoints.map((endpoint) => [endpoint.tool.name, endpoint])); - }; const logAtLevel = (level: 'debug' | 'info' | 'warning' | 'error') => @@ -97,26 +65,23 @@ export function initMcpServer(params: { }, }); + const providedTools = selectTools(params.mcpOptions); + const toolMap = Object.fromEntries(providedTools.map((mcpTool) => [mcpTool.tool.name, mcpTool])); + server.setRequestHandler(ListToolsRequestSchema, async () => { - if (providedEndpoints === null) { - await initTools(server.getClientVersion()); - } return { - tools: providedEndpoints!.map((endpoint) => endpoint.tool), + tools: providedTools.map((mcpTool) => mcpTool.tool), }; }); server.setRequestHandler(CallToolRequestSchema, async (request) => { - if (endpointMap === null) { - await initTools(server.getClientVersion()); - } const { name, arguments: args } = request.params; - const endpoint = endpointMap![name]; - if (!endpoint) { + const mcpTool = toolMap[name]; + if (!mcpTool) { throw new Error(`Unknown tool: ${name}`); } - return executeHandler(endpoint.tool, endpoint.handler, client, args, mcpOptions.capabilities); + return executeHandler(mcpTool.handler, client, args); }); server.setRequestHandler(SetLevelRequestSchema, async (request) => { @@ -146,47 +111,22 @@ export function initMcpServer(params: { /** * Selects the tools to include in the MCP Server based on the provided options. */ -export async function selectTools(endpoints: Endpoint[], options?: McpOptions): Promise { - const filteredEndpoints = query(options?.filters ?? [], endpoints); - - let includedTools = filteredEndpoints.slice(); - - if (includedTools.length > 0) { - if (options?.includeDynamicTools) { - includedTools = dynamicTools(includedTools); - } - } else { - if (options?.includeAllTools) { - includedTools = endpoints.slice(); - } else if (options?.includeDynamicTools) { - includedTools = dynamicTools(endpoints); - } else if (options?.includeCodeTools) { - includedTools = [await codeTool()]; - } else { - includedTools = endpoints.slice(); - } - } +export function selectTools(options?: McpOptions): McpTool[] { + const includedTools = [codeTool()]; if (options?.includeDocsTools ?? true) { includedTools.push(docsSearchTool); } - const capabilities = { ...defaultClientCapabilities, ...options?.capabilities }; - return applyCompatibilityTransformations(includedTools, capabilities); + return includedTools; } /** * Runs the provided handler with the given client and arguments. */ export async function executeHandler( - tool: Tool, handler: HandlerFunction, client: Beagle, args: Record | undefined, - compatibilityOptions?: Partial, ) { - const options = { ...defaultClientCapabilities, ...compatibilityOptions }; - if (!options.validJson && args) { - args = parseEmbeddedJSON(args, tool.inputSchema); - } return await handler(client, args || {}); } diff --git a/packages/mcp-server/src/stdio.ts b/packages/mcp-server/src/stdio.ts index d902a5bb..f07696f3 100644 --- a/packages/mcp-server/src/stdio.ts +++ b/packages/mcp-server/src/stdio.ts @@ -1,11 +1,10 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { initMcpServer, newMcpServer } from './server'; -import { McpOptions } from './options'; -export const launchStdioServer = async (options: McpOptions) => { +export const launchStdioServer = async () => { const server = newMcpServer(); - initMcpServer({ server, mcpOptions: options }); + initMcpServer({ server }); const transport = new StdioServerTransport(); await server.connect(transport); diff --git a/packages/mcp-server/src/tools.ts b/packages/mcp-server/src/tools.ts deleted file mode 100644 index 7e516de7..00000000 --- a/packages/mcp-server/src/tools.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './tools/index'; diff --git a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts b/packages/mcp-server/src/tools/enrollments/create-enrollments.ts deleted file mode 100644 index 9ab1960e..00000000 --- a/packages/mcp-server/src/tools/enrollments/create-enrollments.ts +++ /dev/null @@ -1,80 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'enrollments', - operation: 'write', - tags: [], - httpMethod: 'post', - httpPath: '/api/enrollments', - operationId: 'createEnrollment', -}; - -export const tool: Tool = { - name: 'create_enrollments', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ncreate a new enrollment for a tenant.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/enrollment',\n $defs: {\n enrollment: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n effectiveDate: {\n type: 'string',\n description: 'the date the enrollment will begin, note enrollments cannot begin in the past'\n },\n plan: {\n type: 'string',\n description: 'the plan name/code'\n },\n propertyManagerId: {\n type: 'number'\n },\n status: {\n type: 'string',\n enum: [ 'Premium Paying',\n 'Issued, Not Paid',\n 'Expired',\n 'Lapsed',\n 'Suspended',\n 'Cancelled',\n 'Not taken',\n 'Declined'\n ]\n },\n tenantId: {\n type: 'number'\n },\n note: {\n type: 'string',\n description: 'an optional note field, this can be used for easily appending metadata to enrollments'\n }\n },\n required: [ 'id',\n 'effectiveDate',\n 'plan',\n 'propertyManagerId',\n 'status',\n 'tenantId'\n ]\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - effectiveDate: { - type: 'string', - description: 'the date the enrollment will begin, note enrollments cannot begin in the past', - }, - plan: { - type: 'string', - description: 'the plan name/code', - }, - propertyManagerId: { - type: 'number', - }, - status: { - type: 'string', - enum: [ - 'Premium Paying', - 'Issued, Not Paid', - 'Expired', - 'Lapsed', - 'Suspended', - 'Cancelled', - 'Not taken', - 'Declined', - ], - }, - tenantId: { - type: 'number', - }, - note: { - type: 'string', - description: 'an optional note field, this can be used for easily appending metadata to enrollments', - }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, - }, - required: ['effectiveDate', 'plan', 'propertyManagerId', 'status', 'tenantId'], - }, - annotations: {}, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - try { - return asTextContentResult(await maybeFilter(jq_filter, await client.enrollments.create(body))); - } catch (error) { - if (error instanceof Beagle.APIError || isJqError(error)) { - return asErrorResult(error.message); - } - throw error; - } -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts b/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts deleted file mode 100644 index 1f58c0ca..00000000 --- a/packages/mcp-server/src/tools/enrollments/lapse-enrollments.ts +++ /dev/null @@ -1,41 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'enrollments', - operation: 'write', - tags: [], - httpMethod: 'delete', - httpPath: '/api/enrollments/{id}', - operationId: 'lapseEnrollment', -}; - -export const tool: Tool = { - name: 'lapse_enrollments', - description: - 'lapses a specific enrollment for a tenant, note that if a tenant has multiple enrollments (e.g., SDR and TLL), each must be lapsed individually', - inputSchema: { - type: 'object', - properties: { - id: { - type: 'number', - }, - }, - required: ['id'], - }, - annotations: { - idempotentHint: true, - }, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { id, ...body } = args as any; - const response = await client.enrollments.lapse(id).asResponse(); - return asTextContentResult(await response.text()); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts b/packages/mcp-server/src/tools/enrollments/list-enrollments.ts deleted file mode 100644 index 838be244..00000000 --- a/packages/mcp-server/src/tools/enrollments/list-enrollments.ts +++ /dev/null @@ -1,63 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'enrollments', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/api/enrollments', - operationId: 'listEnrollments', -}; - -export const tool: Tool = { - name: 'list_enrollments', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlist all enrollments, this endpoint is paginated and allows for queries by individual property manager.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n enrollments: {\n type: 'array',\n items: {\n $ref: '#/$defs/enrollment'\n }\n },\n pagination: {\n $ref: '#/$defs/pagination'\n }\n },\n required: [ 'enrollments',\n 'pagination'\n ],\n $defs: {\n enrollment: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n effectiveDate: {\n type: 'string',\n description: 'the date the enrollment will begin, note enrollments cannot begin in the past'\n },\n plan: {\n type: 'string',\n description: 'the plan name/code'\n },\n propertyManagerId: {\n type: 'number'\n },\n status: {\n type: 'string',\n enum: [ 'Premium Paying',\n 'Issued, Not Paid',\n 'Expired',\n 'Lapsed',\n 'Suspended',\n 'Cancelled',\n 'Not taken',\n 'Declined'\n ]\n },\n tenantId: {\n type: 'number'\n },\n note: {\n type: 'string',\n description: 'an optional note field, this can be used for easily appending metadata to enrollments'\n }\n },\n required: [ 'id',\n 'effectiveDate',\n 'plan',\n 'propertyManagerId',\n 'status',\n 'tenantId'\n ]\n },\n pagination: {\n type: 'object',\n properties: {\n page: {\n type: 'number',\n description: 'Current page number.'\n },\n pages: {\n type: 'number',\n description: 'Total number of pages.'\n },\n records: {\n type: 'number',\n description: 'Total number of records.'\n },\n size: {\n type: 'number',\n description: 'Number of items per page.'\n }\n },\n required: [ 'page',\n 'pages',\n 'records',\n 'size'\n ]\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - page: { - type: 'number', - description: 'Page number to fetch.', - }, - propertyManagerId: { - type: 'number', - }, - size: { - type: 'number', - description: 'Number of items per page.', - }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, - }, - required: [], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - const response = await client.enrollments.list(body).asResponse(); - try { - return asTextContentResult(await maybeFilter(jq_filter, await response.json())); - } catch (error) { - if (error instanceof Beagle.APIError || isJqError(error)) { - return asErrorResult(error.message); - } - throw error; - } -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/enrollments/retrieve-certificate-enrollments.ts b/packages/mcp-server/src/tools/enrollments/retrieve-certificate-enrollments.ts deleted file mode 100644 index 1cef506a..00000000 --- a/packages/mcp-server/src/tools/enrollments/retrieve-certificate-enrollments.ts +++ /dev/null @@ -1,39 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Metadata, asBinaryContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'enrollments', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/api/enrollments/{id}/certificate', - operationId: 'getEnrollmentCertificate', -}; - -export const tool: Tool = { - name: 'retrieve_certificate_enrollments', - description: 'get the certificate of enrollment for a given enrollment', - inputSchema: { - type: 'object', - properties: { - id: { - type: 'number', - }, - }, - required: ['id'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { id, ...body } = args as any; - return asBinaryContentResult(await client.enrollments.retrieveCertificate(id).asResponse()); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts b/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts deleted file mode 100644 index 574e8264..00000000 --- a/packages/mcp-server/src/tools/enrollments/retrieve-enrollments.ts +++ /dev/null @@ -1,54 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'enrollments', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/api/enrollments/{id}', - operationId: 'getEnrollment', -}; - -export const tool: Tool = { - name: 'retrieve_enrollments', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nget a specific enrollment by its id.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/enrollment',\n $defs: {\n enrollment: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n effectiveDate: {\n type: 'string',\n description: 'the date the enrollment will begin, note enrollments cannot begin in the past'\n },\n plan: {\n type: 'string',\n description: 'the plan name/code'\n },\n propertyManagerId: {\n type: 'number'\n },\n status: {\n type: 'string',\n enum: [ 'Premium Paying',\n 'Issued, Not Paid',\n 'Expired',\n 'Lapsed',\n 'Suspended',\n 'Cancelled',\n 'Not taken',\n 'Declined'\n ]\n },\n tenantId: {\n type: 'number'\n },\n note: {\n type: 'string',\n description: 'an optional note field, this can be used for easily appending metadata to enrollments'\n }\n },\n required: [ 'id',\n 'effectiveDate',\n 'plan',\n 'propertyManagerId',\n 'status',\n 'tenantId'\n ]\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - id: { - type: 'number', - }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, - }, - required: ['id'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { id, jq_filter, ...body } = args as any; - try { - return asTextContentResult(await maybeFilter(jq_filter, await client.enrollments.retrieve(id))); - } catch (error) { - if (error instanceof Beagle.APIError || isJqError(error)) { - return asErrorResult(error.message); - } - throw error; - } -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/index.ts b/packages/mcp-server/src/tools/index.ts deleted file mode 100644 index d9640613..00000000 --- a/packages/mcp-server/src/tools/index.ts +++ /dev/null @@ -1,115 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Metadata, Endpoint, HandlerFunction } from './types'; - -export { Metadata, Endpoint, HandlerFunction }; - -import retrieve_plans from './plans/retrieve-plans'; -import list_plans from './plans/list-plans'; -import create_property_managers from './property-managers/create-property-managers'; -import retrieve_property_managers from './property-managers/retrieve-property-managers'; -import update_property_managers from './property-managers/update-property-managers'; -import list_property_managers from './property-managers/list-property-managers'; -import delete_property_managers from './property-managers/delete-property-managers'; -import create_tenants from './tenants/create-tenants'; -import retrieve_tenants from './tenants/retrieve-tenants'; -import update_tenants from './tenants/update-tenants'; -import list_tenants from './tenants/list-tenants'; -import delete_tenants from './tenants/delete-tenants'; -import create_enrollments from './enrollments/create-enrollments'; -import retrieve_enrollments from './enrollments/retrieve-enrollments'; -import list_enrollments from './enrollments/list-enrollments'; -import lapse_enrollments from './enrollments/lapse-enrollments'; -import retrieve_certificate_enrollments from './enrollments/retrieve-certificate-enrollments'; -import verify_insurance_verification from './insurance-verification/verify-insurance-verification'; -import create_webhook_endpoints from './webhook/endpoints/create-webhook-endpoints'; -import retrieve_webhook_endpoints from './webhook/endpoints/retrieve-webhook-endpoints'; -import update_webhook_endpoints from './webhook/endpoints/update-webhook-endpoints'; -import list_webhook_endpoints from './webhook/endpoints/list-webhook-endpoints'; -import delete_webhook_endpoints from './webhook/endpoints/delete-webhook-endpoints'; - -export const endpoints: Endpoint[] = []; - -function addEndpoint(endpoint: Endpoint) { - endpoints.push(endpoint); -} - -addEndpoint(retrieve_plans); -addEndpoint(list_plans); -addEndpoint(create_property_managers); -addEndpoint(retrieve_property_managers); -addEndpoint(update_property_managers); -addEndpoint(list_property_managers); -addEndpoint(delete_property_managers); -addEndpoint(create_tenants); -addEndpoint(retrieve_tenants); -addEndpoint(update_tenants); -addEndpoint(list_tenants); -addEndpoint(delete_tenants); -addEndpoint(create_enrollments); -addEndpoint(retrieve_enrollments); -addEndpoint(list_enrollments); -addEndpoint(lapse_enrollments); -addEndpoint(retrieve_certificate_enrollments); -addEndpoint(verify_insurance_verification); -addEndpoint(create_webhook_endpoints); -addEndpoint(retrieve_webhook_endpoints); -addEndpoint(update_webhook_endpoints); -addEndpoint(list_webhook_endpoints); -addEndpoint(delete_webhook_endpoints); - -export type Filter = { - type: 'resource' | 'operation' | 'tag' | 'tool'; - op: 'include' | 'exclude'; - value: string; -}; - -export function query(filters: Filter[], endpoints: Endpoint[]): Endpoint[] { - const allExcludes = filters.length > 0 && filters.every((filter) => filter.op === 'exclude'); - const unmatchedFilters = new Set(filters); - - const filtered = endpoints.filter((endpoint: Endpoint) => { - let included = false || allExcludes; - - for (const filter of filters) { - if (match(filter, endpoint)) { - unmatchedFilters.delete(filter); - included = filter.op === 'include'; - } - } - - return included; - }); - - // Check if any filters didn't match - const unmatched = Array.from(unmatchedFilters).filter((f) => f.type === 'tool' || f.type === 'resource'); - if (unmatched.length > 0) { - throw new Error( - `The following filters did not match any endpoints: ${unmatched - .map((f) => `${f.type}=${f.value}`) - .join(', ')}`, - ); - } - - return filtered; -} - -function match({ type, value }: Filter, endpoint: Endpoint): boolean { - switch (type) { - case 'resource': { - const regexStr = '^' + normalizeResource(value).replace(/\*/g, '.*') + '$'; - const regex = new RegExp(regexStr); - return regex.test(normalizeResource(endpoint.metadata.resource)); - } - case 'operation': - return endpoint.metadata.operation === value; - case 'tag': - return endpoint.metadata.tags.includes(value); - case 'tool': - return endpoint.tool.name === value; - } -} - -function normalizeResource(resource: string): string { - return resource.toLowerCase().replace(/[^a-z.*\-_]*/g, ''); -} diff --git a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts b/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts deleted file mode 100644 index 36b30a6c..00000000 --- a/packages/mcp-server/src/tools/insurance-verification/verify-insurance-verification.ts +++ /dev/null @@ -1,62 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'insurance_verification', - operation: 'write', - tags: [], - httpMethod: 'post', - httpPath: '/api/insurance-verification', - operationId: 'verifyInsurance', -}; - -export const tool: Tool = { - name: 'verify_insurance_verification', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ntrigger a job to parse a tenants insurance document(s)\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/insurance_verification_verify_response',\n $defs: {\n insurance_verification_verify_response: {\n type: 'object',\n properties: {\n message: {\n type: 'string',\n enum: [ 'insurance verification job scheduled'\n ]\n }\n },\n required: [ 'message'\n ]\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - propertyManagerId: { - type: 'number', - }, - tenantId: { - type: 'number', - }, - urls: { - type: 'array', - description: 'an array of presigned pdf urls for the tenants policy document(s)', - items: { - type: 'string', - }, - }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, - }, - required: ['propertyManagerId', 'tenantId', 'urls'], - }, - annotations: {}, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - try { - return asTextContentResult(await maybeFilter(jq_filter, await client.insuranceVerification.verify(body))); - } catch (error) { - if (error instanceof Beagle.APIError || isJqError(error)) { - return asErrorResult(error.message); - } - throw error; - } -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/plans/list-plans.ts b/packages/mcp-server/src/tools/plans/list-plans.ts deleted file mode 100644 index 3c359a7b..00000000 --- a/packages/mcp-server/src/tools/plans/list-plans.ts +++ /dev/null @@ -1,51 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'plans', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/api/plans', - operationId: 'listPlans', -}; - -export const tool: Tool = { - name: 'list_plans', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlist all available plans, note this endpoint is currently unpaginated unlike all other list endpoints.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/plan_list_response',\n $defs: {\n plan_list_response: {\n type: 'array',\n items: {\n $ref: '#/$defs/plan'\n }\n },\n plan: {\n type: 'object',\n properties: {\n description: {\n type: 'string'\n },\n name: {\n type: 'string',\n description: 'the plans name/code, this is used when creating enrollments.'\n },\n rate: {\n type: 'number',\n description: 'the price of the plan'\n },\n contents: {\n type: 'number',\n description: 'value of contents replacement, note this is only on some TLL plans.'\n },\n liability: {\n type: 'number',\n description: 'value of liability waived, note this is only on TLL plans.'\n },\n value: {\n type: 'number',\n description: 'general value field, this is currently used for SDR and SDD plans for the replacement or discount value.'\n }\n },\n required: [ 'description',\n 'name',\n 'rate'\n ]\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, - }, - required: [], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { jq_filter } = args as any; - try { - return asTextContentResult(await maybeFilter(jq_filter, await client.plans.list())); - } catch (error) { - if (error instanceof Beagle.APIError || isJqError(error)) { - return asErrorResult(error.message); - } - throw error; - } -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/plans/retrieve-plans.ts b/packages/mcp-server/src/tools/plans/retrieve-plans.ts deleted file mode 100644 index 565640f4..00000000 --- a/packages/mcp-server/src/tools/plans/retrieve-plans.ts +++ /dev/null @@ -1,54 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'plans', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/api/plans/{code}', - operationId: 'getPlan', -}; - -export const tool: Tool = { - name: 'retrieve_plans', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nretrieve a specific plans details by its code.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/plan',\n $defs: {\n plan: {\n type: 'object',\n properties: {\n description: {\n type: 'string'\n },\n name: {\n type: 'string',\n description: 'the plans name/code, this is used when creating enrollments.'\n },\n rate: {\n type: 'number',\n description: 'the price of the plan'\n },\n contents: {\n type: 'number',\n description: 'value of contents replacement, note this is only on some TLL plans.'\n },\n liability: {\n type: 'number',\n description: 'value of liability waived, note this is only on TLL plans.'\n },\n value: {\n type: 'number',\n description: 'general value field, this is currently used for SDR and SDD plans for the replacement or discount value.'\n }\n },\n required: [ 'description',\n 'name',\n 'rate'\n ]\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - code: { - type: 'string', - }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, - }, - required: ['code'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { code, jq_filter, ...body } = args as any; - try { - return asTextContentResult(await maybeFilter(jq_filter, await client.plans.retrieve(code))); - } catch (error) { - if (error instanceof Beagle.APIError || isJqError(error)) { - return asErrorResult(error.message); - } - throw error; - } -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts b/packages/mcp-server/src/tools/property-managers/create-property-managers.ts deleted file mode 100644 index 94b00903..00000000 --- a/packages/mcp-server/src/tools/property-managers/create-property-managers.ts +++ /dev/null @@ -1,125 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'property_managers', - operation: 'write', - tags: [], - httpMethod: 'post', - httpPath: '/api/property-managers', - operationId: 'createPropertyManager', -}; - -export const tool: Tool = { - name: 'create_property_managers', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ncreate a new property manager.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/property_manager',\n $defs: {\n property_manager: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n addresses: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/address'\n }\n ]\n }\n },\n contacts: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/contact'\n }\n ]\n }\n },\n name: {\n type: 'string',\n description: 'name of the property manager'\n },\n clickWrapAt: {\n type: 'number'\n }\n },\n required: [ 'id',\n 'addresses',\n 'contacts',\n 'name'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - addresses: { - type: 'array', - items: { - allOf: [ - { - $ref: '#/$defs/address', - }, - ], - }, - }, - contacts: { - type: 'array', - items: { - allOf: [ - { - $ref: '#/$defs/contact', - }, - ], - }, - }, - name: { - type: 'string', - description: 'name of the property manager', - }, - clickWrapAt: { - type: 'number', - }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, - }, - required: ['addresses', 'contacts', 'name'], - $defs: { - address: { - type: 'object', - properties: { - city: { - type: 'string', - }, - state: { - type: 'string', - description: 'two letter state code, ie CA', - }, - street1: { - type: 'string', - }, - zip: { - type: 'string', - description: '5 digit US zip code, ie 94104', - }, - street2: { - type: 'string', - }, - }, - required: ['city', 'state', 'street1', 'zip'], - }, - contact: { - type: 'object', - properties: { - email: { - type: 'string', - }, - name: { - type: 'object', - properties: { - first: { - type: 'string', - }, - last: { - type: 'string', - }, - }, - required: ['first', 'last'], - }, - phone: { - type: 'string', - }, - }, - required: ['email', 'name'], - }, - }, - }, - annotations: {}, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - try { - return asTextContentResult(await maybeFilter(jq_filter, await client.propertyManagers.create(body))); - } catch (error) { - if (error instanceof Beagle.APIError || isJqError(error)) { - return asErrorResult(error.message); - } - throw error; - } -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts b/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts deleted file mode 100644 index c2aafee6..00000000 --- a/packages/mcp-server/src/tools/property-managers/delete-property-managers.ts +++ /dev/null @@ -1,40 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'property_managers', - operation: 'write', - tags: [], - httpMethod: 'delete', - httpPath: '/api/property-managers/{id}', - operationId: 'deletePropertyManager', -}; - -export const tool: Tool = { - name: 'delete_property_managers', - description: 'delete a property manager by id.', - inputSchema: { - type: 'object', - properties: { - id: { - type: 'number', - }, - }, - required: ['id'], - }, - annotations: { - idempotentHint: true, - }, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { id, ...body } = args as any; - const response = await client.propertyManagers.delete(id).asResponse(); - return asTextContentResult(await response.text()); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts b/packages/mcp-server/src/tools/property-managers/list-property-managers.ts deleted file mode 100644 index 25f4407a..00000000 --- a/packages/mcp-server/src/tools/property-managers/list-property-managers.ts +++ /dev/null @@ -1,60 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'property_managers', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/api/property-managers', - operationId: 'listPropertyManagers', -}; - -export const tool: Tool = { - name: 'list_property_managers', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlist all property managers, note this endpoint is paginated.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n pagination: {\n $ref: '#/$defs/pagination'\n },\n propertyManagers: {\n type: 'array',\n items: {\n $ref: '#/$defs/property_manager'\n }\n }\n },\n required: [ 'pagination',\n 'propertyManagers'\n ],\n $defs: {\n pagination: {\n type: 'object',\n properties: {\n page: {\n type: 'number',\n description: 'Current page number.'\n },\n pages: {\n type: 'number',\n description: 'Total number of pages.'\n },\n records: {\n type: 'number',\n description: 'Total number of records.'\n },\n size: {\n type: 'number',\n description: 'Number of items per page.'\n }\n },\n required: [ 'page',\n 'pages',\n 'records',\n 'size'\n ]\n },\n property_manager: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n addresses: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/address'\n }\n ]\n }\n },\n contacts: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/contact'\n }\n ]\n }\n },\n name: {\n type: 'string',\n description: 'name of the property manager'\n },\n clickWrapAt: {\n type: 'number'\n }\n },\n required: [ 'id',\n 'addresses',\n 'contacts',\n 'name'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - page: { - type: 'number', - description: 'Page number to fetch.', - }, - size: { - type: 'number', - description: 'Number of items per page.', - }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, - }, - required: [], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - const response = await client.propertyManagers.list(body).asResponse(); - try { - return asTextContentResult(await maybeFilter(jq_filter, await response.json())); - } catch (error) { - if (error instanceof Beagle.APIError || isJqError(error)) { - return asErrorResult(error.message); - } - throw error; - } -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts b/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts deleted file mode 100644 index 46a021ae..00000000 --- a/packages/mcp-server/src/tools/property-managers/retrieve-property-managers.ts +++ /dev/null @@ -1,54 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'property_managers', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/api/property-managers/{id}', - operationId: 'getPropertyManager', -}; - -export const tool: Tool = { - name: 'retrieve_property_managers', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nget a property manager by id.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/property_manager',\n $defs: {\n property_manager: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n addresses: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/address'\n }\n ]\n }\n },\n contacts: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/contact'\n }\n ]\n }\n },\n name: {\n type: 'string',\n description: 'name of the property manager'\n },\n clickWrapAt: {\n type: 'number'\n }\n },\n required: [ 'id',\n 'addresses',\n 'contacts',\n 'name'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - id: { - type: 'number', - }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, - }, - required: ['id'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { id, jq_filter, ...body } = args as any; - try { - return asTextContentResult(await maybeFilter(jq_filter, await client.propertyManagers.retrieve(id))); - } catch (error) { - if (error instanceof Beagle.APIError || isJqError(error)) { - return asErrorResult(error.message); - } - throw error; - } -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts b/packages/mcp-server/src/tools/property-managers/update-property-managers.ts deleted file mode 100644 index 19e93b04..00000000 --- a/packages/mcp-server/src/tools/property-managers/update-property-managers.ts +++ /dev/null @@ -1,128 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'property_managers', - operation: 'write', - tags: [], - httpMethod: 'patch', - httpPath: '/api/property-managers/{id}', - operationId: 'updatePropertyManager', -}; - -export const tool: Tool = { - name: 'update_property_managers', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nupdate an existing property manager by id, note that when updating contacts or addresses you need to send the whole array you want to replace them with.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/property_manager',\n $defs: {\n property_manager: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n addresses: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/address'\n }\n ]\n }\n },\n contacts: {\n type: 'array',\n items: {\n allOf: [ {\n $ref: '#/$defs/contact'\n }\n ]\n }\n },\n name: {\n type: 'string',\n description: 'name of the property manager'\n },\n clickWrapAt: {\n type: 'number'\n }\n },\n required: [ 'id',\n 'addresses',\n 'contacts',\n 'name'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - id: { - type: 'number', - }, - addresses: { - type: 'array', - items: { - allOf: [ - { - $ref: '#/$defs/address', - }, - ], - }, - }, - clickWrapAt: { - type: 'number', - }, - contacts: { - type: 'array', - items: { - allOf: [ - { - $ref: '#/$defs/contact', - }, - ], - }, - }, - name: { - type: 'string', - description: 'name of the property manager', - }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, - }, - required: ['id'], - $defs: { - address: { - type: 'object', - properties: { - city: { - type: 'string', - }, - state: { - type: 'string', - description: 'two letter state code, ie CA', - }, - street1: { - type: 'string', - }, - zip: { - type: 'string', - description: '5 digit US zip code, ie 94104', - }, - street2: { - type: 'string', - }, - }, - required: ['city', 'state', 'street1', 'zip'], - }, - contact: { - type: 'object', - properties: { - email: { - type: 'string', - }, - name: { - type: 'object', - properties: { - first: { - type: 'string', - }, - last: { - type: 'string', - }, - }, - required: ['first', 'last'], - }, - phone: { - type: 'string', - }, - }, - required: ['email', 'name'], - }, - }, - }, - annotations: {}, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { id, jq_filter, ...body } = args as any; - try { - return asTextContentResult(await maybeFilter(jq_filter, await client.propertyManagers.update(id, body))); - } catch (error) { - if (error instanceof Beagle.APIError || isJqError(error)) { - return asErrorResult(error.message); - } - throw error; - } -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/tenants/create-tenants.ts b/packages/mcp-server/src/tools/tenants/create-tenants.ts deleted file mode 100644 index 5ab34358..00000000 --- a/packages/mcp-server/src/tools/tenants/create-tenants.ts +++ /dev/null @@ -1,107 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'tenants', - operation: 'write', - tags: [], - httpMethod: 'post', - httpPath: '/api/tenants', - operationId: 'createTenant', -}; - -export const tool: Tool = { - name: 'create_tenants', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ncreate a new tenant.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/tenant',\n $defs: {\n tenant: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n address: {\n $ref: '#/$defs/address'\n },\n contact: {\n $ref: '#/$defs/contact'\n }\n },\n required: [ 'id',\n 'address',\n 'contact'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - address: { - $ref: '#/$defs/address', - }, - contact: { - $ref: '#/$defs/contact', - }, - propertyManagerId: { - type: 'number', - }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, - }, - required: ['address', 'contact', 'propertyManagerId'], - $defs: { - address: { - type: 'object', - properties: { - city: { - type: 'string', - }, - state: { - type: 'string', - description: 'two letter state code, ie CA', - }, - street1: { - type: 'string', - }, - zip: { - type: 'string', - description: '5 digit US zip code, ie 94104', - }, - street2: { - type: 'string', - }, - }, - required: ['city', 'state', 'street1', 'zip'], - }, - contact: { - type: 'object', - properties: { - email: { - type: 'string', - }, - name: { - type: 'object', - properties: { - first: { - type: 'string', - }, - last: { - type: 'string', - }, - }, - required: ['first', 'last'], - }, - phone: { - type: 'string', - }, - }, - required: ['email', 'name'], - }, - }, - }, - annotations: {}, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - try { - return asTextContentResult(await maybeFilter(jq_filter, await client.tenants.create(body))); - } catch (error) { - if (error instanceof Beagle.APIError || isJqError(error)) { - return asErrorResult(error.message); - } - throw error; - } -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/tenants/delete-tenants.ts b/packages/mcp-server/src/tools/tenants/delete-tenants.ts deleted file mode 100644 index 89273d02..00000000 --- a/packages/mcp-server/src/tools/tenants/delete-tenants.ts +++ /dev/null @@ -1,40 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'tenants', - operation: 'write', - tags: [], - httpMethod: 'delete', - httpPath: '/api/tenants/{id}', - operationId: 'deleteTenant', -}; - -export const tool: Tool = { - name: 'delete_tenants', - description: 'delete an existing tenant by their id.', - inputSchema: { - type: 'object', - properties: { - id: { - type: 'number', - }, - }, - required: ['id'], - }, - annotations: { - idempotentHint: true, - }, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { id, ...body } = args as any; - const response = await client.tenants.delete(id).asResponse(); - return asTextContentResult(await response.text()); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/tenants/list-tenants.ts b/packages/mcp-server/src/tools/tenants/list-tenants.ts deleted file mode 100644 index cd3f4bda..00000000 --- a/packages/mcp-server/src/tools/tenants/list-tenants.ts +++ /dev/null @@ -1,63 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'tenants', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/api/tenants', - operationId: 'listTenants', -}; - -export const tool: Tool = { - name: 'list_tenants', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlist all tenants, this endpoint is paginated and allows for queries by individual property manager.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n pagination: {\n $ref: '#/$defs/pagination'\n },\n tenants: {\n type: 'array',\n items: {\n $ref: '#/$defs/tenant'\n }\n }\n },\n required: [ 'pagination',\n 'tenants'\n ],\n $defs: {\n pagination: {\n type: 'object',\n properties: {\n page: {\n type: 'number',\n description: 'Current page number.'\n },\n pages: {\n type: 'number',\n description: 'Total number of pages.'\n },\n records: {\n type: 'number',\n description: 'Total number of records.'\n },\n size: {\n type: 'number',\n description: 'Number of items per page.'\n }\n },\n required: [ 'page',\n 'pages',\n 'records',\n 'size'\n ]\n },\n tenant: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n address: {\n $ref: '#/$defs/address'\n },\n contact: {\n $ref: '#/$defs/contact'\n }\n },\n required: [ 'id',\n 'address',\n 'contact'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - page: { - type: 'number', - description: 'Page number to fetch.', - }, - propertyManagerId: { - type: 'number', - }, - size: { - type: 'number', - description: 'Number of items per page.', - }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, - }, - required: [], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - const response = await client.tenants.list(body).asResponse(); - try { - return asTextContentResult(await maybeFilter(jq_filter, await response.json())); - } catch (error) { - if (error instanceof Beagle.APIError || isJqError(error)) { - return asErrorResult(error.message); - } - throw error; - } -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts b/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts deleted file mode 100644 index 0d796a20..00000000 --- a/packages/mcp-server/src/tools/tenants/retrieve-tenants.ts +++ /dev/null @@ -1,54 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'tenants', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/api/tenants/{id}', - operationId: 'getTenant', -}; - -export const tool: Tool = { - name: 'retrieve_tenants', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nretrieve a single tenant by their id.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/tenant',\n $defs: {\n tenant: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n address: {\n $ref: '#/$defs/address'\n },\n contact: {\n $ref: '#/$defs/contact'\n }\n },\n required: [ 'id',\n 'address',\n 'contact'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - id: { - type: 'number', - }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, - }, - required: ['id'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { id, jq_filter, ...body } = args as any; - try { - return asTextContentResult(await maybeFilter(jq_filter, await client.tenants.retrieve(id))); - } catch (error) { - if (error instanceof Beagle.APIError || isJqError(error)) { - return asErrorResult(error.message); - } - throw error; - } -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/tenants/update-tenants.ts b/packages/mcp-server/src/tools/tenants/update-tenants.ts deleted file mode 100644 index d42c6589..00000000 --- a/packages/mcp-server/src/tools/tenants/update-tenants.ts +++ /dev/null @@ -1,107 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'tenants', - operation: 'write', - tags: [], - httpMethod: 'patch', - httpPath: '/api/tenants/{id}', - operationId: 'updateTenant', -}; - -export const tool: Tool = { - name: 'update_tenants', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nupdate an existing tenant by their id.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/tenant',\n $defs: {\n tenant: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n address: {\n $ref: '#/$defs/address'\n },\n contact: {\n $ref: '#/$defs/contact'\n }\n },\n required: [ 'id',\n 'address',\n 'contact'\n ]\n },\n address: {\n type: 'object',\n properties: {\n city: {\n type: 'string'\n },\n state: {\n type: 'string',\n description: 'two letter state code, ie CA'\n },\n street1: {\n type: 'string'\n },\n zip: {\n type: 'string',\n description: '5 digit US zip code, ie 94104'\n },\n street2: {\n type: 'string'\n }\n },\n required: [ 'city',\n 'state',\n 'street1',\n 'zip'\n ]\n },\n contact: {\n type: 'object',\n properties: {\n email: {\n type: 'string'\n },\n name: {\n type: 'object',\n properties: {\n first: {\n type: 'string'\n },\n last: {\n type: 'string'\n }\n },\n required: [ 'first',\n 'last'\n ]\n },\n phone: {\n type: 'string'\n }\n },\n required: [ 'email',\n 'name'\n ]\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - id: { - type: 'number', - }, - address: { - $ref: '#/$defs/address', - }, - contact: { - $ref: '#/$defs/contact', - }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, - }, - required: ['id'], - $defs: { - address: { - type: 'object', - properties: { - city: { - type: 'string', - }, - state: { - type: 'string', - description: 'two letter state code, ie CA', - }, - street1: { - type: 'string', - }, - zip: { - type: 'string', - description: '5 digit US zip code, ie 94104', - }, - street2: { - type: 'string', - }, - }, - required: ['city', 'state', 'street1', 'zip'], - }, - contact: { - type: 'object', - properties: { - email: { - type: 'string', - }, - name: { - type: 'object', - properties: { - first: { - type: 'string', - }, - last: { - type: 'string', - }, - }, - required: ['first', 'last'], - }, - phone: { - type: 'string', - }, - }, - required: ['email', 'name'], - }, - }, - }, - annotations: {}, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { id, jq_filter, ...body } = args as any; - try { - return asTextContentResult(await maybeFilter(jq_filter, await client.tenants.update(id, body))); - } catch (error) { - if (error instanceof Beagle.APIError || isJqError(error)) { - return asErrorResult(error.message); - } - throw error; - } -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts deleted file mode 100644 index 7fa0b8be..00000000 --- a/packages/mcp-server/src/tools/webhook/endpoints/create-webhook-endpoints.ts +++ /dev/null @@ -1,58 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'webhook.endpoints', - operation: 'write', - tags: [], - httpMethod: 'post', - httpPath: '/api/webhook/endpoints', - operationId: 'createWebhookEndpoint', -}; - -export const tool: Tool = { - name: 'create_webhook_endpoints', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\ncreates a new webhook target.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/endpoint_create_response',\n $defs: {\n endpoint_create_response: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n active: {\n type: 'boolean'\n },\n companyId: {\n type: 'number'\n },\n createdAt: {\n type: 'string'\n },\n updatedAt: {\n type: 'string'\n },\n url: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'active',\n 'companyId',\n 'createdAt',\n 'updatedAt',\n 'url'\n ]\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - secret: { - type: 'string', - }, - url: { - type: 'string', - }, - active: { - type: 'boolean', - }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, - }, - required: ['secret', 'url'], - }, - annotations: {}, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - try { - return asTextContentResult(await maybeFilter(jq_filter, await client.webhook.endpoints.create(body))); - } catch (error) { - if (error instanceof Beagle.APIError || isJqError(error)) { - return asErrorResult(error.message); - } - throw error; - } -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts deleted file mode 100644 index 4804e3e0..00000000 --- a/packages/mcp-server/src/tools/webhook/endpoints/delete-webhook-endpoints.ts +++ /dev/null @@ -1,40 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Metadata, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'webhook.endpoints', - operation: 'write', - tags: [], - httpMethod: 'delete', - httpPath: '/api/webhook/endpoints/{id}', - operationId: 'deleteWebhookEndpoint', -}; - -export const tool: Tool = { - name: 'delete_webhook_endpoints', - description: 'delete an existing webhook endpoint by its id.', - inputSchema: { - type: 'object', - properties: { - id: { - type: 'number', - }, - }, - required: ['id'], - }, - annotations: { - idempotentHint: true, - }, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { id, ...body } = args as any; - const response = await client.webhook.endpoints.delete(id).asResponse(); - return asTextContentResult(await response.text()); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts deleted file mode 100644 index 1878dcd0..00000000 --- a/packages/mcp-server/src/tools/webhook/endpoints/list-webhook-endpoints.ts +++ /dev/null @@ -1,60 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'webhook.endpoints', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/api/webhook/endpoints', - operationId: 'listWebhookEndpoints', -}; - -export const tool: Tool = { - name: 'list_webhook_endpoints', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nlist all webhook endpoints, this endpoint is paginated and allows for queries by individual property manager.\n\n# Response Schema\n```json\n{\n type: 'object',\n properties: {\n endpoints: {\n type: 'array',\n items: {\n $ref: '#/$defs/endpoint_list_response'\n }\n },\n pagination: {\n $ref: '#/$defs/pagination'\n }\n },\n required: [ 'endpoints',\n 'pagination'\n ],\n $defs: {\n endpoint_list_response: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n active: {\n type: 'boolean'\n },\n companyId: {\n type: 'number'\n },\n createdAt: {\n type: 'string'\n },\n updatedAt: {\n type: 'string'\n },\n url: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'active',\n 'companyId',\n 'createdAt',\n 'updatedAt',\n 'url'\n ]\n },\n pagination: {\n type: 'object',\n properties: {\n page: {\n type: 'number',\n description: 'Current page number.'\n },\n pages: {\n type: 'number',\n description: 'Total number of pages.'\n },\n records: {\n type: 'number',\n description: 'Total number of records.'\n },\n size: {\n type: 'number',\n description: 'Number of items per page.'\n }\n },\n required: [ 'page',\n 'pages',\n 'records',\n 'size'\n ]\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - page: { - type: 'number', - description: 'Page number to fetch.', - }, - size: { - type: 'number', - description: 'Number of items per page.', - }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, - }, - required: [], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - const response = await client.webhook.endpoints.list(body).asResponse(); - try { - return asTextContentResult(await maybeFilter(jq_filter, await response.json())); - } catch (error) { - if (error instanceof Beagle.APIError || isJqError(error)) { - return asErrorResult(error.message); - } - throw error; - } -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts deleted file mode 100644 index 77acb182..00000000 --- a/packages/mcp-server/src/tools/webhook/endpoints/retrieve-webhook-endpoints.ts +++ /dev/null @@ -1,54 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'webhook.endpoints', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/api/webhook/endpoints/{id}', - operationId: 'getWebhookEndpoint', -}; - -export const tool: Tool = { - name: 'retrieve_webhook_endpoints', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nretrieve a single webhook endpoint by its id.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/endpoint_retrieve_response',\n $defs: {\n endpoint_retrieve_response: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n active: {\n type: 'boolean'\n },\n companyId: {\n type: 'number'\n },\n createdAt: {\n type: 'string'\n },\n updatedAt: {\n type: 'string'\n },\n url: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'active',\n 'companyId',\n 'createdAt',\n 'updatedAt',\n 'url'\n ]\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - id: { - type: 'number', - }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, - }, - required: ['id'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { id, jq_filter, ...body } = args as any; - try { - return asTextContentResult(await maybeFilter(jq_filter, await client.webhook.endpoints.retrieve(id))); - } catch (error) { - if (error instanceof Beagle.APIError || isJqError(error)) { - return asErrorResult(error.message); - } - throw error; - } -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts b/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts deleted file mode 100644 index 588ba2ce..00000000 --- a/packages/mcp-server/src/tools/webhook/endpoints/update-webhook-endpoints.ts +++ /dev/null @@ -1,61 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { isJqError, maybeFilter } from '@corgi-tech/beagle-mcp/filtering'; -import { Metadata, asErrorResult, asTextContentResult } from '@corgi-tech/beagle-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Beagle from '@corgi-tech/beagle'; - -export const metadata: Metadata = { - resource: 'webhook.endpoints', - operation: 'write', - tags: [], - httpMethod: 'patch', - httpPath: '/api/webhook/endpoints/{id}', - operationId: 'updateWebhookEndpoint', -}; - -export const tool: Tool = { - name: 'update_webhook_endpoints', - description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nupdate an existing webhook endpoint by its id.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/endpoint_update_response',\n $defs: {\n endpoint_update_response: {\n type: 'object',\n properties: {\n id: {\n type: 'number'\n },\n active: {\n type: 'boolean'\n },\n companyId: {\n type: 'number'\n },\n createdAt: {\n type: 'string'\n },\n updatedAt: {\n type: 'string'\n },\n url: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'active',\n 'companyId',\n 'createdAt',\n 'updatedAt',\n 'url'\n ]\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - id: { - type: 'number', - }, - secret: { - type: 'string', - }, - url: { - type: 'string', - }, - active: { - type: 'boolean', - }, - jq_filter: { - type: 'string', - title: 'jq Filter', - description: - 'A jq filter to apply to the response to include certain fields. Consult the output schema in the tool description to see the fields that are available.\n\nFor example: to include only the `name` field in every object of a results array, you can provide ".results[].name".\n\nFor more information, see the [jq documentation](https://jqlang.org/manual/).', - }, - }, - required: ['id', 'secret', 'url'], - }, - annotations: {}, -}; - -export const handler = async (client: Beagle, args: Record | undefined) => { - const { id, jq_filter, ...body } = args as any; - try { - return asTextContentResult(await maybeFilter(jq_filter, await client.webhook.endpoints.update(id, body))); - } catch (error) { - if (error instanceof Beagle.APIError || isJqError(error)) { - return asErrorResult(error.message); - } - throw error; - } -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/types.ts b/packages/mcp-server/src/types.ts similarity index 98% rename from packages/mcp-server/src/tools/types.ts rename to packages/mcp-server/src/types.ts index 1661b689..9e4179f9 100644 --- a/packages/mcp-server/src/tools/types.ts +++ b/packages/mcp-server/src/types.ts @@ -108,7 +108,7 @@ export type Metadata = { operationId?: string; }; -export type Endpoint = { +export type McpTool = { metadata: Metadata; tool: Tool; handler: HandlerFunction; diff --git a/packages/mcp-server/tests/compat.test.ts b/packages/mcp-server/tests/compat.test.ts deleted file mode 100644 index d6272f6c..00000000 --- a/packages/mcp-server/tests/compat.test.ts +++ /dev/null @@ -1,1166 +0,0 @@ -import { - truncateToolNames, - removeTopLevelUnions, - removeAnyOf, - inlineRefs, - applyCompatibilityTransformations, - removeFormats, - findUsedDefs, -} from '../src/compat'; -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import { JSONSchema } from '../src/compat'; -import { Endpoint } from '../src/tools'; - -describe('truncateToolNames', () => { - it('should return original names when maxLength is 0 or negative', () => { - const names = ['tool1', 'tool2', 'tool3']; - expect(truncateToolNames(names, 0)).toEqual(new Map()); - expect(truncateToolNames(names, -1)).toEqual(new Map()); - }); - - it('should return original names when all names are shorter than maxLength', () => { - const names = ['tool1', 'tool2', 'tool3']; - expect(truncateToolNames(names, 10)).toEqual(new Map()); - }); - - it('should truncate names longer than maxLength', () => { - const names = ['very-long-tool-name', 'another-long-tool-name', 'short']; - expect(truncateToolNames(names, 10)).toEqual( - new Map([ - ['very-long-tool-name', 'very-long-'], - ['another-long-tool-name', 'another-lo'], - ]), - ); - }); - - it('should handle duplicate truncated names by appending numbers', () => { - const names = ['tool-name-a', 'tool-name-b', 'tool-name-c']; - expect(truncateToolNames(names, 8)).toEqual( - new Map([ - ['tool-name-a', 'tool-na1'], - ['tool-name-b', 'tool-na2'], - ['tool-name-c', 'tool-na3'], - ]), - ); - }); -}); - -describe('removeTopLevelUnions', () => { - const createTestTool = (overrides = {}): Tool => ({ - name: 'test-tool', - description: 'Test tool', - inputSchema: { - type: 'object', - properties: {}, - }, - ...overrides, - }); - - it('should return the original tool if it has no anyOf at the top level', () => { - const tool = createTestTool({ - inputSchema: { - type: 'object', - properties: { - foo: { type: 'string' }, - }, - }, - }); - - expect(removeTopLevelUnions(tool)).toEqual([tool]); - }); - - it('should split a tool with top-level anyOf into multiple tools', () => { - const tool = createTestTool({ - name: 'union-tool', - description: 'A tool with unions', - inputSchema: { - type: 'object', - properties: { - common: { type: 'string' }, - }, - anyOf: [ - { - title: 'first variant', - description: 'Its the first variant', - properties: { - variant1: { type: 'string' }, - }, - required: ['variant1'], - }, - { - title: 'second variant', - properties: { - variant2: { type: 'number' }, - }, - required: ['variant2'], - }, - ], - }, - }); - - const result = removeTopLevelUnions(tool); - - expect(result).toEqual([ - { - name: 'union-tool_first_variant', - description: 'Its the first variant', - inputSchema: { - type: 'object', - title: 'first variant', - description: 'Its the first variant', - properties: { - common: { type: 'string' }, - variant1: { type: 'string' }, - }, - required: ['variant1'], - }, - }, - { - name: 'union-tool_second_variant', - description: 'A tool with unions', - inputSchema: { - type: 'object', - title: 'second variant', - description: 'A tool with unions', - properties: { - common: { type: 'string' }, - variant2: { type: 'number' }, - }, - required: ['variant2'], - }, - }, - ]); - }); - - it('should handle $defs and only include those used by the variant', () => { - const tool = createTestTool({ - name: 'defs-tool', - description: 'A tool with $defs', - inputSchema: { - type: 'object', - properties: { - common: { type: 'string' }, - }, - $defs: { - def1: { type: 'string', format: 'email' }, - def2: { type: 'number', minimum: 0 }, - unused: { type: 'boolean' }, - }, - anyOf: [ - { - properties: { - email: { $ref: '#/$defs/def1' }, - }, - }, - { - properties: { - count: { $ref: '#/$defs/def2' }, - }, - }, - ], - }, - }); - - const result = removeTopLevelUnions(tool); - - expect(result).toEqual([ - { - name: 'defs-tool_variant1', - description: 'A tool with $defs', - inputSchema: { - type: 'object', - description: 'A tool with $defs', - properties: { - common: { type: 'string' }, - email: { $ref: '#/$defs/def1' }, - }, - $defs: { - def1: { type: 'string', format: 'email' }, - }, - }, - }, - { - name: 'defs-tool_variant2', - description: 'A tool with $defs', - inputSchema: { - type: 'object', - description: 'A tool with $defs', - properties: { - common: { type: 'string' }, - count: { $ref: '#/$defs/def2' }, - }, - $defs: { - def2: { type: 'number', minimum: 0 }, - }, - }, - }, - ]); - }); -}); - -describe('removeAnyOf', () => { - it('should return original schema if it has no anyOf', () => { - const schema = { - type: 'object', - properties: { - foo: { type: 'string' }, - bar: { type: 'number' }, - }, - }; - - expect(removeAnyOf(schema)).toEqual(schema); - }); - - it('should remove anyOf field and use the first variant', () => { - const schema = { - type: 'object', - properties: { - common: { type: 'string' }, - }, - anyOf: [ - { - properties: { - variant1: { type: 'string' }, - }, - required: ['variant1'], - }, - { - properties: { - variant2: { type: 'number' }, - }, - required: ['variant2'], - }, - ], - }; - - const expected = { - type: 'object', - properties: { - common: { type: 'string' }, - variant1: { type: 'string' }, - }, - required: ['variant1'], - }; - - expect(removeAnyOf(schema)).toEqual(expected); - }); - - it('should recursively remove anyOf fields from nested properties', () => { - const schema = { - type: 'object', - properties: { - foo: { type: 'string' }, - nested: { - type: 'object', - properties: { - bar: { type: 'number' }, - }, - anyOf: [ - { - properties: { - option1: { type: 'boolean' }, - }, - }, - { - properties: { - option2: { type: 'array' }, - }, - }, - ], - }, - }, - }; - - const expected = { - type: 'object', - properties: { - foo: { type: 'string' }, - nested: { - type: 'object', - properties: { - bar: { type: 'number' }, - option1: { type: 'boolean' }, - }, - }, - }, - }; - - expect(removeAnyOf(schema)).toEqual(expected); - }); - - it('should handle arrays', () => { - const schema = { - type: 'object', - properties: { - items: { - type: 'array', - items: { - anyOf: [{ type: 'string' }, { type: 'number' }], - }, - }, - }, - }; - - const expected = { - type: 'object', - properties: { - items: { - type: 'array', - items: { - type: 'string', - }, - }, - }, - }; - - expect(removeAnyOf(schema)).toEqual(expected); - }); -}); - -describe('findUsedDefs', () => { - it('should handle circular references without stack overflow', () => { - const defs = { - person: { - type: 'object', - properties: { - name: { type: 'string' }, - friend: { $ref: '#/$defs/person' }, // Circular reference - }, - }, - }; - - const schema = { - type: 'object', - properties: { - user: { $ref: '#/$defs/person' }, - }, - }; - - // This should not throw a stack overflow error - expect(() => { - const result = findUsedDefs(schema, defs); - expect(result).toHaveProperty('person'); - }).not.toThrow(); - }); - - it('should handle indirect circular references without stack overflow', () => { - const defs = { - node: { - type: 'object', - properties: { - value: { type: 'string' }, - child: { $ref: '#/$defs/childNode' }, - }, - }, - childNode: { - type: 'object', - properties: { - value: { type: 'string' }, - parent: { $ref: '#/$defs/node' }, // Indirect circular reference - }, - }, - }; - - const schema = { - type: 'object', - properties: { - root: { $ref: '#/$defs/node' }, - }, - }; - - // This should not throw a stack overflow error - expect(() => { - const result = findUsedDefs(schema, defs); - expect(result).toHaveProperty('node'); - expect(result).toHaveProperty('childNode'); - }).not.toThrow(); - }); - - it('should find all used definitions in non-circular schemas', () => { - const defs = { - user: { - type: 'object', - properties: { - name: { type: 'string' }, - address: { $ref: '#/$defs/address' }, - }, - }, - address: { - type: 'object', - properties: { - street: { type: 'string' }, - city: { type: 'string' }, - }, - }, - unused: { - type: 'object', - properties: { - data: { type: 'string' }, - }, - }, - }; - - const schema = { - type: 'object', - properties: { - person: { $ref: '#/$defs/user' }, - }, - }; - - const result = findUsedDefs(schema, defs); - expect(result).toHaveProperty('user'); - expect(result).toHaveProperty('address'); - expect(result).not.toHaveProperty('unused'); - }); -}); - -describe('inlineRefs', () => { - it('should return the original schema if it does not contain $refs', () => { - const schema: JSONSchema = { - type: 'object', - properties: { - name: { type: 'string' }, - age: { type: 'number' }, - }, - }; - - expect(inlineRefs(schema)).toEqual(schema); - }); - - it('should inline simple $refs', () => { - const schema: JSONSchema = { - type: 'object', - properties: { - user: { $ref: '#/$defs/user' }, - }, - $defs: { - user: { - type: 'object', - properties: { - name: { type: 'string' }, - email: { type: 'string' }, - }, - }, - }, - }; - - const expected: JSONSchema = { - type: 'object', - properties: { - user: { - type: 'object', - properties: { - name: { type: 'string' }, - email: { type: 'string' }, - }, - }, - }, - }; - - expect(inlineRefs(schema)).toEqual(expected); - }); - - it('should inline nested $refs', () => { - const schema: JSONSchema = { - type: 'object', - properties: { - order: { $ref: '#/$defs/order' }, - }, - $defs: { - order: { - type: 'object', - properties: { - id: { type: 'string' }, - items: { type: 'array', items: { $ref: '#/$defs/item' } }, - }, - }, - item: { - type: 'object', - properties: { - product: { type: 'string' }, - quantity: { type: 'integer' }, - }, - }, - }, - }; - - const expected: JSONSchema = { - type: 'object', - properties: { - order: { - type: 'object', - properties: { - id: { type: 'string' }, - items: { - type: 'array', - items: { - type: 'object', - properties: { - product: { type: 'string' }, - quantity: { type: 'integer' }, - }, - }, - }, - }, - }, - }, - }; - - expect(inlineRefs(schema)).toEqual(expected); - }); - - it('should handle circular references by removing the circular part', () => { - const schema: JSONSchema = { - type: 'object', - properties: { - person: { $ref: '#/$defs/person' }, - }, - $defs: { - person: { - type: 'object', - properties: { - name: { type: 'string' }, - friend: { $ref: '#/$defs/person' }, // Circular reference - }, - }, - }, - }; - - const expected: JSONSchema = { - type: 'object', - properties: { - person: { - type: 'object', - properties: { - name: { type: 'string' }, - // friend property is removed to break the circular reference - }, - }, - }, - }; - - expect(inlineRefs(schema)).toEqual(expected); - }); - - it('should handle indirect circular references', () => { - const schema: JSONSchema = { - type: 'object', - properties: { - node: { $ref: '#/$defs/node' }, - }, - $defs: { - node: { - type: 'object', - properties: { - value: { type: 'string' }, - child: { $ref: '#/$defs/childNode' }, - }, - }, - childNode: { - type: 'object', - properties: { - value: { type: 'string' }, - parent: { $ref: '#/$defs/node' }, // Circular reference through childNode - }, - }, - }, - }; - - const expected: JSONSchema = { - type: 'object', - properties: { - node: { - type: 'object', - properties: { - value: { type: 'string' }, - child: { - type: 'object', - properties: { - value: { type: 'string' }, - // parent property is removed to break the circular reference - }, - }, - }, - }, - }, - }; - - expect(inlineRefs(schema)).toEqual(expected); - }); - - it('should preserve other properties when inlining references', () => { - const schema: JSONSchema = { - type: 'object', - properties: { - address: { $ref: '#/$defs/address', description: 'User address' }, - }, - $defs: { - address: { - type: 'object', - properties: { - street: { type: 'string' }, - city: { type: 'string' }, - }, - required: ['street'], - }, - }, - }; - - const expected: JSONSchema = { - type: 'object', - properties: { - address: { - type: 'object', - description: 'User address', - properties: { - street: { type: 'string' }, - city: { type: 'string' }, - }, - required: ['street'], - }, - }, - }; - - expect(inlineRefs(schema)).toEqual(expected); - }); -}); - -describe('removeFormats', () => { - it('should return original schema if formats capability is true', () => { - const schema = { - type: 'object', - properties: { - date: { type: 'string', description: 'A date field', format: 'date' }, - email: { type: 'string', description: 'An email field', format: 'email' }, - }, - }; - - expect(removeFormats(schema, true)).toEqual(schema); - }); - - it('should move format to description when formats capability is false', () => { - const schema = { - type: 'object', - properties: { - date: { type: 'string', description: 'A date field', format: 'date' }, - email: { type: 'string', description: 'An email field', format: 'email' }, - }, - }; - - const expected = { - type: 'object', - properties: { - date: { type: 'string', description: 'A date field (format: "date")' }, - email: { type: 'string', description: 'An email field (format: "email")' }, - }, - }; - - expect(removeFormats(schema, false)).toEqual(expected); - }); - - it('should handle properties without description', () => { - const schema = { - type: 'object', - properties: { - date: { type: 'string', format: 'date' }, - }, - }; - - const expected = { - type: 'object', - properties: { - date: { type: 'string', description: '(format: "date")' }, - }, - }; - - expect(removeFormats(schema, false)).toEqual(expected); - }); - - it('should handle nested properties', () => { - const schema = { - type: 'object', - properties: { - user: { - type: 'object', - properties: { - created_at: { type: 'string', description: 'Creation date', format: 'date-time' }, - }, - }, - }, - }; - - const expected = { - type: 'object', - properties: { - user: { - type: 'object', - properties: { - created_at: { type: 'string', description: 'Creation date (format: "date-time")' }, - }, - }, - }, - }; - - expect(removeFormats(schema, false)).toEqual(expected); - }); - - it('should handle arrays of objects', () => { - const schema = { - type: 'object', - properties: { - dates: { - type: 'array', - items: { - type: 'object', - properties: { - start: { type: 'string', description: 'Start date', format: 'date' }, - end: { type: 'string', description: 'End date', format: 'date' }, - }, - }, - }, - }, - }; - - const expected = { - type: 'object', - properties: { - dates: { - type: 'array', - items: { - type: 'object', - properties: { - start: { type: 'string', description: 'Start date (format: "date")' }, - end: { type: 'string', description: 'End date (format: "date")' }, - }, - }, - }, - }, - }; - - expect(removeFormats(schema, false)).toEqual(expected); - }); - - it('should handle schemas with $defs', () => { - const schema = { - type: 'object', - properties: { - date: { type: 'string', description: 'A date field', format: 'date' }, - }, - $defs: { - timestamp: { - type: 'string', - description: 'A timestamp field', - format: 'date-time', - }, - }, - }; - - const expected = { - type: 'object', - properties: { - date: { type: 'string', description: 'A date field (format: "date")' }, - }, - $defs: { - timestamp: { - type: 'string', - description: 'A timestamp field (format: "date-time")', - }, - }, - }; - - expect(removeFormats(schema, false)).toEqual(expected); - }); -}); - -describe('applyCompatibilityTransformations', () => { - const createTestTool = (name: string, overrides = {}): Tool => ({ - name, - description: 'Test tool', - inputSchema: { - type: 'object', - properties: {}, - }, - ...overrides, - }); - - const createTestEndpoint = (tool: Tool): Endpoint => ({ - tool, - handler: jest.fn(), - metadata: { - resource: 'test', - operation: 'read' as const, - tags: [], - }, - }); - - it('should not modify endpoints when all capabilities are enabled', () => { - const tool = createTestTool('test-tool'); - const endpoints = [createTestEndpoint(tool)]; - - const capabilities = { - topLevelUnions: true, - validJson: true, - refs: true, - unions: true, - formats: true, - toolNameLength: undefined, - }; - - const transformed = applyCompatibilityTransformations(endpoints, capabilities); - expect(transformed).toEqual(endpoints); - }); - - it('should split tools with top-level unions when topLevelUnions is disabled', () => { - const tool = createTestTool('union-tool', { - inputSchema: { - type: 'object', - properties: { - common: { type: 'string' }, - }, - anyOf: [ - { - title: 'first variant', - properties: { - variant1: { type: 'string' }, - }, - }, - { - title: 'second variant', - properties: { - variant2: { type: 'number' }, - }, - }, - ], - }, - }); - - const endpoints = [createTestEndpoint(tool)]; - - const capabilities = { - topLevelUnions: false, - validJson: true, - refs: true, - unions: true, - formats: true, - toolNameLength: undefined, - }; - - const transformed = applyCompatibilityTransformations(endpoints, capabilities); - expect(transformed.length).toBe(2); - expect(transformed[0]!.tool.name).toBe('union-tool_first_variant'); - expect(transformed[1]!.tool.name).toBe('union-tool_second_variant'); - }); - - it('should handle variants without titles in removeTopLevelUnions', () => { - const tool = createTestTool('union-tool', { - inputSchema: { - type: 'object', - properties: { - common: { type: 'string' }, - }, - anyOf: [ - { - properties: { - variant1: { type: 'string' }, - }, - }, - { - properties: { - variant2: { type: 'number' }, - }, - }, - ], - }, - }); - - const endpoints = [createTestEndpoint(tool)]; - - const capabilities = { - topLevelUnions: false, - validJson: true, - refs: true, - unions: true, - formats: true, - toolNameLength: undefined, - }; - - const transformed = applyCompatibilityTransformations(endpoints, capabilities); - expect(transformed.length).toBe(2); - expect(transformed[0]!.tool.name).toBe('union-tool_variant1'); - expect(transformed[1]!.tool.name).toBe('union-tool_variant2'); - }); - - it('should truncate tool names when toolNameLength is set', () => { - const tools = [ - createTestTool('very-long-tool-name-that-exceeds-limit'), - createTestTool('another-long-tool-name-to-truncate'), - createTestTool('short-name'), - ]; - - const endpoints = tools.map(createTestEndpoint); - - const capabilities = { - topLevelUnions: true, - validJson: true, - refs: true, - unions: true, - formats: true, - toolNameLength: 20, - }; - - const transformed = applyCompatibilityTransformations(endpoints, capabilities); - expect(transformed[0]!.tool.name).toBe('very-long-tool-name-'); - expect(transformed[1]!.tool.name).toBe('another-long-tool-na'); - expect(transformed[2]!.tool.name).toBe('short-name'); - }); - - it('should inline refs when refs capability is disabled', () => { - const tool = createTestTool('ref-tool', { - inputSchema: { - type: 'object', - properties: { - user: { $ref: '#/$defs/user' }, - }, - $defs: { - user: { - type: 'object', - properties: { - name: { type: 'string' }, - email: { type: 'string' }, - }, - }, - }, - }, - }); - - const endpoints = [createTestEndpoint(tool)]; - - const capabilities = { - topLevelUnions: true, - validJson: true, - refs: false, - unions: true, - formats: true, - toolNameLength: undefined, - }; - - const transformed = applyCompatibilityTransformations(endpoints, capabilities); - const schema = transformed[0]!.tool.inputSchema as JSONSchema; - expect(schema.$defs).toBeUndefined(); - - if (schema.properties) { - expect(schema.properties['user']).toEqual({ - type: 'object', - properties: { - name: { type: 'string' }, - email: { type: 'string' }, - }, - }); - } - }); - - it('should preserve external refs when inlining', () => { - const tool = createTestTool('ref-tool', { - inputSchema: { - type: 'object', - properties: { - internal: { $ref: '#/$defs/internal' }, - external: { $ref: 'https://example.com/schemas/external.json' }, - }, - $defs: { - internal: { - type: 'object', - properties: { - name: { type: 'string' }, - }, - }, - }, - }, - }); - - const endpoints = [createTestEndpoint(tool)]; - - const capabilities = { - topLevelUnions: true, - validJson: true, - refs: false, - unions: true, - formats: true, - toolNameLength: undefined, - }; - - const transformed = applyCompatibilityTransformations(endpoints, capabilities); - const schema = transformed[0]!.tool.inputSchema as JSONSchema; - - if (schema.properties) { - expect(schema.properties['internal']).toEqual({ - type: 'object', - properties: { - name: { type: 'string' }, - }, - }); - expect(schema.properties['external']).toEqual({ - $ref: 'https://example.com/schemas/external.json', - }); - } - }); - - it('should remove anyOf fields when unions capability is disabled', () => { - const tool = createTestTool('union-tool', { - inputSchema: { - type: 'object', - properties: { - field: { - anyOf: [{ type: 'string' }, { type: 'number' }], - }, - }, - }, - }); - - const endpoints = [createTestEndpoint(tool)]; - - const capabilities = { - topLevelUnions: true, - validJson: true, - refs: true, - unions: false, - formats: true, - toolNameLength: undefined, - }; - - const transformed = applyCompatibilityTransformations(endpoints, capabilities); - const schema = transformed[0]!.tool.inputSchema as JSONSchema; - - if (schema.properties && schema.properties['field']) { - const field = schema.properties['field']; - expect(field.anyOf).toBeUndefined(); - expect(field.type).toBe('string'); - } - }); - - it('should correctly combine topLevelUnions and toolNameLength transformations', () => { - const tool = createTestTool('very-long-union-tool-name', { - inputSchema: { - type: 'object', - properties: { - common: { type: 'string' }, - }, - anyOf: [ - { - title: 'first variant', - properties: { - variant1: { type: 'string' }, - }, - }, - { - title: 'second variant', - properties: { - variant2: { type: 'number' }, - }, - }, - ], - }, - }); - - const endpoints = [createTestEndpoint(tool)]; - - const capabilities = { - topLevelUnions: false, - validJson: true, - refs: true, - unions: true, - formats: true, - toolNameLength: 20, - }; - - const transformed = applyCompatibilityTransformations(endpoints, capabilities); - expect(transformed.length).toBe(2); - - // Both names should be truncated because they exceed 20 characters - expect(transformed[0]!.tool.name).toBe('very-long-union-too1'); - expect(transformed[1]!.tool.name).toBe('very-long-union-too2'); - }); - - it('should correctly combine refs and unions transformations', () => { - const tool = createTestTool('complex-tool', { - inputSchema: { - type: 'object', - properties: { - user: { $ref: '#/$defs/user' }, - }, - $defs: { - user: { - type: 'object', - properties: { - preference: { - anyOf: [{ type: 'string' }, { type: 'number' }], - }, - }, - }, - }, - }, - }); - - const endpoints = [createTestEndpoint(tool)]; - - const capabilities = { - topLevelUnions: true, - validJson: true, - refs: false, - unions: false, - formats: true, - toolNameLength: undefined, - }; - - const transformed = applyCompatibilityTransformations(endpoints, capabilities); - const schema = transformed[0]!.tool.inputSchema as JSONSchema; - - // Refs should be inlined - expect(schema.$defs).toBeUndefined(); - - // Safely access nested properties - if (schema.properties && schema.properties['user']) { - const user = schema.properties['user']; - // User should be inlined - expect(user.type).toBe('object'); - - // AnyOf in the inlined user.preference should be removed - if (user.properties && user.properties['preference']) { - const preference = user.properties['preference']; - expect(preference.anyOf).toBeUndefined(); - expect(preference.type).toBe('string'); - } - } - }); - - it('should handle formats capability being false', () => { - const tool = createTestTool('format-tool', { - inputSchema: { - type: 'object', - properties: { - date: { type: 'string', description: 'A date', format: 'date' }, - }, - }, - }); - - const endpoints = [createTestEndpoint(tool)]; - - const capabilities = { - topLevelUnions: true, - validJson: true, - refs: true, - unions: true, - formats: false, - toolNameLength: undefined, - }; - - const transformed = applyCompatibilityTransformations(endpoints, capabilities); - const schema = transformed[0]!.tool.inputSchema as JSONSchema; - - if (schema.properties && schema.properties['date']) { - const dateField = schema.properties['date']; - expect(dateField['format']).toBeUndefined(); - expect(dateField['description']).toBe('A date (format: "date")'); - } - }); -}); diff --git a/packages/mcp-server/tests/dynamic-tools.test.ts b/packages/mcp-server/tests/dynamic-tools.test.ts deleted file mode 100644 index 08963af8..00000000 --- a/packages/mcp-server/tests/dynamic-tools.test.ts +++ /dev/null @@ -1,185 +0,0 @@ -import { dynamicTools } from '../src/dynamic-tools'; -import { Endpoint } from '../src/tools'; - -describe('dynamicTools', () => { - const fakeClient = {} as any; - - const endpoints: Endpoint[] = [ - makeEndpoint('test_read_endpoint', 'test_resource', 'read', ['test']), - makeEndpoint('test_write_endpoint', 'test_resource', 'write', ['test']), - makeEndpoint('user_endpoint', 'user', 'read', ['user', 'admin']), - makeEndpoint('admin_endpoint', 'admin', 'write', ['admin']), - ]; - - const tools = dynamicTools(endpoints); - - const toolsMap = { - list_api_endpoints: toolOrError('list_api_endpoints'), - get_api_endpoint_schema: toolOrError('get_api_endpoint_schema'), - invoke_api_endpoint: toolOrError('invoke_api_endpoint'), - }; - - describe('list_api_endpoints', () => { - it('should return all endpoints when no search query is provided', async () => { - const content = await toolsMap.list_api_endpoints.handler(fakeClient, {}); - const result = JSON.parse(content.content[0].text); - - expect(result.tools).toHaveLength(endpoints.length); - expect(result.tools.map((t: { name: string }) => t.name)).toContain('test_read_endpoint'); - expect(result.tools.map((t: { name: string }) => t.name)).toContain('test_write_endpoint'); - expect(result.tools.map((t: { name: string }) => t.name)).toContain('user_endpoint'); - expect(result.tools.map((t: { name: string }) => t.name)).toContain('admin_endpoint'); - }); - - it('should filter endpoints by name', async () => { - const content = await toolsMap.list_api_endpoints.handler(fakeClient, { search_query: 'user' }); - const result = JSON.parse(content.content[0].text); - - expect(result.tools).toHaveLength(1); - expect(result.tools[0].name).toBe('user_endpoint'); - }); - - it('should filter endpoints by resource', async () => { - const content = await toolsMap.list_api_endpoints.handler(fakeClient, { search_query: 'admin' }); - const result = JSON.parse(content.content[0].text); - - expect(result.tools.some((t: { resource: string }) => t.resource === 'admin')).toBeTruthy(); - }); - - it('should filter endpoints by tag', async () => { - const content = await toolsMap.list_api_endpoints.handler(fakeClient, { search_query: 'admin' }); - const result = JSON.parse(content.content[0].text); - - expect(result.tools.some((t: { tags: string[] }) => t.tags.includes('admin'))).toBeTruthy(); - }); - - it('should be case insensitive in search', async () => { - const content = await toolsMap.list_api_endpoints.handler(fakeClient, { search_query: 'ADMIN' }); - const result = JSON.parse(content.content[0].text); - - expect(result.tools.length).toBe(2); - result.tools.forEach((tool: { name: string; resource: string; tags: string[] }) => { - expect( - tool.name.toLowerCase().includes('admin') || - tool.resource.toLowerCase().includes('admin') || - tool.tags.some((tag: string) => tag.toLowerCase().includes('admin')), - ).toBeTruthy(); - }); - }); - - it('should filter endpoints by description', async () => { - const content = await toolsMap.list_api_endpoints.handler(fakeClient, { - search_query: 'Test endpoint for user_endpoint', - }); - const result = JSON.parse(content.content[0].text); - - expect(result.tools).toHaveLength(1); - expect(result.tools[0].name).toBe('user_endpoint'); - expect(result.tools[0].description).toBe('Test endpoint for user_endpoint'); - }); - - it('should filter endpoints by partial description match', async () => { - const content = await toolsMap.list_api_endpoints.handler(fakeClient, { - search_query: 'endpoint for user', - }); - const result = JSON.parse(content.content[0].text); - - expect(result.tools).toHaveLength(1); - expect(result.tools[0].name).toBe('user_endpoint'); - }); - }); - - describe('get_api_endpoint_schema', () => { - it('should return schema for existing endpoint', async () => { - const content = await toolsMap.get_api_endpoint_schema.handler(fakeClient, { - endpoint: 'test_read_endpoint', - }); - const result = JSON.parse(content.content[0].text); - - expect(result).toEqual(endpoints[0]?.tool); - }); - - it('should throw error for non-existent endpoint', async () => { - await expect( - toolsMap.get_api_endpoint_schema.handler(fakeClient, { endpoint: 'non_existent_endpoint' }), - ).rejects.toThrow('Endpoint non_existent_endpoint not found'); - }); - - it('should throw error when no endpoint provided', async () => { - await expect(toolsMap.get_api_endpoint_schema.handler(fakeClient, undefined)).rejects.toThrow( - 'No endpoint provided', - ); - }); - }); - - describe('invoke_api_endpoint', () => { - it('should successfully invoke endpoint with valid arguments', async () => { - const mockHandler = endpoints[0]?.handler as jest.Mock; - mockHandler.mockClear(); - - await toolsMap.invoke_api_endpoint.handler(fakeClient, { - endpoint_name: 'test_read_endpoint', - args: { testParam: 'test value' }, - }); - - expect(mockHandler).toHaveBeenCalledWith(fakeClient, { testParam: 'test value' }); - }); - - it('should throw error for non-existent endpoint', async () => { - await expect( - toolsMap.invoke_api_endpoint.handler(fakeClient, { - endpoint_name: 'non_existent_endpoint', - args: { testParam: 'test value' }, - }), - ).rejects.toThrow(/Endpoint non_existent_endpoint not found/); - }); - - it('should throw error when no arguments provided', async () => { - await expect(toolsMap.invoke_api_endpoint.handler(fakeClient, undefined)).rejects.toThrow( - 'No endpoint provided', - ); - }); - - it('should throw error for invalid argument schema', async () => { - await expect( - toolsMap.invoke_api_endpoint.handler(fakeClient, { - endpoint_name: 'test_read_endpoint', - args: { wrongParam: 'test value' }, // Missing required testParam - }), - ).rejects.toThrow(/Invalid arguments for endpoint/); - }); - }); - - function toolOrError(name: string) { - const tool = tools.find((tool) => tool.tool.name === name); - if (!tool) throw new Error(`Tool ${name} not found`); - return tool; - } -}); - -function makeEndpoint( - name: string, - resource: string, - operation: 'read' | 'write', - tags: string[] = [], -): Endpoint { - return { - metadata: { - resource, - operation, - tags, - }, - tool: { - name, - description: `Test endpoint for ${name}`, - inputSchema: { - type: 'object', - properties: { - testParam: { type: 'string' }, - }, - required: ['testParam'], - }, - }, - handler: jest.fn().mockResolvedValue({ success: true }), - }; -} diff --git a/packages/mcp-server/tests/options.test.ts b/packages/mcp-server/tests/options.test.ts index 4d9b60ca..7a2d5114 100644 --- a/packages/mcp-server/tests/options.test.ts +++ b/packages/mcp-server/tests/options.test.ts @@ -1,6 +1,4 @@ import { parseCLIOptions, parseQueryOptions } from '../src/options'; -import { Filter } from '../src/tools'; -import { parseEmbeddedJSON } from '../src/compat'; // Mock process.argv const mockArgv = (args: string[]) => { @@ -12,529 +10,41 @@ const mockArgv = (args: string[]) => { }; describe('parseCLIOptions', () => { - it('should parse basic filter options', () => { - const cleanup = mockArgv([ - '--tool=test-tool', - '--resource=test-resource', - '--operation=read', - '--tag=test-tag', - ]); + it('default parsing should be stdio', () => { + const cleanup = mockArgv([]); const result = parseCLIOptions(); - expect(result.filters).toEqual([ - { type: 'tag', op: 'include', value: 'test-tag' }, - { type: 'resource', op: 'include', value: 'test-resource' }, - { type: 'tool', op: 'include', value: 'test-tool' }, - { type: 'operation', op: 'include', value: 'read' }, - ] as Filter[]); - - expect(result.capabilities).toEqual({}); - - expect(result.list).toBe(false); + expect(result.transport).toBe('stdio'); cleanup(); }); - it('should parse exclusion filters', () => { - const cleanup = mockArgv([ - '--no-tool=exclude-tool', - '--no-resource=exclude-resource', - '--no-operation=write', - '--no-tag=exclude-tag', - ]); + it('using http transport with a port', () => { + const cleanup = mockArgv(['--transport=http', '--port=2222']); const result = parseCLIOptions(); - expect(result.filters).toEqual([ - { type: 'tag', op: 'exclude', value: 'exclude-tag' }, - { type: 'resource', op: 'exclude', value: 'exclude-resource' }, - { type: 'tool', op: 'exclude', value: 'exclude-tool' }, - { type: 'operation', op: 'exclude', value: 'write' }, - ] as Filter[]); - - expect(result.capabilities).toEqual({}); - - cleanup(); - }); - - it('should parse client presets', () => { - const cleanup = mockArgv(['--client=openai-agents']); - - const result = parseCLIOptions(); - - expect(result.client).toEqual('openai-agents'); - - cleanup(); - }); - - it('should parse individual capabilities', () => { - const cleanup = mockArgv([ - '--capability=top-level-unions', - '--capability=valid-json', - '--capability=refs', - '--capability=unions', - '--capability=tool-name-length=40', - ]); - - const result = parseCLIOptions(); - - expect(result.capabilities).toEqual({ - topLevelUnions: true, - validJson: true, - refs: true, - unions: true, - toolNameLength: 40, - }); - - cleanup(); - }); - - it('should handle list option', () => { - const cleanup = mockArgv(['--list']); - - const result = parseCLIOptions(); - - expect(result.list).toBe(true); - - cleanup(); - }); - - it('should handle multiple filters of the same type', () => { - const cleanup = mockArgv(['--tool=tool1', '--tool=tool2', '--resource=res1', '--resource=res2']); - - const result = parseCLIOptions(); - - expect(result.filters).toEqual([ - { type: 'resource', op: 'include', value: 'res1' }, - { type: 'resource', op: 'include', value: 'res2' }, - { type: 'tool', op: 'include', value: 'tool1' }, - { type: 'tool', op: 'include', value: 'tool2' }, - ] as Filter[]); - - cleanup(); - }); - - it('should handle comma-separated values in array options', () => { - const cleanup = mockArgv([ - '--tool=tool1,tool2', - '--resource=res1,res2', - '--capability=top-level-unions,valid-json,unions', - ]); - - const result = parseCLIOptions(); - - expect(result.filters).toEqual([ - { type: 'resource', op: 'include', value: 'res1' }, - { type: 'resource', op: 'include', value: 'res2' }, - { type: 'tool', op: 'include', value: 'tool1' }, - { type: 'tool', op: 'include', value: 'tool2' }, - ] as Filter[]); - - expect(result.capabilities).toEqual({ - topLevelUnions: true, - validJson: true, - unions: true, - }); - - cleanup(); - }); - - it('should handle invalid tool-name-length format', () => { - const cleanup = mockArgv(['--capability=tool-name-length=invalid']); - - // Mock console.error to prevent output during test - const originalError = console.error; - console.error = jest.fn(); - - expect(() => parseCLIOptions()).toThrow(); - - console.error = originalError; - cleanup(); - }); - - it('should handle unknown capability', () => { - const cleanup = mockArgv(['--capability=unknown-capability']); - - // Mock console.error to prevent output during test - const originalError = console.error; - console.error = jest.fn(); - - expect(() => parseCLIOptions()).toThrow(); - - console.error = originalError; + expect(result.transport).toBe('http'); + expect(result.port).toBe(2222); cleanup(); }); }); describe('parseQueryOptions', () => { - const defaultOptions = { - client: undefined, - includeDynamicTools: undefined, - includeCodeTools: undefined, - includeAllTools: undefined, - filters: [], - capabilities: { - topLevelUnions: true, - validJson: true, - refs: true, - unions: true, - formats: true, - toolNameLength: undefined, - }, - }; - - it('should parse basic filter options from query string', () => { - const query = 'tool=test-tool&resource=test-resource&operation=read&tag=test-tag'; - const result = parseQueryOptions(defaultOptions, query); - - expect(result.filters).toEqual([ - { type: 'resource', op: 'include', value: 'test-resource' }, - { type: 'operation', op: 'include', value: 'read' }, - { type: 'tag', op: 'include', value: 'test-tag' }, - { type: 'tool', op: 'include', value: 'test-tool' }, - ]); - - expect(result.capabilities).toEqual({ - topLevelUnions: true, - validJson: true, - refs: true, - unions: true, - formats: true, - toolNameLength: undefined, - }); - }); - - it('should parse exclusion filters from query string', () => { - const query = 'no_tool=exclude-tool&no_resource=exclude-resource&no_operation=write&no_tag=exclude-tag'; - const result = parseQueryOptions(defaultOptions, query); - - expect(result.filters).toEqual([ - { type: 'resource', op: 'exclude', value: 'exclude-resource' }, - { type: 'operation', op: 'exclude', value: 'write' }, - { type: 'tag', op: 'exclude', value: 'exclude-tag' }, - { type: 'tool', op: 'exclude', value: 'exclude-tool' }, - ]); - }); - - it('should parse client option from query string', () => { - const query = 'client=openai-agents'; - const result = parseQueryOptions(defaultOptions, query); - - expect(result.client).toBe('openai-agents'); - }); - - it('should parse client capabilities from query string', () => { - const query = 'capability=top-level-unions&capability=valid-json&capability=tool-name-length%3D40'; - const result = parseQueryOptions(defaultOptions, query); - - expect(result.capabilities).toEqual({ - topLevelUnions: true, - validJson: true, - refs: true, - unions: true, - formats: true, - toolNameLength: 40, - }); - }); - - it('should parse no-capability options from query string', () => { - const query = 'no_capability=top-level-unions&no_capability=refs&no_capability=formats'; - const result = parseQueryOptions(defaultOptions, query); - - expect(result.capabilities).toEqual({ - topLevelUnions: false, - validJson: true, - refs: false, - unions: true, - formats: false, - toolNameLength: undefined, - }); - }); - - it('should parse tools options from query string', () => { - const query = 'tools=dynamic&tools=all'; - const result = parseQueryOptions(defaultOptions, query); - - expect(result.includeDynamicTools).toBe(true); - expect(result.includeAllTools).toBe(true); - }); - - it('should parse no-tools options from query string', () => { - const query = 'tools=dynamic&tools=all&no_tools=dynamic'; - const result = parseQueryOptions(defaultOptions, query); - - expect(result.includeDynamicTools).toBe(false); - expect(result.includeAllTools).toBe(true); - }); - - it('should handle array values in query string', () => { - const query = 'tool[]=tool1&tool[]=tool2&resource[]=res1&resource[]=res2'; - const result = parseQueryOptions(defaultOptions, query); - - expect(result.filters).toEqual([ - { type: 'resource', op: 'include', value: 'res1' }, - { type: 'resource', op: 'include', value: 'res2' }, - { type: 'tool', op: 'include', value: 'tool1' }, - { type: 'tool', op: 'include', value: 'tool2' }, - ]); - }); - - it('should merge with default options', () => { - const defaultWithFilters = { - ...defaultOptions, - filters: [{ type: 'tag' as const, op: 'include' as const, value: 'existing-tag' }], - client: 'cursor' as const, - includeDynamicTools: true, - }; - - const query = 'tool=new-tool&resource=new-resource'; - const result = parseQueryOptions(defaultWithFilters, query); - - expect(result.filters).toEqual([ - { type: 'tag', op: 'include', value: 'existing-tag' }, - { type: 'resource', op: 'include', value: 'new-resource' }, - { type: 'tool', op: 'include', value: 'new-tool' }, - ]); - - expect(result.client).toBe('cursor'); - expect(result.includeDynamicTools).toBe(true); - }); - - it('should override client from default options', () => { - const defaultWithClient = { - ...defaultOptions, - client: 'cursor' as const, - }; + const defaultOptions = {}; - const query = 'client=openai-agents'; - const result = parseQueryOptions(defaultWithClient, query); - - expect(result.client).toBe('openai-agents'); - }); - - it('should merge capabilities with default options', () => { - const defaultWithCapabilities = { - ...defaultOptions, - capabilities: { - topLevelUnions: false, - validJson: false, - refs: true, - unions: true, - formats: true, - toolNameLength: 30, - }, - }; - - const query = 'capability=top-level-unions&no_capability=refs'; - const result = parseQueryOptions(defaultWithCapabilities, query); - - expect(result.capabilities).toEqual({ - topLevelUnions: true, - validJson: false, - refs: false, - unions: true, - formats: true, - toolNameLength: 30, - }); - }); - - it('should handle empty query string', () => { + it('default parsing should be empty', () => { const query = ''; const result = parseQueryOptions(defaultOptions, query); - expect(result).toEqual(defaultOptions); + expect(result).toEqual({}); }); it('should handle invalid query string gracefully', () => { - const query = 'invalid=value&operation=invalid-operation'; + const query = 'invalid=value&tools=invalid-operation'; - // Should throw due to Zod validation for invalid operation + // Should throw due to Zod validation for invalid tools expect(() => parseQueryOptions(defaultOptions, query)).toThrow(); }); - - it('should preserve default undefined values when not specified', () => { - const defaultWithUndefined = { - ...defaultOptions, - client: undefined, - includeDynamicTools: undefined, - includeAllTools: undefined, - }; - - const query = 'tool=test-tool'; - const result = parseQueryOptions(defaultWithUndefined, query); - - expect(result.client).toBeUndefined(); - expect(result.includeDynamicTools).toBeFalsy(); - expect(result.includeAllTools).toBeFalsy(); - }); - - it('should handle complex query with mixed include and exclude filters', () => { - const query = - 'tool=include-tool&no_tool=exclude-tool&resource=include-res&no_resource=exclude-res&operation=read&tag=include-tag&no_tag=exclude-tag'; - const result = parseQueryOptions(defaultOptions, query); - - expect(result.filters).toEqual([ - { type: 'resource', op: 'include', value: 'include-res' }, - { type: 'operation', op: 'include', value: 'read' }, - { type: 'tag', op: 'include', value: 'include-tag' }, - { type: 'tool', op: 'include', value: 'include-tool' }, - { type: 'resource', op: 'exclude', value: 'exclude-res' }, - { type: 'tag', op: 'exclude', value: 'exclude-tag' }, - { type: 'tool', op: 'exclude', value: 'exclude-tool' }, - ]); - }); - - it('code tools are enabled on http servers with default option set', () => { - const query = 'tools=code'; - const result = parseQueryOptions({ ...defaultOptions, includeCodeTools: true }, query); - - expect(result.includeCodeTools).toBe(true); - }); - - it('code tools are prevented on http servers when no default option set', () => { - const query = 'tools=code'; - const result = parseQueryOptions(defaultOptions, query); - - expect(result.includeCodeTools).toBe(undefined); - }); - - it('code tools are prevented on http servers when default option is explicitly false', () => { - const query = 'tools=code'; - const result = parseQueryOptions({ ...defaultOptions, includeCodeTools: false }, query); - - expect(result.includeCodeTools).toBe(false); - }); -}); - -describe('parseEmbeddedJSON', () => { - it('should not change non-string values', () => { - const args = { - numberProp: 42, - booleanProp: true, - objectProp: { nested: 'value' }, - arrayProp: [1, 2, 3], - nullProp: null, - undefinedProp: undefined, - }; - const schema = {}; - - const result = parseEmbeddedJSON(args, schema); - - expect(result).toBe(args); // Should return original object since no changes made - expect(result['numberProp']).toBe(42); - expect(result['booleanProp']).toBe(true); - expect(result['objectProp']).toEqual({ nested: 'value' }); - expect(result['arrayProp']).toEqual([1, 2, 3]); - expect(result['nullProp']).toBe(null); - expect(result['undefinedProp']).toBe(undefined); - }); - - it('should parse valid JSON objects in string properties', () => { - const args = { - jsonObjectString: '{"key": "value", "number": 123}', - regularString: 'not json', - }; - const schema = {}; - - const result = parseEmbeddedJSON(args, schema); - - expect(result).not.toBe(args); // Should return new object since changes were made - expect(result['jsonObjectString']).toEqual({ key: 'value', number: 123 }); - expect(result['regularString']).toBe('not json'); - }); - - it('should leave invalid JSON in string properties unchanged', () => { - const args = { - invalidJson1: '{"key": value}', // Missing quotes around value - invalidJson2: '{key: "value"}', // Missing quotes around key - invalidJson3: '{"key": "value",}', // Trailing comma - invalidJson4: 'just a regular string', - emptyString: '', - }; - const schema = {}; - - const result = parseEmbeddedJSON(args, schema); - - expect(result).toBe(args); // Should return original object since no changes made - expect(result['invalidJson1']).toBe('{"key": value}'); - expect(result['invalidJson2']).toBe('{key: "value"}'); - expect(result['invalidJson3']).toBe('{"key": "value",}'); - expect(result['invalidJson4']).toBe('just a regular string'); - expect(result['emptyString']).toBe(''); - }); - - it('should not parse JSON primitives in string properties', () => { - const args = { - numberString: '123', - floatString: '45.67', - negativeNumberString: '-89', - booleanTrueString: 'true', - booleanFalseString: 'false', - nullString: 'null', - jsonArrayString: '[1, 2, 3, "test"]', - regularString: 'not json', - }; - const schema = {}; - - const result = parseEmbeddedJSON(args, schema); - - expect(result).toBe(args); // Should return original object since no changes made - expect(result['numberString']).toBe('123'); - expect(result['floatString']).toBe('45.67'); - expect(result['negativeNumberString']).toBe('-89'); - expect(result['booleanTrueString']).toBe('true'); - expect(result['booleanFalseString']).toBe('false'); - expect(result['nullString']).toBe('null'); - expect(result['jsonArrayString']).toBe('[1, 2, 3, "test"]'); - expect(result['regularString']).toBe('not json'); - }); - - it('should handle mixed valid objects and other JSON types', () => { - const args = { - validObject: '{"success": true}', - invalidObject: '{"missing": quote}', - validNumber: '42', - validArray: '[1, 2, 3]', - keepAsString: 'hello world', - nonString: 123, - }; - const schema = {}; - - const result = parseEmbeddedJSON(args, schema); - - expect(result).not.toBe(args); // Should return new object since some changes were made - expect(result['validObject']).toEqual({ success: true }); - expect(result['invalidObject']).toBe('{"missing": quote}'); - expect(result['validNumber']).toBe('42'); // Not parsed, remains string - expect(result['validArray']).toBe('[1, 2, 3]'); // Not parsed, remains string - expect(result['keepAsString']).toBe('hello world'); - expect(result['nonString']).toBe(123); - }); - - it('should return original object when no strings are present', () => { - const args = { - number: 42, - boolean: true, - object: { key: 'value' }, - }; - const schema = {}; - - const result = parseEmbeddedJSON(args, schema); - - expect(result).toBe(args); // Should return original object since no changes made - }); - - it('should return original object when all strings are invalid JSON', () => { - const args = { - string1: 'hello', - string2: 'world', - string3: 'not json at all', - }; - const schema = {}; - - const result = parseEmbeddedJSON(args, schema); - - expect(result).toBe(args); // Should return original object since no changes made - }); }); diff --git a/packages/mcp-server/tests/tools.test.ts b/packages/mcp-server/tests/tools.test.ts deleted file mode 100644 index cfff24a2..00000000 --- a/packages/mcp-server/tests/tools.test.ts +++ /dev/null @@ -1,225 +0,0 @@ -import { Endpoint, Filter, Metadata, query } from '../src/tools'; - -describe('Endpoint filtering', () => { - const endpoints: Endpoint[] = [ - endpoint({ - resource: 'user', - operation: 'read', - tags: ['admin'], - toolName: 'retrieve_user', - }), - endpoint({ - resource: 'user.profile', - operation: 'write', - tags: [], - toolName: 'create_user_profile', - }), - endpoint({ - resource: 'user.profile', - operation: 'read', - tags: [], - toolName: 'get_user_profile', - }), - endpoint({ - resource: 'user.roles.permissions', - operation: 'write', - tags: ['admin', 'security'], - toolName: 'update_user_role_permissions', - }), - endpoint({ - resource: 'documents.metadata.tags', - operation: 'write', - tags: ['taxonomy', 'metadata'], - toolName: 'create_document_metadata_tags', - }), - endpoint({ - resource: 'organization.settings', - operation: 'read', - tags: ['admin', 'configuration'], - toolName: 'get_organization_settings', - }), - ]; - - const tests: { name: string; filters: Filter[]; expected: string[] }[] = [ - { - name: 'match none', - filters: [], - expected: [], - }, - - // Resource tests - { - name: 'simple resource', - filters: [{ type: 'resource', op: 'include', value: 'user' }], - expected: ['retrieve_user'], - }, - { - name: 'exclude resource', - filters: [{ type: 'resource', op: 'exclude', value: 'user' }], - expected: [ - 'create_user_profile', - 'get_user_profile', - 'update_user_role_permissions', - 'create_document_metadata_tags', - 'get_organization_settings', - ], - }, - { - name: 'resource and subresources', - filters: [{ type: 'resource', op: 'include', value: 'user*' }], - expected: ['retrieve_user', 'create_user_profile', 'get_user_profile', 'update_user_role_permissions'], - }, - { - name: 'just subresources', - filters: [{ type: 'resource', op: 'include', value: 'user.*' }], - expected: ['create_user_profile', 'get_user_profile', 'update_user_role_permissions'], - }, - { - name: 'specific subresource', - filters: [{ type: 'resource', op: 'include', value: 'user.roles.permissions' }], - expected: ['update_user_role_permissions'], - }, - { - name: 'deep wildcard match', - filters: [{ type: 'resource', op: 'include', value: '*.*.tags' }], - expected: ['create_document_metadata_tags'], - }, - - // Operation tests - { - name: 'read operation', - filters: [{ type: 'operation', op: 'include', value: 'read' }], - expected: ['retrieve_user', 'get_user_profile', 'get_organization_settings'], - }, - { - name: 'write operation', - filters: [{ type: 'operation', op: 'include', value: 'write' }], - expected: ['create_user_profile', 'update_user_role_permissions', 'create_document_metadata_tags'], - }, - { - name: 'resource and operation combined', - filters: [ - { type: 'resource', op: 'include', value: 'user.profile' }, - { type: 'operation', op: 'exclude', value: 'write' }, - ], - expected: ['get_user_profile'], - }, - - // Tag tests - { - name: 'admin tag', - filters: [{ type: 'tag', op: 'include', value: 'admin' }], - expected: ['retrieve_user', 'update_user_role_permissions', 'get_organization_settings'], - }, - { - name: 'taxonomy tag', - filters: [{ type: 'tag', op: 'include', value: 'taxonomy' }], - expected: ['create_document_metadata_tags'], - }, - { - name: 'multiple tags (OR logic)', - filters: [ - { type: 'tag', op: 'include', value: 'admin' }, - { type: 'tag', op: 'include', value: 'security' }, - ], - expected: ['retrieve_user', 'update_user_role_permissions', 'get_organization_settings'], - }, - { - name: 'excluding a tag', - filters: [ - { type: 'tag', op: 'include', value: 'admin' }, - { type: 'tag', op: 'exclude', value: 'security' }, - ], - expected: ['retrieve_user', 'get_organization_settings'], - }, - - // Tool name tests - { - name: 'tool name match', - filters: [{ type: 'tool', op: 'include', value: 'get_organization_settings' }], - expected: ['get_organization_settings'], - }, - { - name: 'two tools match', - filters: [ - { type: 'tool', op: 'include', value: 'get_organization_settings' }, - { type: 'tool', op: 'include', value: 'create_user_profile' }, - ], - expected: ['create_user_profile', 'get_organization_settings'], - }, - { - name: 'excluding tool by name', - filters: [ - { type: 'resource', op: 'include', value: 'user*' }, - { type: 'tool', op: 'exclude', value: 'retrieve_user' }, - ], - expected: ['create_user_profile', 'get_user_profile', 'update_user_role_permissions'], - }, - - // Complex combinations - { - name: 'complex filter: read operations with admin tag', - filters: [ - { type: 'operation', op: 'include', value: 'read' }, - { type: 'tag', op: 'include', value: 'admin' }, - ], - expected: [ - 'retrieve_user', - 'get_user_profile', - 'update_user_role_permissions', - 'get_organization_settings', - ], - }, - { - name: 'complex filter: user resources with no tags', - filters: [ - { type: 'resource', op: 'include', value: 'user.profile' }, - { type: 'tag', op: 'exclude', value: 'admin' }, - ], - expected: ['create_user_profile', 'get_user_profile'], - }, - { - name: 'complex filter: user resources and tags', - filters: [ - { type: 'resource', op: 'include', value: 'user.profile' }, - { type: 'tag', op: 'include', value: 'admin' }, - ], - expected: [ - 'retrieve_user', - 'create_user_profile', - 'get_user_profile', - 'update_user_role_permissions', - 'get_organization_settings', - ], - }, - ]; - - tests.forEach((test) => { - it(`filters by ${test.name}`, () => { - const filtered = query(test.filters, endpoints); - expect(filtered.map((e) => e.tool.name)).toEqual(test.expected); - }); - }); -}); - -function endpoint({ - resource, - operation, - tags, - toolName, -}: { - resource: string; - operation: Metadata['operation']; - tags: string[]; - toolName: string; -}): Endpoint { - return { - metadata: { - resource, - operation, - tags, - }, - tool: { name: toolName, inputSchema: { type: 'object', properties: {} } }, - handler: jest.fn(), - }; -} diff --git a/packages/mcp-server/yarn.lock b/packages/mcp-server/yarn.lock index 38be884f..a592e9c7 100644 --- a/packages/mcp-server/yarn.lock +++ b/packages/mcp-server/yarn.lock @@ -2,136 +2,134 @@ # yarn lockfile v1 -"@ampproject/remapping@^2.2.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" - integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== - dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.24" - -"@anthropic-ai/mcpb@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@anthropic-ai/mcpb/-/mcpb-1.1.0.tgz#1af18de2ab9499d321d6310d0be095f5fef5161b" - integrity sha512-nOnhG1eNpGKSIDv6lt3xsI3w2p2k0D/rPTMGXXugLovCEaJ7svh8XMfCe145vs8qo384t8wKbokWAvx9PkQMDA== +"@anthropic-ai/mcpb@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@anthropic-ai/mcpb/-/mcpb-2.1.2.tgz#cf02801929734b8810961f22e2eb72758c27d527" + integrity sha512-goRbBC8ySo7SWb7tRzr+tL6FxDc4JPTRCdgfD2omba7freofvjq5rom1lBnYHZHo6Mizs1jAHJeN53aZbDoy8A== dependencies: "@inquirer/prompts" "^6.0.1" commander "^13.1.0" fflate "^0.8.2" galactus "^1.0.0" ignore "^7.0.5" - node-forge "^1.3.1" + node-forge "^1.3.2" pretty-bytes "^5.6.0" zod "^3.25.67" + zod-to-json-schema "^3.24.6" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" - integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.28.6.tgz#72499312ec58b1e2245ba4a4f550c132be4982f7" + integrity sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q== dependencies: - "@babel/helper-validator-identifier" "^7.27.1" + "@babel/helper-validator-identifier" "^7.28.5" js-tokens "^4.0.0" picocolors "^1.1.1" -"@babel/compat-data@^7.27.2": - version "7.27.2" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.27.2.tgz#4183f9e642fd84e74e3eea7ffa93a412e3b102c9" - integrity sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ== +"@babel/compat-data@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.28.6.tgz#103f466803fa0f059e82ccac271475470570d74c" + integrity sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg== "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.27.1.tgz#89de51e86bd12246003e3524704c49541b16c3e6" - integrity sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.27.1" - "@babel/generator" "^7.27.1" - "@babel/helper-compilation-targets" "^7.27.1" - "@babel/helper-module-transforms" "^7.27.1" - "@babel/helpers" "^7.27.1" - "@babel/parser" "^7.27.1" - "@babel/template" "^7.27.1" - "@babel/traverse" "^7.27.1" - "@babel/types" "^7.27.1" + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.6.tgz#531bf883a1126e53501ba46eb3bb414047af507f" + integrity sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/generator" "^7.28.6" + "@babel/helper-compilation-targets" "^7.28.6" + "@babel/helper-module-transforms" "^7.28.6" + "@babel/helpers" "^7.28.6" + "@babel/parser" "^7.28.6" + "@babel/template" "^7.28.6" + "@babel/traverse" "^7.28.6" + "@babel/types" "^7.28.6" + "@jridgewell/remapping" "^2.3.5" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.27.1", "@babel/generator@^7.7.2": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.27.1.tgz#862d4fad858f7208edd487c28b58144036b76230" - integrity sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w== +"@babel/generator@^7.28.6", "@babel/generator@^7.7.2": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.6.tgz#48dcc65d98fcc8626a48f72b62e263d25fc3c3f1" + integrity sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw== dependencies: - "@babel/parser" "^7.27.1" - "@babel/types" "^7.27.1" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" + "@babel/parser" "^7.28.6" + "@babel/types" "^7.28.6" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" jsesc "^3.0.2" -"@babel/helper-compilation-targets@^7.27.1": - version "7.27.2" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz#46a0f6efab808d51d29ce96858dd10ce8732733d" - integrity sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ== +"@babel/helper-compilation-targets@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz#32c4a3f41f12ed1532179b108a4d746e105c2b25" + integrity sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA== dependencies: - "@babel/compat-data" "^7.27.2" + "@babel/compat-data" "^7.28.6" "@babel/helper-validator-option" "^7.27.1" browserslist "^4.24.0" lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-module-imports@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204" - integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w== +"@babel/helper-globals@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674" + integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== + +"@babel/helper-module-imports@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz#60632cbd6ffb70b22823187201116762a03e2d5c" + integrity sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw== dependencies: - "@babel/traverse" "^7.27.1" - "@babel/types" "^7.27.1" + "@babel/traverse" "^7.28.6" + "@babel/types" "^7.28.6" -"@babel/helper-module-transforms@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz#e1663b8b71d2de948da5c4fb2a20ca4f3ec27a6f" - integrity sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g== +"@babel/helper-module-transforms@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz#9312d9d9e56edc35aeb6e95c25d4106b50b9eb1e" + integrity sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA== dependencies: - "@babel/helper-module-imports" "^7.27.1" - "@babel/helper-validator-identifier" "^7.27.1" - "@babel/traverse" "^7.27.1" + "@babel/helper-module-imports" "^7.28.6" + "@babel/helper-validator-identifier" "^7.28.5" + "@babel/traverse" "^7.28.6" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.27.1", "@babel/helper-plugin-utils@^7.8.0": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz#ddb2f876534ff8013e6c2b299bf4d39b3c51d44c" - integrity sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw== +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.28.6", "@babel/helper-plugin-utils@^7.8.0": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz#6f13ea251b68c8532e985fd532f28741a8af9ac8" + integrity sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug== "@babel/helper-string-parser@^7.27.1": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== -"@babel/helper-validator-identifier@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" - integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== +"@babel/helper-validator-identifier@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" + integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== "@babel/helper-validator-option@^7.27.1": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== -"@babel/helpers@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.27.1.tgz#ffc27013038607cdba3288e692c3611c06a18aa4" - integrity sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ== +"@babel/helpers@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.28.6.tgz#fca903a313ae675617936e8998b814c415cbf5d7" + integrity sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw== dependencies: - "@babel/template" "^7.27.1" - "@babel/types" "^7.27.1" + "@babel/template" "^7.28.6" + "@babel/types" "^7.28.6" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.27.1", "@babel/parser@^7.27.2": - version "7.27.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.2.tgz#577518bedb17a2ce4212afd052e01f7df0941127" - integrity sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw== +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.6.tgz#f01a8885b7fa1e56dd8a155130226cd698ef13fd" + integrity sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ== dependencies: - "@babel/types" "^7.27.1" + "@babel/types" "^7.28.6" "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -162,11 +160,11 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-import-attributes@^7.24.7": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz#34c017d54496f9b11b61474e7ea3dfd5563ffe07" - integrity sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww== + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz#b71d5914665f60124e133696f17cd7669062c503" + integrity sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw== dependencies: - "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-plugin-utils" "^7.28.6" "@babel/plugin-syntax-import-meta@^7.10.4": version "7.10.4" @@ -183,11 +181,11 @@ "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-jsx@^7.7.2": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz#2f9beb5eff30fa507c5532d107daac7b888fa34c" - integrity sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w== + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz#f8ca28bbd84883b5fea0e447c635b81ba73997ee" + integrity sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w== dependencies: - "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-plugin-utils" "^7.28.6" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" @@ -246,41 +244,41 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.7.2": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz#5147d29066a793450f220c63fa3a9431b7e6dd18" - integrity sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ== - dependencies: - "@babel/helper-plugin-utils" "^7.27.1" - -"@babel/template@^7.27.1", "@babel/template@^7.3.3": - version "7.27.2" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d" - integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== - dependencies: - "@babel/code-frame" "^7.27.1" - "@babel/parser" "^7.27.2" - "@babel/types" "^7.27.1" - -"@babel/traverse@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.1.tgz#4db772902b133bbddd1c4f7a7ee47761c1b9f291" - integrity sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg== - dependencies: - "@babel/code-frame" "^7.27.1" - "@babel/generator" "^7.27.1" - "@babel/parser" "^7.27.1" - "@babel/template" "^7.27.1" - "@babel/types" "^7.27.1" + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz#c7b2ddf1d0a811145b1de800d1abd146af92e3a2" + integrity sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A== + dependencies: + "@babel/helper-plugin-utils" "^7.28.6" + +"@babel/template@^7.28.6", "@babel/template@^7.3.3": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.28.6.tgz#0e7e56ecedb78aeef66ce7972b082fce76a23e57" + integrity sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/parser" "^7.28.6" + "@babel/types" "^7.28.6" + +"@babel/traverse@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.6.tgz#871ddc79a80599a5030c53b1cc48cbe3a5583c2e" + integrity sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/generator" "^7.28.6" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.28.6" + "@babel/template" "^7.28.6" + "@babel/types" "^7.28.6" debug "^4.3.1" - globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.27.1", "@babel/types@^7.3.3": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.1.tgz#9defc53c16fc899e46941fc6901a9eea1c9d8560" - integrity sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q== +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.28.2", "@babel/types@^7.28.6", "@babel/types@^7.3.3": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.6.tgz#c3e9377f1b155005bcc4c46020e7e394e13089df" + integrity sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg== dependencies: "@babel/helper-string-parser" "^7.27.1" - "@babel/helper-validator-identifier" "^7.27.1" + "@babel/helper-validator-identifier" "^7.28.5" "@bcoe/v8-coverage@^0.2.3": version "0.2.3" @@ -300,16 +298,16 @@ "@jridgewell/trace-mapping" "0.3.9" "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": - version "4.7.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz#607084630c6c033992a082de6e6fbc1a8b52175a" - integrity sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw== + version "4.9.1" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz#4e90af67bc51ddee6cdef5284edf572ec376b595" + integrity sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ== dependencies: eslint-visitor-keys "^3.4.3" "@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" - integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== + version "4.12.2" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#bccdf615bcf7b6e8db830ec0b8d21c9a25de597b" + integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew== "@eslint/eslintrc@^2.1.4": version "2.1.4" @@ -331,6 +329,11 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2" integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q== +"@hono/node-server@^1.19.7": + version "1.19.9" + resolved "https://registry.yarnpkg.com/@hono/node-server/-/node-server-1.19.9.tgz#8f37119b1acf283fd3f6035f3d1356fdb97a09ac" + integrity sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw== + "@humanwhocodes/config-array@^0.13.0": version "0.13.0" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748" @@ -696,13 +699,20 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" -"@jridgewell/gen-mapping@^0.3.5": - version "0.3.8" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142" - integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== +"@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.5": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f" + integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/remapping@^2.3.5": + version "2.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/remapping/-/remapping-2.3.5.tgz#375c476d1972947851ba1e15ae8f123047445aa1" + integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" "@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": @@ -710,15 +720,10 @@ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" - integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== "@jridgewell/trace-mapping@0.3.9": version "0.3.9" @@ -728,19 +733,20 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": - version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.28": + version "0.3.31" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== dependencies: "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@modelcontextprotocol/sdk@^1.24.0": - version "1.24.3" - resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.24.3.tgz#81a3fcc919cb4ce8630e2bcecf59759176eb331a" - integrity sha512-YgSHW29fuzKKAHTGe9zjNoo+yF8KaQPzDC2W9Pv41E7/57IfY+AMGJ/aDFlgTLcVVELoggKE4syABCE75u3NCw== +"@modelcontextprotocol/sdk@^1.25.2": + version "1.25.2" + resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.25.2.tgz#2284560b4e044b4ce5f328ee180931110cb8c5cf" + integrity sha512-LZFeo4F9M5qOhC/Uc1aQSrBHxMrvxett+9KLHt7OhcExtoiRN9DKgbZffMP/nxjutWDQpfMDfP3nkHI4X9ijww== dependencies: + "@hono/node-server" "^1.19.7" ajv "^8.17.1" ajv-formats "^3.0.1" content-type "^1.0.5" @@ -751,6 +757,7 @@ express "^5.0.1" express-rate-limit "^7.5.0" jose "^6.1.1" + json-schema-typed "^8.0.2" pkce-challenge "^5.0.0" raw-body "^3.0.0" zod "^3.25 || ^4.0" @@ -777,10 +784,10 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@pkgr/core@^0.2.3": - version "0.2.4" - resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.4.tgz#d897170a2b0ba51f78a099edccd968f7b103387c" - integrity sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw== +"@pkgr/core@^0.2.9": + version "0.2.9" + resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.9.tgz#d229a7b7f9dac167a156992ef23c7f023653f53b" + integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA== "@sinclair/typebox@^0.27.8": version "0.27.8" @@ -812,9 +819,9 @@ path-browserify "^1.0.1" "@tsconfig/node10@^1.0.7": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" - integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== + version "1.0.12" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.12.tgz#be57ceac1e4692b41be9de6be8c32a106636dba4" + integrity sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ== "@tsconfig/node12@^1.0.7": version "1.0.11" @@ -858,11 +865,11 @@ "@babel/types" "^7.0.0" "@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.7.tgz#968cdc2366ec3da159f61166428ee40f370e56c2" - integrity sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng== + version "7.28.0" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.28.0.tgz#07d713d6cce0d265c9849db0cbe62d3f61f36f74" + integrity sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q== dependencies: - "@babel/types" "^7.20.7" + "@babel/types" "^7.28.2" "@types/body-parser@*": version "1.19.6" @@ -887,9 +894,9 @@ "@types/node" "*" "@types/express-serve-static-core@^5.0.0": - version "5.0.7" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz#2fa94879c9d46b11a5df4c74ac75befd6b283de6" - integrity sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ== + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz#1a77faffee9572d39124933259be2523837d7eaa" + integrity sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A== dependencies: "@types/node" "*" "@types/qs" "*" @@ -897,13 +904,13 @@ "@types/send" "*" "@types/express@^5.0.3": - version "5.0.3" - resolved "https://registry.yarnpkg.com/@types/express/-/express-5.0.3.tgz#6c4bc6acddc2e2a587142e1d8be0bce20757e956" - integrity sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw== + version "5.0.6" + resolved "https://registry.yarnpkg.com/@types/express/-/express-5.0.6.tgz#2d724b2c990dcb8c8444063f3580a903f6d500cc" + integrity sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA== dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "^5.0.0" - "@types/serve-static" "*" + "@types/serve-static" "^2" "@types/graceful-fs@^4.1.3": version "4.1.9" @@ -944,11 +951,6 @@ expect "^29.0.0" pretty-format "^29.0.0" -"@types/mime@^1": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" - integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== - "@types/mute-stream@^0.0.4": version "0.0.4" resolved "https://registry.yarnpkg.com/@types/mute-stream/-/mute-stream-0.0.4.tgz#77208e56a08767af6c5e1237be8888e2f255c478" @@ -957,16 +959,16 @@ "@types/node" "*" "@types/node@*": - version "22.15.17" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.15.17.tgz#355ccec95f705b664e4332bb64a7f07db30b7055" - integrity sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw== + version "25.0.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-25.0.8.tgz#e54e00f94fe1db2497b3e42d292b8376a2678c8d" + integrity sha512-powIePYMmC3ibL0UJ2i2s0WIbq6cg6UyVFQxSCpaPxxzAaziRfimGivjdF943sSGV6RADVbk0Nvlm5P/FB44Zg== dependencies: - undici-types "~6.21.0" + undici-types "~7.16.0" "@types/node@^22.5.5": - version "22.19.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.19.2.tgz#2f0956fba46518aaf7578c84e37bddab55f85d01" - integrity sha512-LPM2G3Syo1GLzXLGJAKdqoU35XvrWzGJ21/7sgZTUpbkBaOasTj8tjwn6w+hCkqaa1TfJ/w67rJSwYItlJ2mYw== + version "22.19.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.19.6.tgz#0e9d80ebcd2dfce03265768c17a1212d4eb07e82" + integrity sha512-qm+G8HuG6hOHQigsi7VGuLjUVu6TtBo/F05zvX04Mw2uCg9Dv0Qxy3Qw7j41SidlTcl5D/5yg0SEZqOB+EqZnQ== dependencies: undici-types "~6.21.0" @@ -981,21 +983,19 @@ integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== "@types/send@*": - version "0.17.5" - resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.5.tgz#d991d4f2b16f2b1ef497131f00a9114290791e74" - integrity sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w== + version "1.2.1" + resolved "https://registry.yarnpkg.com/@types/send/-/send-1.2.1.tgz#6a784e45543c18c774c049bff6d3dbaf045c9c74" + integrity sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ== dependencies: - "@types/mime" "^1" "@types/node" "*" -"@types/serve-static@*": - version "1.15.8" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.8.tgz#8180c3fbe4a70e8f00b9f70b9ba7f08f35987877" - integrity sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg== +"@types/serve-static@^2": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-2.2.0.tgz#d4a447503ead0d1671132d1ab6bd58b805d8de6a" + integrity sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ== dependencies: "@types/http-errors" "*" "@types/node" "*" - "@types/send" "*" "@types/stack-utils@^2.0.0": version "2.0.3" @@ -1013,9 +1013,9 @@ integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== "@types/yargs@^17.0.8": - version "17.0.33" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.33.tgz#8c32303da83eec050a84b3c7ae7b9f922d13e32d" - integrity sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA== + version "17.0.35" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.35.tgz#07013e46aa4d7d7d50a49e15604c1c5340d4eb24" + integrity sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg== dependencies: "@types/yargs-parser" "*" @@ -1131,9 +1131,9 @@ acorn-walk@^8.1.1: acorn "^8.11.0" acorn@^8.11.0, acorn@^8.4.1, acorn@^8.9.0: - version "8.14.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" - integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== + version "8.15.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== aggregate-error@^3.0.0: version "3.1.0" @@ -1219,11 +1219,6 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -async@^3.2.3: - version "3.2.6" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" - integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== - babel-jest@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" @@ -1259,9 +1254,9 @@ babel-plugin-jest-hoist@^29.6.3: "@types/babel__traverse" "^7.0.6" babel-preset-current-node-syntax@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz#9a929eafece419612ef4ae4f60b1862ebad8ef30" - integrity sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw== + version "1.2.0" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz#20730d6cdc7dda5d89401cab10ac6a32067acde6" + integrity sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg== dependencies: "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-bigint" "^7.8.3" @@ -1292,33 +1287,38 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -body-parser@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-2.2.0.tgz#f7a9656de305249a715b549b7b8fd1ab9dfddcfa" - integrity sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg== +baseline-browser-mapping@^2.9.0: + version "2.9.14" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz#3b6af0bc032445bca04de58caa9a87cfe921cbb3" + integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== + +body-parser@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-2.2.2.tgz#1a32cdb966beaf68de50a9dfbe5b58f83cb8890c" + integrity sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA== dependencies: bytes "^3.1.2" content-type "^1.0.5" - debug "^4.4.0" + debug "^4.4.3" http-errors "^2.0.0" - iconv-lite "^0.6.3" + iconv-lite "^0.7.0" on-finished "^2.4.1" - qs "^6.14.0" - raw-body "^3.0.0" - type-is "^2.0.0" + qs "^6.14.1" + raw-body "^3.0.1" + type-is "^2.0.1" brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + version "1.1.12" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + version "2.0.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== dependencies: balanced-match "^1.0.0" @@ -1330,14 +1330,15 @@ braces@^3.0.3: fill-range "^7.1.1" browserslist@^4.24.0: - version "4.24.5" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.5.tgz#aa0f5b8560fe81fde84c6dcb38f759bafba0e11b" - integrity sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw== + version "4.28.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.1.tgz#7f534594628c53c63101079e27e40de490456a95" + integrity sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA== dependencies: - caniuse-lite "^1.0.30001716" - electron-to-chromium "^1.5.149" - node-releases "^2.0.19" - update-browserslist-db "^1.1.3" + baseline-browser-mapping "^2.9.0" + caniuse-lite "^1.0.30001759" + electron-to-chromium "^1.5.263" + node-releases "^2.0.27" + update-browserslist-db "^1.2.0" bs-logger@^0.2.6: version "0.2.6" @@ -1358,7 +1359,7 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -bytes@3.1.2, bytes@^3.1.2: +bytes@^3.1.2, bytes@~3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== @@ -1394,12 +1395,12 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001716: - version "1.0.30001717" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001717.tgz#5d9fec5ce09796a1893013825510678928aca129" - integrity sha512-auPpttCq6BDEG8ZAuHJIplGw6GODhjw+/11e7IjpnYCxZcW/ONgPs0KVBJ0d1bY3e2+7PRe5RCLyP+PfwVgkYw== +caniuse-lite@^1.0.30001759: + version "1.0.30001764" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz#03206c56469f236103b90f9ae10bcb8b9e1f6005" + integrity sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g== -chalk@^4.0.0, chalk@^4.0.2: +chalk@^4.0.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -1457,9 +1458,9 @@ code-block-writer@^12.0.0: integrity sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w== collect-v8-coverage@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" - integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== + version "1.0.3" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz#cc1f01eb8d02298cbc9a437c74c70ab4e5210b80" + integrity sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw== color-convert@^2.0.1: version "2.0.1" @@ -1484,11 +1485,9 @@ concat-map@0.0.1: integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== content-disposition@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-1.0.0.tgz#844426cb398f934caefcbb172200126bc7ceace2" - integrity sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg== - dependencies: - safe-buffer "5.2.1" + version "1.0.1" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-1.0.1.tgz#a8b7bbeb2904befdfb6787e5c0c086959f605f9b" + integrity sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q== content-type@^1.0.5: version "1.0.5" @@ -1545,17 +1544,17 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3, cross-spawn@^7.0.5: shebang-command "^2.0.0" which "^2.0.1" -debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5, debug@^4.3.7, debug@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" - integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.7, debug@^4.4.0, debug@^4.4.3: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== dependencies: ms "^2.1.3" dedent@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.6.0.tgz#79d52d6389b1ffa67d2bcef59ba51847a9d503b2" - integrity sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA== + version "1.7.1" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.7.1.tgz#364661eea3d73f3faba7089214420ec2f8f13e15" + integrity sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg== deep-is@^0.1.3: version "0.1.4" @@ -1567,7 +1566,7 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== -depd@2.0.0, depd@^2.0.0: +depd@^2.0.0, depd@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== @@ -1608,17 +1607,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -ejs@^3.1.10: - version "3.1.10" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b" - integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA== - dependencies: - jake "^10.8.5" - -electron-to-chromium@^1.5.149: - version "1.5.151" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.151.tgz#5edd6c17e1b2f14b4662c41b9379f96cc8c2bb7c" - integrity sha512-Rl6uugut2l9sLojjS4H4SAr3A4IgACMLgpuEMPYCVcKydzfyPrn5absNRju38IhQOf/NwjJY8OGWjlteqYeBCA== +electron-to-chromium@^1.5.263: + version "1.5.267" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz#5d84f2df8cdb6bfe7e873706bb21bd4bfb574dc7" + integrity sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw== emittery@^0.13.1: version "0.13.1" @@ -1636,9 +1628,9 @@ encodeurl@^2.0.0: integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + version "1.3.4" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414" + integrity sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ== dependencies: is-arrayish "^0.2.1" @@ -1680,12 +1672,12 @@ escape-string-regexp@^4.0.0: integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== eslint-plugin-prettier@^5.0.1: - version "5.4.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.0.tgz#54d4748904e58eaf1ffe26c4bffa4986ca7f952b" - integrity sha512-BvQOvUhkVQM1i63iMETK9Hjud9QhqBnbtT1Zc642p9ynzBuCe5pybkOnvqZIBypXmMlsGcnU4HZ8sCTPfpAexA== + version "5.5.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz#9eae11593faa108859c26f9a9c367d619a0769c0" + integrity sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw== dependencies: - prettier-linter-helpers "^1.0.0" - synckit "^0.11.0" + prettier-linter-helpers "^1.0.1" + synckit "^0.11.12" eslint-plugin-unused-imports@^3.0.0: version "3.2.0" @@ -1713,9 +1705,9 @@ eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== eslint-visitor-keys@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" - integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" + integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== eslint@^8.49.0: version "8.57.1" @@ -1776,9 +1768,9 @@ esprima@^4.0.0: integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.4.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" - integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + version "1.7.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.7.0.tgz#08d048f261f0ddedb5bae95f46809463d9c9496d" + integrity sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g== dependencies: estraverse "^5.1.0" @@ -1804,15 +1796,10 @@ etag@^1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -eventsource-parser@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-3.0.3.tgz#e9af1d40b77e6268cdcbc767321e8b9f066adea8" - integrity sha512-nVpZkTMM9rF6AQ9gPJpFsNAMt48wIzB5TQgiTLdHiuO8XEDhUgZEhqKlZWXbIzo9VmJ/HvysHqEaVeD5v9TPvA== - -eventsource-parser@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-3.0.1.tgz#5e358dba9a55ba64ca90da883c4ca35bd82467bd" - integrity sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA== +eventsource-parser@^3.0.0, eventsource-parser@^3.0.1: + version "3.0.6" + resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-3.0.6.tgz#292e165e34cacbc936c3c92719ef326d4aeb4e90" + integrity sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg== eventsource@^3.0.2: version "3.0.7" @@ -1853,22 +1840,23 @@ expect@^29.0.0, expect@^29.7.0: jest-util "^29.7.0" express-rate-limit@^7.5.0: - version "7.5.0" - resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-7.5.0.tgz#6a67990a724b4fbbc69119419feef50c51e8b28f" - integrity sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg== + version "7.5.1" + resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-7.5.1.tgz#8c3a42f69209a3a1c969890070ece9e20a879dec" + integrity sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw== express@^5.0.1, express@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/express/-/express-5.1.0.tgz#d31beaf715a0016f0d53f47d3b4d7acf28c75cc9" - integrity sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA== + version "5.2.1" + resolved "https://registry.yarnpkg.com/express/-/express-5.2.1.tgz#8f21d15b6d327f92b4794ecf8cb08a72f956ac04" + integrity sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw== dependencies: accepts "^2.0.0" - body-parser "^2.2.0" + body-parser "^2.2.1" content-disposition "^1.0.0" content-type "^1.0.5" cookie "^0.7.1" cookie-signature "^1.2.1" debug "^4.4.0" + depd "^2.0.0" encodeurl "^2.0.0" escape-html "^1.0.3" etag "^1.8.1" @@ -1936,9 +1924,9 @@ fast-uri@^3.0.1: integrity sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA== fastq@^1.6.0: - version "1.19.1" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" - integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== + version "1.20.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.20.1.tgz#ca750a10dc925bc8b18839fd203e3ef4b3ced675" + integrity sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw== dependencies: reusify "^1.0.4" @@ -1961,13 +1949,6 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" -filelist@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5" - integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q== - dependencies: - minimatch "^5.0.1" - fill-range@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" @@ -1976,9 +1957,9 @@ fill-range@^7.1.1: to-regex-range "^5.0.1" finalhandler@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-2.1.0.tgz#72306373aa89d05a8242ed569ed86a1bff7c561f" - integrity sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q== + version "2.1.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-2.1.1.tgz#a2c517a6559852bcdb06d1f8bd7f51b68fad8099" + integrity sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA== dependencies: debug "^4.4.0" encodeurl "^2.0.0" @@ -2148,11 +2129,6 @@ glob@^7.1.3, glob@^7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - globals@^13.19.0: version "13.24.0" resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" @@ -2175,6 +2151,18 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +handlebars@^4.7.8: + version "4.7.8" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" + integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== + dependencies: + minimist "^1.2.5" + neo-async "^2.6.2" + source-map "^0.6.1" + wordwrap "^1.0.0" + optionalDependencies: + uglify-js "^3.1.4" + has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" @@ -2197,29 +2185,22 @@ html-escaper@^2.0.0: resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -http-errors@2.0.0, http-errors@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== +http-errors@^2.0.0, http-errors@^2.0.1, http-errors@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.1.tgz#36d2f65bc909c8790018dd36fb4d93da6caae06b" + integrity sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ== dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" + depd "~2.0.0" + inherits "~2.0.4" + setprototypeof "~1.2.0" + statuses "~2.0.2" + toidentifier "~1.0.1" human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -iconv-lite@0.6.3, iconv-lite@^0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" - integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== - dependencies: - safer-buffer ">= 2.1.2 < 3.0.0" - iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -2227,6 +2208,13 @@ iconv-lite@^0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@^0.7.0, iconv-lite@~0.7.0: + version "0.7.2" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.7.2.tgz#d0bdeac3f12b4835b7359c2ad89c422a4d1cc72e" + integrity sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + ignore@^5.2.0, ignore@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" @@ -2271,7 +2259,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.3: +inherits@2, inherits@^2.0.3, inherits@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -2286,7 +2274,7 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== -is-core-module@^2.16.0: +is-core-module@^2.16.1: version "2.16.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== @@ -2386,23 +2374,13 @@ istanbul-lib-source-maps@^4.0.0: source-map "^0.6.1" istanbul-reports@^3.1.3: - version "3.1.7" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" - integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.2.0.tgz#cb4535162b5784aa623cee21a7252cf2c807ac93" + integrity sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jake@^10.8.5: - version "10.9.2" - resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.2.tgz#6ae487e6a69afec3a5e167628996b59f35ae2b7f" - integrity sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA== - dependencies: - async "^3.2.3" - chalk "^4.0.2" - filelist "^1.0.4" - minimatch "^3.1.2" - jest-changed-files@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" @@ -2703,7 +2681,7 @@ jest-snapshot@^29.7.0: pretty-format "^29.7.0" semver "^7.5.3" -jest-util@^29.0.0, jest-util@^29.7.0: +jest-util@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== @@ -2776,17 +2754,17 @@ js-tokens@^4.0.0: integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + version "3.14.2" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.2.tgz#77485ce1dd7f33c061fd1b16ecea23b55fcb04b0" + integrity sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg== dependencies: argparse "^1.0.7" esprima "^4.0.0" js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + version "4.1.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" + integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== dependencies: argparse "^2.0.1" @@ -2815,6 +2793,11 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== +json-schema-typed@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/json-schema-typed/-/json-schema-typed-8.0.2.tgz#e98ee7b1899ff4a184534d1f167c288c66bbeff4" + integrity sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" @@ -2952,10 +2935,10 @@ mime-db@^1.54.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5" integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ== -mime-types@^3.0.0, mime-types@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-3.0.1.tgz#b1d94d6997a9b32fd69ebaed0db73de8acb519ce" - integrity sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA== +mime-types@^3.0.0, mime-types@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-3.0.2.tgz#39002d4182575d5af036ffa118100f2524b2e2ab" + integrity sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A== dependencies: mime-db "^1.54.0" @@ -2971,13 +2954,6 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" -minimatch@^5.0.1: - version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== - dependencies: - brace-expansion "^2.0.1" - minimatch@^7.4.3: version "7.4.6" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-7.4.6.tgz#845d6f254d8f4a5e4fd6baf44d5f10c8448365fb" @@ -2992,7 +2968,7 @@ minimatch@^9.0.4: dependencies: brace-expansion "^2.0.1" -minimist@^1.2.6: +minimist@^1.2.5, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -3022,7 +2998,12 @@ negotiator@^1.0.0: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a" integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg== -node-forge@^1.3.1: +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +node-forge@^1.3.2: version "1.3.3" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.3.tgz#0ad80f6333b3a0045e827ac20b7f735f93716751" integrity sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg== @@ -3032,10 +3013,10 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== -node-releases@^2.0.19: - version "2.0.19" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" - integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== +node-releases@^2.0.27: + version "2.0.27" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.27.tgz#eedca519205cf20f650f61d56b070db111231e4e" + integrity sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA== normalize-path@^3.0.0: version "3.0.0" @@ -3192,9 +3173,9 @@ path-parse@^1.0.7: integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== path-to-regexp@^8.0.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.2.0.tgz#73990cc29e57a3ff2a0d914095156df5db79e8b4" - integrity sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ== + version "8.3.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.3.0.tgz#aa818a6981f99321003a08987d3cec9c3474cd1f" + integrity sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA== picocolors@^1.1.1: version "1.1.1" @@ -3212,9 +3193,9 @@ pirates@^4.0.4: integrity sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA== pkce-challenge@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/pkce-challenge/-/pkce-challenge-5.0.0.tgz#c3a405cb49e272094a38e890a2b51da0228c4d97" - integrity sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ== + version "5.0.1" + resolved "https://registry.yarnpkg.com/pkce-challenge/-/pkce-challenge-5.0.1.tgz#3b4446865b17b1745e9ace2016a31f48ddf6230d" + integrity sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ== pkg-dir@^4.2.0: version "4.2.0" @@ -3228,17 +3209,17 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== +prettier-linter-helpers@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz#6a31f88a4bad6c7adda253de12ba4edaea80ebcd" + integrity sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg== dependencies: fast-diff "^1.1.2" prettier@^3.0.0: - version "3.5.3" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.5.3.tgz#4fc2ce0d657e7a02e602549f053b239cb7dfe1b5" - integrity sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw== + version "3.7.4" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.7.4.tgz#d2f8335d4b1cec47e1c8098645411b0c9dff9c0f" + integrity sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA== pretty-bytes@^5.6.0: version "5.6.0" @@ -3280,10 +3261,10 @@ pure-rand@^6.0.0: resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2" integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== -qs@^6.14.0: - version "6.14.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.0.tgz#c63fa40680d2c5c941412a0e899c89af60c0a930" - integrity sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w== +qs@^6.14.0, qs@^6.14.1: + version "6.14.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.1.tgz#a41d85b9d3902f31d27861790506294881871159" + integrity sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ== dependencies: side-channel "^1.1.0" @@ -3297,15 +3278,15 @@ range-parser@^1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-3.0.0.tgz#25b3476f07a51600619dae3fe82ddc28a36e5e0f" - integrity sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g== +raw-body@^3.0.0, raw-body@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-3.0.2.tgz#3e3ada5ae5568f9095d84376fd3a49b8fb000a51" + integrity sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA== dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.6.3" - unpipe "1.0.0" + bytes "~3.1.2" + http-errors "~2.0.1" + iconv-lite "~0.7.0" + unpipe "~1.0.0" react-is@^18.0.0: version "18.3.1" @@ -3321,6 +3302,9 @@ readable-stream@^3.4.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +"replicate@file:../../dist": + version "2.0.0-alpha.74" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -3354,11 +3338,11 @@ resolve.exports@^2.0.0: integrity sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A== resolve@^1.20.0: - version "1.22.10" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" - integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== + version "1.22.11" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.11.tgz#aad857ce1ffb8bfa9b0b1ac29f1156383f68c262" + integrity sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ== dependencies: - is-core-module "^2.16.0" + is-core-module "^2.16.1" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -3392,7 +3376,7 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -safe-buffer@5.2.1, safe-buffer@~5.2.0: +safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -3407,39 +3391,39 @@ semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.7.1: - version "7.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" - integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== +semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.7.3: + version "7.7.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" + integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== send@^1.1.0, send@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/send/-/send-1.2.0.tgz#32a7554fb777b831dfa828370f773a3808d37212" - integrity sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw== + version "1.2.1" + resolved "https://registry.yarnpkg.com/send/-/send-1.2.1.tgz#9eab743b874f3550f40a26867bf286ad60d3f3ed" + integrity sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ== dependencies: - debug "^4.3.5" + debug "^4.4.3" encodeurl "^2.0.0" escape-html "^1.0.3" etag "^1.8.1" fresh "^2.0.0" - http-errors "^2.0.0" - mime-types "^3.0.1" + http-errors "^2.0.1" + mime-types "^3.0.2" ms "^2.1.3" on-finished "^2.4.1" range-parser "^1.2.1" - statuses "^2.0.1" + statuses "^2.0.2" serve-static@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-2.2.0.tgz#9c02564ee259bdd2251b82d659a2e7e1938d66f9" - integrity sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ== + version "2.2.1" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-2.2.1.tgz#7f186a4a4e5f5b663ad7a4294ff1bf37cf0e98a9" + integrity sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw== dependencies: encodeurl "^2.0.0" escape-html "^1.0.3" parseurl "^1.3.3" send "^1.2.0" -setprototypeof@1.2.0: +setprototypeof@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== @@ -3541,10 +3525,10 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" -statuses@2.0.1, statuses@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== +statuses@^2.0.1, statuses@^2.0.2, statuses@~2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.2.tgz#8f75eecef765b5e1cfcdc080da59409ed424e382" + integrity sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw== string-length@^4.0.1: version "4.0.2" @@ -3628,13 +3612,12 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -synckit@^0.11.0: - version "0.11.4" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.4.tgz#48972326b59723fc15b8d159803cf8302b545d59" - integrity sha512-Q/XQKRaJiLiFIBNN+mndW7S/RHxvwzuZS6ZwmRzUBqJBv/5QIKCEwkBC8GBf8EQJKYnaFs0wOZbKTXBPj8L9oQ== +synckit@^0.11.12: + version "0.11.12" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.12.tgz#abe74124264fbc00a48011b0d98bdc1cffb64a7b" + integrity sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ== dependencies: - "@pkgr/core" "^0.2.3" - tslib "^2.8.1" + "@pkgr/core" "^0.2.9" test-exclude@^6.0.0: version "6.0.0" @@ -3669,30 +3652,29 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -toidentifier@1.0.1: +toidentifier@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== ts-api-utils@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz#595f7094e46eed364c13fd23e75f9513d29baf91" - integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ== + version "2.4.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.4.0.tgz#2690579f96d2790253bdcf1ca35d569ad78f9ad8" + integrity sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA== ts-jest@^29.1.0: - version "29.3.2" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.3.2.tgz#0576cdf0a507f811fe73dcd16d135ce89f8156cb" - integrity sha512-bJJkrWc6PjFVz5g2DGCNUo8z7oFEYaz1xP1NpeDU7KNLMWPpEyV8Chbpkn8xjzgRDpQhnGMyvyldoL7h8JXyug== + version "29.4.6" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.4.6.tgz#51cb7c133f227396818b71297ad7409bb77106e9" + integrity sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA== dependencies: bs-logger "^0.2.6" - ejs "^3.1.10" fast-json-stable-stringify "^2.1.0" - jest-util "^29.0.0" + handlebars "^4.7.8" json5 "^2.2.3" lodash.memoize "^4.1.2" make-error "^1.3.6" - semver "^7.7.1" - type-fest "^4.39.1" + semver "^7.7.3" + type-fest "^4.41.0" yargs-parser "^21.1.1" ts-morph@^19.0.0: @@ -3773,12 +3755,12 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== -type-fest@^4.39.1: +type-fest@^4.41.0: version "4.41.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.41.0.tgz#6ae1c8e5731273c2bf1f58ad39cbae2c91a46c58" integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA== -type-is@^2.0.0, type-is@^2.0.1: +type-is@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/type-is/-/type-is-2.0.1.tgz#64f6cf03f92fce4015c2b224793f6bdd4b068c97" integrity sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw== @@ -3792,25 +3774,35 @@ typescript@5.8.3: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e" integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== +uglify-js@^3.1.4: + version "3.19.3" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.19.3.tgz#82315e9bbc6f2b25888858acd1fff8441035b77f" + integrity sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ== + undici-types@~6.21.0: version "6.21.0" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== +undici-types@~7.16.0: + version "7.16.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.16.0.tgz#ffccdff36aea4884cbfce9a750a0580224f58a46" + integrity sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw== + universalify@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== -unpipe@1.0.0: +unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -update-browserslist-db@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420" - integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== +update-browserslist-db@^1.2.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz#64d76db58713136acbeb4c49114366cc6cc2e80d" + integrity sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w== dependencies: escalade "^3.2.0" picocolors "^1.1.1" @@ -3865,6 +3857,11 @@ word-wrap@^1.2.5: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== +wordwrap@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== + wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -3939,25 +3936,20 @@ yoctocolors-cjs@^2.1.2: resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz#7e4964ea8ec422b7a40ac917d3a344cfd2304baa" integrity sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw== -zod-to-json-schema@^3.24.5: - version "3.24.5" - resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz#d1095440b147fb7c2093812a53c54df8d5df50a3" - integrity sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g== - -zod-to-json-schema@^3.25.0: - version "3.25.0" - resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.25.0.tgz#df504c957c4fb0feff467c74d03e6aab0b013e1c" - integrity sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ== +zod-to-json-schema@^3.24.5, zod-to-json-schema@^3.24.6, zod-to-json-schema@^3.25.0: + version "3.25.1" + resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz#7f24962101a439ddade2bf1aeab3c3bfec7d84ba" + integrity sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA== zod-validation-error@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/zod-validation-error/-/zod-validation-error-4.0.1.tgz#a105723eb40299578a6a38cb86647068f6d005b1" - integrity sha512-F3rdaCOHs5ViJ5YTz5zzRtfkQdMdIeKudJAoxy7yB/2ZMEHw73lmCAcQw11r7++20MyGl4WV59EVh7A9rNAyog== + version "4.0.2" + resolved "https://registry.yarnpkg.com/zod-validation-error/-/zod-validation-error-4.0.2.tgz#bc605eba49ce0fcd598c127fee1c236be3f22918" + integrity sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ== "zod@^3.25 || ^4.0": - version "4.1.13" - resolved "https://registry.yarnpkg.com/zod/-/zod-4.1.13.tgz#93699a8afe937ba96badbb0ce8be6033c0a4b6b1" - integrity sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig== + version "4.3.5" + resolved "https://registry.yarnpkg.com/zod/-/zod-4.3.5.tgz#aeb269a6f9fc259b1212c348c7c5432aaa474d2a" + integrity sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g== zod@^3.25.20, zod@^3.25.67: version "3.25.76" diff --git a/src/resources/plans.ts b/src/resources/plans.ts index a61a3811..7f5e3a52 100644 --- a/src/resources/plans.ts +++ b/src/resources/plans.ts @@ -19,8 +19,7 @@ export class Plans extends APIResource { } /** - * list all available plans, note this endpoint is currently unpaginated unlike all - * other list endpoints. + * List all available insurance plans that tenants can be enrolled in. * * @example * ```ts @@ -36,7 +35,7 @@ export interface Plan { description: string; /** - * the plans name/code, this is used when creating enrollments. + * the plan's name/code, this is used when creating enrollments. */ name: string; diff --git a/tests/api-resources/enrollments.test.ts b/tests/api-resources/enrollments.test.ts index 73c108d9..2a804963 100644 --- a/tests/api-resources/enrollments.test.ts +++ b/tests/api-resources/enrollments.test.ts @@ -67,7 +67,11 @@ describe('resource enrollments', () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( client.enrollments.list( - { page: 1, propertyManagerId: 1, size: 1 }, + { + page: 1, + propertyManagerId: 1, + size: 1, + }, { path: '/_stainless_unknown_path' }, ), ).rejects.toThrow(Beagle.NotFoundError); diff --git a/tests/api-resources/property-managers.test.ts b/tests/api-resources/property-managers.test.ts index 28de7542..c530d853 100644 --- a/tests/api-resources/property-managers.test.ts +++ b/tests/api-resources/property-managers.test.ts @@ -11,8 +11,22 @@ describe('resource propertyManagers', () => { // Prism tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.propertyManagers.create({ - addresses: [{ city: 'city', state: 'xx', street1: 'street1', zip: '60513', kind: 'billing' }], - contacts: [{ email: 'dev@stainless.com', name: { first: 'first', last: 'last' }, kind: 'agreements' }], + addresses: [ + { + city: 'city', + state: 'xx', + street1: 'street1', + zip: '60513', + kind: 'billing', + }, + ], + contacts: [ + { + email: 'dev@stainless.com', + name: { first: 'first', last: 'last' }, + kind: 'agreements', + }, + ], name: 'name', }); const rawResponse = await responsePromise.asResponse(); @@ -28,7 +42,14 @@ describe('resource propertyManagers', () => { test.skip('create: required and optional params', async () => { const response = await client.propertyManagers.create({ addresses: [ - { city: 'city', state: 'xx', street1: 'street1', zip: '60513', street2: 'street2', kind: 'billing' }, + { + city: 'city', + state: 'xx', + street1: 'street1', + zip: '60513', + street2: 'street2', + kind: 'billing', + }, ], contacts: [ { diff --git a/tests/api-resources/tenants.test.ts b/tests/api-resources/tenants.test.ts index ea1eb026..dec6b749 100644 --- a/tests/api-resources/tenants.test.ts +++ b/tests/api-resources/tenants.test.ts @@ -11,8 +11,16 @@ describe('resource tenants', () => { // Prism tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.tenants.create({ - address: { city: 'city', state: 'xx', street1: 'street1', zip: '60513' }, - contact: { email: 'dev@stainless.com', name: { first: 'first', last: 'last' } }, + address: { + city: 'city', + state: 'xx', + street1: 'street1', + zip: '60513', + }, + contact: { + email: 'dev@stainless.com', + name: { first: 'first', last: 'last' }, + }, propertyManagerId: 0, }); const rawResponse = await responsePromise.asResponse(); @@ -27,8 +35,18 @@ describe('resource tenants', () => { // Prism tests are disabled test.skip('create: required and optional params', async () => { const response = await client.tenants.create({ - address: { city: 'city', state: 'xx', street1: 'street1', zip: '60513', street2: 'street2' }, - contact: { email: 'dev@stainless.com', name: { first: 'first', last: 'last' }, phone: 'phone' }, + address: { + city: 'city', + state: 'xx', + street1: 'street1', + zip: '60513', + street2: 'street2', + }, + contact: { + email: 'dev@stainless.com', + name: { first: 'first', last: 'last' }, + phone: 'phone', + }, propertyManagerId: 0, }); }); @@ -73,7 +91,14 @@ describe('resource tenants', () => { test.skip('list: request options and params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( - client.tenants.list({ page: 1, propertyManagerId: 1, size: 1 }, { path: '/_stainless_unknown_path' }), + client.tenants.list( + { + page: 1, + propertyManagerId: 1, + size: 1, + }, + { path: '/_stainless_unknown_path' }, + ), ).rejects.toThrow(Beagle.NotFoundError); }); diff --git a/tests/index.test.ts b/tests/index.test.ts index 34842826..78a138ed 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -87,7 +87,11 @@ describe('instantiate client', () => { error: jest.fn(), }; - const client = new Beagle({ logger: logger, logLevel: 'debug', apiKey: 'My API Key' }); + const client = new Beagle({ + logger: logger, + logLevel: 'debug', + apiKey: 'My API Key', + }); await forceAPIResponseForClient(client); expect(debugMock).toHaveBeenCalled(); @@ -107,7 +111,11 @@ describe('instantiate client', () => { error: jest.fn(), }; - const client = new Beagle({ logger: logger, logLevel: 'info', apiKey: 'My API Key' }); + const client = new Beagle({ + logger: logger, + logLevel: 'info', + apiKey: 'My API Key', + }); await forceAPIResponseForClient(client); expect(debugMock).not.toHaveBeenCalled(); @@ -157,7 +165,11 @@ describe('instantiate client', () => { }; process.env['BEAGLE_LOG'] = 'debug'; - const client = new Beagle({ logger: logger, logLevel: 'off', apiKey: 'My API Key' }); + const client = new Beagle({ + logger: logger, + logLevel: 'off', + apiKey: 'My API Key', + }); await forceAPIResponseForClient(client); expect(debugMock).not.toHaveBeenCalled(); @@ -173,7 +185,11 @@ describe('instantiate client', () => { }; process.env['BEAGLE_LOG'] = 'not a log level'; - const client = new Beagle({ logger: logger, logLevel: 'debug', apiKey: 'My API Key' }); + const client = new Beagle({ + logger: logger, + logLevel: 'debug', + apiKey: 'My API Key', + }); expect(client.logLevel).toBe('debug'); expect(warnMock).not.toHaveBeenCalled(); }); @@ -267,7 +283,11 @@ describe('instantiate client', () => { return new Response(JSON.stringify({}), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Beagle({ baseURL: 'http://localhost:5000/', apiKey: 'My API Key', fetch: testFetch }); + const client = new Beagle({ + baseURL: 'http://localhost:5000/', + apiKey: 'My API Key', + fetch: testFetch, + }); await client.patch('/foo'); expect(capturedRequest?.method).toEqual('PATCH'); @@ -320,7 +340,11 @@ describe('instantiate client', () => { `"Ambiguous URL; The \`baseURL\` option (or BEAGLE_BASE_URL env var) and the \`environment\` option are given. If you want to use the environment you must pass baseURL: null"`, ); - const client = new Beagle({ apiKey: 'My API Key', baseURL: null, environment: 'production' }); + const client = new Beagle({ + apiKey: 'My API Key', + baseURL: null, + environment: 'production', + }); expect(client.baseURL).toEqual('https://developer.beagleforpm.com'); }); @@ -358,7 +382,11 @@ describe('instantiate client', () => { describe('withOptions', () => { test('creates a new client with overridden options', async () => { - const client = new Beagle({ baseURL: 'http://localhost:5000/', maxRetries: 3, apiKey: 'My API Key' }); + const client = new Beagle({ + baseURL: 'http://localhost:5000/', + maxRetries: 3, + apiKey: 'My API Key', + }); const newClient = client.withOptions({ maxRetries: 5, @@ -398,7 +426,11 @@ describe('instantiate client', () => { }); test('respects runtime property changes when creating new client', () => { - const client = new Beagle({ baseURL: 'http://localhost:5000/', timeout: 1000, apiKey: 'My API Key' }); + const client = new Beagle({ + baseURL: 'http://localhost:5000/', + timeout: 1000, + apiKey: 'My API Key', + }); // Modify the client properties directly after creation client.baseURL = 'http://localhost:6000/'; @@ -544,7 +576,11 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Beagle({ apiKey: 'My API Key', timeout: 10, fetch: testFetch }); + const client = new Beagle({ + apiKey: 'My API Key', + timeout: 10, + fetch: testFetch, + }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); expect(count).toEqual(2); @@ -574,7 +610,11 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Beagle({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); + const client = new Beagle({ + apiKey: 'My API Key', + fetch: testFetch, + maxRetries: 4, + }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); @@ -598,7 +638,11 @@ describe('retries', () => { capturedRequest = init; return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Beagle({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); + const client = new Beagle({ + apiKey: 'My API Key', + fetch: testFetch, + maxRetries: 4, + }); expect( await client.request({ @@ -660,7 +704,11 @@ describe('retries', () => { capturedRequest = init; return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Beagle({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); + const client = new Beagle({ + apiKey: 'My API Key', + fetch: testFetch, + maxRetries: 4, + }); expect( await client.request({ diff --git a/yarn.lock b/yarn.lock index 5f56a201..fc9f262b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,14 +7,6 @@ resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== -"@ampproject/remapping@^2.2.0": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" - integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== - dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" - "@andrewbranch/untar.js@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@andrewbranch/untar.js/-/untar.js-1.0.3.tgz#ba9494f85eb83017c5c855763969caf1d0adea00" @@ -46,155 +38,119 @@ typescript "5.6.1-rc" validate-npm-package-name "^5.0.0" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" - integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.28.6.tgz#72499312ec58b1e2245ba4a4f550c132be4982f7" + integrity sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q== dependencies: - "@babel/highlight" "^7.23.4" - chalk "^2.4.2" + "@babel/helper-validator-identifier" "^7.28.5" + js-tokens "^4.0.0" + picocolors "^1.1.1" -"@babel/compat-data@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" - integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== +"@babel/compat-data@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.28.6.tgz#103f466803fa0f059e82ccac271475470570d74c" + integrity sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg== "@babel/core@^7.11.6", "@babel/core@^7.12.3": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.6.tgz#8be77cd77c55baadcc1eae1c33df90ab6d2151d4" - integrity sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helpers" "^7.23.6" - "@babel/parser" "^7.23.6" - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.6" - "@babel/types" "^7.23.6" + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.6.tgz#531bf883a1126e53501ba46eb3bb414047af507f" + integrity sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/generator" "^7.28.6" + "@babel/helper-compilation-targets" "^7.28.6" + "@babel/helper-module-transforms" "^7.28.6" + "@babel/helpers" "^7.28.6" + "@babel/parser" "^7.28.6" + "@babel/template" "^7.28.6" + "@babel/traverse" "^7.28.6" + "@babel/types" "^7.28.6" + "@jridgewell/remapping" "^2.3.5" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.23.6", "@babel/generator@^7.7.2": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" - integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== +"@babel/generator@^7.28.6", "@babel/generator@^7.7.2": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.6.tgz#48dcc65d98fcc8626a48f72b62e263d25fc3c3f1" + integrity sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw== + dependencies: + "@babel/parser" "^7.28.6" + "@babel/types" "^7.28.6" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" + jsesc "^3.0.2" + +"@babel/helper-compilation-targets@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz#32c4a3f41f12ed1532179b108a4d746e105c2b25" + integrity sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA== + dependencies: + "@babel/compat-data" "^7.28.6" + "@babel/helper-validator-option" "^7.27.1" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-globals@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674" + integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== + +"@babel/helper-module-imports@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz#60632cbd6ffb70b22823187201116762a03e2d5c" + integrity sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw== dependencies: - "@babel/types" "^7.23.6" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" - jsesc "^2.5.1" + "@babel/traverse" "^7.28.6" + "@babel/types" "^7.28.6" -"@babel/helper-compilation-targets@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" - integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== +"@babel/helper-module-transforms@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz#9312d9d9e56edc35aeb6e95c25d4106b50b9eb1e" + integrity sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA== dependencies: - "@babel/compat-data" "^7.23.5" - "@babel/helper-validator-option" "^7.23.5" - browserslist "^4.22.2" - lru-cache "^5.1.1" - semver "^6.3.1" + "@babel/helper-module-imports" "^7.28.6" + "@babel/helper-validator-identifier" "^7.28.5" + "@babel/traverse" "^7.28.6" -"@babel/helper-environment-visitor@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" - integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== - -"@babel/helper-function-name@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" - integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== - dependencies: - "@babel/template" "^7.22.15" - "@babel/types" "^7.23.0" - -"@babel/helper-hoist-variables@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" - integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-module-imports@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" - integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== - dependencies: - "@babel/types" "^7.22.15" - -"@babel/helper-module-transforms@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" - integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-simple-access" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/helper-validator-identifier" "^7.22.20" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" - integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== - -"@babel/helper-simple-access@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" - integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-split-export-declaration@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" - integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-string-parser@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" - integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== - -"@babel/helper-validator-identifier@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" - integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== - -"@babel/helper-validator-option@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" - integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== - -"@babel/helpers@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.6.tgz#d03af2ee5fb34691eec0cda90f5ecbb4d4da145a" - integrity sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA== - dependencies: - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.6" - "@babel/types" "^7.23.6" - -"@babel/highlight@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" - integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== - dependencies: - "@babel/helper-validator-identifier" "^7.22.20" - chalk "^2.4.2" - js-tokens "^4.0.0" +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.28.6", "@babel/helper-plugin-utils@^7.8.0": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz#6f13ea251b68c8532e985fd532f28741a8af9ac8" + integrity sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug== + +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== + +"@babel/helper-validator-identifier@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" + integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== + +"@babel/helper-validator-option@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" + integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== + +"@babel/helpers@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.28.6.tgz#fca903a313ae675617936e8998b814c415cbf5d7" + integrity sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw== + dependencies: + "@babel/template" "^7.28.6" + "@babel/types" "^7.28.6" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b" - integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ== +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.6.tgz#f01a8885b7fa1e56dd8a155130226cd698ef13fd" + integrity sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ== + dependencies: + "@babel/types" "^7.28.6" "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -210,14 +166,28 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-class-properties@^7.8.3": +"@babel/plugin-syntax-class-properties@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-syntax-import-meta@^7.8.3": +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-import-attributes@^7.24.7": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz#b71d5914665f60124e133696f17cd7669062c503" + integrity sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw== + dependencies: + "@babel/helper-plugin-utils" "^7.28.6" + +"@babel/plugin-syntax-import-meta@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== @@ -232,13 +202,13 @@ "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-jsx@^7.7.2": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" - integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz#f8ca28bbd84883b5fea0e447c635b81ba73997ee" + integrity sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.28.6" -"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== @@ -252,7 +222,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.8.3": +"@babel/plugin-syntax-numeric-separator@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== @@ -280,7 +250,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.8.3": +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== @@ -288,45 +265,41 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.7.2": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f" - integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/template@^7.22.15", "@babel/template@^7.3.3": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" - integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== - dependencies: - "@babel/code-frame" "^7.22.13" - "@babel/parser" "^7.22.15" - "@babel/types" "^7.22.15" - -"@babel/traverse@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.6.tgz#b53526a2367a0dd6edc423637f3d2d0f2521abc5" - integrity sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ== - dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.23.6" - "@babel/types" "^7.23.6" + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz#c7b2ddf1d0a811145b1de800d1abd146af92e3a2" + integrity sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A== + dependencies: + "@babel/helper-plugin-utils" "^7.28.6" + +"@babel/template@^7.28.6", "@babel/template@^7.3.3": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.28.6.tgz#0e7e56ecedb78aeef66ce7972b082fce76a23e57" + integrity sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/parser" "^7.28.6" + "@babel/types" "^7.28.6" + +"@babel/traverse@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.6.tgz#871ddc79a80599a5030c53b1cc48cbe3a5583c2e" + integrity sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/generator" "^7.28.6" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.28.6" + "@babel/template" "^7.28.6" + "@babel/types" "^7.28.6" debug "^4.3.1" - globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.3.3": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd" - integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg== +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.28.6", "@babel/types@^7.3.3": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.6.tgz#c3e9377f1b155005bcc4c46020e7e394e13089df" + integrity sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg== dependencies: - "@babel/helper-string-parser" "^7.23.4" - "@babel/helper-validator-identifier" "^7.22.20" - to-fast-properties "^2.0.0" + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.28.5" "@bcoe/v8-coverage@^0.2.3": version "0.2.3" @@ -668,31 +641,38 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" - integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== +"@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.5": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f" + integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/remapping@^2.3.5": + version "2.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/remapping/-/remapping-2.3.5.tgz#375c476d1972947851ba1e15ae8f123047445aa1" + integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ== dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" "@jridgewell/resolve-uri@^3.1.0": version "3.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": +"@jridgewell/sourcemap-codec@^1.4.14": version "1.4.15" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9": +"@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18": version "0.3.20" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== @@ -700,6 +680,14 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.28": + version "0.3.31" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1116,13 +1104,6 @@ ansi-regex@^6.1.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" @@ -1200,22 +1181,25 @@ babel-plugin-jest-hoist@^29.6.3: "@types/babel__traverse" "^7.0.6" babel-preset-current-node-syntax@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" - integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + version "1.2.0" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz#20730d6cdc7dda5d89401cab10ac6a32067acde6" + integrity sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg== dependencies: "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.8.3" - "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-import-attributes" "^7.24.7" + "@babel/plugin-syntax-import-meta" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-top-level-await" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" babel-preset-jest@^29.6.3: version "29.6.3" @@ -1230,18 +1214,23 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +baseline-browser-mapping@^2.9.0: + version "2.9.14" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz#3b6af0bc032445bca04de58caa9a87cfe921cbb3" + integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== + brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + version "1.1.12" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + version "2.0.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== dependencies: balanced-match "^1.0.0" @@ -1252,15 +1241,16 @@ braces@^3.0.3: dependencies: fill-range "^7.1.1" -browserslist@^4.22.2: - version "4.22.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b" - integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A== +browserslist@^4.24.0: + version "4.28.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.1.tgz#7f534594628c53c63101079e27e40de490456a95" + integrity sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA== dependencies: - caniuse-lite "^1.0.30001565" - electron-to-chromium "^1.4.601" - node-releases "^2.0.14" - update-browserslist-db "^1.0.13" + baseline-browser-mapping "^2.9.0" + caniuse-lite "^1.0.30001759" + electron-to-chromium "^1.5.263" + node-releases "^2.0.27" + update-browserslist-db "^1.2.0" bs-logger@0.x: version "0.2.6" @@ -1296,19 +1286,10 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001565: - version "1.0.30001570" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz#b4e5c1fa786f733ab78fc70f592df6b3f23244ca" - integrity sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw== - -chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" +caniuse-lite@^1.0.30001759: + version "1.0.30001764" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz#03206c56469f236103b90f9ae10bcb8b9e1f6005" + integrity sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g== chalk@^4.0.0, chalk@^4.1.2: version "4.1.2" @@ -1397,13 +1378,6 @@ collect-v8-coverage@^1.0.0: resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -1411,11 +1385,6 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" @@ -1507,10 +1476,10 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -electron-to-chromium@^1.4.601: - version "1.4.614" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.614.tgz#2fe789d61fa09cb875569f37c309d0c2701f91c0" - integrity sha512-X4ze/9Sc3QWs6h92yerwqv7aB/uU8vCjZcrMjA8N9R1pjMFRe44dLsck5FzLilOYvcXuDn93B+bpGYyufc70gQ== +electron-to-chromium@^1.5.263: + version "1.5.267" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz#5d84f2df8cdb6bfe7e873706bb21bd4bfb574dc7" + integrity sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw== emittery@^0.13.1: version "0.13.1" @@ -1544,10 +1513,10 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== +escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== escape-string-regexp@^2.0.0: version "2.0.0" @@ -1883,11 +1852,6 @@ glob@^8.0.1: minimatch "^5.0.1" once "^1.3.0" -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - globals@^14.0.0: version "14.0.0" resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" @@ -1903,11 +1867,6 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" @@ -2459,9 +2418,9 @@ js-tokens@^4.0.0: integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + version "3.14.2" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.2.tgz#77485ce1dd7f33c061fd1b16ecea23b55fcb04b0" + integrity sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -2473,10 +2432,10 @@ js-yaml@^4.1.1: dependencies: argparse "^2.0.1" -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +jsesc@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== json-buffer@3.0.1: version "3.0.1" @@ -2711,10 +2670,10 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== -node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== +node-releases@^2.0.27: + version "2.0.27" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.27.tgz#eedca519205cf20f650f61d56b070db111231e4e" + integrity sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA== normalize-path@^3.0.0: version "3.0.0" @@ -2882,11 +2841,6 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" @@ -3190,13 +3144,6 @@ superstruct@^1.0.4: resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" integrity sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ== -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - supports-color@^7.0.0, supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -3259,11 +3206,6 @@ tmpl@1.0.5: resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -3389,13 +3331,13 @@ unicode-emoji-modifier-base@^1.0.0: resolved "https://registry.yarnpkg.com/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz#dbbd5b54ba30f287e2a8d5a249da6c0cef369459" integrity sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g== -update-browserslist-db@^1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" - integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== +update-browserslist-db@^1.2.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz#64d76db58713136acbeb4c49114366cc6cc2e80d" + integrity sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w== dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" + escalade "^3.2.0" + picocolors "^1.1.1" uri-js@^4.2.2: version "4.4.1" From dabc9a7d69d81803d8ace73720b62f6002eac2f3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 28 Jan 2026 19:25:28 +0000 Subject: [PATCH 071/138] feat(api): api update --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/publish-npm.yml | 2 +- .github/workflows/release-doctor.yml | 3 ++- .stats.yml | 4 ++-- README.md | 4 ++-- packages/mcp-server/README.md | 6 +++--- packages/mcp-server/src/code-tool.ts | 12 ++++++++---- packages/mcp-server/src/server.ts | 7 +++++++ packages/mcp-server/yarn.lock | 3 --- 9 files changed, 29 insertions(+), 20 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 19c17968..4b453721 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/beagle-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Node uses: actions/setup-node@v4 @@ -41,7 +41,7 @@ jobs: contents: read id-token: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Node uses: actions/setup-node@v4 @@ -57,7 +57,7 @@ jobs: - name: Get GitHub OIDC Token if: github.repository == 'stainless-sdks/beagle-typescript' id: github-oidc - uses: actions/github-script@v6 + uses: actions/github-script@v8 with: script: core.setOutput('github_token', await core.getIDToken()); @@ -83,7 +83,7 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/beagle-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Node uses: actions/setup-node@v4 diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 5053ad90..545bb383 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -20,7 +20,7 @@ jobs: contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Node uses: actions/setup-node@v3 diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 31f5d5ee..c188ebc6 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,10 +12,11 @@ jobs: if: github.repository == 'corgi-tech/beagle-sdks' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Check release environment run: | bash ./bin/check-release-environment env: NPM_TOKEN: ${{ secrets.BEAGLE_NPM_TOKEN || secrets.NPM_TOKEN }} + diff --git a/.stats.yml b/.stats.yml index 2fa4d986..b48b3c03 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 23 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-31b09d79d346937b987ae9132a4bb1200ef2aefdfaa4eda5bd9800ad20293f1a.yml -openapi_spec_hash: 85a9e4ac6a6000b79c6b7685f1630bc2 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-f58cb8ce1675b972840c58f1006a29ac817d0449dc20e43d3f9cd6ddd3dec638.yml +openapi_spec_hash: c3f02f1dc76b62f3897a980727b11f98 config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/README.md b/README.md index c294f7b5..170121ef 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ It is generated with [Stainless](https://www.stainless.com/). Use the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application. -[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXX0) -[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%7D) +[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ) +[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D) > Note: You may need to set environment variables in your MCP client. diff --git a/packages/mcp-server/README.md b/packages/mcp-server/README.md index c720b961..61fe2703 100644 --- a/packages/mcp-server/README.md +++ b/packages/mcp-server/README.md @@ -41,14 +41,14 @@ For clients with a configuration JSON, it might look something like this: If you use Cursor, you can install the MCP server by using the button below. You will need to set your environment variables in Cursor's `mcp.json`, which can be found in Cursor Settings > Tools & MCP > New MCP Server. -[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiU2V0IHlvdXIgQkVBR0xFX0FQSV9LRVkgaGVyZS4ifX0) +[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ) ### VS Code If you use MCP, you can install the MCP server by clicking the link below. You will need to set your environment variables in VS Code's `mcp.json`, which can be found via Command Palette > MCP: Open User Configuration. -[Open VS Code](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22Set%20your%20BEAGLE_API_KEY%20here.%22%7D%7D) +[Open VS Code](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D) ### Claude Code @@ -56,7 +56,7 @@ If you use Claude Code, you can install the MCP server by running the command be environment variables in Claude Code's `.claude.json`, which can be found in your home directory. ``` -claude mcp add corgi_tech_beagle_mcp_api --env BEAGLE_API_KEY="Your BEAGLE_API_KEY here." -- npx -y @corgi-tech/beagle-mcp +claude mcp add corgi_tech_beagle_mcp_api --env BEAGLE_API_KEY="My API Key" -- npx -y @corgi-tech/beagle-mcp ``` ## Code Mode diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 2e80fdcf..2a5eb737 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -2,8 +2,9 @@ import { McpTool, Metadata, ToolCallResult, asErrorResult, asTextContentResult } from './types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import { readEnv, readEnvOrError } from './server'; +import { readEnv, requireValue } from './server'; import { WorkerInput, WorkerOutput } from './code-tool-types'; +import { Beagle } from '@corgi-tech/beagle'; const prompt = `Runs JavaScript code to interact with the Beagle API. @@ -52,7 +53,7 @@ export function codeTool(): McpTool { required: ['code'], }, }; - const handler = async (_: unknown, args: any): Promise => { + const handler = async (client: Beagle, args: any): Promise => { const code = args.code as string; const intent = args.intent as string | undefined; @@ -68,8 +69,11 @@ export function codeTool(): McpTool { ...(stainlessAPIKey && { Authorization: stainlessAPIKey }), 'Content-Type': 'application/json', client_envs: JSON.stringify({ - BEAGLE_API_KEY: readEnvOrError('BEAGLE_API_KEY'), - BEAGLE_BASE_URL: readEnv('BEAGLE_BASE_URL'), + BEAGLE_API_KEY: requireValue( + readEnv('BEAGLE_API_KEY') ?? client.apiKey, + 'set BEAGLE_API_KEY environment variable or provide apiKey client option', + ), + BEAGLE_BASE_URL: readEnv('BEAGLE_BASE_URL') ?? client.baseURL ?? undefined, }), }, body: JSON.stringify({ diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index da656fa4..14dab712 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -146,3 +146,10 @@ export const readEnvOrError = (env: string): string => { } return envValue; }; + +export const requireValue = (value: T | undefined, description: string): T => { + if (value === undefined) { + throw new Error(`Missing required value: ${description}`); + } + return value; +}; diff --git a/packages/mcp-server/yarn.lock b/packages/mcp-server/yarn.lock index a592e9c7..fe102775 100644 --- a/packages/mcp-server/yarn.lock +++ b/packages/mcp-server/yarn.lock @@ -3302,9 +3302,6 @@ readable-stream@^3.4.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -"replicate@file:../../dist": - version "2.0.0-alpha.74" - require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" From 767718501422e254729875742c8270dd7d91181d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 29 Jan 2026 06:35:36 +0000 Subject: [PATCH 072/138] chore(mcp): up tsconfig lib version to es2022 --- packages/mcp-server/tsconfig.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/mcp-server/tsconfig.json b/packages/mcp-server/tsconfig.json index ee8fd2fe..68bce321 100644 --- a/packages/mcp-server/tsconfig.json +++ b/packages/mcp-server/tsconfig.json @@ -2,8 +2,8 @@ "include": ["src", "tests", "examples"], "exclude": [], "compilerOptions": { - "target": "es2020", - "lib": ["es2020"], + "target": "es2022", + "lib": ["es2022"], "module": "commonjs", "moduleResolution": "node", "esModuleInterop": true, From 94390bc6b29e976c0a83036f1bb11a111cad63ba Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 31 Jan 2026 07:42:42 +0000 Subject: [PATCH 073/138] chore(internal): codegen related update --- packages/mcp-server/src/code-tool.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 2a5eb737..5a434230 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -73,7 +73,10 @@ export function codeTool(): McpTool { readEnv('BEAGLE_API_KEY') ?? client.apiKey, 'set BEAGLE_API_KEY environment variable or provide apiKey client option', ), - BEAGLE_BASE_URL: readEnv('BEAGLE_BASE_URL') ?? client.baseURL ?? undefined, + BEAGLE_BASE_URL: + readEnv('BEAGLE_BASE_URL') ?? readEnv('BEAGLE_ENVIRONMENT') ? + undefined + : client.baseURL ?? undefined, }), }, body: JSON.stringify({ From 82117a62e14c3a1ac72fc3c632c7fb21b7934d94 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 3 Feb 2026 07:40:17 +0000 Subject: [PATCH 074/138] chore(internal): codegen related update --- packages/mcp-server/package.json | 4 ++++ packages/mcp-server/src/headers.ts | 2 +- packages/mcp-server/src/http.ts | 9 +++++---- packages/mcp-server/src/options.ts | 1 + src/client.ts | 5 +++-- src/internal/parse.ts | 6 ++++++ 6 files changed, 20 insertions(+), 7 deletions(-) diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 6f5ead4a..622cdd6c 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -34,10 +34,12 @@ "@cloudflare/cabidela": "^0.2.4", "@modelcontextprotocol/sdk": "^1.25.2", "@valtown/deno-http-worker": "^0.0.21", + "cookie-parser": "^1.4.6", "cors": "^2.8.5", "express": "^5.1.0", "fuse.js": "^7.1.0", "jq-web": "https://github.com/stainless-api/jq-web/releases/download/v0.8.8/jq-web.tar.gz", + "morgan": "^1.10.0", "qs": "^6.14.1", "typescript": "5.8.3", "yargs": "^17.7.2", @@ -50,9 +52,11 @@ }, "devDependencies": { "@anthropic-ai/mcpb": "^2.1.2", + "@types/cookie-parser": "^1.4.10", "@types/cors": "^2.8.19", "@types/express": "^5.0.3", "@types/jest": "^29.4.0", + "@types/morgan": "^1.9.10", "@types/qs": "^6.14.0", "@types/yargs": "^17.0.8", "@typescript-eslint/eslint-plugin": "8.31.1", diff --git a/packages/mcp-server/src/headers.ts b/packages/mcp-server/src/headers.ts index d909a484..5f78b71b 100644 --- a/packages/mcp-server/src/headers.ts +++ b/packages/mcp-server/src/headers.ts @@ -3,7 +3,7 @@ import { IncomingMessage } from 'node:http'; import { ClientOptions } from '@corgi-tech/beagle'; -export const parseAuthHeaders = (req: IncomingMessage): Partial => { +export const parseAuthHeaders = (req: IncomingMessage, required?: boolean): Partial => { const apiKey = Array.isArray(req.headers['x-api-key']) ? req.headers['x-api-key'][0] : req.headers['x-api-key']; return { apiKey }; diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index dcfeba6a..42eb5002 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -2,8 +2,8 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; - import express from 'express'; +import morgan from 'morgan'; import { McpOptions } from './options'; import { ClientOptions, initMcpServer, newMcpServer } from './server'; import { parseAuthHeaders } from './headers'; @@ -20,7 +20,7 @@ const newServer = ({ const server = newMcpServer(); try { - const authOptions = parseAuthHeaders(req); + const authOptions = parseAuthHeaders(req, false); initMcpServer({ server: server, clientOptions: { @@ -75,14 +75,15 @@ const del = async (req: express.Request, res: express.Response) => { export const streamableHTTPApp = ({ clientOptions = {}, - mcpOptions = {}, + mcpOptions, }: { clientOptions?: ClientOptions; - mcpOptions?: McpOptions; + mcpOptions: McpOptions; }): express.Express => { const app = express(); app.set('query parser', 'extended'); app.use(express.json()); + app.use(morgan('combined')); app.get('/', get); app.post('/', post({ clientOptions, mcpOptions })); diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index c66ad8ce..025280ec 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -35,6 +35,7 @@ export function parseCLIOptions(): CLIOptions { }) .option('port', { type: 'number', + default: 3000, description: 'Port to serve on if using http transport', }) .option('socket', { diff --git a/src/client.ts b/src/client.ts index 93fcd308..5896761a 100644 --- a/src/client.ts +++ b/src/client.ts @@ -576,9 +576,10 @@ export class Beagle { controller: AbortController, ): Promise { const { signal, method, ...options } = init || {}; - if (signal) signal.addEventListener('abort', () => controller.abort()); + const abort = controller.abort.bind(controller); + if (signal) signal.addEventListener('abort', abort, { once: true }); - const timeout = setTimeout(() => controller.abort(), ms); + const timeout = setTimeout(abort, ms); const isReadableBody = ((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) || diff --git a/src/internal/parse.ts b/src/internal/parse.ts index 9484cb0a..0da1dab4 100644 --- a/src/internal/parse.ts +++ b/src/internal/parse.ts @@ -29,6 +29,12 @@ export async function defaultParseResponse(client: Beagle, props: APIResponse const mediaType = contentType?.split(';')[0]?.trim(); const isJSON = mediaType?.includes('application/json') || mediaType?.endsWith('+json'); if (isJSON) { + const contentLength = response.headers.get('content-length'); + if (contentLength === '0') { + // if there is no content we can't do anything + return undefined as T; + } + const json = await response.json(); return json as T; } From e78d81d51c46ff263fea13b083c9af5e81465e72 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 4 Feb 2026 00:25:09 +0000 Subject: [PATCH 075/138] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index b48b3c03..9f0d35ea 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 23 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-f58cb8ce1675b972840c58f1006a29ac817d0449dc20e43d3f9cd6ddd3dec638.yml -openapi_spec_hash: c3f02f1dc76b62f3897a980727b11f98 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-9db45f773e69505831bb9b09819dce561cfcc93e46a8c72f3dde4ad78397a5c9.yml +openapi_spec_hash: 370037979caccba51c705bb2332f4170 config_hash: a50e91a2233ab4faad057e676e3cfe49 From e0d836ab92ff11783082dc87b1c82e8f290cba7c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 5 Feb 2026 05:20:39 +0000 Subject: [PATCH 076/138] chore(internal): codegen related update --- packages/mcp-server/package.json | 1 + packages/mcp-server/src/http.ts | 37 ++++++++++++++++------- packages/mcp-server/src/index.ts | 6 +++- packages/mcp-server/src/options.ts | 28 +++++++++-------- packages/mcp-server/src/server.ts | 48 ++++++++++++++++++++++++++---- packages/mcp-server/src/stdio.ts | 4 +-- src/client.ts | 9 +++++- 7 files changed, 100 insertions(+), 33 deletions(-) diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 622cdd6c..49c8562c 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -40,6 +40,7 @@ "fuse.js": "^7.1.0", "jq-web": "https://github.com/stainless-api/jq-web/releases/download/v0.8.8/jq-web.tar.gz", "morgan": "^1.10.0", + "morgan-body": "^2.6.9", "qs": "^6.14.1", "typescript": "5.8.3", "yargs": "^17.7.2", diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index 42eb5002..1f851cb6 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -4,11 +4,12 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; import express from 'express'; import morgan from 'morgan'; +import morganBody from 'morgan-body'; import { McpOptions } from './options'; import { ClientOptions, initMcpServer, newMcpServer } from './server'; import { parseAuthHeaders } from './headers'; -const newServer = ({ +const newServer = async ({ clientOptions, req, res, @@ -16,12 +17,12 @@ const newServer = ({ clientOptions: ClientOptions; req: express.Request; res: express.Response; -}): McpServer | null => { - const server = newMcpServer(); +}): Promise => { + const server = await newMcpServer(); try { const authOptions = parseAuthHeaders(req, false); - initMcpServer({ + await initMcpServer({ server: server, clientOptions: { ...clientOptions, @@ -45,7 +46,7 @@ const newServer = ({ const post = (options: { clientOptions: ClientOptions; mcpOptions: McpOptions }) => async (req: express.Request, res: express.Response) => { - const server = newServer({ ...options, req, res }); + const server = await newServer({ ...options, req, res }); // If we return null, we already set the authorization error. if (server === null) return; const transport = new StreamableHTTPServerTransport(); @@ -76,14 +77,26 @@ const del = async (req: express.Request, res: express.Response) => { export const streamableHTTPApp = ({ clientOptions = {}, mcpOptions, + debug, }: { clientOptions?: ClientOptions; mcpOptions: McpOptions; + debug: boolean; }): express.Express => { const app = express(); app.set('query parser', 'extended'); app.use(express.json()); - app.use(morgan('combined')); + + if (debug) { + morganBody(app, { + logAllReqHeader: true, + logAllResHeader: true, + logRequestBody: true, + logResponseBody: true, + }); + } else { + app.use(morgan('combined')); + } app.get('/', get); app.post('/', post({ clientOptions, mcpOptions })); @@ -92,9 +105,13 @@ export const streamableHTTPApp = ({ return app; }; -export const launchStreamableHTTPServer = async (options: McpOptions, port: number | string | undefined) => { - const app = streamableHTTPApp({ mcpOptions: options }); - const server = app.listen(port); +export const launchStreamableHTTPServer = async (params: { + mcpOptions: McpOptions; + debug: boolean; + port: number | string | undefined; +}) => { + const app = streamableHTTPApp({ mcpOptions: params.mcpOptions, debug: params.debug }); + const server = app.listen(params.port); const address = server.address(); if (typeof address === 'string') { @@ -102,6 +119,6 @@ export const launchStreamableHTTPServer = async (options: McpOptions, port: numb } else if (address !== null) { console.error(`MCP Server running on streamable HTTP on port ${address.port}`); } else { - console.error(`MCP Server running on streamable HTTP on port ${port}`); + console.error(`MCP Server running on streamable HTTP on port ${params.port}`); } }; diff --git a/packages/mcp-server/src/index.ts b/packages/mcp-server/src/index.ts index 0f6dd426..d75968e3 100644 --- a/packages/mcp-server/src/index.ts +++ b/packages/mcp-server/src/index.ts @@ -21,7 +21,11 @@ async function main() { await launchStdioServer(); break; case 'http': - await launchStreamableHTTPServer(options, options.port ?? options.socket); + await launchStreamableHTTPServer({ + mcpOptions: options, + debug: options.debug, + port: options.port ?? options.socket, + }); break; } } diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index 025280ec..74380833 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -4,6 +4,7 @@ import { hideBin } from 'yargs/helpers'; import z from 'zod'; export type CLIOptions = McpOptions & { + debug: boolean; transport: 'stdio' | 'http'; port: number | undefined; socket: string | undefined; @@ -15,17 +16,24 @@ export type McpOptions = { export function parseCLIOptions(): CLIOptions { const opts = yargs(hideBin(process.argv)) - .option('tools', { + .option('debug', { type: 'boolean', description: 'Enable debug logging' }) + .option('no-tools', { type: 'string', array: true, choices: ['code', 'docs'], - description: 'Use dynamic tools or all tools', + description: 'Tools to explicitly disable', }) - .option('no-tools', { + .option('port', { + type: 'number', + default: 3000, + description: 'Port to serve on if using http transport', + }) + .option('socket', { type: 'string', description: 'Unix socket to serve on if using http transport' }) + .option('tools', { type: 'string', array: true, choices: ['code', 'docs'], - description: 'Do not use any dynamic or all tools', + description: 'Tools to explicitly enable', }) .option('transport', { type: 'string', @@ -33,15 +41,8 @@ export function parseCLIOptions(): CLIOptions { default: 'stdio', description: 'What transport to use; stdio for local servers or http for remote servers', }) - .option('port', { - type: 'number', - default: 3000, - description: 'Port to serve on if using http transport', - }) - .option('socket', { - type: 'string', - description: 'Unix socket to serve on if using http transport', - }) + .env('MCP_SERVER') + .version(true) .help(); const argv = opts.parseSync(); @@ -57,6 +58,7 @@ export function parseCLIOptions(): CLIOptions { return { ...(includeDocsTools !== undefined && { includeDocsTools }), + debug: !!argv.debug, transport, port: argv.port, socket: argv.socket, diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 14dab712..73099a4a 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -17,23 +17,59 @@ import { HandlerFunction, McpTool } from './types'; export { McpOptions } from './options'; export { ClientOptions } from '@corgi-tech/beagle'; -export const newMcpServer = () => +async function getInstructions() { + // This API key is optional; providing it allows the server to fetch instructions for unreleased versions. + const stainlessAPIKey = readEnv('STAINLESS_API_KEY'); + const response = await fetch( + readEnv('CODE_MODE_INSTRUCTIONS_URL') ?? 'https://api.stainless.com/api/ai/instructions/beagle', + { + method: 'GET', + headers: { ...(stainlessAPIKey && { Authorization: stainlessAPIKey }) }, + }, + ); + + let instructions: string | undefined; + if (!response.ok) { + console.warn( + 'Warning: failed to retrieve MCP server instructions. Proceeding with default instructions...', + ); + + instructions = ` + This is the beagle MCP server. You will use Code Mode to help the user perform + actions. You can use search_docs tool to learn about how to take action with this server. Then, + you will write TypeScript code using the execute tool take action. It is CRITICAL that you be + thoughtful and deliberate when executing code. Always try to entirely solve the problem in code + block: it can be as long as you need to get the job done! + `; + } + + instructions ??= ((await response.json()) as { instructions: string }).instructions; + instructions = ` + The current time in Unix timestamps is ${Date.now()}. + + ${instructions} + `; + + return instructions; +} + +export const newMcpServer = async () => new McpServer( { name: 'corgi_tech_beagle_api', version: '0.0.1-alpha.0', }, - { capabilities: { tools: {}, logging: {} } }, + { + instructions: await getInstructions(), + capabilities: { tools: {}, logging: {} }, + }, ); -// Create server instance -export const server = newMcpServer(); - /** * Initializes the provided MCP Server with the given tools and handlers. * If not provided, the default client, tools and handlers will be used. */ -export function initMcpServer(params: { +export async function initMcpServer(params: { server: Server | McpServer; clientOptions?: ClientOptions; mcpOptions?: McpOptions; diff --git a/packages/mcp-server/src/stdio.ts b/packages/mcp-server/src/stdio.ts index f07696f3..47aeb0c9 100644 --- a/packages/mcp-server/src/stdio.ts +++ b/packages/mcp-server/src/stdio.ts @@ -2,9 +2,9 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js' import { initMcpServer, newMcpServer } from './server'; export const launchStdioServer = async () => { - const server = newMcpServer(); + const server = await newMcpServer(); - initMcpServer({ server }); + await initMcpServer({ server }); const transport = new StdioServerTransport(); await server.connect(transport); diff --git a/src/client.ts b/src/client.ts index 5896761a..e5f68708 100644 --- a/src/client.ts +++ b/src/client.ts @@ -576,7 +576,7 @@ export class Beagle { controller: AbortController, ): Promise { const { signal, method, ...options } = init || {}; - const abort = controller.abort.bind(controller); + const abort = this._makeAbort(controller); if (signal) signal.addEventListener('abort', abort, { once: true }); const timeout = setTimeout(abort, ms); @@ -602,6 +602,7 @@ export class Beagle { return await this.fetch.call(undefined, url, fetchOptions); } finally { clearTimeout(timeout); + if (signal) signal.removeEventListener('abort', abort); } } @@ -746,6 +747,12 @@ export class Beagle { return headers.values; } + private _makeAbort(controller: AbortController) { + // note: we can't just inline this method inside `fetchWithTimeout()` because then the closure + // would capture all request options, and cause a memory leak. + return () => controller.abort(); + } + private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): { bodyHeaders: HeadersLike; body: BodyInit | undefined; From d01b7ab283ec4fa0e8bb75b394ec699e8faa074d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Feb 2026 07:17:45 +0000 Subject: [PATCH 077/138] chore(internal): codegen related update --- src/client.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/client.ts b/src/client.ts index e5f68708..462ddfaa 100644 --- a/src/client.ts +++ b/src/client.ts @@ -553,9 +553,14 @@ export class Beagle { getAPIList = Pagination.AbstractPage>( path: string, Page: new (...args: any[]) => PageClass, - opts?: RequestOptions, + opts?: PromiseOrValue, ): Pagination.PagePromise { - return this.requestAPIList(Page, { method: 'get', path, ...opts }); + return this.requestAPIList( + Page, + opts && 'then' in opts ? + opts.then((opts) => ({ method: 'get', path, ...opts })) + : { method: 'get', path, ...opts }, + ); } requestAPIList< @@ -563,7 +568,7 @@ export class Beagle { PageClass extends Pagination.AbstractPage = Pagination.AbstractPage, >( Page: new (...args: ConstructorParameters) => PageClass, - options: FinalRequestOptions, + options: PromiseOrValue, ): Pagination.PagePromise { const request = this.makeRequest(options, null, undefined); return new Pagination.PagePromise(this as any as Beagle, request, Page); @@ -602,7 +607,6 @@ export class Beagle { return await this.fetch.call(undefined, url, fetchOptions); } finally { clearTimeout(timeout); - if (signal) signal.removeEventListener('abort', abort); } } From df35c3f62a43d2cb86a96e00614568e7f1ec2c65 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 7 Feb 2026 05:23:45 +0000 Subject: [PATCH 078/138] feat(api): api update --- .stats.yml | 4 +- README.md | 35 +------- api.md | 38 ++++++--- packages/mcp-server/src/code-tool.ts | 2 + packages/mcp-server/src/http.ts | 3 + packages/mcp-server/src/server.ts | 8 +- src/client.ts | 37 +++++++-- src/resources/enrollments.ts | 63 ++++++++++---- src/resources/index.ts | 16 +++- src/resources/plans.ts | 30 ++++--- src/resources/property-managers.ts | 79 +++++++++++++----- src/resources/tenants.ts | 73 +++++++++++++---- src/resources/webhook/endpoints.ts | 118 ++++++++++++++++++--------- src/resources/webhook/index.ts | 1 - src/resources/webhook/webhook.ts | 2 - 15 files changed, 339 insertions(+), 170 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9f0d35ea..d54b2466 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 23 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-9db45f773e69505831bb9b09819dce561cfcc93e46a8c72f3dde4ad78397a5c9.yml -openapi_spec_hash: 370037979caccba51c705bb2332f4170 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-cd8cc6696f901a410f58cf964cff1b0bd0d5b7863ddd4e4f66301674465c9d02.yml +openapi_spec_hash: 10752adafce32e55a442b0c835ae567d config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/README.md b/README.md index 170121ef..6e97fdcc 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,8 @@ const client = new Beagle({ }); const plans = await client.plans.list(); + +console.log(plans.data); ``` ### Request & Response types @@ -131,37 +133,6 @@ On timeout, an `APIConnectionTimeoutError` is thrown. Note that requests which time out will be [retried twice by default](#retries). -## Auto-pagination - -List methods in the Beagle API are paginated. -You can use the `for await … of` syntax to iterate through items across all pages: - -```ts -async function fetchAllTenants(params) { - const allTenants = []; - // Automatically fetches more pages as needed. - for await (const tenant of client.tenants.list()) { - allTenants.push(tenant); - } - return allTenants; -} -``` - -Alternatively, you can request a single page at a time: - -```ts -let page = await client.tenants.list(); -for (const tenant of page.tenants) { - console.log(tenant); -} - -// Convenience methods are provided for manually paginating: -while (page.hasNextPage()) { - page = await page.getNextPage(); - // ... -} -``` - ## Advanced Usage ### Accessing raw Response data (e.g., headers) @@ -182,7 +153,7 @@ console.log(response.statusText); // access the underlying Response object const { data: plans, response: raw } = await client.plans.list().withResponse(); console.log(raw.headers.get('X-My-Header')); -console.log(plans); +console.log(plans.data); ``` ### Logging diff --git a/api.md b/api.md index 3b23350a..7a390d57 100644 --- a/api.md +++ b/api.md @@ -3,11 +3,12 @@ Types: - Plan +- PlanRetrieveResponse - PlanListResponse Methods: -- client.plans.retrieve(code) -> Plan +- client.plans.retrieve(code) -> PlanRetrieveResponse - client.plans.list() -> PlanListResponse # PropertyManagers @@ -16,13 +17,17 @@ Types: - Pagination - PropertyManager +- PropertyManagerCreateResponse +- PropertyManagerRetrieveResponse +- PropertyManagerUpdateResponse +- PropertyManagerListResponse Methods: -- client.propertyManagers.create({ ...params }) -> PropertyManager -- client.propertyManagers.retrieve(id) -> PropertyManager -- client.propertyManagers.update(id, { ...params }) -> PropertyManager -- client.propertyManagers.list({ ...params }) -> PropertyManagersPropertyManagersPagination +- client.propertyManagers.create({ ...params }) -> PropertyManagerCreateResponse +- client.propertyManagers.retrieve(id) -> PropertyManagerRetrieveResponse +- client.propertyManagers.update(id, { ...params }) -> PropertyManagerUpdateResponse +- client.propertyManagers.list({ ...params }) -> PropertyManagerListResponse - client.propertyManagers.delete(id) -> void # Tenants @@ -32,13 +37,17 @@ Types: - Address - Contact - Tenant +- TenantCreateResponse +- TenantRetrieveResponse +- TenantUpdateResponse +- TenantListResponse Methods: -- client.tenants.create({ ...params }) -> Tenant -- client.tenants.retrieve(id) -> Tenant -- client.tenants.update(id, { ...params }) -> Tenant -- client.tenants.list({ ...params }) -> TenantsTenantsPagination +- client.tenants.create({ ...params }) -> TenantCreateResponse +- client.tenants.retrieve(id) -> TenantRetrieveResponse +- client.tenants.update(id, { ...params }) -> TenantUpdateResponse +- client.tenants.list({ ...params }) -> TenantListResponse - client.tenants.delete(id) -> void # Enrollments @@ -46,12 +55,15 @@ Methods: Types: - Enrollment +- EnrollmentCreateResponse +- EnrollmentRetrieveResponse +- EnrollmentListResponse Methods: -- client.enrollments.create({ ...params }) -> Enrollment -- client.enrollments.retrieve(id) -> Enrollment -- client.enrollments.list({ ...params }) -> EnrollmentsEnrollmentsPagination +- client.enrollments.create({ ...params }) -> EnrollmentCreateResponse +- client.enrollments.retrieve(id) -> EnrollmentRetrieveResponse +- client.enrollments.list({ ...params }) -> EnrollmentListResponse - client.enrollments.lapse(id) -> void - client.enrollments.retrieveCertificate(id) -> Response @@ -81,5 +93,5 @@ Methods: - client.webhook.endpoints.create({ ...params }) -> EndpointCreateResponse - client.webhook.endpoints.retrieve(id) -> EndpointRetrieveResponse - client.webhook.endpoints.update(id, { ...params }) -> EndpointUpdateResponse -- client.webhook.endpoints.list({ ...params }) -> EndpointListResponsesWebhookEndpointsPagination +- client.webhook.endpoints.list({ ...params }) -> EndpointListResponse - client.webhook.endpoints.delete(id) -> void diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 5a434230..bc1634d5 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -15,6 +15,8 @@ For example: \`\`\` async function run(client) { const plans = await client.plans.list(); + + console.log(plans.data); } \`\`\` diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index 1f851cb6..b2031368 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -98,6 +98,9 @@ export const streamableHTTPApp = ({ app.use(morgan('combined')); } + app.get('/health', async (req: express.Request, res: express.Response) => { + res.status(200).send('OK'); + }); app.get('/', get); app.post('/', post({ clientOptions, mcpOptions })); app.delete('/', del); diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 73099a4a..5bc14968 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -36,10 +36,10 @@ async function getInstructions() { instructions = ` This is the beagle MCP server. You will use Code Mode to help the user perform - actions. You can use search_docs tool to learn about how to take action with this server. Then, - you will write TypeScript code using the execute tool take action. It is CRITICAL that you be - thoughtful and deliberate when executing code. Always try to entirely solve the problem in code - block: it can be as long as you need to get the job done! + actions. You can use search_docs tool to learn about how to take action with this server. Then, + you will write TypeScript code using the execute tool take action. It is CRITICAL that you be + thoughtful and deliberate when executing code. Always try to entirely solve the problem in code + block: it can be as long as you need to get the job done! `; } diff --git a/src/client.ts b/src/client.ts index 462ddfaa..27703123 100644 --- a/src/client.ts +++ b/src/client.ts @@ -31,34 +31,42 @@ import { APIPromise } from './core/api-promise'; import { Enrollment, EnrollmentCreateParams, + EnrollmentCreateResponse, EnrollmentListParams, + EnrollmentListResponse, + EnrollmentRetrieveResponse, Enrollments, - EnrollmentsEnrollmentsPagination, } from './resources/enrollments'; import { InsuranceVerification, InsuranceVerificationVerifyParams, InsuranceVerificationVerifyResponse, } from './resources/insurance-verification'; -import { Plan, PlanListResponse, Plans } from './resources/plans'; +import { Plan, PlanListResponse, PlanRetrieveResponse, Plans } from './resources/plans'; import { Pagination as PropertyManagersAPIPagination, PropertyManager, PropertyManagerCreateParams, + PropertyManagerCreateResponse, PropertyManagerListParams, + PropertyManagerListResponse, + PropertyManagerRetrieveResponse, PropertyManagerUpdateParams, + PropertyManagerUpdateResponse, PropertyManagers, - PropertyManagersPropertyManagersPagination, } from './resources/property-managers'; import { Address, Contact, Tenant, TenantCreateParams, + TenantCreateResponse, TenantListParams, + TenantListResponse, + TenantRetrieveResponse, TenantUpdateParams, + TenantUpdateResponse, Tenants, - TenantsTenantsPagination, } from './resources/tenants'; import { Webhook } from './resources/webhook/webhook'; import { type Fetch } from './internal/builtin-types'; @@ -855,13 +863,21 @@ export declare namespace Beagle { type WebhookEndpointsPaginationResponse as WebhookEndpointsPaginationResponse, }; - export { Plans as Plans, type Plan as Plan, type PlanListResponse as PlanListResponse }; + export { + Plans as Plans, + type Plan as Plan, + type PlanRetrieveResponse as PlanRetrieveResponse, + type PlanListResponse as PlanListResponse, + }; export { PropertyManagers as PropertyManagers, type PropertyManagersAPIPagination as Pagination, type PropertyManager as PropertyManager, - type PropertyManagersPropertyManagersPagination as PropertyManagersPropertyManagersPagination, + type PropertyManagerCreateResponse as PropertyManagerCreateResponse, + type PropertyManagerRetrieveResponse as PropertyManagerRetrieveResponse, + type PropertyManagerUpdateResponse as PropertyManagerUpdateResponse, + type PropertyManagerListResponse as PropertyManagerListResponse, type PropertyManagerCreateParams as PropertyManagerCreateParams, type PropertyManagerUpdateParams as PropertyManagerUpdateParams, type PropertyManagerListParams as PropertyManagerListParams, @@ -872,7 +888,10 @@ export declare namespace Beagle { type Address as Address, type Contact as Contact, type Tenant as Tenant, - type TenantsTenantsPagination as TenantsTenantsPagination, + type TenantCreateResponse as TenantCreateResponse, + type TenantRetrieveResponse as TenantRetrieveResponse, + type TenantUpdateResponse as TenantUpdateResponse, + type TenantListResponse as TenantListResponse, type TenantCreateParams as TenantCreateParams, type TenantUpdateParams as TenantUpdateParams, type TenantListParams as TenantListParams, @@ -881,7 +900,9 @@ export declare namespace Beagle { export { Enrollments as Enrollments, type Enrollment as Enrollment, - type EnrollmentsEnrollmentsPagination as EnrollmentsEnrollmentsPagination, + type EnrollmentCreateResponse as EnrollmentCreateResponse, + type EnrollmentRetrieveResponse as EnrollmentRetrieveResponse, + type EnrollmentListResponse as EnrollmentListResponse, type EnrollmentCreateParams as EnrollmentCreateParams, type EnrollmentListParams as EnrollmentListParams, }; diff --git a/src/resources/enrollments.ts b/src/resources/enrollments.ts index c8ba101d..4703a9b1 100644 --- a/src/resources/enrollments.ts +++ b/src/resources/enrollments.ts @@ -1,8 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../core/resource'; +import * as EnrollmentsAPI from './enrollments'; +import * as PropertyManagersAPI from './property-managers'; import { APIPromise } from '../core/api-promise'; -import { EnrollmentsPagination, type EnrollmentsPaginationParams, PagePromise } from '../core/pagination'; import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; @@ -22,7 +23,7 @@ export class Enrollments extends APIResource { * }); * ``` */ - create(body: EnrollmentCreateParams, options?: RequestOptions): APIPromise { + create(body: EnrollmentCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/api/enrollments', { body, ...options }); } @@ -34,7 +35,7 @@ export class Enrollments extends APIResource { * const enrollment = await client.enrollments.retrieve(123); * ``` */ - retrieve(id: number | null, options?: RequestOptions): APIPromise { + retrieve(id: number | null, options?: RequestOptions): APIPromise { return this._client.get(path`/api/enrollments/${id}`, options); } @@ -44,20 +45,14 @@ export class Enrollments extends APIResource { * * @example * ```ts - * // Automatically fetches more pages as needed. - * for await (const enrollment of client.enrollments.list()) { - * // ... - * } + * const enrollments = await client.enrollments.list(); * ``` */ list( query: EnrollmentListParams | null | undefined = {}, options?: RequestOptions, - ): PagePromise { - return this._client.getAPIList('/api/enrollments', EnrollmentsPagination, { - query, - ...options, - }); + ): APIPromise { + return this._client.get('/api/enrollments', { query, ...options }); } /** @@ -97,8 +92,6 @@ export class Enrollments extends APIResource { } } -export type EnrollmentsEnrollmentsPagination = EnrollmentsPagination; - export interface Enrollment { id: number; @@ -133,6 +126,32 @@ export interface Enrollment { note?: string; } +export interface EnrollmentCreateResponse { + data: Enrollment; + + success: true; +} + +export interface EnrollmentRetrieveResponse { + data: Enrollment; + + success: true; +} + +export interface EnrollmentListResponse { + data: EnrollmentListResponse.Data; + + success: true; +} + +export namespace EnrollmentListResponse { + export interface Data { + items: Array; + + pagination: PropertyManagersAPI.Pagination; + } +} + export interface EnrollmentCreateParams { /** * the date the enrollment will begin, note enrollments cannot begin in the past @@ -165,14 +184,26 @@ export interface EnrollmentCreateParams { note?: string; } -export interface EnrollmentListParams extends EnrollmentsPaginationParams { +export interface EnrollmentListParams { + /** + * Page number to fetch. + */ + page?: number; + propertyManagerId?: number; + + /** + * Number of items per page. + */ + size?: number; } export declare namespace Enrollments { export { type Enrollment as Enrollment, - type EnrollmentsEnrollmentsPagination as EnrollmentsEnrollmentsPagination, + type EnrollmentCreateResponse as EnrollmentCreateResponse, + type EnrollmentRetrieveResponse as EnrollmentRetrieveResponse, + type EnrollmentListResponse as EnrollmentListResponse, type EnrollmentCreateParams as EnrollmentCreateParams, type EnrollmentListParams as EnrollmentListParams, }; diff --git a/src/resources/index.ts b/src/resources/index.ts index e1d91bfd..981bef39 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -3,33 +3,41 @@ export { Enrollments, type Enrollment, + type EnrollmentCreateResponse, + type EnrollmentRetrieveResponse, + type EnrollmentListResponse, type EnrollmentCreateParams, type EnrollmentListParams, - type EnrollmentsEnrollmentsPagination, } from './enrollments'; export { InsuranceVerification, type InsuranceVerificationVerifyResponse, type InsuranceVerificationVerifyParams, } from './insurance-verification'; -export { Plans, type Plan, type PlanListResponse } from './plans'; +export { Plans, type Plan, type PlanRetrieveResponse, type PlanListResponse } from './plans'; export { PropertyManagers, type Pagination, type PropertyManager, + type PropertyManagerCreateResponse, + type PropertyManagerRetrieveResponse, + type PropertyManagerUpdateResponse, + type PropertyManagerListResponse, type PropertyManagerCreateParams, type PropertyManagerUpdateParams, type PropertyManagerListParams, - type PropertyManagersPropertyManagersPagination, } from './property-managers'; export { Tenants, type Address, type Contact, type Tenant, + type TenantCreateResponse, + type TenantRetrieveResponse, + type TenantUpdateResponse, + type TenantListResponse, type TenantCreateParams, type TenantUpdateParams, type TenantListParams, - type TenantsTenantsPagination, } from './tenants'; export { Webhook } from './webhook/webhook'; diff --git a/src/resources/plans.ts b/src/resources/plans.ts index 7f5e3a52..2e994b2d 100644 --- a/src/resources/plans.ts +++ b/src/resources/plans.ts @@ -8,23 +8,13 @@ import { path } from '../internal/utils/path'; export class Plans extends APIResource { /** * retrieve a specific plans details by its code. - * - * @example - * ```ts - * const plan = await client.plans.retrieve('code'); - * ``` */ - retrieve(code: string, options?: RequestOptions): APIPromise { + retrieve(code: string, options?: RequestOptions): APIPromise { return this._client.get(path`/api/plans/${code}`, options); } /** * List all available insurance plans that tenants can be enrolled in. - * - * @example - * ```ts - * const plans = await client.plans.list(); - * ``` */ list(options?: RequestOptions): APIPromise { return this._client.get('/api/plans', options); @@ -61,8 +51,22 @@ export interface Plan { value?: number; } -export type PlanListResponse = Array; +export interface PlanRetrieveResponse { + data: Plan; + + success: true; +} + +export interface PlanListResponse { + data: Array; + + success: true; +} export declare namespace Plans { - export { type Plan as Plan, type PlanListResponse as PlanListResponse }; + export { + type Plan as Plan, + type PlanRetrieveResponse as PlanRetrieveResponse, + type PlanListResponse as PlanListResponse, + }; } diff --git a/src/resources/property-managers.ts b/src/resources/property-managers.ts index 60333ecf..0fe32d1a 100644 --- a/src/resources/property-managers.ts +++ b/src/resources/property-managers.ts @@ -1,13 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../core/resource'; +import * as PropertyManagersAPI from './property-managers'; import * as TenantsAPI from './tenants'; import { APIPromise } from '../core/api-promise'; -import { - PagePromise, - PropertyManagersPagination, - type PropertyManagersPaginationParams, -} from '../core/pagination'; import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; @@ -40,7 +36,10 @@ export class PropertyManagers extends APIResource { * }); * ``` */ - create(body: PropertyManagerCreateParams, options?: RequestOptions): APIPromise { + create( + body: PropertyManagerCreateParams, + options?: RequestOptions, + ): APIPromise { return this._client.post('/api/property-managers', { body, ...options }); } @@ -53,7 +52,7 @@ export class PropertyManagers extends APIResource { * await client.propertyManagers.retrieve(123); * ``` */ - retrieve(id: number | null, options?: RequestOptions): APIPromise { + retrieve(id: number | null, options?: RequestOptions): APIPromise { return this._client.get(path`/api/property-managers/${id}`, options); } @@ -71,7 +70,7 @@ export class PropertyManagers extends APIResource { id: number | null, body: PropertyManagerUpdateParams, options?: RequestOptions, - ): APIPromise { + ): APIPromise { return this._client.patch(path`/api/property-managers/${id}`, { body, ...options }); } @@ -80,20 +79,15 @@ export class PropertyManagers extends APIResource { * * @example * ```ts - * // Automatically fetches more pages as needed. - * for await (const propertyManager of client.propertyManagers.list()) { - * // ... - * } + * const propertyManagers = + * await client.propertyManagers.list(); * ``` */ list( query: PropertyManagerListParams | null | undefined = {}, options?: RequestOptions, - ): PagePromise { - return this._client.getAPIList('/api/property-managers', PropertyManagersPagination, { - query, - ...options, - }); + ): APIPromise { + return this._client.get('/api/property-managers', { query, ...options }); } /** @@ -112,8 +106,6 @@ export class PropertyManagers extends APIResource { } } -export type PropertyManagersPropertyManagersPagination = PropertyManagersPagination; - export interface Pagination { /** * Current page number. @@ -161,6 +153,38 @@ export namespace PropertyManager { } } +export interface PropertyManagerCreateResponse { + data: PropertyManager; + + success: true; +} + +export interface PropertyManagerRetrieveResponse { + data: PropertyManager; + + success: true; +} + +export interface PropertyManagerUpdateResponse { + data: PropertyManager; + + success: true; +} + +export interface PropertyManagerListResponse { + data: PropertyManagerListResponse.Data; + + success: true; +} + +export namespace PropertyManagerListResponse { + export interface Data { + items: Array; + + pagination: PropertyManagersAPI.Pagination; + } +} + export interface PropertyManagerCreateParams { addresses: Array; @@ -207,13 +231,26 @@ export namespace PropertyManagerUpdateParams { } } -export interface PropertyManagerListParams extends PropertyManagersPaginationParams {} +export interface PropertyManagerListParams { + /** + * Page number to fetch. + */ + page?: number; + + /** + * Number of items per page. + */ + size?: number; +} export declare namespace PropertyManagers { export { type Pagination as Pagination, type PropertyManager as PropertyManager, - type PropertyManagersPropertyManagersPagination as PropertyManagersPropertyManagersPagination, + type PropertyManagerCreateResponse as PropertyManagerCreateResponse, + type PropertyManagerRetrieveResponse as PropertyManagerRetrieveResponse, + type PropertyManagerUpdateResponse as PropertyManagerUpdateResponse, + type PropertyManagerListResponse as PropertyManagerListResponse, type PropertyManagerCreateParams as PropertyManagerCreateParams, type PropertyManagerUpdateParams as PropertyManagerUpdateParams, type PropertyManagerListParams as PropertyManagerListParams, diff --git a/src/resources/tenants.ts b/src/resources/tenants.ts index 487dbce7..fd1906a0 100644 --- a/src/resources/tenants.ts +++ b/src/resources/tenants.ts @@ -1,8 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../core/resource'; +import * as TenantsAPI from './tenants'; +import * as PropertyManagersAPI from './property-managers'; import { APIPromise } from '../core/api-promise'; -import { PagePromise, TenantsPagination, type TenantsPaginationParams } from '../core/pagination'; import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; @@ -28,7 +29,7 @@ export class Tenants extends APIResource { * }); * ``` */ - create(body: TenantCreateParams, options?: RequestOptions): APIPromise { + create(body: TenantCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/api/tenants', { body, ...options }); } @@ -40,7 +41,7 @@ export class Tenants extends APIResource { * const tenant = await client.tenants.retrieve(123); * ``` */ - retrieve(id: number | null, options?: RequestOptions): APIPromise { + retrieve(id: number | null, options?: RequestOptions): APIPromise { return this._client.get(path`/api/tenants/${id}`, options); } @@ -52,7 +53,11 @@ export class Tenants extends APIResource { * const tenant = await client.tenants.update(123); * ``` */ - update(id: number | null, body: TenantUpdateParams, options?: RequestOptions): APIPromise { + update( + id: number | null, + body: TenantUpdateParams, + options?: RequestOptions, + ): APIPromise { return this._client.patch(path`/api/tenants/${id}`, { body, ...options }); } @@ -62,17 +67,14 @@ export class Tenants extends APIResource { * * @example * ```ts - * // Automatically fetches more pages as needed. - * for await (const tenant of client.tenants.list()) { - * // ... - * } + * const tenants = await client.tenants.list(); * ``` */ list( query: TenantListParams | null | undefined = {}, options?: RequestOptions, - ): PagePromise { - return this._client.getAPIList('/api/tenants', TenantsPagination, { query, ...options }); + ): APIPromise { + return this._client.get('/api/tenants', { query, ...options }); } /** @@ -91,8 +93,6 @@ export class Tenants extends APIResource { } } -export type TenantsTenantsPagination = TenantsPagination; - export interface Address { city: string; @@ -135,6 +135,38 @@ export interface Tenant { contact: Contact; } +export interface TenantCreateResponse { + data: Tenant; + + success: true; +} + +export interface TenantRetrieveResponse { + data: Tenant; + + success: true; +} + +export interface TenantUpdateResponse { + data: Tenant; + + success: true; +} + +export interface TenantListResponse { + data: TenantListResponse.Data; + + success: true; +} + +export namespace TenantListResponse { + export interface Data { + items: Array; + + pagination: PropertyManagersAPI.Pagination; + } +} + export interface TenantCreateParams { address: Address; @@ -149,8 +181,18 @@ export interface TenantUpdateParams { contact?: Contact; } -export interface TenantListParams extends TenantsPaginationParams { +export interface TenantListParams { + /** + * Page number to fetch. + */ + page?: number; + propertyManagerId?: number; + + /** + * Number of items per page. + */ + size?: number; } export declare namespace Tenants { @@ -158,7 +200,10 @@ export declare namespace Tenants { type Address as Address, type Contact as Contact, type Tenant as Tenant, - type TenantsTenantsPagination as TenantsTenantsPagination, + type TenantCreateResponse as TenantCreateResponse, + type TenantRetrieveResponse as TenantRetrieveResponse, + type TenantUpdateResponse as TenantUpdateResponse, + type TenantListResponse as TenantListResponse, type TenantCreateParams as TenantCreateParams, type TenantUpdateParams as TenantUpdateParams, type TenantListParams as TenantListParams, diff --git a/src/resources/webhook/endpoints.ts b/src/resources/webhook/endpoints.ts index c9d6a495..026aa710 100644 --- a/src/resources/webhook/endpoints.ts +++ b/src/resources/webhook/endpoints.ts @@ -1,12 +1,8 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../core/resource'; +import * as PropertyManagersAPI from '../property-managers'; import { APIPromise } from '../../core/api-promise'; -import { - PagePromise, - WebhookEndpointsPagination, - type WebhookEndpointsPaginationParams, -} from '../../core/pagination'; import { buildHeaders } from '../../internal/headers'; import { RequestOptions } from '../../internal/request-options'; import { path } from '../../internal/utils/path'; @@ -44,12 +40,8 @@ export class Endpoints extends APIResource { list( query: EndpointListParams | null | undefined = {}, options?: RequestOptions, - ): PagePromise { - return this._client.getAPIList( - '/api/webhook/endpoints', - WebhookEndpointsPagination, - { query, ...options }, - ); + ): APIPromise { + return this._client.get('/api/webhook/endpoints', { query, ...options }); } /** @@ -63,63 +55,100 @@ export class Endpoints extends APIResource { } } -export type EndpointListResponsesWebhookEndpointsPagination = - WebhookEndpointsPagination; - export interface EndpointCreateResponse { - id: number; + data: EndpointCreateResponse.Data; + + success: true; +} - active: boolean; +export namespace EndpointCreateResponse { + export interface Data { + id: number; - companyId: number; + active: boolean; - createdAt: string; + companyId: number; - updatedAt: string; + createdAt: string; - url: string; + updatedAt: string; + + url: string; + } } export interface EndpointRetrieveResponse { - id: number; + data: EndpointRetrieveResponse.Data; - active: boolean; + success: true; +} - companyId: number; +export namespace EndpointRetrieveResponse { + export interface Data { + id: number; - createdAt: string; + active: boolean; - updatedAt: string; + companyId: number; - url: string; + createdAt: string; + + updatedAt: string; + + url: string; + } } export interface EndpointUpdateResponse { - id: number; + data: EndpointUpdateResponse.Data; - active: boolean; + success: true; +} - companyId: number; +export namespace EndpointUpdateResponse { + export interface Data { + id: number; - createdAt: string; + active: boolean; - updatedAt: string; + companyId: number; - url: string; + createdAt: string; + + updatedAt: string; + + url: string; + } } export interface EndpointListResponse { - id: number; + data: EndpointListResponse.Data; - active: boolean; + success: true; +} - companyId: number; +export namespace EndpointListResponse { + export interface Data { + items: Array; - createdAt: string; + pagination: PropertyManagersAPI.Pagination; + } - updatedAt: string; + export namespace Data { + export interface Item { + id: number; - url: string; + active: boolean; + + companyId: number; + + createdAt: string; + + updatedAt: string; + + url: string; + } + } } export interface EndpointCreateParams { @@ -138,7 +167,17 @@ export interface EndpointUpdateParams { active?: boolean; } -export interface EndpointListParams extends WebhookEndpointsPaginationParams {} +export interface EndpointListParams { + /** + * Page number to fetch. + */ + page?: number; + + /** + * Number of items per page. + */ + size?: number; +} export declare namespace Endpoints { export { @@ -146,7 +185,6 @@ export declare namespace Endpoints { type EndpointRetrieveResponse as EndpointRetrieveResponse, type EndpointUpdateResponse as EndpointUpdateResponse, type EndpointListResponse as EndpointListResponse, - type EndpointListResponsesWebhookEndpointsPagination as EndpointListResponsesWebhookEndpointsPagination, type EndpointCreateParams as EndpointCreateParams, type EndpointUpdateParams as EndpointUpdateParams, type EndpointListParams as EndpointListParams, diff --git a/src/resources/webhook/index.ts b/src/resources/webhook/index.ts index ce1a32a7..3dd38bd6 100644 --- a/src/resources/webhook/index.ts +++ b/src/resources/webhook/index.ts @@ -9,6 +9,5 @@ export { type EndpointCreateParams, type EndpointUpdateParams, type EndpointListParams, - type EndpointListResponsesWebhookEndpointsPagination, } from './endpoints'; export { Webhook } from './webhook'; diff --git a/src/resources/webhook/webhook.ts b/src/resources/webhook/webhook.ts index ef3cda87..631ba551 100644 --- a/src/resources/webhook/webhook.ts +++ b/src/resources/webhook/webhook.ts @@ -7,7 +7,6 @@ import { EndpointCreateResponse, EndpointListParams, EndpointListResponse, - EndpointListResponsesWebhookEndpointsPagination, EndpointRetrieveResponse, EndpointUpdateParams, EndpointUpdateResponse, @@ -27,7 +26,6 @@ export declare namespace Webhook { type EndpointRetrieveResponse as EndpointRetrieveResponse, type EndpointUpdateResponse as EndpointUpdateResponse, type EndpointListResponse as EndpointListResponse, - type EndpointListResponsesWebhookEndpointsPagination as EndpointListResponsesWebhookEndpointsPagination, type EndpointCreateParams as EndpointCreateParams, type EndpointUpdateParams as EndpointUpdateParams, type EndpointListParams as EndpointListParams, From e3d038e4263c54d5f76209f881b25292b5451dfe Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 06:10:54 +0000 Subject: [PATCH 079/138] chore(internal): codegen related update --- .dockerignore | 59 +++++++ packages/mcp-server/Dockerfile | 71 +++++++++ packages/mcp-server/src/code-tool.ts | 21 ++- packages/mcp-server/src/http.ts | 3 + packages/mcp-server/src/index.ts | 2 +- packages/mcp-server/src/methods.ts | 222 +++++++++++++++++++++++++++ packages/mcp-server/src/options.ts | 23 +++ packages/mcp-server/src/server.ts | 7 +- packages/mcp-server/src/stdio.ts | 5 +- 9 files changed, 408 insertions(+), 5 deletions(-) create mode 100644 .dockerignore create mode 100644 packages/mcp-server/Dockerfile create mode 100644 packages/mcp-server/src/methods.ts diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..12ff1e64 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,59 @@ +# Dependencies +node_modules/ +**/node_modules/ + +# Build outputs +dist/ +**/dist/ + +# Git +.git/ +.gitignore + +# CI/CD +.github/ +.gitlab-ci.yml +.travis.yml + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# Testing +test/ +tests/ +__tests__/ +*.test.js +*.spec.js +coverage/ +.nyc_output/ + +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Environment +.env +.env.* + +# Temporary files +*.tmp +*.temp +.cache/ + +# Examples and scripts +examples/ +bin/ + +# Other packages (we only need mcp-server) +packages/*/ +!packages/mcp-server/ diff --git a/packages/mcp-server/Dockerfile b/packages/mcp-server/Dockerfile new file mode 100644 index 00000000..7f1432a6 --- /dev/null +++ b/packages/mcp-server/Dockerfile @@ -0,0 +1,71 @@ +# Dockerfile for Beagle MCP Server +# +# This Dockerfile builds a Docker image for the MCP Server. +# +# To build the image locally: +# docker build -f packages/mcp-server/Dockerfile -t @corgi-tech/beagle-mcp:local . +# +# To run the image: +# docker run -i @corgi-tech/beagle-mcp:local [OPTIONS] +# +# Common options: +# --tool= Include specific tools +# --resource= Include tools for specific resources +# --operation=read|write Filter by operation type +# --client= Set client compatibility (e.g., claude, cursor) +# --transport= Set transport type (stdio or http) +# +# For a full list of options: +# docker run -i @corgi-tech/beagle-mcp:local --help +# +# Note: The MCP server uses stdio transport by default. Docker's -i flag +# enables interactive mode, allowing the container to communicate over stdin/stdout. + +# Build stage +FROM node:24-alpine AS builder + +# Install bash for build script +RUN apk add --no-cache bash openssl + +# Set working directory +WORKDIR /build + +# Copy entire repository +COPY . . + +# Install all dependencies and build everything +RUN yarn install --frozen-lockfile && \ + yarn build + +# Production stage +FROM node:24-alpine + +# Add non-root user +RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001 + +# Set working directory +WORKDIR /app + +# Copy the built mcp-server dist directory +COPY --from=builder /build/packages/mcp-server/dist ./ + +# Copy node_modules from mcp-server (includes all production deps) +COPY --from=builder /build/packages/mcp-server/node_modules ./node_modules + +# Copy the built @corgi-tech/beagle into node_modules +COPY --from=builder /build/dist ./node_modules/@corgi-tech/beagle + +# Change ownership to nodejs user +RUN chown -R nodejs:nodejs /app + +# Switch to non-root user +USER nodejs + +# The MCP server uses stdio transport by default +# No exposed ports needed for stdio communication + +# Set the entrypoint to the MCP server +ENTRYPOINT ["node", "index.js"] + +# Allow passing arguments to the MCP server +CMD [] diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index bc1634d5..96850463 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -4,6 +4,7 @@ import { McpTool, Metadata, ToolCallResult, asErrorResult, asTextContentResult } import { Tool } from '@modelcontextprotocol/sdk/types.js'; import { readEnv, requireValue } from './server'; import { WorkerInput, WorkerOutput } from './code-tool-types'; +import { SdkMethod } from './methods'; import { Beagle } from '@corgi-tech/beagle'; const prompt = `Runs JavaScript code to interact with the Beagle API. @@ -35,7 +36,7 @@ Variables will not persist between calls, so make sure to return or log any data * * @param endpoints - The endpoints to include in the list. */ -export function codeTool(): McpTool { +export function codeTool(params: { blockedMethods: SdkMethod[] | undefined }): McpTool { const metadata: Metadata = { resource: 'all', operation: 'write', tags: [] }; const tool: Tool = { name: 'execute', @@ -59,6 +60,24 @@ export function codeTool(): McpTool { const code = args.code as string; const intent = args.intent as string | undefined; + // Do very basic blocking of code that includes forbidden method names. + // + // WARNING: This is not secure against obfuscation and other evasion methods. If + // stronger security blocks are required, then these should be enforced in the downstream + // API (e.g., by having users call the MCP server with API keys with limited permissions). + if (params.blockedMethods) { + const blockedMatches = params.blockedMethods.filter((method) => + code.includes(method.fullyQualifiedName), + ); + if (blockedMatches.length > 0) { + return asErrorResult( + `The following methods have been blocked by the MCP server and cannot be used in code execution: ${blockedMatches + .map((m) => m.fullyQualifiedName) + .join(', ')}`, + ); + } + } + // this is not required, but passing a Stainless API key for the matching project_name // will allow you to run code-mode queries against non-published versions of your SDK. const stainlessAPIKey = readEnv('STAINLESS_API_KEY'); diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index b2031368..8ca827c2 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -11,10 +11,12 @@ import { parseAuthHeaders } from './headers'; const newServer = async ({ clientOptions, + mcpOptions, req, res, }: { clientOptions: ClientOptions; + mcpOptions: McpOptions; req: express.Request; res: express.Response; }): Promise => { @@ -24,6 +26,7 @@ const newServer = async ({ const authOptions = parseAuthHeaders(req, false); await initMcpServer({ server: server, + mcpOptions: mcpOptions, clientOptions: { ...clientOptions, ...authOptions, diff --git a/packages/mcp-server/src/index.ts b/packages/mcp-server/src/index.ts index d75968e3..003a7655 100644 --- a/packages/mcp-server/src/index.ts +++ b/packages/mcp-server/src/index.ts @@ -18,7 +18,7 @@ async function main() { switch (options.transport) { case 'stdio': - await launchStdioServer(); + await launchStdioServer(options); break; case 'http': await launchStreamableHTTPServer({ diff --git a/packages/mcp-server/src/methods.ts b/packages/mcp-server/src/methods.ts new file mode 100644 index 00000000..483dca51 --- /dev/null +++ b/packages/mcp-server/src/methods.ts @@ -0,0 +1,222 @@ +import { McpOptions } from './options'; + +export type SdkMethod = { + clientCallName: string; + fullyQualifiedName: string; + httpMethod?: 'get' | 'post' | 'put' | 'patch' | 'delete' | 'query'; + httpPath?: string; +}; + +export const sdkMethods: SdkMethod[] = [ + { + clientCallName: 'client.plans.retrieve', + fullyQualifiedName: 'plans.retrieve', + httpMethod: 'get', + httpPath: '/api/plans/{code}', + }, + { + clientCallName: 'client.plans.list', + fullyQualifiedName: 'plans.list', + httpMethod: 'get', + httpPath: '/api/plans', + }, + { + clientCallName: 'client.propertyManagers.create', + fullyQualifiedName: 'propertyManagers.create', + httpMethod: 'post', + httpPath: '/api/property-managers', + }, + { + clientCallName: 'client.propertyManagers.retrieve', + fullyQualifiedName: 'propertyManagers.retrieve', + httpMethod: 'get', + httpPath: '/api/property-managers/{id}', + }, + { + clientCallName: 'client.propertyManagers.update', + fullyQualifiedName: 'propertyManagers.update', + httpMethod: 'patch', + httpPath: '/api/property-managers/{id}', + }, + { + clientCallName: 'client.propertyManagers.list', + fullyQualifiedName: 'propertyManagers.list', + httpMethod: 'get', + httpPath: '/api/property-managers', + }, + { + clientCallName: 'client.propertyManagers.delete', + fullyQualifiedName: 'propertyManagers.delete', + httpMethod: 'delete', + httpPath: '/api/property-managers/{id}', + }, + { + clientCallName: 'client.tenants.create', + fullyQualifiedName: 'tenants.create', + httpMethod: 'post', + httpPath: '/api/tenants', + }, + { + clientCallName: 'client.tenants.retrieve', + fullyQualifiedName: 'tenants.retrieve', + httpMethod: 'get', + httpPath: '/api/tenants/{id}', + }, + { + clientCallName: 'client.tenants.update', + fullyQualifiedName: 'tenants.update', + httpMethod: 'patch', + httpPath: '/api/tenants/{id}', + }, + { + clientCallName: 'client.tenants.list', + fullyQualifiedName: 'tenants.list', + httpMethod: 'get', + httpPath: '/api/tenants', + }, + { + clientCallName: 'client.tenants.delete', + fullyQualifiedName: 'tenants.delete', + httpMethod: 'delete', + httpPath: '/api/tenants/{id}', + }, + { + clientCallName: 'client.enrollments.create', + fullyQualifiedName: 'enrollments.create', + httpMethod: 'post', + httpPath: '/api/enrollments', + }, + { + clientCallName: 'client.enrollments.retrieve', + fullyQualifiedName: 'enrollments.retrieve', + httpMethod: 'get', + httpPath: '/api/enrollments/{id}', + }, + { + clientCallName: 'client.enrollments.list', + fullyQualifiedName: 'enrollments.list', + httpMethod: 'get', + httpPath: '/api/enrollments', + }, + { + clientCallName: 'client.enrollments.lapse', + fullyQualifiedName: 'enrollments.lapse', + httpMethod: 'delete', + httpPath: '/api/enrollments/{id}', + }, + { + clientCallName: 'client.enrollments.retrieveCertificate', + fullyQualifiedName: 'enrollments.retrieveCertificate', + httpMethod: 'get', + httpPath: '/api/enrollments/{id}/certificate', + }, + { + clientCallName: 'client.insuranceVerification.verify', + fullyQualifiedName: 'insuranceVerification.verify', + httpMethod: 'post', + httpPath: '/api/insurance-verification', + }, + { + clientCallName: 'client.webhook.endpoints.create', + fullyQualifiedName: 'webhook.endpoints.create', + httpMethod: 'post', + httpPath: '/api/webhook/endpoints', + }, + { + clientCallName: 'client.webhook.endpoints.retrieve', + fullyQualifiedName: 'webhook.endpoints.retrieve', + httpMethod: 'get', + httpPath: '/api/webhook/endpoints/{id}', + }, + { + clientCallName: 'client.webhook.endpoints.update', + fullyQualifiedName: 'webhook.endpoints.update', + httpMethod: 'patch', + httpPath: '/api/webhook/endpoints/{id}', + }, + { + clientCallName: 'client.webhook.endpoints.list', + fullyQualifiedName: 'webhook.endpoints.list', + httpMethod: 'get', + httpPath: '/api/webhook/endpoints', + }, + { + clientCallName: 'client.webhook.endpoints.delete', + fullyQualifiedName: 'webhook.endpoints.delete', + httpMethod: 'delete', + httpPath: '/api/webhook/endpoints/{id}', + }, +]; + +function allowedMethodsForCodeTool(options: McpOptions | undefined): SdkMethod[] | undefined { + if (!options) { + return undefined; + } + + let allowedMethods: SdkMethod[]; + + if (options.codeAllowHttpGets || options.codeAllowedMethods) { + // Start with nothing allowed and then add into it from options + let allowedMethodsSet = new Set(); + + if (options.codeAllowHttpGets) { + // Add all methods that map to an HTTP GET + sdkMethods + .filter((method) => method.httpMethod === 'get') + .forEach((method) => allowedMethodsSet.add(method)); + } + + if (options.codeAllowedMethods) { + // Add all methods that match any of the allowed regexps + const allowedRegexps = options.codeAllowedMethods.map((pattern) => { + try { + return new RegExp(pattern); + } catch (e) { + throw new Error( + `Invalid regex pattern for allowed method: "${pattern}": ${e instanceof Error ? e.message : e}`, + ); + } + }); + + sdkMethods + .filter((method) => allowedRegexps.some((regexp) => regexp.test(method.fullyQualifiedName))) + .forEach((method) => allowedMethodsSet.add(method)); + } + + allowedMethods = Array.from(allowedMethodsSet); + } else { + // Start with everything allowed + allowedMethods = [...sdkMethods]; + } + + if (options.codeBlockedMethods) { + // Filter down based on blocked regexps + const blockedRegexps = options.codeBlockedMethods.map((pattern) => { + try { + return new RegExp(pattern); + } catch (e) { + throw new Error( + `Invalid regex pattern for blocked method: "${pattern}": ${e instanceof Error ? e.message : e}`, + ); + } + }); + + allowedMethods = allowedMethods.filter( + (method) => !blockedRegexps.some((regexp) => regexp.test(method.fullyQualifiedName)), + ); + } + + return allowedMethods; +} + +export function blockedMethodsForCodeTool(options: McpOptions | undefined): SdkMethod[] | undefined { + const allowedMethods = allowedMethodsForCodeTool(options); + if (!allowedMethods) { + return undefined; + } + + const allowedSet = new Set(allowedMethods.map((method) => method.fullyQualifiedName)); + + // Return any methods that are not explicitly allowed + return sdkMethods.filter((method) => !allowedSet.has(method.fullyQualifiedName)); +} diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index 74380833..92d1b074 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -12,10 +12,30 @@ export type CLIOptions = McpOptions & { export type McpOptions = { includeDocsTools?: boolean | undefined; + codeAllowHttpGets?: boolean | undefined; + codeAllowedMethods?: string[] | undefined; + codeBlockedMethods?: string[] | undefined; }; export function parseCLIOptions(): CLIOptions { const opts = yargs(hideBin(process.argv)) + .option('code-allow-http-gets', { + type: 'boolean', + description: + 'Allow all code tool methods that map to HTTP GET operations. If all code-allow-* flags are unset, then everything is allowed.', + }) + .option('code-allowed-methods', { + type: 'string', + array: true, + description: + 'Methods to explicitly allow for code tool. Evaluated as regular expressions against method fully qualified names. If all code-allow-* flags are unset, then everything is allowed.', + }) + .option('code-blocked-methods', { + type: 'string', + array: true, + description: + 'Methods to explicitly block for code tool. Evaluated as regular expressions against method fully qualified names. If all code-allow-* flags are unset, then everything is allowed.', + }) .option('debug', { type: 'boolean', description: 'Enable debug logging' }) .option('no-tools', { type: 'string', @@ -59,6 +79,9 @@ export function parseCLIOptions(): CLIOptions { return { ...(includeDocsTools !== undefined && { includeDocsTools }), debug: !!argv.debug, + codeAllowHttpGets: argv.codeAllowHttpGets, + codeAllowedMethods: argv.codeAllowedMethods, + codeBlockedMethods: argv.codeBlockedMethods, transport, port: argv.port, socket: argv.socket, diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 5bc14968..54fe73ef 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -12,6 +12,7 @@ import Beagle from '@corgi-tech/beagle'; import { codeTool } from './code-tool'; import docsSearchTool from './docs-search-tool'; import { McpOptions } from './options'; +import { blockedMethodsForCodeTool } from './methods'; import { HandlerFunction, McpTool } from './types'; export { McpOptions } from './options'; @@ -148,7 +149,11 @@ export async function initMcpServer(params: { * Selects the tools to include in the MCP Server based on the provided options. */ export function selectTools(options?: McpOptions): McpTool[] { - const includedTools = [codeTool()]; + const includedTools = [ + codeTool({ + blockedMethods: blockedMethodsForCodeTool(options), + }), + ]; if (options?.includeDocsTools ?? true) { includedTools.push(docsSearchTool); } diff --git a/packages/mcp-server/src/stdio.ts b/packages/mcp-server/src/stdio.ts index 47aeb0c9..57b99126 100644 --- a/packages/mcp-server/src/stdio.ts +++ b/packages/mcp-server/src/stdio.ts @@ -1,10 +1,11 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; +import { McpOptions } from './options'; import { initMcpServer, newMcpServer } from './server'; -export const launchStdioServer = async () => { +export const launchStdioServer = async (mcpOptions: McpOptions) => { const server = await newMcpServer(); - await initMcpServer({ server }); + await initMcpServer({ server, mcpOptions }); const transport = new StdioServerTransport(); await server.connect(transport); From 7247d7ba2bf1e0a328d1a04a8d6754b70798a2ad Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 11 Feb 2026 12:43:46 +0000 Subject: [PATCH 080/138] chore(internal): codegen related update --- src/resources/enrollments.ts | 6 +++--- src/resources/property-managers.ts | 6 +++--- src/resources/tenants.ts | 10 +++------- src/resources/webhook/endpoints.ts | 6 +++--- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/resources/enrollments.ts b/src/resources/enrollments.ts index 4703a9b1..087e2e13 100644 --- a/src/resources/enrollments.ts +++ b/src/resources/enrollments.ts @@ -35,7 +35,7 @@ export class Enrollments extends APIResource { * const enrollment = await client.enrollments.retrieve(123); * ``` */ - retrieve(id: number | null, options?: RequestOptions): APIPromise { + retrieve(id: number, options?: RequestOptions): APIPromise { return this._client.get(path`/api/enrollments/${id}`, options); } @@ -64,7 +64,7 @@ export class Enrollments extends APIResource { * await client.enrollments.lapse(123); * ``` */ - lapse(id: number | null, options?: RequestOptions): APIPromise { + lapse(id: number, options?: RequestOptions): APIPromise { return this._client.delete(path`/api/enrollments/${id}`, { ...options, headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), @@ -83,7 +83,7 @@ export class Enrollments extends APIResource { * console.log(content); * ``` */ - retrieveCertificate(id: number | null, options?: RequestOptions): APIPromise { + retrieveCertificate(id: number, options?: RequestOptions): APIPromise { return this._client.get(path`/api/enrollments/${id}/certificate`, { ...options, headers: buildHeaders([{ Accept: 'application/pdf' }, options?.headers]), diff --git a/src/resources/property-managers.ts b/src/resources/property-managers.ts index 0fe32d1a..e9b5debe 100644 --- a/src/resources/property-managers.ts +++ b/src/resources/property-managers.ts @@ -52,7 +52,7 @@ export class PropertyManagers extends APIResource { * await client.propertyManagers.retrieve(123); * ``` */ - retrieve(id: number | null, options?: RequestOptions): APIPromise { + retrieve(id: number, options?: RequestOptions): APIPromise { return this._client.get(path`/api/property-managers/${id}`, options); } @@ -67,7 +67,7 @@ export class PropertyManagers extends APIResource { * ``` */ update( - id: number | null, + id: number, body: PropertyManagerUpdateParams, options?: RequestOptions, ): APIPromise { @@ -98,7 +98,7 @@ export class PropertyManagers extends APIResource { * await client.propertyManagers.delete(123); * ``` */ - delete(id: number | null, options?: RequestOptions): APIPromise { + delete(id: number, options?: RequestOptions): APIPromise { return this._client.delete(path`/api/property-managers/${id}`, { ...options, headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), diff --git a/src/resources/tenants.ts b/src/resources/tenants.ts index fd1906a0..8dbb94c0 100644 --- a/src/resources/tenants.ts +++ b/src/resources/tenants.ts @@ -41,7 +41,7 @@ export class Tenants extends APIResource { * const tenant = await client.tenants.retrieve(123); * ``` */ - retrieve(id: number | null, options?: RequestOptions): APIPromise { + retrieve(id: number, options?: RequestOptions): APIPromise { return this._client.get(path`/api/tenants/${id}`, options); } @@ -53,11 +53,7 @@ export class Tenants extends APIResource { * const tenant = await client.tenants.update(123); * ``` */ - update( - id: number | null, - body: TenantUpdateParams, - options?: RequestOptions, - ): APIPromise { + update(id: number, body: TenantUpdateParams, options?: RequestOptions): APIPromise { return this._client.patch(path`/api/tenants/${id}`, { body, ...options }); } @@ -85,7 +81,7 @@ export class Tenants extends APIResource { * await client.tenants.delete(123); * ``` */ - delete(id: number | null, options?: RequestOptions): APIPromise { + delete(id: number, options?: RequestOptions): APIPromise { return this._client.delete(path`/api/tenants/${id}`, { ...options, headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), diff --git a/src/resources/webhook/endpoints.ts b/src/resources/webhook/endpoints.ts index 026aa710..3a79c55d 100644 --- a/src/resources/webhook/endpoints.ts +++ b/src/resources/webhook/endpoints.ts @@ -18,7 +18,7 @@ export class Endpoints extends APIResource { /** * retrieve a single webhook endpoint by its id. */ - retrieve(id: number | null, options?: RequestOptions): APIPromise { + retrieve(id: number, options?: RequestOptions): APIPromise { return this._client.get(path`/api/webhook/endpoints/${id}`, options); } @@ -26,7 +26,7 @@ export class Endpoints extends APIResource { * update an existing webhook endpoint by its id. */ update( - id: number | null, + id: number, body: EndpointUpdateParams, options?: RequestOptions, ): APIPromise { @@ -47,7 +47,7 @@ export class Endpoints extends APIResource { /** * delete an existing webhook endpoint by its id. */ - delete(id: number | null, options?: RequestOptions): APIPromise { + delete(id: number, options?: RequestOptions): APIPromise { return this._client.delete(path`/api/webhook/endpoints/${id}`, { ...options, headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), From f51ff818983d9d6474a8b367e8d3d9c8ddec1429 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 12 Feb 2026 15:38:59 +0000 Subject: [PATCH 081/138] chore(internal): codegen related update --- src/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.ts b/src/client.ts index 27703123..2dbe6340 100644 --- a/src/client.ts +++ b/src/client.ts @@ -524,7 +524,7 @@ export class Beagle { loggerFor(this).info(`${responseInfo} - ${retryMessage}`); const errText = await response.text().catch((err: any) => castToError(err).message); - const errJSON = safeJSON(errText); + const errJSON = safeJSON(errText) as any; const errMessage = errJSON ? undefined : errText; loggerFor(this).debug( From 9bb2822d8a46d582cd0042ee5b22dc837cd8babc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 14 Feb 2026 10:22:44 +0000 Subject: [PATCH 082/138] chore(internal): codegen related update --- .../mcp-server/src/{headers.ts => auth.ts} | 0 packages/mcp-server/src/code-tool.ts | 2 +- packages/mcp-server/src/docs-search-tool.ts | 8 +++++- packages/mcp-server/src/http.ts | 5 ++-- packages/mcp-server/src/methods.ts | 2 ++ packages/mcp-server/src/options.ts | 2 ++ packages/mcp-server/src/server.ts | 28 +------------------ packages/mcp-server/src/util.ts | 25 +++++++++++++++++ 8 files changed, 41 insertions(+), 31 deletions(-) rename packages/mcp-server/src/{headers.ts => auth.ts} (100%) create mode 100644 packages/mcp-server/src/util.ts diff --git a/packages/mcp-server/src/headers.ts b/packages/mcp-server/src/auth.ts similarity index 100% rename from packages/mcp-server/src/headers.ts rename to packages/mcp-server/src/auth.ts diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 96850463..a9cb0893 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -2,7 +2,7 @@ import { McpTool, Metadata, ToolCallResult, asErrorResult, asTextContentResult } from './types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import { readEnv, requireValue } from './server'; +import { readEnv, requireValue } from './util'; import { WorkerInput, WorkerOutput } from './code-tool-types'; import { SdkMethod } from './methods'; import { Beagle } from '@corgi-tech/beagle'; diff --git a/packages/mcp-server/src/docs-search-tool.ts b/packages/mcp-server/src/docs-search-tool.ts index d4a4fc8d..22eb85a5 100644 --- a/packages/mcp-server/src/docs-search-tool.ts +++ b/packages/mcp-server/src/docs-search-tool.ts @@ -1,6 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { Metadata, asTextContentResult } from './types'; +import { readEnv } from './util'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; @@ -45,7 +46,12 @@ const docsSearchURL = export const handler = async (_: unknown, args: Record | undefined) => { const body = args as any; const query = new URLSearchParams(body).toString(); - const result = await fetch(`${docsSearchURL}?${query}`); + const stainlessAPIKey = readEnv('STAINLESS_API_KEY'); + const result = await fetch(`${docsSearchURL}?${query}`, { + headers: { + ...(stainlessAPIKey && { Authorization: stainlessAPIKey }), + }, + }); if (!result.ok) { throw new Error( diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index 8ca827c2..b0b38e6c 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -2,12 +2,13 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; +import { ClientOptions } from '@corgi-tech/beagle'; import express from 'express'; import morgan from 'morgan'; import morganBody from 'morgan-body'; +import { parseAuthHeaders } from './auth'; import { McpOptions } from './options'; -import { ClientOptions, initMcpServer, newMcpServer } from './server'; -import { parseAuthHeaders } from './headers'; +import { initMcpServer, newMcpServer } from './server'; const newServer = async ({ clientOptions, diff --git a/packages/mcp-server/src/methods.ts b/packages/mcp-server/src/methods.ts index 483dca51..8e644551 100644 --- a/packages/mcp-server/src/methods.ts +++ b/packages/mcp-server/src/methods.ts @@ -1,3 +1,5 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + import { McpOptions } from './options'; export type SdkMethod = { diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index 92d1b074..cfde21d0 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -1,3 +1,5 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + import qs from 'qs'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 54fe73ef..808f73e8 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -14,9 +14,7 @@ import docsSearchTool from './docs-search-tool'; import { McpOptions } from './options'; import { blockedMethodsForCodeTool } from './methods'; import { HandlerFunction, McpTool } from './types'; - -export { McpOptions } from './options'; -export { ClientOptions } from '@corgi-tech/beagle'; +import { readEnv } from './util'; async function getInstructions() { // This API key is optional; providing it allows the server to fetch instructions for unreleased versions. @@ -170,27 +168,3 @@ export async function executeHandler( ) { return await handler(client, args || {}); } - -export const readEnv = (env: string): string | undefined => { - if (typeof (globalThis as any).process !== 'undefined') { - return (globalThis as any).process.env?.[env]?.trim(); - } else if (typeof (globalThis as any).Deno !== 'undefined') { - return (globalThis as any).Deno.env?.get?.(env)?.trim(); - } - return; -}; - -export const readEnvOrError = (env: string): string => { - let envValue = readEnv(env); - if (envValue === undefined) { - throw new Error(`Environment variable ${env} is not set`); - } - return envValue; -}; - -export const requireValue = (value: T | undefined, description: string): T => { - if (value === undefined) { - throw new Error(`Missing required value: ${description}`); - } - return value; -}; diff --git a/packages/mcp-server/src/util.ts b/packages/mcp-server/src/util.ts new file mode 100644 index 00000000..40ed5501 --- /dev/null +++ b/packages/mcp-server/src/util.ts @@ -0,0 +1,25 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export const readEnv = (env: string): string | undefined => { + if (typeof (globalThis as any).process !== 'undefined') { + return (globalThis as any).process.env?.[env]?.trim(); + } else if (typeof (globalThis as any).Deno !== 'undefined') { + return (globalThis as any).Deno.env?.get?.(env)?.trim(); + } + return; +}; + +export const readEnvOrError = (env: string): string => { + let envValue = readEnv(env); + if (envValue === undefined) { + throw new Error(`Environment variable ${env} is not set`); + } + return envValue; +}; + +export const requireValue = (value: T | undefined, description: string): T => { + if (value === undefined) { + throw new Error(`Missing required value: ${description}`); + } + return value; +}; From 40f63e208dd454a7f2d68ebe64e419b7f1becb3a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 09:43:10 +0000 Subject: [PATCH 083/138] chore(internal): codegen related update --- packages/mcp-server/src/auth.ts | 17 ++++++++- packages/mcp-server/src/code-tool.ts | 33 ++++++++++------- packages/mcp-server/src/docs-search-tool.ts | 15 ++++---- packages/mcp-server/src/http.ts | 21 +++++++---- packages/mcp-server/src/options.ts | 9 +++++ packages/mcp-server/src/server.ts | 40 +++++++++++++-------- packages/mcp-server/src/stdio.ts | 4 +-- packages/mcp-server/src/types.ts | 16 ++++++--- src/client.ts | 8 +++++ 9 files changed, 117 insertions(+), 46 deletions(-) diff --git a/packages/mcp-server/src/auth.ts b/packages/mcp-server/src/auth.ts index 5f78b71b..f25e9eac 100644 --- a/packages/mcp-server/src/auth.ts +++ b/packages/mcp-server/src/auth.ts @@ -2,9 +2,24 @@ import { IncomingMessage } from 'node:http'; import { ClientOptions } from '@corgi-tech/beagle'; +import { McpOptions } from './options'; -export const parseAuthHeaders = (req: IncomingMessage, required?: boolean): Partial => { +export const parseClientAuthHeaders = (req: IncomingMessage, required?: boolean): Partial => { const apiKey = Array.isArray(req.headers['x-api-key']) ? req.headers['x-api-key'][0] : req.headers['x-api-key']; return { apiKey }; }; + +export const getStainlessApiKey = (req: IncomingMessage, mcpOptions: McpOptions): string | undefined => { + // Try to get the key from the x-stainless-api-key header + const headerKey = + Array.isArray(req.headers['x-stainless-api-key']) ? + req.headers['x-stainless-api-key'][0] + : req.headers['x-stainless-api-key']; + if (headerKey && typeof headerKey === 'string') { + return headerKey; + } + + // Fall back to value set in the mcpOptions (e.g. from environment variable), if provided + return mcpOptions.stainlessApiKey; +}; diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index a9cb0893..6f8b1384 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -1,11 +1,17 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { McpTool, Metadata, ToolCallResult, asErrorResult, asTextContentResult } from './types'; +import { + McpRequestContext, + McpTool, + Metadata, + ToolCallResult, + asErrorResult, + asTextContentResult, +} from './types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import { readEnv, requireValue } from './util'; import { WorkerInput, WorkerOutput } from './code-tool-types'; import { SdkMethod } from './methods'; -import { Beagle } from '@corgi-tech/beagle'; const prompt = `Runs JavaScript code to interact with the Beagle API. @@ -36,7 +42,7 @@ Variables will not persist between calls, so make sure to return or log any data * * @param endpoints - The endpoints to include in the list. */ -export function codeTool(params: { blockedMethods: SdkMethod[] | undefined }): McpTool { +export function codeTool({ blockedMethods }: { blockedMethods: SdkMethod[] | undefined }): McpTool { const metadata: Metadata = { resource: 'all', operation: 'write', tags: [] }; const tool: Tool = { name: 'execute', @@ -56,19 +62,24 @@ export function codeTool(params: { blockedMethods: SdkMethod[] | undefined }): M required: ['code'], }, }; - const handler = async (client: Beagle, args: any): Promise => { + const handler = async ({ + reqContext, + args, + }: { + reqContext: McpRequestContext; + args: any; + }): Promise => { const code = args.code as string; const intent = args.intent as string | undefined; + const client = reqContext.client; // Do very basic blocking of code that includes forbidden method names. // // WARNING: This is not secure against obfuscation and other evasion methods. If // stronger security blocks are required, then these should be enforced in the downstream // API (e.g., by having users call the MCP server with API keys with limited permissions). - if (params.blockedMethods) { - const blockedMatches = params.blockedMethods.filter((method) => - code.includes(method.fullyQualifiedName), - ); + if (blockedMethods) { + const blockedMatches = blockedMethods.filter((method) => code.includes(method.fullyQualifiedName)); if (blockedMatches.length > 0) { return asErrorResult( `The following methods have been blocked by the MCP server and cannot be used in code execution: ${blockedMatches @@ -78,16 +89,14 @@ export function codeTool(params: { blockedMethods: SdkMethod[] | undefined }): M } } - // this is not required, but passing a Stainless API key for the matching project_name - // will allow you to run code-mode queries against non-published versions of your SDK. - const stainlessAPIKey = readEnv('STAINLESS_API_KEY'); const codeModeEndpoint = readEnv('CODE_MODE_ENDPOINT_URL') ?? 'https://api.stainless.com/api/ai/code-tool'; + // Setting a Stainless API key authenticates requests to the code tool endpoint. const res = await fetch(codeModeEndpoint, { method: 'POST', headers: { - ...(stainlessAPIKey && { Authorization: stainlessAPIKey }), + ...(reqContext.stainlessApiKey && { Authorization: reqContext.stainlessApiKey }), 'Content-Type': 'application/json', client_envs: JSON.stringify({ BEAGLE_API_KEY: requireValue( diff --git a/packages/mcp-server/src/docs-search-tool.ts b/packages/mcp-server/src/docs-search-tool.ts index 22eb85a5..7b3f203f 100644 --- a/packages/mcp-server/src/docs-search-tool.ts +++ b/packages/mcp-server/src/docs-search-tool.ts @@ -1,8 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Metadata, asTextContentResult } from './types'; -import { readEnv } from './util'; - +import { Metadata, McpRequestContext, asTextContentResult } from './types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; export const metadata: Metadata = { @@ -43,13 +41,18 @@ export const tool: Tool = { const docsSearchURL = process.env['DOCS_SEARCH_URL'] || 'https://api.stainless.com/api/projects/beagle/docs/search'; -export const handler = async (_: unknown, args: Record | undefined) => { +export const handler = async ({ + reqContext, + args, +}: { + reqContext: McpRequestContext; + args: Record | undefined; +}) => { const body = args as any; const query = new URLSearchParams(body).toString(); - const stainlessAPIKey = readEnv('STAINLESS_API_KEY'); const result = await fetch(`${docsSearchURL}?${query}`, { headers: { - ...(stainlessAPIKey && { Authorization: stainlessAPIKey }), + ...(reqContext.stainlessApiKey && { Authorization: reqContext.stainlessApiKey }), }, }); diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index b0b38e6c..c55a178d 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -6,7 +6,7 @@ import { ClientOptions } from '@corgi-tech/beagle'; import express from 'express'; import morgan from 'morgan'; import morganBody from 'morgan-body'; -import { parseAuthHeaders } from './auth'; +import { getStainlessApiKey, parseClientAuthHeaders } from './auth'; import { McpOptions } from './options'; import { initMcpServer, newMcpServer } from './server'; @@ -21,10 +21,12 @@ const newServer = async ({ req: express.Request; res: express.Response; }): Promise => { - const server = await newMcpServer(); + const stainlessApiKey = getStainlessApiKey(req, mcpOptions); + const server = await newMcpServer(stainlessApiKey); try { - const authOptions = parseAuthHeaders(req, false); + const authOptions = parseClientAuthHeaders(req, false); + await initMcpServer({ server: server, mcpOptions: mcpOptions, @@ -32,6 +34,7 @@ const newServer = async ({ ...clientOptions, ...authOptions, }, + stainlessApiKey: stainlessApiKey, }); } catch (error) { res.status(401).json({ @@ -112,13 +115,17 @@ export const streamableHTTPApp = ({ return app; }; -export const launchStreamableHTTPServer = async (params: { +export const launchStreamableHTTPServer = async ({ + mcpOptions, + debug, + port, +}: { mcpOptions: McpOptions; debug: boolean; port: number | string | undefined; }) => { - const app = streamableHTTPApp({ mcpOptions: params.mcpOptions, debug: params.debug }); - const server = app.listen(params.port); + const app = streamableHTTPApp({ mcpOptions, debug }); + const server = app.listen(port); const address = server.address(); if (typeof address === 'string') { @@ -126,6 +133,6 @@ export const launchStreamableHTTPServer = async (params: { } else if (address !== null) { console.error(`MCP Server running on streamable HTTP on port ${address.port}`); } else { - console.error(`MCP Server running on streamable HTTP on port ${params.port}`); + console.error(`MCP Server running on streamable HTTP on port ${port}`); } }; diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index cfde21d0..32a88713 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -4,6 +4,7 @@ import qs from 'qs'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; import z from 'zod'; +import { readEnv } from './util'; export type CLIOptions = McpOptions & { debug: boolean; @@ -14,6 +15,7 @@ export type CLIOptions = McpOptions & { export type McpOptions = { includeDocsTools?: boolean | undefined; + stainlessApiKey?: string | undefined; codeAllowHttpGets?: boolean | undefined; codeAllowedMethods?: string[] | undefined; codeBlockedMethods?: string[] | undefined; @@ -51,6 +53,12 @@ export function parseCLIOptions(): CLIOptions { description: 'Port to serve on if using http transport', }) .option('socket', { type: 'string', description: 'Unix socket to serve on if using http transport' }) + .option('stainless-api-key', { + type: 'string', + default: readEnv('STAINLESS_API_KEY'), + description: + 'API key for Stainless. Used to authenticate requests to Stainless-hosted tools endpoints.', + }) .option('tools', { type: 'string', array: true, @@ -81,6 +89,7 @@ export function parseCLIOptions(): CLIOptions { return { ...(includeDocsTools !== undefined && { includeDocsTools }), debug: !!argv.debug, + stainlessApiKey: argv.stainlessApiKey, codeAllowHttpGets: argv.codeAllowHttpGets, codeAllowedMethods: argv.codeAllowedMethods, codeBlockedMethods: argv.codeBlockedMethods, diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 808f73e8..4037f5c7 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -13,17 +13,17 @@ import { codeTool } from './code-tool'; import docsSearchTool from './docs-search-tool'; import { McpOptions } from './options'; import { blockedMethodsForCodeTool } from './methods'; -import { HandlerFunction, McpTool } from './types'; +import { HandlerFunction, McpRequestContext, ToolCallResult, McpTool } from './types'; import { readEnv } from './util'; -async function getInstructions() { - // This API key is optional; providing it allows the server to fetch instructions for unreleased versions. - const stainlessAPIKey = readEnv('STAINLESS_API_KEY'); +async function getInstructions(stainlessApiKey: string | undefined): Promise { + // Setting the stainless API key is optional, but may be required + // to authenticate requests to the Stainless API. const response = await fetch( readEnv('CODE_MODE_INSTRUCTIONS_URL') ?? 'https://api.stainless.com/api/ai/instructions/beagle', { method: 'GET', - headers: { ...(stainlessAPIKey && { Authorization: stainlessAPIKey }) }, + headers: { ...(stainlessApiKey && { Authorization: stainlessApiKey }) }, }, ); @@ -52,14 +52,14 @@ async function getInstructions() { return instructions; } -export const newMcpServer = async () => +export const newMcpServer = async (stainlessApiKey: string | undefined) => new McpServer( { name: 'corgi_tech_beagle_api', version: '0.0.1-alpha.0', }, { - instructions: await getInstructions(), + instructions: await getInstructions(stainlessApiKey), capabilities: { tools: {}, logging: {} }, }, ); @@ -72,6 +72,7 @@ export async function initMcpServer(params: { server: Server | McpServer; clientOptions?: ClientOptions; mcpOptions?: McpOptions; + stainlessApiKey?: string | undefined; }) { const server = params.server instanceof McpServer ? params.server.server : params.server; @@ -116,7 +117,14 @@ export async function initMcpServer(params: { throw new Error(`Unknown tool: ${name}`); } - return executeHandler(mcpTool.handler, client, args); + return executeHandler({ + handler: mcpTool.handler, + reqContext: { + client, + stainlessApiKey: params.stainlessApiKey ?? params.mcpOptions?.stainlessApiKey, + }, + args, + }); }); server.setRequestHandler(SetLevelRequestSchema, async (request) => { @@ -161,10 +169,14 @@ export function selectTools(options?: McpOptions): McpTool[] { /** * Runs the provided handler with the given client and arguments. */ -export async function executeHandler( - handler: HandlerFunction, - client: Beagle, - args: Record | undefined, -) { - return await handler(client, args || {}); +export async function executeHandler({ + handler, + reqContext, + args, +}: { + handler: HandlerFunction; + reqContext: McpRequestContext; + args: Record | undefined; +}): Promise { + return await handler({ reqContext, args: args || {} }); } diff --git a/packages/mcp-server/src/stdio.ts b/packages/mcp-server/src/stdio.ts index 57b99126..ceccaed3 100644 --- a/packages/mcp-server/src/stdio.ts +++ b/packages/mcp-server/src/stdio.ts @@ -3,9 +3,9 @@ import { McpOptions } from './options'; import { initMcpServer, newMcpServer } from './server'; export const launchStdioServer = async (mcpOptions: McpOptions) => { - const server = await newMcpServer(); + const server = await newMcpServer(mcpOptions.stainlessApiKey); - await initMcpServer({ server, mcpOptions }); + await initMcpServer({ server, mcpOptions, stainlessApiKey: mcpOptions.stainlessApiKey }); const transport = new StdioServerTransport(); await server.connect(transport); diff --git a/packages/mcp-server/src/types.ts b/packages/mcp-server/src/types.ts index 9e4179f9..038c3985 100644 --- a/packages/mcp-server/src/types.ts +++ b/packages/mcp-server/src/types.ts @@ -42,10 +42,18 @@ export type ToolCallResult = { isError?: boolean; }; -export type HandlerFunction = ( - client: Beagle, - args: Record | undefined, -) => Promise; +export type McpRequestContext = { + client: Beagle; + stainlessApiKey?: string | undefined; +}; + +export type HandlerFunction = ({ + reqContext, + args, +}: { + reqContext: McpRequestContext; + args: Record | undefined; +}) => Promise; export function asTextContentResult(result: unknown): ToolCallResult { return { diff --git a/src/client.ts b/src/client.ts index 2dbe6340..a7cb70a1 100644 --- a/src/client.ts +++ b/src/client.ts @@ -797,6 +797,14 @@ export class Beagle { (Symbol.iterator in body && 'next' in body && typeof body.next === 'function')) ) { return { bodyHeaders: undefined, body: Shims.ReadableStreamFrom(body as AsyncIterable) }; + } else if ( + typeof body === 'object' && + headers.values.get('content-type') === 'application/x-www-form-urlencoded' + ) { + return { + bodyHeaders: { 'content-type': 'application/x-www-form-urlencoded' }, + body: this.stringifyQuery(body as Record), + }; } else { return this.#encoder({ body, headers }); } From ba5a41e81c157bc49fda7d9bff1ab01e960d4bfc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 19 Feb 2026 09:41:13 +0000 Subject: [PATCH 084/138] chore(internal): codegen related update --- packages/mcp-server/src/instructions.ts | 74 +++++++++++++++++++++++++ packages/mcp-server/src/server.ts | 37 +------------ 2 files changed, 75 insertions(+), 36 deletions(-) create mode 100644 packages/mcp-server/src/instructions.ts diff --git a/packages/mcp-server/src/instructions.ts b/packages/mcp-server/src/instructions.ts new file mode 100644 index 00000000..1e78fa59 --- /dev/null +++ b/packages/mcp-server/src/instructions.ts @@ -0,0 +1,74 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { readEnv } from './util'; + +const INSTRUCTIONS_CACHE_TTL_MS = 15 * 60 * 1000; // 15 minutes + +interface InstructionsCacheEntry { + fetchedInstructions: string; + fetchedAt: number; +} + +const instructionsCache = new Map(); + +// Periodically evict stale entries so the cache doesn't grow unboundedly. +const _cacheCleanupInterval = setInterval(() => { + const now = Date.now(); + for (const [key, entry] of instructionsCache) { + if (now - entry.fetchedAt > INSTRUCTIONS_CACHE_TTL_MS) { + instructionsCache.delete(key); + } + } +}, INSTRUCTIONS_CACHE_TTL_MS); + +// Don't keep the process alive just for cleanup. +_cacheCleanupInterval.unref(); + +export async function getInstructions(stainlessApiKey: string | undefined): Promise { + const cacheKey = stainlessApiKey ?? ''; + const cached = instructionsCache.get(cacheKey); + + if (cached && Date.now() - cached.fetchedAt <= INSTRUCTIONS_CACHE_TTL_MS) { + return cached.fetchedInstructions; + } + + const fetchedInstructions = await fetchLatestInstructions(stainlessApiKey); + instructionsCache.set(cacheKey, { fetchedInstructions, fetchedAt: Date.now() }); + return fetchedInstructions; +} + +async function fetchLatestInstructions(stainlessApiKey: string | undefined): Promise { + // Setting the stainless API key is optional, but may be required + // to authenticate requests to the Stainless API. + const response = await fetch( + readEnv('CODE_MODE_INSTRUCTIONS_URL') ?? 'https://api.stainless.com/api/ai/instructions/beagle', + { + method: 'GET', + headers: { ...(stainlessApiKey && { Authorization: stainlessApiKey }) }, + }, + ); + + let instructions: string | undefined; + if (!response.ok) { + console.warn( + 'Warning: failed to retrieve MCP server instructions. Proceeding with default instructions...', + ); + + instructions = ` + This is the beagle MCP server. You will use Code Mode to help the user perform + actions. You can use search_docs tool to learn about how to take action with this server. Then, + you will write TypeScript code using the execute tool take action. It is CRITICAL that you be + thoughtful and deliberate when executing code. Always try to entirely solve the problem in code + block: it can be as long as you need to get the job done! + `; + } + + instructions ??= ((await response.json()) as { instructions: string }).instructions; + instructions = ` + If needed, you can get the current time by executing Date.now(). + + ${instructions} + `; + + return instructions; +} diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 4037f5c7..0f3fc7cb 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -11,47 +11,12 @@ import { ClientOptions } from '@corgi-tech/beagle'; import Beagle from '@corgi-tech/beagle'; import { codeTool } from './code-tool'; import docsSearchTool from './docs-search-tool'; +import { getInstructions } from './instructions'; import { McpOptions } from './options'; import { blockedMethodsForCodeTool } from './methods'; import { HandlerFunction, McpRequestContext, ToolCallResult, McpTool } from './types'; import { readEnv } from './util'; -async function getInstructions(stainlessApiKey: string | undefined): Promise { - // Setting the stainless API key is optional, but may be required - // to authenticate requests to the Stainless API. - const response = await fetch( - readEnv('CODE_MODE_INSTRUCTIONS_URL') ?? 'https://api.stainless.com/api/ai/instructions/beagle', - { - method: 'GET', - headers: { ...(stainlessApiKey && { Authorization: stainlessApiKey }) }, - }, - ); - - let instructions: string | undefined; - if (!response.ok) { - console.warn( - 'Warning: failed to retrieve MCP server instructions. Proceeding with default instructions...', - ); - - instructions = ` - This is the beagle MCP server. You will use Code Mode to help the user perform - actions. You can use search_docs tool to learn about how to take action with this server. Then, - you will write TypeScript code using the execute tool take action. It is CRITICAL that you be - thoughtful and deliberate when executing code. Always try to entirely solve the problem in code - block: it can be as long as you need to get the job done! - `; - } - - instructions ??= ((await response.json()) as { instructions: string }).instructions; - instructions = ` - The current time in Unix timestamps is ${Date.now()}. - - ${instructions} - `; - - return instructions; -} - export const newMcpServer = async (stainlessApiKey: string | undefined) => new McpServer( { From 23c144132a69e9703f64c1700ab693dcee45dac4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 19 Feb 2026 17:31:14 +0000 Subject: [PATCH 085/138] feat(api): api update --- .stats.yml | 4 +- CONTRIBUTING.md | 6 -- packages/mcp-server/src/http.ts | 31 +++------ packages/mcp-server/src/index.ts | 2 +- packages/mcp-server/src/server.ts | 66 +++++++++++++++---- scripts/mock | 41 ------------ scripts/test | 46 ------------- tests/api-resources/enrollments.test.ts | 12 ++-- .../insurance-verification.test.ts | 4 +- tests/api-resources/plans.test.ts | 4 +- tests/api-resources/property-managers.test.ts | 14 ++-- tests/api-resources/tenants.test.ts | 14 ++-- tests/api-resources/webhook/endpoints.test.ts | 16 ++--- 13 files changed, 97 insertions(+), 163 deletions(-) delete mode 100755 scripts/mock diff --git a/.stats.yml b/.stats.yml index d54b2466..749dd7be 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 23 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-cd8cc6696f901a410f58cf964cff1b0bd0d5b7863ddd4e4f66301674465c9d02.yml -openapi_spec_hash: 10752adafce32e55a442b0c835ae567d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-5ab1daf2e9cd2b373093fdbd17460f248ae9247728df3710bab5bfb603cf20e1.yml +openapi_spec_hash: be884fdd7ed2976a88f4f5396ccdacb2 config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 547acc18..4b66acfb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -65,12 +65,6 @@ $ pnpm link -—global @corgi-tech/beagle ## 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. - -```sh -$ npx prism mock path/to/your/openapi.yml -``` - ```sh $ yarn run test ``` diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index c55a178d..7cd88046 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -24,28 +24,17 @@ const newServer = async ({ const stainlessApiKey = getStainlessApiKey(req, mcpOptions); const server = await newMcpServer(stainlessApiKey); - try { - const authOptions = parseClientAuthHeaders(req, false); + const authOptions = parseClientAuthHeaders(req, false); - await initMcpServer({ - server: server, - mcpOptions: mcpOptions, - clientOptions: { - ...clientOptions, - ...authOptions, - }, - stainlessApiKey: stainlessApiKey, - }); - } catch (error) { - res.status(401).json({ - jsonrpc: '2.0', - error: { - code: -32000, - message: `Unauthorized: ${error instanceof Error ? error.message : error}`, - }, - }); - return null; - } + await initMcpServer({ + server: server, + mcpOptions: mcpOptions, + clientOptions: { + ...clientOptions, + ...authOptions, + }, + stainlessApiKey: stainlessApiKey, + }); return server; }; diff --git a/packages/mcp-server/src/index.ts b/packages/mcp-server/src/index.ts index 003a7655..654d25cf 100644 --- a/packages/mcp-server/src/index.ts +++ b/packages/mcp-server/src/index.ts @@ -24,7 +24,7 @@ async function main() { await launchStreamableHTTPServer({ mcpOptions: options, debug: options.debug, - port: options.port ?? options.socket, + port: options.socket ?? options.port, }); break; } diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 0f3fc7cb..22cd0dbe 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -56,15 +56,33 @@ export async function initMcpServer(params: { error: logAtLevel('error'), }; - let client = new Beagle({ - ...{ environment: (readEnv('BEAGLE_ENVIRONMENT') || undefined) as any }, - logger, - ...params.clientOptions, - defaultHeaders: { - ...params.clientOptions?.defaultHeaders, - 'X-Stainless-MCP': 'true', - }, - }); + let _client: Beagle | undefined; + let _clientError: Error | undefined; + let _logLevel: 'debug' | 'info' | 'warn' | 'error' | 'off' | undefined; + + const getClient = (): Beagle => { + if (_clientError) throw _clientError; + if (!_client) { + try { + _client = new Beagle({ + ...{ environment: (readEnv('BEAGLE_ENVIRONMENT') || undefined) as any }, + logger, + ...params.clientOptions, + defaultHeaders: { + ...params.clientOptions?.defaultHeaders, + 'X-Stainless-MCP': 'true', + }, + }); + if (_logLevel) { + _client = _client.withOptions({ logLevel: _logLevel }); + } + } catch (e) { + _clientError = e instanceof Error ? e : new Error(String(e)); + throw _clientError; + } + } + return _client; + }; const providedTools = selectTools(params.mcpOptions); const toolMap = Object.fromEntries(providedTools.map((mcpTool) => [mcpTool.tool.name, mcpTool])); @@ -82,6 +100,21 @@ export async function initMcpServer(params: { throw new Error(`Unknown tool: ${name}`); } + let client: Beagle; + try { + client = getClient(); + } catch (error) { + return { + content: [ + { + type: 'text' as const, + text: `Failed to initialize client: ${error instanceof Error ? error.message : String(error)}`, + }, + ], + isError: true, + }; + } + return executeHandler({ handler: mcpTool.handler, reqContext: { @@ -94,24 +127,29 @@ export async function initMcpServer(params: { server.setRequestHandler(SetLevelRequestSchema, async (request) => { const { level } = request.params; + let logLevel: 'debug' | 'info' | 'warn' | 'error' | 'off'; switch (level) { case 'debug': - client = client.withOptions({ logLevel: 'debug' }); + logLevel = 'debug'; break; case 'info': - client = client.withOptions({ logLevel: 'info' }); + logLevel = 'info'; break; case 'notice': case 'warning': - client = client.withOptions({ logLevel: 'warn' }); + logLevel = 'warn'; break; case 'error': - client = client.withOptions({ logLevel: 'error' }); + logLevel = 'error'; break; default: - client = client.withOptions({ logLevel: 'off' }); + logLevel = 'off'; break; } + _logLevel = logLevel; + if (_client) { + _client = _client.withOptions({ logLevel }); + } return {}; }); } diff --git a/scripts/mock b/scripts/mock deleted file mode 100755 index 0b28f6ea..00000000 --- a/scripts/mock +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env bash - -set -e - -cd "$(dirname "$0")/.." - -if [[ -n "$1" && "$1" != '--'* ]]; then - URL="$1" - shift -else - URL="$(grep 'openapi_spec_url' .stats.yml | cut -d' ' -f2)" -fi - -# Check if the URL is empty -if [ -z "$URL" ]; then - echo "Error: No OpenAPI spec path/url provided or found in .stats.yml" - exit 1 -fi - -echo "==> Starting mock server with URL ${URL}" - -# Run prism mock on the given spec -if [ "$1" == "--daemon" ]; then - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & - - # Wait for server to come online - echo -n "Waiting for server" - while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do - echo -n "." - sleep 0.1 - done - - if grep -q "✖ fatal" ".prism.log"; then - cat .prism.log - exit 1 - fi - - echo -else - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" -fi diff --git a/scripts/test b/scripts/test index 7bce0516..548da9bb 100755 --- a/scripts/test +++ b/scripts/test @@ -4,53 +4,7 @@ set -e cd "$(dirname "$0")/.." -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[0;33m' -NC='\033[0m' # No Color -function prism_is_running() { - curl --silent "http://localhost:4010" >/dev/null 2>&1 -} - -kill_server_on_port() { - pids=$(lsof -t -i tcp:"$1" || echo "") - if [ "$pids" != "" ]; then - kill "$pids" - echo "Stopped $pids." - fi -} - -function is_overriding_api_base_url() { - [ -n "$TEST_API_BASE_URL" ] -} - -if ! is_overriding_api_base_url && ! prism_is_running ; then - # When we exit this script, make sure to kill the background mock server process - trap 'kill_server_on_port 4010' EXIT - - # Start the dev server - ./scripts/mock --daemon -fi - -if is_overriding_api_base_url ; then - echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" - echo -elif ! prism_is_running ; then - echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server" - echo -e "running against your OpenAPI spec." - echo - echo -e "To run the server, pass in the path or url of your OpenAPI" - echo -e "spec to the prism command:" - echo - echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}" - echo - - exit 1 -else - echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" - echo -fi echo "==> Running tests" ./node_modules/.bin/jest "$@" diff --git a/tests/api-resources/enrollments.test.ts b/tests/api-resources/enrollments.test.ts index 2a804963..c733c4a3 100644 --- a/tests/api-resources/enrollments.test.ts +++ b/tests/api-resources/enrollments.test.ts @@ -8,7 +8,7 @@ const client = new Beagle({ }); describe('resource enrollments', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.enrollments.create({ effectiveDate: 'effectiveDate', @@ -26,7 +26,7 @@ describe('resource enrollments', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.enrollments.create({ effectiveDate: 'effectiveDate', @@ -38,7 +38,7 @@ describe('resource enrollments', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('retrieve', async () => { const responsePromise = client.enrollments.retrieve(123); const rawResponse = await responsePromise.asResponse(); @@ -50,7 +50,7 @@ describe('resource enrollments', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.enrollments.list(); const rawResponse = await responsePromise.asResponse(); @@ -62,7 +62,7 @@ describe('resource enrollments', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list: request options and params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( @@ -77,7 +77,7 @@ describe('resource enrollments', () => { ).rejects.toThrow(Beagle.NotFoundError); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('lapse', async () => { const responsePromise = client.enrollments.lapse(123); const rawResponse = await responsePromise.asResponse(); diff --git a/tests/api-resources/insurance-verification.test.ts b/tests/api-resources/insurance-verification.test.ts index 49f7a2fd..134d48bd 100644 --- a/tests/api-resources/insurance-verification.test.ts +++ b/tests/api-resources/insurance-verification.test.ts @@ -8,7 +8,7 @@ const client = new Beagle({ }); describe('resource insuranceVerification', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('verify: only required params', async () => { const responsePromise = client.insuranceVerification.verify({ propertyManagerId: 0, @@ -24,7 +24,7 @@ describe('resource insuranceVerification', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('verify: required and optional params', async () => { const response = await client.insuranceVerification.verify({ propertyManagerId: 0, diff --git a/tests/api-resources/plans.test.ts b/tests/api-resources/plans.test.ts index 9216bf73..345eb218 100644 --- a/tests/api-resources/plans.test.ts +++ b/tests/api-resources/plans.test.ts @@ -8,7 +8,7 @@ const client = new Beagle({ }); describe('resource plans', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('retrieve', async () => { const responsePromise = client.plans.retrieve('code'); const rawResponse = await responsePromise.asResponse(); @@ -20,7 +20,7 @@ describe('resource plans', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.plans.list(); const rawResponse = await responsePromise.asResponse(); diff --git a/tests/api-resources/property-managers.test.ts b/tests/api-resources/property-managers.test.ts index c530d853..ade84b77 100644 --- a/tests/api-resources/property-managers.test.ts +++ b/tests/api-resources/property-managers.test.ts @@ -8,7 +8,7 @@ const client = new Beagle({ }); describe('resource propertyManagers', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.propertyManagers.create({ addresses: [ @@ -38,7 +38,7 @@ describe('resource propertyManagers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.propertyManagers.create({ addresses: [ @@ -64,7 +64,7 @@ describe('resource propertyManagers', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('retrieve', async () => { const responsePromise = client.propertyManagers.retrieve(123); const rawResponse = await responsePromise.asResponse(); @@ -76,7 +76,7 @@ describe('resource propertyManagers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('update', async () => { const responsePromise = client.propertyManagers.update(123, {}); const rawResponse = await responsePromise.asResponse(); @@ -88,7 +88,7 @@ describe('resource propertyManagers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.propertyManagers.list(); const rawResponse = await responsePromise.asResponse(); @@ -100,7 +100,7 @@ describe('resource propertyManagers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list: request options and params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( @@ -108,7 +108,7 @@ describe('resource propertyManagers', () => { ).rejects.toThrow(Beagle.NotFoundError); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('delete', async () => { const responsePromise = client.propertyManagers.delete(123); const rawResponse = await responsePromise.asResponse(); diff --git a/tests/api-resources/tenants.test.ts b/tests/api-resources/tenants.test.ts index dec6b749..f663ceeb 100644 --- a/tests/api-resources/tenants.test.ts +++ b/tests/api-resources/tenants.test.ts @@ -8,7 +8,7 @@ const client = new Beagle({ }); describe('resource tenants', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.tenants.create({ address: { @@ -32,7 +32,7 @@ describe('resource tenants', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.tenants.create({ address: { @@ -51,7 +51,7 @@ describe('resource tenants', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('retrieve', async () => { const responsePromise = client.tenants.retrieve(123); const rawResponse = await responsePromise.asResponse(); @@ -63,7 +63,7 @@ describe('resource tenants', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('update', async () => { const responsePromise = client.tenants.update(123, {}); const rawResponse = await responsePromise.asResponse(); @@ -75,7 +75,7 @@ describe('resource tenants', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.tenants.list(); const rawResponse = await responsePromise.asResponse(); @@ -87,7 +87,7 @@ describe('resource tenants', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list: request options and params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( @@ -102,7 +102,7 @@ describe('resource tenants', () => { ).rejects.toThrow(Beagle.NotFoundError); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('delete', async () => { const responsePromise = client.tenants.delete(123); const rawResponse = await responsePromise.asResponse(); diff --git a/tests/api-resources/webhook/endpoints.test.ts b/tests/api-resources/webhook/endpoints.test.ts index 4f03592d..3255f93d 100644 --- a/tests/api-resources/webhook/endpoints.test.ts +++ b/tests/api-resources/webhook/endpoints.test.ts @@ -8,7 +8,7 @@ const client = new Beagle({ }); describe('resource endpoints', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.webhook.endpoints.create({ secret: 'secret', url: 'https://example.com' }); const rawResponse = await responsePromise.asResponse(); @@ -20,7 +20,7 @@ describe('resource endpoints', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.webhook.endpoints.create({ secret: 'secret', @@ -29,7 +29,7 @@ describe('resource endpoints', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('retrieve', async () => { const responsePromise = client.webhook.endpoints.retrieve(123); const rawResponse = await responsePromise.asResponse(); @@ -41,7 +41,7 @@ describe('resource endpoints', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('update: only required params', async () => { const responsePromise = client.webhook.endpoints.update(123, { secret: 'secret', @@ -56,7 +56,7 @@ describe('resource endpoints', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('update: required and optional params', async () => { const response = await client.webhook.endpoints.update(123, { secret: 'secret', @@ -65,7 +65,7 @@ describe('resource endpoints', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.webhook.endpoints.list(); const rawResponse = await responsePromise.asResponse(); @@ -77,7 +77,7 @@ describe('resource endpoints', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list: request options and params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( @@ -85,7 +85,7 @@ describe('resource endpoints', () => { ).rejects.toThrow(Beagle.NotFoundError); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('delete', async () => { const responsePromise = client.webhook.endpoints.delete(123); const rawResponse = await responsePromise.asResponse(); From 363169875585a0166881b7b11a12a096a11a388c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 13:23:14 +0000 Subject: [PATCH 086/138] chore(mcp): correctly update version in sync with sdk --- release-please-config.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/release-please-config.json b/release-please-config.json index b1909804..9b042792 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -68,6 +68,11 @@ "type": "json", "path": "packages/mcp-server/package.json", "jsonpath": "$.version" + }, + { + "type": "json", + "path": "packages/mcp-server/manifest.json", + "jsonpath": "$.version" } ] } From ff2235783f30d1331d845693dbdd1347bc4b4795 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 23 Feb 2026 18:31:15 +0000 Subject: [PATCH 087/138] feat(api): api update --- .stats.yml | 4 ++-- CONTRIBUTING.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 749dd7be..dbeff499 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 23 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-5ab1daf2e9cd2b373093fdbd17460f248ae9247728df3710bab5bfb603cf20e1.yml -openapi_spec_hash: be884fdd7ed2976a88f4f5396ccdacb2 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-6d603cbe0503dc603b84acf3865e5ae1b293a8839b1b6236fdf002f316ae0569.yml +openapi_spec_hash: 0954f998dc3e52e8a55c2f15d0797c8f config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4b66acfb..cad8d890 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -60,7 +60,7 @@ $ yarn link @corgi-tech/beagle # With pnpm $ pnpm link --global $ cd ../my-package -$ pnpm link -—global @corgi-tech/beagle +$ pnpm link --global @corgi-tech/beagle ``` ## Running tests From b7ed22d46820f5f6e4c0a94fde9abe8e0d0d3dfb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 15:04:22 +0000 Subject: [PATCH 088/138] chore(internal): upgrade @modelcontextprotocol/sdk and hono --- packages/mcp-server/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 49c8562c..38145113 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -32,7 +32,7 @@ "dependencies": { "@corgi-tech/beagle": "file:../../dist/", "@cloudflare/cabidela": "^0.2.4", - "@modelcontextprotocol/sdk": "^1.25.2", + "@modelcontextprotocol/sdk": "^1.26.0", "@valtown/deno-http-worker": "^0.0.21", "cookie-parser": "^1.4.6", "cors": "^2.8.5", From de56d4a0f82afcc062322e36e8fab75d2e53bde1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:56:37 +0000 Subject: [PATCH 089/138] chore(internal): make MCP code execution location configurable via a flag --- packages/mcp-server/Dockerfile | 14 +- packages/mcp-server/src/code-tool-paths.cts | 3 + packages/mcp-server/src/code-tool-types.ts | 1 + packages/mcp-server/src/code-tool-worker.ts | 293 ++++++++++++++++++ packages/mcp-server/src/code-tool.ts | 318 +++++++++++++++++--- packages/mcp-server/src/options.ts | 12 + packages/mcp-server/src/server.ts | 1 + packages/mcp-server/tests/options.test.ts | 20 +- 8 files changed, 592 insertions(+), 70 deletions(-) create mode 100644 packages/mcp-server/src/code-tool-paths.cts create mode 100644 packages/mcp-server/src/code-tool-worker.ts diff --git a/packages/mcp-server/Dockerfile b/packages/mcp-server/Dockerfile index 7f1432a6..3b0f78b5 100644 --- a/packages/mcp-server/Dockerfile +++ b/packages/mcp-server/Dockerfile @@ -37,9 +37,21 @@ COPY . . RUN yarn install --frozen-lockfile && \ yarn build -# Production stage +FROM denoland/deno:bin-2.6.10 AS deno_installer +FROM gcr.io/distroless/cc@sha256:66d87e170bc2c5e2b8cf853501141c3c55b4e502b8677595c57534df54a68cc5 AS cc + FROM node:24-alpine +# Install deno +COPY --from=deno_installer /deno /usr/local/bin/deno + +# Add in shared libraries needed by Deno +COPY --from=cc --chown=root:root --chmod=755 /lib/*-linux-gnu/* /usr/local/lib/ +COPY --from=cc --chown=root:root --chmod=755 /lib/ld-linux-* /lib/ + +RUN mkdir /lib64 && ln -s /usr/local/lib/ld-linux-* /lib64/ +ENV LD_LIBRARY_PATH=/usr/lib:/usr/local/lib + # Add non-root user RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001 diff --git a/packages/mcp-server/src/code-tool-paths.cts b/packages/mcp-server/src/code-tool-paths.cts new file mode 100644 index 00000000..15ce7f55 --- /dev/null +++ b/packages/mcp-server/src/code-tool-paths.cts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export const workerPath = require.resolve('./code-tool-worker.mjs'); diff --git a/packages/mcp-server/src/code-tool-types.ts b/packages/mcp-server/src/code-tool-types.ts index 9dca2664..ffbb8220 100644 --- a/packages/mcp-server/src/code-tool-types.ts +++ b/packages/mcp-server/src/code-tool-types.ts @@ -8,6 +8,7 @@ export type WorkerInput = { client_opts: ClientOptions; intent?: string | undefined; }; + export type WorkerOutput = { is_error: boolean; result: unknown | null; diff --git a/packages/mcp-server/src/code-tool-worker.ts b/packages/mcp-server/src/code-tool-worker.ts new file mode 100644 index 00000000..6b71bb40 --- /dev/null +++ b/packages/mcp-server/src/code-tool-worker.ts @@ -0,0 +1,293 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import path from 'node:path'; +import util from 'node:util'; +import Fuse from 'fuse.js'; +import ts from 'typescript'; +import { WorkerOutput } from './code-tool-types'; +import { Beagle, ClientOptions } from '@corgi-tech/beagle'; + +function getRunFunctionSource(code: string): { + type: 'declaration' | 'expression'; + client: string | undefined; + code: string; +} | null { + const sourceFile = ts.createSourceFile('code.ts', code, ts.ScriptTarget.Latest, true); + const printer = ts.createPrinter(); + + for (const statement of sourceFile.statements) { + // Check for top-level function declarations + if (ts.isFunctionDeclaration(statement)) { + if (statement.name?.text === 'run') { + return { + type: 'declaration', + client: statement.parameters[0]?.name.getText(), + code: printer.printNode(ts.EmitHint.Unspecified, statement.body!, sourceFile), + }; + } + } + + // Check for variable declarations: const run = () => {} or const run = function() {} + if (ts.isVariableStatement(statement)) { + for (const declaration of statement.declarationList.declarations) { + if ( + ts.isIdentifier(declaration.name) && + declaration.name.text === 'run' && + // Check if it's initialized with a function + declaration.initializer && + (ts.isFunctionExpression(declaration.initializer) || ts.isArrowFunction(declaration.initializer)) + ) { + return { + type: 'expression', + client: declaration.initializer.parameters[0]?.name.getText(), + code: printer.printNode(ts.EmitHint.Unspecified, declaration.initializer, sourceFile), + }; + } + } + } + } + + return null; +} + +function getTSDiagnostics(code: string): string[] { + const functionSource = getRunFunctionSource(code)!; + const codeWithImport = [ + 'import { Beagle } from "@corgi-tech/beagle";', + functionSource.type === 'declaration' ? + `async function run(${functionSource.client}: Beagle)` + : `const run: (${functionSource.client}: Beagle) => Promise =`, + functionSource.code, + ].join('\n'); + const sourcePath = path.resolve('code.ts'); + const ast = ts.createSourceFile(sourcePath, codeWithImport, ts.ScriptTarget.Latest, true); + const options = ts.getDefaultCompilerOptions(); + options.target = ts.ScriptTarget.Latest; + options.module = ts.ModuleKind.NodeNext; + options.moduleResolution = ts.ModuleResolutionKind.NodeNext; + const host = ts.createCompilerHost(options, true); + const newHost: typeof host = { + ...host, + getSourceFile: (...args) => { + if (path.resolve(args[0]) === sourcePath) { + return ast; + } + return host.getSourceFile(...args); + }, + readFile: (...args) => { + if (path.resolve(args[0]) === sourcePath) { + return codeWithImport; + } + return host.readFile(...args); + }, + fileExists: (...args) => { + if (path.resolve(args[0]) === sourcePath) { + return true; + } + return host.fileExists(...args); + }, + }; + const program = ts.createProgram({ + options, + rootNames: [sourcePath], + host: newHost, + }); + const diagnostics = ts.getPreEmitDiagnostics(program, ast); + return diagnostics.map((d) => { + const message = ts.flattenDiagnosticMessageText(d.messageText, '\n'); + if (!d.file || !d.start) return `- ${message}`; + const { line: lineNumber } = ts.getLineAndCharacterOfPosition(d.file, d.start); + const line = codeWithImport.split('\n').at(lineNumber)?.trim(); + return line ? `- ${message}\n ${line}` : `- ${message}`; + }); +} + +const fuse = new Fuse( + [ + 'client.plans.list', + 'client.plans.retrieve', + 'client.propertyManagers.create', + 'client.propertyManagers.delete', + 'client.propertyManagers.list', + 'client.propertyManagers.retrieve', + 'client.propertyManagers.update', + 'client.tenants.create', + 'client.tenants.delete', + 'client.tenants.list', + 'client.tenants.retrieve', + 'client.tenants.update', + 'client.enrollments.create', + 'client.enrollments.lapse', + 'client.enrollments.list', + 'client.enrollments.retrieve', + 'client.enrollments.retrieveCertificate', + 'client.insuranceVerification.verify', + 'client.webhook.endpoints.create', + 'client.webhook.endpoints.delete', + 'client.webhook.endpoints.list', + 'client.webhook.endpoints.retrieve', + 'client.webhook.endpoints.update', + ], + { threshold: 1, shouldSort: true }, +); + +function getMethodSuggestions(fullyQualifiedMethodName: string): string[] { + return fuse + .search(fullyQualifiedMethodName) + .map(({ item }) => item) + .slice(0, 5); +} + +const proxyToObj = new WeakMap(); +const objToProxy = new WeakMap(); + +type ClientProxyConfig = { + path: string[]; + isBelievedBad?: boolean; +}; + +function makeSdkProxy(obj: T, { path, isBelievedBad = false }: ClientProxyConfig): T { + let proxy: T = objToProxy.get(obj); + + if (!proxy) { + proxy = new Proxy(obj, { + get(target, prop, receiver) { + const propPath = [...path, String(prop)]; + const value = Reflect.get(target, prop, receiver); + + if (isBelievedBad || (!(prop in target) && value === undefined)) { + // If we're accessing a path that doesn't exist, it will probably eventually error. + // Let's proxy it and mark it bad so that we can control the error message. + // We proxy an empty class so that an invocation or construction attempt is possible. + return makeSdkProxy(class {}, { path: propPath, isBelievedBad: true }); + } + + if (value !== null && (typeof value === 'object' || typeof value === 'function')) { + return makeSdkProxy(value, { path: propPath, isBelievedBad }); + } + + return value; + }, + + apply(target, thisArg, args) { + if (isBelievedBad || typeof target !== 'function') { + const fullyQualifiedMethodName = path.join('.'); + const suggestions = getMethodSuggestions(fullyQualifiedMethodName); + throw new Error( + `${fullyQualifiedMethodName} is not a function. Did you mean: ${suggestions.join(', ')}`, + ); + } + + return Reflect.apply(target, proxyToObj.get(thisArg) ?? thisArg, args); + }, + + construct(target, args, newTarget) { + if (isBelievedBad || typeof target !== 'function') { + const fullyQualifiedMethodName = path.join('.'); + const suggestions = getMethodSuggestions(fullyQualifiedMethodName); + throw new Error( + `${fullyQualifiedMethodName} is not a constructor. Did you mean: ${suggestions.join(', ')}`, + ); + } + + return Reflect.construct(target, args, newTarget); + }, + }); + + objToProxy.set(obj, proxy); + proxyToObj.set(proxy, obj); + } + + return proxy; +} + +function parseError(code: string, error: unknown): string | undefined { + if (!(error instanceof Error)) return; + const message = error.name ? `${error.name}: ${error.message}` : error.message; + try { + // Deno uses V8; the first ":LINE:COLUMN" is the top of stack. + const lineNumber = error.stack?.match(/:([0-9]+):[0-9]+/)?.[1]; + // -1 for the zero-based indexing + const line = + lineNumber && + code + .split('\n') + .at(parseInt(lineNumber, 10) - 1) + ?.trim(); + return line ? `${message}\n at line ${lineNumber}\n ${line}` : message; + } catch { + return message; + } +} + +const fetch = async (req: Request): Promise => { + const { opts, code } = (await req.json()) as { opts: ClientOptions; code: string }; + + const runFunctionSource = code ? getRunFunctionSource(code) : null; + if (!runFunctionSource) { + const message = + code ? + 'The code is missing a top-level `run` function.' + : 'The code argument is missing. Provide one containing a top-level `run` function.'; + return Response.json( + { + is_error: true, + result: `${message} Write code within this template:\n\n\`\`\`\nasync function run(client) {\n // Fill this out\n}\n\`\`\``, + log_lines: [], + err_lines: [], + } satisfies WorkerOutput, + { status: 400, statusText: 'Code execution error' }, + ); + } + + const diagnostics = getTSDiagnostics(code); + if (diagnostics.length > 0) { + return Response.json( + { + is_error: true, + result: `The code contains TypeScript diagnostics:\n${diagnostics.join('\n')}`, + log_lines: [], + err_lines: [], + } satisfies WorkerOutput, + { status: 400, statusText: 'Code execution error' }, + ); + } + + const client = new Beagle({ + ...opts, + }); + + const log_lines: string[] = []; + const err_lines: string[] = []; + const console = { + log: (...args: unknown[]) => { + log_lines.push(util.format(...args)); + }, + error: (...args: unknown[]) => { + err_lines.push(util.format(...args)); + }, + }; + try { + let run_ = async (client: any) => {}; + eval(`${code}\nrun_ = run;`); + const result = await run_(makeSdkProxy(client, { path: ['client'] })); + return Response.json({ + is_error: false, + result, + log_lines, + err_lines, + } satisfies WorkerOutput); + } catch (e) { + return Response.json( + { + is_error: true, + result: parseError(code, e), + log_lines, + err_lines, + } satisfies WorkerOutput, + { status: 400, statusText: 'Code execution error' }, + ); + } +}; + +export default { fetch }; diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 6f8b1384..2638c565 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -1,6 +1,12 @@ // 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, McpTool, Metadata, @@ -12,6 +18,8 @@ import { Tool } from '@modelcontextprotocol/sdk/types.js'; import { readEnv, requireValue } from './util'; import { WorkerInput, WorkerOutput } from './code-tool-types'; import { SdkMethod } from './methods'; +import { McpCodeExecutionMode } from './options'; +import { ClientOptions } from '@corgi-tech/beagle'; const prompt = `Runs JavaScript code to interact with the Beagle API. @@ -40,9 +48,19 @@ Variables will not persist between calls, so make sure to return or log any data * we expose a single tool that can be used to search for endpoints by name, resource, operation, or tag, and then * a generic endpoint that can be used to invoke any endpoint with the provided arguments. * - * @param endpoints - The endpoints to include in the list. + * @param blockedMethods - The methods to block for code execution. Blocking is done by simple string + * matching, so it is not secure against obfuscation. For stronger security, block in the downstream API + * with limited API keys. + * @param codeExecutionMode - Whether to execute code in a local Deno environment or in a remote + * sandbox environment hosted by Stainless. */ -export function codeTool({ blockedMethods }: { blockedMethods: SdkMethod[] | undefined }): McpTool { +export function codeTool({ + blockedMethods, + codeExecutionMode, +}: { + blockedMethods: SdkMethod[] | undefined; + codeExecutionMode: McpCodeExecutionMode; +}): McpTool { const metadata: Metadata = { resource: 'all', operation: 'write', tags: [] }; const tool: Tool = { name: 'execute', @@ -62,6 +80,7 @@ export function codeTool({ blockedMethods }: { blockedMethods: SdkMethod[] | und required: ['code'], }, }; + const handler = async ({ reqContext, args, @@ -70,9 +89,6 @@ export function codeTool({ blockedMethods }: { blockedMethods: SdkMethod[] | und args: any; }): Promise => { const code = args.code as string; - const intent = args.intent as string | undefined; - const client = reqContext.client; - // Do very basic blocking of code that includes forbidden method names. // // WARNING: This is not secure against obfuscation and other evasion methods. If @@ -89,54 +105,256 @@ export function codeTool({ blockedMethods }: { blockedMethods: SdkMethod[] | und } } - const codeModeEndpoint = - readEnv('CODE_MODE_ENDPOINT_URL') ?? 'https://api.stainless.com/api/ai/code-tool'; - - // 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', - client_envs: JSON.stringify({ - BEAGLE_API_KEY: requireValue( - readEnv('BEAGLE_API_KEY') ?? client.apiKey, - 'set BEAGLE_API_KEY environment variable or provide apiKey client option', - ), - BEAGLE_BASE_URL: - readEnv('BEAGLE_BASE_URL') ?? readEnv('BEAGLE_ENVIRONMENT') ? - undefined - : client.baseURL ?? undefined, - }), - }, - body: JSON.stringify({ - project_name: 'beagle', - code, - intent, - client_opts: { environment: (readEnv('BEAGLE_ENVIRONMENT') || undefined) as any }, - } satisfies WorkerInput), - }); + if (codeExecutionMode === 'local') { + return await localDenoHandler({ reqContext, args }); + } else { + return await remoteStainlessHandler({ reqContext, args }); + } + }; + + return { metadata, tool, handler }; +} + +const remoteStainlessHandler = async ({ + reqContext, + args, +}: { + reqContext: McpRequestContext; + args: any; +}): Promise => { + const code = args.code as string; + const intent = args.intent as string | undefined; + const client = reqContext.client; - if (!res.ok) { - throw new Error( - `${res.status}: ${ - res.statusText - } error when trying to contact Code Tool server. Details: ${await res.text()}`, + const codeModeEndpoint = readEnv('CODE_MODE_ENDPOINT_URL') ?? 'https://api.stainless.com/api/ai/code-tool'; + + // 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', + client_envs: JSON.stringify({ + BEAGLE_API_KEY: requireValue( + readEnv('BEAGLE_API_KEY') ?? client.apiKey, + 'set BEAGLE_API_KEY environment variable or provide apiKey client option', + ), + BEAGLE_BASE_URL: + readEnv('BEAGLE_BASE_URL') ?? readEnv('BEAGLE_ENVIRONMENT') ? + undefined + : client.baseURL ?? undefined, + }), + }, + body: JSON.stringify({ + project_name: 'beagle', + code, + intent, + client_opts: { environment: (readEnv('BEAGLE_ENVIRONMENT') || undefined) as any }, + } satisfies WorkerInput), + }); + + if (!res.ok) { + throw new Error( + `${res.status}: ${ + res.statusText + } error when trying to contact Code Tool server. Details: ${await res.text()}`, + ); + } + + const { is_error, result, log_lines, err_lines } = (await res.json()) as WorkerOutput; + const hasLogs = log_lines.length > 0 || err_lines.length > 0; + const output = { + result, + ...(log_lines.length > 0 && { log_lines }), + ...(err_lines.length > 0 && { err_lines }), + }; + if (is_error) { + return asErrorResult(typeof result === 'string' && !hasLogs ? result : JSON.stringify(output, null, 2)); + } + return asTextContentResult(output); +}; + +const localDenoHandler = async ({ + reqContext, + args, +}: { + reqContext: McpRequestContext; + args: unknown; +}): Promise => { + const client = reqContext.client; + const baseURLHostname = new URL(client.baseURL).hostname; + const { code } = args as { code: string }; + + let denoPath: string; + + const packageRoot = path.resolve(path.dirname(workerPath), '..'); + const packageNodeModulesPath = path.resolve(packageRoot, 'node_modules'); + + // Check if deno is in PATH + const { execSync } = await import('node:child_process'); + try { + execSync('command -v deno', { stdio: 'ignore' }); + denoPath = 'deno'; + } catch { + try { + // Use deno binary in node_modules if it's found + const denoNodeModulesPath = path.resolve(packageNodeModulesPath, 'deno', 'bin.cjs'); + await fs.promises.access(denoNodeModulesPath, fs.constants.X_OK); + denoPath = denoNodeModulesPath; + } catch { + return asErrorResult( + 'Deno is required for code execution but was not found. ' + + 'Install it from https://deno.land or run: npm install deno', ); } + } + + const allowReadPaths = [ + 'code-tool-worker.mjs', + `${workerPath.replace(/([\/\\]node_modules)[\/\\].+$/, '$1')}/`, + packageRoot, + ]; - const { is_error, result, log_lines, err_lines } = (await res.json()) as WorkerOutput; - const hasLogs = log_lines.length > 0 || err_lines.length > 0; - const output = { - result, - ...(log_lines.length > 0 && { log_lines }), - ...(err_lines.length > 0 && { err_lines }), - }; - if (is_error) { - return asErrorResult(typeof result === 'string' && !hasLogs ? result : JSON.stringify(output, null, 2)); + // Follow symlinks in node_modules to allow read access to workspace-linked packages + try { + const sdkPkgName = '@corgi-tech/beagle'; + const sdkDir = path.resolve(packageNodeModulesPath, sdkPkgName); + const realSdkDir = fs.realpathSync(sdkDir); + if (realSdkDir !== sdkDir) { + allowReadPaths.push(realSdkDir); } - return asTextContentResult(output); - }; + } catch { + // Ignore if symlink resolution fails + } - return { metadata, tool, handler }; -} + const allowRead = allowReadPaths.join(','); + + const worker = await newDenoHTTPWorker(url.pathToFileURL(workerPath), { + denoExecutable: denoPath, + runFlags: [ + `--node-modules-dir=manual`, + `--allow-read=${allowRead}`, + `--allow-net=${baseURLHostname}`, + // Allow environment variables because instantiating the client will try to read from them, + // even though they are not set. + '--allow-env', + ], + printOutput: true, + spawnOptions: { + cwd: path.dirname(workerPath), + }, + }); + + try { + const resp = await new Promise((resolve, reject) => { + worker.addEventListener('exit', (exitCode) => { + reject(new Error(`Worker exited with code ${exitCode}`)); + }); + + const opts: ClientOptions = { + baseURL: client.baseURL, + apiKey: client.apiKey, + defaultHeaders: { + 'X-Stainless-MCP': 'true', + }, + }; + + const req = worker.request( + 'http://localhost', + { + headers: { + 'content-type': 'application/json', + }, + method: 'POST', + }, + (resp) => { + const body: Uint8Array[] = []; + resp.on('error', (err) => { + reject(err); + }); + resp.on('data', (chunk) => { + body.push(chunk); + }); + resp.on('end', () => { + resolve( + new Response(Buffer.concat(body).toString(), { + status: resp.statusCode ?? 200, + headers: resp.headers as any, + }), + ); + }); + }, + ); + + const body = JSON.stringify({ + opts, + code, + }); + + req.write(body, (err) => { + if (err != null) { + reject(err); + } + }); + + req.end(); + }); + + if (resp.status === 200) { + const { result, log_lines, err_lines } = (await resp.json()) as WorkerOutput; + const returnOutput: ContentBlock | null = + result == null ? null : ( + { + type: 'text', + text: typeof result === 'string' ? result : JSON.stringify(result), + } + ); + const logOutput: ContentBlock | null = + log_lines.length === 0 ? + null + : { + type: 'text', + text: log_lines.join('\n'), + }; + const errOutput: ContentBlock | null = + err_lines.length === 0 ? + null + : { + type: 'text', + text: 'Error output:\n' + err_lines.join('\n'), + }; + return { + content: [returnOutput, logOutput, errOutput].filter((block) => block !== null), + }; + } else { + const { result, log_lines, err_lines } = (await resp.json()) as WorkerOutput; + const messageOutput: ContentBlock | null = + result == null ? null : ( + { + type: 'text', + text: typeof result === 'string' ? result : JSON.stringify(result), + } + ); + const logOutput: ContentBlock | null = + log_lines.length === 0 ? + null + : { + type: 'text', + text: log_lines.join('\n'), + }; + const errOutput: ContentBlock | null = + err_lines.length === 0 ? + null + : { + type: 'text', + text: 'Error output:\n' + err_lines.join('\n'), + }; + return { + content: [messageOutput, logOutput, errOutput].filter((block) => block !== null), + isError: true, + }; + } + } finally { + worker.terminate(); + } +}; diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index 32a88713..9e9d15cd 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -19,8 +19,11 @@ export type McpOptions = { codeAllowHttpGets?: boolean | undefined; codeAllowedMethods?: string[] | undefined; codeBlockedMethods?: string[] | undefined; + codeExecutionMode: McpCodeExecutionMode; }; +export type McpCodeExecutionMode = 'stainless-sandbox' | 'local'; + export function parseCLIOptions(): CLIOptions { const opts = yargs(hideBin(process.argv)) .option('code-allow-http-gets', { @@ -40,6 +43,13 @@ export function parseCLIOptions(): CLIOptions { description: 'Methods to explicitly block for code tool. Evaluated as regular expressions against method fully qualified names. If all code-allow-* flags are unset, then everything is allowed.', }) + .option('code-execution-mode', { + type: 'string', + choices: ['stainless-sandbox', 'local'], + default: 'stainless-sandbox', + description: + "Where to run code execution in code tool; 'stainless-sandbox' will execute code in Stainless-hosted sandboxes whereas 'local' will execute code locally on the MCP server machine.", + }) .option('debug', { type: 'boolean', description: 'Enable debug logging' }) .option('no-tools', { type: 'string', @@ -93,6 +103,7 @@ export function parseCLIOptions(): CLIOptions { codeAllowHttpGets: argv.codeAllowHttpGets, codeAllowedMethods: argv.codeAllowedMethods, codeBlockedMethods: argv.codeBlockedMethods, + codeExecutionMode: argv.codeExecutionMode as McpCodeExecutionMode, transport, port: argv.port, socket: argv.socket, @@ -124,6 +135,7 @@ export function parseQueryOptions(defaultOptions: McpOptions, query: unknown): M : defaultOptions.includeDocsTools; return { + codeExecutionMode: defaultOptions.codeExecutionMode, ...(docsTools !== undefined && { includeDocsTools: docsTools }), }; } diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 22cd0dbe..5458ee19 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -161,6 +161,7 @@ export function selectTools(options?: McpOptions): McpTool[] { const includedTools = [ codeTool({ blockedMethods: blockedMethodsForCodeTool(options), + codeExecutionMode: options?.codeExecutionMode ?? 'stainless-sandbox', }), ]; if (options?.includeDocsTools ?? true) { diff --git a/packages/mcp-server/tests/options.test.ts b/packages/mcp-server/tests/options.test.ts index 7a2d5114..17306295 100644 --- a/packages/mcp-server/tests/options.test.ts +++ b/packages/mcp-server/tests/options.test.ts @@ -1,4 +1,4 @@ -import { parseCLIOptions, parseQueryOptions } from '../src/options'; +import { parseCLIOptions } from '../src/options'; // Mock process.argv const mockArgv = (args: string[]) => { @@ -30,21 +30,3 @@ describe('parseCLIOptions', () => { cleanup(); }); }); - -describe('parseQueryOptions', () => { - const defaultOptions = {}; - - it('default parsing should be empty', () => { - const query = ''; - const result = parseQueryOptions(defaultOptions, query); - - expect(result).toEqual({}); - }); - - it('should handle invalid query string gracefully', () => { - const query = 'invalid=value&tools=invalid-operation'; - - // Should throw due to Zod validation for invalid tools - expect(() => parseQueryOptions(defaultOptions, query)).toThrow(); - }); -}); From 29a6f084bf441b4c61979f944fdab9c65bf0c8a3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 11:25:58 +0000 Subject: [PATCH 090/138] chore(internal): fix MCP Dockerfiles so they can be built without buildkit --- packages/mcp-server/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/mcp-server/Dockerfile b/packages/mcp-server/Dockerfile index 3b0f78b5..00f2417b 100644 --- a/packages/mcp-server/Dockerfile +++ b/packages/mcp-server/Dockerfile @@ -46,8 +46,8 @@ FROM node:24-alpine COPY --from=deno_installer /deno /usr/local/bin/deno # Add in shared libraries needed by Deno -COPY --from=cc --chown=root:root --chmod=755 /lib/*-linux-gnu/* /usr/local/lib/ -COPY --from=cc --chown=root:root --chmod=755 /lib/ld-linux-* /lib/ +COPY --from=cc /lib/*-linux-gnu/* /usr/local/lib/ +COPY --from=cc /lib/ld-linux-* /lib/ RUN mkdir /lib64 && ln -s /usr/local/lib/ld-linux-* /lib64/ ENV LD_LIBRARY_PATH=/usr/lib:/usr/local/lib From f15f82d8febe62f4c13529feea47c012e8d397f9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 11:29:23 +0000 Subject: [PATCH 091/138] chore(internal): fix MCP Dockerfiles so they can be built without buildkit --- packages/mcp-server/Dockerfile | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/packages/mcp-server/Dockerfile b/packages/mcp-server/Dockerfile index 00f2417b..476ae526 100644 --- a/packages/mcp-server/Dockerfile +++ b/packages/mcp-server/Dockerfile @@ -37,19 +37,11 @@ COPY . . RUN yarn install --frozen-lockfile && \ yarn build -FROM denoland/deno:bin-2.6.10 AS deno_installer -FROM gcr.io/distroless/cc@sha256:66d87e170bc2c5e2b8cf853501141c3c55b4e502b8677595c57534df54a68cc5 AS cc +FROM denoland/deno:alpine-2.7.1 -FROM node:24-alpine +# Install node and npm +RUN apk add --no-cache nodejs npm -# Install deno -COPY --from=deno_installer /deno /usr/local/bin/deno - -# Add in shared libraries needed by Deno -COPY --from=cc /lib/*-linux-gnu/* /usr/local/lib/ -COPY --from=cc /lib/ld-linux-* /lib/ - -RUN mkdir /lib64 && ln -s /usr/local/lib/ld-linux-* /lib64/ ENV LD_LIBRARY_PATH=/usr/lib:/usr/local/lib # Add non-root user @@ -69,6 +61,7 @@ COPY --from=builder /build/dist ./node_modules/@corgi-tech/beagle # Change ownership to nodejs user RUN chown -R nodejs:nodejs /app +RUN chown -R nodejs:nodejs /deno-dir # Switch to non-root user USER nodejs From 522fc908bf543d920f7d6e1dd17b16a233532064 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 27 Feb 2026 15:32:25 +0000 Subject: [PATCH 092/138] chore(internal): codegen related update --- packages/mcp-server/src/code-tool.ts | 6 ++++-- packages/mcp-server/src/options.ts | 11 ++++++++++- packages/mcp-server/src/server.ts | 16 ++++++++++------ src/client.ts | 22 +++++----------------- src/internal/utils.ts | 1 + src/internal/utils/query.ts | 23 +++++++++++++++++++++++ tests/stringifyQuery.test.ts | 6 ++---- 7 files changed, 55 insertions(+), 30 deletions(-) create mode 100644 src/internal/utils/query.ts diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 2638c565..0dd9a2a9 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -23,7 +23,7 @@ import { ClientOptions } from '@corgi-tech/beagle'; const prompt = `Runs JavaScript code to interact with the Beagle API. -You are a skilled programmer writing code to interface with the service. +You are a skilled TypeScript programmer writing code to interface with the service. Define an async function named "run" that takes a single parameter of an initialized SDK client and it will be run. For example: @@ -39,7 +39,9 @@ You will be returned anything that your function returns, plus the results of an Do not add try-catch blocks for single API calls. The tool will handle errors for you. Do not add comments unless necessary for generating better code. Code will run in a container, and cannot interact with the network outside of the given SDK client. -Variables will not persist between calls, so make sure to return or log any data you might need later.`; +Variables will not persist between calls, so make sure to return or log any data you might need later. +Remember that you are writing TypeScript code, so you need to be careful with your types. +Always type dynamic key-value stores explicitly as Record instead of {}.`; /** * A tool that runs code against a copy of the SDK. diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index 9e9d15cd..069b8811 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -14,6 +14,7 @@ export type CLIOptions = McpOptions & { }; export type McpOptions = { + includeCodeTool?: boolean | undefined; includeDocsTools?: boolean | undefined; stainlessApiKey?: string | undefined; codeAllowHttpGets?: boolean | undefined; @@ -92,11 +93,13 @@ export function parseCLIOptions(): CLIOptions { : argv.tools?.includes(toolType) ? true : undefined; + const includeCodeTool = shouldIncludeToolType('code'); const includeDocsTools = shouldIncludeToolType('docs'); const transport = argv.transport as 'stdio' | 'http'; return { + ...(includeCodeTool !== undefined && { includeCodeTool }), ...(includeDocsTools !== undefined && { includeDocsTools }), debug: !!argv.debug, stainlessApiKey: argv.stainlessApiKey, @@ -129,13 +132,19 @@ export function parseQueryOptions(defaultOptions: McpOptions, query: unknown): M const queryObject = typeof query === 'string' ? qs.parse(query) : query; const queryOptions = QueryOptions.parse(queryObject); + let codeTool: boolean | undefined = + queryOptions.no_tools && queryOptions.no_tools?.includes('code') ? false + : queryOptions.tools?.includes('code') ? true + : defaultOptions.includeCodeTool; + let docsTools: boolean | undefined = queryOptions.no_tools && queryOptions.no_tools?.includes('docs') ? false : queryOptions.tools?.includes('docs') ? true : defaultOptions.includeDocsTools; return { - codeExecutionMode: defaultOptions.codeExecutionMode, + ...(codeTool !== undefined && { includeCodeTool: codeTool }), ...(docsTools !== undefined && { includeDocsTools: docsTools }), + codeExecutionMode: defaultOptions.codeExecutionMode, }; } diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 5458ee19..2c909c19 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -158,12 +158,16 @@ export async function initMcpServer(params: { * Selects the tools to include in the MCP Server based on the provided options. */ export function selectTools(options?: McpOptions): McpTool[] { - const includedTools = [ - codeTool({ - blockedMethods: blockedMethodsForCodeTool(options), - codeExecutionMode: options?.codeExecutionMode ?? 'stainless-sandbox', - }), - ]; + const includedTools = []; + + if (options?.includeCodeTool ?? true) { + includedTools.push( + codeTool({ + blockedMethods: blockedMethodsForCodeTool(options), + codeExecutionMode: options?.codeExecutionMode ?? 'stainless-sandbox', + }), + ); + } if (options?.includeDocsTools ?? true) { includedTools.push(docsSearchTool); } diff --git a/src/client.ts b/src/client.ts index a7cb70a1..34775d5d 100644 --- a/src/client.ts +++ b/src/client.ts @@ -11,6 +11,7 @@ import type { APIResponseProps } from './internal/parse'; import { getPlatformHeaders } from './internal/detect-platform'; import * as Shims from './internal/shims'; import * as Opts from './internal/request-options'; +import { stringifyQuery } from './internal/utils/query'; import { VERSION } from './version'; import * as Errors from './core/error'; import * as Pagination from './core/pagination'; @@ -289,21 +290,8 @@ export class Beagle { /** * Basic re-implementation of `qs.stringify` for primitive types. */ - protected stringifyQuery(query: Record): string { - return Object.entries(query) - .filter(([_, value]) => typeof value !== 'undefined') - .map(([key, value]) => { - if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { - return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; - } - if (value === null) { - return `${encodeURIComponent(key)}=`; - } - throw new Errors.BeagleError( - `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`, - ); - }) - .join('&'); + protected stringifyQuery(query: object | Record): string { + return stringifyQuery(query); } private getUserAgent(): string { @@ -340,7 +328,7 @@ export class Beagle { } if (typeof query === 'object' && query && !Array.isArray(query)) { - url.search = this.stringifyQuery(query as Record); + url.search = this.stringifyQuery(query); } return url.toString(); @@ -803,7 +791,7 @@ export class Beagle { ) { return { bodyHeaders: { 'content-type': 'application/x-www-form-urlencoded' }, - body: this.stringifyQuery(body as Record), + body: this.stringifyQuery(body), }; } else { return this.#encoder({ body, headers }); diff --git a/src/internal/utils.ts b/src/internal/utils.ts index 3cbfacce..c591353b 100644 --- a/src/internal/utils.ts +++ b/src/internal/utils.ts @@ -6,3 +6,4 @@ export * from './utils/env'; export * from './utils/log'; export * from './utils/uuid'; export * from './utils/sleep'; +export * from './utils/query'; diff --git a/src/internal/utils/query.ts b/src/internal/utils/query.ts new file mode 100644 index 00000000..2c43c947 --- /dev/null +++ b/src/internal/utils/query.ts @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { BeagleError } from '../../core/error'; + +/** + * Basic re-implementation of `qs.stringify` for primitive types. + */ +export function stringifyQuery(query: object | Record) { + return Object.entries(query) + .filter(([_, value]) => typeof value !== 'undefined') + .map(([key, value]) => { + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; + } + if (value === null) { + return `${encodeURIComponent(key)}=`; + } + throw new BeagleError( + `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`, + ); + }) + .join('&'); +} diff --git a/tests/stringifyQuery.test.ts b/tests/stringifyQuery.test.ts index 6f93dfdd..cbe61511 100644 --- a/tests/stringifyQuery.test.ts +++ b/tests/stringifyQuery.test.ts @@ -1,8 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Beagle } from '@corgi-tech/beagle'; - -const { stringifyQuery } = Beagle.prototype as any; +import { stringifyQuery } from '@corgi-tech/beagle/internal/utils/query'; describe(stringifyQuery, () => { for (const [input, expected] of [ @@ -15,7 +13,7 @@ describe(stringifyQuery, () => { 'e=f', )}=${encodeURIComponent('g&h')}`, ], - ]) { + ] as const) { it(`${JSON.stringify(input)} -> ${expected}`, () => { expect(stringifyQuery(input)).toEqual(expected); }); From 37d999e60811093717bbe1d5ff8def0042c9b359 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 13:31:47 +0000 Subject: [PATCH 093/138] chore(internal): codegen related update --- packages/mcp-server/package.json | 6 +- packages/mcp-server/src/code-tool.ts | 28 +++++++- packages/mcp-server/src/docs-search-tool.ts | 37 ++++++++++- packages/mcp-server/src/http.ts | 74 +++++++++++++++------ packages/mcp-server/src/index.ts | 26 ++++---- packages/mcp-server/src/instructions.ts | 3 +- packages/mcp-server/src/logger.ts | 28 ++++++++ packages/mcp-server/src/options.ts | 11 +++ packages/mcp-server/src/stdio.ts | 3 +- src/client.ts | 15 +++++ src/resources/enrollments.ts | 3 + src/resources/insurance-verification.ts | 3 + src/resources/plans.ts | 3 + src/resources/property-managers.ts | 3 + src/resources/tenants.ts | 3 + src/resources/webhook/endpoints.ts | 3 + 16 files changed, 206 insertions(+), 43 deletions(-) create mode 100644 packages/mcp-server/src/logger.ts diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 38145113..0afd2a82 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -39,8 +39,9 @@ "express": "^5.1.0", "fuse.js": "^7.1.0", "jq-web": "https://github.com/stainless-api/jq-web/releases/download/v0.8.8/jq-web.tar.gz", - "morgan": "^1.10.0", - "morgan-body": "^2.6.9", + "pino": "^10.3.1", + "pino-http": "^11.0.0", + "pino-pretty": "^13.1.3", "qs": "^6.14.1", "typescript": "5.8.3", "yargs": "^17.7.2", @@ -57,7 +58,6 @@ "@types/cors": "^2.8.19", "@types/express": "^5.0.3", "@types/jest": "^29.4.0", - "@types/morgan": "^1.9.10", "@types/qs": "^6.14.0", "@types/yargs": "^17.0.8", "@typescript-eslint/eslint-plugin": "8.31.1", diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 0dd9a2a9..8d2e9752 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -17,6 +17,7 @@ import { import { Tool } from '@modelcontextprotocol/sdk/types.js'; import { readEnv, requireValue } from './util'; import { WorkerInput, WorkerOutput } from './code-tool-types'; +import { getLogger } from './logger'; import { SdkMethod } from './methods'; import { McpCodeExecutionMode } from './options'; import { ClientOptions } from '@corgi-tech/beagle'; @@ -83,6 +84,8 @@ export function codeTool({ }, }; + const logger = getLogger(); + const handler = async ({ reqContext, args, @@ -107,11 +110,27 @@ export function codeTool({ } } + let result: ToolCallResult; + const startTime = Date.now(); + if (codeExecutionMode === 'local') { - return await localDenoHandler({ reqContext, args }); + logger.debug('Executing code in local Deno environment'); + result = await localDenoHandler({ reqContext, args }); } else { - return await remoteStainlessHandler({ reqContext, args }); + logger.debug('Executing code in remote Stainless environment'); + result = await remoteStainlessHandler({ reqContext, args }); } + + logger.info( + { + codeExecutionMode, + durationMs: Date.now() - startTime, + isError: result.isError, + contentRows: result.content?.length ?? 0, + }, + 'Got code tool execution result', + ); + return result; }; return { metadata, tool, handler }; @@ -156,6 +175,11 @@ const remoteStainlessHandler = async ({ }); if (!res.ok) { + if (res.status === 404 && !reqContext.stainlessApiKey) { + throw new Error( + 'Could not access code tool for this project. You may need to provide a Stainless API key via the STAINLESS_API_KEY environment variable, the --stainless-api-key flag, or the x-stainless-api-key HTTP header.', + ); + } throw new Error( `${res.status}: ${ res.statusText diff --git a/packages/mcp-server/src/docs-search-tool.ts b/packages/mcp-server/src/docs-search-tool.ts index 7b3f203f..d5fb3079 100644 --- a/packages/mcp-server/src/docs-search-tool.ts +++ b/packages/mcp-server/src/docs-search-tool.ts @@ -1,7 +1,8 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Metadata, McpRequestContext, asTextContentResult } from './types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; +import { Metadata, McpRequestContext, asTextContentResult } from './types'; +import { getLogger } from './logger'; export const metadata: Metadata = { resource: 'all', @@ -50,19 +51,49 @@ export const handler = async ({ }) => { const body = args as any; const query = new URLSearchParams(body).toString(); + + const startTime = Date.now(); const result = await fetch(`${docsSearchURL}?${query}`, { headers: { ...(reqContext.stainlessApiKey && { Authorization: reqContext.stainlessApiKey }), }, }); + const logger = getLogger(); + if (!result.ok) { + const errorText = await result.text(); + logger.warn( + { + durationMs: Date.now() - startTime, + query: body.query, + status: result.status, + statusText: result.statusText, + errorText, + }, + 'Got error response from docs search tool', + ); + + if (result.status === 404 && !reqContext.stainlessApiKey) { + throw new Error( + 'Could not find docs for this project. You may need to provide a Stainless API key via the STAINLESS_API_KEY environment variable, the --stainless-api-key flag, or the x-stainless-api-key HTTP header.', + ); + } + throw new Error( - `${result.status}: ${result.statusText} when using doc search tool. Details: ${await result.text()}`, + `${result.status}: ${result.statusText} when using doc search tool. Details: ${errorText}`, ); } - return asTextContentResult(await result.json()); + const resultBody = await result.json(); + logger.info( + { + durationMs: Date.now() - startTime, + query: body.query, + }, + 'Got docs search result', + ); + return asTextContentResult(resultBody); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index 7cd88046..e1514b24 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -4,9 +4,10 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; import { ClientOptions } from '@corgi-tech/beagle'; import express from 'express'; -import morgan from 'morgan'; -import morganBody from 'morgan-body'; +import pino from 'pino'; +import pinoHttp from 'pino-http'; import { getStainlessApiKey, parseClientAuthHeaders } from './auth'; +import { getLogger } from './logger'; import { McpOptions } from './options'; import { initMcpServer, newMcpServer } from './server'; @@ -70,29 +71,60 @@ const del = async (req: express.Request, res: express.Response) => { }); }; +const redactHeaders = (headers: Record) => { + const hiddenHeaders = /auth|cookie|key|token/i; + const filtered = { ...headers }; + Object.keys(filtered).forEach((key) => { + if (hiddenHeaders.test(key)) { + filtered[key] = '[REDACTED]'; + } + }); + return filtered; +}; + export const streamableHTTPApp = ({ clientOptions = {}, mcpOptions, - debug, }: { clientOptions?: ClientOptions; mcpOptions: McpOptions; - debug: boolean; }): express.Express => { const app = express(); app.set('query parser', 'extended'); app.use(express.json()); - - if (debug) { - morganBody(app, { - logAllReqHeader: true, - logAllResHeader: true, - logRequestBody: true, - logResponseBody: true, - }); - } else { - app.use(morgan('combined')); - } + app.use( + pinoHttp({ + logger: getLogger(), + customLogLevel: (req, res) => { + if (res.statusCode >= 500) { + return 'error'; + } else if (res.statusCode >= 400) { + return 'warn'; + } + return 'info'; + }, + customSuccessMessage: function (req, res) { + return `Request ${req.method} to ${req.url} completed with status ${res.statusCode}`; + }, + customErrorMessage: function (req, res, err) { + return `Request ${req.method} to ${req.url} errored with status ${res.statusCode}`; + }, + serializers: { + req: pino.stdSerializers.wrapRequestSerializer((req) => { + return { + ...req, + headers: redactHeaders(req.raw.headers), + }; + }), + res: pino.stdSerializers.wrapResponseSerializer((res) => { + return { + ...res, + headers: redactHeaders(res.headers), + }; + }), + }, + }), + ); app.get('/health', async (req: express.Request, res: express.Response) => { res.status(200).send('OK'); @@ -106,22 +138,22 @@ export const streamableHTTPApp = ({ export const launchStreamableHTTPServer = async ({ mcpOptions, - debug, port, }: { mcpOptions: McpOptions; - debug: boolean; port: number | string | undefined; }) => { - const app = streamableHTTPApp({ mcpOptions, debug }); + const app = streamableHTTPApp({ mcpOptions }); const server = app.listen(port); const address = server.address(); + const logger = getLogger(); + if (typeof address === 'string') { - console.error(`MCP Server running on streamable HTTP at ${address}`); + logger.info(`MCP Server running on streamable HTTP at ${address}`); } else if (address !== null) { - console.error(`MCP Server running on streamable HTTP on port ${address.port}`); + logger.info(`MCP Server running on streamable HTTP on port ${address.port}`); } else { - console.error(`MCP Server running on streamable HTTP on port ${port}`); + logger.info(`MCP Server running on streamable HTTP on port ${port}`); } }; diff --git a/packages/mcp-server/src/index.ts b/packages/mcp-server/src/index.ts index 654d25cf..5bca4a60 100644 --- a/packages/mcp-server/src/index.ts +++ b/packages/mcp-server/src/index.ts @@ -5,15 +5,20 @@ import { McpOptions, parseCLIOptions } from './options'; import { launchStdioServer } from './stdio'; import { launchStreamableHTTPServer } from './http'; import type { McpTool } from './types'; +import { configureLogger, getLogger } from './logger'; async function main() { const options = parseOptionsOrError(); + configureLogger({ + level: options.debug ? 'debug' : 'info', + pretty: options.logFormat === 'pretty', + }); const selectedTools = await selectToolsOrError(options); - console.error( - `MCP Server starting with ${selectedTools.length} tools:`, - selectedTools.map((e) => e.tool.name), + getLogger().info( + { tools: selectedTools.map((e) => e.tool.name) }, + `MCP Server starting with ${selectedTools.length} tools`, ); switch (options.transport) { @@ -23,7 +28,6 @@ async function main() { case 'http': await launchStreamableHTTPServer({ mcpOptions: options, - debug: options.debug, port: options.socket ?? options.port, }); break; @@ -32,7 +36,8 @@ async function main() { if (require.main === module) { main().catch((error) => { - console.error('Fatal error in main():', error); + // Logger might not be initialized yet + console.error('Fatal error in main()', error); process.exit(1); }); } @@ -41,7 +46,8 @@ function parseOptionsOrError() { try { return parseCLIOptions(); } catch (error) { - console.error('Error parsing options:', error); + // Logger is initialized after options, so use console.error here + console.error('Error parsing options', error); process.exit(1); } } @@ -50,16 +56,12 @@ async function selectToolsOrError(options: McpOptions): Promise { try { const includedTools = selectTools(options); if (includedTools.length === 0) { - console.error('No tools match the provided filters.'); + getLogger().error('No tools match the provided filters'); process.exit(1); } return includedTools; } catch (error) { - if (error instanceof Error) { - console.error('Error filtering tools:', error.message); - } else { - console.error('Error filtering tools:', error); - } + getLogger().error({ error }, 'Error filtering tools'); process.exit(1); } } diff --git a/packages/mcp-server/src/instructions.ts b/packages/mcp-server/src/instructions.ts index 1e78fa59..1eea4008 100644 --- a/packages/mcp-server/src/instructions.ts +++ b/packages/mcp-server/src/instructions.ts @@ -1,6 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { readEnv } from './util'; +import { getLogger } from './logger'; const INSTRUCTIONS_CACHE_TTL_MS = 15 * 60 * 1000; // 15 minutes @@ -50,7 +51,7 @@ async function fetchLatestInstructions(stainlessApiKey: string | undefined): Pro let instructions: string | undefined; if (!response.ok) { - console.warn( + getLogger().warn( 'Warning: failed to retrieve MCP server instructions. Proceeding with default instructions...', ); diff --git a/packages/mcp-server/src/logger.ts b/packages/mcp-server/src/logger.ts new file mode 100644 index 00000000..29dab11c --- /dev/null +++ b/packages/mcp-server/src/logger.ts @@ -0,0 +1,28 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { pino, type Level, type Logger } from 'pino'; +import pretty from 'pino-pretty'; + +let _logger: Logger | undefined; + +export function configureLogger({ level, pretty: usePretty }: { level: Level; pretty: boolean }): void { + _logger = pino( + { + level, + timestamp: pino.stdTimeFunctions.isoTime, + formatters: { + level(label) { + return { level: label }; + }, + }, + }, + usePretty ? pretty({ colorize: true, levelFirst: true, destination: 2 }) : process.stderr, + ); +} + +export function getLogger(): Logger { + if (!_logger) { + throw new Error('Logger has not been configured. Call configureLogger() before using the logger.'); + } + return _logger; +} diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index 069b8811..b9e8e8a6 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -8,6 +8,7 @@ import { readEnv } from './util'; export type CLIOptions = McpOptions & { debug: boolean; + logFormat: 'json' | 'pretty'; transport: 'stdio' | 'http'; port: number | undefined; socket: string | undefined; @@ -52,6 +53,11 @@ export function parseCLIOptions(): CLIOptions { "Where to run code execution in code tool; 'stainless-sandbox' will execute code in Stainless-hosted sandboxes whereas 'local' will execute code locally on the MCP server machine.", }) .option('debug', { type: 'boolean', description: 'Enable debug logging' }) + .option('log-format', { + type: 'string', + choices: ['json', 'pretty'], + description: 'Format for log output; defaults to json unless tty is detected', + }) .option('no-tools', { type: 'string', array: true, @@ -97,6 +103,10 @@ export function parseCLIOptions(): CLIOptions { const includeDocsTools = shouldIncludeToolType('docs'); const transport = argv.transport as 'stdio' | 'http'; + const logFormat = + argv.logFormat ? (argv.logFormat as 'json' | 'pretty') + : process.stderr.isTTY ? 'pretty' + : 'json'; return { ...(includeCodeTool !== undefined && { includeCodeTool }), @@ -108,6 +118,7 @@ export function parseCLIOptions(): CLIOptions { codeBlockedMethods: argv.codeBlockedMethods, codeExecutionMode: argv.codeExecutionMode as McpCodeExecutionMode, transport, + logFormat, port: argv.port, socket: argv.socket, }; diff --git a/packages/mcp-server/src/stdio.ts b/packages/mcp-server/src/stdio.ts index ceccaed3..e8bcbb19 100644 --- a/packages/mcp-server/src/stdio.ts +++ b/packages/mcp-server/src/stdio.ts @@ -1,6 +1,7 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { McpOptions } from './options'; import { initMcpServer, newMcpServer } from './server'; +import { getLogger } from './logger'; export const launchStdioServer = async (mcpOptions: McpOptions) => { const server = await newMcpServer(mcpOptions.stainlessApiKey); @@ -9,5 +10,5 @@ export const launchStdioServer = async (mcpOptions: McpOptions) => { const transport = new StdioServerTransport(); await server.connect(transport); - console.error('MCP Server running on stdio'); + getLogger().info('MCP Server running on stdio'); }; diff --git a/src/client.ts b/src/client.ts index 34775d5d..095bec1b 100644 --- a/src/client.ts +++ b/src/client.ts @@ -817,10 +817,25 @@ export class Beagle { static toFile = Uploads.toFile; + /** + * Retrieve a list of all plans or look up details by plan code. Each plan defines its name, description, rate, and any coverage values. + */ plans: API.Plans = new API.Plans(this); + /** + * Track and update your property managers. Create, list, retrieve, update, or delete property manager profiles. Each profile aggregates addresses and contact channels for billing, legal, and support. + */ propertyManagers: API.PropertyManagers = new API.PropertyManagers(this); + /** + * Maintain your tenant directory and their primary contact and address. You can create, update, retrieve, list, or delete tenant records. Listings support pagination and filtering by property manager. + */ tenants: API.Tenants = new API.Tenants(this); + /** + * Handle the connections of tenants to plans over time. Create, list, retrieve, or lapse an enrollment records. Enrollments record the chosen plan, effective date, and optional notes. + */ enrollments: API.Enrollments = new API.Enrollments(this); + /** + * Trigger insurance document parsing and verifications on demand. This is currently under development please reach out for support integrating. + */ insuranceVerification: API.InsuranceVerification = new API.InsuranceVerification(this); webhook: API.Webhook = new API.Webhook(this); } diff --git a/src/resources/enrollments.ts b/src/resources/enrollments.ts index 087e2e13..2a019e34 100644 --- a/src/resources/enrollments.ts +++ b/src/resources/enrollments.ts @@ -8,6 +8,9 @@ import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; +/** + * Handle the connections of tenants to plans over time. Create, list, retrieve, or lapse an enrollment records. Enrollments record the chosen plan, effective date, and optional notes. + */ export class Enrollments extends APIResource { /** * create a new enrollment for a tenant. diff --git a/src/resources/insurance-verification.ts b/src/resources/insurance-verification.ts index 31443022..13360aa9 100644 --- a/src/resources/insurance-verification.ts +++ b/src/resources/insurance-verification.ts @@ -4,6 +4,9 @@ import { APIResource } from '../core/resource'; import { APIPromise } from '../core/api-promise'; import { RequestOptions } from '../internal/request-options'; +/** + * Trigger insurance document parsing and verifications on demand. This is currently under development please reach out for support integrating. + */ export class InsuranceVerification extends APIResource { /** * trigger a job to parse a tenants insurance document(s) diff --git a/src/resources/plans.ts b/src/resources/plans.ts index 2e994b2d..1d115692 100644 --- a/src/resources/plans.ts +++ b/src/resources/plans.ts @@ -5,6 +5,9 @@ import { APIPromise } from '../core/api-promise'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; +/** + * Retrieve a list of all plans or look up details by plan code. Each plan defines its name, description, rate, and any coverage values. + */ export class Plans extends APIResource { /** * retrieve a specific plans details by its code. diff --git a/src/resources/property-managers.ts b/src/resources/property-managers.ts index e9b5debe..a0d8f2ee 100644 --- a/src/resources/property-managers.ts +++ b/src/resources/property-managers.ts @@ -8,6 +8,9 @@ import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; +/** + * Track and update your property managers. Create, list, retrieve, update, or delete property manager profiles. Each profile aggregates addresses and contact channels for billing, legal, and support. + */ export class PropertyManagers extends APIResource { /** * create a new property manager. diff --git a/src/resources/tenants.ts b/src/resources/tenants.ts index 8dbb94c0..09ca2d38 100644 --- a/src/resources/tenants.ts +++ b/src/resources/tenants.ts @@ -8,6 +8,9 @@ import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; +/** + * Maintain your tenant directory and their primary contact and address. You can create, update, retrieve, list, or delete tenant records. Listings support pagination and filtering by property manager. + */ export class Tenants extends APIResource { /** * create a new tenant. diff --git a/src/resources/webhook/endpoints.ts b/src/resources/webhook/endpoints.ts index 3a79c55d..5becc3ac 100644 --- a/src/resources/webhook/endpoints.ts +++ b/src/resources/webhook/endpoints.ts @@ -7,6 +7,9 @@ import { buildHeaders } from '../../internal/headers'; import { RequestOptions } from '../../internal/request-options'; import { path } from '../../internal/utils/path'; +/** + * Receive real-time notifications about tenant coverage changes and lapses. Webhooks deliver responses when tenants with third-party insurance modify their coverage or when coverage lapses, enabling you to stay informed about critical insurance status changes that may affect your properties and tenants. + */ export class Endpoints extends APIResource { /** * creates a new webhook target. From be604b5893ff914f86c895ea90d22baaddc8535d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 5 Mar 2026 07:38:31 +0000 Subject: [PATCH 094/138] chore(internal): codegen related update --- packages/mcp-server/src/code-tool.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 8d2e9752..87bcaa62 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -155,7 +155,7 @@ const remoteStainlessHandler = async ({ headers: { ...(reqContext.stainlessApiKey && { Authorization: reqContext.stainlessApiKey }), 'Content-Type': 'application/json', - client_envs: JSON.stringify({ + 'x-stainless-mcp-client-envs': JSON.stringify({ BEAGLE_API_KEY: requireValue( readEnv('BEAGLE_API_KEY') ?? client.apiKey, 'set BEAGLE_API_KEY environment variable or provide apiKey client option', From 64360c0082d42f064984c9f4deb37e0004c1c9fa Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 7 Mar 2026 10:58:31 +0000 Subject: [PATCH 095/138] chore(internal): codegen related update --- src/client.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client.ts b/src/client.ts index 095bec1b..154bfd79 100644 --- a/src/client.ts +++ b/src/client.ts @@ -657,9 +657,9 @@ export class Beagle { } } - // If the API asks us to wait a certain amount of time (and it's a reasonable amount), - // just do what it says, but otherwise calculate a default - if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) { + // If the API asks us to wait a certain amount of time, just do what it + // says, but otherwise calculate a default + if (timeoutMillis === undefined) { const maxRetries = options.maxRetries ?? this.maxRetries; timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries); } From b0f7b26a49fbfbf9bf5223f29419417be2db7214 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 8 Mar 2026 02:27:20 +0000 Subject: [PATCH 096/138] chore(internal): codegen related update --- .github/workflows/ci.yml | 12 +++++++++--- packages/mcp-server/src/docs-search-tool.ts | 3 ++- packages/mcp-server/src/instructions.ts | 14 ++------------ src/client.ts | 5 +++-- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b453721..27a518a2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,14 +55,18 @@ jobs: run: ./scripts/build - name: Get GitHub OIDC Token - if: github.repository == 'stainless-sdks/beagle-typescript' + if: |- + github.repository == 'stainless-sdks/beagle-typescript' && + !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc uses: actions/github-script@v8 with: script: core.setOutput('github_token', await core.getIDToken()); - name: Upload tarball - if: github.repository == 'stainless-sdks/beagle-typescript' + if: |- + github.repository == 'stainless-sdks/beagle-typescript' && + !startsWith(github.ref, 'refs/heads/stl/') env: URL: https://pkg.stainless.com/s AUTH: ${{ steps.github-oidc.outputs.github_token }} @@ -70,7 +74,9 @@ jobs: run: ./scripts/utils/upload-artifact.sh - name: Upload MCP Server tarball - if: github.repository == 'stainless-sdks/beagle-typescript' + if: |- + github.repository == 'stainless-sdks/beagle-typescript' && + !startsWith(github.ref, 'refs/heads/stl/') env: URL: https://pkg.stainless.com/s?subpackage=mcp-server AUTH: ${{ steps.github-oidc.outputs.github_token }} diff --git a/packages/mcp-server/src/docs-search-tool.ts b/packages/mcp-server/src/docs-search-tool.ts index d5fb3079..b06308d4 100644 --- a/packages/mcp-server/src/docs-search-tool.ts +++ b/packages/mcp-server/src/docs-search-tool.ts @@ -13,7 +13,8 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'search_docs', - description: 'Search for documentation for how to use the client to interact with the API.', + description: + 'Search SDK documentation to find methods, parameters, and usage examples for interacting with the API. Use this before writing code when you need to discover the right approach.', inputSchema: { type: 'object', properties: { diff --git a/packages/mcp-server/src/instructions.ts b/packages/mcp-server/src/instructions.ts index 1eea4008..4eb361b9 100644 --- a/packages/mcp-server/src/instructions.ts +++ b/packages/mcp-server/src/instructions.ts @@ -55,21 +55,11 @@ async function fetchLatestInstructions(stainlessApiKey: string | undefined): Pro 'Warning: failed to retrieve MCP server instructions. Proceeding with default instructions...', ); - instructions = ` - This is the beagle MCP server. You will use Code Mode to help the user perform - actions. You can use search_docs tool to learn about how to take action with this server. Then, - you will write TypeScript code using the execute tool take action. It is CRITICAL that you be - thoughtful and deliberate when executing code. Always try to entirely solve the problem in code - block: it can be as long as you need to get the job done! - `; + instructions = + '\n This is the beagle MCP server.\n\n Available tools:\n - search_docs: Search SDK documentation to find the right methods and parameters.\n - execute: Run TypeScript code against a pre-authenticated SDK client. Define an async run(client) function.\n\n Workflow:\n - If unsure about the API, call search_docs first.\n - Write complete solutions in a single execute call when possible. For large datasets, use API filters to narrow results or paginate within a single execute block.\n - If execute returns an error, read the error and fix your code rather than retrying the same approach.\n - Variables do not persist between execute calls. Return or log all data you need.\n - Individual HTTP requests to the API have a 30-second timeout. If a request times out, try a smaller query or add filters.\n - Code execution has a total timeout of approximately 5 minutes. If your code times out, simplify it or break it into smaller steps.\n '; } instructions ??= ((await response.json()) as { instructions: string }).instructions; - instructions = ` - If needed, you can get the current time by executing Date.now(). - - ${instructions} - `; return instructions; } diff --git a/src/client.ts b/src/client.ts index 154bfd79..7b556947 100644 --- a/src/client.ts +++ b/src/client.ts @@ -323,8 +323,9 @@ export class Beagle { : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path)); const defaultQuery = this.defaultQuery(); - if (!isEmptyObj(defaultQuery)) { - query = { ...defaultQuery, ...query }; + const pathQuery = Object.fromEntries(url.searchParams); + if (!isEmptyObj(defaultQuery) || !isEmptyObj(pathQuery)) { + query = { ...pathQuery, ...defaultQuery, ...query }; } if (typeof query === 'object' && query && !Array.isArray(query)) { From 7e137eba30e258562dcafff4078da074e20ff482 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 10:14:55 +0000 Subject: [PATCH 097/138] chore(internal): codegen related update --- package.json | 11 +++++++++ packages/mcp-server/package.json | 15 +++++++----- yarn.lock | 39 +++++--------------------------- 3 files changed, 26 insertions(+), 39 deletions(-) diff --git a/package.json b/package.json index bd1ab12d..b414d45b 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,17 @@ "typescript": "5.8.3", "typescript-eslint": "8.31.1" }, + "overrides": { + "minimatch": "^9.0.5" + }, + "pnpm": { + "overrides": { + "minimatch": "^9.0.5" + } + }, + "resolutions": { + "minimatch": "^9.0.5" + }, "exports": { ".": { "import": "./dist/index.mjs", diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 0afd2a82..e61b95f4 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -26,13 +26,16 @@ "format": "prettier --write --cache --cache-strategy metadata . !dist", "prepare": "npm run build", "tsn": "ts-node -r tsconfig-paths/register", - "lint": "eslint --ext ts,js .", - "fix": "eslint --fix --ext ts,js ." + "lint": "eslint .", + "fix": "eslint --fix ." }, "dependencies": { "@corgi-tech/beagle": "file:../../dist/", + "ajv": "^8.18.0", "@cloudflare/cabidela": "^0.2.4", - "@modelcontextprotocol/sdk": "^1.26.0", + "@hono/node-server": "^1.19.10", + "@modelcontextprotocol/sdk": "^1.27.1", + "hono": "^4.12.4", "@valtown/deno-http-worker": "^0.0.21", "cookie-parser": "^1.4.6", "cors": "^2.8.5", @@ -62,9 +65,9 @@ "@types/yargs": "^17.0.8", "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", - "eslint": "^8.49.0", - "eslint-plugin-prettier": "^5.0.1", - "eslint-plugin-unused-imports": "^3.0.0", + "eslint": "^9.39.1", + "eslint-plugin-prettier": "^5.4.1", + "eslint-plugin-unused-imports": "^4.1.4", "jest": "^29.4.0", "prettier": "^3.0.0", "ts-jest": "^29.1.0", diff --git a/yarn.lock b/yarn.lock index fc9f262b..078f09a8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1219,15 +1219,7 @@ baseline-browser-mapping@^2.9.0: resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz#3b6af0bc032445bca04de58caa9a87cfe921cbb3" integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== -brace-expansion@^1.1.7: - version "1.1.12" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" - integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1: +brace-expansion@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== @@ -1395,11 +1387,6 @@ commander@^10.0.1: resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - convert-source-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" @@ -2600,26 +2587,12 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^5.0.1: - version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^9.0.4: - version "9.0.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" - integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2, minimatch@^5.0.1, minimatch@^9.0.4, minimatch@^9.0.5: + version "9.0.9" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.9.tgz#9b0cb9fcb78087f6fd7eababe2511c4d3d60574e" + integrity sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg== dependencies: - brace-expansion "^2.0.1" + brace-expansion "^2.0.2" minimist@^1.2.6: version "1.2.6" From 440ae1570850aa44c6e74c1b0ef5266589e7c883 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 12 Mar 2026 15:21:10 +0000 Subject: [PATCH 098/138] chore(internal): codegen related update --- packages/mcp-server/yarn.lock | 549 +++++++++++++++++++++++----------- 1 file changed, 382 insertions(+), 167 deletions(-) diff --git a/packages/mcp-server/yarn.lock b/packages/mcp-server/yarn.lock index fe102775..c7e37692 100644 --- a/packages/mcp-server/yarn.lock +++ b/packages/mcp-server/yarn.lock @@ -297,61 +297,101 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": +"@eslint-community/eslint-utils@^4.4.0", "@eslint-community/eslint-utils@^4.8.0": version "4.9.1" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz#4e90af67bc51ddee6cdef5284edf572ec376b595" integrity sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ== dependencies: eslint-visitor-keys "^3.4.3" -"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1": +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1": version "4.12.2" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#bccdf615bcf7b6e8db830ec0b8d21c9a25de597b" integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew== -"@eslint/eslintrc@^2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" - integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== +"@eslint/config-array@^0.21.2": + version "0.21.2" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.21.2.tgz#f29e22057ad5316cf23836cee9a34c81fffcb7e6" + integrity sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw== dependencies: - ajv "^6.12.4" + "@eslint/object-schema" "^2.1.7" + debug "^4.3.1" + minimatch "^3.1.5" + +"@eslint/config-helpers@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.4.2.tgz#1bd006ceeb7e2e55b2b773ab318d300e1a66aeda" + integrity sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw== + dependencies: + "@eslint/core" "^0.17.0" + +"@eslint/core@^0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.17.0.tgz#77225820413d9617509da9342190a2019e78761c" + integrity sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/eslintrc@^3.3.5": + version "3.3.5" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.5.tgz#c131793cfc1a7b96f24a83e0a8bbd4b881558c60" + integrity sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg== + dependencies: + ajv "^6.14.0" debug "^4.3.2" - espree "^9.6.0" - globals "^13.19.0" + espree "^10.0.1" + globals "^14.0.0" ignore "^5.2.0" import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" + js-yaml "^4.1.1" + minimatch "^3.1.5" strip-json-comments "^3.1.1" -"@eslint/js@8.57.1": - version "8.57.1" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2" - integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q== +"@eslint/js@9.39.4": + version "9.39.4" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.39.4.tgz#a3f83bfc6fd9bf33a853dfacd0b49b398eb596c1" + integrity sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw== -"@hono/node-server@^1.19.7": - version "1.19.9" - resolved "https://registry.yarnpkg.com/@hono/node-server/-/node-server-1.19.9.tgz#8f37119b1acf283fd3f6035f3d1356fdb97a09ac" - integrity sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw== +"@eslint/object-schema@^2.1.7": + version "2.1.7" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.7.tgz#6e2126a1347e86a4dedf8706ec67ff8e107ebbad" + integrity sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA== -"@humanwhocodes/config-array@^0.13.0": - version "0.13.0" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748" - integrity sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw== +"@eslint/plugin-kit@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz#9779e3fd9b7ee33571a57435cf4335a1794a6cb2" + integrity sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA== dependencies: - "@humanwhocodes/object-schema" "^2.0.3" - debug "^4.3.1" - minimatch "^3.0.5" + "@eslint/core" "^0.17.0" + levn "^0.4.1" + +"@hono/node-server@^1.19.10", "@hono/node-server@^1.19.9": + version "1.19.11" + resolved "https://registry.yarnpkg.com/@hono/node-server/-/node-server-1.19.11.tgz#dc419f0826dd2504e9fc86ad289d5636a0444e2f" + integrity sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g== + +"@humanfs/core@^0.19.1": + version "0.19.1" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" + integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== + +"@humanfs/node@^0.16.6": + version "0.16.7" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.7.tgz#822cb7b3a12c5a240a24f621b5a2413e27a45f26" + integrity sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ== + dependencies: + "@humanfs/core" "^0.19.1" + "@humanwhocodes/retry" "^0.4.0" "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/object-schema@^2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" - integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== +"@humanwhocodes/retry@^0.4.0", "@humanwhocodes/retry@^0.4.2": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.3.tgz#c2b9d2e374ee62c586d3adbea87199b1d7a7a6ba" + integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== "@inquirer/checkbox@^3.0.1": version "3.0.1" @@ -741,12 +781,12 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@modelcontextprotocol/sdk@^1.25.2": - version "1.25.2" - resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.25.2.tgz#2284560b4e044b4ce5f328ee180931110cb8c5cf" - integrity sha512-LZFeo4F9M5qOhC/Uc1aQSrBHxMrvxett+9KLHt7OhcExtoiRN9DKgbZffMP/nxjutWDQpfMDfP3nkHI4X9ijww== +"@modelcontextprotocol/sdk@^1.27.1": + version "1.27.1" + resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.27.1.tgz#a602cf823bf8a68e13e7112f50aeb02b09fb83b9" + integrity sha512-sr6GbP+4edBwFndLbM60gf07z0FQ79gaExpnsjMGePXqFcSSb7t6iscpjk9DhFhwd+mTEQrzNafGP8/iGGFYaA== dependencies: - "@hono/node-server" "^1.19.7" + "@hono/node-server" "^1.19.9" ajv "^8.17.1" ajv-formats "^3.0.1" content-type "^1.0.5" @@ -754,14 +794,15 @@ cross-spawn "^7.0.5" eventsource "^3.0.2" eventsource-parser "^3.0.0" - express "^5.0.1" - express-rate-limit "^7.5.0" - jose "^6.1.1" + express "^5.2.1" + express-rate-limit "^8.2.1" + hono "^4.11.4" + jose "^6.1.3" json-schema-typed "^8.0.2" pkce-challenge "^5.0.0" raw-body "^3.0.0" zod "^3.25 || ^4.0" - zod-to-json-schema "^3.25.0" + zod-to-json-schema "^3.25.1" "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -776,7 +817,7 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": +"@nodelib/fs.walk@^1.2.3": version "1.2.8" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== @@ -784,6 +825,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@pinojs/redact@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@pinojs/redact/-/redact-0.4.0.tgz#c3de060dd12640dcc838516aa2a6803cc7b2e9d6" + integrity sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg== + "@pkgr/core@^0.2.9": version "0.2.9" resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.9.tgz#d229a7b7f9dac167a156992ef23c7f023653f53b" @@ -886,6 +932,11 @@ dependencies: "@types/node" "*" +"@types/cookie-parser@^1.4.10": + version "1.4.10" + resolved "https://registry.yarnpkg.com/@types/cookie-parser/-/cookie-parser-1.4.10.tgz#a045272a383a30597a01955d4f9c790018f214e4" + integrity sha512-B4xqkqfZ8Wek+rCOeRxsjMS9OgvzebEzzLYw7NHYuvzb7IdxOkI0ZHGgeEBX4PUM7QGVvNSK60T3OvWj3YfBRg== + "@types/cors@^2.8.19": version "2.8.19" resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.19.tgz#d93ea2673fd8c9f697367f5eeefc2bbfa94f0342" @@ -893,6 +944,11 @@ dependencies: "@types/node" "*" +"@types/estree@^1.0.6": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + "@types/express-serve-static-core@^5.0.0": version "5.1.1" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz#1a77faffee9572d39124933259be2523837d7eaa" @@ -951,6 +1007,11 @@ expect "^29.0.0" pretty-format "^29.0.0" +"@types/json-schema@^7.0.15": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + "@types/mute-stream@^0.0.4": version "0.0.4" resolved "https://registry.yarnpkg.com/@types/mute-stream/-/mute-stream-0.0.4.tgz#77208e56a08767af6c5e1237be8888e2f255c478" @@ -1100,11 +1161,6 @@ "@typescript-eslint/types" "8.31.1" eslint-visitor-keys "^4.2.0" -"@ungap/structured-clone@^1.2.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" - integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== - "@valtown/deno-http-worker@^0.0.21": version "0.0.21" resolved "https://registry.yarnpkg.com/@valtown/deno-http-worker/-/deno-http-worker-0.0.21.tgz#9ce3b5c1d0db211fe7ea8297881fe551838474ad" @@ -1130,11 +1186,16 @@ acorn-walk@^8.1.1: dependencies: acorn "^8.11.0" -acorn@^8.11.0, acorn@^8.4.1, acorn@^8.9.0: +acorn@^8.11.0, acorn@^8.4.1: version "8.15.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== +acorn@^8.15.0: + version "8.16.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.16.0.tgz#4ce79c89be40afe7afe8f3adb902a1f1ce9ac08a" + integrity sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw== + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -1150,10 +1211,10 @@ ajv-formats@^3.0.1: dependencies: ajv "^8.0.0" -ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== +ajv@^6.14.0: + version "6.14.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.14.0.tgz#fd067713e228210636ebb08c60bd3765d6dbe73a" + integrity sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" @@ -1170,6 +1231,16 @@ ajv@^8.0.0, ajv@^8.17.1: json-schema-traverse "^1.0.0" require-from-string "^2.0.2" +ajv@^8.18.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.18.0.tgz#8864186b6738d003eb3a933172bb3833e10cefbc" + integrity sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + ansi-escapes@^4.2.1, ansi-escapes@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -1219,6 +1290,11 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +atomic-sleep@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" + integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== + babel-jest@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" @@ -1474,6 +1550,11 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +colorette@^2.0.7: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + commander@^13.1.0: version "13.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-13.1.0.tgz#776167db68c78f38dcce1f9b8d7b8b9a488abf46" @@ -1499,12 +1580,25 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== +cookie-parser@^1.4.6: + version "1.4.7" + resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.7.tgz#e2125635dfd766888ffe90d60c286404fa0e7b26" + integrity sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw== + dependencies: + cookie "0.7.2" + cookie-signature "1.0.6" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + cookie-signature@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.2.2.tgz#57c7fc3cc293acab9fec54d73e15690ebe4a1793" integrity sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg== -cookie@^0.7.1: +cookie@0.7.2, cookie@^0.7.1: version "0.7.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== @@ -1535,7 +1629,7 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cross-spawn@^7.0.2, cross-spawn@^7.0.3, cross-spawn@^7.0.5: +cross-spawn@^7.0.3, cross-spawn@^7.0.5, cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== @@ -1544,6 +1638,11 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3, cross-spawn@^7.0.5: shebang-command "^2.0.0" which "^2.0.1" +dateformat@^4.6.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" + integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== + debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.7, debug@^4.4.0, debug@^4.4.3: version "4.4.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" @@ -1586,13 +1685,6 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - dunder-proto@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" @@ -1627,6 +1719,13 @@ encodeurl@^2.0.0: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== +end-of-stream@^1.1.0: + version "1.4.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c" + integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== + dependencies: + once "^1.4.0" + error-ex@^1.3.1: version "1.3.4" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414" @@ -1671,7 +1770,7 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -eslint-plugin-prettier@^5.0.1: +eslint-plugin-prettier@^5.4.1: version "5.5.5" resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz#9eae11593faa108859c26f9a9c367d619a0769c0" integrity sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw== @@ -1679,95 +1778,84 @@ eslint-plugin-prettier@^5.0.1: prettier-linter-helpers "^1.0.1" synckit "^0.11.12" -eslint-plugin-unused-imports@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-3.2.0.tgz#63a98c9ad5f622cd9f830f70bc77739f25ccfe0d" - integrity sha512-6uXyn6xdINEpxE1MtDjxQsyXB37lfyO2yKGVVgtD7WEWQGORSOZjgrD6hBhvGv4/SO+TOlS+UnC6JppRqbuwGQ== - dependencies: - eslint-rule-composer "^0.3.0" - -eslint-rule-composer@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" - integrity sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg== +eslint-plugin-unused-imports@^4.1.4: + version "4.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.4.1.tgz#a831f0a2937d7631eba30cb87091ab7d3a5da0e1" + integrity sha512-oZGYUz1X3sRMGUB+0cZyK2VcvRX5lm/vB56PgNNcU+7ficUCKm66oZWKUubXWnOuPjQ8PvmXtCViXBMONPe7tQ== -eslint-scope@^7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" - integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== +eslint-scope@^8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.4.0.tgz#88e646a207fad61436ffa39eb505147200655c82" + integrity sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: +eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint-visitor-keys@^4.2.0: +eslint-visitor-keys@^4.2.0, eslint-visitor-keys@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== -eslint@^8.49.0: - version "8.57.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.1.tgz#7df109654aba7e3bbe5c8eae533c5e461d3c6ca9" - integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.57.1" - "@humanwhocodes/config-array" "^0.13.0" +eslint@^9.39.1: + version "9.39.4" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.39.4.tgz#855da1b2e2ad66dc5991195f35e262bcec8117b5" + integrity sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ== + dependencies: + "@eslint-community/eslint-utils" "^4.8.0" + "@eslint-community/regexpp" "^4.12.1" + "@eslint/config-array" "^0.21.2" + "@eslint/config-helpers" "^0.4.2" + "@eslint/core" "^0.17.0" + "@eslint/eslintrc" "^3.3.5" + "@eslint/js" "9.39.4" + "@eslint/plugin-kit" "^0.4.1" + "@humanfs/node" "^0.16.6" "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - "@ungap/structured-clone" "^1.2.0" - ajv "^6.12.4" + "@humanwhocodes/retry" "^0.4.2" + "@types/estree" "^1.0.6" + ajv "^6.14.0" chalk "^4.0.0" - cross-spawn "^7.0.2" + cross-spawn "^7.0.6" debug "^4.3.2" - doctrine "^3.0.0" escape-string-regexp "^4.0.0" - eslint-scope "^7.2.2" - eslint-visitor-keys "^3.4.3" - espree "^9.6.1" - esquery "^1.4.2" + eslint-scope "^8.4.0" + eslint-visitor-keys "^4.2.1" + espree "^10.4.0" + esquery "^1.5.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" + file-entry-cache "^8.0.0" find-up "^5.0.0" glob-parent "^6.0.2" - globals "^13.19.0" - graphemer "^1.4.0" ignore "^5.2.0" imurmurhash "^0.1.4" is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" lodash.merge "^4.6.2" - minimatch "^3.1.2" + minimatch "^3.1.5" natural-compare "^1.4.0" optionator "^0.9.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" -espree@^9.6.0, espree@^9.6.1: - version "9.6.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" - integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== +espree@^10.0.1, espree@^10.4.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.4.0.tgz#d54f4949d4629005a1fa168d937c3ff1f7e2a837" + integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ== dependencies: - acorn "^8.9.0" + acorn "^8.15.0" acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.1" + eslint-visitor-keys "^4.2.1" esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.2: +esquery@^1.5.0: version "1.7.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.7.0.tgz#08d048f261f0ddedb5bae95f46809463d9c9496d" integrity sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g== @@ -1839,12 +1927,14 @@ expect@^29.0.0, expect@^29.7.0: jest-message-util "^29.7.0" jest-util "^29.7.0" -express-rate-limit@^7.5.0: - version "7.5.1" - resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-7.5.1.tgz#8c3a42f69209a3a1c969890070ece9e20a879dec" - integrity sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw== +express-rate-limit@^8.2.1: + version "8.3.1" + resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-8.3.1.tgz#0aaba098eadd40f6737f30a98e6b16fa1a29edfb" + integrity sha512-D1dKN+cmyPWuvB+G2SREQDzPY1agpBIcTa9sJxOPMCNeH3gwzhqJRDWCXW3gg0y//+LQ/8j52JbMROWyrKdMdw== + dependencies: + ip-address "10.1.0" -express@^5.0.1, express@^5.1.0: +express@^5.1.0, express@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/express/-/express-5.2.1.tgz#8f21d15b6d327f92b4794ecf8cb08a72f956ac04" integrity sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw== @@ -1887,6 +1977,11 @@ external-editor@^3.1.0: iconv-lite "^0.4.24" tmp "^0.0.33" +fast-copy@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-4.0.2.tgz#57f14115e1edbec274f69090072a480aa29cbedd" + integrity sha512-ybA6PDXIXOXivLJK/z9e+Otk7ve13I4ckBvGO5I2RRmBU1gMHLVDJYEuJYhGwez7YNlYji2M2DvVU+a9mSFDlw== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -1918,6 +2013,11 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-safe-stringify@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" + integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== + fast-uri@^3.0.1: version "3.1.0" resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa" @@ -1942,12 +2042,12 @@ fflate@^0.8.2: resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== dependencies: - flat-cache "^3.0.4" + flat-cache "^4.0.0" fill-range@^7.1.1: version "7.1.1" @@ -1984,14 +2084,13 @@ find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" -flat-cache@^3.0.4: - version "3.2.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" - integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== dependencies: flatted "^3.2.9" - keyv "^4.5.3" - rimraf "^3.0.2" + keyv "^4.5.4" flatted@^3.2.9: version "3.3.3" @@ -2129,12 +2228,10 @@ glob@^7.1.3, glob@^7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" -globals@^13.19.0: - version "13.24.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" - integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== - dependencies: - type-fest "^0.20.2" +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== gopd@^1.2.0: version "1.2.0" @@ -2180,6 +2277,16 @@ hasown@^2.0.2: dependencies: function-bind "^1.1.2" +help-me@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6" + integrity sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg== + +hono@^4.11.4, hono@^4.12.4: + version "4.12.7" + resolved "https://registry.yarnpkg.com/hono/-/hono-4.12.7.tgz#ca000956e965c2b3d791e43540498e616d6c6442" + integrity sha512-jq9l1DM0zVIvsm3lv9Nw9nlJnMNPOcAtsbsgiUhWcFzPE99Gvo6yRTlszSLLYacMeQ6quHD6hMfId8crVHvexw== + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -2264,6 +2371,11 @@ inherits@2, inherits@^2.0.3, inherits@~2.0.4: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +ip-address@10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-10.1.0.tgz#d8dcffb34d0e02eb241427444a6e23f5b0595aa4" + integrity sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q== + ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" @@ -2308,11 +2420,6 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - is-promise@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-4.0.0.tgz#42ff9f84206c1991d26debf520dd5c01042dd2f3" @@ -2739,10 +2846,15 @@ jest@^29.4.0: import-local "^3.0.2" jest-cli "^29.7.0" -jose@^6.1.1: - version "6.1.3" - resolved "https://registry.yarnpkg.com/jose/-/jose-6.1.3.tgz#8453d7be88af7bb7d64a0481d6a35a0145ba3ea5" - integrity sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ== +jose@^6.1.3: + version "6.2.1" + resolved "https://registry.yarnpkg.com/jose/-/jose-6.2.1.tgz#7a6b1de83816deaee9055a558e1278a7b2b9ea1b" + integrity sha512-jUaKr1yrbfaImV7R2TN/b3IcZzsw38/chqMpo2XJ7i2F8AfM/lA4G1goC3JVEwg0H7UldTmSt3P68nt31W7/mw== + +joycon@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" + integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== "jq-web@https://github.com/stainless-api/jq-web/releases/download/v0.8.8/jq-web.tar.gz": version "0.8.8" @@ -2761,7 +2873,7 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^4.1.0: +js-yaml@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== @@ -2817,7 +2929,7 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" -keyv@^4.5.3: +keyv@^4.5.4: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== @@ -2947,10 +3059,10 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.5.tgz#580c88f8d5445f2bd6aa8f3cadefa0de79fbd69e" + integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w== dependencies: brace-expansion "^1.1.7" @@ -3040,6 +3152,11 @@ object-inspect@^1.13.3: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== +on-exit-leak-free@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" + integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA== + on-finished@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" @@ -3047,7 +3164,7 @@ on-finished@^2.4.1: dependencies: ee-first "1.1.1" -once@^1.3.0, once@^1.4.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== @@ -3187,6 +3304,64 @@ picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pino-abstract-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz#b21e5f33a297e8c4c915c62b3ce5dd4a87a52c23" + integrity sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg== + dependencies: + split2 "^4.0.0" + +pino-http@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/pino-http/-/pino-http-11.0.0.tgz#ebadef4694fc59aadab9be7e5939aea625b4615f" + integrity sha512-wqg5XIAGRRIWtTk8qPGxkbrfiwEWz1lgedVLvhLALudKXvg1/L2lTFgTGPJ4Z2e3qcRmxoFxDuSdMdMGNM6I1g== + dependencies: + get-caller-file "^2.0.5" + pino "^10.0.0" + pino-std-serializers "^7.0.0" + process-warning "^5.0.0" + +pino-pretty@^13.1.3: + version "13.1.3" + resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-13.1.3.tgz#2274cccda925dd355c104079a5029f6598d0381b" + integrity sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg== + dependencies: + colorette "^2.0.7" + dateformat "^4.6.3" + fast-copy "^4.0.0" + fast-safe-stringify "^2.1.1" + help-me "^5.0.0" + joycon "^3.1.1" + minimist "^1.2.6" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^3.0.0" + pump "^3.0.0" + secure-json-parse "^4.0.0" + sonic-boom "^4.0.1" + strip-json-comments "^5.0.2" + +pino-std-serializers@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz#a7b0cd65225f29e92540e7853bd73b07479893fc" + integrity sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw== + +pino@^10.0.0, pino@^10.3.1: + version "10.3.1" + resolved "https://registry.yarnpkg.com/pino/-/pino-10.3.1.tgz#6552c8f8d8481844c9e452e7bf0be90bff1939ce" + integrity sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg== + dependencies: + "@pinojs/redact" "^0.4.0" + atomic-sleep "^1.0.0" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^3.0.0" + pino-std-serializers "^7.0.0" + process-warning "^5.0.0" + quick-format-unescaped "^4.0.3" + real-require "^0.2.0" + safe-stable-stringify "^2.3.1" + sonic-boom "^4.0.1" + thread-stream "^4.0.0" + pirates@^4.0.4: version "4.0.7" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.7.tgz#643b4a18c4257c8a65104b73f3049ce9a0a15e22" @@ -3235,6 +3410,11 @@ pretty-format@^29.0.0, pretty-format@^29.7.0: ansi-styles "^5.0.0" react-is "^18.0.0" +process-warning@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-5.0.0.tgz#566e0bf79d1dff30a72d8bbbe9e8ecefe8d378d7" + integrity sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA== + prompts@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" @@ -3251,6 +3431,14 @@ proxy-addr@^2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" +pump@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.4.tgz#1f313430527fa8b905622ebd22fe1444e757ab3c" + integrity sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + punycode@^2.1.0: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" @@ -3273,6 +3461,11 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +quick-format-unescaped@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" + integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== + range-parser@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -3302,6 +3495,11 @@ readable-stream@^3.4.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +real-require@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" + integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -3348,13 +3546,6 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - router@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/router/-/router-2.2.0.tgz#019be620b711c87641167cc79b99090f00b146ef" @@ -3378,11 +3569,21 @@ safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-stable-stringify@^2.3.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" + integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== + "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +secure-json-parse@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-4.1.0.tgz#4f1ab41c67a13497ea1b9131bb4183a22865477c" + integrity sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA== + semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" @@ -3497,6 +3698,13 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +sonic-boom@^4.0.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.2.1.tgz#28598250df4899c0ac572d7e2f0460690ba6a030" + integrity sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q== + dependencies: + atomic-sleep "^1.0.0" + source-map-support@0.5.13: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" @@ -3510,6 +3718,11 @@ source-map@^0.6.0, source-map@^0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +split2@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -3585,6 +3798,11 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@^5.0.2: + version "5.0.3" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-5.0.3.tgz#b7304249dd402ee67fd518ada993ab3593458bcf" + integrity sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw== + superstruct@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" @@ -3625,10 +3843,12 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +thread-stream@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-4.0.0.tgz#732f007c24da7084f729d6e3a7e3f5934a7380b7" + integrity sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA== + dependencies: + real-require "^0.2.0" tmp@^0.0.33: version "0.0.33" @@ -3742,11 +3962,6 @@ type-detect@4.0.8: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - type-fest@^0.21.3: version "0.21.3" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" @@ -3933,7 +4148,7 @@ yoctocolors-cjs@^2.1.2: resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz#7e4964ea8ec422b7a40ac917d3a344cfd2304baa" integrity sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw== -zod-to-json-schema@^3.24.5, zod-to-json-schema@^3.24.6, zod-to-json-schema@^3.25.0: +zod-to-json-schema@^3.24.5, zod-to-json-schema@^3.24.6, zod-to-json-schema@^3.25.1: version "3.25.1" resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz#7f24962101a439ddade2bf1aeab3c3bfec7d84ba" integrity sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA== From 9a160cf9ab6b99e57419fe01d6ee38a9278ad558 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 12 Mar 2026 23:31:47 +0000 Subject: [PATCH 099/138] feat(api): api update --- .stats.yml | 6 +- api.md | 15 -- packages/mcp-server/src/code-tool-worker.ts | 5 - packages/mcp-server/src/methods.ts | 30 --- src/resources/webhook/endpoints.ts | 192 +----------------- src/resources/webhook/index.ts | 11 +- src/resources/webhook/webhook.ts | 22 +- tests/api-resources/webhook/endpoints.test.ts | 99 --------- 8 files changed, 7 insertions(+), 373 deletions(-) delete mode 100644 tests/api-resources/webhook/endpoints.test.ts diff --git a/.stats.yml b/.stats.yml index dbeff499..943842ca 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 23 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-6d603cbe0503dc603b84acf3865e5ae1b293a8839b1b6236fdf002f316ae0569.yml -openapi_spec_hash: 0954f998dc3e52e8a55c2f15d0797c8f +configured_endpoints: 18 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-d4578381e65f8053eeba7a38dca5c581256b4fc0950d6a2e0748e2308b701393.yml +openapi_spec_hash: 0d170456faa019dfc17b4ef826d3729a config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/api.md b/api.md index 7a390d57..d8cfb5fe 100644 --- a/api.md +++ b/api.md @@ -80,18 +80,3 @@ Methods: # Webhook ## Endpoints - -Types: - -- EndpointCreateResponse -- EndpointRetrieveResponse -- EndpointUpdateResponse -- EndpointListResponse - -Methods: - -- client.webhook.endpoints.create({ ...params }) -> EndpointCreateResponse -- client.webhook.endpoints.retrieve(id) -> EndpointRetrieveResponse -- client.webhook.endpoints.update(id, { ...params }) -> EndpointUpdateResponse -- client.webhook.endpoints.list({ ...params }) -> EndpointListResponse -- client.webhook.endpoints.delete(id) -> void diff --git a/packages/mcp-server/src/code-tool-worker.ts b/packages/mcp-server/src/code-tool-worker.ts index 6b71bb40..1376ec88 100644 --- a/packages/mcp-server/src/code-tool-worker.ts +++ b/packages/mcp-server/src/code-tool-worker.ts @@ -122,11 +122,6 @@ const fuse = new Fuse( 'client.enrollments.retrieve', 'client.enrollments.retrieveCertificate', 'client.insuranceVerification.verify', - 'client.webhook.endpoints.create', - 'client.webhook.endpoints.delete', - 'client.webhook.endpoints.list', - 'client.webhook.endpoints.retrieve', - 'client.webhook.endpoints.update', ], { threshold: 1, shouldSort: true }, ); diff --git a/packages/mcp-server/src/methods.ts b/packages/mcp-server/src/methods.ts index 8e644551..90d52067 100644 --- a/packages/mcp-server/src/methods.ts +++ b/packages/mcp-server/src/methods.ts @@ -118,36 +118,6 @@ export const sdkMethods: SdkMethod[] = [ httpMethod: 'post', httpPath: '/api/insurance-verification', }, - { - clientCallName: 'client.webhook.endpoints.create', - fullyQualifiedName: 'webhook.endpoints.create', - httpMethod: 'post', - httpPath: '/api/webhook/endpoints', - }, - { - clientCallName: 'client.webhook.endpoints.retrieve', - fullyQualifiedName: 'webhook.endpoints.retrieve', - httpMethod: 'get', - httpPath: '/api/webhook/endpoints/{id}', - }, - { - clientCallName: 'client.webhook.endpoints.update', - fullyQualifiedName: 'webhook.endpoints.update', - httpMethod: 'patch', - httpPath: '/api/webhook/endpoints/{id}', - }, - { - clientCallName: 'client.webhook.endpoints.list', - fullyQualifiedName: 'webhook.endpoints.list', - httpMethod: 'get', - httpPath: '/api/webhook/endpoints', - }, - { - clientCallName: 'client.webhook.endpoints.delete', - fullyQualifiedName: 'webhook.endpoints.delete', - httpMethod: 'delete', - httpPath: '/api/webhook/endpoints/{id}', - }, ]; function allowedMethodsForCodeTool(options: McpOptions | undefined): SdkMethod[] | undefined { diff --git a/src/resources/webhook/endpoints.ts b/src/resources/webhook/endpoints.ts index 5becc3ac..2a196058 100644 --- a/src/resources/webhook/endpoints.ts +++ b/src/resources/webhook/endpoints.ts @@ -1,195 +1,5 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../core/resource'; -import * as PropertyManagersAPI from '../property-managers'; -import { APIPromise } from '../../core/api-promise'; -import { buildHeaders } from '../../internal/headers'; -import { RequestOptions } from '../../internal/request-options'; -import { path } from '../../internal/utils/path'; -/** - * Receive real-time notifications about tenant coverage changes and lapses. Webhooks deliver responses when tenants with third-party insurance modify their coverage or when coverage lapses, enabling you to stay informed about critical insurance status changes that may affect your properties and tenants. - */ -export class Endpoints extends APIResource { - /** - * creates a new webhook target. - */ - create(body: EndpointCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/api/webhook/endpoints', { body, ...options }); - } - - /** - * retrieve a single webhook endpoint by its id. - */ - retrieve(id: number, options?: RequestOptions): APIPromise { - return this._client.get(path`/api/webhook/endpoints/${id}`, options); - } - - /** - * update an existing webhook endpoint by its id. - */ - update( - id: number, - body: EndpointUpdateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.patch(path`/api/webhook/endpoints/${id}`, { body, ...options }); - } - - /** - * list all webhook endpoints, this endpoint is paginated and allows for queries by - * individual property manager. - */ - list( - query: EndpointListParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.get('/api/webhook/endpoints', { query, ...options }); - } - - /** - * delete an existing webhook endpoint by its id. - */ - delete(id: number, options?: RequestOptions): APIPromise { - return this._client.delete(path`/api/webhook/endpoints/${id}`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } -} - -export interface EndpointCreateResponse { - data: EndpointCreateResponse.Data; - - success: true; -} - -export namespace EndpointCreateResponse { - export interface Data { - id: number; - - active: boolean; - - companyId: number; - - createdAt: string; - - updatedAt: string; - - url: string; - } -} - -export interface EndpointRetrieveResponse { - data: EndpointRetrieveResponse.Data; - - success: true; -} - -export namespace EndpointRetrieveResponse { - export interface Data { - id: number; - - active: boolean; - - companyId: number; - - createdAt: string; - - updatedAt: string; - - url: string; - } -} - -export interface EndpointUpdateResponse { - data: EndpointUpdateResponse.Data; - - success: true; -} - -export namespace EndpointUpdateResponse { - export interface Data { - id: number; - - active: boolean; - - companyId: number; - - createdAt: string; - - updatedAt: string; - - url: string; - } -} - -export interface EndpointListResponse { - data: EndpointListResponse.Data; - - success: true; -} - -export namespace EndpointListResponse { - export interface Data { - items: Array; - - pagination: PropertyManagersAPI.Pagination; - } - - export namespace Data { - export interface Item { - id: number; - - active: boolean; - - companyId: number; - - createdAt: string; - - updatedAt: string; - - url: string; - } - } -} - -export interface EndpointCreateParams { - secret: string; - - url: string; - - active?: boolean; -} - -export interface EndpointUpdateParams { - secret: string; - - url: string; - - active?: boolean; -} - -export interface EndpointListParams { - /** - * Page number to fetch. - */ - page?: number; - - /** - * Number of items per page. - */ - size?: number; -} - -export declare namespace Endpoints { - export { - type EndpointCreateResponse as EndpointCreateResponse, - type EndpointRetrieveResponse as EndpointRetrieveResponse, - type EndpointUpdateResponse as EndpointUpdateResponse, - type EndpointListResponse as EndpointListResponse, - type EndpointCreateParams as EndpointCreateParams, - type EndpointUpdateParams as EndpointUpdateParams, - type EndpointListParams as EndpointListParams, - }; -} +export class Endpoints extends APIResource {} diff --git a/src/resources/webhook/index.ts b/src/resources/webhook/index.ts index 3dd38bd6..f383a789 100644 --- a/src/resources/webhook/index.ts +++ b/src/resources/webhook/index.ts @@ -1,13 +1,4 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { - Endpoints, - type EndpointCreateResponse, - type EndpointRetrieveResponse, - type EndpointUpdateResponse, - type EndpointListResponse, - type EndpointCreateParams, - type EndpointUpdateParams, - type EndpointListParams, -} from './endpoints'; +export { Endpoints } from './endpoints'; export { Webhook } from './webhook'; diff --git a/src/resources/webhook/webhook.ts b/src/resources/webhook/webhook.ts index 631ba551..10b70c91 100644 --- a/src/resources/webhook/webhook.ts +++ b/src/resources/webhook/webhook.ts @@ -2,16 +2,7 @@ import { APIResource } from '../../core/resource'; import * as EndpointsAPI from './endpoints'; -import { - EndpointCreateParams, - EndpointCreateResponse, - EndpointListParams, - EndpointListResponse, - EndpointRetrieveResponse, - EndpointUpdateParams, - EndpointUpdateResponse, - Endpoints, -} from './endpoints'; +import { Endpoints } from './endpoints'; export class Webhook extends APIResource { endpoints: EndpointsAPI.Endpoints = new EndpointsAPI.Endpoints(this._client); @@ -20,14 +11,5 @@ export class Webhook extends APIResource { Webhook.Endpoints = Endpoints; export declare namespace Webhook { - export { - Endpoints as Endpoints, - type EndpointCreateResponse as EndpointCreateResponse, - type EndpointRetrieveResponse as EndpointRetrieveResponse, - type EndpointUpdateResponse as EndpointUpdateResponse, - type EndpointListResponse as EndpointListResponse, - type EndpointCreateParams as EndpointCreateParams, - type EndpointUpdateParams as EndpointUpdateParams, - type EndpointListParams as EndpointListParams, - }; + export { Endpoints as Endpoints }; } diff --git a/tests/api-resources/webhook/endpoints.test.ts b/tests/api-resources/webhook/endpoints.test.ts deleted file mode 100644 index 3255f93d..00000000 --- a/tests/api-resources/webhook/endpoints.test.ts +++ /dev/null @@ -1,99 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Beagle from '@corgi-tech/beagle'; - -const client = new Beagle({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource endpoints', () => { - // Mock server tests are disabled - test.skip('create: only required params', async () => { - const responsePromise = client.webhook.endpoints.create({ secret: 'secret', url: 'https://example.com' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Mock server tests are disabled - test.skip('create: required and optional params', async () => { - const response = await client.webhook.endpoints.create({ - secret: 'secret', - url: 'https://example.com', - active: true, - }); - }); - - // Mock server tests are disabled - test.skip('retrieve', async () => { - const responsePromise = client.webhook.endpoints.retrieve(123); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Mock server tests are disabled - test.skip('update: only required params', async () => { - const responsePromise = client.webhook.endpoints.update(123, { - secret: 'secret', - url: 'https://example.com', - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Mock server tests are disabled - test.skip('update: required and optional params', async () => { - const response = await client.webhook.endpoints.update(123, { - secret: 'secret', - url: 'https://example.com', - active: true, - }); - }); - - // Mock server tests are disabled - test.skip('list', async () => { - const responsePromise = client.webhook.endpoints.list(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Mock server tests are disabled - test.skip('list: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.webhook.endpoints.list({ page: 1, size: 1 }, { path: '/_stainless_unknown_path' }), - ).rejects.toThrow(Beagle.NotFoundError); - }); - - // Mock server tests are disabled - test.skip('delete', async () => { - const responsePromise = client.webhook.endpoints.delete(123); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); -}); From 94258adedfbaf1272f7d137b5e10b5b9270c3b5a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 14 Mar 2026 17:04:07 +0000 Subject: [PATCH 100/138] chore(internal): codegen related update --- packages/mcp-server/src/code-tool-paths.cts | 4 +- packages/mcp-server/src/code-tool.ts | 55 ++++++++++++--------- packages/mcp-server/src/http.ts | 16 +++++- packages/mcp-server/src/instructions.ts | 25 ++++------ packages/mcp-server/src/server.ts | 2 + packages/mcp-server/src/types.ts | 1 + 6 files changed, 64 insertions(+), 39 deletions(-) diff --git a/packages/mcp-server/src/code-tool-paths.cts b/packages/mcp-server/src/code-tool-paths.cts index 15ce7f55..78263e45 100644 --- a/packages/mcp-server/src/code-tool-paths.cts +++ b/packages/mcp-server/src/code-tool-paths.cts @@ -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'); +} diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 87bcaa62..003b8d64 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -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, @@ -149,22 +144,24 @@ const remoteStainlessHandler = async ({ const codeModeEndpoint = readEnv('CODE_MODE_ENDPOINT_URL') ?? 'https://api.stainless.com/api/ai/code-tool'; + const localClientEnvs = { + BEAGLE_API_KEY: requireValue( + readEnv('BEAGLE_API_KEY') ?? client.apiKey, + 'set BEAGLE_API_KEY environment variable or provide apiKey client option', + ), + BEAGLE_BASE_URL: + readEnv('BEAGLE_BASE_URL') ?? readEnv('BEAGLE_ENVIRONMENT') ? undefined : 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({ - BEAGLE_API_KEY: requireValue( - readEnv('BEAGLE_API_KEY') ?? client.apiKey, - 'set BEAGLE_API_KEY environment variable or provide apiKey client option', - ), - BEAGLE_BASE_URL: - readEnv('BEAGLE_BASE_URL') ?? readEnv('BEAGLE_ENVIRONMENT') ? - undefined - : client.baseURL ?? undefined, - }), + 'x-stainless-mcp-client-envs': JSON.stringify(mergedClientEnvs), }, body: JSON.stringify({ project_name: 'beagle', @@ -207,6 +204,13 @@ const localDenoHandler = async ({ reqContext: McpRequestContext; args: unknown; }): Promise => { + 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 }; @@ -268,6 +272,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 }, }, }); @@ -277,13 +284,17 @@ const localDenoHandler = async ({ reject(new Error(`Worker exited with code ${exitCode}`)); }); - const opts: ClientOptions = { - baseURL: client.baseURL, - apiKey: client.apiKey, - defaultHeaders: { - 'X-Stainless-MCP': 'true', - }, - }; + // Strip null/undefined values so that the worker SDK client can fall back to + // reading from environment variables (including any upstreamClientEnvs). + const opts: ClientOptions = Object.fromEntries( + Object.entries({ + baseURL: client.baseURL, + apiKey: client.apiKey, + defaultHeaders: { + 'X-Stainless-MCP': 'true', + }, + }).filter(([_, v]) => v != null), + ) as ClientOptions; const req = worker.request( 'http://localhost', diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index e1514b24..fc77a969 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -27,6 +27,19 @@ const newServer = async ({ const authOptions = parseClientAuthHeaders(req, false); + let upstreamClientEnvs: Record | undefined; + const clientEnvsHeader = req.headers['x-stainless-mcp-client-envs']; + if (typeof clientEnvsHeader === 'string') { + try { + const parsed = JSON.parse(clientEnvsHeader); + if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) { + upstreamClientEnvs = parsed; + } + } catch { + // Ignore malformed header + } + } + await initMcpServer({ server: server, mcpOptions: mcpOptions, @@ -35,6 +48,7 @@ const newServer = async ({ ...authOptions, }, stainlessApiKey: stainlessApiKey, + upstreamClientEnvs, }); return server; @@ -72,7 +86,7 @@ const del = async (req: express.Request, res: express.Response) => { }; const redactHeaders = (headers: Record) => { - const hiddenHeaders = /auth|cookie|key|token/i; + const hiddenHeaders = /auth|cookie|key|token|x-stainless-mcp-client-envs/i; const filtered = { ...headers }; Object.keys(filtered).forEach((key) => { if (hiddenHeaders.test(key)) { diff --git a/packages/mcp-server/src/instructions.ts b/packages/mcp-server/src/instructions.ts index 4eb361b9..3a9a82ef 100644 --- a/packages/mcp-server/src/instructions.ts +++ b/packages/mcp-server/src/instructions.ts @@ -12,29 +12,24 @@ interface InstructionsCacheEntry { const instructionsCache = new Map(); -// Periodically evict stale entries so the cache doesn't grow unboundedly. -const _cacheCleanupInterval = setInterval(() => { - const now = Date.now(); - for (const [key, entry] of instructionsCache) { - if (now - entry.fetchedAt > INSTRUCTIONS_CACHE_TTL_MS) { - instructionsCache.delete(key); - } - } -}, INSTRUCTIONS_CACHE_TTL_MS); - -// Don't keep the process alive just for cleanup. -_cacheCleanupInterval.unref(); - export async function getInstructions(stainlessApiKey: string | undefined): Promise { + const now = Date.now(); const cacheKey = stainlessApiKey ?? ''; const cached = instructionsCache.get(cacheKey); - if (cached && Date.now() - cached.fetchedAt <= INSTRUCTIONS_CACHE_TTL_MS) { + if (cached && now - cached.fetchedAt <= INSTRUCTIONS_CACHE_TTL_MS) { return cached.fetchedInstructions; } + // Evict stale entries so the cache doesn't grow unboundedly. + for (const [key, entry] of instructionsCache) { + if (now - entry.fetchedAt > INSTRUCTIONS_CACHE_TTL_MS) { + instructionsCache.delete(key); + } + } + const fetchedInstructions = await fetchLatestInstructions(stainlessApiKey); - instructionsCache.set(cacheKey, { fetchedInstructions, fetchedAt: Date.now() }); + instructionsCache.set(cacheKey, { fetchedInstructions, fetchedAt: now }); return fetchedInstructions; } diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 2c909c19..61e6ceba 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -38,6 +38,7 @@ export async function initMcpServer(params: { clientOptions?: ClientOptions; mcpOptions?: McpOptions; stainlessApiKey?: string | undefined; + upstreamClientEnvs?: Record | undefined; }) { const server = params.server instanceof McpServer ? params.server.server : params.server; @@ -120,6 +121,7 @@ export async function initMcpServer(params: { reqContext: { client, stainlessApiKey: params.stainlessApiKey ?? params.mcpOptions?.stainlessApiKey, + upstreamClientEnvs: params.upstreamClientEnvs, }, args, }); diff --git a/packages/mcp-server/src/types.ts b/packages/mcp-server/src/types.ts index 038c3985..8f1a8486 100644 --- a/packages/mcp-server/src/types.ts +++ b/packages/mcp-server/src/types.ts @@ -45,6 +45,7 @@ export type ToolCallResult = { export type McpRequestContext = { client: Beagle; stainlessApiKey?: string | undefined; + upstreamClientEnvs?: Record | undefined; }; export type HandlerFunction = ({ From d1bdeb77d1a6d0e46e67e6d4865f7d0da0d689a7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 17 Mar 2026 14:38:32 +0000 Subject: [PATCH 101/138] chore(internal): codegen related update --- .github/workflows/ci.yml | 14 ++++++++------ packages/mcp-server/src/http.ts | 30 +++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 27a518a2..4d817cde 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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/**' diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index fc77a969..acbda258 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -40,9 +40,37 @@ const newServer = async ({ } } + // Parse x-stainless-mcp-client-permissions header to override permission options + // + // Note: Permissions are best-effort and intended to prevent clients from doing unexpected things; + // they're not a hard security boundary, so we allow arbitrary, client-driven overrides. + // + // See the Stainless MCP documentation for more details. + let effectiveMcpOptions = mcpOptions; + const clientPermissionsHeader = req.headers['x-stainless-mcp-client-permissions']; + if (typeof clientPermissionsHeader === 'string') { + try { + const parsed = JSON.parse(clientPermissionsHeader); + if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) { + effectiveMcpOptions = { + ...mcpOptions, + ...(typeof parsed.allow_http_gets === 'boolean' && { codeAllowHttpGets: parsed.allow_http_gets }), + ...(Array.isArray(parsed.allowed_methods) && { codeAllowedMethods: parsed.allowed_methods }), + ...(Array.isArray(parsed.blocked_methods) && { codeBlockedMethods: parsed.blocked_methods }), + }; + getLogger().info( + { clientPermissions: parsed }, + 'Overriding code execution permissions from x-stainless-mcp-client-permissions header', + ); + } + } catch (error) { + getLogger().warn({ error }, 'Failed to parse x-stainless-mcp-client-permissions header'); + } + } + await initMcpServer({ server: server, - mcpOptions: mcpOptions, + mcpOptions: effectiveMcpOptions, clientOptions: { ...clientOptions, ...authOptions, From d60812edd7fba4a49d43cd19f05f5c0a0cdc19eb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 17 Mar 2026 16:33:24 +0000 Subject: [PATCH 102/138] feat(api): api update --- .stats.yml | 4 ++-- src/resources/property-managers.ts | 9 +++++++++ tests/api-resources/property-managers.test.ts | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 943842ca..23f0bbee 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 18 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-d4578381e65f8053eeba7a38dca5c581256b4fc0950d6a2e0748e2308b701393.yml -openapi_spec_hash: 0d170456faa019dfc17b4ef826d3729a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-f340cf66cf6c32aee8c389f9669af6a597b8cc6d4dfa43b1684891bd4456f6c3.yml +openapi_spec_hash: 19d0b34634cf043a359948267866fef4 config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/src/resources/property-managers.ts b/src/resources/property-managers.ts index a0d8f2ee..ff1da565 100644 --- a/src/resources/property-managers.ts +++ b/src/resources/property-managers.ts @@ -143,6 +143,9 @@ export interface PropertyManager { */ name: string; + /** + * unix timestamp (ms) of clickwrap agreement signature + */ clickWrapAt?: number; } @@ -198,6 +201,9 @@ export interface PropertyManagerCreateParams { */ name: string; + /** + * unix timestamp (ms) of clickwrap agreement signature + */ clickWrapAt?: number; } @@ -214,6 +220,9 @@ export namespace PropertyManagerCreateParams { export interface PropertyManagerUpdateParams { addresses?: Array; + /** + * unix timestamp (ms) of clickwrap agreement signature + */ clickWrapAt?: number; contacts?: Array; diff --git a/tests/api-resources/property-managers.test.ts b/tests/api-resources/property-managers.test.ts index ade84b77..eb409837 100644 --- a/tests/api-resources/property-managers.test.ts +++ b/tests/api-resources/property-managers.test.ts @@ -60,7 +60,7 @@ describe('resource propertyManagers', () => { }, ], name: 'name', - clickWrapAt: 0, + clickWrapAt: 946684800000, }); }); From dd8e619d252ab2568fd779a79449789628f6eb4c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 20 Mar 2026 23:32:07 +0000 Subject: [PATCH 103/138] feat(api): api update --- .stats.yml | 4 ++-- src/resources/property-managers.ts | 32 ++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/.stats.yml b/.stats.yml index 23f0bbee..0cda3249 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 18 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-f340cf66cf6c32aee8c389f9669af6a597b8cc6d4dfa43b1684891bd4456f6c3.yml -openapi_spec_hash: 19d0b34634cf043a359948267866fef4 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-2be66f33121d1e682b2b34d3594a529e13e21c97a51c5778f18845d24273d76d.yml +openapi_spec_hash: 58b42d9f6c1caa1030e9461f26b95d94 config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/src/resources/property-managers.ts b/src/resources/property-managers.ts index ff1da565..5e6018b9 100644 --- a/src/resources/property-managers.ts +++ b/src/resources/property-managers.ts @@ -60,8 +60,10 @@ export class PropertyManagers extends APIResource { } /** - * update an existing property manager by id, note that when updating contacts or - * addresses you need to send the whole array you want to replace them with. + * update an existing property manager by ID + * + * (Note that when updating **contacts** or **addresses** you need to send the + * whole array you want to replace them with) * * @example * ```ts @@ -94,7 +96,7 @@ export class PropertyManagers extends APIResource { } /** - * delete a property manager by id. + * delete a property manager by ID. * * @example * ```ts @@ -134,12 +136,18 @@ export interface Pagination { export interface PropertyManager { id: number; + /** + * street addresses for each Property + */ addresses: Array; + /** + * contact information for each Property Manager + */ contacts: Array; /** - * name of the property manager + * name of the Property Management Company */ name: string; @@ -192,12 +200,18 @@ export namespace PropertyManagerListResponse { } export interface PropertyManagerCreateParams { + /** + * street addresses for each Property + */ addresses: Array; + /** + * contact information for each Property Manager + */ contacts: Array; /** - * name of the property manager + * name of the Property Management Company */ name: string; @@ -218,6 +232,9 @@ export namespace PropertyManagerCreateParams { } export interface PropertyManagerUpdateParams { + /** + * street addresses for each Property + */ addresses?: Array; /** @@ -225,10 +242,13 @@ export interface PropertyManagerUpdateParams { */ clickWrapAt?: number; + /** + * contact information for each Property Manager + */ contacts?: Array; /** - * name of the property manager + * name of the Property Management Company */ name?: string; } From 5b0416129e941ab2cf00b73a3748d9edc491fb94 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 24 Mar 2026 05:28:01 +0000 Subject: [PATCH 104/138] chore(internal): codegen related update --- .gitignore | 1 + packages/mcp-server/src/code-tool.ts | 16 +++++++--------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index d62bea50..b7d4f6b9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .prism.log +.stdy.log node_modules yarn-error.log codegen.log diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 003b8d64..86e7a56c 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -286,15 +286,13 @@ const localDenoHandler = async ({ // Strip null/undefined values so that the worker SDK client can fall back to // reading from environment variables (including any upstreamClientEnvs). - const opts: ClientOptions = Object.fromEntries( - Object.entries({ - baseURL: client.baseURL, - apiKey: client.apiKey, - defaultHeaders: { - 'X-Stainless-MCP': 'true', - }, - }).filter(([_, v]) => v != null), - ) as ClientOptions; + const opts = { + ...(client.baseURL != null ? { baseURL: client.baseURL } : undefined), + ...(client.apiKey != null ? { apiKey: client.apiKey } : undefined), + defaultHeaders: { + 'X-Stainless-MCP': 'true', + }, + } satisfies Partial as ClientOptions; const req = worker.request( 'http://localhost', From 4b5a6626ff1f3ce289c7a2bc25b3fb200f6beeaf Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 25 Mar 2026 03:35:17 +0000 Subject: [PATCH 105/138] chore(internal): codegen related update --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4d817cde..926fb73e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: timeout-minutes: 10 name: lint runs-on: ${{ github.repository == 'stainless-sdks/beagle-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 @@ -38,7 +38,7 @@ jobs: timeout-minutes: 5 name: build runs-on: ${{ github.repository == 'stainless-sdks/beagle-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 From 1456ba62ee4641021cb2aef893588bffc71d791e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 27 Mar 2026 07:00:03 +0000 Subject: [PATCH 106/138] chore(internal): codegen related update --- packages/mcp-server/src/http.ts | 3 ++- packages/mcp-server/src/instructions.ts | 31 +++++++++++++++++++++---- packages/mcp-server/src/options.ts | 6 +++++ packages/mcp-server/src/server.ts | 10 ++++++-- packages/mcp-server/src/stdio.ts | 5 +++- 5 files changed, 47 insertions(+), 8 deletions(-) diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index acbda258..b8255445 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -23,7 +23,8 @@ const newServer = async ({ res: express.Response; }): Promise => { const stainlessApiKey = getStainlessApiKey(req, mcpOptions); - const server = await newMcpServer(stainlessApiKey); + const customInstructionsPath = mcpOptions.customInstructionsPath; + const server = await newMcpServer({ stainlessApiKey, customInstructionsPath }); const authOptions = parseClientAuthHeaders(req, false); diff --git a/packages/mcp-server/src/instructions.ts b/packages/mcp-server/src/instructions.ts index 3a9a82ef..f3086d66 100644 --- a/packages/mcp-server/src/instructions.ts +++ b/packages/mcp-server/src/instructions.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import fs from 'fs/promises'; import { readEnv } from './util'; import { getLogger } from './logger'; @@ -12,9 +13,15 @@ interface InstructionsCacheEntry { const instructionsCache = new Map(); -export async function getInstructions(stainlessApiKey: string | undefined): Promise { +export async function getInstructions({ + stainlessApiKey, + customInstructionsPath, +}: { + stainlessApiKey?: string | undefined; + customInstructionsPath?: string | undefined; +}): Promise { const now = Date.now(); - const cacheKey = stainlessApiKey ?? ''; + const cacheKey = customInstructionsPath ?? stainlessApiKey ?? ''; const cached = instructionsCache.get(cacheKey); if (cached && now - cached.fetchedAt <= INSTRUCTIONS_CACHE_TTL_MS) { @@ -28,12 +35,28 @@ export async function getInstructions(stainlessApiKey: string | undefined): Prom } } - const fetchedInstructions = await fetchLatestInstructions(stainlessApiKey); + let fetchedInstructions: string; + + if (customInstructionsPath) { + fetchedInstructions = await fetchLatestInstructionsFromFile(customInstructionsPath); + } else { + fetchedInstructions = await fetchLatestInstructionsFromApi(stainlessApiKey); + } + instructionsCache.set(cacheKey, { fetchedInstructions, fetchedAt: now }); return fetchedInstructions; } -async function fetchLatestInstructions(stainlessApiKey: string | undefined): Promise { +async function fetchLatestInstructionsFromFile(path: string): Promise { + try { + return await fs.readFile(path, 'utf-8'); + } catch (error) { + getLogger().error({ error, path }, 'Error fetching instructions from file'); + throw error; + } +} + +async function fetchLatestInstructionsFromApi(stainlessApiKey: string | undefined): Promise { // Setting the stainless API key is optional, but may be required // to authenticate requests to the Stainless API. const response = await fetch( diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index b9e8e8a6..d68058dc 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -22,6 +22,7 @@ export type McpOptions = { codeAllowedMethods?: string[] | undefined; codeBlockedMethods?: string[] | undefined; codeExecutionMode: McpCodeExecutionMode; + customInstructionsPath?: string | undefined; }; export type McpCodeExecutionMode = 'stainless-sandbox' | 'local'; @@ -52,6 +53,10 @@ export function parseCLIOptions(): CLIOptions { description: "Where to run code execution in code tool; 'stainless-sandbox' will execute code in Stainless-hosted sandboxes whereas 'local' will execute code locally on the MCP server machine.", }) + .option('custom-instructions-path', { + type: 'string', + description: 'Path to custom instructions for the MCP server', + }) .option('debug', { type: 'boolean', description: 'Enable debug logging' }) .option('log-format', { type: 'string', @@ -117,6 +122,7 @@ export function parseCLIOptions(): CLIOptions { codeAllowedMethods: argv.codeAllowedMethods, codeBlockedMethods: argv.codeBlockedMethods, codeExecutionMode: argv.codeExecutionMode as McpCodeExecutionMode, + customInstructionsPath: argv.customInstructionsPath, transport, logFormat, port: argv.port, diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 61e6ceba..8a342c43 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -17,14 +17,20 @@ import { blockedMethodsForCodeTool } from './methods'; import { HandlerFunction, McpRequestContext, ToolCallResult, McpTool } from './types'; import { readEnv } from './util'; -export const newMcpServer = async (stainlessApiKey: string | undefined) => +export const newMcpServer = async ({ + stainlessApiKey, + customInstructionsPath, +}: { + stainlessApiKey?: string | undefined; + customInstructionsPath?: string | undefined; +}) => new McpServer( { name: 'corgi_tech_beagle_api', version: '0.0.1-alpha.0', }, { - instructions: await getInstructions(stainlessApiKey), + instructions: await getInstructions({ stainlessApiKey, customInstructionsPath }), capabilities: { tools: {}, logging: {} }, }, ); diff --git a/packages/mcp-server/src/stdio.ts b/packages/mcp-server/src/stdio.ts index e8bcbb19..b04a5441 100644 --- a/packages/mcp-server/src/stdio.ts +++ b/packages/mcp-server/src/stdio.ts @@ -4,7 +4,10 @@ import { initMcpServer, newMcpServer } from './server'; import { getLogger } from './logger'; export const launchStdioServer = async (mcpOptions: McpOptions) => { - const server = await newMcpServer(mcpOptions.stainlessApiKey); + const server = await newMcpServer({ + stainlessApiKey: mcpOptions.stainlessApiKey, + customInstructionsPath: mcpOptions.customInstructionsPath, + }); await initMcpServer({ server, mcpOptions, stainlessApiKey: mcpOptions.stainlessApiKey }); From b749c77c8a7bcec61090e4ffed69a9af715ec390 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 28 Mar 2026 07:58:37 +0000 Subject: [PATCH 107/138] chore(internal): codegen related update --- .github/workflows/publish-npm.yml | 5 +- packages/mcp-server/package.json | 1 + packages/mcp-server/src/docs-search-tool.ts | 66 ++- packages/mcp-server/src/local-docs-search.ts | 546 +++++++++++++++++++ packages/mcp-server/src/options.ts | 18 + packages/mcp-server/src/server.ts | 8 + yarn.lock | 6 +- 7 files changed, 635 insertions(+), 15 deletions(-) create mode 100644 packages/mcp-server/src/local-docs-search.ts diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 545bb383..62727506 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -33,13 +33,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: + INPUT_PATH: ${{ github.event.inputs.path }} NPM_TOKEN: ${{ secrets.BEAGLE_NPM_TOKEN || secrets.NPM_TOKEN }} - name: Upload MCP Server DXT GitHub release asset diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index e61b95f4..679acbc4 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -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", diff --git a/packages/mcp-server/src/docs-search-tool.ts b/packages/mcp-server/src/docs-search-tool.ts index b06308d4..0bcbff47 100644 --- a/packages/mcp-server/src/docs-search-tool.ts +++ b/packages/mcp-server/src/docs-search-tool.ts @@ -3,6 +3,7 @@ import { Tool } from '@modelcontextprotocol/sdk/types.js'; import { Metadata, McpRequestContext, asTextContentResult } from './types'; import { getLogger } from './logger'; +import type { LocalDocsSearch } from './local-docs-search'; export const metadata: Metadata = { resource: 'all', @@ -43,20 +44,49 @@ export const tool: Tool = { const docsSearchURL = process.env['DOCS_SEARCH_URL'] || 'https://api.stainless.com/api/projects/beagle/docs/search'; -export const handler = async ({ - reqContext, - args, -}: { - reqContext: McpRequestContext; - args: Record | undefined; -}) => { +let _localSearch: LocalDocsSearch | undefined; + +export function setLocalSearch(search: LocalDocsSearch): void { + _localSearch = search; +} + +const SUPPORTED_LANGUAGES = new Set(['http', 'typescript', 'javascript']); + +async function searchLocal(args: Record): Promise { + if (!_localSearch) { + throw new Error('Local search not initialized'); + } + + const query = (args['query'] as string) ?? ''; + const language = (args['language'] as string) ?? 'typescript'; + const detail = (args['detail'] as string) ?? 'verbose'; + + if (!SUPPORTED_LANGUAGES.has(language)) { + throw new Error( + `Local docs search only supports HTTP, TypeScript, and JavaScript. Got language="${language}". ` + + `Use --docs-search-mode stainless-api for other languages, or set language to "http", "typescript", or "javascript".`, + ); + } + + return _localSearch.search({ + query, + language, + detail, + maxResults: 10, + }).results; +} + +async function searchRemote( + args: Record, + stainlessApiKey: string | undefined, +): Promise { const body = args as any; const query = new URLSearchParams(body).toString(); const startTime = Date.now(); const result = await fetch(`${docsSearchURL}?${query}`, { headers: { - ...(reqContext.stainlessApiKey && { Authorization: reqContext.stainlessApiKey }), + ...(stainlessApiKey && { Authorization: stainlessApiKey }), }, }); @@ -75,7 +105,7 @@ export const handler = async ({ 'Got error response from docs search tool', ); - if (result.status === 404 && !reqContext.stainlessApiKey) { + if (result.status === 404 && !stainlessApiKey) { throw new Error( 'Could not find docs for this project. You may need to provide a Stainless API key via the STAINLESS_API_KEY environment variable, the --stainless-api-key flag, or the x-stainless-api-key HTTP header.', ); @@ -94,7 +124,23 @@ export const handler = async ({ }, 'Got docs search result', ); - return asTextContentResult(resultBody); + return resultBody; +} + +export const handler = async ({ + reqContext, + args, +}: { + reqContext: McpRequestContext; + args: Record | undefined; +}) => { + const body = args ?? {}; + + if (_localSearch) { + return asTextContentResult(await searchLocal(body)); + } + + return asTextContentResult(await searchRemote(body, reqContext.stainlessApiKey)); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts new file mode 100644 index 00000000..88d29645 --- /dev/null +++ b/packages/mcp-server/src/local-docs-search.ts @@ -0,0 +1,546 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import MiniSearch from 'minisearch'; +import * as fs from 'node:fs/promises'; +import * as path from 'node:path'; +import { getLogger } from './logger'; + +type MethodEntry = { + name: string; + endpoint: string; + httpMethod: string; + summary: string; + description: string; + stainlessPath: string; + qualified: string; + params?: string[]; + response?: string; + markdown?: string; +}; + +type ProseChunk = { + content: string; + tag: string; + sectionContext?: string; + source?: string; +}; + +type MiniSearchDocument = { + id: string; + kind: 'http_method' | 'prose'; + name?: string; + endpoint?: string; + summary?: string; + description?: string; + qualified?: string; + stainlessPath?: string; + content?: string; + sectionContext?: string; + _original: Record; +}; + +type SearchResult = { + results: (string | Record)[]; +}; + +const EMBEDDED_METHODS: MethodEntry[] = [ + { + name: 'retrieve', + endpoint: '/api/plans/{code}', + httpMethod: 'get', + summary: 'Get Plan', + description: 'retrieve a specific plans details by its code.', + stainlessPath: '(resource) plans > (method) retrieve', + qualified: 'client.plans.retrieve', + params: ['code: string;'], + response: + '{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }; success: true; }', + markdown: + "## retrieve\n\n`client.plans.retrieve(code: string): { data: plan; success: true; }`\n\n**get** `/api/plans/{code}`\n\nretrieve a specific plans details by its code.\n\n### Parameters\n\n- `code: string`\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plan = await client.plans.retrieve('code');\n\nconsole.log(plan);\n```", + }, + { + name: 'list', + endpoint: '/api/plans', + httpMethod: 'get', + summary: 'List Plans', + description: 'List all available insurance plans that tenants can be enrolled in.', + stainlessPath: '(resource) plans > (method) list', + qualified: 'client.plans.list', + response: + '{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }[]; success: true; }', + markdown: + "## list\n\n`client.plans.list(): { data: plan[]; success: true; }`\n\n**get** `/api/plans`\n\nList all available insurance plans that tenants can be enrolled in.\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }[]; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }[]`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plans = await client.plans.list();\n\nconsole.log(plans);\n```", + }, + { + name: 'create', + endpoint: '/api/property-managers', + httpMethod: 'post', + summary: 'Create Property Manager', + description: 'create a new property manager.', + stainlessPath: '(resource) property_managers > (method) create', + qualified: 'client.propertyManagers.create', + params: [ + 'addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[];', + 'contacts: { email: string; name: { first: string; last: string; }; phone?: string; }[];', + 'name: string;', + 'clickWrapAt?: number;', + ], + response: + '{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }', + markdown: + "## create\n\n`client.propertyManagers.create(addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[], contacts: { email: string; name: object; phone?: string; }[], name: string, clickWrapAt?: number): { data: property_manager; success: true; }`\n\n**post** `/api/property-managers`\n\ncreate a new property manager.\n\n### Parameters\n\n- `addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]`\n street addresses for each Property\n\n- `contacts: { email: string; name: { first: string; last: string; }; phone?: string; }[]`\n contact information for each Property Manager\n\n- `name: string`\n name of the Property Management Company\n\n- `clickWrapAt?: number`\n unix timestamp (ms) of clickwrap agreement signature\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.create({\n addresses: [{\n city: 'city',\n state: 'xx',\n street1: 'street1',\n zip: '60513',\n kind: 'billing',\n}],\n contacts: [{\n email: 'dev@stainless.com',\n name: { first: 'first', last: 'last' },\n kind: 'agreements',\n}],\n name: 'name',\n});\n\nconsole.log(propertyManager);\n```", + }, + { + name: 'retrieve', + endpoint: '/api/property-managers/{id}', + httpMethod: 'get', + summary: 'Get Property Manager', + description: 'get a property manager by id.', + stainlessPath: '(resource) property_managers > (method) retrieve', + qualified: 'client.propertyManagers.retrieve', + params: ['id: number;'], + response: + '{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }', + markdown: + "## retrieve\n\n`client.propertyManagers.retrieve(id: number): { data: property_manager; success: true; }`\n\n**get** `/api/property-managers/{id}`\n\nget a property manager by id.\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.retrieve(123);\n\nconsole.log(propertyManager);\n```", + }, + { + name: 'update', + endpoint: '/api/property-managers/{id}', + httpMethod: 'patch', + summary: 'Update Property Manager', + description: + 'update an existing property manager by ID\n\n(Note that when updating **contacts** or **addresses** you need to send the whole array you want to replace them with)', + stainlessPath: '(resource) property_managers > (method) update', + qualified: 'client.propertyManagers.update', + params: [ + 'id: number;', + 'addresses?: { city: string; state: string; street1: string; zip: string; street2?: string; }[];', + 'clickWrapAt?: number;', + 'contacts?: { email: string; name: { first: string; last: string; }; phone?: string; }[];', + 'name?: string;', + ], + response: + '{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }', + markdown: + "## update\n\n`client.propertyManagers.update(id: number, addresses?: { city: string; state: string; street1: string; zip: string; street2?: string; }[], clickWrapAt?: number, contacts?: { email: string; name: object; phone?: string; }[], name?: string): { data: property_manager; success: true; }`\n\n**patch** `/api/property-managers/{id}`\n\nupdate an existing property manager by ID\n\n(Note that when updating **contacts** or **addresses** you need to send the whole array you want to replace them with)\n\n### Parameters\n\n- `id: number`\n\n- `addresses?: { city: string; state: string; street1: string; zip: string; street2?: string; }[]`\n street addresses for each Property\n\n- `clickWrapAt?: number`\n unix timestamp (ms) of clickwrap agreement signature\n\n- `contacts?: { email: string; name: { first: string; last: string; }; phone?: string; }[]`\n contact information for each Property Manager\n\n- `name?: string`\n name of the Property Management Company\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.update(123);\n\nconsole.log(propertyManager);\n```", + }, + { + name: 'list', + endpoint: '/api/property-managers', + httpMethod: 'get', + summary: 'List Property Managers', + description: 'list all property managers, note this endpoint is paginated.', + stainlessPath: '(resource) property_managers > (method) list', + qualified: 'client.propertyManagers.list', + params: ['page?: number;', 'size?: number;'], + response: '{ data: { items: object[]; pagination: object; }; success: true; }', + markdown: + "## list\n\n`client.propertyManagers.list(page?: number, size?: number): { data: object; success: true; }`\n\n**get** `/api/property-managers`\n\nlist all property managers, note this endpoint is paginated.\n\n### Parameters\n\n- `page?: number`\n Page number to fetch.\n\n- `size?: number`\n Number of items per page.\n\n### Returns\n\n- `{ data: { items: object[]; pagination: object; }; success: true; }`\n\n - `data: { items: { id: number; addresses: object[]; contacts: object[]; name: string; clickWrapAt?: number; }[]; pagination: { page: number; pages: number; records: number; size: number; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManagers = await client.propertyManagers.list();\n\nconsole.log(propertyManagers);\n```", + }, + { + name: 'delete', + endpoint: '/api/property-managers/{id}', + httpMethod: 'delete', + summary: 'Delete Property Manager', + description: 'delete a property manager by ID.', + stainlessPath: '(resource) property_managers > (method) delete', + qualified: 'client.propertyManagers.delete', + params: ['id: number;'], + markdown: + "## delete\n\n`client.propertyManagers.delete(id: number): void`\n\n**delete** `/api/property-managers/{id}`\n\ndelete a property manager by ID.\n\n### Parameters\n\n- `id: number`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nawait client.propertyManagers.delete(123)\n```", + }, + { + name: 'create', + endpoint: '/api/tenants', + httpMethod: 'post', + summary: 'Create Tenant', + description: 'create a new tenant.', + stainlessPath: '(resource) tenants > (method) create', + qualified: 'client.tenants.create', + params: [ + 'address: { city: string; state: string; street1: string; zip: string; street2?: string; };', + 'contact: { email: string; name: { first: string; last: string; }; phone?: string; };', + 'propertyManagerId: number;', + ], + response: '{ data: { id: number; address: address; contact: contact; }; success: true; }', + markdown: + "## create\n\n`client.tenants.create(address: { city: string; state: string; street1: string; zip: string; street2?: string; }, contact: { email: string; name: object; phone?: string; }, propertyManagerId: number): { data: tenant; success: true; }`\n\n**post** `/api/tenants`\n\ncreate a new tenant.\n\n### Parameters\n\n- `address: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `city: string`\n - `state: string`\n two letter state code, ie CA\n - `street1: string`\n - `zip: string`\n 5 digit US zip code, ie 94104\n - `street2?: string`\n\n- `contact: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `email: string`\n - `name: { first: string; last: string; }`\n - `phone?: string`\n\n- `propertyManagerId: number`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.create({\n address: {\n city: 'city',\n state: 'xx',\n street1: 'street1',\n zip: '60513',\n},\n contact: {\n email: 'dev@stainless.com',\n name: { first: 'first', last: 'last' },\n},\n propertyManagerId: 0,\n});\n\nconsole.log(tenant);\n```", + }, + { + name: 'retrieve', + endpoint: '/api/tenants/{id}', + httpMethod: 'get', + summary: 'Get Tenant', + description: 'retrieve a single tenant by their id.', + stainlessPath: '(resource) tenants > (method) retrieve', + qualified: 'client.tenants.retrieve', + params: ['id: number;'], + response: '{ data: { id: number; address: address; contact: contact; }; success: true; }', + markdown: + "## retrieve\n\n`client.tenants.retrieve(id: number): { data: tenant; success: true; }`\n\n**get** `/api/tenants/{id}`\n\nretrieve a single tenant by their id.\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.retrieve(123);\n\nconsole.log(tenant);\n```", + }, + { + name: 'update', + endpoint: '/api/tenants/{id}', + httpMethod: 'patch', + summary: 'Update Tenant', + description: 'update an existing tenant by their id.', + stainlessPath: '(resource) tenants > (method) update', + qualified: 'client.tenants.update', + params: [ + 'id: number;', + 'address?: { city: string; state: string; street1: string; zip: string; street2?: string; };', + 'contact?: { email: string; name: { first: string; last: string; }; phone?: string; };', + ], + response: '{ data: { id: number; address: address; contact: contact; }; success: true; }', + markdown: + "## update\n\n`client.tenants.update(id: number, address?: { city: string; state: string; street1: string; zip: string; street2?: string; }, contact?: { email: string; name: object; phone?: string; }): { data: tenant; success: true; }`\n\n**patch** `/api/tenants/{id}`\n\nupdate an existing tenant by their id.\n\n### Parameters\n\n- `id: number`\n\n- `address?: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `city: string`\n - `state: string`\n two letter state code, ie CA\n - `street1: string`\n - `zip: string`\n 5 digit US zip code, ie 94104\n - `street2?: string`\n\n- `contact?: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `email: string`\n - `name: { first: string; last: string; }`\n - `phone?: string`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.update(123);\n\nconsole.log(tenant);\n```", + }, + { + name: 'list', + endpoint: '/api/tenants', + httpMethod: 'get', + summary: 'List Tenants', + description: + 'list all tenants, this endpoint is paginated and allows for queries by individual property manager.', + stainlessPath: '(resource) tenants > (method) list', + qualified: 'client.tenants.list', + params: ['page?: number;', 'propertyManagerId?: number;', 'size?: number;'], + response: '{ data: { items: object[]; pagination: object; }; success: true; }', + markdown: + "## list\n\n`client.tenants.list(page?: number, propertyManagerId?: number, size?: number): { data: object; success: true; }`\n\n**get** `/api/tenants`\n\nlist all tenants, this endpoint is paginated and allows for queries by individual property manager.\n\n### Parameters\n\n- `page?: number`\n Page number to fetch.\n\n- `propertyManagerId?: number`\n\n- `size?: number`\n Number of items per page.\n\n### Returns\n\n- `{ data: { items: object[]; pagination: object; }; success: true; }`\n\n - `data: { items: { id: number; address: object; contact: object; }[]; pagination: { page: number; pages: number; records: number; size: number; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenants = await client.tenants.list();\n\nconsole.log(tenants);\n```", + }, + { + name: 'delete', + endpoint: '/api/tenants/{id}', + httpMethod: 'delete', + summary: 'Delete Tenant', + description: 'delete an existing tenant by their id.', + stainlessPath: '(resource) tenants > (method) delete', + qualified: 'client.tenants.delete', + params: ['id: number;'], + markdown: + "## delete\n\n`client.tenants.delete(id: number): void`\n\n**delete** `/api/tenants/{id}`\n\ndelete an existing tenant by their id.\n\n### Parameters\n\n- `id: number`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nawait client.tenants.delete(123)\n```", + }, + { + name: 'create', + endpoint: '/api/enrollments', + httpMethod: 'post', + summary: 'Create Enrollment', + description: 'create a new enrollment for a tenant.', + stainlessPath: '(resource) enrollments > (method) create', + qualified: 'client.enrollments.create', + params: [ + 'effectiveDate: string;', + 'plan: string;', + 'propertyManagerId: number;', + 'status: string;', + 'tenantId: number;', + 'note?: string;', + ], + response: + '{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }', + markdown: + "## create\n\n`client.enrollments.create(effectiveDate: string, plan: string, propertyManagerId: number, status: string, tenantId: number, note?: string): { data: enrollment; success: true; }`\n\n**post** `/api/enrollments`\n\ncreate a new enrollment for a tenant.\n\n### Parameters\n\n- `effectiveDate: string`\n the date the enrollment will begin, note enrollments cannot begin in the past\n\n- `plan: string`\n the plan name/code\n\n- `propertyManagerId: number`\n\n- `status: string`\n\n- `tenantId: number`\n\n- `note?: string`\n an optional note field, this can be used for easily appending metadata to enrollments\n\n### Returns\n\n- `{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }`\n\n - `data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollment = await client.enrollments.create({\n effectiveDate: 'effectiveDate',\n plan: 'plan',\n propertyManagerId: 0,\n status: 'Premium Paying',\n tenantId: 0,\n});\n\nconsole.log(enrollment);\n```", + }, + { + name: 'retrieve', + endpoint: '/api/enrollments/{id}', + httpMethod: 'get', + summary: 'Get Enrollment', + description: 'get a specific enrollment by its id.', + stainlessPath: '(resource) enrollments > (method) retrieve', + qualified: 'client.enrollments.retrieve', + params: ['id: number;'], + response: + '{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }', + markdown: + "## retrieve\n\n`client.enrollments.retrieve(id: number): { data: enrollment; success: true; }`\n\n**get** `/api/enrollments/{id}`\n\nget a specific enrollment by its id.\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }`\n\n - `data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollment = await client.enrollments.retrieve(123);\n\nconsole.log(enrollment);\n```", + }, + { + name: 'list', + endpoint: '/api/enrollments', + httpMethod: 'get', + summary: 'List Enrollments', + description: + 'list all enrollments, this endpoint is paginated and allows for queries by individual property manager.', + stainlessPath: '(resource) enrollments > (method) list', + qualified: 'client.enrollments.list', + params: ['page?: number;', 'propertyManagerId?: number;', 'size?: number;'], + response: '{ data: { items: object[]; pagination: object; }; success: true; }', + markdown: + "## list\n\n`client.enrollments.list(page?: number, propertyManagerId?: number, size?: number): { data: object; success: true; }`\n\n**get** `/api/enrollments`\n\nlist all enrollments, this endpoint is paginated and allows for queries by individual property manager.\n\n### Parameters\n\n- `page?: number`\n Page number to fetch.\n\n- `propertyManagerId?: number`\n\n- `size?: number`\n Number of items per page.\n\n### Returns\n\n- `{ data: { items: object[]; pagination: object; }; success: true; }`\n\n - `data: { items: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }[]; pagination: { page: number; pages: number; records: number; size: number; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollments = await client.enrollments.list();\n\nconsole.log(enrollments);\n```", + }, + { + name: 'lapse', + endpoint: '/api/enrollments/{id}', + httpMethod: 'delete', + summary: 'Lapse Enrollment', + description: + 'lapses a specific enrollment for a tenant, note that if a tenant has multiple enrollments (e.g., SDR and TLL), each must be lapsed individually', + stainlessPath: '(resource) enrollments > (method) lapse', + qualified: 'client.enrollments.lapse', + params: ['id: number;'], + markdown: + "## lapse\n\n`client.enrollments.lapse(id: number): void`\n\n**delete** `/api/enrollments/{id}`\n\nlapses a specific enrollment for a tenant, note that if a tenant has multiple enrollments (e.g., SDR and TLL), each must be lapsed individually\n\n### Parameters\n\n- `id: number`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nawait client.enrollments.lapse(123)\n```", + }, + { + name: 'retrieve_certificate', + endpoint: '/api/enrollments/{id}/certificate', + httpMethod: 'get', + summary: 'Get Enrollment Certificate', + description: 'get the certificate of enrollment for a given enrollment', + stainlessPath: '(resource) enrollments > (method) retrieve_certificate', + qualified: 'client.enrollments.retrieveCertificate', + params: ['id: number;'], + response: 'string', + markdown: + "## retrieve_certificate\n\n`client.enrollments.retrieveCertificate(id: number): string`\n\n**get** `/api/enrollments/{id}/certificate`\n\nget the certificate of enrollment for a given enrollment\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `string`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst response = await client.enrollments.retrieveCertificate(123);\n\nconsole.log(response);\n\nconst content = await response.blob()\nconsole.log(content)\n```", + }, + { + name: 'verify', + endpoint: '/api/insurance-verification', + httpMethod: 'post', + summary: 'Verify a tenants insurance policy', + description: 'trigger a job to parse a tenants insurance document(s)', + stainlessPath: '(resource) insurance_verification > (method) verify', + qualified: 'client.insuranceVerification.verify', + params: ['propertyManagerId: number;', 'tenantId: number;', 'urls: string[];'], + response: "{ message: 'insurance verification job scheduled'; }", + markdown: + "## verify\n\n`client.insuranceVerification.verify(propertyManagerId: number, tenantId: number, urls: string[]): { message: 'insurance verification job scheduled'; }`\n\n**post** `/api/insurance-verification`\n\ntrigger a job to parse a tenants insurance document(s)\n\n### Parameters\n\n- `propertyManagerId: number`\n\n- `tenantId: number`\n\n- `urls: string[]`\n an array of presigned pdf urls for the tenants policy document(s)\n\n### Returns\n\n- `{ message: 'insurance verification job scheduled'; }`\n\n - `message: 'insurance verification job scheduled'`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst response = await client.insuranceVerification.verify({\n propertyManagerId: 0,\n tenantId: 0,\n urls: ['string'],\n});\n\nconsole.log(response);\n```", + }, +]; + +const INDEX_OPTIONS = { + fields: [ + 'name', + 'endpoint', + 'summary', + 'description', + 'qualified', + 'stainlessPath', + 'content', + 'sectionContext', + ], + storeFields: ['kind', '_original'], + searchOptions: { + prefix: true, + fuzzy: 0.2, + boost: { + name: 3, + endpoint: 2, + summary: 2, + qualified: 2, + content: 1, + } as Record, + }, +}; + +/** + * Self-contained local search engine backed by MiniSearch. + * Method data is embedded at SDK build time; prose documents + * can be loaded from an optional docs directory at runtime. + */ +export class LocalDocsSearch { + private methodIndex: MiniSearch; + private proseIndex: MiniSearch; + + private constructor() { + this.methodIndex = new MiniSearch(INDEX_OPTIONS); + this.proseIndex = new MiniSearch(INDEX_OPTIONS); + } + + static async create(opts?: { docsDir?: string }): Promise { + const instance = new LocalDocsSearch(); + instance.indexMethods(EMBEDDED_METHODS); + if (opts?.docsDir) { + await instance.loadDocsDirectory(opts.docsDir); + } + return instance; + } + + // Note: Language is accepted for interface consistency with remote search, but currently has no + // effect since this local search only supports TypeScript docs. + search(props: { + query: string; + language?: string; + detail?: string; + maxResults?: number; + maxLength?: number; + }): SearchResult { + const { query, detail = 'default', maxResults = 5, maxLength = 100_000 } = props; + + const useMarkdown = detail === 'verbose' || detail === 'high'; + + // Search both indices and merge results by score + const methodHits = this.methodIndex + .search(query) + .map((hit) => ({ ...hit, _kind: 'http_method' as const })); + const proseHits = this.proseIndex.search(query).map((hit) => ({ ...hit, _kind: 'prose' as const })); + const merged = [...methodHits, ...proseHits].sort((a, b) => b.score - a.score); + const top = merged.slice(0, maxResults); + + const fullResults: (string | Record)[] = []; + + for (const hit of top) { + const original = (hit as Record)['_original']; + if (hit._kind === 'http_method') { + const m = original as MethodEntry; + if (useMarkdown && m.markdown) { + fullResults.push(m.markdown); + } else { + fullResults.push({ + method: m.qualified, + summary: m.summary, + description: m.description, + endpoint: `${m.httpMethod.toUpperCase()} ${m.endpoint}`, + ...(m.params ? { params: m.params } : {}), + ...(m.response ? { response: m.response } : {}), + }); + } + } else { + const c = original as ProseChunk; + fullResults.push({ + content: c.content, + ...(c.source ? { source: c.source } : {}), + }); + } + } + + let totalLength = 0; + const results: (string | Record)[] = []; + for (const result of fullResults) { + const len = typeof result === 'string' ? result.length : JSON.stringify(result).length; + totalLength += len; + if (totalLength > maxLength) break; + results.push(result); + } + + if (results.length < fullResults.length) { + results.unshift(`Truncated; showing ${results.length} of ${fullResults.length} results.`); + } + + return { results }; + } + + private indexMethods(methods: MethodEntry[]): void { + const docs: MiniSearchDocument[] = methods.map((m, i) => ({ + id: `method-${i}`, + kind: 'http_method' as const, + name: m.name, + endpoint: m.endpoint, + summary: m.summary, + description: m.description, + qualified: m.qualified, + stainlessPath: m.stainlessPath, + _original: m as unknown as Record, + })); + if (docs.length > 0) { + this.methodIndex.addAll(docs); + } + } + + private async loadDocsDirectory(docsDir: string): Promise { + let entries; + try { + entries = await fs.readdir(docsDir, { withFileTypes: true }); + } catch (err) { + getLogger().warn({ err, docsDir }, 'Could not read docs directory'); + return; + } + + const files = entries + .filter((e) => e.isFile()) + .filter((e) => e.name.endsWith('.md') || e.name.endsWith('.markdown') || e.name.endsWith('.json')); + + for (const file of files) { + try { + const filePath = path.join(docsDir, file.name); + const content = await fs.readFile(filePath, 'utf-8'); + + if (file.name.endsWith('.json')) { + const texts = extractTexts(JSON.parse(content)); + if (texts.length > 0) { + this.indexProse(texts.join('\n\n'), file.name); + } + } else { + this.indexProse(content, file.name); + } + } catch (err) { + getLogger().warn({ err, file: file.name }, 'Failed to index docs file'); + } + } + } + + private indexProse(markdown: string, source: string): void { + const chunks = chunkMarkdown(markdown); + const baseId = this.proseIndex.documentCount; + + const docs: MiniSearchDocument[] = chunks.map((chunk, i) => ({ + id: `prose-${baseId + i}`, + kind: 'prose' as const, + content: chunk.content, + ...(chunk.sectionContext != null ? { sectionContext: chunk.sectionContext } : {}), + _original: { ...chunk, source } as unknown as Record, + })); + + if (docs.length > 0) { + this.proseIndex.addAll(docs); + } + } +} + +/** Lightweight markdown chunker — splits on headers, chunks by word count. */ +function chunkMarkdown(markdown: string): { content: string; tag: string; sectionContext?: string }[] { + // Strip YAML frontmatter + const stripped = markdown.replace(/^---\n[\s\S]*?\n---\n?/, ''); + const lines = stripped.split('\n'); + + const chunks: { content: string; tag: string; sectionContext?: string }[] = []; + const headers: string[] = []; + let current: string[] = []; + + const flush = () => { + const text = current.join('\n').trim(); + if (!text) return; + const sectionContext = headers.length > 0 ? headers.join(' > ') : undefined; + // Split into ~200-word chunks + const words = text.split(/\s+/); + for (let i = 0; i < words.length; i += 200) { + const slice = words.slice(i, i + 200).join(' '); + if (slice) { + chunks.push({ content: slice, tag: 'p', ...(sectionContext != null ? { sectionContext } : {}) }); + } + } + current = []; + }; + + for (const line of lines) { + const headerMatch = line.match(/^(#{1,6})\s+(.+)/); + if (headerMatch) { + flush(); + const level = headerMatch[1]!.length; + const text = headerMatch[2]!.trim(); + while (headers.length >= level) headers.pop(); + headers.push(text); + } else { + current.push(line); + } + } + flush(); + + return chunks; +} + +/** Recursively extracts string values from a JSON structure. */ +function extractTexts(data: unknown, depth = 0): string[] { + if (depth > 10) return []; + if (typeof data === 'string') return data.trim() ? [data] : []; + if (Array.isArray(data)) return data.flatMap((item) => extractTexts(item, depth + 1)); + if (typeof data === 'object' && data !== null) { + return Object.values(data).flatMap((v) => extractTexts(v, depth + 1)); + } + return []; +} diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index d68058dc..f1518764 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -18,6 +18,8 @@ export type McpOptions = { includeCodeTool?: boolean | undefined; includeDocsTools?: boolean | undefined; stainlessApiKey?: string | undefined; + docsSearchMode?: 'stainless-api' | 'local' | undefined; + docsDir?: string | undefined; codeAllowHttpGets?: boolean | undefined; codeAllowedMethods?: string[] | undefined; codeBlockedMethods?: string[] | undefined; @@ -58,6 +60,18 @@ export function parseCLIOptions(): CLIOptions { description: 'Path to custom instructions for the MCP server', }) .option('debug', { type: 'boolean', description: 'Enable debug logging' }) + .option('docs-dir', { + type: 'string', + description: + 'Path to a directory of local documentation files (markdown/JSON) to include in local docs search.', + }) + .option('docs-search-mode', { + type: 'string', + choices: ['stainless-api', 'local'], + default: 'stainless-api', + description: + "Where to search documentation; 'stainless-api' uses the Stainless-hosted search API whereas 'local' uses an in-memory search index built from embedded SDK method data and optional local docs files.", + }) .option('log-format', { type: 'string', choices: ['json', 'pretty'], @@ -118,6 +132,8 @@ export function parseCLIOptions(): CLIOptions { ...(includeDocsTools !== undefined && { includeDocsTools }), debug: !!argv.debug, stainlessApiKey: argv.stainlessApiKey, + docsSearchMode: argv.docsSearchMode as 'stainless-api' | 'local' | undefined, + docsDir: argv.docsDir, codeAllowHttpGets: argv.codeAllowHttpGets, codeAllowedMethods: argv.codeAllowedMethods, codeBlockedMethods: argv.codeBlockedMethods, @@ -163,5 +179,7 @@ export function parseQueryOptions(defaultOptions: McpOptions, query: unknown): M ...(codeTool !== undefined && { includeCodeTool: codeTool }), ...(docsTools !== undefined && { includeDocsTools: docsTools }), codeExecutionMode: defaultOptions.codeExecutionMode, + docsSearchMode: defaultOptions.docsSearchMode, + docsDir: defaultOptions.docsDir, }; } diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 8a342c43..b124d6f6 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -11,6 +11,8 @@ import { ClientOptions } from '@corgi-tech/beagle'; import Beagle from '@corgi-tech/beagle'; import { codeTool } from './code-tool'; import docsSearchTool from './docs-search-tool'; +import { setLocalSearch } from './docs-search-tool'; +import { LocalDocsSearch } from './local-docs-search'; import { getInstructions } from './instructions'; import { McpOptions } from './options'; import { blockedMethodsForCodeTool } from './methods'; @@ -63,6 +65,12 @@ export async function initMcpServer(params: { error: logAtLevel('error'), }; + if (params.mcpOptions?.docsSearchMode === 'local') { + const docsDir = params.mcpOptions?.docsDir; + const localSearch = await LocalDocsSearch.create(docsDir ? { docsDir } : undefined); + setLocalSearch(localSearch); + } + let _client: Beagle | undefined; let _clientError: Error | undefined; let _logLevel: 'debug' | 'info' | 'warn' | 'error' | 'off' | undefined; diff --git a/yarn.lock b/yarn.lock index 078f09a8..e5e2a93b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1220,9 +1220,9 @@ baseline-browser-mapping@^2.9.0: integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== brace-expansion@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" - integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== + version "2.0.3" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.3.tgz#0493338bdd58e319b1039c67cf7ee439892c01d9" + integrity sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA== dependencies: balanced-match "^1.0.0" From 5062a2c25ad7601b8d0da820cd2f500757828885 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:21:01 +0000 Subject: [PATCH 108/138] chore(internal): codegen related update --- packages/mcp-server/src/docs-search-tool.ts | 28 +++----- packages/mcp-server/src/http.ts | 16 +++++ packages/mcp-server/src/local-docs-search.ts | 73 +++++++++++++++++--- packages/mcp-server/src/server.ts | 4 ++ packages/mcp-server/src/types.ts | 2 + 5 files changed, 94 insertions(+), 29 deletions(-) diff --git a/packages/mcp-server/src/docs-search-tool.ts b/packages/mcp-server/src/docs-search-tool.ts index 0bcbff47..eed209aa 100644 --- a/packages/mcp-server/src/docs-search-tool.ts +++ b/packages/mcp-server/src/docs-search-tool.ts @@ -50,8 +50,6 @@ export function setLocalSearch(search: LocalDocsSearch): void { _localSearch = search; } -const SUPPORTED_LANGUAGES = new Set(['http', 'typescript', 'javascript']); - async function searchLocal(args: Record): Promise { if (!_localSearch) { throw new Error('Local search not initialized'); @@ -59,34 +57,28 @@ async function searchLocal(args: Record): Promise { const query = (args['query'] as string) ?? ''; const language = (args['language'] as string) ?? 'typescript'; - const detail = (args['detail'] as string) ?? 'verbose'; - - if (!SUPPORTED_LANGUAGES.has(language)) { - throw new Error( - `Local docs search only supports HTTP, TypeScript, and JavaScript. Got language="${language}". ` + - `Use --docs-search-mode stainless-api for other languages, or set language to "http", "typescript", or "javascript".`, - ); - } + const detail = (args['detail'] as string) ?? 'default'; return _localSearch.search({ query, language, detail, - maxResults: 10, + maxResults: 5, }).results; } -async function searchRemote( - args: Record, - stainlessApiKey: string | undefined, -): Promise { +async function searchRemote(args: Record, reqContext: McpRequestContext): Promise { const body = args as any; const query = new URLSearchParams(body).toString(); const startTime = Date.now(); const result = await fetch(`${docsSearchURL}?${query}`, { headers: { - ...(stainlessApiKey && { Authorization: stainlessApiKey }), + ...(reqContext.stainlessApiKey && { Authorization: reqContext.stainlessApiKey }), + ...(reqContext.mcpSessionId && { 'x-stainless-mcp-session-id': reqContext.mcpSessionId }), + ...(reqContext.mcpClientInfo && { + 'x-stainless-mcp-client-info': JSON.stringify(reqContext.mcpClientInfo), + }), }, }); @@ -105,7 +97,7 @@ async function searchRemote( 'Got error response from docs search tool', ); - if (result.status === 404 && !stainlessApiKey) { + if (result.status === 404 && !reqContext.stainlessApiKey) { throw new Error( 'Could not find docs for this project. You may need to provide a Stainless API key via the STAINLESS_API_KEY environment variable, the --stainless-api-key flag, or the x-stainless-api-key HTTP header.', ); @@ -140,7 +132,7 @@ export const handler = async ({ return asTextContentResult(await searchLocal(body)); } - return asTextContentResult(await searchRemote(body, reqContext.stainlessApiKey)); + return asTextContentResult(await searchRemote(body, reqContext)); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index b8255445..414ae2ad 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -78,6 +78,11 @@ const newServer = async ({ }, stainlessApiKey: stainlessApiKey, upstreamClientEnvs, + mcpSessionId: (req as any).mcpSessionId, + mcpClientInfo: + typeof req.body?.params?.clientInfo?.name === 'string' ? + { name: req.body.params.clientInfo.name, version: String(req.body.params.clientInfo.version ?? '') } + : undefined, }); return server; @@ -135,6 +140,17 @@ export const streamableHTTPApp = ({ const app = express(); app.set('query parser', 'extended'); app.use(express.json()); + app.use((req: express.Request, res: express.Response, next: express.NextFunction) => { + const existing = req.headers['mcp-session-id']; + const sessionId = (Array.isArray(existing) ? existing[0] : existing) || crypto.randomUUID(); + (req as any).mcpSessionId = sessionId; + const origWriteHead = res.writeHead.bind(res); + res.writeHead = function (statusCode: number, ...rest: any[]) { + res.setHeader('mcp-session-id', sessionId); + return origWriteHead(statusCode, ...rest); + } as typeof res.writeHead; + next(); + }); app.use( pinoHttp({ logger: getLogger(), diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 88d29645..86e9e53c 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -5,6 +5,11 @@ import * as fs from 'node:fs/promises'; import * as path from 'node:path'; import { getLogger } from './logger'; +type PerLanguageData = { + method?: string; + example?: string; +}; + type MethodEntry = { name: string; endpoint: string; @@ -16,6 +21,7 @@ type MethodEntry = { params?: string[]; response?: string; markdown?: string; + perLanguage?: Record; }; type ProseChunk = { @@ -313,6 +319,8 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, ]; +const EMBEDDED_READMES: { language: string; content: string }[] = []; + const INDEX_OPTIONS = { fields: [ 'name', @@ -327,13 +335,15 @@ const INDEX_OPTIONS = { storeFields: ['kind', '_original'], searchOptions: { prefix: true, - fuzzy: 0.2, + fuzzy: 0.1, boost: { - name: 3, - endpoint: 2, + name: 5, + stainlessPath: 3, + endpoint: 3, + qualified: 3, summary: 2, - qualified: 2, content: 1, + description: 1, } as Record, }, }; @@ -355,14 +365,15 @@ export class LocalDocsSearch { static async create(opts?: { docsDir?: string }): Promise { const instance = new LocalDocsSearch(); instance.indexMethods(EMBEDDED_METHODS); + for (const readme of EMBEDDED_READMES) { + instance.indexProse(readme.content, `readme:${readme.language}`); + } if (opts?.docsDir) { await instance.loadDocsDirectory(opts.docsDir); } return instance; } - // Note: Language is accepted for interface consistency with remote search, but currently has no - // effect since this local search only supports TypeScript docs. search(props: { query: string; language?: string; @@ -370,15 +381,29 @@ export class LocalDocsSearch { maxResults?: number; maxLength?: number; }): SearchResult { - const { query, detail = 'default', maxResults = 5, maxLength = 100_000 } = props; + const { query, language = 'typescript', detail = 'default', maxResults = 5, maxLength = 100_000 } = props; const useMarkdown = detail === 'verbose' || detail === 'high'; - // Search both indices and merge results by score + // Search both indices and merge results by score. + // Filter prose hits so language-tagged content (READMEs and docs with + // frontmatter) only matches the requested language. const methodHits = this.methodIndex .search(query) .map((hit) => ({ ...hit, _kind: 'http_method' as const })); - const proseHits = this.proseIndex.search(query).map((hit) => ({ ...hit, _kind: 'prose' as const })); + const proseHits = this.proseIndex + .search(query) + .filter((hit) => { + const source = ((hit as Record)['_original'] as ProseChunk | undefined)?.source; + if (!source) return true; + // Check for language-tagged sources: "readme:" or "lang::" + let taggedLang: string | undefined; + if (source.startsWith('readme:')) taggedLang = source.slice('readme:'.length); + else if (source.startsWith('lang:')) taggedLang = source.split(':')[1]; + if (!taggedLang) return true; + return taggedLang === language || (language === 'javascript' && taggedLang === 'typescript'); + }) + .map((hit) => ({ ...hit, _kind: 'prose' as const })); const merged = [...methodHits, ...proseHits].sort((a, b) => b.score - a.score); const top = merged.slice(0, maxResults); @@ -391,11 +416,16 @@ export class LocalDocsSearch { if (useMarkdown && m.markdown) { fullResults.push(m.markdown); } else { + // Use per-language data when available, falling back to the + // top-level fields (which are TypeScript-specific in the + // legacy codepath). + const langData = m.perLanguage?.[language]; fullResults.push({ - method: m.qualified, + method: langData?.method ?? m.qualified, summary: m.summary, description: m.description, endpoint: `${m.httpMethod.toUpperCase()} ${m.endpoint}`, + ...(langData?.example ? { example: langData.example } : {}), ...(m.params ? { params: m.params } : {}), ...(m.response ? { response: m.response } : {}), }); @@ -466,7 +496,19 @@ export class LocalDocsSearch { this.indexProse(texts.join('\n\n'), file.name); } } else { - this.indexProse(content, file.name); + // Parse optional YAML frontmatter for language tagging. + // Files with a "language" field in frontmatter will only + // surface in searches for that language. + // + // Example: + // --- + // language: python + // --- + // # Error handling in Python + // ... + const frontmatter = parseFrontmatter(content); + const source = frontmatter.language ? `lang:${frontmatter.language}:${file.name}` : file.name; + this.indexProse(content, source); } } catch (err) { getLogger().warn({ err, file: file.name }, 'Failed to index docs file'); @@ -544,3 +586,12 @@ function extractTexts(data: unknown, depth = 0): string[] { } return []; } + +/** Parses YAML frontmatter from a markdown string, extracting the language field if present. */ +function parseFrontmatter(markdown: string): { language?: string } { + const match = markdown.match(/^---\n([\s\S]*?)\n---/); + if (!match) return {}; + const body = match[1] ?? ''; + const langMatch = body.match(/^language:\s*(.+)$/m); + return langMatch ? { language: langMatch[1]!.trim() } : {}; +} diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index b124d6f6..81931ad5 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -47,6 +47,8 @@ export async function initMcpServer(params: { mcpOptions?: McpOptions; stainlessApiKey?: string | undefined; upstreamClientEnvs?: Record | undefined; + mcpSessionId?: string | undefined; + mcpClientInfo?: { name: string; version: string } | undefined; }) { const server = params.server instanceof McpServer ? params.server.server : params.server; @@ -136,6 +138,8 @@ export async function initMcpServer(params: { client, stainlessApiKey: params.stainlessApiKey ?? params.mcpOptions?.stainlessApiKey, upstreamClientEnvs: params.upstreamClientEnvs, + mcpSessionId: params.mcpSessionId, + mcpClientInfo: params.mcpClientInfo, }, args, }); diff --git a/packages/mcp-server/src/types.ts b/packages/mcp-server/src/types.ts index 8f1a8486..28a7f5c2 100644 --- a/packages/mcp-server/src/types.ts +++ b/packages/mcp-server/src/types.ts @@ -46,6 +46,8 @@ export type McpRequestContext = { client: Beagle; stainlessApiKey?: string | undefined; upstreamClientEnvs?: Record | undefined; + mcpSessionId?: string | undefined; + mcpClientInfo?: { name: string; version: string } | undefined; }; export type HandlerFunction = ({ From e76d478464cad7d133de1759662af827074ccb5a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 09:26:44 +0000 Subject: [PATCH 109/138] chore(internal): codegen related update --- packages/mcp-server/src/local-docs-search.ts | 756 ++++++++++++++++--- 1 file changed, 669 insertions(+), 87 deletions(-) diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 86e9e53c..a1e068b2 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -50,20 +50,6 @@ type SearchResult = { }; const EMBEDDED_METHODS: MethodEntry[] = [ - { - name: 'retrieve', - endpoint: '/api/plans/{code}', - httpMethod: 'get', - summary: 'Get Plan', - description: 'retrieve a specific plans details by its code.', - stainlessPath: '(resource) plans > (method) retrieve', - qualified: 'client.plans.retrieve', - params: ['code: string;'], - response: - '{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }; success: true; }', - markdown: - "## retrieve\n\n`client.plans.retrieve(code: string): { data: plan; success: true; }`\n\n**get** `/api/plans/{code}`\n\nretrieve a specific plans details by its code.\n\n### Parameters\n\n- `code: string`\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plan = await client.plans.retrieve('code');\n\nconsole.log(plan);\n```", - }, { name: 'list', endpoint: '/api/plans', @@ -76,25 +62,81 @@ const EMBEDDED_METHODS: MethodEntry[] = [ '{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }[]; success: true; }', markdown: "## list\n\n`client.plans.list(): { data: plan[]; success: true; }`\n\n**get** `/api/plans`\n\nList all available insurance plans that tenants can be enrolled in.\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }[]; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }[]`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plans = await client.plans.list();\n\nconsole.log(plans);\n```", + perLanguage: { + go: { + method: 'client.Plans.List', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tplans, err := client.Plans.List(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", plans.Data)\n}\n', + }, + http: { + example: 'curl https://developer.beagleforpm.com/api/plans \\\n -H "x-api-key: $BEAGLE_API_KEY"', + }, + java: { + method: 'plans().list', + example: + 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n PlanListResponse plans = client.plans().list();\n }\n}', + }, + python: { + method: 'plans.list', + example: + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nplans = client.plans.list()\nprint(plans.data)', + }, + ruby: { + method: 'plans.list', + example: + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nplans = beagle.plans.list\n\nputs(plans)', + }, + typescript: { + method: 'client.plans.list', + example: + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst plans = await client.plans.list();\n\nconsole.log(plans.data);", + }, + }, }, { - name: 'create', - endpoint: '/api/property-managers', - httpMethod: 'post', - summary: 'Create Property Manager', - description: 'create a new property manager.', - stainlessPath: '(resource) property_managers > (method) create', - qualified: 'client.propertyManagers.create', - params: [ - 'addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[];', - 'contacts: { email: string; name: { first: string; last: string; }; phone?: string; }[];', - 'name: string;', - 'clickWrapAt?: number;', - ], + name: 'retrieve', + endpoint: '/api/plans/{code}', + httpMethod: 'get', + summary: 'Get Plan', + description: 'retrieve a specific plans details by its code.', + stainlessPath: '(resource) plans > (method) retrieve', + qualified: 'client.plans.retrieve', + params: ['code: string;'], response: - '{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }', + '{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }; success: true; }', markdown: - "## create\n\n`client.propertyManagers.create(addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[], contacts: { email: string; name: object; phone?: string; }[], name: string, clickWrapAt?: number): { data: property_manager; success: true; }`\n\n**post** `/api/property-managers`\n\ncreate a new property manager.\n\n### Parameters\n\n- `addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]`\n street addresses for each Property\n\n- `contacts: { email: string; name: { first: string; last: string; }; phone?: string; }[]`\n contact information for each Property Manager\n\n- `name: string`\n name of the Property Management Company\n\n- `clickWrapAt?: number`\n unix timestamp (ms) of clickwrap agreement signature\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.create({\n addresses: [{\n city: 'city',\n state: 'xx',\n street1: 'street1',\n zip: '60513',\n kind: 'billing',\n}],\n contacts: [{\n email: 'dev@stainless.com',\n name: { first: 'first', last: 'last' },\n kind: 'agreements',\n}],\n name: 'name',\n});\n\nconsole.log(propertyManager);\n```", + "## retrieve\n\n`client.plans.retrieve(code: string): { data: plan; success: true; }`\n\n**get** `/api/plans/{code}`\n\nretrieve a specific plans details by its code.\n\n### Parameters\n\n- `code: string`\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plan = await client.plans.retrieve('code');\n\nconsole.log(plan);\n```", + perLanguage: { + go: { + method: 'client.Plans.Get', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tplan, err := client.Plans.Get(context.TODO(), "code")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", plan.Data)\n}\n', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/plans/$CODE \\\n -H "x-api-key: $BEAGLE_API_KEY"', + }, + java: { + method: 'plans().retrieve', + example: + 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanRetrieveParams;\nimport com.beagle.api.models.plans.PlanRetrieveResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n PlanRetrieveResponse plan = client.plans().retrieve("code");\n }\n}', + }, + python: { + method: 'plans.retrieve', + example: + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nplan = client.plans.retrieve(\n "code",\n)\nprint(plan.data)', + }, + ruby: { + method: 'plans.retrieve', + example: + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nplan = beagle.plans.retrieve("code")\n\nputs(plan)', + }, + typescript: { + method: 'client.plans.retrieve', + example: + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst plan = await client.plans.retrieve('code');\n\nconsole.log(plan.data);", + }, + }, }, { name: 'retrieve', @@ -109,6 +151,37 @@ const EMBEDDED_METHODS: MethodEntry[] = [ '{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }', markdown: "## retrieve\n\n`client.propertyManagers.retrieve(id: number): { data: property_manager; success: true; }`\n\n**get** `/api/property-managers/{id}`\n\nget a property manager by id.\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.retrieve(123);\n\nconsole.log(propertyManager);\n```", + perLanguage: { + go: { + method: 'client.PropertyManagers.Get', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tpropertyManager, err := client.PropertyManagers.Get(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", propertyManager.Data)\n}\n', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/property-managers/$ID \\\n -H "x-api-key: $BEAGLE_API_KEY"', + }, + java: { + method: 'propertyManagers().retrieve', + example: + 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.propertymanagers.PropertyManagerRetrieveParams;\nimport com.beagle.api.models.propertymanagers.PropertyManagerRetrieveResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n PropertyManagerRetrieveResponse propertyManager = client.propertyManagers().retrieve(123.0);\n }\n}', + }, + python: { + method: 'property_managers.retrieve', + example: + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nproperty_manager = client.property_managers.retrieve(\n 123,\n)\nprint(property_manager.data)', + }, + ruby: { + method: 'property_managers.retrieve', + example: + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nproperty_manager = beagle.property_managers.retrieve(123)\n\nputs(property_manager)', + }, + typescript: { + method: 'client.propertyManagers.retrieve', + example: + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst propertyManager = await client.propertyManagers.retrieve(123);\n\nconsole.log(propertyManager.data);", + }, + }, }, { name: 'update', @@ -130,6 +203,80 @@ const EMBEDDED_METHODS: MethodEntry[] = [ '{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }', markdown: "## update\n\n`client.propertyManagers.update(id: number, addresses?: { city: string; state: string; street1: string; zip: string; street2?: string; }[], clickWrapAt?: number, contacts?: { email: string; name: object; phone?: string; }[], name?: string): { data: property_manager; success: true; }`\n\n**patch** `/api/property-managers/{id}`\n\nupdate an existing property manager by ID\n\n(Note that when updating **contacts** or **addresses** you need to send the whole array you want to replace them with)\n\n### Parameters\n\n- `id: number`\n\n- `addresses?: { city: string; state: string; street1: string; zip: string; street2?: string; }[]`\n street addresses for each Property\n\n- `clickWrapAt?: number`\n unix timestamp (ms) of clickwrap agreement signature\n\n- `contacts?: { email: string; name: { first: string; last: string; }; phone?: string; }[]`\n contact information for each Property Manager\n\n- `name?: string`\n name of the Property Management Company\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.update(123);\n\nconsole.log(propertyManager);\n```", + perLanguage: { + go: { + method: 'client.PropertyManagers.Update', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tpropertyManager, err := client.PropertyManagers.Update(\n\t\tcontext.TODO(),\n\t\t123,\n\t\tbeagle.PropertyManagerUpdateParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", propertyManager.Data)\n}\n', + }, + http: { + example: + "curl https://developer.beagleforpm.com/api/property-managers/$ID \\\n -X PATCH \\\n -H 'Content-Type: application/json' \\\n -H \"x-api-key: $BEAGLE_API_KEY\" \\\n -d '{}'", + }, + java: { + method: 'propertyManagers().update', + example: + 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.propertymanagers.PropertyManagerUpdateParams;\nimport com.beagle.api.models.propertymanagers.PropertyManagerUpdateResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n PropertyManagerUpdateResponse propertyManager = client.propertyManagers().update(123.0);\n }\n}', + }, + python: { + method: 'property_managers.update', + example: + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nproperty_manager = client.property_managers.update(\n id=123,\n)\nprint(property_manager.data)', + }, + ruby: { + method: 'property_managers.update', + example: + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nproperty_manager = beagle.property_managers.update(123)\n\nputs(property_manager)', + }, + typescript: { + method: 'client.propertyManagers.update', + example: + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst propertyManager = await client.propertyManagers.update(123);\n\nconsole.log(propertyManager.data);", + }, + }, + }, + { + name: 'delete', + endpoint: '/api/property-managers/{id}', + httpMethod: 'delete', + summary: 'Delete Property Manager', + description: 'delete a property manager by ID.', + stainlessPath: '(resource) property_managers > (method) delete', + qualified: 'client.propertyManagers.delete', + params: ['id: number;'], + markdown: + "## delete\n\n`client.propertyManagers.delete(id: number): void`\n\n**delete** `/api/property-managers/{id}`\n\ndelete a property manager by ID.\n\n### Parameters\n\n- `id: number`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nawait client.propertyManagers.delete(123)\n```", + perLanguage: { + go: { + method: 'client.PropertyManagers.Delete', + example: + 'package main\n\nimport (\n\t"context"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\terr := client.PropertyManagers.Delete(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/property-managers/$ID \\\n -X DELETE \\\n -H "x-api-key: $BEAGLE_API_KEY"', + }, + java: { + method: 'propertyManagers().delete', + example: + 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.propertymanagers.PropertyManagerDeleteParams;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n client.propertyManagers().delete(123.0);\n }\n}', + }, + python: { + method: 'property_managers.delete', + example: + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nclient.property_managers.delete(\n 123,\n)', + }, + ruby: { + method: 'property_managers.delete', + example: + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nresult = beagle.property_managers.delete(123)\n\nputs(result)', + }, + typescript: { + method: 'client.propertyManagers.delete', + example: + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nawait client.propertyManagers.delete(123);", + }, + }, }, { name: 'list', @@ -143,35 +290,87 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: '{ data: { items: object[]; pagination: object; }; success: true; }', markdown: "## list\n\n`client.propertyManagers.list(page?: number, size?: number): { data: object; success: true; }`\n\n**get** `/api/property-managers`\n\nlist all property managers, note this endpoint is paginated.\n\n### Parameters\n\n- `page?: number`\n Page number to fetch.\n\n- `size?: number`\n Number of items per page.\n\n### Returns\n\n- `{ data: { items: object[]; pagination: object; }; success: true; }`\n\n - `data: { items: { id: number; addresses: object[]; contacts: object[]; name: string; clickWrapAt?: number; }[]; pagination: { page: number; pages: number; records: number; size: number; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManagers = await client.propertyManagers.list();\n\nconsole.log(propertyManagers);\n```", - }, - { - name: 'delete', - endpoint: '/api/property-managers/{id}', - httpMethod: 'delete', - summary: 'Delete Property Manager', - description: 'delete a property manager by ID.', - stainlessPath: '(resource) property_managers > (method) delete', - qualified: 'client.propertyManagers.delete', - params: ['id: number;'], - markdown: - "## delete\n\n`client.propertyManagers.delete(id: number): void`\n\n**delete** `/api/property-managers/{id}`\n\ndelete a property manager by ID.\n\n### Parameters\n\n- `id: number`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nawait client.propertyManagers.delete(123)\n```", + perLanguage: { + go: { + method: 'client.PropertyManagers.List', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tpropertyManagers, err := client.PropertyManagers.List(context.TODO(), beagle.PropertyManagerListParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", propertyManagers.Data)\n}\n', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/property-managers \\\n -H "x-api-key: $BEAGLE_API_KEY"', + }, + java: { + method: 'propertyManagers().list', + example: + 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.propertymanagers.PropertyManagerListParams;\nimport com.beagle.api.models.propertymanagers.PropertyManagerListResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n PropertyManagerListResponse propertyManagers = client.propertyManagers().list();\n }\n}', + }, + python: { + method: 'property_managers.list', + example: + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nproperty_managers = client.property_managers.list()\nprint(property_managers.data)', + }, + ruby: { + method: 'property_managers.list', + example: + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nproperty_managers = beagle.property_managers.list\n\nputs(property_managers)', + }, + typescript: { + method: 'client.propertyManagers.list', + example: + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst propertyManagers = await client.propertyManagers.list();\n\nconsole.log(propertyManagers.data);", + }, + }, }, { name: 'create', - endpoint: '/api/tenants', + endpoint: '/api/property-managers', httpMethod: 'post', - summary: 'Create Tenant', - description: 'create a new tenant.', - stainlessPath: '(resource) tenants > (method) create', - qualified: 'client.tenants.create', + summary: 'Create Property Manager', + description: 'create a new property manager.', + stainlessPath: '(resource) property_managers > (method) create', + qualified: 'client.propertyManagers.create', params: [ - 'address: { city: string; state: string; street1: string; zip: string; street2?: string; };', - 'contact: { email: string; name: { first: string; last: string; }; phone?: string; };', - 'propertyManagerId: number;', + 'addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[];', + 'contacts: { email: string; name: { first: string; last: string; }; phone?: string; }[];', + 'name: string;', + 'clickWrapAt?: number;', ], - response: '{ data: { id: number; address: address; contact: contact; }; success: true; }', + response: + '{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }', markdown: - "## create\n\n`client.tenants.create(address: { city: string; state: string; street1: string; zip: string; street2?: string; }, contact: { email: string; name: object; phone?: string; }, propertyManagerId: number): { data: tenant; success: true; }`\n\n**post** `/api/tenants`\n\ncreate a new tenant.\n\n### Parameters\n\n- `address: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `city: string`\n - `state: string`\n two letter state code, ie CA\n - `street1: string`\n - `zip: string`\n 5 digit US zip code, ie 94104\n - `street2?: string`\n\n- `contact: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `email: string`\n - `name: { first: string; last: string; }`\n - `phone?: string`\n\n- `propertyManagerId: number`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.create({\n address: {\n city: 'city',\n state: 'xx',\n street1: 'street1',\n zip: '60513',\n},\n contact: {\n email: 'dev@stainless.com',\n name: { first: 'first', last: 'last' },\n},\n propertyManagerId: 0,\n});\n\nconsole.log(tenant);\n```", + "## create\n\n`client.propertyManagers.create(addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[], contacts: { email: string; name: object; phone?: string; }[], name: string, clickWrapAt?: number): { data: property_manager; success: true; }`\n\n**post** `/api/property-managers`\n\ncreate a new property manager.\n\n### Parameters\n\n- `addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]`\n street addresses for each Property\n\n- `contacts: { email: string; name: { first: string; last: string; }; phone?: string; }[]`\n contact information for each Property Manager\n\n- `name: string`\n name of the Property Management Company\n\n- `clickWrapAt?: number`\n unix timestamp (ms) of clickwrap agreement signature\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.create({\n addresses: [{\n city: 'city',\n state: 'xx',\n street1: 'street1',\n zip: '60513',\n kind: 'billing',\n}],\n contacts: [{\n email: 'dev@stainless.com',\n name: { first: 'first', last: 'last' },\n kind: 'agreements',\n}],\n name: 'name',\n});\n\nconsole.log(propertyManager);\n```", + perLanguage: { + go: { + method: 'client.PropertyManagers.New', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tpropertyManager, err := client.PropertyManagers.New(context.TODO(), beagle.PropertyManagerNewParams{\n\t\tAddresses: []beagle.PropertyManagerNewParamsAddress{{\n\t\t\tAddressParam: beagle.AddressParam{\n\t\t\t\tCity: "city",\n\t\t\t\tState: "xx",\n\t\t\t\tStreet1: "street1",\n\t\t\t\tZip: "60513",\n\t\t\t},\n\t\t\tKind: "billing",\n\t\t}},\n\t\tContacts: []beagle.PropertyManagerNewParamsContact{{\n\t\t\tContactParam: beagle.ContactParam{\n\t\t\t\tEmail: "dev@stainless.com",\n\t\t\t\tName: beagle.ContactNameParam{\n\t\t\t\t\tFirst: "first",\n\t\t\t\t\tLast: "last",\n\t\t\t\t},\n\t\t\t},\n\t\t\tKind: "agreements",\n\t\t}},\n\t\tName: "name",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", propertyManager.Data)\n}\n', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/property-managers \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "addresses": [\n {\n "city": "city",\n "state": "xx",\n "street1": "street1",\n "zip": "60513",\n "kind": "billing"\n }\n ],\n "contacts": [\n {\n "email": "dev@stainless.com",\n "name": {\n "first": "first",\n "last": "last"\n },\n "kind": "agreements"\n }\n ],\n "name": "name"\n }\'', + }, + java: { + method: 'propertyManagers().create', + example: + 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.propertymanagers.PropertyManagerCreateParams;\nimport com.beagle.api.models.propertymanagers.PropertyManagerCreateResponse;\nimport com.beagle.api.models.tenants.Contact;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n PropertyManagerCreateParams params = PropertyManagerCreateParams.builder()\n .addAddress(PropertyManagerCreateParams.Address.builder()\n .city("South Salt Lake")\n .state("UT")\n .street1("123 Electric Ave.")\n .zip("84115")\n .kind(PropertyManagerCreateParams.Address.Kind.PLACE_OF_BUSINESS)\n .build())\n .addContact(PropertyManagerCreateParams.Contact.builder()\n .email("mr.milchick@example.com")\n .name(Contact.Name.builder()\n .first("Seth")\n .last("Milchick")\n .build())\n .kind(PropertyManagerCreateParams.Contact.Kind.REPORTING)\n .build())\n .name("Lumon Apartments")\n .build();\n PropertyManagerCreateResponse propertyManager = client.propertyManagers().create(params);\n }\n}', + }, + python: { + method: 'property_managers.create', + example: + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nproperty_manager = client.property_managers.create(\n addresses=[{\n "city": "city",\n "state": "xx",\n "street1": "street1",\n "zip": "60513",\n "kind": "billing",\n }],\n contacts=[{\n "email": "dev@stainless.com",\n "name": {\n "first": "first",\n "last": "last",\n },\n "kind": "agreements",\n }],\n name="name",\n)\nprint(property_manager.data)', + }, + ruby: { + method: 'property_managers.create', + example: + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nproperty_manager = beagle.property_managers.create(\n addresses: [{city: "city", state: "xx", street1: "street1", zip: "60513", kind: :billing}],\n contacts: [{email: "dev@stainless.com", name: {first: "first", last: "last"}, kind: :agreements}],\n name: "name"\n)\n\nputs(property_manager)', + }, + typescript: { + method: 'client.propertyManagers.create', + example: + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst propertyManager = await client.propertyManagers.create({\n addresses: [\n {\n city: 'city',\n state: 'xx',\n street1: 'street1',\n zip: '60513',\n kind: 'billing',\n },\n ],\n contacts: [\n {\n email: 'dev@stainless.com',\n name: { first: 'first', last: 'last' },\n kind: 'agreements',\n },\n ],\n name: 'name',\n});\n\nconsole.log(propertyManager.data);", + }, + }, }, { name: 'retrieve', @@ -185,6 +384,37 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: '{ data: { id: number; address: address; contact: contact; }; success: true; }', markdown: "## retrieve\n\n`client.tenants.retrieve(id: number): { data: tenant; success: true; }`\n\n**get** `/api/tenants/{id}`\n\nretrieve a single tenant by their id.\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.retrieve(123);\n\nconsole.log(tenant);\n```", + perLanguage: { + go: { + method: 'client.Tenants.Get', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\ttenant, err := client.Tenants.Get(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", tenant.Data)\n}\n', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/tenants/$ID \\\n -H "x-api-key: $BEAGLE_API_KEY"', + }, + java: { + method: 'tenants().retrieve', + example: + 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.tenants.TenantRetrieveParams;\nimport com.beagle.api.models.tenants.TenantRetrieveResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n TenantRetrieveResponse tenant = client.tenants().retrieve(123.0);\n }\n}', + }, + python: { + method: 'tenants.retrieve', + example: + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\ntenant = client.tenants.retrieve(\n 123,\n)\nprint(tenant.data)', + }, + ruby: { + method: 'tenants.retrieve', + example: + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\ntenant = beagle.tenants.retrieve(123)\n\nputs(tenant)', + }, + typescript: { + method: 'client.tenants.retrieve', + example: + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst tenant = await client.tenants.retrieve(123);\n\nconsole.log(tenant.data);", + }, + }, }, { name: 'update', @@ -202,6 +432,80 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: '{ data: { id: number; address: address; contact: contact; }; success: true; }', markdown: "## update\n\n`client.tenants.update(id: number, address?: { city: string; state: string; street1: string; zip: string; street2?: string; }, contact?: { email: string; name: object; phone?: string; }): { data: tenant; success: true; }`\n\n**patch** `/api/tenants/{id}`\n\nupdate an existing tenant by their id.\n\n### Parameters\n\n- `id: number`\n\n- `address?: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `city: string`\n - `state: string`\n two letter state code, ie CA\n - `street1: string`\n - `zip: string`\n 5 digit US zip code, ie 94104\n - `street2?: string`\n\n- `contact?: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `email: string`\n - `name: { first: string; last: string; }`\n - `phone?: string`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.update(123);\n\nconsole.log(tenant);\n```", + perLanguage: { + go: { + method: 'client.Tenants.Update', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\ttenant, err := client.Tenants.Update(\n\t\tcontext.TODO(),\n\t\t123,\n\t\tbeagle.TenantUpdateParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", tenant.Data)\n}\n', + }, + http: { + example: + "curl https://developer.beagleforpm.com/api/tenants/$ID \\\n -X PATCH \\\n -H 'Content-Type: application/json' \\\n -H \"x-api-key: $BEAGLE_API_KEY\" \\\n -d '{}'", + }, + java: { + method: 'tenants().update', + example: + 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.tenants.TenantUpdateParams;\nimport com.beagle.api.models.tenants.TenantUpdateResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n TenantUpdateResponse tenant = client.tenants().update(123.0);\n }\n}', + }, + python: { + method: 'tenants.update', + example: + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\ntenant = client.tenants.update(\n id=123,\n)\nprint(tenant.data)', + }, + ruby: { + method: 'tenants.update', + example: + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\ntenant = beagle.tenants.update(123)\n\nputs(tenant)', + }, + typescript: { + method: 'client.tenants.update', + example: + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst tenant = await client.tenants.update(123);\n\nconsole.log(tenant.data);", + }, + }, + }, + { + name: 'delete', + endpoint: '/api/tenants/{id}', + httpMethod: 'delete', + summary: 'Delete Tenant', + description: 'delete an existing tenant by their id.', + stainlessPath: '(resource) tenants > (method) delete', + qualified: 'client.tenants.delete', + params: ['id: number;'], + markdown: + "## delete\n\n`client.tenants.delete(id: number): void`\n\n**delete** `/api/tenants/{id}`\n\ndelete an existing tenant by their id.\n\n### Parameters\n\n- `id: number`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nawait client.tenants.delete(123)\n```", + perLanguage: { + go: { + method: 'client.Tenants.Delete', + example: + 'package main\n\nimport (\n\t"context"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\terr := client.Tenants.Delete(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/tenants/$ID \\\n -X DELETE \\\n -H "x-api-key: $BEAGLE_API_KEY"', + }, + java: { + method: 'tenants().delete', + example: + 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.tenants.TenantDeleteParams;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n client.tenants().delete(123.0);\n }\n}', + }, + python: { + method: 'tenants.delete', + example: + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nclient.tenants.delete(\n 123,\n)', + }, + ruby: { + method: 'tenants.delete', + example: + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nresult = beagle.tenants.delete(123)\n\nputs(result)', + }, + typescript: { + method: 'client.tenants.delete', + example: + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nawait client.tenants.delete(123);", + }, + }, }, { name: 'list', @@ -216,39 +520,84 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: '{ data: { items: object[]; pagination: object; }; success: true; }', markdown: "## list\n\n`client.tenants.list(page?: number, propertyManagerId?: number, size?: number): { data: object; success: true; }`\n\n**get** `/api/tenants`\n\nlist all tenants, this endpoint is paginated and allows for queries by individual property manager.\n\n### Parameters\n\n- `page?: number`\n Page number to fetch.\n\n- `propertyManagerId?: number`\n\n- `size?: number`\n Number of items per page.\n\n### Returns\n\n- `{ data: { items: object[]; pagination: object; }; success: true; }`\n\n - `data: { items: { id: number; address: object; contact: object; }[]; pagination: { page: number; pages: number; records: number; size: number; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenants = await client.tenants.list();\n\nconsole.log(tenants);\n```", - }, - { - name: 'delete', - endpoint: '/api/tenants/{id}', - httpMethod: 'delete', - summary: 'Delete Tenant', - description: 'delete an existing tenant by their id.', - stainlessPath: '(resource) tenants > (method) delete', - qualified: 'client.tenants.delete', - params: ['id: number;'], - markdown: - "## delete\n\n`client.tenants.delete(id: number): void`\n\n**delete** `/api/tenants/{id}`\n\ndelete an existing tenant by their id.\n\n### Parameters\n\n- `id: number`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nawait client.tenants.delete(123)\n```", + perLanguage: { + go: { + method: 'client.Tenants.List', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\ttenants, err := client.Tenants.List(context.TODO(), beagle.TenantListParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", tenants.Data)\n}\n', + }, + http: { + example: 'curl https://developer.beagleforpm.com/api/tenants \\\n -H "x-api-key: $BEAGLE_API_KEY"', + }, + java: { + method: 'tenants().list', + example: + 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.tenants.TenantListParams;\nimport com.beagle.api.models.tenants.TenantListResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n TenantListResponse tenants = client.tenants().list();\n }\n}', + }, + python: { + method: 'tenants.list', + example: + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\ntenants = client.tenants.list()\nprint(tenants.data)', + }, + ruby: { + method: 'tenants.list', + example: + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\ntenants = beagle.tenants.list\n\nputs(tenants)', + }, + typescript: { + method: 'client.tenants.list', + example: + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst tenants = await client.tenants.list();\n\nconsole.log(tenants.data);", + }, + }, }, { name: 'create', - endpoint: '/api/enrollments', + endpoint: '/api/tenants', httpMethod: 'post', - summary: 'Create Enrollment', - description: 'create a new enrollment for a tenant.', - stainlessPath: '(resource) enrollments > (method) create', - qualified: 'client.enrollments.create', + summary: 'Create Tenant', + description: 'create a new tenant.', + stainlessPath: '(resource) tenants > (method) create', + qualified: 'client.tenants.create', params: [ - 'effectiveDate: string;', - 'plan: string;', + 'address: { city: string; state: string; street1: string; zip: string; street2?: string; };', + 'contact: { email: string; name: { first: string; last: string; }; phone?: string; };', 'propertyManagerId: number;', - 'status: string;', - 'tenantId: number;', - 'note?: string;', ], - response: - '{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }', + response: '{ data: { id: number; address: address; contact: contact; }; success: true; }', markdown: - "## create\n\n`client.enrollments.create(effectiveDate: string, plan: string, propertyManagerId: number, status: string, tenantId: number, note?: string): { data: enrollment; success: true; }`\n\n**post** `/api/enrollments`\n\ncreate a new enrollment for a tenant.\n\n### Parameters\n\n- `effectiveDate: string`\n the date the enrollment will begin, note enrollments cannot begin in the past\n\n- `plan: string`\n the plan name/code\n\n- `propertyManagerId: number`\n\n- `status: string`\n\n- `tenantId: number`\n\n- `note?: string`\n an optional note field, this can be used for easily appending metadata to enrollments\n\n### Returns\n\n- `{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }`\n\n - `data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollment = await client.enrollments.create({\n effectiveDate: 'effectiveDate',\n plan: 'plan',\n propertyManagerId: 0,\n status: 'Premium Paying',\n tenantId: 0,\n});\n\nconsole.log(enrollment);\n```", + "## create\n\n`client.tenants.create(address: { city: string; state: string; street1: string; zip: string; street2?: string; }, contact: { email: string; name: object; phone?: string; }, propertyManagerId: number): { data: tenant; success: true; }`\n\n**post** `/api/tenants`\n\ncreate a new tenant.\n\n### Parameters\n\n- `address: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `city: string`\n - `state: string`\n two letter state code, ie CA\n - `street1: string`\n - `zip: string`\n 5 digit US zip code, ie 94104\n - `street2?: string`\n\n- `contact: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `email: string`\n - `name: { first: string; last: string; }`\n - `phone?: string`\n\n- `propertyManagerId: number`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.create({\n address: {\n city: 'city',\n state: 'xx',\n street1: 'street1',\n zip: '60513',\n},\n contact: {\n email: 'dev@stainless.com',\n name: { first: 'first', last: 'last' },\n},\n propertyManagerId: 0,\n});\n\nconsole.log(tenant);\n```", + perLanguage: { + go: { + method: 'client.Tenants.New', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\ttenant, err := client.Tenants.New(context.TODO(), beagle.TenantNewParams{\n\t\tAddress: beagle.AddressParam{\n\t\t\tCity: "city",\n\t\t\tState: "xx",\n\t\t\tStreet1: "street1",\n\t\t\tZip: "60513",\n\t\t},\n\t\tContact: beagle.ContactParam{\n\t\t\tEmail: "dev@stainless.com",\n\t\t\tName: beagle.ContactNameParam{\n\t\t\t\tFirst: "first",\n\t\t\t\tLast: "last",\n\t\t\t},\n\t\t},\n\t\tPropertyManagerID: 0,\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", tenant.Data)\n}\n', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/tenants \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "address": {\n "city": "city",\n "state": "xx",\n "street1": "street1",\n "zip": "60513"\n },\n "contact": {\n "email": "dev@stainless.com",\n "name": {\n "first": "first",\n "last": "last"\n }\n },\n "propertyManagerId": 0\n }\'', + }, + java: { + method: 'tenants().create', + example: + 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.tenants.Address;\nimport com.beagle.api.models.tenants.Contact;\nimport com.beagle.api.models.tenants.TenantCreateParams;\nimport com.beagle.api.models.tenants.TenantCreateResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n TenantCreateParams params = TenantCreateParams.builder()\n .address(Address.builder()\n .city("South Salt Lake")\n .state("UT")\n .street1("123 Main St.")\n .zip("84115")\n .build())\n .contact(Contact.builder()\n .email("mark.s@example.com")\n .name(Contact.Name.builder()\n .first("Mark")\n .last("Scout")\n .build())\n .build())\n .propertyManagerId(123.0)\n .build();\n TenantCreateResponse tenant = client.tenants().create(params);\n }\n}', + }, + python: { + method: 'tenants.create', + example: + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\ntenant = client.tenants.create(\n address={\n "city": "city",\n "state": "xx",\n "street1": "street1",\n "zip": "60513",\n },\n contact={\n "email": "dev@stainless.com",\n "name": {\n "first": "first",\n "last": "last",\n },\n },\n property_manager_id=0,\n)\nprint(tenant.data)', + }, + ruby: { + method: 'tenants.create', + example: + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\ntenant = beagle.tenants.create(\n address: {city: "city", state: "xx", street1: "street1", zip: "60513"},\n contact: {email: "dev@stainless.com", name: {first: "first", last: "last"}},\n property_manager_id: 0\n)\n\nputs(tenant)', + }, + typescript: { + method: 'client.tenants.create', + example: + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst tenant = await client.tenants.create({\n address: {\n city: 'city',\n state: 'xx',\n street1: 'street1',\n zip: '60513',\n },\n contact: {\n email: 'dev@stainless.com',\n name: { first: 'first', last: 'last' },\n },\n propertyManagerId: 0,\n});\n\nconsole.log(tenant.data);", + }, + }, }, { name: 'retrieve', @@ -263,6 +612,81 @@ const EMBEDDED_METHODS: MethodEntry[] = [ '{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }', markdown: "## retrieve\n\n`client.enrollments.retrieve(id: number): { data: enrollment; success: true; }`\n\n**get** `/api/enrollments/{id}`\n\nget a specific enrollment by its id.\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }`\n\n - `data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollment = await client.enrollments.retrieve(123);\n\nconsole.log(enrollment);\n```", + perLanguage: { + go: { + method: 'client.Enrollments.Get', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tenrollment, err := client.Enrollments.Get(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", enrollment.Data)\n}\n', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/enrollments/$ID \\\n -H "x-api-key: $BEAGLE_API_KEY"', + }, + java: { + method: 'enrollments().retrieve', + example: + 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.enrollments.EnrollmentRetrieveParams;\nimport com.beagle.api.models.enrollments.EnrollmentRetrieveResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n EnrollmentRetrieveResponse enrollment = client.enrollments().retrieve(123.0);\n }\n}', + }, + python: { + method: 'enrollments.retrieve', + example: + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nenrollment = client.enrollments.retrieve(\n 123,\n)\nprint(enrollment.data)', + }, + ruby: { + method: 'enrollments.retrieve', + example: + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nenrollment = beagle.enrollments.retrieve(123)\n\nputs(enrollment)', + }, + typescript: { + method: 'client.enrollments.retrieve', + example: + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst enrollment = await client.enrollments.retrieve(123);\n\nconsole.log(enrollment.data);", + }, + }, + }, + { + name: 'lapse', + endpoint: '/api/enrollments/{id}', + httpMethod: 'delete', + summary: 'Lapse Enrollment', + description: + 'lapses a specific enrollment for a tenant, note that if a tenant has multiple enrollments (e.g., SDR and TLL), each must be lapsed individually', + stainlessPath: '(resource) enrollments > (method) lapse', + qualified: 'client.enrollments.lapse', + params: ['id: number;'], + markdown: + "## lapse\n\n`client.enrollments.lapse(id: number): void`\n\n**delete** `/api/enrollments/{id}`\n\nlapses a specific enrollment for a tenant, note that if a tenant has multiple enrollments (e.g., SDR and TLL), each must be lapsed individually\n\n### Parameters\n\n- `id: number`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nawait client.enrollments.lapse(123)\n```", + perLanguage: { + go: { + method: 'client.Enrollments.Lapse', + example: + 'package main\n\nimport (\n\t"context"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\terr := client.Enrollments.Lapse(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/enrollments/$ID \\\n -X DELETE \\\n -H "x-api-key: $BEAGLE_API_KEY"', + }, + java: { + method: 'enrollments().lapse', + example: + 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.enrollments.EnrollmentLapseParams;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n client.enrollments().lapse(123.0);\n }\n}', + }, + python: { + method: 'enrollments.lapse', + example: + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nclient.enrollments.lapse(\n 123,\n)', + }, + ruby: { + method: 'enrollments.lapse', + example: + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nresult = beagle.enrollments.lapse(123)\n\nputs(result)', + }, + typescript: { + method: 'client.enrollments.lapse', + example: + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nawait client.enrollments.lapse(123);", + }, + }, }, { name: 'list', @@ -277,19 +701,89 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: '{ data: { items: object[]; pagination: object; }; success: true; }', markdown: "## list\n\n`client.enrollments.list(page?: number, propertyManagerId?: number, size?: number): { data: object; success: true; }`\n\n**get** `/api/enrollments`\n\nlist all enrollments, this endpoint is paginated and allows for queries by individual property manager.\n\n### Parameters\n\n- `page?: number`\n Page number to fetch.\n\n- `propertyManagerId?: number`\n\n- `size?: number`\n Number of items per page.\n\n### Returns\n\n- `{ data: { items: object[]; pagination: object; }; success: true; }`\n\n - `data: { items: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }[]; pagination: { page: number; pages: number; records: number; size: number; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollments = await client.enrollments.list();\n\nconsole.log(enrollments);\n```", + perLanguage: { + go: { + method: 'client.Enrollments.List', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tenrollments, err := client.Enrollments.List(context.TODO(), beagle.EnrollmentListParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", enrollments.Data)\n}\n', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/enrollments \\\n -H "x-api-key: $BEAGLE_API_KEY"', + }, + java: { + method: 'enrollments().list', + example: + 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.enrollments.EnrollmentListParams;\nimport com.beagle.api.models.enrollments.EnrollmentListResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n EnrollmentListResponse enrollments = client.enrollments().list();\n }\n}', + }, + python: { + method: 'enrollments.list', + example: + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nenrollments = client.enrollments.list()\nprint(enrollments.data)', + }, + ruby: { + method: 'enrollments.list', + example: + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nenrollments = beagle.enrollments.list\n\nputs(enrollments)', + }, + typescript: { + method: 'client.enrollments.list', + example: + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst enrollments = await client.enrollments.list();\n\nconsole.log(enrollments.data);", + }, + }, }, { - name: 'lapse', - endpoint: '/api/enrollments/{id}', - httpMethod: 'delete', - summary: 'Lapse Enrollment', - description: - 'lapses a specific enrollment for a tenant, note that if a tenant has multiple enrollments (e.g., SDR and TLL), each must be lapsed individually', - stainlessPath: '(resource) enrollments > (method) lapse', - qualified: 'client.enrollments.lapse', - params: ['id: number;'], + name: 'create', + endpoint: '/api/enrollments', + httpMethod: 'post', + summary: 'Create Enrollment', + description: 'create a new enrollment for a tenant.', + stainlessPath: '(resource) enrollments > (method) create', + qualified: 'client.enrollments.create', + params: [ + 'effectiveDate: string;', + 'plan: string;', + 'propertyManagerId: number;', + 'status: string;', + 'tenantId: number;', + 'note?: string;', + ], + response: + '{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }', markdown: - "## lapse\n\n`client.enrollments.lapse(id: number): void`\n\n**delete** `/api/enrollments/{id}`\n\nlapses a specific enrollment for a tenant, note that if a tenant has multiple enrollments (e.g., SDR and TLL), each must be lapsed individually\n\n### Parameters\n\n- `id: number`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nawait client.enrollments.lapse(123)\n```", + "## create\n\n`client.enrollments.create(effectiveDate: string, plan: string, propertyManagerId: number, status: string, tenantId: number, note?: string): { data: enrollment; success: true; }`\n\n**post** `/api/enrollments`\n\ncreate a new enrollment for a tenant.\n\n### Parameters\n\n- `effectiveDate: string`\n the date the enrollment will begin, note enrollments cannot begin in the past\n\n- `plan: string`\n the plan name/code\n\n- `propertyManagerId: number`\n\n- `status: string`\n\n- `tenantId: number`\n\n- `note?: string`\n an optional note field, this can be used for easily appending metadata to enrollments\n\n### Returns\n\n- `{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }`\n\n - `data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollment = await client.enrollments.create({\n effectiveDate: 'effectiveDate',\n plan: 'plan',\n propertyManagerId: 0,\n status: 'Premium Paying',\n tenantId: 0,\n});\n\nconsole.log(enrollment);\n```", + perLanguage: { + go: { + method: 'client.Enrollments.New', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tenrollment, err := client.Enrollments.New(context.TODO(), beagle.EnrollmentNewParams{\n\t\tEffectiveDate: "effectiveDate",\n\t\tPlan: "plan",\n\t\tPropertyManagerID: 0,\n\t\tStatus: beagle.EnrollmentNewParamsStatusPremiumPaying,\n\t\tTenantID: 0,\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", enrollment.Data)\n}\n', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/enrollments \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "effectiveDate": "effectiveDate",\n "plan": "plan",\n "propertyManagerId": 0,\n "status": "Premium Paying",\n "tenantId": 0\n }\'', + }, + java: { + method: 'enrollments().create', + example: + 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.enrollments.EnrollmentCreateParams;\nimport com.beagle.api.models.enrollments.EnrollmentCreateResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n EnrollmentCreateParams params = EnrollmentCreateParams.builder()\n .effectiveDate("2025-11-10T19:50:20.638Z")\n .plan("TLL_100K_CONTENTS_5K_ACV")\n .propertyManagerId(123.0)\n .status(EnrollmentCreateParams.Status.ISSUED_NOT_PAID)\n .tenantId(123.0)\n .build();\n EnrollmentCreateResponse enrollment = client.enrollments().create(params);\n }\n}', + }, + python: { + method: 'enrollments.create', + example: + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nenrollment = client.enrollments.create(\n effective_date="effectiveDate",\n plan="plan",\n property_manager_id=0,\n status="Premium Paying",\n tenant_id=0,\n)\nprint(enrollment.data)', + }, + ruby: { + method: 'enrollments.create', + example: + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nenrollment = beagle.enrollments.create(\n effective_date: "effectiveDate",\n plan: "plan",\n property_manager_id: 0,\n status: :"Premium Paying",\n tenant_id: 0\n)\n\nputs(enrollment)', + }, + typescript: { + method: 'client.enrollments.create', + example: + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst enrollment = await client.enrollments.create({\n effectiveDate: 'effectiveDate',\n plan: 'plan',\n propertyManagerId: 0,\n status: 'Premium Paying',\n tenantId: 0,\n});\n\nconsole.log(enrollment.data);", + }, + }, }, { name: 'retrieve_certificate', @@ -303,6 +797,37 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: 'string', markdown: "## retrieve_certificate\n\n`client.enrollments.retrieveCertificate(id: number): string`\n\n**get** `/api/enrollments/{id}/certificate`\n\nget the certificate of enrollment for a given enrollment\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `string`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst response = await client.enrollments.retrieveCertificate(123);\n\nconsole.log(response);\n\nconst content = await response.blob()\nconsole.log(content)\n```", + perLanguage: { + go: { + method: 'client.Enrollments.GetCertificate', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tresponse, err := client.Enrollments.GetCertificate(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/enrollments/$ID/certificate \\\n -H "x-api-key: $BEAGLE_API_KEY"', + }, + java: { + method: 'enrollments().retrieveCertificate', + example: + 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.core.http.HttpResponse;\nimport com.beagle.api.models.enrollments.EnrollmentRetrieveCertificateParams;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n HttpResponse response = client.enrollments().retrieveCertificate(123.0);\n }\n}', + }, + python: { + method: 'enrollments.retrieve_certificate', + example: + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nresponse = client.enrollments.retrieve_certificate(\n 123,\n)\nprint(response)\ncontent = response.read()\nprint(content)', + }, + ruby: { + method: 'enrollments.retrieve_certificate', + example: + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nresponse = beagle.enrollments.retrieve_certificate(123)\n\nputs(response)', + }, + typescript: { + method: 'client.enrollments.retrieveCertificate', + example: + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst response = await client.enrollments.retrieveCertificate(123);\n\nconsole.log(response);\n\nconst content = await response.blob();\nconsole.log(content);", + }, + }, }, { name: 'verify', @@ -316,10 +841,67 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: "{ message: 'insurance verification job scheduled'; }", markdown: "## verify\n\n`client.insuranceVerification.verify(propertyManagerId: number, tenantId: number, urls: string[]): { message: 'insurance verification job scheduled'; }`\n\n**post** `/api/insurance-verification`\n\ntrigger a job to parse a tenants insurance document(s)\n\n### Parameters\n\n- `propertyManagerId: number`\n\n- `tenantId: number`\n\n- `urls: string[]`\n an array of presigned pdf urls for the tenants policy document(s)\n\n### Returns\n\n- `{ message: 'insurance verification job scheduled'; }`\n\n - `message: 'insurance verification job scheduled'`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst response = await client.insuranceVerification.verify({\n propertyManagerId: 0,\n tenantId: 0,\n urls: ['string'],\n});\n\nconsole.log(response);\n```", + perLanguage: { + go: { + method: 'client.InsuranceVerification.Verify', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tresponse, err := client.InsuranceVerification.Verify(context.TODO(), beagle.InsuranceVerificationVerifyParams{\n\t\tPropertyManagerID: 0,\n\t\tTenantID: 0,\n\t\tURLs: []string{"string"},\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Message)\n}\n', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/insurance-verification \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "propertyManagerId": 0,\n "tenantId": 0,\n "urls": [\n "string"\n ]\n }\'', + }, + java: { + method: 'insuranceVerification().verify', + example: + 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.insuranceverification.InsuranceVerificationVerifyParams;\nimport com.beagle.api.models.insuranceverification.InsuranceVerificationVerifyResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n InsuranceVerificationVerifyParams params = InsuranceVerificationVerifyParams.builder()\n .propertyManagerId(0.0)\n .tenantId(0.0)\n .addUrl("string")\n .build();\n InsuranceVerificationVerifyResponse response = client.insuranceVerification().verify(params);\n }\n}', + }, + python: { + method: 'insurance_verification.verify', + example: + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nresponse = client.insurance_verification.verify(\n property_manager_id=0,\n tenant_id=0,\n urls=["string"],\n)\nprint(response.message)', + }, + ruby: { + method: 'insurance_verification.verify', + example: + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nresponse = beagle.insurance_verification.verify(property_manager_id: 0, tenant_id: 0, urls: ["string"])\n\nputs(response)', + }, + typescript: { + method: 'client.insuranceVerification.verify', + example: + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst response = await client.insuranceVerification.verify({\n propertyManagerId: 0,\n tenantId: 0,\n urls: ['string'],\n});\n\nconsole.log(response.message);", + }, + }, }, ]; -const EMBEDDED_READMES: { language: string; content: string }[] = []; +const EMBEDDED_READMES: { language: string; content: string }[] = [ + { + language: 'python', + content: + '# Beagle Python API library\n\n\n[![PyPI version](https://img.shields.io/pypi/v/beagle.svg?label=pypi%20(stable))](https://pypi.org/project/beagle/)\n\nThe Beagle Python library provides convenient access to the Beagle REST API from any Python 3.9+\napplication. The library includes type definitions for all request params and response fields,\nand offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx).\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\n## Documentation\n\n The full API of this library can be found in [api.md](api.md).\n\n## Installation\n\n```sh\n# install from this staging repo\npip install git+ssh://git@github.com/stainless-sdks/beagle-python.git\n```\n> [!NOTE]\n> Once this package is [published to PyPI](https://www.stainless.com/docs/guides/publish), this will become: `pip install beagle`\n\n## Usage\n\nThe full API of this library can be found in [api.md](api.md).\n\n```python\nimport os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n # defaults to "production".\n environment="staging",\n)\n\nplans = client.plans.list()\nprint(plans.data)\n```\n\nWhile you can provide an `api_key` keyword argument,\nwe recommend using [python-dotenv](https://pypi.org/project/python-dotenv/)\nto add `BEAGLE_API_KEY="My API Key"` to your `.env` file\nso that your API Key is not stored in source control.\n\n## Async usage\n\nSimply import `AsyncBeagle` instead of `Beagle` and use `await` with each API call:\n\n```python\nimport os\nimport asyncio\nfrom beagle import AsyncBeagle\n\nclient = AsyncBeagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n # defaults to "production".\n environment="staging",\n)\n\nasync def main() -> None:\n plans = await client.plans.list()\n print(plans.data)\n\nasyncio.run(main())\n```\n\nFunctionality between the synchronous and asynchronous clients is otherwise identical.\n\n### With aiohttp\n\nBy default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.\n\nYou can enable this by installing `aiohttp`:\n\n```sh\n# install from this staging repo\npip install \'beagle[aiohttp] @ git+ssh://git@github.com/stainless-sdks/beagle-python.git\'\n```\n\nThen you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:\n\n```python\nimport os\nimport asyncio\nfrom beagle import DefaultAioHttpClient\nfrom beagle import AsyncBeagle\n\nasync def main() -> None:\n async with AsyncBeagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n http_client=DefaultAioHttpClient(),\n) as client:\n plans = await client.plans.list()\n print(plans.data)\n\nasyncio.run(main())\n```\n\n\n\n## Using types\n\nNested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:\n\n- Serializing back into JSON, `model.to_json()`\n- Converting to a dictionary, `model.to_dict()`\n\nTyped requests and responses provide autocomplete and documentation within your editor. If you would like to see type errors in VS Code to help catch bugs earlier, set `python.analysis.typeCheckingMode` to `basic`.\n\n\n\n## Nested params\n\nNested parameters are dictionaries, typed using `TypedDict`, for example:\n\n```python\nfrom beagle import Beagle\n\nclient = Beagle()\n\ntenant = client.tenants.create(\n address={\n "city": "city",\n "state": "xx",\n "street1": "street1",\n "zip": "60513",\n },\n contact={\n "email": "dev@stainless.com",\n "name": {\n "first": "first",\n "last": "last",\n },\n },\n property_manager_id=0,\n)\nprint(tenant.address)\n```\n\n\n\n## Handling errors\n\nWhen the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `beagle.APIConnectionError` is raised.\n\nWhen the API returns a non-success status code (that is, 4xx or 5xx\nresponse), a subclass of `beagle.APIStatusError` is raised, containing `status_code` and `response` properties.\n\nAll errors inherit from `beagle.APIError`.\n\n```python\nimport beagle\nfrom beagle import Beagle\n\nclient = Beagle()\n\ntry:\n client.plans.list()\nexcept beagle.APIConnectionError as e:\n print("The server could not be reached")\n print(e.__cause__) # an underlying Exception, likely raised within httpx.\nexcept beagle.RateLimitError as e:\n print("A 429 status code was received; we should back off a bit.")\nexcept beagle.APIStatusError as e:\n print("Another non-200-range status code was received")\n print(e.status_code)\n print(e.response)\n```\n\nError codes are as follows:\n\n| Status Code | Error Type |\n| ----------- | -------------------------- |\n| 400 | `BadRequestError` |\n| 401 | `AuthenticationError` |\n| 403 | `PermissionDeniedError` |\n| 404 | `NotFoundError` |\n| 422 | `UnprocessableEntityError` |\n| 429 | `RateLimitError` |\n| >=500 | `InternalServerError` |\n| N/A | `APIConnectionError` |\n\n### Retries\n\nCertain errors are automatically retried 2 times by default, with a short exponential backoff.\nConnection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict,\n429 Rate Limit, and >=500 Internal errors are all retried by default.\n\nYou can use the `max_retries` option to configure or disable retry settings:\n\n```python\nfrom beagle import Beagle\n\n# Configure the default for all requests:\nclient = Beagle(\n # default is 2\n max_retries=0,\n)\n\n# Or, configure per-request:\nclient.with_options(max_retries = 5).plans.list()\n```\n\n### Timeouts\n\nBy default requests time out after 1 minute. You can configure this with a `timeout` option,\nwhich accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object:\n\n```python\nfrom beagle import Beagle\n\n# Configure the default for all requests:\nclient = Beagle(\n # 20 seconds (default is 1 minute)\n timeout=20.0,\n)\n\n# More granular control:\nclient = Beagle(\n timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0),\n)\n\n# Override per-request:\nclient.with_options(timeout = 5.0).plans.list()\n```\n\nOn timeout, an `APITimeoutError` is thrown.\n\nNote that requests that time out are [retried twice by default](#retries).\n\n\n\n## Advanced\n\n### Logging\n\nWe use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module.\n\nYou can enable logging by setting the environment variable `BEAGLE_LOG` to `info`.\n\n```shell\n$ export BEAGLE_LOG=info\n```\n\nOr to `debug` for more verbose logging.\n\n### How to tell whether `None` means `null` or missing\n\nIn an API response, a field may be explicitly `null`, or missing entirely; in either case, its value is `None` in this library. You can differentiate the two cases with `.model_fields_set`:\n\n```py\nif response.my_field is None:\n if \'my_field\' not in response.model_fields_set:\n print(\'Got json like {}, without a "my_field" key present at all.\')\n else:\n print(\'Got json like {"my_field": null}.\')\n```\n\n### Accessing raw response data (e.g. headers)\n\nThe "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call, e.g.,\n\n```py\nfrom beagle import Beagle\n\nclient = Beagle()\nresponse = client.plans.with_raw_response.list()\nprint(response.headers.get(\'X-My-Header\'))\n\nplan = response.parse() # get the object that `plans.list()` would have returned\nprint(plan.data)\n```\n\nThese methods return an [`APIResponse`](https://github.com/stainless-sdks/beagle-python/tree/main/src/beagle/_response.py) object.\n\nThe async client returns an [`AsyncAPIResponse`](https://github.com/stainless-sdks/beagle-python/tree/main/src/beagle/_response.py) with the same structure, the only difference being `await`able methods for reading the response content.\n\n#### `.with_streaming_response`\n\nThe above interface eagerly reads the full response body when you make the request, which may not always be what you want.\n\nTo stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.\n\n```python\nwith client.plans.with_streaming_response.list() as response :\n print(response.headers.get(\'X-My-Header\'))\n\n for line in response.iter_lines():\n print(line)\n```\n\nThe context manager is required so that the response will reliably be closed.\n\n### Making custom/undocumented requests\n\nThis library is typed for convenient access to the documented API.\n\nIf you need to access undocumented endpoints, params, or response properties, the library can still be used.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints, you can make requests using `client.get`, `client.post`, and other\nhttp verbs. Options on the client will be respected (such as retries) when making this request.\n\n```py\nimport httpx\n\nresponse = client.post(\n "/foo",\n cast_to=httpx.Response,\n body={"my_param": True},\n)\n\nprint(response.headers.get("x-foo"))\n```\n\n#### Undocumented request params\n\nIf you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` request\noptions.\n\n#### Undocumented response properties\n\nTo access undocumented response properties, you can access the extra fields like `response.unknown_prop`. You\ncan also get all the extra fields on the Pydantic model as a dict with\n[`response.model_extra`](https://docs.pydantic.dev/latest/api/base_model/#pydantic.BaseModel.model_extra).\n\n### Configuring the HTTP client\n\nYou can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including:\n\n- Support for [proxies](https://www.python-httpx.org/advanced/proxies/)\n- Custom [transports](https://www.python-httpx.org/advanced/transports/)\n- Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality\n\n```python\nimport httpx\nfrom beagle import Beagle, DefaultHttpxClient\n\nclient = Beagle(\n # Or use the `BEAGLE_BASE_URL` env var\n base_url="http://my.test.server.example.com:8083",\n http_client=DefaultHttpxClient(proxy="http://my.test.proxy.example.com", transport=httpx.HTTPTransport(local_address="0.0.0.0")),\n)\n```\n\nYou can also customize the client on a per-request basis by using `with_options()`:\n\n```python\nclient.with_options(http_client=DefaultHttpxClient(...))\n```\n\n### Managing HTTP resources\n\nBy default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting.\n\n```py\nfrom beagle import Beagle\n\nwith Beagle() as client:\n # make requests here\n ...\n\n# HTTP client is now closed\n```\n\n## Versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes that only affect static types, without breaking runtime behavior.\n2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n3. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/beagle-python/issues) with questions, bugs, or suggestions.\n\n### Determining the installed version\n\nIf you\'ve upgraded to the latest version but aren\'t seeing any new features you were expecting then your python environment is likely still using an older version.\n\nYou can determine the version that is being used at runtime with:\n\n```py\nimport beagle\nprint(beagle.__version__)\n```\n\n## Requirements\n\nPython 3.9 or higher.\n\n## Contributing\n\nSee [the contributing documentation](./CONTRIBUTING.md).\n', + }, + { + language: 'go', + content: + '# Beagle Go API Library\n\nGo Reference\n\nThe Beagle Go library provides convenient access to the Beagle REST API\nfrom applications written in Go.\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\n## Installation\n\n\n\n```go\nimport (\n\t"github.com/stainless-sdks/beagle-go" // imported as SDK_PackageName\n)\n```\n\n\n\nOr to pin the version:\n\n\n\n```sh\ngo get -u \'github.com/stainless-sdks/beagle-go@v0.0.1\'\n```\n\n\n\n## Requirements\n\nThis library requires Go 1.22+.\n\n## Usage\n\nThe full API of this library can be found in [api.md](api.md).\n\n```go\npackage main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"), // defaults to os.LookupEnv("BEAGLE_API_KEY")\n\t\toption.WithEnvironmentStaging(), // defaults to option.WithEnvironmentProduction()\n\t)\n\tplans, err := client.Plans.List(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", plans.Data)\n}\n\n```\n\n### Request fields\n\nAll request parameters are wrapped in a generic `Field` type,\nwhich we use to distinguish zero values from null or omitted fields.\n\nThis prevents accidentally sending a zero value if you forget a required parameter,\nand enables explicitly sending `null`, `false`, `\'\'`, or `0` on optional parameters.\nAny field not specified is not sent.\n\nTo construct fields with values, use the helpers `String()`, `Int()`, `Float()`, or most commonly, the generic `F[T]()`.\nTo send a null, use `Null[T]()`, and to send a nonconforming value, use `Raw[T](any)`. For example:\n\n```go\nparams := FooParams{\n\tName: SDK_PackageName.F("hello"),\n\n\t// Explicitly send `"description": null`\n\tDescription: SDK_PackageName.Null[string](),\n\n\tPoint: SDK_PackageName.F(SDK_PackageName.Point{\n\t\tX: SDK_PackageName.Int(0),\n\t\tY: SDK_PackageName.Int(1),\n\n\t\t// In cases where the API specifies a given type,\n\t\t// but you want to send something else, use `Raw`:\n\t\tZ: SDK_PackageName.Raw[int64](0.01), // sends a float\n\t}),\n}\n```\n\n### Response objects\n\nAll fields in response structs are value types (not pointers or wrappers).\n\nIf a given field is `null`, not present, or invalid, the corresponding field\nwill simply be its zero value.\n\nAll response structs also include a special `JSON` field, containing more detailed\ninformation about each property, which you can use like so:\n\n```go\nif res.Name == "" {\n\t// true if `"name"` is either not present or explicitly null\n\tres.JSON.Name.IsNull()\n\n\t// true if the `"name"` key was not present in the response JSON at all\n\tres.JSON.Name.IsMissing()\n\n\t// When the API returns data that cannot be coerced to the expected type:\n\tif res.JSON.Name.IsInvalid() {\n\t\traw := res.JSON.Name.Raw()\n\n\t\tlegacyName := struct{\n\t\t\tFirst string `json:"first"`\n\t\t\tLast string `json:"last"`\n\t\t}{}\n\t\tjson.Unmarshal([]byte(raw), &legacyName)\n\t\tname = legacyName.First + " " + legacyName.Last\n\t}\n}\n```\n\nThese `.JSON` structs also include an `Extras` map containing\nany properties in the json response that were not specified\nin the struct. This can be useful for API features not yet\npresent in the SDK.\n\n```go\nbody := res.JSON.ExtraFields["my_unexpected_field"].Raw()\n```\n\n### RequestOptions\n\nThis library uses the functional options pattern. Functions defined in the\n`SDK_PackageOptionName` package return a `RequestOption`, which is a closure that mutates a\n`RequestConfig`. These options can be supplied to the client or at individual\nrequests. For example:\n\n```go\nclient := SDK_PackageName.SDK_ClientInitializerName(\n\t// Adds a header to every request made by the client\n\tSDK_PackageOptionName.WithHeader("X-Some-Header", "custom_header_info"),\n)\n\nclient.Plans.List(context.TODO(), ...,\n\t// Override the header\n\tSDK_PackageOptionName.WithHeader("X-Some-Header", "some_other_custom_header_info"),\n\t// Add an undocumented field to the request body, using sjson syntax\n\tSDK_PackageOptionName.WithJSONSet("some.json.path", map[string]string{"my": "object"}),\n)\n```\n\nSee the [full list of request options](https://pkg.go.dev/github.com/stainless-sdks/beagle-go/SDK_PackageOptionName).\n\n### Pagination\n\nThis library provides some conveniences for working with paginated list endpoints.\n\nYou can use `.ListAutoPaging()` methods to iterate through items across all pages:\n\n\n\nOr you can use simple `.List()` methods to fetch a single page and receive a standard response object\nwith additional helper methods like `.GetNextPage()`, e.g.:\n\n\n\n### Errors\n\nWhen the API returns a non-success status code, we return an error with type\n`*SDK_PackageName.Error`. This contains the `StatusCode`, `*http.Request`, and\n`*http.Response` values of the request, as well as the JSON of the error body\n(much like other response objects in the SDK).\n\nTo handle errors, we recommend that you use the `errors.As` pattern:\n\n```go\n_, err := client.Plans.List(context.TODO())\nif err != nil {\n\tvar apierr *beagle.Error\n\tif errors.As(err, &apierr) {\n\t\tprintln(string(apierr.DumpRequest(true))) // Prints the serialized HTTP request\n\t\tprintln(string(apierr.DumpResponse(true))) // Prints the serialized HTTP response\n\t}\n\tpanic(err.Error()) // GET "/api/plans": 400 Bad Request { ... }\n}\n```\n\nWhen other errors occur, they are returned unwrapped; for example,\nif HTTP transport fails, you might receive `*url.Error` wrapping `*net.OpError`.\n\n### Timeouts\n\nRequests do not time out by default; use context to configure a timeout for a request lifecycle.\n\nNote that if a request is [retried](#retries), the context timeout does not start over.\nTo set a per-retry timeout, use `SDK_PackageOptionName.WithRequestTimeout()`.\n\n```go\n// This sets the timeout for the request, including all the retries.\nctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)\ndefer cancel()\nclient.Plans.List(\n\tctx,\n\t// This sets the per-retry timeout\n\toption.WithRequestTimeout(20*time.Second),\n)\n```\n\n### File uploads\n\nRequest parameters that correspond to file uploads in multipart requests are typed as\n`param.Field[io.Reader]`. The contents of the `io.Reader` will by default be sent as a multipart form\npart with the file name of "anonymous_file" and content-type of "application/octet-stream".\n\nThe file name and content-type can be customized by implementing `Name() string` or `ContentType()\nstring` on the run-time type of `io.Reader`. Note that `os.File` implements `Name() string`, so a\nfile returned by `os.Open` will be sent with the file name on disk.\n\nWe also provide a helper `SDK_PackageName.FileParam(reader io.Reader, filename string, contentType string)`\nwhich can be used to wrap any `io.Reader` with the appropriate file name and content type.\n\n\n\n### Retries\n\nCertain errors will be automatically retried 2 times by default, with a short exponential backoff.\nWe retry by default all connection errors, 408 Request Timeout, 409 Conflict, 429 Rate Limit,\nand >=500 Internal errors.\n\nYou can use the `WithMaxRetries` option to configure or disable this:\n\n```go\n// Configure the default for all requests:\nclient := beagle.NewClient(\n\toption.WithMaxRetries(0), // default is 2\n)\n\n// Override per-request:\nclient.Plans.List(context.TODO(), option.WithMaxRetries(5))\n```\n\n\n### Accessing raw response data (e.g. response headers)\n\nYou can access the raw HTTP response data by using the `option.WithResponseInto()` request option. This is useful when\nyou need to examine response headers, status codes, or other details.\n\n```go\n// Create a variable to store the HTTP response\nvar response *http.Response\nplans, err := client.Plans.List(context.TODO(), option.WithResponseInto(&response))\nif err != nil {\n\t// handle error\n}\nfmt.Printf("%+v\\n", plans)\n\nfmt.Printf("Status Code: %d\\n", response.StatusCode)\nfmt.Printf("Headers: %+#v\\n", response.Header)\n```\n\n### Making custom/undocumented requests\n\nThis library is typed for convenient access to the documented API. If you need to access undocumented\nendpoints, params, or response properties, the library can still be used.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints, you can use `client.Get`, `client.Post`, and other HTTP verbs.\n`RequestOptions` on the client, such as retries, will be respected when making these requests.\n\n```go\nvar (\n // params can be an io.Reader, a []byte, an encoding/json serializable object,\n // or a "…Params" struct defined in this library.\n params map[string]interface{}\n\n // result can be an []byte, *http.Response, a encoding/json deserializable object,\n // or a model defined in this library.\n result *http.Response\n)\nerr := client.Post(context.Background(), "/unspecified", params, &result)\nif err != nil {\n …\n}\n```\n\n#### Undocumented request params\n\nTo make requests using undocumented parameters, you may use either the `SDK_PackageOptionName.WithQuerySet()`\nor the `SDK_PackageOptionName.WithJSONSet()` methods.\n\n```go\nparams := FooNewParams{\n ID: SDK_PackageName.F("id_xxxx"),\n Data: SDK_PackageName.F(FooNewParamsData{\n FirstName: SDK_PackageName.F("John"),\n }),\n}\nclient.Foo.New(context.Background(), params, SDK_PackageOptionName.WithJSONSet("data.last_name", "Doe"))\n```\n\n#### Undocumented response properties\n\nTo access undocumented response properties, you may either access the raw JSON of the response as a string\nwith `result.JSON.RawJSON()`, or get the raw JSON of a particular field on the result with\n`result.JSON.Foo.Raw()`.\n\nAny fields that are not present on the response struct will be saved and can be accessed by `result.JSON.ExtraFields()` which returns the extra fields as a `map[string]Field`.\n\n### Middleware\n\nWe provide `SDK_PackageOptionName.WithMiddleware` which applies the given\nmiddleware to requests.\n\n```go\nfunc Logger(req *http.Request, next SDK_PackageOptionName.MiddlewareNext) (res *http.Response, err error) {\n\t// Before the request\n\tstart := time.Now()\n\tLogReq(req)\n\n\t// Forward the request to the next handler\n\tres, err = next(req)\n\n\t// Handle stuff after the request\n\tend := time.Now()\n\tLogRes(res, err, start - end)\n\n return res, err\n}\n\nclient := SDK_PackageName.SDK_ClientInitializerName(\n\tSDK_PackageOptionName.WithMiddleware(Logger),\n)\n```\n\nWhen multiple middlewares are provided as variadic arguments, the middlewares\nare applied left to right. If `SDK_PackageOptionName.WithMiddleware` is given\nmultiple times, for example first in the client then the method, the\nmiddleware in the client will run first and the middleware given in the method\nwill run next.\n\nYou may also replace the default `http.Client` with\n`SDK_PackageOptionName.WithHTTPClient(client)`. Only one http client is\naccepted (this overwrites any previous client) and receives requests after any\nmiddleware has been applied.\n\n## Semantic versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n2. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/beagle-go/issues) with questions, bugs, or suggestions.\n\n## Contributing\n\nSee [the contributing documentation](./CONTRIBUTING.md).\n', + }, + { + language: 'typescript', + content: + "# Beagle TypeScript API Library\n\n[![NPM version](https://img.shields.io/npm/v/@corgi-tech/beagle.svg?label=npm%20(stable))](https://npmjs.org/package/@corgi-tech/beagle) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@corgi-tech/beagle)\n\nThis library provides convenient access to the Beagle REST API from server-side TypeScript or JavaScript.\n\n\n\nThe full API of this library can be found in [api.md](api.md).\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\n## Installation\n\n```sh\nnpm install @corgi-tech/beagle\n```\n\n\n\n## Usage\n\nThe full API of this library can be found in [api.md](api.md).\n\n\n```js\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n environment: 'staging', // defaults to 'production'\n});\n\nconst plans = await client.plans.list();\n\nconsole.log(plans.data);\n```\n\n\n\n### Request & Response types\n\nThis library includes TypeScript definitions for all request params and response fields. You may import and use them like so:\n\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n environment: 'staging', // defaults to 'production'\n});\n\nconst plans: Beagle.PlanListResponse = await client.plans.list();\n```\n\nDocumentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors.\n\n\n\n\n\n## Handling errors\n\nWhen the library is unable to connect to the API,\nor if the API returns a non-success status code (i.e., 4xx or 5xx response),\na subclass of `APIError` will be thrown:\n\n\n```ts\nconst plans = await client.plans.list().catch(async (err) => {\n if (err instanceof Beagle.APIError) {\n console.log(err.status); // 400\n console.log(err.name); // BadRequestError\n console.log(err.headers); // {server: 'nginx', ...}\n } else {\n throw err;\n }\n});\n```\n\nError codes are as follows:\n\n| Status Code | Error Type |\n| ----------- | -------------------------- |\n| 400 | `BadRequestError` |\n| 401 | `AuthenticationError` |\n| 403 | `PermissionDeniedError` |\n| 404 | `NotFoundError` |\n| 422 | `UnprocessableEntityError` |\n| 429 | `RateLimitError` |\n| >=500 | `InternalServerError` |\n| N/A | `APIConnectionError` |\n\n### Retries\n\nCertain errors will be automatically retried 2 times by default, with a short exponential backoff.\nConnection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict,\n429 Rate Limit, and >=500 Internal errors will all be retried by default.\n\nYou can use the `maxRetries` option to configure or disable this:\n\n\n```js\n// Configure the default for all requests:\nconst client = new Beagle({\n maxRetries: 0, // default is 2\n});\n\n// Or, configure per-request:\nawait client.plans.list({\n maxRetries: 5,\n});\n```\n\n### Timeouts\n\nRequests time out after 1 minute by default. You can configure this with a `timeout` option:\n\n\n```ts\n// Configure the default for all requests:\nconst client = new Beagle({\n timeout: 20 * 1000, // 20 seconds (default is 1 minute)\n});\n\n// Override per-request:\nawait client.plans.list({\n timeout: 5 * 1000,\n});\n```\n\nOn timeout, an `APIConnectionTimeoutError` is thrown.\n\nNote that requests which time out will be [retried twice by default](#retries).\n\n\n\n\n\n## Advanced Usage\n\n### Accessing raw Response data (e.g., headers)\n\nThe \"raw\" `Response` returned by `fetch()` can be accessed through the `.asResponse()` method on the `APIPromise` type that all methods return.\nThis method returns as soon as the headers for a successful response are received and does not consume the response body, so you are free to write custom parsing or streaming logic.\n\nYou can also use the `.withResponse()` method to get the raw `Response` along with the parsed data.\nUnlike `.asResponse()` this method consumes the body, returning once it is parsed.\n\n\n```ts\nconst client = new Beagle();\n\nconst response = await client.plans.list().asResponse();\nconsole.log(response.headers.get('X-My-Header'));\nconsole.log(response.statusText); // access the underlying Response object\n\nconst { data: plans, response: raw } = await client.plans.list().withResponse();\nconsole.log(raw.headers.get('X-My-Header'));\nconsole.log(plans.data);\n```\n\n### Logging\n\n> [!IMPORTANT]\n> All log messages are intended for debugging only. The format and content of log messages\n> may change between releases.\n\n#### Log levels\n\nThe log level can be configured in two ways:\n\n1. Via the `BEAGLE_LOG` environment variable\n2. Using the `logLevel` client option (overrides the environment variable if set)\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n logLevel: 'debug', // Show all log messages\n});\n```\n\nAvailable log levels, from most to least verbose:\n\n- `'debug'` - Show debug messages, info, warnings, and errors\n- `'info'` - Show info messages, warnings, and errors\n- `'warn'` - Show warnings and errors (default)\n- `'error'` - Show only errors\n- `'off'` - Disable all logging\n\nAt the `'debug'` level, all HTTP requests and responses are logged, including headers and bodies.\nSome authentication-related headers are redacted, but sensitive data in request and response bodies\nmay still be visible.\n\n#### Custom logger\n\nBy default, this library logs to `globalThis.console`. You can also provide a custom logger.\nMost logging libraries are supported, including [pino](https://www.npmjs.com/package/pino), [winston](https://www.npmjs.com/package/winston), [bunyan](https://www.npmjs.com/package/bunyan), [consola](https://www.npmjs.com/package/consola), [signale](https://www.npmjs.com/package/signale), and [@std/log](https://jsr.io/@std/log). If your logger doesn't work, please open an issue.\n\nWhen providing a custom logger, the `logLevel` option still controls which messages are emitted, messages\nbelow the configured level will not be sent to your logger.\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\nimport pino from 'pino';\n\nconst logger = pino();\n\nconst client = new Beagle({\n logger: logger.child({ name: 'Beagle' }),\n logLevel: 'debug', // Send all messages to pino, allowing it to filter\n});\n```\n\n### Making custom/undocumented requests\n\nThis library is typed for convenient access to the documented API. If you need to access undocumented\nendpoints, params, or response properties, the library can still be used.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints, you can use `client.get`, `client.post`, and other HTTP verbs.\nOptions on the client, such as retries, will be respected when making these requests.\n\n```ts\nawait client.post('/some/path', {\n body: { some_prop: 'foo' },\n query: { some_query_arg: 'bar' },\n});\n```\n\n#### Undocumented request params\n\nTo make requests using undocumented parameters, you may use `// @ts-expect-error` on the undocumented\nparameter. This library doesn't validate at runtime that the request matches the type, so any extra values you\nsend will be sent as-is.\n\n```ts\nclient.plans.list({\n // ...\n // @ts-expect-error baz is not yet public\n baz: 'undocumented option',\n});\n```\n\nFor requests with the `GET` verb, any extra params will be in the query, all other requests will send the\nextra param in the body.\n\nIf you want to explicitly send an extra argument, you can do so with the `query`, `body`, and `headers` request\noptions.\n\n#### Undocumented response properties\n\nTo access undocumented response properties, you may access the response object with `// @ts-expect-error` on\nthe response object, or cast the response object to the requisite type. Like the request params, we do not\nvalidate or strip extra properties from the response from the API.\n\n### Customizing the fetch client\n\nBy default, this library expects a global `fetch` function is defined.\n\nIf you want to use a different `fetch` function, you can either polyfill the global:\n\n```ts\nimport fetch from 'my-fetch';\n\nglobalThis.fetch = fetch;\n```\n\nOr pass it to the client:\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\nimport fetch from 'my-fetch';\n\nconst client = new Beagle({ fetch });\n```\n\n### Fetch options\n\nIf you want to set custom `fetch` options without overriding the `fetch` function, you can provide a `fetchOptions` object when instantiating the client or making a request. (Request-specific options override client options.)\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n fetchOptions: {\n // `RequestInit` options\n },\n});\n```\n\n#### Configuring proxies\n\nTo modify proxy behavior, you can provide custom `fetchOptions` that add runtime-specific proxy\noptions to requests:\n\n **Node** [[docs](https://github.com/nodejs/undici/blob/main/docs/docs/api/ProxyAgent.md#example---proxyagent-with-fetch)]\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\nimport * as undici from 'undici';\n\nconst proxyAgent = new undici.ProxyAgent('http://localhost:8888');\nconst client = new Beagle({\n fetchOptions: {\n dispatcher: proxyAgent,\n },\n});\n```\n\n **Bun** [[docs](https://bun.sh/guides/http/proxy)]\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n fetchOptions: {\n proxy: 'http://localhost:8888',\n },\n});\n```\n\n **Deno** [[docs](https://docs.deno.com/api/deno/~/Deno.createHttpClient)]\n\n```ts\nimport Beagle from 'npm:@corgi-tech/beagle';\n\nconst httpClient = Deno.createHttpClient({ proxy: { url: 'http://localhost:8888' } });\nconst client = new Beagle({\n fetchOptions: {\n client: httpClient,\n },\n});\n```\n\n## Frequently Asked Questions\n\n## Semantic versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes that only affect static types, without breaking runtime behavior.\n2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n3. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/corgi-tech/beagle-sdks/issues) with questions, bugs, or suggestions.\n\n## Requirements\n\nTypeScript >= 4.9 is supported.\n\nThe following runtimes are supported:\n\n- Web browsers (Up-to-date Chrome, Firefox, Safari, Edge, and more)\n- Node.js 20 LTS or later ([non-EOL](https://endoflife.date/nodejs)) versions.\n- Deno v1.28.0 or higher.\n- Bun 1.0 or later.\n- Cloudflare Workers.\n- Vercel Edge Runtime.\n- Jest 28 or greater with the `\"node\"` environment (`\"jsdom\"` is not supported at this time).\n- Nitro v2.6 or greater.\n\nNote that React Native is not supported at this time.\n\nIf you are interested in other runtime environments, please open or upvote an issue on GitHub.\n\n## Contributing\n\nSee [the contributing documentation](./CONTRIBUTING.md).\n", + }, + { + language: 'ruby', + content: + '# Beagle Ruby API library\n\nThe Beagle Ruby library provides convenient access to the Beagle REST API from any Ruby 3.2.0+ application. It ships with comprehensive types & docstrings in Yard, RBS, and RBI – [see below](https://github.com/stainless-sdks/beagle-ruby#Sorbet) for usage with Sorbet. The standard library\'s `net/http` is used as the HTTP transport, with connection pooling via the `connection_pool` gem.\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\n## Documentation\n\nDocumentation for releases of this gem can be found [on RubyDoc](https://gemdocs.org/gems/beagle).\n\n\n\n## Installation\n\nTo use this gem, install via Bundler by adding the following to your application\'s `Gemfile`:\n\n```ruby\ngem "beagle", "~> 0.0.1"\n```\n\n## Usage\n\n```ruby\nrequire "bundler/setup"\nrequire "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: ENV["BEAGLE_API_KEY"], # This is the default and can be omitted\n environment: "staging" # defaults to "production"\n)\n\nplans = beagle.plans.list\n\nputs(plans.data)\n```\n\n\n\n\n\n\n\n### Handling errors\n\nWhen the library is unable to connect to the API, or if the API returns a non-success status code (i.e., 4xx or 5xx response), a subclass of `Beagle::Errors::APIError` will be thrown:\n\n```ruby\nbegin\n plan = beagle.plans.list\nrescue Beagle::Errors::APIConnectionError => e\n puts("The server could not be reached")\n puts(e.cause) # an underlying Exception, likely raised within `net/http`\nrescue Beagle::Errors::RateLimitError => e\n puts("A 429 status code was received; we should back off a bit.")\nrescue Beagle::Errors::APIStatusError => e\n puts("Another non-200-range status code was received")\n puts(e.status)\nend\n```\n\nError codes are as follows:\n\n| Cause | Error Type |\n| ---------------- | -------------------------- |\n| HTTP 400 | `BadRequestError` |\n| HTTP 401 | `AuthenticationError` |\n| HTTP 403 | `PermissionDeniedError` |\n| HTTP 404 | `NotFoundError` |\n| HTTP 409 | `ConflictError` |\n| HTTP 422 | `UnprocessableEntityError` |\n| HTTP 429 | `RateLimitError` |\n| HTTP >= 500 | `InternalServerError` |\n| Other HTTP error | `APIStatusError` |\n| Timeout | `APITimeoutError` |\n| Network error | `APIConnectionError` |\n\n### Retries\n\nCertain errors will be automatically retried 2 times by default, with a short exponential backoff.\n\nConnection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict, 429 Rate Limit, >=500 Internal errors, and timeouts will all be retried by default.\n\nYou can use the `max_retries` option to configure or disable this:\n\n```ruby\n# Configure the default for all requests:\nbeagle = Beagle::Client.new(\n max_retries: 0 # default is 2\n)\n\n# Or, configure per-request:\nbeagle.plans.list(request_options: {max_retries: 5})\n```\n\n### Timeouts\n\nBy default, requests will time out after 60 seconds. You can use the timeout option to configure or disable this:\n\n```ruby\n# Configure the default for all requests:\nbeagle = Beagle::Client.new(\n timeout: nil # default is 60\n)\n\n# Or, configure per-request:\nbeagle.plans.list(request_options: {timeout: 5})\n```\n\nOn timeout, `Beagle::Errors::APITimeoutError` is raised.\n\nNote that requests that time out are retried by default.\n\n## Advanced concepts\n\n### BaseModel\n\nAll parameter and response objects inherit from `Beagle::Internal::Type::BaseModel`, which provides several conveniences, including:\n\n1. All fields, including unknown ones, are accessible with `obj[:prop]` syntax, and can be destructured with `obj => {prop: prop}` or pattern-matching syntax.\n\n2. Structural equivalence for equality; if two API calls return the same values, comparing the responses with == will return true.\n\n3. Both instances and the classes themselves can be pretty-printed.\n\n4. Helpers such as `#to_h`, `#deep_to_h`, `#to_json`, and `#to_yaml`.\n\n### Making custom or undocumented requests\n\n#### Undocumented properties\n\nYou can send undocumented parameters to any endpoint, and read undocumented response properties, like so:\n\nNote: the `extra_` parameters of the same name overrides the documented parameters.\n\n```ruby\nplans =\n beagle.plans.list(\n request_options: {\n extra_query: {my_query_parameter: value},\n extra_body: {my_body_parameter: value},\n extra_headers: {"my-header": value}\n }\n )\n\nputs(plans[:my_undocumented_property])\n```\n\n#### Undocumented request params\n\nIf you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` under the `request_options:` parameter when making a request, as seen in the examples above.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints while retaining the benefit of auth, retries, and so on, you can make requests using `client.request`, like so:\n\n```ruby\nresponse = client.request(\n method: :post,\n path: \'/undocumented/endpoint\',\n query: {"dog": "woof"},\n headers: {"useful-header": "interesting-value"},\n body: {"hello": "world"}\n)\n```\n\n### Concurrency & connection pooling\n\nThe `Beagle::Client` instances are threadsafe, but are only are fork-safe when there are no in-flight HTTP requests.\n\nEach instance of `Beagle::Client` has its own HTTP connection pool with a default size of 99. As such, we recommend instantiating the client once per application in most settings.\n\nWhen all available connections from the pool are checked out, requests wait for a new connection to become available, with queue time counting towards the request timeout.\n\nUnless otherwise specified, other classes in the SDK do not have locks protecting their underlying data structure.\n\n## Sorbet\n\nThis library provides comprehensive [RBI](https://sorbet.org/docs/rbi) definitions, and has no dependency on sorbet-runtime.\n\nYou can provide typesafe request parameters like so:\n\n```ruby\nbeagle.plans.list \n```\n\nOr, equivalently:\n\n```ruby\n# Hashes work, but are not typesafe:\nbeagle.plans.list\n\n# You can also splat a full Params class:\nparams = Beagle::PlanListParams.new\nbeagle.plans.list(**params)\n```\n\n### Enums\n\nSince this library does not depend on `sorbet-runtime`, it cannot provide [`T::Enum`](https://sorbet.org/docs/tenum) instances. Instead, we provide "tagged symbols" instead, which is always a primitive at runtime:\n\n```ruby\n# :"Premium Paying"\nputs(Beagle::EnrollmentCreateParams::Status::PREMIUM_PAYING)\n\n# Revealed type: `T.all(Beagle::EnrollmentCreateParams::Status, Symbol)`\nT.reveal_type(Beagle::EnrollmentCreateParams::Status::PREMIUM_PAYING)\n```\n\nEnum parameters have a "relaxed" type, so you can either pass in enum constants or their literal value:\n\n```ruby\n# Using the enum constants preserves the tagged type information:\nbeagle.enrollments.create(\n status: Beagle::EnrollmentCreateParams::Status::PREMIUM_PAYING,\n # …\n)\n\n# Literal values are also permissible:\nbeagle.enrollments.create(\n status: :"Premium Paying",\n # …\n)\n```\n\n## Versioning\n\nThis package follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions. As the library is in initial development and has a major version of `0`, APIs may change at any time.\n\nThis package considers improvements to the (non-runtime) `*.rbi` and `*.rbs` type definitions to be non-breaking changes.\n\n## Requirements\n\nRuby 3.2.0 or higher.\n\n## Contributing\n\nSee [the contributing documentation](https://github.com/stainless-sdks/beagle-ruby/tree/main/CONTRIBUTING.md).\n', + }, + { + language: 'java', + content: + '# Beagle Java API Library\n\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.beagle.api/beagle-java)](https://central.sonatype.com/artifact/com.beagle.api/beagle-java/0.0.1)\n[![javadoc](https://javadoc.io/badge2/com.beagle.api/beagle-java/0.0.1/javadoc.svg)](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1)\n\n\nThe Beagle Java SDK provides convenient access to the Beagle REST API from applications written in Java.\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\nJavadocs are available on [javadoc.io](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1).\n\n## Installation\n\n### Gradle\n\n~~~kotlin\nimplementation("com.beagle.api:beagle-java:0.0.1")\n~~~\n\n### Maven\n\n~~~xml\n\n com.beagle.api\n beagle-java\n 0.0.1\n\n~~~\n\n## Requirements\n\nThis library requires Java 8 or later.\n\n## Usage\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nPlanListResponse plans = client.plans().list();\n```\n\n## Client configuration\n\nConfigure the client using system properties or environment variables:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n```\n\nOr manually:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .apiKey("My API Key")\n .build();\n```\n\nOr using a combination of the two approaches:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n // Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n // Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\n .fromEnv()\n .apiKey("My API Key")\n .build();\n```\n\nSee this table for the available options:\n\n| Setter | System property | Environment variable | Required | Default value |\n| --------- | ---------------- | -------------------- | -------- | ------------------------------------- |\n| `apiKey` | `beagle.apiKey` | `BEAGLE_API_KEY` | true | - |\n| `baseUrl` | `beagle.baseUrl` | `BEAGLE_BASE_URL` | true | `"https://developer.beagleforpm.com"` |\n\nSystem properties take precedence over environment variables.\n\n> [!TIP]\n> Don\'t create more than one client in the same application. Each client has a connection pool and\n> thread pools, which are more efficient to share between requests.\n\n### Modifying configuration\n\nTo temporarily use a modified client configuration, while reusing the same connection and thread pools, call `withOptions()` on any client or service:\n\n```java\nimport com.beagle.api.client.BeagleClient;\n\nBeagleClient clientWithOptions = client.withOptions(optionsBuilder -> {\n optionsBuilder.baseUrl("https://example.com");\n optionsBuilder.maxRetries(42);\n});\n```\n\nThe `withOptions()` method does not affect the original client or service.\n\n## Requests and responses\n\nTo send a request to the Beagle API, build an instance of some `Params` class and pass it to the corresponding client method. When the response is received, it will be deserialized into an instance of a Java class.\n\nFor example, `client.plans().list(...)` should be called with an instance of `PlanListParams`, and it will return an instance of `PlanListResponse`.\n\n## Immutability\n\nEach class in the SDK has an associated [builder](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java) or factory method for constructing it.\n\nEach class is [immutable](https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html) once constructed. If the class has an associated builder, then it has a `toBuilder()` method, which can be used to convert it back to a builder for making a modified copy.\n\nBecause each class is immutable, builder modification will _never_ affect already built class instances.\n\n## Asynchronous execution\n\nThe default client is synchronous. To switch to asynchronous execution, call the `async()` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nCompletableFuture plans = client.async().plans().list();\n```\n\nOr create an asynchronous client from the beginning:\n\n```java\nimport com.beagle.api.client.BeagleClientAsync;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClientAsync;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClientAsync client = BeagleOkHttpClientAsync.fromEnv();\n\nCompletableFuture plans = client.plans().list();\n```\n\nThe asynchronous client supports the same options as the synchronous one, except most methods return `CompletableFuture`s.\n\n\n\n\n\n## Binary responses\n\nThe SDK defines methods that return binary responses, which are used for API responses that shouldn\'t necessarily be parsed, like non-JSON data.\n\nThese methods return [`HttpResponse`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpResponse.kt):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport com.beagle.api.models.enrollments.EnrollmentRetrieveCertificateParams;\n\nHttpResponse response = client.enrollments().retrieveCertificate(123.0);\n```\n\nTo save the response content to a file, use the [`Files.copy(...)`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#copy-java.io.InputStream-java.nio.file.Path-java.nio.file.CopyOption...-) method:\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.nio.file.StandardCopyOption;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n Files.copy(\n response.body(),\n Paths.get(path),\n StandardCopyOption.REPLACE_EXISTING\n );\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\nOr transfer the response content to any [`OutputStream`](https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n response.body().transferTo(Files.newOutputStream(Paths.get(path)));\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\n## Raw responses\n\nThe SDK defines methods that deserialize responses into instances of Java classes. However, these methods don\'t provide access to the response headers, status code, or the raw response body.\n\nTo access this data, prefix any HTTP method call on a client or service with `withRawResponse()`:\n\n```java\nimport com.beagle.api.core.http.Headers;\nimport com.beagle.api.core.http.HttpResponseFor;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\nHttpResponseFor plans = client.plans().withRawResponse().list();\n\nint statusCode = plans.statusCode();\nHeaders headers = plans.headers();\n```\n\nYou can still deserialize the response into an instance of a Java class if needed:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse parsedPlans = plans.parse();\n```\n\n## Error handling\n\nThe SDK throws custom unchecked exception types:\n\n- [`BeagleServiceException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleServiceException.kt): Base class for HTTP errors. See this table for which exception subclass is thrown for each HTTP status code:\n\n | Status | Exception |\n | ------ | -------------------------------------------------- |\n | 400 | [`BadRequestException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BadRequestException.kt) |\n | 401 | [`UnauthorizedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnauthorizedException.kt) |\n | 403 | [`PermissionDeniedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/PermissionDeniedException.kt) |\n | 404 | [`NotFoundException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/NotFoundException.kt) |\n | 422 | [`UnprocessableEntityException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnprocessableEntityException.kt) |\n | 429 | [`RateLimitException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/RateLimitException.kt) |\n | 5xx | [`InternalServerException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/InternalServerException.kt) |\n | others | [`UnexpectedStatusCodeException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnexpectedStatusCodeException.kt) |\n\n- [`BeagleIoException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleIoException.kt): I/O networking errors.\n\n- [`BeagleRetryableException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleRetryableException.kt): Generic error indicating a failure that could be retried by the client.\n\n- [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt): Failure to interpret successfully parsed data. For example, when accessing a property that\'s supposed to be required, but the API unexpectedly omitted it from the response.\n\n- [`BeagleException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleException.kt): Base class for all exceptions. Most errors will result in one of the previously mentioned ones, but completely generic errors may be thrown using the base class.\n\n\n\n## Logging\n\nThe SDK uses the standard [OkHttp logging interceptor](https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor).\n\nEnable logging by setting the `BEAGLE_LOG` environment variable to `info`:\n\n```sh\nexport BEAGLE_LOG=info\n```\n\nOr to `debug` for more verbose logging:\n\n```sh\nexport BEAGLE_LOG=debug\n```\n\n## ProGuard and R8\n\nAlthough the SDK uses reflection, it is still usable with [ProGuard](https://github.com/Guardsquare/proguard) and [R8](https://developer.android.com/topic/performance/app-optimization/enable-app-optimization) because `beagle-java-core` is published with a [configuration file](beagle-java-core/src/main/resources/META-INF/proguard/beagle-java-core.pro) containing [keep rules](https://www.guardsquare.com/manual/configuration/usage).\n\nProGuard and R8 should automatically detect and use the published rules, but you can also manually copy the keep rules if necessary.\n\n\n\n\n\n## Jackson\n\nThe SDK depends on [Jackson](https://github.com/FasterXML/jackson) for JSON serialization/deserialization. It is compatible with version 2.13.4 or higher, but depends on version 2.18.2 by default.\n\nThe SDK throws an exception if it detects an incompatible Jackson version at runtime (e.g. if the default version was overridden in your Maven or Gradle config).\n\nIf the SDK threw an exception, but you\'re _certain_ the version is compatible, then disable the version check using the `checkJacksonVersionCompatibility` on [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt).\n\n> [!CAUTION]\n> We make no guarantee that the SDK works correctly when the Jackson version check is disabled.\n\nAlso note that there are bugs in older Jackson versions that can affect the SDK. We don\'t work around all Jackson bugs ([example](https://github.com/FasterXML/jackson-databind/issues/3240)) and expect users to upgrade Jackson for those instead.\n\n## Network options\n\n### Retries\n\nThe SDK automatically retries 2 times by default, with a short exponential backoff between requests.\n\nOnly the following error types are retried:\n- Connection errors (for example, due to a network connectivity problem)\n- 408 Request Timeout\n- 409 Conflict\n- 429 Rate Limit\n- 5xx Internal\n\nThe API may also explicitly instruct the SDK to retry or not retry a request.\n\nTo set a custom number of retries, configure the client using the `maxRetries` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .maxRetries(4)\n .build();\n```\n\n### Timeouts\n\nRequests time out after 1 minute by default.\n\nTo set a custom timeout, configure the method call using the `timeout` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().timeout(Duration.ofSeconds(30)).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .timeout(Duration.ofSeconds(30))\n .build();\n```\n\n### Proxies\n\nTo route requests through a proxy, configure the client using the `proxy` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.net.InetSocketAddress;\nimport java.net.Proxy;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .proxy(new Proxy(\n Proxy.Type.HTTP, new InetSocketAddress(\n "https://example.com", 8080\n )\n ))\n .build();\n```\n\n### Connection pooling\n\nTo customize the underlying OkHttp connection pool, configure the client using the `maxIdleConnections` and `keepAliveDuration` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `maxIdleConnections` is set, then `keepAliveDuration` must be set, and vice versa.\n .maxIdleConnections(10)\n .keepAliveDuration(Duration.ofMinutes(2))\n .build();\n```\n\nIf both options are unset, OkHttp\'s default connection pool settings are used.\n\n### HTTPS\n\n> [!NOTE]\n> Most applications should not call these methods, and instead use the system defaults. The defaults include\n> special optimizations that can be lost if the implementations are modified.\n\nTo configure how HTTPS connections are secured, configure the client using the `sslSocketFactory`, `trustManager`, and `hostnameVerifier` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `sslSocketFactory` is set, then `trustManager` must be set, and vice versa.\n .sslSocketFactory(yourSSLSocketFactory)\n .trustManager(yourTrustManager)\n .hostnameVerifier(yourHostnameVerifier)\n .build();\n```\n\n### Environments\n\nThe SDK sends requests to the production by default. To send requests to a different environment, configure the client like so:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .staging()\n .build();\n```\n\n### Custom HTTP client\n\nThe SDK consists of three artifacts:\n- `beagle-java-core`\n - Contains core SDK logic\n - Does not depend on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleClient`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClient.kt), [`BeagleClientAsync`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsync.kt), [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt), and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), all of which can work with any HTTP client\n- `beagle-java-client-okhttp`\n - Depends on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) and [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), which provide a way to construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), respectively, using OkHttp\n- `beagle-java`\n - Depends on and exposes the APIs of both `beagle-java-core` and `beagle-java-client-okhttp`\n - Does not have its own logic\n\nThis structure allows replacing the SDK\'s default HTTP client without pulling in unnecessary dependencies.\n\n#### Customized [`OkHttpClient`](https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.html)\n\n> [!TIP]\n> Try the available [network options](#network-options) before replacing the default client.\n\nTo use a customized `OkHttpClient`:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Copy `beagle-java-client-okhttp`\'s [`OkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/OkHttpClient.kt) class into your code and customize it\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your customized client\n\n### Completely custom HTTP client\n\nTo use a completely custom HTTP client:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Write a class that implements the [`HttpClient`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpClient.kt) interface\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your new client class\n\n## Undocumented API functionality\n\nThe SDK is typed for convenient usage of the documented API. However, it also supports working with undocumented or not yet supported parts of the API.\n\n### Parameters\n\nTo set undocumented parameters, call the `putAdditionalHeader`, `putAdditionalQueryParam`, or `putAdditionalBodyProperty` methods on any `Params` class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder()\n .putAdditionalHeader("Secret-Header", "42")\n .putAdditionalQueryParam("secret_query_param", "42")\n .putAdditionalBodyProperty("secretProperty", JsonValue.from("42"))\n .build();\n```\n\nThese can be accessed on the built object later using the `_additionalHeaders()`, `_additionalQueryParams()`, and `_additionalBodyProperties()` methods.\n\nTo set undocumented parameters on _nested_ headers, query params, or body classes, call the `putAdditionalProperty` method on the nested class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.tenants.Address;\nimport com.beagle.api.models.tenants.TenantCreateParams;\n\nTenantCreateParams params = TenantCreateParams.builder()\n .address(Address.builder()\n .putAdditionalProperty("secretProperty", JsonValue.from("42"))\n .build())\n .build();\n```\n\nThese properties can be accessed on the nested built object later using the `_additionalProperties()` method.\n\nTo set a documented parameter or property to an undocumented or not yet supported _value_, pass a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) object to its setter:\n\n```java\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder().build();\n```\n\nThe most straightforward way to create a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) is using its `from(...)` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.List;\nimport java.util.Map;\n\n// Create primitive JSON values\nJsonValue nullValue = JsonValue.from(null);\nJsonValue booleanValue = JsonValue.from(true);\nJsonValue numberValue = JsonValue.from(42);\nJsonValue stringValue = JsonValue.from("Hello World!");\n\n// Create a JSON array value equivalent to `["Hello", "World"]`\nJsonValue arrayValue = JsonValue.from(List.of(\n "Hello", "World"\n));\n\n// Create a JSON object value equivalent to `{ "a": 1, "b": 2 }`\nJsonValue objectValue = JsonValue.from(Map.of(\n "a", 1,\n "b", 2\n));\n\n// Create an arbitrarily nested JSON equivalent to:\n// {\n// "a": [1, 2],\n// "b": [3, 4]\n// }\nJsonValue complexValue = JsonValue.from(Map.of(\n "a", List.of(\n 1, 2\n ),\n "b", List.of(\n 3, 4\n )\n));\n```\n\nNormally a `Builder` class\'s `build` method will throw [`IllegalStateException`](https://docs.oracle.com/javase/8/docs/api/java/lang/IllegalStateException.html) if any required parameter or property is unset.\n\nTo forcibly omit a required parameter or property, pass [`JsonMissing`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt):\n\n```java\nimport com.beagle.api.core.JsonMissing;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanRetrieveParams;\n\nPlanListParams params = PlanRetrieveParams.builder()\n .code(JsonMissing.of())\n .build();\n```\n\n### Response properties\n\nTo access undocumented response properties, call the `_additionalProperties()` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.Map;\n\nMap additionalProperties = client.plans().list(params)._additionalProperties();\nJsonValue secretPropertyValue = additionalProperties.get("secretProperty");\n\nString result = secretPropertyValue.accept(new JsonValue.Visitor<>() {\n @Override\n public String visitNull() {\n return "It\'s null!";\n }\n\n @Override\n public String visitBoolean(boolean value) {\n return "It\'s a boolean!";\n }\n\n @Override\n public String visitNumber(Number value) {\n return "It\'s a number!";\n }\n\n // Other methods include `visitMissing`, `visitString`, `visitArray`, and `visitObject`\n // The default implementation of each unimplemented method delegates to `visitDefault`, which throws by default, but can also be overridden\n});\n```\n\nTo access a property\'s raw JSON value, which may be undocumented, call its `_` prefixed method:\n\n```java\nimport com.beagle.api.core.JsonField;\nimport java.util.Optional;\n\nJsonField field = client.plans().list(params)._field();\n\nif (field.isMissing()) {\n // The property is absent from the JSON response\n} else if (field.isNull()) {\n // The property was set to literal null\n} else {\n // Check if value was provided as a string\n // Other methods include `asNumber()`, `asBoolean()`, etc.\n Optional jsonString = field.asString();\n\n // Try to deserialize into a custom type\n MyClass myObject = field.asUnknown().orElseThrow().convert(MyClass.class);\n}\n```\n\n### Response validation\n\nIn rare cases, the API may return a response that doesn\'t match the expected type. For example, the SDK may expect a property to contain a `String`, but the API could return something else.\n\nBy default, the SDK will not throw an exception in this case. It will throw [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt) only if you directly access the property.\n\nIf you would prefer to check that the response is completely well-typed upfront, then either call `validate()`:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(params).validate();\n```\n\nOr configure the method call to validate the response using the `responseValidation` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().responseValidation(true).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .responseValidation(true)\n .build();\n```\n\n## FAQ\n\n### Why don\'t you use plain `enum` classes?\n\nJava `enum` classes are not trivially [forwards compatible](https://www.stainless.com/blog/making-java-enums-forwards-compatible). Using them in the SDK could cause runtime exceptions if the API is updated to respond with a new enum value.\n\n### Why do you represent fields using `JsonField` instead of just plain `T`?\n\nUsing `JsonField` enables a few features:\n\n- Allowing usage of [undocumented API functionality](#undocumented-api-functionality)\n- Lazily [validating the API response against the expected shape](#response-validation)\n- Representing absent vs explicitly null values\n\n### Why don\'t you use [`data` classes](https://kotlinlang.org/docs/data-classes.html)?\n\nIt is not [backwards compatible to add new fields to a data class](https://kotlinlang.org/docs/api-guidelines-backward-compatibility.html#avoid-using-data-classes-in-your-api) and we don\'t want to introduce a breaking change every time we add a field to a class.\n\n### Why don\'t you use checked exceptions?\n\nChecked exceptions are widely considered a mistake in the Java programming language. In fact, they were omitted from Kotlin for this reason.\n\nChecked exceptions:\n\n- Are verbose to handle\n- Encourage error handling at the wrong level of abstraction, where nothing can be done about the error\n- Are tedious to propagate due to the [function coloring problem](https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function)\n- Don\'t play well with lambdas (also due to the function coloring problem)\n\n## Semantic versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n2. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/beagle-java/issues) with questions, bugs, or suggestions.\n', + }, +]; const INDEX_OPTIONS = { fields: [ From 08118229a18bc20e69ff03e53fb69b2f5dd6cbd5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 05:42:24 +0000 Subject: [PATCH 110/138] chore(internal): codegen related update --- packages/mcp-server/src/code-tool-worker.ts | 12 ++- packages/mcp-server/src/local-docs-search.ts | 95 ++++++++++++++++++++ 2 files changed, 105 insertions(+), 2 deletions(-) diff --git a/packages/mcp-server/src/code-tool-worker.ts b/packages/mcp-server/src/code-tool-worker.ts index 1376ec88..3114b99e 100644 --- a/packages/mcp-server/src/code-tool-worker.ts +++ b/packages/mcp-server/src/code-tool-worker.ts @@ -7,6 +7,10 @@ import ts from 'typescript'; import { WorkerOutput } from './code-tool-types'; import { Beagle, ClientOptions } from '@corgi-tech/beagle'; +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; @@ -254,7 +258,9 @@ const fetch = async (req: Request): Promise => { 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)); }, @@ -264,7 +270,7 @@ const fetch = async (req: Request): Promise => { }; 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, @@ -282,6 +288,8 @@ const fetch = async (req: Request): Promise => { } satisfies WorkerOutput, { status: 400, statusText: 'Code execution error' }, ); + } finally { + globalThis.console = originalConsole; } }; diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index a1e068b2..f9c96af2 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -63,6 +63,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## list\n\n`client.plans.list(): { data: plan[]; success: true; }`\n\n**get** `/api/plans`\n\nList all available insurance plans that tenants can be enrolled in.\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }[]; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }[]`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plans = await client.plans.list();\n\nconsole.log(plans);\n```", perLanguage: { + csharp: { + method: 'Plans.List', + example: + 'PlanListParams parameters = new();\n\nvar plans = await client.Plans.List(parameters);\n\nConsole.WriteLine(plans);', + }, go: { method: 'client.Plans.List', example: @@ -107,6 +112,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## retrieve\n\n`client.plans.retrieve(code: string): { data: plan; success: true; }`\n\n**get** `/api/plans/{code}`\n\nretrieve a specific plans details by its code.\n\n### Parameters\n\n- `code: string`\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plan = await client.plans.retrieve('code');\n\nconsole.log(plan);\n```", perLanguage: { + csharp: { + method: 'Plans.Retrieve', + example: + 'PlanRetrieveParams parameters = new() { Code = "code" };\n\nvar plan = await client.Plans.Retrieve(parameters);\n\nConsole.WriteLine(plan);', + }, go: { method: 'client.Plans.Get', example: @@ -152,6 +162,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## retrieve\n\n`client.propertyManagers.retrieve(id: number): { data: property_manager; success: true; }`\n\n**get** `/api/property-managers/{id}`\n\nget a property manager by id.\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.retrieve(123);\n\nconsole.log(propertyManager);\n```", perLanguage: { + csharp: { + method: 'PropertyManagers.Retrieve', + example: + 'PropertyManagerRetrieveParams parameters = new() { ID = 123 };\n\nvar propertyManager = await client.PropertyManagers.Retrieve(parameters);\n\nConsole.WriteLine(propertyManager);', + }, go: { method: 'client.PropertyManagers.Get', example: @@ -204,6 +219,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## update\n\n`client.propertyManagers.update(id: number, addresses?: { city: string; state: string; street1: string; zip: string; street2?: string; }[], clickWrapAt?: number, contacts?: { email: string; name: object; phone?: string; }[], name?: string): { data: property_manager; success: true; }`\n\n**patch** `/api/property-managers/{id}`\n\nupdate an existing property manager by ID\n\n(Note that when updating **contacts** or **addresses** you need to send the whole array you want to replace them with)\n\n### Parameters\n\n- `id: number`\n\n- `addresses?: { city: string; state: string; street1: string; zip: string; street2?: string; }[]`\n street addresses for each Property\n\n- `clickWrapAt?: number`\n unix timestamp (ms) of clickwrap agreement signature\n\n- `contacts?: { email: string; name: { first: string; last: string; }; phone?: string; }[]`\n contact information for each Property Manager\n\n- `name?: string`\n name of the Property Management Company\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.update(123);\n\nconsole.log(propertyManager);\n```", perLanguage: { + csharp: { + method: 'PropertyManagers.Update', + example: + 'PropertyManagerUpdateParams parameters = new() { ID = 123 };\n\nvar propertyManager = await client.PropertyManagers.Update(parameters);\n\nConsole.WriteLine(propertyManager);', + }, go: { method: 'client.PropertyManagers.Update', example: @@ -247,6 +267,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## delete\n\n`client.propertyManagers.delete(id: number): void`\n\n**delete** `/api/property-managers/{id}`\n\ndelete a property manager by ID.\n\n### Parameters\n\n- `id: number`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nawait client.propertyManagers.delete(123)\n```", perLanguage: { + csharp: { + method: 'PropertyManagers.Delete', + example: + 'PropertyManagerDeleteParams parameters = new() { ID = 123 };\n\nawait client.PropertyManagers.Delete(parameters);', + }, go: { method: 'client.PropertyManagers.Delete', example: @@ -291,6 +316,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## list\n\n`client.propertyManagers.list(page?: number, size?: number): { data: object; success: true; }`\n\n**get** `/api/property-managers`\n\nlist all property managers, note this endpoint is paginated.\n\n### Parameters\n\n- `page?: number`\n Page number to fetch.\n\n- `size?: number`\n Number of items per page.\n\n### Returns\n\n- `{ data: { items: object[]; pagination: object; }; success: true; }`\n\n - `data: { items: { id: number; addresses: object[]; contacts: object[]; name: string; clickWrapAt?: number; }[]; pagination: { page: number; pages: number; records: number; size: number; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManagers = await client.propertyManagers.list();\n\nconsole.log(propertyManagers);\n```", perLanguage: { + csharp: { + method: 'PropertyManagers.List', + example: + 'PropertyManagerListParams parameters = new();\n\nvar propertyManagers = await client.PropertyManagers.List(parameters);\n\nConsole.WriteLine(propertyManagers);', + }, go: { method: 'client.PropertyManagers.List', example: @@ -341,6 +371,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## create\n\n`client.propertyManagers.create(addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[], contacts: { email: string; name: object; phone?: string; }[], name: string, clickWrapAt?: number): { data: property_manager; success: true; }`\n\n**post** `/api/property-managers`\n\ncreate a new property manager.\n\n### Parameters\n\n- `addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]`\n street addresses for each Property\n\n- `contacts: { email: string; name: { first: string; last: string; }; phone?: string; }[]`\n contact information for each Property Manager\n\n- `name: string`\n name of the Property Management Company\n\n- `clickWrapAt?: number`\n unix timestamp (ms) of clickwrap agreement signature\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.create({\n addresses: [{\n city: 'city',\n state: 'xx',\n street1: 'street1',\n zip: '60513',\n kind: 'billing',\n}],\n contacts: [{\n email: 'dev@stainless.com',\n name: { first: 'first', last: 'last' },\n kind: 'agreements',\n}],\n name: 'name',\n});\n\nconsole.log(propertyManager);\n```", perLanguage: { + csharp: { + method: 'PropertyManagers.Create', + example: + 'PropertyManagerCreateParams parameters = new()\n{\n Addresses =\n [\n new()\n {\n City = "city",\n State = "xx",\n Street1 = "street1",\n Zip = "60513",\n Street2 = "street2",\n Kind = Kind.Billing,\n },\n ],\n Contacts =\n [\n new()\n {\n Email = "dev@stainless.com",\n Name = new()\n {\n First = "first",\n Last = "last",\n },\n Phone = "phone",\n Kind = Kind.Agreements,\n },\n ],\n Name = "name",\n};\n\nvar propertyManager = await client.PropertyManagers.Create(parameters);\n\nConsole.WriteLine(propertyManager);', + }, go: { method: 'client.PropertyManagers.New', example: @@ -385,6 +420,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## retrieve\n\n`client.tenants.retrieve(id: number): { data: tenant; success: true; }`\n\n**get** `/api/tenants/{id}`\n\nretrieve a single tenant by their id.\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.retrieve(123);\n\nconsole.log(tenant);\n```", perLanguage: { + csharp: { + method: 'Tenants.Retrieve', + example: + 'TenantRetrieveParams parameters = new() { ID = 123 };\n\nvar tenant = await client.Tenants.Retrieve(parameters);\n\nConsole.WriteLine(tenant);', + }, go: { method: 'client.Tenants.Get', example: @@ -433,6 +473,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## update\n\n`client.tenants.update(id: number, address?: { city: string; state: string; street1: string; zip: string; street2?: string; }, contact?: { email: string; name: object; phone?: string; }): { data: tenant; success: true; }`\n\n**patch** `/api/tenants/{id}`\n\nupdate an existing tenant by their id.\n\n### Parameters\n\n- `id: number`\n\n- `address?: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `city: string`\n - `state: string`\n two letter state code, ie CA\n - `street1: string`\n - `zip: string`\n 5 digit US zip code, ie 94104\n - `street2?: string`\n\n- `contact?: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `email: string`\n - `name: { first: string; last: string; }`\n - `phone?: string`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.update(123);\n\nconsole.log(tenant);\n```", perLanguage: { + csharp: { + method: 'Tenants.Update', + example: + 'TenantUpdateParams parameters = new() { ID = 123 };\n\nvar tenant = await client.Tenants.Update(parameters);\n\nConsole.WriteLine(tenant);', + }, go: { method: 'client.Tenants.Update', example: @@ -476,6 +521,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## delete\n\n`client.tenants.delete(id: number): void`\n\n**delete** `/api/tenants/{id}`\n\ndelete an existing tenant by their id.\n\n### Parameters\n\n- `id: number`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nawait client.tenants.delete(123)\n```", perLanguage: { + csharp: { + method: 'Tenants.Delete', + example: + 'TenantDeleteParams parameters = new() { ID = 123 };\n\nawait client.Tenants.Delete(parameters);', + }, go: { method: 'client.Tenants.Delete', example: @@ -521,6 +571,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## list\n\n`client.tenants.list(page?: number, propertyManagerId?: number, size?: number): { data: object; success: true; }`\n\n**get** `/api/tenants`\n\nlist all tenants, this endpoint is paginated and allows for queries by individual property manager.\n\n### Parameters\n\n- `page?: number`\n Page number to fetch.\n\n- `propertyManagerId?: number`\n\n- `size?: number`\n Number of items per page.\n\n### Returns\n\n- `{ data: { items: object[]; pagination: object; }; success: true; }`\n\n - `data: { items: { id: number; address: object; contact: object; }[]; pagination: { page: number; pages: number; records: number; size: number; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenants = await client.tenants.list();\n\nconsole.log(tenants);\n```", perLanguage: { + csharp: { + method: 'Tenants.List', + example: + 'TenantListParams parameters = new();\n\nvar tenants = await client.Tenants.List(parameters);\n\nConsole.WriteLine(tenants);', + }, go: { method: 'client.Tenants.List', example: @@ -568,6 +623,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## create\n\n`client.tenants.create(address: { city: string; state: string; street1: string; zip: string; street2?: string; }, contact: { email: string; name: object; phone?: string; }, propertyManagerId: number): { data: tenant; success: true; }`\n\n**post** `/api/tenants`\n\ncreate a new tenant.\n\n### Parameters\n\n- `address: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `city: string`\n - `state: string`\n two letter state code, ie CA\n - `street1: string`\n - `zip: string`\n 5 digit US zip code, ie 94104\n - `street2?: string`\n\n- `contact: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `email: string`\n - `name: { first: string; last: string; }`\n - `phone?: string`\n\n- `propertyManagerId: number`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.create({\n address: {\n city: 'city',\n state: 'xx',\n street1: 'street1',\n zip: '60513',\n},\n contact: {\n email: 'dev@stainless.com',\n name: { first: 'first', last: 'last' },\n},\n propertyManagerId: 0,\n});\n\nconsole.log(tenant);\n```", perLanguage: { + csharp: { + method: 'Tenants.Create', + example: + 'TenantCreateParams parameters = new()\n{\n Address = new()\n {\n City = "city",\n State = "xx",\n Street1 = "street1",\n Zip = "60513",\n Street2 = "street2",\n },\n Contact = new()\n {\n Email = "dev@stainless.com",\n Name = new()\n {\n First = "first",\n Last = "last",\n },\n Phone = "phone",\n },\n PropertyManagerID = 0,\n};\n\nvar tenant = await client.Tenants.Create(parameters);\n\nConsole.WriteLine(tenant);', + }, go: { method: 'client.Tenants.New', example: @@ -613,6 +673,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## retrieve\n\n`client.enrollments.retrieve(id: number): { data: enrollment; success: true; }`\n\n**get** `/api/enrollments/{id}`\n\nget a specific enrollment by its id.\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }`\n\n - `data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollment = await client.enrollments.retrieve(123);\n\nconsole.log(enrollment);\n```", perLanguage: { + csharp: { + method: 'Enrollments.Retrieve', + example: + 'EnrollmentRetrieveParams parameters = new() { ID = 123 };\n\nvar enrollment = await client.Enrollments.Retrieve(parameters);\n\nConsole.WriteLine(enrollment);', + }, go: { method: 'client.Enrollments.Get', example: @@ -657,6 +722,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## lapse\n\n`client.enrollments.lapse(id: number): void`\n\n**delete** `/api/enrollments/{id}`\n\nlapses a specific enrollment for a tenant, note that if a tenant has multiple enrollments (e.g., SDR and TLL), each must be lapsed individually\n\n### Parameters\n\n- `id: number`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nawait client.enrollments.lapse(123)\n```", perLanguage: { + csharp: { + method: 'Enrollments.Lapse', + example: + 'EnrollmentLapseParams parameters = new() { ID = 123 };\n\nawait client.Enrollments.Lapse(parameters);', + }, go: { method: 'client.Enrollments.Lapse', example: @@ -702,6 +772,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## list\n\n`client.enrollments.list(page?: number, propertyManagerId?: number, size?: number): { data: object; success: true; }`\n\n**get** `/api/enrollments`\n\nlist all enrollments, this endpoint is paginated and allows for queries by individual property manager.\n\n### Parameters\n\n- `page?: number`\n Page number to fetch.\n\n- `propertyManagerId?: number`\n\n- `size?: number`\n Number of items per page.\n\n### Returns\n\n- `{ data: { items: object[]; pagination: object; }; success: true; }`\n\n - `data: { items: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }[]; pagination: { page: number; pages: number; records: number; size: number; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollments = await client.enrollments.list();\n\nconsole.log(enrollments);\n```", perLanguage: { + csharp: { + method: 'Enrollments.List', + example: + 'EnrollmentListParams parameters = new();\n\nvar enrollments = await client.Enrollments.List(parameters);\n\nConsole.WriteLine(enrollments);', + }, go: { method: 'client.Enrollments.List', example: @@ -754,6 +829,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## create\n\n`client.enrollments.create(effectiveDate: string, plan: string, propertyManagerId: number, status: string, tenantId: number, note?: string): { data: enrollment; success: true; }`\n\n**post** `/api/enrollments`\n\ncreate a new enrollment for a tenant.\n\n### Parameters\n\n- `effectiveDate: string`\n the date the enrollment will begin, note enrollments cannot begin in the past\n\n- `plan: string`\n the plan name/code\n\n- `propertyManagerId: number`\n\n- `status: string`\n\n- `tenantId: number`\n\n- `note?: string`\n an optional note field, this can be used for easily appending metadata to enrollments\n\n### Returns\n\n- `{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }`\n\n - `data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollment = await client.enrollments.create({\n effectiveDate: 'effectiveDate',\n plan: 'plan',\n propertyManagerId: 0,\n status: 'Premium Paying',\n tenantId: 0,\n});\n\nconsole.log(enrollment);\n```", perLanguage: { + csharp: { + method: 'Enrollments.Create', + example: + 'EnrollmentCreateParams parameters = new()\n{\n EffectiveDate = "effectiveDate",\n Plan = "plan",\n PropertyManagerID = 0,\n Status = Status.PremiumPaying,\n TenantID = 0,\n};\n\nvar enrollment = await client.Enrollments.Create(parameters);\n\nConsole.WriteLine(enrollment);', + }, go: { method: 'client.Enrollments.New', example: @@ -798,6 +878,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## retrieve_certificate\n\n`client.enrollments.retrieveCertificate(id: number): string`\n\n**get** `/api/enrollments/{id}/certificate`\n\nget the certificate of enrollment for a given enrollment\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `string`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst response = await client.enrollments.retrieveCertificate(123);\n\nconsole.log(response);\n\nconst content = await response.blob()\nconsole.log(content)\n```", perLanguage: { + csharp: { + method: 'Enrollments.RetrieveCertificate', + example: + 'EnrollmentRetrieveCertificateParams parameters = new() { ID = 123 };\n\nvar response = await client.Enrollments.RetrieveCertificate(parameters);\n\nConsole.WriteLine(response);', + }, go: { method: 'client.Enrollments.GetCertificate', example: @@ -842,6 +927,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## verify\n\n`client.insuranceVerification.verify(propertyManagerId: number, tenantId: number, urls: string[]): { message: 'insurance verification job scheduled'; }`\n\n**post** `/api/insurance-verification`\n\ntrigger a job to parse a tenants insurance document(s)\n\n### Parameters\n\n- `propertyManagerId: number`\n\n- `tenantId: number`\n\n- `urls: string[]`\n an array of presigned pdf urls for the tenants policy document(s)\n\n### Returns\n\n- `{ message: 'insurance verification job scheduled'; }`\n\n - `message: 'insurance verification job scheduled'`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst response = await client.insuranceVerification.verify({\n propertyManagerId: 0,\n tenantId: 0,\n urls: ['string'],\n});\n\nconsole.log(response);\n```", perLanguage: { + csharp: { + method: 'InsuranceVerification.Verify', + example: + 'InsuranceVerificationVerifyParams parameters = new()\n{\n PropertyManagerID = 0,\n TenantID = 0,\n Urls =\n [\n "string"\n ],\n};\n\nvar response = await client.InsuranceVerification.Verify(parameters);\n\nConsole.WriteLine(response);', + }, go: { method: 'client.InsuranceVerification.Verify', example: @@ -901,6 +991,11 @@ const EMBEDDED_READMES: { language: string; content: string }[] = [ content: '# Beagle Java API Library\n\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.beagle.api/beagle-java)](https://central.sonatype.com/artifact/com.beagle.api/beagle-java/0.0.1)\n[![javadoc](https://javadoc.io/badge2/com.beagle.api/beagle-java/0.0.1/javadoc.svg)](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1)\n\n\nThe Beagle Java SDK provides convenient access to the Beagle REST API from applications written in Java.\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\nJavadocs are available on [javadoc.io](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1).\n\n## Installation\n\n### Gradle\n\n~~~kotlin\nimplementation("com.beagle.api:beagle-java:0.0.1")\n~~~\n\n### Maven\n\n~~~xml\n\n com.beagle.api\n beagle-java\n 0.0.1\n\n~~~\n\n## Requirements\n\nThis library requires Java 8 or later.\n\n## Usage\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nPlanListResponse plans = client.plans().list();\n```\n\n## Client configuration\n\nConfigure the client using system properties or environment variables:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n```\n\nOr manually:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .apiKey("My API Key")\n .build();\n```\n\nOr using a combination of the two approaches:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n // Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n // Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\n .fromEnv()\n .apiKey("My API Key")\n .build();\n```\n\nSee this table for the available options:\n\n| Setter | System property | Environment variable | Required | Default value |\n| --------- | ---------------- | -------------------- | -------- | ------------------------------------- |\n| `apiKey` | `beagle.apiKey` | `BEAGLE_API_KEY` | true | - |\n| `baseUrl` | `beagle.baseUrl` | `BEAGLE_BASE_URL` | true | `"https://developer.beagleforpm.com"` |\n\nSystem properties take precedence over environment variables.\n\n> [!TIP]\n> Don\'t create more than one client in the same application. Each client has a connection pool and\n> thread pools, which are more efficient to share between requests.\n\n### Modifying configuration\n\nTo temporarily use a modified client configuration, while reusing the same connection and thread pools, call `withOptions()` on any client or service:\n\n```java\nimport com.beagle.api.client.BeagleClient;\n\nBeagleClient clientWithOptions = client.withOptions(optionsBuilder -> {\n optionsBuilder.baseUrl("https://example.com");\n optionsBuilder.maxRetries(42);\n});\n```\n\nThe `withOptions()` method does not affect the original client or service.\n\n## Requests and responses\n\nTo send a request to the Beagle API, build an instance of some `Params` class and pass it to the corresponding client method. When the response is received, it will be deserialized into an instance of a Java class.\n\nFor example, `client.plans().list(...)` should be called with an instance of `PlanListParams`, and it will return an instance of `PlanListResponse`.\n\n## Immutability\n\nEach class in the SDK has an associated [builder](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java) or factory method for constructing it.\n\nEach class is [immutable](https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html) once constructed. If the class has an associated builder, then it has a `toBuilder()` method, which can be used to convert it back to a builder for making a modified copy.\n\nBecause each class is immutable, builder modification will _never_ affect already built class instances.\n\n## Asynchronous execution\n\nThe default client is synchronous. To switch to asynchronous execution, call the `async()` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nCompletableFuture plans = client.async().plans().list();\n```\n\nOr create an asynchronous client from the beginning:\n\n```java\nimport com.beagle.api.client.BeagleClientAsync;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClientAsync;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClientAsync client = BeagleOkHttpClientAsync.fromEnv();\n\nCompletableFuture plans = client.plans().list();\n```\n\nThe asynchronous client supports the same options as the synchronous one, except most methods return `CompletableFuture`s.\n\n\n\n\n\n## Binary responses\n\nThe SDK defines methods that return binary responses, which are used for API responses that shouldn\'t necessarily be parsed, like non-JSON data.\n\nThese methods return [`HttpResponse`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpResponse.kt):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport com.beagle.api.models.enrollments.EnrollmentRetrieveCertificateParams;\n\nHttpResponse response = client.enrollments().retrieveCertificate(123.0);\n```\n\nTo save the response content to a file, use the [`Files.copy(...)`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#copy-java.io.InputStream-java.nio.file.Path-java.nio.file.CopyOption...-) method:\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.nio.file.StandardCopyOption;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n Files.copy(\n response.body(),\n Paths.get(path),\n StandardCopyOption.REPLACE_EXISTING\n );\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\nOr transfer the response content to any [`OutputStream`](https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n response.body().transferTo(Files.newOutputStream(Paths.get(path)));\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\n## Raw responses\n\nThe SDK defines methods that deserialize responses into instances of Java classes. However, these methods don\'t provide access to the response headers, status code, or the raw response body.\n\nTo access this data, prefix any HTTP method call on a client or service with `withRawResponse()`:\n\n```java\nimport com.beagle.api.core.http.Headers;\nimport com.beagle.api.core.http.HttpResponseFor;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\nHttpResponseFor plans = client.plans().withRawResponse().list();\n\nint statusCode = plans.statusCode();\nHeaders headers = plans.headers();\n```\n\nYou can still deserialize the response into an instance of a Java class if needed:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse parsedPlans = plans.parse();\n```\n\n## Error handling\n\nThe SDK throws custom unchecked exception types:\n\n- [`BeagleServiceException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleServiceException.kt): Base class for HTTP errors. See this table for which exception subclass is thrown for each HTTP status code:\n\n | Status | Exception |\n | ------ | -------------------------------------------------- |\n | 400 | [`BadRequestException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BadRequestException.kt) |\n | 401 | [`UnauthorizedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnauthorizedException.kt) |\n | 403 | [`PermissionDeniedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/PermissionDeniedException.kt) |\n | 404 | [`NotFoundException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/NotFoundException.kt) |\n | 422 | [`UnprocessableEntityException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnprocessableEntityException.kt) |\n | 429 | [`RateLimitException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/RateLimitException.kt) |\n | 5xx | [`InternalServerException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/InternalServerException.kt) |\n | others | [`UnexpectedStatusCodeException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnexpectedStatusCodeException.kt) |\n\n- [`BeagleIoException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleIoException.kt): I/O networking errors.\n\n- [`BeagleRetryableException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleRetryableException.kt): Generic error indicating a failure that could be retried by the client.\n\n- [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt): Failure to interpret successfully parsed data. For example, when accessing a property that\'s supposed to be required, but the API unexpectedly omitted it from the response.\n\n- [`BeagleException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleException.kt): Base class for all exceptions. Most errors will result in one of the previously mentioned ones, but completely generic errors may be thrown using the base class.\n\n\n\n## Logging\n\nThe SDK uses the standard [OkHttp logging interceptor](https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor).\n\nEnable logging by setting the `BEAGLE_LOG` environment variable to `info`:\n\n```sh\nexport BEAGLE_LOG=info\n```\n\nOr to `debug` for more verbose logging:\n\n```sh\nexport BEAGLE_LOG=debug\n```\n\n## ProGuard and R8\n\nAlthough the SDK uses reflection, it is still usable with [ProGuard](https://github.com/Guardsquare/proguard) and [R8](https://developer.android.com/topic/performance/app-optimization/enable-app-optimization) because `beagle-java-core` is published with a [configuration file](beagle-java-core/src/main/resources/META-INF/proguard/beagle-java-core.pro) containing [keep rules](https://www.guardsquare.com/manual/configuration/usage).\n\nProGuard and R8 should automatically detect and use the published rules, but you can also manually copy the keep rules if necessary.\n\n\n\n\n\n## Jackson\n\nThe SDK depends on [Jackson](https://github.com/FasterXML/jackson) for JSON serialization/deserialization. It is compatible with version 2.13.4 or higher, but depends on version 2.18.2 by default.\n\nThe SDK throws an exception if it detects an incompatible Jackson version at runtime (e.g. if the default version was overridden in your Maven or Gradle config).\n\nIf the SDK threw an exception, but you\'re _certain_ the version is compatible, then disable the version check using the `checkJacksonVersionCompatibility` on [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt).\n\n> [!CAUTION]\n> We make no guarantee that the SDK works correctly when the Jackson version check is disabled.\n\nAlso note that there are bugs in older Jackson versions that can affect the SDK. We don\'t work around all Jackson bugs ([example](https://github.com/FasterXML/jackson-databind/issues/3240)) and expect users to upgrade Jackson for those instead.\n\n## Network options\n\n### Retries\n\nThe SDK automatically retries 2 times by default, with a short exponential backoff between requests.\n\nOnly the following error types are retried:\n- Connection errors (for example, due to a network connectivity problem)\n- 408 Request Timeout\n- 409 Conflict\n- 429 Rate Limit\n- 5xx Internal\n\nThe API may also explicitly instruct the SDK to retry or not retry a request.\n\nTo set a custom number of retries, configure the client using the `maxRetries` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .maxRetries(4)\n .build();\n```\n\n### Timeouts\n\nRequests time out after 1 minute by default.\n\nTo set a custom timeout, configure the method call using the `timeout` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().timeout(Duration.ofSeconds(30)).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .timeout(Duration.ofSeconds(30))\n .build();\n```\n\n### Proxies\n\nTo route requests through a proxy, configure the client using the `proxy` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.net.InetSocketAddress;\nimport java.net.Proxy;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .proxy(new Proxy(\n Proxy.Type.HTTP, new InetSocketAddress(\n "https://example.com", 8080\n )\n ))\n .build();\n```\n\n### Connection pooling\n\nTo customize the underlying OkHttp connection pool, configure the client using the `maxIdleConnections` and `keepAliveDuration` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `maxIdleConnections` is set, then `keepAliveDuration` must be set, and vice versa.\n .maxIdleConnections(10)\n .keepAliveDuration(Duration.ofMinutes(2))\n .build();\n```\n\nIf both options are unset, OkHttp\'s default connection pool settings are used.\n\n### HTTPS\n\n> [!NOTE]\n> Most applications should not call these methods, and instead use the system defaults. The defaults include\n> special optimizations that can be lost if the implementations are modified.\n\nTo configure how HTTPS connections are secured, configure the client using the `sslSocketFactory`, `trustManager`, and `hostnameVerifier` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `sslSocketFactory` is set, then `trustManager` must be set, and vice versa.\n .sslSocketFactory(yourSSLSocketFactory)\n .trustManager(yourTrustManager)\n .hostnameVerifier(yourHostnameVerifier)\n .build();\n```\n\n### Environments\n\nThe SDK sends requests to the production by default. To send requests to a different environment, configure the client like so:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .staging()\n .build();\n```\n\n### Custom HTTP client\n\nThe SDK consists of three artifacts:\n- `beagle-java-core`\n - Contains core SDK logic\n - Does not depend on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleClient`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClient.kt), [`BeagleClientAsync`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsync.kt), [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt), and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), all of which can work with any HTTP client\n- `beagle-java-client-okhttp`\n - Depends on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) and [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), which provide a way to construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), respectively, using OkHttp\n- `beagle-java`\n - Depends on and exposes the APIs of both `beagle-java-core` and `beagle-java-client-okhttp`\n - Does not have its own logic\n\nThis structure allows replacing the SDK\'s default HTTP client without pulling in unnecessary dependencies.\n\n#### Customized [`OkHttpClient`](https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.html)\n\n> [!TIP]\n> Try the available [network options](#network-options) before replacing the default client.\n\nTo use a customized `OkHttpClient`:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Copy `beagle-java-client-okhttp`\'s [`OkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/OkHttpClient.kt) class into your code and customize it\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your customized client\n\n### Completely custom HTTP client\n\nTo use a completely custom HTTP client:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Write a class that implements the [`HttpClient`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpClient.kt) interface\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your new client class\n\n## Undocumented API functionality\n\nThe SDK is typed for convenient usage of the documented API. However, it also supports working with undocumented or not yet supported parts of the API.\n\n### Parameters\n\nTo set undocumented parameters, call the `putAdditionalHeader`, `putAdditionalQueryParam`, or `putAdditionalBodyProperty` methods on any `Params` class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder()\n .putAdditionalHeader("Secret-Header", "42")\n .putAdditionalQueryParam("secret_query_param", "42")\n .putAdditionalBodyProperty("secretProperty", JsonValue.from("42"))\n .build();\n```\n\nThese can be accessed on the built object later using the `_additionalHeaders()`, `_additionalQueryParams()`, and `_additionalBodyProperties()` methods.\n\nTo set undocumented parameters on _nested_ headers, query params, or body classes, call the `putAdditionalProperty` method on the nested class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.tenants.Address;\nimport com.beagle.api.models.tenants.TenantCreateParams;\n\nTenantCreateParams params = TenantCreateParams.builder()\n .address(Address.builder()\n .putAdditionalProperty("secretProperty", JsonValue.from("42"))\n .build())\n .build();\n```\n\nThese properties can be accessed on the nested built object later using the `_additionalProperties()` method.\n\nTo set a documented parameter or property to an undocumented or not yet supported _value_, pass a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) object to its setter:\n\n```java\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder().build();\n```\n\nThe most straightforward way to create a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) is using its `from(...)` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.List;\nimport java.util.Map;\n\n// Create primitive JSON values\nJsonValue nullValue = JsonValue.from(null);\nJsonValue booleanValue = JsonValue.from(true);\nJsonValue numberValue = JsonValue.from(42);\nJsonValue stringValue = JsonValue.from("Hello World!");\n\n// Create a JSON array value equivalent to `["Hello", "World"]`\nJsonValue arrayValue = JsonValue.from(List.of(\n "Hello", "World"\n));\n\n// Create a JSON object value equivalent to `{ "a": 1, "b": 2 }`\nJsonValue objectValue = JsonValue.from(Map.of(\n "a", 1,\n "b", 2\n));\n\n// Create an arbitrarily nested JSON equivalent to:\n// {\n// "a": [1, 2],\n// "b": [3, 4]\n// }\nJsonValue complexValue = JsonValue.from(Map.of(\n "a", List.of(\n 1, 2\n ),\n "b", List.of(\n 3, 4\n )\n));\n```\n\nNormally a `Builder` class\'s `build` method will throw [`IllegalStateException`](https://docs.oracle.com/javase/8/docs/api/java/lang/IllegalStateException.html) if any required parameter or property is unset.\n\nTo forcibly omit a required parameter or property, pass [`JsonMissing`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt):\n\n```java\nimport com.beagle.api.core.JsonMissing;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanRetrieveParams;\n\nPlanListParams params = PlanRetrieveParams.builder()\n .code(JsonMissing.of())\n .build();\n```\n\n### Response properties\n\nTo access undocumented response properties, call the `_additionalProperties()` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.Map;\n\nMap additionalProperties = client.plans().list(params)._additionalProperties();\nJsonValue secretPropertyValue = additionalProperties.get("secretProperty");\n\nString result = secretPropertyValue.accept(new JsonValue.Visitor<>() {\n @Override\n public String visitNull() {\n return "It\'s null!";\n }\n\n @Override\n public String visitBoolean(boolean value) {\n return "It\'s a boolean!";\n }\n\n @Override\n public String visitNumber(Number value) {\n return "It\'s a number!";\n }\n\n // Other methods include `visitMissing`, `visitString`, `visitArray`, and `visitObject`\n // The default implementation of each unimplemented method delegates to `visitDefault`, which throws by default, but can also be overridden\n});\n```\n\nTo access a property\'s raw JSON value, which may be undocumented, call its `_` prefixed method:\n\n```java\nimport com.beagle.api.core.JsonField;\nimport java.util.Optional;\n\nJsonField field = client.plans().list(params)._field();\n\nif (field.isMissing()) {\n // The property is absent from the JSON response\n} else if (field.isNull()) {\n // The property was set to literal null\n} else {\n // Check if value was provided as a string\n // Other methods include `asNumber()`, `asBoolean()`, etc.\n Optional jsonString = field.asString();\n\n // Try to deserialize into a custom type\n MyClass myObject = field.asUnknown().orElseThrow().convert(MyClass.class);\n}\n```\n\n### Response validation\n\nIn rare cases, the API may return a response that doesn\'t match the expected type. For example, the SDK may expect a property to contain a `String`, but the API could return something else.\n\nBy default, the SDK will not throw an exception in this case. It will throw [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt) only if you directly access the property.\n\nIf you would prefer to check that the response is completely well-typed upfront, then either call `validate()`:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(params).validate();\n```\n\nOr configure the method call to validate the response using the `responseValidation` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().responseValidation(true).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .responseValidation(true)\n .build();\n```\n\n## FAQ\n\n### Why don\'t you use plain `enum` classes?\n\nJava `enum` classes are not trivially [forwards compatible](https://www.stainless.com/blog/making-java-enums-forwards-compatible). Using them in the SDK could cause runtime exceptions if the API is updated to respond with a new enum value.\n\n### Why do you represent fields using `JsonField` instead of just plain `T`?\n\nUsing `JsonField` enables a few features:\n\n- Allowing usage of [undocumented API functionality](#undocumented-api-functionality)\n- Lazily [validating the API response against the expected shape](#response-validation)\n- Representing absent vs explicitly null values\n\n### Why don\'t you use [`data` classes](https://kotlinlang.org/docs/data-classes.html)?\n\nIt is not [backwards compatible to add new fields to a data class](https://kotlinlang.org/docs/api-guidelines-backward-compatibility.html#avoid-using-data-classes-in-your-api) and we don\'t want to introduce a breaking change every time we add a field to a class.\n\n### Why don\'t you use checked exceptions?\n\nChecked exceptions are widely considered a mistake in the Java programming language. In fact, they were omitted from Kotlin for this reason.\n\nChecked exceptions:\n\n- Are verbose to handle\n- Encourage error handling at the wrong level of abstraction, where nothing can be done about the error\n- Are tedious to propagate due to the [function coloring problem](https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function)\n- Don\'t play well with lambdas (also due to the function coloring problem)\n\n## Semantic versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n2. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/beagle-java/issues) with questions, bugs, or suggestions.\n', }, + { + language: 'csharp', + content: + '# Beagle C# API Library\n\nThe Beagle C# SDK provides convenient access to the Beagle REST API from applications written in C#.\n\n## Installation\n\n```bash\ngit clone git@github.com:stainless-sdks/beagle-csharp.git\ndotnet add reference beagle-csharp/src/Beagle\n```\n\n## Requirements\n\nThis library requires .NET Standard 2.0 or later.\n\n## Usage\n\nSee the [`examples`](examples) directory for complete and runnable examples.\n\n```csharp\nBeagleClient client = new();\n\nPlanListParams parameters = new();\n\nvar plans = await client.Plans.List(parameters);\n\nConsole.WriteLine(plans);\n```', + }, ]; const INDEX_OPTIONS = { From a964764acd8d0ff492707aee8b4aaeb0d25f261c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 3 Apr 2026 05:54:49 +0000 Subject: [PATCH 111/138] chore(internal): codegen related update --- packages/mcp-server/Dockerfile | 4 +++- packages/mcp-server/package.json | 2 +- packages/mcp-server/src/http.ts | 17 +++++++++++++---- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/packages/mcp-server/Dockerfile b/packages/mcp-server/Dockerfile index 476ae526..8f2567be 100644 --- a/packages/mcp-server/Dockerfile +++ b/packages/mcp-server/Dockerfile @@ -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/@corgi-tech/beagle FROM denoland/deno:alpine-2.7.1 diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 679acbc4..7cd44103 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -30,7 +30,7 @@ "fix": "eslint --fix ." }, "dependencies": { - "@corgi-tech/beagle": "file:../../dist/", + "@corgi-tech/beagle": "link:../../dist/", "ajv": "^8.18.0", "@cloudflare/cabidela": "^0.2.4", "@hono/node-server": "^1.19.10", diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index 414ae2ad..d3ea8db1 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -69,6 +69,11 @@ const newServer = async ({ } } + const mcpClientInfo = + typeof req.body?.params?.clientInfo?.name === 'string' ? + { name: req.body.params.clientInfo.name, version: String(req.body.params.clientInfo.version ?? '') } + : undefined; + await initMcpServer({ server: server, mcpOptions: effectiveMcpOptions, @@ -79,12 +84,13 @@ const newServer = async ({ stainlessApiKey: stainlessApiKey, upstreamClientEnvs, mcpSessionId: (req as any).mcpSessionId, - mcpClientInfo: - typeof req.body?.params?.clientInfo?.name === 'string' ? - { name: req.body.params.clientInfo.name, version: String(req.body.params.clientInfo.version ?? '') } - : undefined, + mcpClientInfo, }); + if (mcpClientInfo) { + getLogger().info({ mcpSessionId: (req as any).mcpSessionId, mcpClientInfo }, 'MCP client connected'); + } + return server; }; @@ -154,6 +160,9 @@ export const streamableHTTPApp = ({ app.use( pinoHttp({ logger: getLogger(), + customProps: (req) => ({ + mcpSessionId: (req as any).mcpSessionId, + }), customLogLevel: (req, res) => { if (res.statusCode >= 500) { return 'error'; From 3b62b6d6f4dccf2b11aec39e363fae8ebc9f1e60 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 3 Apr 2026 17:31:57 +0000 Subject: [PATCH 112/138] feat(api): api update --- .stats.yml | 4 ++-- packages/mcp-server/src/local-docs-search.ts | 18 +++++++++--------- src/resources/enrollments.ts | 16 +++++----------- tests/api-resources/enrollments.test.ts | 3 +-- 4 files changed, 17 insertions(+), 24 deletions(-) diff --git a/.stats.yml b/.stats.yml index 0cda3249..36756eae 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 18 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-2be66f33121d1e682b2b34d3594a529e13e21c97a51c5778f18845d24273d76d.yml -openapi_spec_hash: 58b42d9f6c1caa1030e9461f26b95d94 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-80d24d74d981ca13dc9b4bbaa9499e9b5d85d7b03c0d6064009496e06e24f4d0.yml +openapi_spec_hash: 0919b932a6281e50ea3a24cd15167f1b config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index f9c96af2..5a8c3fdd 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -820,48 +820,48 @@ const EMBEDDED_METHODS: MethodEntry[] = [ 'effectiveDate: string;', 'plan: string;', 'propertyManagerId: number;', - 'status: string;', 'tenantId: number;', 'note?: string;', + "status?: 'Premium Paying' | 'Issued, Not Paid';", ], response: '{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }', markdown: - "## create\n\n`client.enrollments.create(effectiveDate: string, plan: string, propertyManagerId: number, status: string, tenantId: number, note?: string): { data: enrollment; success: true; }`\n\n**post** `/api/enrollments`\n\ncreate a new enrollment for a tenant.\n\n### Parameters\n\n- `effectiveDate: string`\n the date the enrollment will begin, note enrollments cannot begin in the past\n\n- `plan: string`\n the plan name/code\n\n- `propertyManagerId: number`\n\n- `status: string`\n\n- `tenantId: number`\n\n- `note?: string`\n an optional note field, this can be used for easily appending metadata to enrollments\n\n### Returns\n\n- `{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }`\n\n - `data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollment = await client.enrollments.create({\n effectiveDate: 'effectiveDate',\n plan: 'plan',\n propertyManagerId: 0,\n status: 'Premium Paying',\n tenantId: 0,\n});\n\nconsole.log(enrollment);\n```", + "## create\n\n`client.enrollments.create(effectiveDate: string, plan: string, propertyManagerId: number, tenantId: number, note?: string, status?: 'Premium Paying' | 'Issued, Not Paid'): { data: enrollment; success: true; }`\n\n**post** `/api/enrollments`\n\ncreate a new enrollment for a tenant.\n\n### Parameters\n\n- `effectiveDate: string`\n the date the enrollment will begin, note enrollments cannot begin in the past\n\n- `plan: string`\n the plan name/code\n\n- `propertyManagerId: number`\n\n- `tenantId: number`\n\n- `note?: string`\n an optional note field, this can be used for easily appending metadata to enrollments\n\n- `status?: 'Premium Paying' | 'Issued, Not Paid'`\n the enrollment status — defaults to 'Issued, Not Paid' if not provided\n\n### Returns\n\n- `{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }`\n\n - `data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollment = await client.enrollments.create({\n effectiveDate: 'effectiveDate',\n plan: 'plan',\n propertyManagerId: 0,\n tenantId: 0,\n});\n\nconsole.log(enrollment);\n```", perLanguage: { csharp: { method: 'Enrollments.Create', example: - 'EnrollmentCreateParams parameters = new()\n{\n EffectiveDate = "effectiveDate",\n Plan = "plan",\n PropertyManagerID = 0,\n Status = Status.PremiumPaying,\n TenantID = 0,\n};\n\nvar enrollment = await client.Enrollments.Create(parameters);\n\nConsole.WriteLine(enrollment);', + 'EnrollmentCreateParams parameters = new()\n{\n EffectiveDate = "effectiveDate",\n Plan = "plan",\n PropertyManagerID = 0,\n TenantID = 0,\n};\n\nvar enrollment = await client.Enrollments.Create(parameters);\n\nConsole.WriteLine(enrollment);', }, go: { method: 'client.Enrollments.New', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tenrollment, err := client.Enrollments.New(context.TODO(), beagle.EnrollmentNewParams{\n\t\tEffectiveDate: "effectiveDate",\n\t\tPlan: "plan",\n\t\tPropertyManagerID: 0,\n\t\tStatus: beagle.EnrollmentNewParamsStatusPremiumPaying,\n\t\tTenantID: 0,\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", enrollment.Data)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tenrollment, err := client.Enrollments.New(context.TODO(), beagle.EnrollmentNewParams{\n\t\tEffectiveDate: "effectiveDate",\n\t\tPlan: "plan",\n\t\tPropertyManagerID: 0,\n\t\tTenantID: 0,\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", enrollment.Data)\n}\n', }, http: { example: - 'curl https://developer.beagleforpm.com/api/enrollments \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "effectiveDate": "effectiveDate",\n "plan": "plan",\n "propertyManagerId": 0,\n "status": "Premium Paying",\n "tenantId": 0\n }\'', + 'curl https://developer.beagleforpm.com/api/enrollments \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "effectiveDate": "effectiveDate",\n "plan": "plan",\n "propertyManagerId": 0,\n "tenantId": 0\n }\'', }, java: { method: 'enrollments().create', example: - 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.enrollments.EnrollmentCreateParams;\nimport com.beagle.api.models.enrollments.EnrollmentCreateResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n EnrollmentCreateParams params = EnrollmentCreateParams.builder()\n .effectiveDate("2025-11-10T19:50:20.638Z")\n .plan("TLL_100K_CONTENTS_5K_ACV")\n .propertyManagerId(123.0)\n .status(EnrollmentCreateParams.Status.ISSUED_NOT_PAID)\n .tenantId(123.0)\n .build();\n EnrollmentCreateResponse enrollment = client.enrollments().create(params);\n }\n}', + 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.enrollments.EnrollmentCreateParams;\nimport com.beagle.api.models.enrollments.EnrollmentCreateResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n EnrollmentCreateParams params = EnrollmentCreateParams.builder()\n .effectiveDate("2025-11-10T19:50:20.638Z")\n .plan("TLL_100K_CONTENTS_5K_ACV")\n .propertyManagerId(123.0)\n .tenantId(123.0)\n .build();\n EnrollmentCreateResponse enrollment = client.enrollments().create(params);\n }\n}', }, python: { method: 'enrollments.create', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nenrollment = client.enrollments.create(\n effective_date="effectiveDate",\n plan="plan",\n property_manager_id=0,\n status="Premium Paying",\n tenant_id=0,\n)\nprint(enrollment.data)', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nenrollment = client.enrollments.create(\n effective_date="effectiveDate",\n plan="plan",\n property_manager_id=0,\n tenant_id=0,\n)\nprint(enrollment.data)', }, ruby: { method: 'enrollments.create', example: - 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nenrollment = beagle.enrollments.create(\n effective_date: "effectiveDate",\n plan: "plan",\n property_manager_id: 0,\n status: :"Premium Paying",\n tenant_id: 0\n)\n\nputs(enrollment)', + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nenrollment = beagle.enrollments.create(\n effective_date: "effectiveDate",\n plan: "plan",\n property_manager_id: 0,\n tenant_id: 0\n)\n\nputs(enrollment)', }, typescript: { method: 'client.enrollments.create', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst enrollment = await client.enrollments.create({\n effectiveDate: 'effectiveDate',\n plan: 'plan',\n propertyManagerId: 0,\n status: 'Premium Paying',\n tenantId: 0,\n});\n\nconsole.log(enrollment.data);", + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst enrollment = await client.enrollments.create({\n effectiveDate: 'effectiveDate',\n plan: 'plan',\n propertyManagerId: 0,\n tenantId: 0,\n});\n\nconsole.log(enrollment.data);", }, }, }, diff --git a/src/resources/enrollments.ts b/src/resources/enrollments.ts index 2a019e34..8f9c9740 100644 --- a/src/resources/enrollments.ts +++ b/src/resources/enrollments.ts @@ -21,7 +21,6 @@ export class Enrollments extends APIResource { * effectiveDate: 'effectiveDate', * plan: 'plan', * propertyManagerId: 0, - * status: 'Premium Paying', * tenantId: 0, * }); * ``` @@ -168,16 +167,6 @@ export interface EnrollmentCreateParams { propertyManagerId: number; - status: - | 'Premium Paying' - | 'Issued, Not Paid' - | 'Expired' - | 'Lapsed' - | 'Suspended' - | 'Cancelled' - | 'Not taken' - | 'Declined'; - tenantId: number; /** @@ -185,6 +174,11 @@ export interface EnrollmentCreateParams { * enrollments */ note?: string; + + /** + * the enrollment status — defaults to 'Issued, Not Paid' if not provided + */ + status?: 'Premium Paying' | 'Issued, Not Paid'; } export interface EnrollmentListParams { diff --git a/tests/api-resources/enrollments.test.ts b/tests/api-resources/enrollments.test.ts index c733c4a3..d4ad8899 100644 --- a/tests/api-resources/enrollments.test.ts +++ b/tests/api-resources/enrollments.test.ts @@ -14,7 +14,6 @@ describe('resource enrollments', () => { effectiveDate: 'effectiveDate', plan: 'plan', propertyManagerId: 0, - status: 'Premium Paying', tenantId: 0, }); const rawResponse = await responsePromise.asResponse(); @@ -32,9 +31,9 @@ describe('resource enrollments', () => { effectiveDate: 'effectiveDate', plan: 'plan', propertyManagerId: 0, - status: 'Premium Paying', tenantId: 0, note: 'note', + status: 'Premium Paying', }); }); From f8e55dc9a6aca74d52d2137f9c4ef711801a818d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 08:34:51 +0000 Subject: [PATCH 113/138] chore(internal): codegen related update --- packages/mcp-server/src/instructions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mcp-server/src/instructions.ts b/packages/mcp-server/src/instructions.ts index f3086d66..ef0b6936 100644 --- a/packages/mcp-server/src/instructions.ts +++ b/packages/mcp-server/src/instructions.ts @@ -1,8 +1,8 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import fs from 'fs/promises'; -import { readEnv } from './util'; import { getLogger } from './logger'; +import { readEnv } from './util'; const INSTRUCTIONS_CACHE_TTL_MS = 15 * 60 * 1000; // 15 minutes From ac3f8d44484c8467f83f3cd1bc59c68b0221406d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 11:29:27 +0000 Subject: [PATCH 114/138] chore(mcp-server): increase local docs search result count from 5 to 10 --- packages/mcp-server/src/docs-search-tool.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mcp-server/src/docs-search-tool.ts b/packages/mcp-server/src/docs-search-tool.ts index eed209aa..73325b7d 100644 --- a/packages/mcp-server/src/docs-search-tool.ts +++ b/packages/mcp-server/src/docs-search-tool.ts @@ -63,7 +63,7 @@ async function searchLocal(args: Record): Promise { query, language, detail, - maxResults: 5, + maxResults: 10, }).results; } From 37310585b45733f820ba36bf7accd30b5abe2c30 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 11:31:23 +0000 Subject: [PATCH 115/138] chore(internal): codegen related update --- packages/mcp-server/src/util.ts | 4 ++-- src/internal/utils/env.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/mcp-server/src/util.ts b/packages/mcp-server/src/util.ts index 40ed5501..069a2b47 100644 --- a/packages/mcp-server/src/util.ts +++ b/packages/mcp-server/src/util.ts @@ -2,9 +2,9 @@ export const readEnv = (env: string): string | undefined => { if (typeof (globalThis as any).process !== 'undefined') { - return (globalThis as any).process.env?.[env]?.trim(); + return (globalThis as any).process.env?.[env]?.trim() || undefined; } else if (typeof (globalThis as any).Deno !== 'undefined') { - return (globalThis as any).Deno.env?.get?.(env)?.trim(); + return (globalThis as any).Deno.env?.get?.(env)?.trim() || undefined; } return; }; diff --git a/src/internal/utils/env.ts b/src/internal/utils/env.ts index 2d848007..cc5fa0fa 100644 --- a/src/internal/utils/env.ts +++ b/src/internal/utils/env.ts @@ -9,10 +9,10 @@ */ export const readEnv = (env: string): string | undefined => { if (typeof (globalThis as any).process !== 'undefined') { - return (globalThis as any).process.env?.[env]?.trim() ?? undefined; + return (globalThis as any).process.env?.[env]?.trim() || undefined; } if (typeof (globalThis as any).Deno !== 'undefined') { - return (globalThis as any).Deno.env?.get?.(env)?.trim(); + return (globalThis as any).Deno.env?.get?.(env)?.trim() || undefined; } return undefined; }; From e9f78b10d52231401dab603ec28a5c934063dc9a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 11:45:46 +0000 Subject: [PATCH 116/138] chore(internal): codegen related update --- packages/mcp-server/src/code-tool-worker.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/mcp-server/src/code-tool-worker.ts b/packages/mcp-server/src/code-tool-worker.ts index 3114b99e..fb2e9a40 100644 --- a/packages/mcp-server/src/code-tool-worker.ts +++ b/packages/mcp-server/src/code-tool-worker.ts @@ -202,7 +202,8 @@ function makeSdkProxy(obj: T, { path, isBelievedBad = false }: function parseError(code: string, error: unknown): string | undefined { if (!(error instanceof Error)) return; - const message = error.name ? `${error.name}: ${error.message}` : error.message; + const cause = error.cause instanceof Error ? `: ${error.cause.message}` : ''; + const message = error.name ? `${error.name}: ${error.message}${cause}` : `${error.message}${cause}`; try { // Deno uses V8; the first ":LINE:COLUMN" is the top of stack. const lineNumber = error.stack?.match(/:([0-9]+):[0-9]+/)?.[1]; From 46f241ecc68ec680b7ce8b1f4e6971328a95b625 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 11 Apr 2026 09:37:33 +0000 Subject: [PATCH 117/138] chore(internal): codegen related update --- packages/mcp-server/src/local-docs-search.ts | 44 +++++++++---------- src/resources/enrollments.ts | 8 ++-- src/resources/property-managers.ts | 18 ++++---- src/resources/tenants.ts | 14 +++--- tests/api-resources/enrollments.test.ts | 18 ++++---- tests/api-resources/property-managers.test.ts | 40 ++++++++--------- tests/api-resources/tenants.test.ts | 32 +++++++------- 7 files changed, 87 insertions(+), 87 deletions(-) diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 5a8c3fdd..4042376d 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -369,21 +369,21 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: '{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }', markdown: - "## create\n\n`client.propertyManagers.create(addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[], contacts: { email: string; name: object; phone?: string; }[], name: string, clickWrapAt?: number): { data: property_manager; success: true; }`\n\n**post** `/api/property-managers`\n\ncreate a new property manager.\n\n### Parameters\n\n- `addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]`\n street addresses for each Property\n\n- `contacts: { email: string; name: { first: string; last: string; }; phone?: string; }[]`\n contact information for each Property Manager\n\n- `name: string`\n name of the Property Management Company\n\n- `clickWrapAt?: number`\n unix timestamp (ms) of clickwrap agreement signature\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.create({\n addresses: [{\n city: 'city',\n state: 'xx',\n street1: 'street1',\n zip: '60513',\n kind: 'billing',\n}],\n contacts: [{\n email: 'dev@stainless.com',\n name: { first: 'first', last: 'last' },\n kind: 'agreements',\n}],\n name: 'name',\n});\n\nconsole.log(propertyManager);\n```", + "## create\n\n`client.propertyManagers.create(addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[], contacts: { email: string; name: object; phone?: string; }[], name: string, clickWrapAt?: number): { data: property_manager; success: true; }`\n\n**post** `/api/property-managers`\n\ncreate a new property manager.\n\n### Parameters\n\n- `addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]`\n street addresses for each Property\n\n- `contacts: { email: string; name: { first: string; last: string; }; phone?: string; }[]`\n contact information for each Property Manager\n\n- `name: string`\n name of the Property Management Company\n\n- `clickWrapAt?: number`\n unix timestamp (ms) of clickwrap agreement signature\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.create({\n addresses: [{\n city: 'South Salt Lake',\n state: 'UT',\n street1: '123 Electric Ave.',\n zip: '84115',\n kind: 'place of business',\n}],\n contacts: [{\n email: 'mr.milchick@example.com',\n name: { first: 'Seth', last: 'Milchick' },\n kind: 'reporting',\n}],\n name: 'Lumon Apartments',\n});\n\nconsole.log(propertyManager);\n```", perLanguage: { csharp: { method: 'PropertyManagers.Create', example: - 'PropertyManagerCreateParams parameters = new()\n{\n Addresses =\n [\n new()\n {\n City = "city",\n State = "xx",\n Street1 = "street1",\n Zip = "60513",\n Street2 = "street2",\n Kind = Kind.Billing,\n },\n ],\n Contacts =\n [\n new()\n {\n Email = "dev@stainless.com",\n Name = new()\n {\n First = "first",\n Last = "last",\n },\n Phone = "phone",\n Kind = Kind.Agreements,\n },\n ],\n Name = "name",\n};\n\nvar propertyManager = await client.PropertyManagers.Create(parameters);\n\nConsole.WriteLine(propertyManager);', + 'PropertyManagerCreateParams parameters = new()\n{\n Addresses =\n [\n new()\n {\n City = "South Salt Lake",\n State = "UT",\n Street1 = "123 Electric Ave.",\n Zip = "84115",\n Street2 = "street2",\n Kind = Kind.PlaceOfBusiness,\n },\n ],\n Contacts =\n [\n new()\n {\n Email = "mr.milchick@example.com",\n Name = new()\n {\n First = "Seth",\n Last = "Milchick",\n },\n Phone = "(123) 456-7890",\n Kind = Kind.Reporting,\n },\n ],\n Name = "Lumon Apartments",\n};\n\nvar propertyManager = await client.PropertyManagers.Create(parameters);\n\nConsole.WriteLine(propertyManager);', }, go: { method: 'client.PropertyManagers.New', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tpropertyManager, err := client.PropertyManagers.New(context.TODO(), beagle.PropertyManagerNewParams{\n\t\tAddresses: []beagle.PropertyManagerNewParamsAddress{{\n\t\t\tAddressParam: beagle.AddressParam{\n\t\t\t\tCity: "city",\n\t\t\t\tState: "xx",\n\t\t\t\tStreet1: "street1",\n\t\t\t\tZip: "60513",\n\t\t\t},\n\t\t\tKind: "billing",\n\t\t}},\n\t\tContacts: []beagle.PropertyManagerNewParamsContact{{\n\t\t\tContactParam: beagle.ContactParam{\n\t\t\t\tEmail: "dev@stainless.com",\n\t\t\t\tName: beagle.ContactNameParam{\n\t\t\t\t\tFirst: "first",\n\t\t\t\t\tLast: "last",\n\t\t\t\t},\n\t\t\t},\n\t\t\tKind: "agreements",\n\t\t}},\n\t\tName: "name",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", propertyManager.Data)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tpropertyManager, err := client.PropertyManagers.New(context.TODO(), beagle.PropertyManagerNewParams{\n\t\tAddresses: []beagle.PropertyManagerNewParamsAddress{{\n\t\t\tAddressParam: beagle.AddressParam{\n\t\t\t\tCity: "South Salt Lake",\n\t\t\t\tState: "UT",\n\t\t\t\tStreet1: "123 Electric Ave.",\n\t\t\t\tZip: "84115",\n\t\t\t},\n\t\t\tKind: "place of business",\n\t\t}},\n\t\tContacts: []beagle.PropertyManagerNewParamsContact{{\n\t\t\tContactParam: beagle.ContactParam{\n\t\t\t\tEmail: "mr.milchick@example.com",\n\t\t\t\tName: beagle.ContactNameParam{\n\t\t\t\t\tFirst: "Seth",\n\t\t\t\t\tLast: "Milchick",\n\t\t\t\t},\n\t\t\t},\n\t\t\tKind: "reporting",\n\t\t}},\n\t\tName: "Lumon Apartments",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", propertyManager.Data)\n}\n', }, http: { example: - 'curl https://developer.beagleforpm.com/api/property-managers \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "addresses": [\n {\n "city": "city",\n "state": "xx",\n "street1": "street1",\n "zip": "60513",\n "kind": "billing"\n }\n ],\n "contacts": [\n {\n "email": "dev@stainless.com",\n "name": {\n "first": "first",\n "last": "last"\n },\n "kind": "agreements"\n }\n ],\n "name": "name"\n }\'', + 'curl https://developer.beagleforpm.com/api/property-managers \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "addresses": [\n {\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Electric Ave.",\n "zip": "84115",\n "kind": "place of business"\n }\n ],\n "contacts": [\n {\n "email": "mr.milchick@example.com",\n "name": {\n "first": "Seth",\n "last": "Milchick"\n },\n "phone": "(123) 456-7890",\n "kind": "reporting"\n }\n ],\n "name": "Lumon Apartments"\n }\'', }, java: { method: 'propertyManagers().create', @@ -393,17 +393,17 @@ const EMBEDDED_METHODS: MethodEntry[] = [ python: { method: 'property_managers.create', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nproperty_manager = client.property_managers.create(\n addresses=[{\n "city": "city",\n "state": "xx",\n "street1": "street1",\n "zip": "60513",\n "kind": "billing",\n }],\n contacts=[{\n "email": "dev@stainless.com",\n "name": {\n "first": "first",\n "last": "last",\n },\n "kind": "agreements",\n }],\n name="name",\n)\nprint(property_manager.data)', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nproperty_manager = client.property_managers.create(\n addresses=[{\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Electric Ave.",\n "zip": "84115",\n "kind": "place of business",\n }],\n contacts=[{\n "email": "mr.milchick@example.com",\n "name": {\n "first": "Seth",\n "last": "Milchick",\n },\n "kind": "reporting",\n }],\n name="Lumon Apartments",\n)\nprint(property_manager.data)', }, ruby: { method: 'property_managers.create', example: - 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nproperty_manager = beagle.property_managers.create(\n addresses: [{city: "city", state: "xx", street1: "street1", zip: "60513", kind: :billing}],\n contacts: [{email: "dev@stainless.com", name: {first: "first", last: "last"}, kind: :agreements}],\n name: "name"\n)\n\nputs(property_manager)', + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nproperty_manager = beagle.property_managers.create(\n addresses: [\n {city: "South Salt Lake", state: "UT", street1: "123 Electric Ave.", zip: "84115", kind: :"place of business"}\n ],\n contacts: [{email: "mr.milchick@example.com", name: {first: "Seth", last: "Milchick"}, kind: :reporting}],\n name: "Lumon Apartments"\n)\n\nputs(property_manager)', }, typescript: { method: 'client.propertyManagers.create', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst propertyManager = await client.propertyManagers.create({\n addresses: [\n {\n city: 'city',\n state: 'xx',\n street1: 'street1',\n zip: '60513',\n kind: 'billing',\n },\n ],\n contacts: [\n {\n email: 'dev@stainless.com',\n name: { first: 'first', last: 'last' },\n kind: 'agreements',\n },\n ],\n name: 'name',\n});\n\nconsole.log(propertyManager.data);", + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst propertyManager = await client.propertyManagers.create({\n addresses: [\n {\n city: 'South Salt Lake',\n state: 'UT',\n street1: '123 Electric Ave.',\n zip: '84115',\n kind: 'place of business',\n },\n ],\n contacts: [\n {\n email: 'mr.milchick@example.com',\n name: { first: 'Seth', last: 'Milchick' },\n kind: 'reporting',\n },\n ],\n name: 'Lumon Apartments',\n});\n\nconsole.log(propertyManager.data);", }, }, }, @@ -621,21 +621,21 @@ const EMBEDDED_METHODS: MethodEntry[] = [ ], response: '{ data: { id: number; address: address; contact: contact; }; success: true; }', markdown: - "## create\n\n`client.tenants.create(address: { city: string; state: string; street1: string; zip: string; street2?: string; }, contact: { email: string; name: object; phone?: string; }, propertyManagerId: number): { data: tenant; success: true; }`\n\n**post** `/api/tenants`\n\ncreate a new tenant.\n\n### Parameters\n\n- `address: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `city: string`\n - `state: string`\n two letter state code, ie CA\n - `street1: string`\n - `zip: string`\n 5 digit US zip code, ie 94104\n - `street2?: string`\n\n- `contact: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `email: string`\n - `name: { first: string; last: string; }`\n - `phone?: string`\n\n- `propertyManagerId: number`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.create({\n address: {\n city: 'city',\n state: 'xx',\n street1: 'street1',\n zip: '60513',\n},\n contact: {\n email: 'dev@stainless.com',\n name: { first: 'first', last: 'last' },\n},\n propertyManagerId: 0,\n});\n\nconsole.log(tenant);\n```", + "## create\n\n`client.tenants.create(address: { city: string; state: string; street1: string; zip: string; street2?: string; }, contact: { email: string; name: object; phone?: string; }, propertyManagerId: number): { data: tenant; success: true; }`\n\n**post** `/api/tenants`\n\ncreate a new tenant.\n\n### Parameters\n\n- `address: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `city: string`\n - `state: string`\n two letter state code, ie CA\n - `street1: string`\n - `zip: string`\n 5 digit US zip code, ie 94104\n - `street2?: string`\n\n- `contact: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `email: string`\n - `name: { first: string; last: string; }`\n - `phone?: string`\n\n- `propertyManagerId: number`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.create({\n address: {\n city: 'South Salt Lake',\n state: 'UT',\n street1: '123 Main St.',\n zip: '84115',\n},\n contact: {\n email: 'mark.s@example.com',\n name: { first: 'Mark', last: 'Scout' },\n},\n propertyManagerId: 123,\n});\n\nconsole.log(tenant);\n```", perLanguage: { csharp: { method: 'Tenants.Create', example: - 'TenantCreateParams parameters = new()\n{\n Address = new()\n {\n City = "city",\n State = "xx",\n Street1 = "street1",\n Zip = "60513",\n Street2 = "street2",\n },\n Contact = new()\n {\n Email = "dev@stainless.com",\n Name = new()\n {\n First = "first",\n Last = "last",\n },\n Phone = "phone",\n },\n PropertyManagerID = 0,\n};\n\nvar tenant = await client.Tenants.Create(parameters);\n\nConsole.WriteLine(tenant);', + 'TenantCreateParams parameters = new()\n{\n Address = new()\n {\n City = "South Salt Lake",\n State = "UT",\n Street1 = "123 Main St.",\n Zip = "84115",\n Street2 = "Unit 3",\n },\n Contact = new()\n {\n Email = "mark.s@example.com",\n Name = new()\n {\n First = "Mark",\n Last = "Scout",\n },\n Phone = "(123) 456-7890",\n },\n PropertyManagerID = 123,\n};\n\nvar tenant = await client.Tenants.Create(parameters);\n\nConsole.WriteLine(tenant);', }, go: { method: 'client.Tenants.New', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\ttenant, err := client.Tenants.New(context.TODO(), beagle.TenantNewParams{\n\t\tAddress: beagle.AddressParam{\n\t\t\tCity: "city",\n\t\t\tState: "xx",\n\t\t\tStreet1: "street1",\n\t\t\tZip: "60513",\n\t\t},\n\t\tContact: beagle.ContactParam{\n\t\t\tEmail: "dev@stainless.com",\n\t\t\tName: beagle.ContactNameParam{\n\t\t\t\tFirst: "first",\n\t\t\t\tLast: "last",\n\t\t\t},\n\t\t},\n\t\tPropertyManagerID: 0,\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", tenant.Data)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\ttenant, err := client.Tenants.New(context.TODO(), beagle.TenantNewParams{\n\t\tAddress: beagle.AddressParam{\n\t\t\tCity: "South Salt Lake",\n\t\t\tState: "UT",\n\t\t\tStreet1: "123 Main St.",\n\t\t\tZip: "84115",\n\t\t},\n\t\tContact: beagle.ContactParam{\n\t\t\tEmail: "mark.s@example.com",\n\t\t\tName: beagle.ContactNameParam{\n\t\t\t\tFirst: "Mark",\n\t\t\t\tLast: "Scout",\n\t\t\t},\n\t\t},\n\t\tPropertyManagerID: 123,\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", tenant.Data)\n}\n', }, http: { example: - 'curl https://developer.beagleforpm.com/api/tenants \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "address": {\n "city": "city",\n "state": "xx",\n "street1": "street1",\n "zip": "60513"\n },\n "contact": {\n "email": "dev@stainless.com",\n "name": {\n "first": "first",\n "last": "last"\n }\n },\n "propertyManagerId": 0\n }\'', + 'curl https://developer.beagleforpm.com/api/tenants \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "address": {\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Main St.",\n "zip": "84115",\n "street2": "Unit 3"\n },\n "contact": {\n "email": "mark.s@example.com",\n "name": {\n "first": "Mark",\n "last": "Scout"\n },\n "phone": "(123) 456-7890"\n },\n "propertyManagerId": 123\n }\'', }, java: { method: 'tenants().create', @@ -645,17 +645,17 @@ const EMBEDDED_METHODS: MethodEntry[] = [ python: { method: 'tenants.create', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\ntenant = client.tenants.create(\n address={\n "city": "city",\n "state": "xx",\n "street1": "street1",\n "zip": "60513",\n },\n contact={\n "email": "dev@stainless.com",\n "name": {\n "first": "first",\n "last": "last",\n },\n },\n property_manager_id=0,\n)\nprint(tenant.data)', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\ntenant = client.tenants.create(\n address={\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Main St.",\n "zip": "84115",\n },\n contact={\n "email": "mark.s@example.com",\n "name": {\n "first": "Mark",\n "last": "Scout",\n },\n },\n property_manager_id=123,\n)\nprint(tenant.data)', }, ruby: { method: 'tenants.create', example: - 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\ntenant = beagle.tenants.create(\n address: {city: "city", state: "xx", street1: "street1", zip: "60513"},\n contact: {email: "dev@stainless.com", name: {first: "first", last: "last"}},\n property_manager_id: 0\n)\n\nputs(tenant)', + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\ntenant = beagle.tenants.create(\n address: {city: "South Salt Lake", state: "UT", street1: "123 Main St.", zip: "84115"},\n contact: {email: "mark.s@example.com", name: {first: "Mark", last: "Scout"}},\n property_manager_id: 123\n)\n\nputs(tenant)', }, typescript: { method: 'client.tenants.create', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst tenant = await client.tenants.create({\n address: {\n city: 'city',\n state: 'xx',\n street1: 'street1',\n zip: '60513',\n },\n contact: {\n email: 'dev@stainless.com',\n name: { first: 'first', last: 'last' },\n },\n propertyManagerId: 0,\n});\n\nconsole.log(tenant.data);", + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst tenant = await client.tenants.create({\n address: {\n city: 'South Salt Lake',\n state: 'UT',\n street1: '123 Main St.',\n zip: '84115',\n },\n contact: {\n email: 'mark.s@example.com',\n name: { first: 'Mark', last: 'Scout' },\n },\n propertyManagerId: 123,\n});\n\nconsole.log(tenant.data);", }, }, }, @@ -827,21 +827,21 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: '{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }', markdown: - "## create\n\n`client.enrollments.create(effectiveDate: string, plan: string, propertyManagerId: number, tenantId: number, note?: string, status?: 'Premium Paying' | 'Issued, Not Paid'): { data: enrollment; success: true; }`\n\n**post** `/api/enrollments`\n\ncreate a new enrollment for a tenant.\n\n### Parameters\n\n- `effectiveDate: string`\n the date the enrollment will begin, note enrollments cannot begin in the past\n\n- `plan: string`\n the plan name/code\n\n- `propertyManagerId: number`\n\n- `tenantId: number`\n\n- `note?: string`\n an optional note field, this can be used for easily appending metadata to enrollments\n\n- `status?: 'Premium Paying' | 'Issued, Not Paid'`\n the enrollment status — defaults to 'Issued, Not Paid' if not provided\n\n### Returns\n\n- `{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }`\n\n - `data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollment = await client.enrollments.create({\n effectiveDate: 'effectiveDate',\n plan: 'plan',\n propertyManagerId: 0,\n tenantId: 0,\n});\n\nconsole.log(enrollment);\n```", + "## create\n\n`client.enrollments.create(effectiveDate: string, plan: string, propertyManagerId: number, tenantId: number, note?: string, status?: 'Premium Paying' | 'Issued, Not Paid'): { data: enrollment; success: true; }`\n\n**post** `/api/enrollments`\n\ncreate a new enrollment for a tenant.\n\n### Parameters\n\n- `effectiveDate: string`\n the date the enrollment will begin, note enrollments cannot begin in the past\n\n- `plan: string`\n the plan name/code\n\n- `propertyManagerId: number`\n\n- `tenantId: number`\n\n- `note?: string`\n an optional note field, this can be used for easily appending metadata to enrollments\n\n- `status?: 'Premium Paying' | 'Issued, Not Paid'`\n the enrollment status — defaults to 'Issued, Not Paid' if not provided\n\n### Returns\n\n- `{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }`\n\n - `data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollment = await client.enrollments.create({\n effectiveDate: '2025-11-10T19:50:20.638Z',\n plan: 'TLL_100K_CONTENTS_5K_ACV',\n propertyManagerId: 123,\n tenantId: 123,\n});\n\nconsole.log(enrollment);\n```", perLanguage: { csharp: { method: 'Enrollments.Create', example: - 'EnrollmentCreateParams parameters = new()\n{\n EffectiveDate = "effectiveDate",\n Plan = "plan",\n PropertyManagerID = 0,\n TenantID = 0,\n};\n\nvar enrollment = await client.Enrollments.Create(parameters);\n\nConsole.WriteLine(enrollment);', + 'EnrollmentCreateParams parameters = new()\n{\n EffectiveDate = "2025-11-10T19:50:20.638Z",\n Plan = "TLL_100K_CONTENTS_5K_ACV",\n PropertyManagerID = 123,\n TenantID = 123,\n};\n\nvar enrollment = await client.Enrollments.Create(parameters);\n\nConsole.WriteLine(enrollment);', }, go: { method: 'client.Enrollments.New', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tenrollment, err := client.Enrollments.New(context.TODO(), beagle.EnrollmentNewParams{\n\t\tEffectiveDate: "effectiveDate",\n\t\tPlan: "plan",\n\t\tPropertyManagerID: 0,\n\t\tTenantID: 0,\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", enrollment.Data)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tenrollment, err := client.Enrollments.New(context.TODO(), beagle.EnrollmentNewParams{\n\t\tEffectiveDate: "2025-11-10T19:50:20.638Z",\n\t\tPlan: "TLL_100K_CONTENTS_5K_ACV",\n\t\tPropertyManagerID: 123,\n\t\tTenantID: 123,\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", enrollment.Data)\n}\n', }, http: { example: - 'curl https://developer.beagleforpm.com/api/enrollments \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "effectiveDate": "effectiveDate",\n "plan": "plan",\n "propertyManagerId": 0,\n "tenantId": 0\n }\'', + 'curl https://developer.beagleforpm.com/api/enrollments \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "effectiveDate": "2025-11-10T19:50:20.638Z",\n "plan": "TLL_100K_CONTENTS_5K_ACV",\n "propertyManagerId": 123,\n "tenantId": 123\n }\'', }, java: { method: 'enrollments().create', @@ -851,17 +851,17 @@ const EMBEDDED_METHODS: MethodEntry[] = [ python: { method: 'enrollments.create', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nenrollment = client.enrollments.create(\n effective_date="effectiveDate",\n plan="plan",\n property_manager_id=0,\n tenant_id=0,\n)\nprint(enrollment.data)', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nenrollment = client.enrollments.create(\n effective_date="2025-11-10T19:50:20.638Z",\n plan="TLL_100K_CONTENTS_5K_ACV",\n property_manager_id=123,\n tenant_id=123,\n)\nprint(enrollment.data)', }, ruby: { method: 'enrollments.create', example: - 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nenrollment = beagle.enrollments.create(\n effective_date: "effectiveDate",\n plan: "plan",\n property_manager_id: 0,\n tenant_id: 0\n)\n\nputs(enrollment)', + 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nenrollment = beagle.enrollments.create(\n effective_date: "2025-11-10T19:50:20.638Z",\n plan: "TLL_100K_CONTENTS_5K_ACV",\n property_manager_id: 123,\n tenant_id: 123\n)\n\nputs(enrollment)', }, typescript: { method: 'client.enrollments.create', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst enrollment = await client.enrollments.create({\n effectiveDate: 'effectiveDate',\n plan: 'plan',\n propertyManagerId: 0,\n tenantId: 0,\n});\n\nconsole.log(enrollment.data);", + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst enrollment = await client.enrollments.create({\n effectiveDate: '2025-11-10T19:50:20.638Z',\n plan: 'TLL_100K_CONTENTS_5K_ACV',\n propertyManagerId: 123,\n tenantId: 123,\n});\n\nconsole.log(enrollment.data);", }, }, }, @@ -969,7 +969,7 @@ const EMBEDDED_READMES: { language: string; content: string }[] = [ { language: 'python', content: - '# Beagle Python API library\n\n\n[![PyPI version](https://img.shields.io/pypi/v/beagle.svg?label=pypi%20(stable))](https://pypi.org/project/beagle/)\n\nThe Beagle Python library provides convenient access to the Beagle REST API from any Python 3.9+\napplication. The library includes type definitions for all request params and response fields,\nand offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx).\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\n## Documentation\n\n The full API of this library can be found in [api.md](api.md).\n\n## Installation\n\n```sh\n# install from this staging repo\npip install git+ssh://git@github.com/stainless-sdks/beagle-python.git\n```\n> [!NOTE]\n> Once this package is [published to PyPI](https://www.stainless.com/docs/guides/publish), this will become: `pip install beagle`\n\n## Usage\n\nThe full API of this library can be found in [api.md](api.md).\n\n```python\nimport os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n # defaults to "production".\n environment="staging",\n)\n\nplans = client.plans.list()\nprint(plans.data)\n```\n\nWhile you can provide an `api_key` keyword argument,\nwe recommend using [python-dotenv](https://pypi.org/project/python-dotenv/)\nto add `BEAGLE_API_KEY="My API Key"` to your `.env` file\nso that your API Key is not stored in source control.\n\n## Async usage\n\nSimply import `AsyncBeagle` instead of `Beagle` and use `await` with each API call:\n\n```python\nimport os\nimport asyncio\nfrom beagle import AsyncBeagle\n\nclient = AsyncBeagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n # defaults to "production".\n environment="staging",\n)\n\nasync def main() -> None:\n plans = await client.plans.list()\n print(plans.data)\n\nasyncio.run(main())\n```\n\nFunctionality between the synchronous and asynchronous clients is otherwise identical.\n\n### With aiohttp\n\nBy default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.\n\nYou can enable this by installing `aiohttp`:\n\n```sh\n# install from this staging repo\npip install \'beagle[aiohttp] @ git+ssh://git@github.com/stainless-sdks/beagle-python.git\'\n```\n\nThen you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:\n\n```python\nimport os\nimport asyncio\nfrom beagle import DefaultAioHttpClient\nfrom beagle import AsyncBeagle\n\nasync def main() -> None:\n async with AsyncBeagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n http_client=DefaultAioHttpClient(),\n) as client:\n plans = await client.plans.list()\n print(plans.data)\n\nasyncio.run(main())\n```\n\n\n\n## Using types\n\nNested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:\n\n- Serializing back into JSON, `model.to_json()`\n- Converting to a dictionary, `model.to_dict()`\n\nTyped requests and responses provide autocomplete and documentation within your editor. If you would like to see type errors in VS Code to help catch bugs earlier, set `python.analysis.typeCheckingMode` to `basic`.\n\n\n\n## Nested params\n\nNested parameters are dictionaries, typed using `TypedDict`, for example:\n\n```python\nfrom beagle import Beagle\n\nclient = Beagle()\n\ntenant = client.tenants.create(\n address={\n "city": "city",\n "state": "xx",\n "street1": "street1",\n "zip": "60513",\n },\n contact={\n "email": "dev@stainless.com",\n "name": {\n "first": "first",\n "last": "last",\n },\n },\n property_manager_id=0,\n)\nprint(tenant.address)\n```\n\n\n\n## Handling errors\n\nWhen the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `beagle.APIConnectionError` is raised.\n\nWhen the API returns a non-success status code (that is, 4xx or 5xx\nresponse), a subclass of `beagle.APIStatusError` is raised, containing `status_code` and `response` properties.\n\nAll errors inherit from `beagle.APIError`.\n\n```python\nimport beagle\nfrom beagle import Beagle\n\nclient = Beagle()\n\ntry:\n client.plans.list()\nexcept beagle.APIConnectionError as e:\n print("The server could not be reached")\n print(e.__cause__) # an underlying Exception, likely raised within httpx.\nexcept beagle.RateLimitError as e:\n print("A 429 status code was received; we should back off a bit.")\nexcept beagle.APIStatusError as e:\n print("Another non-200-range status code was received")\n print(e.status_code)\n print(e.response)\n```\n\nError codes are as follows:\n\n| Status Code | Error Type |\n| ----------- | -------------------------- |\n| 400 | `BadRequestError` |\n| 401 | `AuthenticationError` |\n| 403 | `PermissionDeniedError` |\n| 404 | `NotFoundError` |\n| 422 | `UnprocessableEntityError` |\n| 429 | `RateLimitError` |\n| >=500 | `InternalServerError` |\n| N/A | `APIConnectionError` |\n\n### Retries\n\nCertain errors are automatically retried 2 times by default, with a short exponential backoff.\nConnection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict,\n429 Rate Limit, and >=500 Internal errors are all retried by default.\n\nYou can use the `max_retries` option to configure or disable retry settings:\n\n```python\nfrom beagle import Beagle\n\n# Configure the default for all requests:\nclient = Beagle(\n # default is 2\n max_retries=0,\n)\n\n# Or, configure per-request:\nclient.with_options(max_retries = 5).plans.list()\n```\n\n### Timeouts\n\nBy default requests time out after 1 minute. You can configure this with a `timeout` option,\nwhich accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object:\n\n```python\nfrom beagle import Beagle\n\n# Configure the default for all requests:\nclient = Beagle(\n # 20 seconds (default is 1 minute)\n timeout=20.0,\n)\n\n# More granular control:\nclient = Beagle(\n timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0),\n)\n\n# Override per-request:\nclient.with_options(timeout = 5.0).plans.list()\n```\n\nOn timeout, an `APITimeoutError` is thrown.\n\nNote that requests that time out are [retried twice by default](#retries).\n\n\n\n## Advanced\n\n### Logging\n\nWe use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module.\n\nYou can enable logging by setting the environment variable `BEAGLE_LOG` to `info`.\n\n```shell\n$ export BEAGLE_LOG=info\n```\n\nOr to `debug` for more verbose logging.\n\n### How to tell whether `None` means `null` or missing\n\nIn an API response, a field may be explicitly `null`, or missing entirely; in either case, its value is `None` in this library. You can differentiate the two cases with `.model_fields_set`:\n\n```py\nif response.my_field is None:\n if \'my_field\' not in response.model_fields_set:\n print(\'Got json like {}, without a "my_field" key present at all.\')\n else:\n print(\'Got json like {"my_field": null}.\')\n```\n\n### Accessing raw response data (e.g. headers)\n\nThe "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call, e.g.,\n\n```py\nfrom beagle import Beagle\n\nclient = Beagle()\nresponse = client.plans.with_raw_response.list()\nprint(response.headers.get(\'X-My-Header\'))\n\nplan = response.parse() # get the object that `plans.list()` would have returned\nprint(plan.data)\n```\n\nThese methods return an [`APIResponse`](https://github.com/stainless-sdks/beagle-python/tree/main/src/beagle/_response.py) object.\n\nThe async client returns an [`AsyncAPIResponse`](https://github.com/stainless-sdks/beagle-python/tree/main/src/beagle/_response.py) with the same structure, the only difference being `await`able methods for reading the response content.\n\n#### `.with_streaming_response`\n\nThe above interface eagerly reads the full response body when you make the request, which may not always be what you want.\n\nTo stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.\n\n```python\nwith client.plans.with_streaming_response.list() as response :\n print(response.headers.get(\'X-My-Header\'))\n\n for line in response.iter_lines():\n print(line)\n```\n\nThe context manager is required so that the response will reliably be closed.\n\n### Making custom/undocumented requests\n\nThis library is typed for convenient access to the documented API.\n\nIf you need to access undocumented endpoints, params, or response properties, the library can still be used.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints, you can make requests using `client.get`, `client.post`, and other\nhttp verbs. Options on the client will be respected (such as retries) when making this request.\n\n```py\nimport httpx\n\nresponse = client.post(\n "/foo",\n cast_to=httpx.Response,\n body={"my_param": True},\n)\n\nprint(response.headers.get("x-foo"))\n```\n\n#### Undocumented request params\n\nIf you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` request\noptions.\n\n#### Undocumented response properties\n\nTo access undocumented response properties, you can access the extra fields like `response.unknown_prop`. You\ncan also get all the extra fields on the Pydantic model as a dict with\n[`response.model_extra`](https://docs.pydantic.dev/latest/api/base_model/#pydantic.BaseModel.model_extra).\n\n### Configuring the HTTP client\n\nYou can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including:\n\n- Support for [proxies](https://www.python-httpx.org/advanced/proxies/)\n- Custom [transports](https://www.python-httpx.org/advanced/transports/)\n- Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality\n\n```python\nimport httpx\nfrom beagle import Beagle, DefaultHttpxClient\n\nclient = Beagle(\n # Or use the `BEAGLE_BASE_URL` env var\n base_url="http://my.test.server.example.com:8083",\n http_client=DefaultHttpxClient(proxy="http://my.test.proxy.example.com", transport=httpx.HTTPTransport(local_address="0.0.0.0")),\n)\n```\n\nYou can also customize the client on a per-request basis by using `with_options()`:\n\n```python\nclient.with_options(http_client=DefaultHttpxClient(...))\n```\n\n### Managing HTTP resources\n\nBy default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting.\n\n```py\nfrom beagle import Beagle\n\nwith Beagle() as client:\n # make requests here\n ...\n\n# HTTP client is now closed\n```\n\n## Versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes that only affect static types, without breaking runtime behavior.\n2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n3. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/beagle-python/issues) with questions, bugs, or suggestions.\n\n### Determining the installed version\n\nIf you\'ve upgraded to the latest version but aren\'t seeing any new features you were expecting then your python environment is likely still using an older version.\n\nYou can determine the version that is being used at runtime with:\n\n```py\nimport beagle\nprint(beagle.__version__)\n```\n\n## Requirements\n\nPython 3.9 or higher.\n\n## Contributing\n\nSee [the contributing documentation](./CONTRIBUTING.md).\n', + '# Beagle Python API library\n\n\n[![PyPI version](https://img.shields.io/pypi/v/beagle.svg?label=pypi%20(stable))](https://pypi.org/project/beagle/)\n\nThe Beagle Python library provides convenient access to the Beagle REST API from any Python 3.9+\napplication. The library includes type definitions for all request params and response fields,\nand offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx).\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\n## Documentation\n\n The full API of this library can be found in [api.md](api.md).\n\n## Installation\n\n```sh\n# install from this staging repo\npip install git+ssh://git@github.com/stainless-sdks/beagle-python.git\n```\n> [!NOTE]\n> Once this package is [published to PyPI](https://www.stainless.com/docs/guides/publish), this will become: `pip install beagle`\n\n## Usage\n\nThe full API of this library can be found in [api.md](api.md).\n\n```python\nimport os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n # defaults to "production".\n environment="staging",\n)\n\nplans = client.plans.list()\nprint(plans.data)\n```\n\nWhile you can provide an `api_key` keyword argument,\nwe recommend using [python-dotenv](https://pypi.org/project/python-dotenv/)\nto add `BEAGLE_API_KEY="My API Key"` to your `.env` file\nso that your API Key is not stored in source control.\n\n## Async usage\n\nSimply import `AsyncBeagle` instead of `Beagle` and use `await` with each API call:\n\n```python\nimport os\nimport asyncio\nfrom beagle import AsyncBeagle\n\nclient = AsyncBeagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n # defaults to "production".\n environment="staging",\n)\n\nasync def main() -> None:\n plans = await client.plans.list()\n print(plans.data)\n\nasyncio.run(main())\n```\n\nFunctionality between the synchronous and asynchronous clients is otherwise identical.\n\n### With aiohttp\n\nBy default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.\n\nYou can enable this by installing `aiohttp`:\n\n```sh\n# install from this staging repo\npip install \'beagle[aiohttp] @ git+ssh://git@github.com/stainless-sdks/beagle-python.git\'\n```\n\nThen you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:\n\n```python\nimport os\nimport asyncio\nfrom beagle import DefaultAioHttpClient\nfrom beagle import AsyncBeagle\n\nasync def main() -> None:\n async with AsyncBeagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n http_client=DefaultAioHttpClient(),\n) as client:\n plans = await client.plans.list()\n print(plans.data)\n\nasyncio.run(main())\n```\n\n\n\n## Using types\n\nNested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:\n\n- Serializing back into JSON, `model.to_json()`\n- Converting to a dictionary, `model.to_dict()`\n\nTyped requests and responses provide autocomplete and documentation within your editor. If you would like to see type errors in VS Code to help catch bugs earlier, set `python.analysis.typeCheckingMode` to `basic`.\n\n\n\n## Nested params\n\nNested parameters are dictionaries, typed using `TypedDict`, for example:\n\n```python\nfrom beagle import Beagle\n\nclient = Beagle()\n\ntenant = client.tenants.create(\n address={\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Main St.",\n "zip": "84115",\n "street2": "Unit 3",\n },\n contact={\n "email": "mark.s@example.com",\n "name": {\n "first": "Mark",\n "last": "Scout",\n },\n },\n property_manager_id=123,\n)\nprint(tenant.address)\n```\n\n\n\n## Handling errors\n\nWhen the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `beagle.APIConnectionError` is raised.\n\nWhen the API returns a non-success status code (that is, 4xx or 5xx\nresponse), a subclass of `beagle.APIStatusError` is raised, containing `status_code` and `response` properties.\n\nAll errors inherit from `beagle.APIError`.\n\n```python\nimport beagle\nfrom beagle import Beagle\n\nclient = Beagle()\n\ntry:\n client.plans.list()\nexcept beagle.APIConnectionError as e:\n print("The server could not be reached")\n print(e.__cause__) # an underlying Exception, likely raised within httpx.\nexcept beagle.RateLimitError as e:\n print("A 429 status code was received; we should back off a bit.")\nexcept beagle.APIStatusError as e:\n print("Another non-200-range status code was received")\n print(e.status_code)\n print(e.response)\n```\n\nError codes are as follows:\n\n| Status Code | Error Type |\n| ----------- | -------------------------- |\n| 400 | `BadRequestError` |\n| 401 | `AuthenticationError` |\n| 403 | `PermissionDeniedError` |\n| 404 | `NotFoundError` |\n| 422 | `UnprocessableEntityError` |\n| 429 | `RateLimitError` |\n| >=500 | `InternalServerError` |\n| N/A | `APIConnectionError` |\n\n### Retries\n\nCertain errors are automatically retried 2 times by default, with a short exponential backoff.\nConnection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict,\n429 Rate Limit, and >=500 Internal errors are all retried by default.\n\nYou can use the `max_retries` option to configure or disable retry settings:\n\n```python\nfrom beagle import Beagle\n\n# Configure the default for all requests:\nclient = Beagle(\n # default is 2\n max_retries=0,\n)\n\n# Or, configure per-request:\nclient.with_options(max_retries = 5).plans.list()\n```\n\n### Timeouts\n\nBy default requests time out after 1 minute. You can configure this with a `timeout` option,\nwhich accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object:\n\n```python\nfrom beagle import Beagle\n\n# Configure the default for all requests:\nclient = Beagle(\n # 20 seconds (default is 1 minute)\n timeout=20.0,\n)\n\n# More granular control:\nclient = Beagle(\n timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0),\n)\n\n# Override per-request:\nclient.with_options(timeout = 5.0).plans.list()\n```\n\nOn timeout, an `APITimeoutError` is thrown.\n\nNote that requests that time out are [retried twice by default](#retries).\n\n\n\n## Advanced\n\n### Logging\n\nWe use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module.\n\nYou can enable logging by setting the environment variable `BEAGLE_LOG` to `info`.\n\n```shell\n$ export BEAGLE_LOG=info\n```\n\nOr to `debug` for more verbose logging.\n\n### How to tell whether `None` means `null` or missing\n\nIn an API response, a field may be explicitly `null`, or missing entirely; in either case, its value is `None` in this library. You can differentiate the two cases with `.model_fields_set`:\n\n```py\nif response.my_field is None:\n if \'my_field\' not in response.model_fields_set:\n print(\'Got json like {}, without a "my_field" key present at all.\')\n else:\n print(\'Got json like {"my_field": null}.\')\n```\n\n### Accessing raw response data (e.g. headers)\n\nThe "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call, e.g.,\n\n```py\nfrom beagle import Beagle\n\nclient = Beagle()\nresponse = client.plans.with_raw_response.list()\nprint(response.headers.get(\'X-My-Header\'))\n\nplan = response.parse() # get the object that `plans.list()` would have returned\nprint(plan.data)\n```\n\nThese methods return an [`APIResponse`](https://github.com/stainless-sdks/beagle-python/tree/main/src/beagle/_response.py) object.\n\nThe async client returns an [`AsyncAPIResponse`](https://github.com/stainless-sdks/beagle-python/tree/main/src/beagle/_response.py) with the same structure, the only difference being `await`able methods for reading the response content.\n\n#### `.with_streaming_response`\n\nThe above interface eagerly reads the full response body when you make the request, which may not always be what you want.\n\nTo stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.\n\n```python\nwith client.plans.with_streaming_response.list() as response :\n print(response.headers.get(\'X-My-Header\'))\n\n for line in response.iter_lines():\n print(line)\n```\n\nThe context manager is required so that the response will reliably be closed.\n\n### Making custom/undocumented requests\n\nThis library is typed for convenient access to the documented API.\n\nIf you need to access undocumented endpoints, params, or response properties, the library can still be used.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints, you can make requests using `client.get`, `client.post`, and other\nhttp verbs. Options on the client will be respected (such as retries) when making this request.\n\n```py\nimport httpx\n\nresponse = client.post(\n "/foo",\n cast_to=httpx.Response,\n body={"my_param": True},\n)\n\nprint(response.headers.get("x-foo"))\n```\n\n#### Undocumented request params\n\nIf you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` request\noptions.\n\n#### Undocumented response properties\n\nTo access undocumented response properties, you can access the extra fields like `response.unknown_prop`. You\ncan also get all the extra fields on the Pydantic model as a dict with\n[`response.model_extra`](https://docs.pydantic.dev/latest/api/base_model/#pydantic.BaseModel.model_extra).\n\n### Configuring the HTTP client\n\nYou can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including:\n\n- Support for [proxies](https://www.python-httpx.org/advanced/proxies/)\n- Custom [transports](https://www.python-httpx.org/advanced/transports/)\n- Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality\n\n```python\nimport httpx\nfrom beagle import Beagle, DefaultHttpxClient\n\nclient = Beagle(\n # Or use the `BEAGLE_BASE_URL` env var\n base_url="http://my.test.server.example.com:8083",\n http_client=DefaultHttpxClient(proxy="http://my.test.proxy.example.com", transport=httpx.HTTPTransport(local_address="0.0.0.0")),\n)\n```\n\nYou can also customize the client on a per-request basis by using `with_options()`:\n\n```python\nclient.with_options(http_client=DefaultHttpxClient(...))\n```\n\n### Managing HTTP resources\n\nBy default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting.\n\n```py\nfrom beagle import Beagle\n\nwith Beagle() as client:\n # make requests here\n ...\n\n# HTTP client is now closed\n```\n\n## Versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes that only affect static types, without breaking runtime behavior.\n2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n3. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/beagle-python/issues) with questions, bugs, or suggestions.\n\n### Determining the installed version\n\nIf you\'ve upgraded to the latest version but aren\'t seeing any new features you were expecting then your python environment is likely still using an older version.\n\nYou can determine the version that is being used at runtime with:\n\n```py\nimport beagle\nprint(beagle.__version__)\n```\n\n## Requirements\n\nPython 3.9 or higher.\n\n## Contributing\n\nSee [the contributing documentation](./CONTRIBUTING.md).\n', }, { language: 'go', diff --git a/src/resources/enrollments.ts b/src/resources/enrollments.ts index 8f9c9740..36347447 100644 --- a/src/resources/enrollments.ts +++ b/src/resources/enrollments.ts @@ -18,10 +18,10 @@ export class Enrollments extends APIResource { * @example * ```ts * const enrollment = await client.enrollments.create({ - * effectiveDate: 'effectiveDate', - * plan: 'plan', - * propertyManagerId: 0, - * tenantId: 0, + * effectiveDate: '2025-11-10T19:50:20.638Z', + * plan: 'TLL_100K_CONTENTS_5K_ACV', + * propertyManagerId: 123, + * tenantId: 123, * }); * ``` */ diff --git a/src/resources/property-managers.ts b/src/resources/property-managers.ts index 5e6018b9..4c74a16b 100644 --- a/src/resources/property-managers.ts +++ b/src/resources/property-managers.ts @@ -21,21 +21,21 @@ export class PropertyManagers extends APIResource { * await client.propertyManagers.create({ * addresses: [ * { - * city: 'city', - * state: 'xx', - * street1: 'street1', - * zip: '60513', - * kind: 'billing', + * city: 'South Salt Lake', + * state: 'UT', + * street1: '123 Electric Ave.', + * zip: '84115', + * kind: 'place of business', * }, * ], * contacts: [ * { - * email: 'dev@stainless.com', - * name: { first: 'first', last: 'last' }, - * kind: 'agreements', + * email: 'mr.milchick@example.com', + * name: { first: 'Seth', last: 'Milchick' }, + * kind: 'reporting', * }, * ], - * name: 'name', + * name: 'Lumon Apartments', * }); * ``` */ diff --git a/src/resources/tenants.ts b/src/resources/tenants.ts index 09ca2d38..a2474581 100644 --- a/src/resources/tenants.ts +++ b/src/resources/tenants.ts @@ -19,16 +19,16 @@ export class Tenants extends APIResource { * ```ts * const tenant = await client.tenants.create({ * address: { - * city: 'city', - * state: 'xx', - * street1: 'street1', - * zip: '60513', + * city: 'South Salt Lake', + * state: 'UT', + * street1: '123 Main St.', + * zip: '84115', * }, * contact: { - * email: 'dev@stainless.com', - * name: { first: 'first', last: 'last' }, + * email: 'mark.s@example.com', + * name: { first: 'Mark', last: 'Scout' }, * }, - * propertyManagerId: 0, + * propertyManagerId: 123, * }); * ``` */ diff --git a/tests/api-resources/enrollments.test.ts b/tests/api-resources/enrollments.test.ts index d4ad8899..53221226 100644 --- a/tests/api-resources/enrollments.test.ts +++ b/tests/api-resources/enrollments.test.ts @@ -11,10 +11,10 @@ describe('resource enrollments', () => { // Mock server tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.enrollments.create({ - effectiveDate: 'effectiveDate', - plan: 'plan', - propertyManagerId: 0, - tenantId: 0, + effectiveDate: '2025-11-10T19:50:20.638Z', + plan: 'TLL_100K_CONTENTS_5K_ACV', + propertyManagerId: 123, + tenantId: 123, }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); @@ -28,12 +28,12 @@ describe('resource enrollments', () => { // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.enrollments.create({ - effectiveDate: 'effectiveDate', - plan: 'plan', - propertyManagerId: 0, - tenantId: 0, + effectiveDate: '2025-11-10T19:50:20.638Z', + plan: 'TLL_100K_CONTENTS_5K_ACV', + propertyManagerId: 123, + tenantId: 123, note: 'note', - status: 'Premium Paying', + status: 'Issued, Not Paid', }); }); diff --git a/tests/api-resources/property-managers.test.ts b/tests/api-resources/property-managers.test.ts index eb409837..d812506d 100644 --- a/tests/api-resources/property-managers.test.ts +++ b/tests/api-resources/property-managers.test.ts @@ -13,21 +13,21 @@ describe('resource propertyManagers', () => { const responsePromise = client.propertyManagers.create({ addresses: [ { - city: 'city', - state: 'xx', - street1: 'street1', - zip: '60513', - kind: 'billing', + city: 'South Salt Lake', + state: 'UT', + street1: '123 Electric Ave.', + zip: '84115', + kind: 'place of business', }, ], contacts: [ { - email: 'dev@stainless.com', - name: { first: 'first', last: 'last' }, - kind: 'agreements', + email: 'mr.milchick@example.com', + name: { first: 'Seth', last: 'Milchick' }, + kind: 'reporting', }, ], - name: 'name', + name: 'Lumon Apartments', }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); @@ -43,24 +43,24 @@ describe('resource propertyManagers', () => { const response = await client.propertyManagers.create({ addresses: [ { - city: 'city', - state: 'xx', - street1: 'street1', - zip: '60513', + city: 'South Salt Lake', + state: 'UT', + street1: '123 Electric Ave.', + zip: '84115', street2: 'street2', - kind: 'billing', + kind: 'place of business', }, ], contacts: [ { - email: 'dev@stainless.com', - name: { first: 'first', last: 'last' }, - phone: 'phone', - kind: 'agreements', + email: 'mr.milchick@example.com', + name: { first: 'Seth', last: 'Milchick' }, + phone: '(123) 456-7890', + kind: 'reporting', }, ], - name: 'name', - clickWrapAt: 946684800000, + name: 'Lumon Apartments', + clickWrapAt: 1773359774000, }); }); diff --git a/tests/api-resources/tenants.test.ts b/tests/api-resources/tenants.test.ts index f663ceeb..cd73890a 100644 --- a/tests/api-resources/tenants.test.ts +++ b/tests/api-resources/tenants.test.ts @@ -12,16 +12,16 @@ describe('resource tenants', () => { test.skip('create: only required params', async () => { const responsePromise = client.tenants.create({ address: { - city: 'city', - state: 'xx', - street1: 'street1', - zip: '60513', + city: 'South Salt Lake', + state: 'UT', + street1: '123 Main St.', + zip: '84115', }, contact: { - email: 'dev@stainless.com', - name: { first: 'first', last: 'last' }, + email: 'mark.s@example.com', + name: { first: 'Mark', last: 'Scout' }, }, - propertyManagerId: 0, + propertyManagerId: 123, }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); @@ -36,18 +36,18 @@ describe('resource tenants', () => { test.skip('create: required and optional params', async () => { const response = await client.tenants.create({ address: { - city: 'city', - state: 'xx', - street1: 'street1', - zip: '60513', - street2: 'street2', + city: 'South Salt Lake', + state: 'UT', + street1: '123 Main St.', + zip: '84115', + street2: 'Unit 3', }, contact: { - email: 'dev@stainless.com', - name: { first: 'first', last: 'last' }, - phone: 'phone', + email: 'mark.s@example.com', + name: { first: 'Mark', last: 'Scout' }, + phone: '(123) 456-7890', }, - propertyManagerId: 0, + propertyManagerId: 123, }); }); From ac5e4635baa292446c0ac188467401aac01fd2a7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 12 Apr 2026 02:10:16 +0000 Subject: [PATCH 118/138] chore(internal): codegen related update --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index e5e2a93b..f6eae3cd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1220,9 +1220,9 @@ baseline-browser-mapping@^2.9.0: integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== brace-expansion@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.3.tgz#0493338bdd58e319b1039c67cf7ee439892c01d9" - integrity sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA== + version "2.1.0" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.0.tgz#4f41a41190216ee36067ec381526fe9539c4f0ae" + integrity sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w== dependencies: balanced-match "^1.0.0" From 69cd92bb960311538f857859a99bfd75191be650 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 14:32:06 +0000 Subject: [PATCH 119/138] feat(api): api update --- .stats.yml | 4 ++-- packages/mcp-server/src/local-docs-search.ts | 16 +++++++++------- src/resources/property-managers.ts | 15 +++++++++++++++ tests/api-resources/property-managers.test.ts | 1 + 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/.stats.yml b/.stats.yml index 36756eae..a9056371 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 18 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-80d24d74d981ca13dc9b4bbaa9499e9b5d85d7b03c0d6064009496e06e24f4d0.yml -openapi_spec_hash: 0919b932a6281e50ea3a24cd15167f1b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-ef5a755bad62f37f7c5aabda9301f138c4b3d16e9f3bc6b512fd116c18059365.yml +openapi_spec_hash: 7fdd09563daf05b0efbdd74f2bd391d1 config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 4042376d..4c9af321 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -158,9 +158,9 @@ const EMBEDDED_METHODS: MethodEntry[] = [ qualified: 'client.propertyManagers.retrieve', params: ['id: number;'], response: - '{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }', + '{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; totalUnits?: number; }; success: true; }', markdown: - "## retrieve\n\n`client.propertyManagers.retrieve(id: number): { data: property_manager; success: true; }`\n\n**get** `/api/property-managers/{id}`\n\nget a property manager by id.\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.retrieve(123);\n\nconsole.log(propertyManager);\n```", + "## retrieve\n\n`client.propertyManagers.retrieve(id: number): { data: property_manager; success: true; }`\n\n**get** `/api/property-managers/{id}`\n\nget a property manager by id.\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; totalUnits?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; totalUnits?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.retrieve(123);\n\nconsole.log(propertyManager);\n```", perLanguage: { csharp: { method: 'PropertyManagers.Retrieve', @@ -213,11 +213,12 @@ const EMBEDDED_METHODS: MethodEntry[] = [ 'clickWrapAt?: number;', 'contacts?: { email: string; name: { first: string; last: string; }; phone?: string; }[];', 'name?: string;', + 'totalUnits?: number;', ], response: - '{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }', + '{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; totalUnits?: number; }; success: true; }', markdown: - "## update\n\n`client.propertyManagers.update(id: number, addresses?: { city: string; state: string; street1: string; zip: string; street2?: string; }[], clickWrapAt?: number, contacts?: { email: string; name: object; phone?: string; }[], name?: string): { data: property_manager; success: true; }`\n\n**patch** `/api/property-managers/{id}`\n\nupdate an existing property manager by ID\n\n(Note that when updating **contacts** or **addresses** you need to send the whole array you want to replace them with)\n\n### Parameters\n\n- `id: number`\n\n- `addresses?: { city: string; state: string; street1: string; zip: string; street2?: string; }[]`\n street addresses for each Property\n\n- `clickWrapAt?: number`\n unix timestamp (ms) of clickwrap agreement signature\n\n- `contacts?: { email: string; name: { first: string; last: string; }; phone?: string; }[]`\n contact information for each Property Manager\n\n- `name?: string`\n name of the Property Management Company\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.update(123);\n\nconsole.log(propertyManager);\n```", + "## update\n\n`client.propertyManagers.update(id: number, addresses?: { city: string; state: string; street1: string; zip: string; street2?: string; }[], clickWrapAt?: number, contacts?: { email: string; name: object; phone?: string; }[], name?: string, totalUnits?: number): { data: property_manager; success: true; }`\n\n**patch** `/api/property-managers/{id}`\n\nupdate an existing property manager by ID\n\n(Note that when updating **contacts** or **addresses** you need to send the whole array you want to replace them with)\n\n### Parameters\n\n- `id: number`\n\n- `addresses?: { city: string; state: string; street1: string; zip: string; street2?: string; }[]`\n street addresses for each Property\n\n- `clickWrapAt?: number`\n unix timestamp (ms) of clickwrap agreement signature\n\n- `contacts?: { email: string; name: { first: string; last: string; }; phone?: string; }[]`\n contact information for each Property Manager\n\n- `name?: string`\n name of the Property Management Company\n\n- `totalUnits?: number`\n total number of units managed by this property manager\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; totalUnits?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; totalUnits?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.update(123);\n\nconsole.log(propertyManager);\n```", perLanguage: { csharp: { method: 'PropertyManagers.Update', @@ -314,7 +315,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ params: ['page?: number;', 'size?: number;'], response: '{ data: { items: object[]; pagination: object; }; success: true; }', markdown: - "## list\n\n`client.propertyManagers.list(page?: number, size?: number): { data: object; success: true; }`\n\n**get** `/api/property-managers`\n\nlist all property managers, note this endpoint is paginated.\n\n### Parameters\n\n- `page?: number`\n Page number to fetch.\n\n- `size?: number`\n Number of items per page.\n\n### Returns\n\n- `{ data: { items: object[]; pagination: object; }; success: true; }`\n\n - `data: { items: { id: number; addresses: object[]; contacts: object[]; name: string; clickWrapAt?: number; }[]; pagination: { page: number; pages: number; records: number; size: number; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManagers = await client.propertyManagers.list();\n\nconsole.log(propertyManagers);\n```", + "## list\n\n`client.propertyManagers.list(page?: number, size?: number): { data: object; success: true; }`\n\n**get** `/api/property-managers`\n\nlist all property managers, note this endpoint is paginated.\n\n### Parameters\n\n- `page?: number`\n Page number to fetch.\n\n- `size?: number`\n Number of items per page.\n\n### Returns\n\n- `{ data: { items: object[]; pagination: object; }; success: true; }`\n\n - `data: { items: { id: number; addresses: object[]; contacts: object[]; name: string; clickWrapAt?: number; totalUnits?: number; }[]; pagination: { page: number; pages: number; records: number; size: number; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManagers = await client.propertyManagers.list();\n\nconsole.log(propertyManagers);\n```", perLanguage: { csharp: { method: 'PropertyManagers.List', @@ -365,11 +366,12 @@ const EMBEDDED_METHODS: MethodEntry[] = [ 'contacts: { email: string; name: { first: string; last: string; }; phone?: string; }[];', 'name: string;', 'clickWrapAt?: number;', + 'totalUnits?: number;', ], response: - '{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }', + '{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; totalUnits?: number; }; success: true; }', markdown: - "## create\n\n`client.propertyManagers.create(addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[], contacts: { email: string; name: object; phone?: string; }[], name: string, clickWrapAt?: number): { data: property_manager; success: true; }`\n\n**post** `/api/property-managers`\n\ncreate a new property manager.\n\n### Parameters\n\n- `addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]`\n street addresses for each Property\n\n- `contacts: { email: string; name: { first: string; last: string; }; phone?: string; }[]`\n contact information for each Property Manager\n\n- `name: string`\n name of the Property Management Company\n\n- `clickWrapAt?: number`\n unix timestamp (ms) of clickwrap agreement signature\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.create({\n addresses: [{\n city: 'South Salt Lake',\n state: 'UT',\n street1: '123 Electric Ave.',\n zip: '84115',\n kind: 'place of business',\n}],\n contacts: [{\n email: 'mr.milchick@example.com',\n name: { first: 'Seth', last: 'Milchick' },\n kind: 'reporting',\n}],\n name: 'Lumon Apartments',\n});\n\nconsole.log(propertyManager);\n```", + "## create\n\n`client.propertyManagers.create(addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[], contacts: { email: string; name: object; phone?: string; }[], name: string, clickWrapAt?: number, totalUnits?: number): { data: property_manager; success: true; }`\n\n**post** `/api/property-managers`\n\ncreate a new property manager.\n\n### Parameters\n\n- `addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]`\n street addresses for each Property\n\n- `contacts: { email: string; name: { first: string; last: string; }; phone?: string; }[]`\n contact information for each Property Manager\n\n- `name: string`\n name of the Property Management Company\n\n- `clickWrapAt?: number`\n unix timestamp (ms) of clickwrap agreement signature\n\n- `totalUnits?: number`\n total number of units managed by this property manager\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; totalUnits?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; totalUnits?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.create({\n addresses: [{\n city: 'South Salt Lake',\n state: 'UT',\n street1: '123 Electric Ave.',\n zip: '84115',\n kind: 'place of business',\n}],\n contacts: [{\n email: 'mr.milchick@example.com',\n name: { first: 'Seth', last: 'Milchick' },\n kind: 'reporting',\n}],\n name: 'Lumon Apartments',\n});\n\nconsole.log(propertyManager);\n```", perLanguage: { csharp: { method: 'PropertyManagers.Create', diff --git a/src/resources/property-managers.ts b/src/resources/property-managers.ts index 4c74a16b..586e9943 100644 --- a/src/resources/property-managers.ts +++ b/src/resources/property-managers.ts @@ -155,6 +155,11 @@ export interface PropertyManager { * unix timestamp (ms) of clickwrap agreement signature */ clickWrapAt?: number; + + /** + * total number of units managed by this property manager + */ + totalUnits?: number; } export namespace PropertyManager { @@ -219,6 +224,11 @@ export interface PropertyManagerCreateParams { * unix timestamp (ms) of clickwrap agreement signature */ clickWrapAt?: number; + + /** + * total number of units managed by this property manager + */ + totalUnits?: number; } export namespace PropertyManagerCreateParams { @@ -251,6 +261,11 @@ export interface PropertyManagerUpdateParams { * name of the Property Management Company */ name?: string; + + /** + * total number of units managed by this property manager + */ + totalUnits?: number; } export namespace PropertyManagerUpdateParams { diff --git a/tests/api-resources/property-managers.test.ts b/tests/api-resources/property-managers.test.ts index d812506d..6b04f78a 100644 --- a/tests/api-resources/property-managers.test.ts +++ b/tests/api-resources/property-managers.test.ts @@ -61,6 +61,7 @@ describe('resource propertyManagers', () => { ], name: 'Lumon Apartments', clickWrapAt: 1773359774000, + totalUnits: 0, }); }); From a435a4578c8992d07627a8d746317b4737401d42 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 04:14:08 +0000 Subject: [PATCH 120/138] chore(internal): codegen related update --- packages/mcp-server/src/local-docs-search.ts | 20 ++++++++++---------- scripts/bootstrap | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 4c9af321..f1bb2a08 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -969,9 +969,9 @@ const EMBEDDED_METHODS: MethodEntry[] = [ const EMBEDDED_READMES: { language: string; content: string }[] = [ { - language: 'python', + language: 'csharp', content: - '# Beagle Python API library\n\n\n[![PyPI version](https://img.shields.io/pypi/v/beagle.svg?label=pypi%20(stable))](https://pypi.org/project/beagle/)\n\nThe Beagle Python library provides convenient access to the Beagle REST API from any Python 3.9+\napplication. The library includes type definitions for all request params and response fields,\nand offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx).\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\n## Documentation\n\n The full API of this library can be found in [api.md](api.md).\n\n## Installation\n\n```sh\n# install from this staging repo\npip install git+ssh://git@github.com/stainless-sdks/beagle-python.git\n```\n> [!NOTE]\n> Once this package is [published to PyPI](https://www.stainless.com/docs/guides/publish), this will become: `pip install beagle`\n\n## Usage\n\nThe full API of this library can be found in [api.md](api.md).\n\n```python\nimport os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n # defaults to "production".\n environment="staging",\n)\n\nplans = client.plans.list()\nprint(plans.data)\n```\n\nWhile you can provide an `api_key` keyword argument,\nwe recommend using [python-dotenv](https://pypi.org/project/python-dotenv/)\nto add `BEAGLE_API_KEY="My API Key"` to your `.env` file\nso that your API Key is not stored in source control.\n\n## Async usage\n\nSimply import `AsyncBeagle` instead of `Beagle` and use `await` with each API call:\n\n```python\nimport os\nimport asyncio\nfrom beagle import AsyncBeagle\n\nclient = AsyncBeagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n # defaults to "production".\n environment="staging",\n)\n\nasync def main() -> None:\n plans = await client.plans.list()\n print(plans.data)\n\nasyncio.run(main())\n```\n\nFunctionality between the synchronous and asynchronous clients is otherwise identical.\n\n### With aiohttp\n\nBy default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.\n\nYou can enable this by installing `aiohttp`:\n\n```sh\n# install from this staging repo\npip install \'beagle[aiohttp] @ git+ssh://git@github.com/stainless-sdks/beagle-python.git\'\n```\n\nThen you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:\n\n```python\nimport os\nimport asyncio\nfrom beagle import DefaultAioHttpClient\nfrom beagle import AsyncBeagle\n\nasync def main() -> None:\n async with AsyncBeagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n http_client=DefaultAioHttpClient(),\n) as client:\n plans = await client.plans.list()\n print(plans.data)\n\nasyncio.run(main())\n```\n\n\n\n## Using types\n\nNested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:\n\n- Serializing back into JSON, `model.to_json()`\n- Converting to a dictionary, `model.to_dict()`\n\nTyped requests and responses provide autocomplete and documentation within your editor. If you would like to see type errors in VS Code to help catch bugs earlier, set `python.analysis.typeCheckingMode` to `basic`.\n\n\n\n## Nested params\n\nNested parameters are dictionaries, typed using `TypedDict`, for example:\n\n```python\nfrom beagle import Beagle\n\nclient = Beagle()\n\ntenant = client.tenants.create(\n address={\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Main St.",\n "zip": "84115",\n "street2": "Unit 3",\n },\n contact={\n "email": "mark.s@example.com",\n "name": {\n "first": "Mark",\n "last": "Scout",\n },\n },\n property_manager_id=123,\n)\nprint(tenant.address)\n```\n\n\n\n## Handling errors\n\nWhen the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `beagle.APIConnectionError` is raised.\n\nWhen the API returns a non-success status code (that is, 4xx or 5xx\nresponse), a subclass of `beagle.APIStatusError` is raised, containing `status_code` and `response` properties.\n\nAll errors inherit from `beagle.APIError`.\n\n```python\nimport beagle\nfrom beagle import Beagle\n\nclient = Beagle()\n\ntry:\n client.plans.list()\nexcept beagle.APIConnectionError as e:\n print("The server could not be reached")\n print(e.__cause__) # an underlying Exception, likely raised within httpx.\nexcept beagle.RateLimitError as e:\n print("A 429 status code was received; we should back off a bit.")\nexcept beagle.APIStatusError as e:\n print("Another non-200-range status code was received")\n print(e.status_code)\n print(e.response)\n```\n\nError codes are as follows:\n\n| Status Code | Error Type |\n| ----------- | -------------------------- |\n| 400 | `BadRequestError` |\n| 401 | `AuthenticationError` |\n| 403 | `PermissionDeniedError` |\n| 404 | `NotFoundError` |\n| 422 | `UnprocessableEntityError` |\n| 429 | `RateLimitError` |\n| >=500 | `InternalServerError` |\n| N/A | `APIConnectionError` |\n\n### Retries\n\nCertain errors are automatically retried 2 times by default, with a short exponential backoff.\nConnection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict,\n429 Rate Limit, and >=500 Internal errors are all retried by default.\n\nYou can use the `max_retries` option to configure or disable retry settings:\n\n```python\nfrom beagle import Beagle\n\n# Configure the default for all requests:\nclient = Beagle(\n # default is 2\n max_retries=0,\n)\n\n# Or, configure per-request:\nclient.with_options(max_retries = 5).plans.list()\n```\n\n### Timeouts\n\nBy default requests time out after 1 minute. You can configure this with a `timeout` option,\nwhich accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object:\n\n```python\nfrom beagle import Beagle\n\n# Configure the default for all requests:\nclient = Beagle(\n # 20 seconds (default is 1 minute)\n timeout=20.0,\n)\n\n# More granular control:\nclient = Beagle(\n timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0),\n)\n\n# Override per-request:\nclient.with_options(timeout = 5.0).plans.list()\n```\n\nOn timeout, an `APITimeoutError` is thrown.\n\nNote that requests that time out are [retried twice by default](#retries).\n\n\n\n## Advanced\n\n### Logging\n\nWe use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module.\n\nYou can enable logging by setting the environment variable `BEAGLE_LOG` to `info`.\n\n```shell\n$ export BEAGLE_LOG=info\n```\n\nOr to `debug` for more verbose logging.\n\n### How to tell whether `None` means `null` or missing\n\nIn an API response, a field may be explicitly `null`, or missing entirely; in either case, its value is `None` in this library. You can differentiate the two cases with `.model_fields_set`:\n\n```py\nif response.my_field is None:\n if \'my_field\' not in response.model_fields_set:\n print(\'Got json like {}, without a "my_field" key present at all.\')\n else:\n print(\'Got json like {"my_field": null}.\')\n```\n\n### Accessing raw response data (e.g. headers)\n\nThe "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call, e.g.,\n\n```py\nfrom beagle import Beagle\n\nclient = Beagle()\nresponse = client.plans.with_raw_response.list()\nprint(response.headers.get(\'X-My-Header\'))\n\nplan = response.parse() # get the object that `plans.list()` would have returned\nprint(plan.data)\n```\n\nThese methods return an [`APIResponse`](https://github.com/stainless-sdks/beagle-python/tree/main/src/beagle/_response.py) object.\n\nThe async client returns an [`AsyncAPIResponse`](https://github.com/stainless-sdks/beagle-python/tree/main/src/beagle/_response.py) with the same structure, the only difference being `await`able methods for reading the response content.\n\n#### `.with_streaming_response`\n\nThe above interface eagerly reads the full response body when you make the request, which may not always be what you want.\n\nTo stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.\n\n```python\nwith client.plans.with_streaming_response.list() as response :\n print(response.headers.get(\'X-My-Header\'))\n\n for line in response.iter_lines():\n print(line)\n```\n\nThe context manager is required so that the response will reliably be closed.\n\n### Making custom/undocumented requests\n\nThis library is typed for convenient access to the documented API.\n\nIf you need to access undocumented endpoints, params, or response properties, the library can still be used.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints, you can make requests using `client.get`, `client.post`, and other\nhttp verbs. Options on the client will be respected (such as retries) when making this request.\n\n```py\nimport httpx\n\nresponse = client.post(\n "/foo",\n cast_to=httpx.Response,\n body={"my_param": True},\n)\n\nprint(response.headers.get("x-foo"))\n```\n\n#### Undocumented request params\n\nIf you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` request\noptions.\n\n#### Undocumented response properties\n\nTo access undocumented response properties, you can access the extra fields like `response.unknown_prop`. You\ncan also get all the extra fields on the Pydantic model as a dict with\n[`response.model_extra`](https://docs.pydantic.dev/latest/api/base_model/#pydantic.BaseModel.model_extra).\n\n### Configuring the HTTP client\n\nYou can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including:\n\n- Support for [proxies](https://www.python-httpx.org/advanced/proxies/)\n- Custom [transports](https://www.python-httpx.org/advanced/transports/)\n- Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality\n\n```python\nimport httpx\nfrom beagle import Beagle, DefaultHttpxClient\n\nclient = Beagle(\n # Or use the `BEAGLE_BASE_URL` env var\n base_url="http://my.test.server.example.com:8083",\n http_client=DefaultHttpxClient(proxy="http://my.test.proxy.example.com", transport=httpx.HTTPTransport(local_address="0.0.0.0")),\n)\n```\n\nYou can also customize the client on a per-request basis by using `with_options()`:\n\n```python\nclient.with_options(http_client=DefaultHttpxClient(...))\n```\n\n### Managing HTTP resources\n\nBy default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting.\n\n```py\nfrom beagle import Beagle\n\nwith Beagle() as client:\n # make requests here\n ...\n\n# HTTP client is now closed\n```\n\n## Versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes that only affect static types, without breaking runtime behavior.\n2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n3. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/beagle-python/issues) with questions, bugs, or suggestions.\n\n### Determining the installed version\n\nIf you\'ve upgraded to the latest version but aren\'t seeing any new features you were expecting then your python environment is likely still using an older version.\n\nYou can determine the version that is being used at runtime with:\n\n```py\nimport beagle\nprint(beagle.__version__)\n```\n\n## Requirements\n\nPython 3.9 or higher.\n\n## Contributing\n\nSee [the contributing documentation](./CONTRIBUTING.md).\n', + '# Beagle C# API Library\n\nThe Beagle C# SDK provides convenient access to the Beagle REST API from applications written in C#.\n\n## Installation\n\n```bash\ngit clone git@github.com:stainless-sdks/beagle-csharp.git\ndotnet add reference beagle-csharp/src/Beagle\n```\n\n## Requirements\n\nThis library requires .NET Standard 2.0 or later.\n\n## Usage\n\nSee the [`examples`](examples) directory for complete and runnable examples.\n\n```csharp\nBeagleClient client = new();\n\nPlanListParams parameters = new();\n\nvar plans = await client.Plans.List(parameters);\n\nConsole.WriteLine(plans);\n```', }, { language: 'go', @@ -979,24 +979,24 @@ const EMBEDDED_READMES: { language: string; content: string }[] = [ '# Beagle Go API Library\n\nGo Reference\n\nThe Beagle Go library provides convenient access to the Beagle REST API\nfrom applications written in Go.\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\n## Installation\n\n\n\n```go\nimport (\n\t"github.com/stainless-sdks/beagle-go" // imported as SDK_PackageName\n)\n```\n\n\n\nOr to pin the version:\n\n\n\n```sh\ngo get -u \'github.com/stainless-sdks/beagle-go@v0.0.1\'\n```\n\n\n\n## Requirements\n\nThis library requires Go 1.22+.\n\n## Usage\n\nThe full API of this library can be found in [api.md](api.md).\n\n```go\npackage main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"), // defaults to os.LookupEnv("BEAGLE_API_KEY")\n\t\toption.WithEnvironmentStaging(), // defaults to option.WithEnvironmentProduction()\n\t)\n\tplans, err := client.Plans.List(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", plans.Data)\n}\n\n```\n\n### Request fields\n\nAll request parameters are wrapped in a generic `Field` type,\nwhich we use to distinguish zero values from null or omitted fields.\n\nThis prevents accidentally sending a zero value if you forget a required parameter,\nand enables explicitly sending `null`, `false`, `\'\'`, or `0` on optional parameters.\nAny field not specified is not sent.\n\nTo construct fields with values, use the helpers `String()`, `Int()`, `Float()`, or most commonly, the generic `F[T]()`.\nTo send a null, use `Null[T]()`, and to send a nonconforming value, use `Raw[T](any)`. For example:\n\n```go\nparams := FooParams{\n\tName: SDK_PackageName.F("hello"),\n\n\t// Explicitly send `"description": null`\n\tDescription: SDK_PackageName.Null[string](),\n\n\tPoint: SDK_PackageName.F(SDK_PackageName.Point{\n\t\tX: SDK_PackageName.Int(0),\n\t\tY: SDK_PackageName.Int(1),\n\n\t\t// In cases where the API specifies a given type,\n\t\t// but you want to send something else, use `Raw`:\n\t\tZ: SDK_PackageName.Raw[int64](0.01), // sends a float\n\t}),\n}\n```\n\n### Response objects\n\nAll fields in response structs are value types (not pointers or wrappers).\n\nIf a given field is `null`, not present, or invalid, the corresponding field\nwill simply be its zero value.\n\nAll response structs also include a special `JSON` field, containing more detailed\ninformation about each property, which you can use like so:\n\n```go\nif res.Name == "" {\n\t// true if `"name"` is either not present or explicitly null\n\tres.JSON.Name.IsNull()\n\n\t// true if the `"name"` key was not present in the response JSON at all\n\tres.JSON.Name.IsMissing()\n\n\t// When the API returns data that cannot be coerced to the expected type:\n\tif res.JSON.Name.IsInvalid() {\n\t\traw := res.JSON.Name.Raw()\n\n\t\tlegacyName := struct{\n\t\t\tFirst string `json:"first"`\n\t\t\tLast string `json:"last"`\n\t\t}{}\n\t\tjson.Unmarshal([]byte(raw), &legacyName)\n\t\tname = legacyName.First + " " + legacyName.Last\n\t}\n}\n```\n\nThese `.JSON` structs also include an `Extras` map containing\nany properties in the json response that were not specified\nin the struct. This can be useful for API features not yet\npresent in the SDK.\n\n```go\nbody := res.JSON.ExtraFields["my_unexpected_field"].Raw()\n```\n\n### RequestOptions\n\nThis library uses the functional options pattern. Functions defined in the\n`SDK_PackageOptionName` package return a `RequestOption`, which is a closure that mutates a\n`RequestConfig`. These options can be supplied to the client or at individual\nrequests. For example:\n\n```go\nclient := SDK_PackageName.SDK_ClientInitializerName(\n\t// Adds a header to every request made by the client\n\tSDK_PackageOptionName.WithHeader("X-Some-Header", "custom_header_info"),\n)\n\nclient.Plans.List(context.TODO(), ...,\n\t// Override the header\n\tSDK_PackageOptionName.WithHeader("X-Some-Header", "some_other_custom_header_info"),\n\t// Add an undocumented field to the request body, using sjson syntax\n\tSDK_PackageOptionName.WithJSONSet("some.json.path", map[string]string{"my": "object"}),\n)\n```\n\nSee the [full list of request options](https://pkg.go.dev/github.com/stainless-sdks/beagle-go/SDK_PackageOptionName).\n\n### Pagination\n\nThis library provides some conveniences for working with paginated list endpoints.\n\nYou can use `.ListAutoPaging()` methods to iterate through items across all pages:\n\n\n\nOr you can use simple `.List()` methods to fetch a single page and receive a standard response object\nwith additional helper methods like `.GetNextPage()`, e.g.:\n\n\n\n### Errors\n\nWhen the API returns a non-success status code, we return an error with type\n`*SDK_PackageName.Error`. This contains the `StatusCode`, `*http.Request`, and\n`*http.Response` values of the request, as well as the JSON of the error body\n(much like other response objects in the SDK).\n\nTo handle errors, we recommend that you use the `errors.As` pattern:\n\n```go\n_, err := client.Plans.List(context.TODO())\nif err != nil {\n\tvar apierr *beagle.Error\n\tif errors.As(err, &apierr) {\n\t\tprintln(string(apierr.DumpRequest(true))) // Prints the serialized HTTP request\n\t\tprintln(string(apierr.DumpResponse(true))) // Prints the serialized HTTP response\n\t}\n\tpanic(err.Error()) // GET "/api/plans": 400 Bad Request { ... }\n}\n```\n\nWhen other errors occur, they are returned unwrapped; for example,\nif HTTP transport fails, you might receive `*url.Error` wrapping `*net.OpError`.\n\n### Timeouts\n\nRequests do not time out by default; use context to configure a timeout for a request lifecycle.\n\nNote that if a request is [retried](#retries), the context timeout does not start over.\nTo set a per-retry timeout, use `SDK_PackageOptionName.WithRequestTimeout()`.\n\n```go\n// This sets the timeout for the request, including all the retries.\nctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)\ndefer cancel()\nclient.Plans.List(\n\tctx,\n\t// This sets the per-retry timeout\n\toption.WithRequestTimeout(20*time.Second),\n)\n```\n\n### File uploads\n\nRequest parameters that correspond to file uploads in multipart requests are typed as\n`param.Field[io.Reader]`. The contents of the `io.Reader` will by default be sent as a multipart form\npart with the file name of "anonymous_file" and content-type of "application/octet-stream".\n\nThe file name and content-type can be customized by implementing `Name() string` or `ContentType()\nstring` on the run-time type of `io.Reader`. Note that `os.File` implements `Name() string`, so a\nfile returned by `os.Open` will be sent with the file name on disk.\n\nWe also provide a helper `SDK_PackageName.FileParam(reader io.Reader, filename string, contentType string)`\nwhich can be used to wrap any `io.Reader` with the appropriate file name and content type.\n\n\n\n### Retries\n\nCertain errors will be automatically retried 2 times by default, with a short exponential backoff.\nWe retry by default all connection errors, 408 Request Timeout, 409 Conflict, 429 Rate Limit,\nand >=500 Internal errors.\n\nYou can use the `WithMaxRetries` option to configure or disable this:\n\n```go\n// Configure the default for all requests:\nclient := beagle.NewClient(\n\toption.WithMaxRetries(0), // default is 2\n)\n\n// Override per-request:\nclient.Plans.List(context.TODO(), option.WithMaxRetries(5))\n```\n\n\n### Accessing raw response data (e.g. response headers)\n\nYou can access the raw HTTP response data by using the `option.WithResponseInto()` request option. This is useful when\nyou need to examine response headers, status codes, or other details.\n\n```go\n// Create a variable to store the HTTP response\nvar response *http.Response\nplans, err := client.Plans.List(context.TODO(), option.WithResponseInto(&response))\nif err != nil {\n\t// handle error\n}\nfmt.Printf("%+v\\n", plans)\n\nfmt.Printf("Status Code: %d\\n", response.StatusCode)\nfmt.Printf("Headers: %+#v\\n", response.Header)\n```\n\n### Making custom/undocumented requests\n\nThis library is typed for convenient access to the documented API. If you need to access undocumented\nendpoints, params, or response properties, the library can still be used.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints, you can use `client.Get`, `client.Post`, and other HTTP verbs.\n`RequestOptions` on the client, such as retries, will be respected when making these requests.\n\n```go\nvar (\n // params can be an io.Reader, a []byte, an encoding/json serializable object,\n // or a "…Params" struct defined in this library.\n params map[string]interface{}\n\n // result can be an []byte, *http.Response, a encoding/json deserializable object,\n // or a model defined in this library.\n result *http.Response\n)\nerr := client.Post(context.Background(), "/unspecified", params, &result)\nif err != nil {\n …\n}\n```\n\n#### Undocumented request params\n\nTo make requests using undocumented parameters, you may use either the `SDK_PackageOptionName.WithQuerySet()`\nor the `SDK_PackageOptionName.WithJSONSet()` methods.\n\n```go\nparams := FooNewParams{\n ID: SDK_PackageName.F("id_xxxx"),\n Data: SDK_PackageName.F(FooNewParamsData{\n FirstName: SDK_PackageName.F("John"),\n }),\n}\nclient.Foo.New(context.Background(), params, SDK_PackageOptionName.WithJSONSet("data.last_name", "Doe"))\n```\n\n#### Undocumented response properties\n\nTo access undocumented response properties, you may either access the raw JSON of the response as a string\nwith `result.JSON.RawJSON()`, or get the raw JSON of a particular field on the result with\n`result.JSON.Foo.Raw()`.\n\nAny fields that are not present on the response struct will be saved and can be accessed by `result.JSON.ExtraFields()` which returns the extra fields as a `map[string]Field`.\n\n### Middleware\n\nWe provide `SDK_PackageOptionName.WithMiddleware` which applies the given\nmiddleware to requests.\n\n```go\nfunc Logger(req *http.Request, next SDK_PackageOptionName.MiddlewareNext) (res *http.Response, err error) {\n\t// Before the request\n\tstart := time.Now()\n\tLogReq(req)\n\n\t// Forward the request to the next handler\n\tres, err = next(req)\n\n\t// Handle stuff after the request\n\tend := time.Now()\n\tLogRes(res, err, start - end)\n\n return res, err\n}\n\nclient := SDK_PackageName.SDK_ClientInitializerName(\n\tSDK_PackageOptionName.WithMiddleware(Logger),\n)\n```\n\nWhen multiple middlewares are provided as variadic arguments, the middlewares\nare applied left to right. If `SDK_PackageOptionName.WithMiddleware` is given\nmultiple times, for example first in the client then the method, the\nmiddleware in the client will run first and the middleware given in the method\nwill run next.\n\nYou may also replace the default `http.Client` with\n`SDK_PackageOptionName.WithHTTPClient(client)`. Only one http client is\naccepted (this overwrites any previous client) and receives requests after any\nmiddleware has been applied.\n\n## Semantic versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n2. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/beagle-go/issues) with questions, bugs, or suggestions.\n\n## Contributing\n\nSee [the contributing documentation](./CONTRIBUTING.md).\n', }, { - language: 'typescript', + language: 'java', content: - "# Beagle TypeScript API Library\n\n[![NPM version](https://img.shields.io/npm/v/@corgi-tech/beagle.svg?label=npm%20(stable))](https://npmjs.org/package/@corgi-tech/beagle) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@corgi-tech/beagle)\n\nThis library provides convenient access to the Beagle REST API from server-side TypeScript or JavaScript.\n\n\n\nThe full API of this library can be found in [api.md](api.md).\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\n## Installation\n\n```sh\nnpm install @corgi-tech/beagle\n```\n\n\n\n## Usage\n\nThe full API of this library can be found in [api.md](api.md).\n\n\n```js\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n environment: 'staging', // defaults to 'production'\n});\n\nconst plans = await client.plans.list();\n\nconsole.log(plans.data);\n```\n\n\n\n### Request & Response types\n\nThis library includes TypeScript definitions for all request params and response fields. You may import and use them like so:\n\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n environment: 'staging', // defaults to 'production'\n});\n\nconst plans: Beagle.PlanListResponse = await client.plans.list();\n```\n\nDocumentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors.\n\n\n\n\n\n## Handling errors\n\nWhen the library is unable to connect to the API,\nor if the API returns a non-success status code (i.e., 4xx or 5xx response),\na subclass of `APIError` will be thrown:\n\n\n```ts\nconst plans = await client.plans.list().catch(async (err) => {\n if (err instanceof Beagle.APIError) {\n console.log(err.status); // 400\n console.log(err.name); // BadRequestError\n console.log(err.headers); // {server: 'nginx', ...}\n } else {\n throw err;\n }\n});\n```\n\nError codes are as follows:\n\n| Status Code | Error Type |\n| ----------- | -------------------------- |\n| 400 | `BadRequestError` |\n| 401 | `AuthenticationError` |\n| 403 | `PermissionDeniedError` |\n| 404 | `NotFoundError` |\n| 422 | `UnprocessableEntityError` |\n| 429 | `RateLimitError` |\n| >=500 | `InternalServerError` |\n| N/A | `APIConnectionError` |\n\n### Retries\n\nCertain errors will be automatically retried 2 times by default, with a short exponential backoff.\nConnection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict,\n429 Rate Limit, and >=500 Internal errors will all be retried by default.\n\nYou can use the `maxRetries` option to configure or disable this:\n\n\n```js\n// Configure the default for all requests:\nconst client = new Beagle({\n maxRetries: 0, // default is 2\n});\n\n// Or, configure per-request:\nawait client.plans.list({\n maxRetries: 5,\n});\n```\n\n### Timeouts\n\nRequests time out after 1 minute by default. You can configure this with a `timeout` option:\n\n\n```ts\n// Configure the default for all requests:\nconst client = new Beagle({\n timeout: 20 * 1000, // 20 seconds (default is 1 minute)\n});\n\n// Override per-request:\nawait client.plans.list({\n timeout: 5 * 1000,\n});\n```\n\nOn timeout, an `APIConnectionTimeoutError` is thrown.\n\nNote that requests which time out will be [retried twice by default](#retries).\n\n\n\n\n\n## Advanced Usage\n\n### Accessing raw Response data (e.g., headers)\n\nThe \"raw\" `Response` returned by `fetch()` can be accessed through the `.asResponse()` method on the `APIPromise` type that all methods return.\nThis method returns as soon as the headers for a successful response are received and does not consume the response body, so you are free to write custom parsing or streaming logic.\n\nYou can also use the `.withResponse()` method to get the raw `Response` along with the parsed data.\nUnlike `.asResponse()` this method consumes the body, returning once it is parsed.\n\n\n```ts\nconst client = new Beagle();\n\nconst response = await client.plans.list().asResponse();\nconsole.log(response.headers.get('X-My-Header'));\nconsole.log(response.statusText); // access the underlying Response object\n\nconst { data: plans, response: raw } = await client.plans.list().withResponse();\nconsole.log(raw.headers.get('X-My-Header'));\nconsole.log(plans.data);\n```\n\n### Logging\n\n> [!IMPORTANT]\n> All log messages are intended for debugging only. The format and content of log messages\n> may change between releases.\n\n#### Log levels\n\nThe log level can be configured in two ways:\n\n1. Via the `BEAGLE_LOG` environment variable\n2. Using the `logLevel` client option (overrides the environment variable if set)\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n logLevel: 'debug', // Show all log messages\n});\n```\n\nAvailable log levels, from most to least verbose:\n\n- `'debug'` - Show debug messages, info, warnings, and errors\n- `'info'` - Show info messages, warnings, and errors\n- `'warn'` - Show warnings and errors (default)\n- `'error'` - Show only errors\n- `'off'` - Disable all logging\n\nAt the `'debug'` level, all HTTP requests and responses are logged, including headers and bodies.\nSome authentication-related headers are redacted, but sensitive data in request and response bodies\nmay still be visible.\n\n#### Custom logger\n\nBy default, this library logs to `globalThis.console`. You can also provide a custom logger.\nMost logging libraries are supported, including [pino](https://www.npmjs.com/package/pino), [winston](https://www.npmjs.com/package/winston), [bunyan](https://www.npmjs.com/package/bunyan), [consola](https://www.npmjs.com/package/consola), [signale](https://www.npmjs.com/package/signale), and [@std/log](https://jsr.io/@std/log). If your logger doesn't work, please open an issue.\n\nWhen providing a custom logger, the `logLevel` option still controls which messages are emitted, messages\nbelow the configured level will not be sent to your logger.\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\nimport pino from 'pino';\n\nconst logger = pino();\n\nconst client = new Beagle({\n logger: logger.child({ name: 'Beagle' }),\n logLevel: 'debug', // Send all messages to pino, allowing it to filter\n});\n```\n\n### Making custom/undocumented requests\n\nThis library is typed for convenient access to the documented API. If you need to access undocumented\nendpoints, params, or response properties, the library can still be used.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints, you can use `client.get`, `client.post`, and other HTTP verbs.\nOptions on the client, such as retries, will be respected when making these requests.\n\n```ts\nawait client.post('/some/path', {\n body: { some_prop: 'foo' },\n query: { some_query_arg: 'bar' },\n});\n```\n\n#### Undocumented request params\n\nTo make requests using undocumented parameters, you may use `// @ts-expect-error` on the undocumented\nparameter. This library doesn't validate at runtime that the request matches the type, so any extra values you\nsend will be sent as-is.\n\n```ts\nclient.plans.list({\n // ...\n // @ts-expect-error baz is not yet public\n baz: 'undocumented option',\n});\n```\n\nFor requests with the `GET` verb, any extra params will be in the query, all other requests will send the\nextra param in the body.\n\nIf you want to explicitly send an extra argument, you can do so with the `query`, `body`, and `headers` request\noptions.\n\n#### Undocumented response properties\n\nTo access undocumented response properties, you may access the response object with `// @ts-expect-error` on\nthe response object, or cast the response object to the requisite type. Like the request params, we do not\nvalidate or strip extra properties from the response from the API.\n\n### Customizing the fetch client\n\nBy default, this library expects a global `fetch` function is defined.\n\nIf you want to use a different `fetch` function, you can either polyfill the global:\n\n```ts\nimport fetch from 'my-fetch';\n\nglobalThis.fetch = fetch;\n```\n\nOr pass it to the client:\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\nimport fetch from 'my-fetch';\n\nconst client = new Beagle({ fetch });\n```\n\n### Fetch options\n\nIf you want to set custom `fetch` options without overriding the `fetch` function, you can provide a `fetchOptions` object when instantiating the client or making a request. (Request-specific options override client options.)\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n fetchOptions: {\n // `RequestInit` options\n },\n});\n```\n\n#### Configuring proxies\n\nTo modify proxy behavior, you can provide custom `fetchOptions` that add runtime-specific proxy\noptions to requests:\n\n **Node** [[docs](https://github.com/nodejs/undici/blob/main/docs/docs/api/ProxyAgent.md#example---proxyagent-with-fetch)]\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\nimport * as undici from 'undici';\n\nconst proxyAgent = new undici.ProxyAgent('http://localhost:8888');\nconst client = new Beagle({\n fetchOptions: {\n dispatcher: proxyAgent,\n },\n});\n```\n\n **Bun** [[docs](https://bun.sh/guides/http/proxy)]\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n fetchOptions: {\n proxy: 'http://localhost:8888',\n },\n});\n```\n\n **Deno** [[docs](https://docs.deno.com/api/deno/~/Deno.createHttpClient)]\n\n```ts\nimport Beagle from 'npm:@corgi-tech/beagle';\n\nconst httpClient = Deno.createHttpClient({ proxy: { url: 'http://localhost:8888' } });\nconst client = new Beagle({\n fetchOptions: {\n client: httpClient,\n },\n});\n```\n\n## Frequently Asked Questions\n\n## Semantic versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes that only affect static types, without breaking runtime behavior.\n2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n3. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/corgi-tech/beagle-sdks/issues) with questions, bugs, or suggestions.\n\n## Requirements\n\nTypeScript >= 4.9 is supported.\n\nThe following runtimes are supported:\n\n- Web browsers (Up-to-date Chrome, Firefox, Safari, Edge, and more)\n- Node.js 20 LTS or later ([non-EOL](https://endoflife.date/nodejs)) versions.\n- Deno v1.28.0 or higher.\n- Bun 1.0 or later.\n- Cloudflare Workers.\n- Vercel Edge Runtime.\n- Jest 28 or greater with the `\"node\"` environment (`\"jsdom\"` is not supported at this time).\n- Nitro v2.6 or greater.\n\nNote that React Native is not supported at this time.\n\nIf you are interested in other runtime environments, please open or upvote an issue on GitHub.\n\n## Contributing\n\nSee [the contributing documentation](./CONTRIBUTING.md).\n", + '# Beagle Java API Library\n\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.beagle.api/beagle-java)](https://central.sonatype.com/artifact/com.beagle.api/beagle-java/0.0.1)\n[![javadoc](https://javadoc.io/badge2/com.beagle.api/beagle-java/0.0.1/javadoc.svg)](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1)\n\n\nThe Beagle Java SDK provides convenient access to the Beagle REST API from applications written in Java.\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\nJavadocs are available on [javadoc.io](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1).\n\n## Installation\n\n### Gradle\n\n~~~kotlin\nimplementation("com.beagle.api:beagle-java:0.0.1")\n~~~\n\n### Maven\n\n~~~xml\n\n com.beagle.api\n beagle-java\n 0.0.1\n\n~~~\n\n## Requirements\n\nThis library requires Java 8 or later.\n\n## Usage\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nPlanListResponse plans = client.plans().list();\n```\n\n## Client configuration\n\nConfigure the client using system properties or environment variables:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n```\n\nOr manually:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .apiKey("My API Key")\n .build();\n```\n\nOr using a combination of the two approaches:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n // Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n // Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\n .fromEnv()\n .apiKey("My API Key")\n .build();\n```\n\nSee this table for the available options:\n\n| Setter | System property | Environment variable | Required | Default value |\n| --------- | ---------------- | -------------------- | -------- | ------------------------------------- |\n| `apiKey` | `beagle.apiKey` | `BEAGLE_API_KEY` | true | - |\n| `baseUrl` | `beagle.baseUrl` | `BEAGLE_BASE_URL` | true | `"https://developer.beagleforpm.com"` |\n\nSystem properties take precedence over environment variables.\n\n> [!TIP]\n> Don\'t create more than one client in the same application. Each client has a connection pool and\n> thread pools, which are more efficient to share between requests.\n\n### Modifying configuration\n\nTo temporarily use a modified client configuration, while reusing the same connection and thread pools, call `withOptions()` on any client or service:\n\n```java\nimport com.beagle.api.client.BeagleClient;\n\nBeagleClient clientWithOptions = client.withOptions(optionsBuilder -> {\n optionsBuilder.baseUrl("https://example.com");\n optionsBuilder.maxRetries(42);\n});\n```\n\nThe `withOptions()` method does not affect the original client or service.\n\n## Requests and responses\n\nTo send a request to the Beagle API, build an instance of some `Params` class and pass it to the corresponding client method. When the response is received, it will be deserialized into an instance of a Java class.\n\nFor example, `client.plans().list(...)` should be called with an instance of `PlanListParams`, and it will return an instance of `PlanListResponse`.\n\n## Immutability\n\nEach class in the SDK has an associated [builder](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java) or factory method for constructing it.\n\nEach class is [immutable](https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html) once constructed. If the class has an associated builder, then it has a `toBuilder()` method, which can be used to convert it back to a builder for making a modified copy.\n\nBecause each class is immutable, builder modification will _never_ affect already built class instances.\n\n## Asynchronous execution\n\nThe default client is synchronous. To switch to asynchronous execution, call the `async()` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nCompletableFuture plans = client.async().plans().list();\n```\n\nOr create an asynchronous client from the beginning:\n\n```java\nimport com.beagle.api.client.BeagleClientAsync;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClientAsync;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClientAsync client = BeagleOkHttpClientAsync.fromEnv();\n\nCompletableFuture plans = client.plans().list();\n```\n\nThe asynchronous client supports the same options as the synchronous one, except most methods return `CompletableFuture`s.\n\n\n\n\n\n## Binary responses\n\nThe SDK defines methods that return binary responses, which are used for API responses that shouldn\'t necessarily be parsed, like non-JSON data.\n\nThese methods return [`HttpResponse`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpResponse.kt):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport com.beagle.api.models.enrollments.EnrollmentRetrieveCertificateParams;\n\nHttpResponse response = client.enrollments().retrieveCertificate(123.0);\n```\n\nTo save the response content to a file, use the [`Files.copy(...)`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#copy-java.io.InputStream-java.nio.file.Path-java.nio.file.CopyOption...-) method:\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.nio.file.StandardCopyOption;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n Files.copy(\n response.body(),\n Paths.get(path),\n StandardCopyOption.REPLACE_EXISTING\n );\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\nOr transfer the response content to any [`OutputStream`](https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n response.body().transferTo(Files.newOutputStream(Paths.get(path)));\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\n## Raw responses\n\nThe SDK defines methods that deserialize responses into instances of Java classes. However, these methods don\'t provide access to the response headers, status code, or the raw response body.\n\nTo access this data, prefix any HTTP method call on a client or service with `withRawResponse()`:\n\n```java\nimport com.beagle.api.core.http.Headers;\nimport com.beagle.api.core.http.HttpResponseFor;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\nHttpResponseFor plans = client.plans().withRawResponse().list();\n\nint statusCode = plans.statusCode();\nHeaders headers = plans.headers();\n```\n\nYou can still deserialize the response into an instance of a Java class if needed:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse parsedPlans = plans.parse();\n```\n\n## Error handling\n\nThe SDK throws custom unchecked exception types:\n\n- [`BeagleServiceException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleServiceException.kt): Base class for HTTP errors. See this table for which exception subclass is thrown for each HTTP status code:\n\n | Status | Exception |\n | ------ | -------------------------------------------------- |\n | 400 | [`BadRequestException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BadRequestException.kt) |\n | 401 | [`UnauthorizedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnauthorizedException.kt) |\n | 403 | [`PermissionDeniedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/PermissionDeniedException.kt) |\n | 404 | [`NotFoundException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/NotFoundException.kt) |\n | 422 | [`UnprocessableEntityException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnprocessableEntityException.kt) |\n | 429 | [`RateLimitException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/RateLimitException.kt) |\n | 5xx | [`InternalServerException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/InternalServerException.kt) |\n | others | [`UnexpectedStatusCodeException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnexpectedStatusCodeException.kt) |\n\n- [`BeagleIoException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleIoException.kt): I/O networking errors.\n\n- [`BeagleRetryableException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleRetryableException.kt): Generic error indicating a failure that could be retried by the client.\n\n- [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt): Failure to interpret successfully parsed data. For example, when accessing a property that\'s supposed to be required, but the API unexpectedly omitted it from the response.\n\n- [`BeagleException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleException.kt): Base class for all exceptions. Most errors will result in one of the previously mentioned ones, but completely generic errors may be thrown using the base class.\n\n\n\n## Logging\n\nThe SDK uses the standard [OkHttp logging interceptor](https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor).\n\nEnable logging by setting the `BEAGLE_LOG` environment variable to `info`:\n\n```sh\nexport BEAGLE_LOG=info\n```\n\nOr to `debug` for more verbose logging:\n\n```sh\nexport BEAGLE_LOG=debug\n```\n\n## ProGuard and R8\n\nAlthough the SDK uses reflection, it is still usable with [ProGuard](https://github.com/Guardsquare/proguard) and [R8](https://developer.android.com/topic/performance/app-optimization/enable-app-optimization) because `beagle-java-core` is published with a [configuration file](beagle-java-core/src/main/resources/META-INF/proguard/beagle-java-core.pro) containing [keep rules](https://www.guardsquare.com/manual/configuration/usage).\n\nProGuard and R8 should automatically detect and use the published rules, but you can also manually copy the keep rules if necessary.\n\n\n\n\n\n## Jackson\n\nThe SDK depends on [Jackson](https://github.com/FasterXML/jackson) for JSON serialization/deserialization. It is compatible with version 2.13.4 or higher, but depends on version 2.18.2 by default.\n\nThe SDK throws an exception if it detects an incompatible Jackson version at runtime (e.g. if the default version was overridden in your Maven or Gradle config).\n\nIf the SDK threw an exception, but you\'re _certain_ the version is compatible, then disable the version check using the `checkJacksonVersionCompatibility` on [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt).\n\n> [!CAUTION]\n> We make no guarantee that the SDK works correctly when the Jackson version check is disabled.\n\nAlso note that there are bugs in older Jackson versions that can affect the SDK. We don\'t work around all Jackson bugs ([example](https://github.com/FasterXML/jackson-databind/issues/3240)) and expect users to upgrade Jackson for those instead.\n\n## Network options\n\n### Retries\n\nThe SDK automatically retries 2 times by default, with a short exponential backoff between requests.\n\nOnly the following error types are retried:\n- Connection errors (for example, due to a network connectivity problem)\n- 408 Request Timeout\n- 409 Conflict\n- 429 Rate Limit\n- 5xx Internal\n\nThe API may also explicitly instruct the SDK to retry or not retry a request.\n\nTo set a custom number of retries, configure the client using the `maxRetries` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .maxRetries(4)\n .build();\n```\n\n### Timeouts\n\nRequests time out after 1 minute by default.\n\nTo set a custom timeout, configure the method call using the `timeout` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().timeout(Duration.ofSeconds(30)).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .timeout(Duration.ofSeconds(30))\n .build();\n```\n\n### Proxies\n\nTo route requests through a proxy, configure the client using the `proxy` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.net.InetSocketAddress;\nimport java.net.Proxy;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .proxy(new Proxy(\n Proxy.Type.HTTP, new InetSocketAddress(\n "https://example.com", 8080\n )\n ))\n .build();\n```\n\n### Connection pooling\n\nTo customize the underlying OkHttp connection pool, configure the client using the `maxIdleConnections` and `keepAliveDuration` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `maxIdleConnections` is set, then `keepAliveDuration` must be set, and vice versa.\n .maxIdleConnections(10)\n .keepAliveDuration(Duration.ofMinutes(2))\n .build();\n```\n\nIf both options are unset, OkHttp\'s default connection pool settings are used.\n\n### HTTPS\n\n> [!NOTE]\n> Most applications should not call these methods, and instead use the system defaults. The defaults include\n> special optimizations that can be lost if the implementations are modified.\n\nTo configure how HTTPS connections are secured, configure the client using the `sslSocketFactory`, `trustManager`, and `hostnameVerifier` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `sslSocketFactory` is set, then `trustManager` must be set, and vice versa.\n .sslSocketFactory(yourSSLSocketFactory)\n .trustManager(yourTrustManager)\n .hostnameVerifier(yourHostnameVerifier)\n .build();\n```\n\n### Environments\n\nThe SDK sends requests to the production by default. To send requests to a different environment, configure the client like so:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .staging()\n .build();\n```\n\n### Custom HTTP client\n\nThe SDK consists of three artifacts:\n- `beagle-java-core`\n - Contains core SDK logic\n - Does not depend on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleClient`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClient.kt), [`BeagleClientAsync`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsync.kt), [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt), and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), all of which can work with any HTTP client\n- `beagle-java-client-okhttp`\n - Depends on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) and [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), which provide a way to construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), respectively, using OkHttp\n- `beagle-java`\n - Depends on and exposes the APIs of both `beagle-java-core` and `beagle-java-client-okhttp`\n - Does not have its own logic\n\nThis structure allows replacing the SDK\'s default HTTP client without pulling in unnecessary dependencies.\n\n#### Customized [`OkHttpClient`](https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.html)\n\n> [!TIP]\n> Try the available [network options](#network-options) before replacing the default client.\n\nTo use a customized `OkHttpClient`:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Copy `beagle-java-client-okhttp`\'s [`OkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/OkHttpClient.kt) class into your code and customize it\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your customized client\n\n### Completely custom HTTP client\n\nTo use a completely custom HTTP client:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Write a class that implements the [`HttpClient`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpClient.kt) interface\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your new client class\n\n## Undocumented API functionality\n\nThe SDK is typed for convenient usage of the documented API. However, it also supports working with undocumented or not yet supported parts of the API.\n\n### Parameters\n\nTo set undocumented parameters, call the `putAdditionalHeader`, `putAdditionalQueryParam`, or `putAdditionalBodyProperty` methods on any `Params` class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder()\n .putAdditionalHeader("Secret-Header", "42")\n .putAdditionalQueryParam("secret_query_param", "42")\n .putAdditionalBodyProperty("secretProperty", JsonValue.from("42"))\n .build();\n```\n\nThese can be accessed on the built object later using the `_additionalHeaders()`, `_additionalQueryParams()`, and `_additionalBodyProperties()` methods.\n\nTo set undocumented parameters on _nested_ headers, query params, or body classes, call the `putAdditionalProperty` method on the nested class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.tenants.Address;\nimport com.beagle.api.models.tenants.TenantCreateParams;\n\nTenantCreateParams params = TenantCreateParams.builder()\n .address(Address.builder()\n .putAdditionalProperty("secretProperty", JsonValue.from("42"))\n .build())\n .build();\n```\n\nThese properties can be accessed on the nested built object later using the `_additionalProperties()` method.\n\nTo set a documented parameter or property to an undocumented or not yet supported _value_, pass a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) object to its setter:\n\n```java\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder().build();\n```\n\nThe most straightforward way to create a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) is using its `from(...)` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.List;\nimport java.util.Map;\n\n// Create primitive JSON values\nJsonValue nullValue = JsonValue.from(null);\nJsonValue booleanValue = JsonValue.from(true);\nJsonValue numberValue = JsonValue.from(42);\nJsonValue stringValue = JsonValue.from("Hello World!");\n\n// Create a JSON array value equivalent to `["Hello", "World"]`\nJsonValue arrayValue = JsonValue.from(List.of(\n "Hello", "World"\n));\n\n// Create a JSON object value equivalent to `{ "a": 1, "b": 2 }`\nJsonValue objectValue = JsonValue.from(Map.of(\n "a", 1,\n "b", 2\n));\n\n// Create an arbitrarily nested JSON equivalent to:\n// {\n// "a": [1, 2],\n// "b": [3, 4]\n// }\nJsonValue complexValue = JsonValue.from(Map.of(\n "a", List.of(\n 1, 2\n ),\n "b", List.of(\n 3, 4\n )\n));\n```\n\nNormally a `Builder` class\'s `build` method will throw [`IllegalStateException`](https://docs.oracle.com/javase/8/docs/api/java/lang/IllegalStateException.html) if any required parameter or property is unset.\n\nTo forcibly omit a required parameter or property, pass [`JsonMissing`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt):\n\n```java\nimport com.beagle.api.core.JsonMissing;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanRetrieveParams;\n\nPlanListParams params = PlanRetrieveParams.builder()\n .code(JsonMissing.of())\n .build();\n```\n\n### Response properties\n\nTo access undocumented response properties, call the `_additionalProperties()` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.Map;\n\nMap additionalProperties = client.plans().list(params)._additionalProperties();\nJsonValue secretPropertyValue = additionalProperties.get("secretProperty");\n\nString result = secretPropertyValue.accept(new JsonValue.Visitor<>() {\n @Override\n public String visitNull() {\n return "It\'s null!";\n }\n\n @Override\n public String visitBoolean(boolean value) {\n return "It\'s a boolean!";\n }\n\n @Override\n public String visitNumber(Number value) {\n return "It\'s a number!";\n }\n\n // Other methods include `visitMissing`, `visitString`, `visitArray`, and `visitObject`\n // The default implementation of each unimplemented method delegates to `visitDefault`, which throws by default, but can also be overridden\n});\n```\n\nTo access a property\'s raw JSON value, which may be undocumented, call its `_` prefixed method:\n\n```java\nimport com.beagle.api.core.JsonField;\nimport java.util.Optional;\n\nJsonField field = client.plans().list(params)._field();\n\nif (field.isMissing()) {\n // The property is absent from the JSON response\n} else if (field.isNull()) {\n // The property was set to literal null\n} else {\n // Check if value was provided as a string\n // Other methods include `asNumber()`, `asBoolean()`, etc.\n Optional jsonString = field.asString();\n\n // Try to deserialize into a custom type\n MyClass myObject = field.asUnknown().orElseThrow().convert(MyClass.class);\n}\n```\n\n### Response validation\n\nIn rare cases, the API may return a response that doesn\'t match the expected type. For example, the SDK may expect a property to contain a `String`, but the API could return something else.\n\nBy default, the SDK will not throw an exception in this case. It will throw [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt) only if you directly access the property.\n\nIf you would prefer to check that the response is completely well-typed upfront, then either call `validate()`:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(params).validate();\n```\n\nOr configure the method call to validate the response using the `responseValidation` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().responseValidation(true).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .responseValidation(true)\n .build();\n```\n\n## FAQ\n\n### Why don\'t you use plain `enum` classes?\n\nJava `enum` classes are not trivially [forwards compatible](https://www.stainless.com/blog/making-java-enums-forwards-compatible). Using them in the SDK could cause runtime exceptions if the API is updated to respond with a new enum value.\n\n### Why do you represent fields using `JsonField` instead of just plain `T`?\n\nUsing `JsonField` enables a few features:\n\n- Allowing usage of [undocumented API functionality](#undocumented-api-functionality)\n- Lazily [validating the API response against the expected shape](#response-validation)\n- Representing absent vs explicitly null values\n\n### Why don\'t you use [`data` classes](https://kotlinlang.org/docs/data-classes.html)?\n\nIt is not [backwards compatible to add new fields to a data class](https://kotlinlang.org/docs/api-guidelines-backward-compatibility.html#avoid-using-data-classes-in-your-api) and we don\'t want to introduce a breaking change every time we add a field to a class.\n\n### Why don\'t you use checked exceptions?\n\nChecked exceptions are widely considered a mistake in the Java programming language. In fact, they were omitted from Kotlin for this reason.\n\nChecked exceptions:\n\n- Are verbose to handle\n- Encourage error handling at the wrong level of abstraction, where nothing can be done about the error\n- Are tedious to propagate due to the [function coloring problem](https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function)\n- Don\'t play well with lambdas (also due to the function coloring problem)\n\n## Semantic versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n2. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/beagle-java/issues) with questions, bugs, or suggestions.\n', }, { - language: 'ruby', + language: 'python', content: - '# Beagle Ruby API library\n\nThe Beagle Ruby library provides convenient access to the Beagle REST API from any Ruby 3.2.0+ application. It ships with comprehensive types & docstrings in Yard, RBS, and RBI – [see below](https://github.com/stainless-sdks/beagle-ruby#Sorbet) for usage with Sorbet. The standard library\'s `net/http` is used as the HTTP transport, with connection pooling via the `connection_pool` gem.\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\n## Documentation\n\nDocumentation for releases of this gem can be found [on RubyDoc](https://gemdocs.org/gems/beagle).\n\n\n\n## Installation\n\nTo use this gem, install via Bundler by adding the following to your application\'s `Gemfile`:\n\n```ruby\ngem "beagle", "~> 0.0.1"\n```\n\n## Usage\n\n```ruby\nrequire "bundler/setup"\nrequire "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: ENV["BEAGLE_API_KEY"], # This is the default and can be omitted\n environment: "staging" # defaults to "production"\n)\n\nplans = beagle.plans.list\n\nputs(plans.data)\n```\n\n\n\n\n\n\n\n### Handling errors\n\nWhen the library is unable to connect to the API, or if the API returns a non-success status code (i.e., 4xx or 5xx response), a subclass of `Beagle::Errors::APIError` will be thrown:\n\n```ruby\nbegin\n plan = beagle.plans.list\nrescue Beagle::Errors::APIConnectionError => e\n puts("The server could not be reached")\n puts(e.cause) # an underlying Exception, likely raised within `net/http`\nrescue Beagle::Errors::RateLimitError => e\n puts("A 429 status code was received; we should back off a bit.")\nrescue Beagle::Errors::APIStatusError => e\n puts("Another non-200-range status code was received")\n puts(e.status)\nend\n```\n\nError codes are as follows:\n\n| Cause | Error Type |\n| ---------------- | -------------------------- |\n| HTTP 400 | `BadRequestError` |\n| HTTP 401 | `AuthenticationError` |\n| HTTP 403 | `PermissionDeniedError` |\n| HTTP 404 | `NotFoundError` |\n| HTTP 409 | `ConflictError` |\n| HTTP 422 | `UnprocessableEntityError` |\n| HTTP 429 | `RateLimitError` |\n| HTTP >= 500 | `InternalServerError` |\n| Other HTTP error | `APIStatusError` |\n| Timeout | `APITimeoutError` |\n| Network error | `APIConnectionError` |\n\n### Retries\n\nCertain errors will be automatically retried 2 times by default, with a short exponential backoff.\n\nConnection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict, 429 Rate Limit, >=500 Internal errors, and timeouts will all be retried by default.\n\nYou can use the `max_retries` option to configure or disable this:\n\n```ruby\n# Configure the default for all requests:\nbeagle = Beagle::Client.new(\n max_retries: 0 # default is 2\n)\n\n# Or, configure per-request:\nbeagle.plans.list(request_options: {max_retries: 5})\n```\n\n### Timeouts\n\nBy default, requests will time out after 60 seconds. You can use the timeout option to configure or disable this:\n\n```ruby\n# Configure the default for all requests:\nbeagle = Beagle::Client.new(\n timeout: nil # default is 60\n)\n\n# Or, configure per-request:\nbeagle.plans.list(request_options: {timeout: 5})\n```\n\nOn timeout, `Beagle::Errors::APITimeoutError` is raised.\n\nNote that requests that time out are retried by default.\n\n## Advanced concepts\n\n### BaseModel\n\nAll parameter and response objects inherit from `Beagle::Internal::Type::BaseModel`, which provides several conveniences, including:\n\n1. All fields, including unknown ones, are accessible with `obj[:prop]` syntax, and can be destructured with `obj => {prop: prop}` or pattern-matching syntax.\n\n2. Structural equivalence for equality; if two API calls return the same values, comparing the responses with == will return true.\n\n3. Both instances and the classes themselves can be pretty-printed.\n\n4. Helpers such as `#to_h`, `#deep_to_h`, `#to_json`, and `#to_yaml`.\n\n### Making custom or undocumented requests\n\n#### Undocumented properties\n\nYou can send undocumented parameters to any endpoint, and read undocumented response properties, like so:\n\nNote: the `extra_` parameters of the same name overrides the documented parameters.\n\n```ruby\nplans =\n beagle.plans.list(\n request_options: {\n extra_query: {my_query_parameter: value},\n extra_body: {my_body_parameter: value},\n extra_headers: {"my-header": value}\n }\n )\n\nputs(plans[:my_undocumented_property])\n```\n\n#### Undocumented request params\n\nIf you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` under the `request_options:` parameter when making a request, as seen in the examples above.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints while retaining the benefit of auth, retries, and so on, you can make requests using `client.request`, like so:\n\n```ruby\nresponse = client.request(\n method: :post,\n path: \'/undocumented/endpoint\',\n query: {"dog": "woof"},\n headers: {"useful-header": "interesting-value"},\n body: {"hello": "world"}\n)\n```\n\n### Concurrency & connection pooling\n\nThe `Beagle::Client` instances are threadsafe, but are only are fork-safe when there are no in-flight HTTP requests.\n\nEach instance of `Beagle::Client` has its own HTTP connection pool with a default size of 99. As such, we recommend instantiating the client once per application in most settings.\n\nWhen all available connections from the pool are checked out, requests wait for a new connection to become available, with queue time counting towards the request timeout.\n\nUnless otherwise specified, other classes in the SDK do not have locks protecting their underlying data structure.\n\n## Sorbet\n\nThis library provides comprehensive [RBI](https://sorbet.org/docs/rbi) definitions, and has no dependency on sorbet-runtime.\n\nYou can provide typesafe request parameters like so:\n\n```ruby\nbeagle.plans.list \n```\n\nOr, equivalently:\n\n```ruby\n# Hashes work, but are not typesafe:\nbeagle.plans.list\n\n# You can also splat a full Params class:\nparams = Beagle::PlanListParams.new\nbeagle.plans.list(**params)\n```\n\n### Enums\n\nSince this library does not depend on `sorbet-runtime`, it cannot provide [`T::Enum`](https://sorbet.org/docs/tenum) instances. Instead, we provide "tagged symbols" instead, which is always a primitive at runtime:\n\n```ruby\n# :"Premium Paying"\nputs(Beagle::EnrollmentCreateParams::Status::PREMIUM_PAYING)\n\n# Revealed type: `T.all(Beagle::EnrollmentCreateParams::Status, Symbol)`\nT.reveal_type(Beagle::EnrollmentCreateParams::Status::PREMIUM_PAYING)\n```\n\nEnum parameters have a "relaxed" type, so you can either pass in enum constants or their literal value:\n\n```ruby\n# Using the enum constants preserves the tagged type information:\nbeagle.enrollments.create(\n status: Beagle::EnrollmentCreateParams::Status::PREMIUM_PAYING,\n # …\n)\n\n# Literal values are also permissible:\nbeagle.enrollments.create(\n status: :"Premium Paying",\n # …\n)\n```\n\n## Versioning\n\nThis package follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions. As the library is in initial development and has a major version of `0`, APIs may change at any time.\n\nThis package considers improvements to the (non-runtime) `*.rbi` and `*.rbs` type definitions to be non-breaking changes.\n\n## Requirements\n\nRuby 3.2.0 or higher.\n\n## Contributing\n\nSee [the contributing documentation](https://github.com/stainless-sdks/beagle-ruby/tree/main/CONTRIBUTING.md).\n', + '# Beagle Python API library\n\n\n[![PyPI version](https://img.shields.io/pypi/v/beagle.svg?label=pypi%20(stable))](https://pypi.org/project/beagle/)\n\nThe Beagle Python library provides convenient access to the Beagle REST API from any Python 3.9+\napplication. The library includes type definitions for all request params and response fields,\nand offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx).\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\n## Documentation\n\n The full API of this library can be found in [api.md](api.md).\n\n## Installation\n\n```sh\n# install from this staging repo\npip install git+ssh://git@github.com/stainless-sdks/beagle-python.git\n```\n> [!NOTE]\n> Once this package is [published to PyPI](https://www.stainless.com/docs/guides/publish), this will become: `pip install beagle`\n\n## Usage\n\nThe full API of this library can be found in [api.md](api.md).\n\n```python\nimport os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n # defaults to "production".\n environment="staging",\n)\n\nplans = client.plans.list()\nprint(plans.data)\n```\n\nWhile you can provide an `api_key` keyword argument,\nwe recommend using [python-dotenv](https://pypi.org/project/python-dotenv/)\nto add `BEAGLE_API_KEY="My API Key"` to your `.env` file\nso that your API Key is not stored in source control.\n\n## Async usage\n\nSimply import `AsyncBeagle` instead of `Beagle` and use `await` with each API call:\n\n```python\nimport os\nimport asyncio\nfrom beagle import AsyncBeagle\n\nclient = AsyncBeagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n # defaults to "production".\n environment="staging",\n)\n\nasync def main() -> None:\n plans = await client.plans.list()\n print(plans.data)\n\nasyncio.run(main())\n```\n\nFunctionality between the synchronous and asynchronous clients is otherwise identical.\n\n### With aiohttp\n\nBy default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.\n\nYou can enable this by installing `aiohttp`:\n\n```sh\n# install from this staging repo\npip install \'beagle[aiohttp] @ git+ssh://git@github.com/stainless-sdks/beagle-python.git\'\n```\n\nThen you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:\n\n```python\nimport os\nimport asyncio\nfrom beagle import DefaultAioHttpClient\nfrom beagle import AsyncBeagle\n\nasync def main() -> None:\n async with AsyncBeagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n http_client=DefaultAioHttpClient(),\n) as client:\n plans = await client.plans.list()\n print(plans.data)\n\nasyncio.run(main())\n```\n\n\n\n## Using types\n\nNested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:\n\n- Serializing back into JSON, `model.to_json()`\n- Converting to a dictionary, `model.to_dict()`\n\nTyped requests and responses provide autocomplete and documentation within your editor. If you would like to see type errors in VS Code to help catch bugs earlier, set `python.analysis.typeCheckingMode` to `basic`.\n\n\n\n## Nested params\n\nNested parameters are dictionaries, typed using `TypedDict`, for example:\n\n```python\nfrom beagle import Beagle\n\nclient = Beagle()\n\ntenant = client.tenants.create(\n address={\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Main St.",\n "zip": "84115",\n "street2": "Unit 3",\n },\n contact={\n "email": "mark.s@example.com",\n "name": {\n "first": "Mark",\n "last": "Scout",\n },\n },\n property_manager_id=123,\n)\nprint(tenant.address)\n```\n\n\n\n## Handling errors\n\nWhen the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `beagle.APIConnectionError` is raised.\n\nWhen the API returns a non-success status code (that is, 4xx or 5xx\nresponse), a subclass of `beagle.APIStatusError` is raised, containing `status_code` and `response` properties.\n\nAll errors inherit from `beagle.APIError`.\n\n```python\nimport beagle\nfrom beagle import Beagle\n\nclient = Beagle()\n\ntry:\n client.plans.list()\nexcept beagle.APIConnectionError as e:\n print("The server could not be reached")\n print(e.__cause__) # an underlying Exception, likely raised within httpx.\nexcept beagle.RateLimitError as e:\n print("A 429 status code was received; we should back off a bit.")\nexcept beagle.APIStatusError as e:\n print("Another non-200-range status code was received")\n print(e.status_code)\n print(e.response)\n```\n\nError codes are as follows:\n\n| Status Code | Error Type |\n| ----------- | -------------------------- |\n| 400 | `BadRequestError` |\n| 401 | `AuthenticationError` |\n| 403 | `PermissionDeniedError` |\n| 404 | `NotFoundError` |\n| 422 | `UnprocessableEntityError` |\n| 429 | `RateLimitError` |\n| >=500 | `InternalServerError` |\n| N/A | `APIConnectionError` |\n\n### Retries\n\nCertain errors are automatically retried 2 times by default, with a short exponential backoff.\nConnection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict,\n429 Rate Limit, and >=500 Internal errors are all retried by default.\n\nYou can use the `max_retries` option to configure or disable retry settings:\n\n```python\nfrom beagle import Beagle\n\n# Configure the default for all requests:\nclient = Beagle(\n # default is 2\n max_retries=0,\n)\n\n# Or, configure per-request:\nclient.with_options(max_retries = 5).plans.list()\n```\n\n### Timeouts\n\nBy default requests time out after 1 minute. You can configure this with a `timeout` option,\nwhich accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object:\n\n```python\nfrom beagle import Beagle\n\n# Configure the default for all requests:\nclient = Beagle(\n # 20 seconds (default is 1 minute)\n timeout=20.0,\n)\n\n# More granular control:\nclient = Beagle(\n timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0),\n)\n\n# Override per-request:\nclient.with_options(timeout = 5.0).plans.list()\n```\n\nOn timeout, an `APITimeoutError` is thrown.\n\nNote that requests that time out are [retried twice by default](#retries).\n\n\n\n## Advanced\n\n### Logging\n\nWe use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module.\n\nYou can enable logging by setting the environment variable `BEAGLE_LOG` to `info`.\n\n```shell\n$ export BEAGLE_LOG=info\n```\n\nOr to `debug` for more verbose logging.\n\n### How to tell whether `None` means `null` or missing\n\nIn an API response, a field may be explicitly `null`, or missing entirely; in either case, its value is `None` in this library. You can differentiate the two cases with `.model_fields_set`:\n\n```py\nif response.my_field is None:\n if \'my_field\' not in response.model_fields_set:\n print(\'Got json like {}, without a "my_field" key present at all.\')\n else:\n print(\'Got json like {"my_field": null}.\')\n```\n\n### Accessing raw response data (e.g. headers)\n\nThe "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call, e.g.,\n\n```py\nfrom beagle import Beagle\n\nclient = Beagle()\nresponse = client.plans.with_raw_response.list()\nprint(response.headers.get(\'X-My-Header\'))\n\nplan = response.parse() # get the object that `plans.list()` would have returned\nprint(plan.data)\n```\n\nThese methods return an [`APIResponse`](https://github.com/stainless-sdks/beagle-python/tree/main/src/beagle/_response.py) object.\n\nThe async client returns an [`AsyncAPIResponse`](https://github.com/stainless-sdks/beagle-python/tree/main/src/beagle/_response.py) with the same structure, the only difference being `await`able methods for reading the response content.\n\n#### `.with_streaming_response`\n\nThe above interface eagerly reads the full response body when you make the request, which may not always be what you want.\n\nTo stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.\n\n```python\nwith client.plans.with_streaming_response.list() as response :\n print(response.headers.get(\'X-My-Header\'))\n\n for line in response.iter_lines():\n print(line)\n```\n\nThe context manager is required so that the response will reliably be closed.\n\n### Making custom/undocumented requests\n\nThis library is typed for convenient access to the documented API.\n\nIf you need to access undocumented endpoints, params, or response properties, the library can still be used.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints, you can make requests using `client.get`, `client.post`, and other\nhttp verbs. Options on the client will be respected (such as retries) when making this request.\n\n```py\nimport httpx\n\nresponse = client.post(\n "/foo",\n cast_to=httpx.Response,\n body={"my_param": True},\n)\n\nprint(response.headers.get("x-foo"))\n```\n\n#### Undocumented request params\n\nIf you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` request\noptions.\n\n#### Undocumented response properties\n\nTo access undocumented response properties, you can access the extra fields like `response.unknown_prop`. You\ncan also get all the extra fields on the Pydantic model as a dict with\n[`response.model_extra`](https://docs.pydantic.dev/latest/api/base_model/#pydantic.BaseModel.model_extra).\n\n### Configuring the HTTP client\n\nYou can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including:\n\n- Support for [proxies](https://www.python-httpx.org/advanced/proxies/)\n- Custom [transports](https://www.python-httpx.org/advanced/transports/)\n- Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality\n\n```python\nimport httpx\nfrom beagle import Beagle, DefaultHttpxClient\n\nclient = Beagle(\n # Or use the `BEAGLE_BASE_URL` env var\n base_url="http://my.test.server.example.com:8083",\n http_client=DefaultHttpxClient(proxy="http://my.test.proxy.example.com", transport=httpx.HTTPTransport(local_address="0.0.0.0")),\n)\n```\n\nYou can also customize the client on a per-request basis by using `with_options()`:\n\n```python\nclient.with_options(http_client=DefaultHttpxClient(...))\n```\n\n### Managing HTTP resources\n\nBy default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting.\n\n```py\nfrom beagle import Beagle\n\nwith Beagle() as client:\n # make requests here\n ...\n\n# HTTP client is now closed\n```\n\n## Versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes that only affect static types, without breaking runtime behavior.\n2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n3. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/beagle-python/issues) with questions, bugs, or suggestions.\n\n### Determining the installed version\n\nIf you\'ve upgraded to the latest version but aren\'t seeing any new features you were expecting then your python environment is likely still using an older version.\n\nYou can determine the version that is being used at runtime with:\n\n```py\nimport beagle\nprint(beagle.__version__)\n```\n\n## Requirements\n\nPython 3.9 or higher.\n\n## Contributing\n\nSee [the contributing documentation](./CONTRIBUTING.md).\n', }, { - language: 'java', + language: 'ruby', content: - '# Beagle Java API Library\n\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.beagle.api/beagle-java)](https://central.sonatype.com/artifact/com.beagle.api/beagle-java/0.0.1)\n[![javadoc](https://javadoc.io/badge2/com.beagle.api/beagle-java/0.0.1/javadoc.svg)](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1)\n\n\nThe Beagle Java SDK provides convenient access to the Beagle REST API from applications written in Java.\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\nJavadocs are available on [javadoc.io](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1).\n\n## Installation\n\n### Gradle\n\n~~~kotlin\nimplementation("com.beagle.api:beagle-java:0.0.1")\n~~~\n\n### Maven\n\n~~~xml\n\n com.beagle.api\n beagle-java\n 0.0.1\n\n~~~\n\n## Requirements\n\nThis library requires Java 8 or later.\n\n## Usage\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nPlanListResponse plans = client.plans().list();\n```\n\n## Client configuration\n\nConfigure the client using system properties or environment variables:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n```\n\nOr manually:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .apiKey("My API Key")\n .build();\n```\n\nOr using a combination of the two approaches:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n // Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n // Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\n .fromEnv()\n .apiKey("My API Key")\n .build();\n```\n\nSee this table for the available options:\n\n| Setter | System property | Environment variable | Required | Default value |\n| --------- | ---------------- | -------------------- | -------- | ------------------------------------- |\n| `apiKey` | `beagle.apiKey` | `BEAGLE_API_KEY` | true | - |\n| `baseUrl` | `beagle.baseUrl` | `BEAGLE_BASE_URL` | true | `"https://developer.beagleforpm.com"` |\n\nSystem properties take precedence over environment variables.\n\n> [!TIP]\n> Don\'t create more than one client in the same application. Each client has a connection pool and\n> thread pools, which are more efficient to share between requests.\n\n### Modifying configuration\n\nTo temporarily use a modified client configuration, while reusing the same connection and thread pools, call `withOptions()` on any client or service:\n\n```java\nimport com.beagle.api.client.BeagleClient;\n\nBeagleClient clientWithOptions = client.withOptions(optionsBuilder -> {\n optionsBuilder.baseUrl("https://example.com");\n optionsBuilder.maxRetries(42);\n});\n```\n\nThe `withOptions()` method does not affect the original client or service.\n\n## Requests and responses\n\nTo send a request to the Beagle API, build an instance of some `Params` class and pass it to the corresponding client method. When the response is received, it will be deserialized into an instance of a Java class.\n\nFor example, `client.plans().list(...)` should be called with an instance of `PlanListParams`, and it will return an instance of `PlanListResponse`.\n\n## Immutability\n\nEach class in the SDK has an associated [builder](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java) or factory method for constructing it.\n\nEach class is [immutable](https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html) once constructed. If the class has an associated builder, then it has a `toBuilder()` method, which can be used to convert it back to a builder for making a modified copy.\n\nBecause each class is immutable, builder modification will _never_ affect already built class instances.\n\n## Asynchronous execution\n\nThe default client is synchronous. To switch to asynchronous execution, call the `async()` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nCompletableFuture plans = client.async().plans().list();\n```\n\nOr create an asynchronous client from the beginning:\n\n```java\nimport com.beagle.api.client.BeagleClientAsync;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClientAsync;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClientAsync client = BeagleOkHttpClientAsync.fromEnv();\n\nCompletableFuture plans = client.plans().list();\n```\n\nThe asynchronous client supports the same options as the synchronous one, except most methods return `CompletableFuture`s.\n\n\n\n\n\n## Binary responses\n\nThe SDK defines methods that return binary responses, which are used for API responses that shouldn\'t necessarily be parsed, like non-JSON data.\n\nThese methods return [`HttpResponse`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpResponse.kt):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport com.beagle.api.models.enrollments.EnrollmentRetrieveCertificateParams;\n\nHttpResponse response = client.enrollments().retrieveCertificate(123.0);\n```\n\nTo save the response content to a file, use the [`Files.copy(...)`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#copy-java.io.InputStream-java.nio.file.Path-java.nio.file.CopyOption...-) method:\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.nio.file.StandardCopyOption;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n Files.copy(\n response.body(),\n Paths.get(path),\n StandardCopyOption.REPLACE_EXISTING\n );\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\nOr transfer the response content to any [`OutputStream`](https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n response.body().transferTo(Files.newOutputStream(Paths.get(path)));\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\n## Raw responses\n\nThe SDK defines methods that deserialize responses into instances of Java classes. However, these methods don\'t provide access to the response headers, status code, or the raw response body.\n\nTo access this data, prefix any HTTP method call on a client or service with `withRawResponse()`:\n\n```java\nimport com.beagle.api.core.http.Headers;\nimport com.beagle.api.core.http.HttpResponseFor;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\nHttpResponseFor plans = client.plans().withRawResponse().list();\n\nint statusCode = plans.statusCode();\nHeaders headers = plans.headers();\n```\n\nYou can still deserialize the response into an instance of a Java class if needed:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse parsedPlans = plans.parse();\n```\n\n## Error handling\n\nThe SDK throws custom unchecked exception types:\n\n- [`BeagleServiceException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleServiceException.kt): Base class for HTTP errors. See this table for which exception subclass is thrown for each HTTP status code:\n\n | Status | Exception |\n | ------ | -------------------------------------------------- |\n | 400 | [`BadRequestException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BadRequestException.kt) |\n | 401 | [`UnauthorizedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnauthorizedException.kt) |\n | 403 | [`PermissionDeniedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/PermissionDeniedException.kt) |\n | 404 | [`NotFoundException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/NotFoundException.kt) |\n | 422 | [`UnprocessableEntityException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnprocessableEntityException.kt) |\n | 429 | [`RateLimitException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/RateLimitException.kt) |\n | 5xx | [`InternalServerException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/InternalServerException.kt) |\n | others | [`UnexpectedStatusCodeException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnexpectedStatusCodeException.kt) |\n\n- [`BeagleIoException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleIoException.kt): I/O networking errors.\n\n- [`BeagleRetryableException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleRetryableException.kt): Generic error indicating a failure that could be retried by the client.\n\n- [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt): Failure to interpret successfully parsed data. For example, when accessing a property that\'s supposed to be required, but the API unexpectedly omitted it from the response.\n\n- [`BeagleException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleException.kt): Base class for all exceptions. Most errors will result in one of the previously mentioned ones, but completely generic errors may be thrown using the base class.\n\n\n\n## Logging\n\nThe SDK uses the standard [OkHttp logging interceptor](https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor).\n\nEnable logging by setting the `BEAGLE_LOG` environment variable to `info`:\n\n```sh\nexport BEAGLE_LOG=info\n```\n\nOr to `debug` for more verbose logging:\n\n```sh\nexport BEAGLE_LOG=debug\n```\n\n## ProGuard and R8\n\nAlthough the SDK uses reflection, it is still usable with [ProGuard](https://github.com/Guardsquare/proguard) and [R8](https://developer.android.com/topic/performance/app-optimization/enable-app-optimization) because `beagle-java-core` is published with a [configuration file](beagle-java-core/src/main/resources/META-INF/proguard/beagle-java-core.pro) containing [keep rules](https://www.guardsquare.com/manual/configuration/usage).\n\nProGuard and R8 should automatically detect and use the published rules, but you can also manually copy the keep rules if necessary.\n\n\n\n\n\n## Jackson\n\nThe SDK depends on [Jackson](https://github.com/FasterXML/jackson) for JSON serialization/deserialization. It is compatible with version 2.13.4 or higher, but depends on version 2.18.2 by default.\n\nThe SDK throws an exception if it detects an incompatible Jackson version at runtime (e.g. if the default version was overridden in your Maven or Gradle config).\n\nIf the SDK threw an exception, but you\'re _certain_ the version is compatible, then disable the version check using the `checkJacksonVersionCompatibility` on [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt).\n\n> [!CAUTION]\n> We make no guarantee that the SDK works correctly when the Jackson version check is disabled.\n\nAlso note that there are bugs in older Jackson versions that can affect the SDK. We don\'t work around all Jackson bugs ([example](https://github.com/FasterXML/jackson-databind/issues/3240)) and expect users to upgrade Jackson for those instead.\n\n## Network options\n\n### Retries\n\nThe SDK automatically retries 2 times by default, with a short exponential backoff between requests.\n\nOnly the following error types are retried:\n- Connection errors (for example, due to a network connectivity problem)\n- 408 Request Timeout\n- 409 Conflict\n- 429 Rate Limit\n- 5xx Internal\n\nThe API may also explicitly instruct the SDK to retry or not retry a request.\n\nTo set a custom number of retries, configure the client using the `maxRetries` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .maxRetries(4)\n .build();\n```\n\n### Timeouts\n\nRequests time out after 1 minute by default.\n\nTo set a custom timeout, configure the method call using the `timeout` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().timeout(Duration.ofSeconds(30)).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .timeout(Duration.ofSeconds(30))\n .build();\n```\n\n### Proxies\n\nTo route requests through a proxy, configure the client using the `proxy` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.net.InetSocketAddress;\nimport java.net.Proxy;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .proxy(new Proxy(\n Proxy.Type.HTTP, new InetSocketAddress(\n "https://example.com", 8080\n )\n ))\n .build();\n```\n\n### Connection pooling\n\nTo customize the underlying OkHttp connection pool, configure the client using the `maxIdleConnections` and `keepAliveDuration` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `maxIdleConnections` is set, then `keepAliveDuration` must be set, and vice versa.\n .maxIdleConnections(10)\n .keepAliveDuration(Duration.ofMinutes(2))\n .build();\n```\n\nIf both options are unset, OkHttp\'s default connection pool settings are used.\n\n### HTTPS\n\n> [!NOTE]\n> Most applications should not call these methods, and instead use the system defaults. The defaults include\n> special optimizations that can be lost if the implementations are modified.\n\nTo configure how HTTPS connections are secured, configure the client using the `sslSocketFactory`, `trustManager`, and `hostnameVerifier` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `sslSocketFactory` is set, then `trustManager` must be set, and vice versa.\n .sslSocketFactory(yourSSLSocketFactory)\n .trustManager(yourTrustManager)\n .hostnameVerifier(yourHostnameVerifier)\n .build();\n```\n\n### Environments\n\nThe SDK sends requests to the production by default. To send requests to a different environment, configure the client like so:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .staging()\n .build();\n```\n\n### Custom HTTP client\n\nThe SDK consists of three artifacts:\n- `beagle-java-core`\n - Contains core SDK logic\n - Does not depend on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleClient`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClient.kt), [`BeagleClientAsync`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsync.kt), [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt), and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), all of which can work with any HTTP client\n- `beagle-java-client-okhttp`\n - Depends on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) and [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), which provide a way to construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), respectively, using OkHttp\n- `beagle-java`\n - Depends on and exposes the APIs of both `beagle-java-core` and `beagle-java-client-okhttp`\n - Does not have its own logic\n\nThis structure allows replacing the SDK\'s default HTTP client without pulling in unnecessary dependencies.\n\n#### Customized [`OkHttpClient`](https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.html)\n\n> [!TIP]\n> Try the available [network options](#network-options) before replacing the default client.\n\nTo use a customized `OkHttpClient`:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Copy `beagle-java-client-okhttp`\'s [`OkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/OkHttpClient.kt) class into your code and customize it\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your customized client\n\n### Completely custom HTTP client\n\nTo use a completely custom HTTP client:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Write a class that implements the [`HttpClient`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpClient.kt) interface\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your new client class\n\n## Undocumented API functionality\n\nThe SDK is typed for convenient usage of the documented API. However, it also supports working with undocumented or not yet supported parts of the API.\n\n### Parameters\n\nTo set undocumented parameters, call the `putAdditionalHeader`, `putAdditionalQueryParam`, or `putAdditionalBodyProperty` methods on any `Params` class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder()\n .putAdditionalHeader("Secret-Header", "42")\n .putAdditionalQueryParam("secret_query_param", "42")\n .putAdditionalBodyProperty("secretProperty", JsonValue.from("42"))\n .build();\n```\n\nThese can be accessed on the built object later using the `_additionalHeaders()`, `_additionalQueryParams()`, and `_additionalBodyProperties()` methods.\n\nTo set undocumented parameters on _nested_ headers, query params, or body classes, call the `putAdditionalProperty` method on the nested class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.tenants.Address;\nimport com.beagle.api.models.tenants.TenantCreateParams;\n\nTenantCreateParams params = TenantCreateParams.builder()\n .address(Address.builder()\n .putAdditionalProperty("secretProperty", JsonValue.from("42"))\n .build())\n .build();\n```\n\nThese properties can be accessed on the nested built object later using the `_additionalProperties()` method.\n\nTo set a documented parameter or property to an undocumented or not yet supported _value_, pass a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) object to its setter:\n\n```java\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder().build();\n```\n\nThe most straightforward way to create a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) is using its `from(...)` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.List;\nimport java.util.Map;\n\n// Create primitive JSON values\nJsonValue nullValue = JsonValue.from(null);\nJsonValue booleanValue = JsonValue.from(true);\nJsonValue numberValue = JsonValue.from(42);\nJsonValue stringValue = JsonValue.from("Hello World!");\n\n// Create a JSON array value equivalent to `["Hello", "World"]`\nJsonValue arrayValue = JsonValue.from(List.of(\n "Hello", "World"\n));\n\n// Create a JSON object value equivalent to `{ "a": 1, "b": 2 }`\nJsonValue objectValue = JsonValue.from(Map.of(\n "a", 1,\n "b", 2\n));\n\n// Create an arbitrarily nested JSON equivalent to:\n// {\n// "a": [1, 2],\n// "b": [3, 4]\n// }\nJsonValue complexValue = JsonValue.from(Map.of(\n "a", List.of(\n 1, 2\n ),\n "b", List.of(\n 3, 4\n )\n));\n```\n\nNormally a `Builder` class\'s `build` method will throw [`IllegalStateException`](https://docs.oracle.com/javase/8/docs/api/java/lang/IllegalStateException.html) if any required parameter or property is unset.\n\nTo forcibly omit a required parameter or property, pass [`JsonMissing`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt):\n\n```java\nimport com.beagle.api.core.JsonMissing;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanRetrieveParams;\n\nPlanListParams params = PlanRetrieveParams.builder()\n .code(JsonMissing.of())\n .build();\n```\n\n### Response properties\n\nTo access undocumented response properties, call the `_additionalProperties()` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.Map;\n\nMap additionalProperties = client.plans().list(params)._additionalProperties();\nJsonValue secretPropertyValue = additionalProperties.get("secretProperty");\n\nString result = secretPropertyValue.accept(new JsonValue.Visitor<>() {\n @Override\n public String visitNull() {\n return "It\'s null!";\n }\n\n @Override\n public String visitBoolean(boolean value) {\n return "It\'s a boolean!";\n }\n\n @Override\n public String visitNumber(Number value) {\n return "It\'s a number!";\n }\n\n // Other methods include `visitMissing`, `visitString`, `visitArray`, and `visitObject`\n // The default implementation of each unimplemented method delegates to `visitDefault`, which throws by default, but can also be overridden\n});\n```\n\nTo access a property\'s raw JSON value, which may be undocumented, call its `_` prefixed method:\n\n```java\nimport com.beagle.api.core.JsonField;\nimport java.util.Optional;\n\nJsonField field = client.plans().list(params)._field();\n\nif (field.isMissing()) {\n // The property is absent from the JSON response\n} else if (field.isNull()) {\n // The property was set to literal null\n} else {\n // Check if value was provided as a string\n // Other methods include `asNumber()`, `asBoolean()`, etc.\n Optional jsonString = field.asString();\n\n // Try to deserialize into a custom type\n MyClass myObject = field.asUnknown().orElseThrow().convert(MyClass.class);\n}\n```\n\n### Response validation\n\nIn rare cases, the API may return a response that doesn\'t match the expected type. For example, the SDK may expect a property to contain a `String`, but the API could return something else.\n\nBy default, the SDK will not throw an exception in this case. It will throw [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt) only if you directly access the property.\n\nIf you would prefer to check that the response is completely well-typed upfront, then either call `validate()`:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(params).validate();\n```\n\nOr configure the method call to validate the response using the `responseValidation` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().responseValidation(true).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .responseValidation(true)\n .build();\n```\n\n## FAQ\n\n### Why don\'t you use plain `enum` classes?\n\nJava `enum` classes are not trivially [forwards compatible](https://www.stainless.com/blog/making-java-enums-forwards-compatible). Using them in the SDK could cause runtime exceptions if the API is updated to respond with a new enum value.\n\n### Why do you represent fields using `JsonField` instead of just plain `T`?\n\nUsing `JsonField` enables a few features:\n\n- Allowing usage of [undocumented API functionality](#undocumented-api-functionality)\n- Lazily [validating the API response against the expected shape](#response-validation)\n- Representing absent vs explicitly null values\n\n### Why don\'t you use [`data` classes](https://kotlinlang.org/docs/data-classes.html)?\n\nIt is not [backwards compatible to add new fields to a data class](https://kotlinlang.org/docs/api-guidelines-backward-compatibility.html#avoid-using-data-classes-in-your-api) and we don\'t want to introduce a breaking change every time we add a field to a class.\n\n### Why don\'t you use checked exceptions?\n\nChecked exceptions are widely considered a mistake in the Java programming language. In fact, they were omitted from Kotlin for this reason.\n\nChecked exceptions:\n\n- Are verbose to handle\n- Encourage error handling at the wrong level of abstraction, where nothing can be done about the error\n- Are tedious to propagate due to the [function coloring problem](https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function)\n- Don\'t play well with lambdas (also due to the function coloring problem)\n\n## Semantic versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n2. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/beagle-java/issues) with questions, bugs, or suggestions.\n', + '# Beagle Ruby API library\n\nThe Beagle Ruby library provides convenient access to the Beagle REST API from any Ruby 3.2.0+ application. It ships with comprehensive types & docstrings in Yard, RBS, and RBI – [see below](https://github.com/stainless-sdks/beagle-ruby#Sorbet) for usage with Sorbet. The standard library\'s `net/http` is used as the HTTP transport, with connection pooling via the `connection_pool` gem.\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\n## Documentation\n\nDocumentation for releases of this gem can be found [on RubyDoc](https://gemdocs.org/gems/beagle).\n\n\n\n## Installation\n\nTo use this gem, install via Bundler by adding the following to your application\'s `Gemfile`:\n\n```ruby\ngem "beagle", "~> 0.0.1"\n```\n\n## Usage\n\n```ruby\nrequire "bundler/setup"\nrequire "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: ENV["BEAGLE_API_KEY"], # This is the default and can be omitted\n environment: "staging" # defaults to "production"\n)\n\nplans = beagle.plans.list\n\nputs(plans.data)\n```\n\n\n\n\n\n\n\n### Handling errors\n\nWhen the library is unable to connect to the API, or if the API returns a non-success status code (i.e., 4xx or 5xx response), a subclass of `Beagle::Errors::APIError` will be thrown:\n\n```ruby\nbegin\n plan = beagle.plans.list\nrescue Beagle::Errors::APIConnectionError => e\n puts("The server could not be reached")\n puts(e.cause) # an underlying Exception, likely raised within `net/http`\nrescue Beagle::Errors::RateLimitError => e\n puts("A 429 status code was received; we should back off a bit.")\nrescue Beagle::Errors::APIStatusError => e\n puts("Another non-200-range status code was received")\n puts(e.status)\nend\n```\n\nError codes are as follows:\n\n| Cause | Error Type |\n| ---------------- | -------------------------- |\n| HTTP 400 | `BadRequestError` |\n| HTTP 401 | `AuthenticationError` |\n| HTTP 403 | `PermissionDeniedError` |\n| HTTP 404 | `NotFoundError` |\n| HTTP 409 | `ConflictError` |\n| HTTP 422 | `UnprocessableEntityError` |\n| HTTP 429 | `RateLimitError` |\n| HTTP >= 500 | `InternalServerError` |\n| Other HTTP error | `APIStatusError` |\n| Timeout | `APITimeoutError` |\n| Network error | `APIConnectionError` |\n\n### Retries\n\nCertain errors will be automatically retried 2 times by default, with a short exponential backoff.\n\nConnection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict, 429 Rate Limit, >=500 Internal errors, and timeouts will all be retried by default.\n\nYou can use the `max_retries` option to configure or disable this:\n\n```ruby\n# Configure the default for all requests:\nbeagle = Beagle::Client.new(\n max_retries: 0 # default is 2\n)\n\n# Or, configure per-request:\nbeagle.plans.list(request_options: {max_retries: 5})\n```\n\n### Timeouts\n\nBy default, requests will time out after 60 seconds. You can use the timeout option to configure or disable this:\n\n```ruby\n# Configure the default for all requests:\nbeagle = Beagle::Client.new(\n timeout: nil # default is 60\n)\n\n# Or, configure per-request:\nbeagle.plans.list(request_options: {timeout: 5})\n```\n\nOn timeout, `Beagle::Errors::APITimeoutError` is raised.\n\nNote that requests that time out are retried by default.\n\n## Advanced concepts\n\n### BaseModel\n\nAll parameter and response objects inherit from `Beagle::Internal::Type::BaseModel`, which provides several conveniences, including:\n\n1. All fields, including unknown ones, are accessible with `obj[:prop]` syntax, and can be destructured with `obj => {prop: prop}` or pattern-matching syntax.\n\n2. Structural equivalence for equality; if two API calls return the same values, comparing the responses with == will return true.\n\n3. Both instances and the classes themselves can be pretty-printed.\n\n4. Helpers such as `#to_h`, `#deep_to_h`, `#to_json`, and `#to_yaml`.\n\n### Making custom or undocumented requests\n\n#### Undocumented properties\n\nYou can send undocumented parameters to any endpoint, and read undocumented response properties, like so:\n\nNote: the `extra_` parameters of the same name overrides the documented parameters.\n\n```ruby\nplans =\n beagle.plans.list(\n request_options: {\n extra_query: {my_query_parameter: value},\n extra_body: {my_body_parameter: value},\n extra_headers: {"my-header": value}\n }\n )\n\nputs(plans[:my_undocumented_property])\n```\n\n#### Undocumented request params\n\nIf you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` under the `request_options:` parameter when making a request, as seen in the examples above.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints while retaining the benefit of auth, retries, and so on, you can make requests using `client.request`, like so:\n\n```ruby\nresponse = client.request(\n method: :post,\n path: \'/undocumented/endpoint\',\n query: {"dog": "woof"},\n headers: {"useful-header": "interesting-value"},\n body: {"hello": "world"}\n)\n```\n\n### Concurrency & connection pooling\n\nThe `Beagle::Client` instances are threadsafe, but are only are fork-safe when there are no in-flight HTTP requests.\n\nEach instance of `Beagle::Client` has its own HTTP connection pool with a default size of 99. As such, we recommend instantiating the client once per application in most settings.\n\nWhen all available connections from the pool are checked out, requests wait for a new connection to become available, with queue time counting towards the request timeout.\n\nUnless otherwise specified, other classes in the SDK do not have locks protecting their underlying data structure.\n\n## Sorbet\n\nThis library provides comprehensive [RBI](https://sorbet.org/docs/rbi) definitions, and has no dependency on sorbet-runtime.\n\nYou can provide typesafe request parameters like so:\n\n```ruby\nbeagle.plans.list \n```\n\nOr, equivalently:\n\n```ruby\n# Hashes work, but are not typesafe:\nbeagle.plans.list\n\n# You can also splat a full Params class:\nparams = Beagle::PlanListParams.new\nbeagle.plans.list(**params)\n```\n\n### Enums\n\nSince this library does not depend on `sorbet-runtime`, it cannot provide [`T::Enum`](https://sorbet.org/docs/tenum) instances. Instead, we provide "tagged symbols" instead, which is always a primitive at runtime:\n\n```ruby\n# :"Premium Paying"\nputs(Beagle::EnrollmentCreateParams::Status::PREMIUM_PAYING)\n\n# Revealed type: `T.all(Beagle::EnrollmentCreateParams::Status, Symbol)`\nT.reveal_type(Beagle::EnrollmentCreateParams::Status::PREMIUM_PAYING)\n```\n\nEnum parameters have a "relaxed" type, so you can either pass in enum constants or their literal value:\n\n```ruby\n# Using the enum constants preserves the tagged type information:\nbeagle.enrollments.create(\n status: Beagle::EnrollmentCreateParams::Status::PREMIUM_PAYING,\n # …\n)\n\n# Literal values are also permissible:\nbeagle.enrollments.create(\n status: :"Premium Paying",\n # …\n)\n```\n\n## Versioning\n\nThis package follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions. As the library is in initial development and has a major version of `0`, APIs may change at any time.\n\nThis package considers improvements to the (non-runtime) `*.rbi` and `*.rbs` type definitions to be non-breaking changes.\n\n## Requirements\n\nRuby 3.2.0 or higher.\n\n## Contributing\n\nSee [the contributing documentation](https://github.com/stainless-sdks/beagle-ruby/tree/main/CONTRIBUTING.md).\n', }, { - language: 'csharp', + language: 'typescript', content: - '# Beagle C# API Library\n\nThe Beagle C# SDK provides convenient access to the Beagle REST API from applications written in C#.\n\n## Installation\n\n```bash\ngit clone git@github.com:stainless-sdks/beagle-csharp.git\ndotnet add reference beagle-csharp/src/Beagle\n```\n\n## Requirements\n\nThis library requires .NET Standard 2.0 or later.\n\n## Usage\n\nSee the [`examples`](examples) directory for complete and runnable examples.\n\n```csharp\nBeagleClient client = new();\n\nPlanListParams parameters = new();\n\nvar plans = await client.Plans.List(parameters);\n\nConsole.WriteLine(plans);\n```', + "# Beagle TypeScript API Library\n\n[![NPM version](https://img.shields.io/npm/v/@corgi-tech/beagle.svg?label=npm%20(stable))](https://npmjs.org/package/@corgi-tech/beagle) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@corgi-tech/beagle)\n\nThis library provides convenient access to the Beagle REST API from server-side TypeScript or JavaScript.\n\n\n\nThe full API of this library can be found in [api.md](api.md).\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\n## Installation\n\n```sh\nnpm install @corgi-tech/beagle\n```\n\n\n\n## Usage\n\nThe full API of this library can be found in [api.md](api.md).\n\n\n```js\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n environment: 'staging', // defaults to 'production'\n});\n\nconst plans = await client.plans.list();\n\nconsole.log(plans.data);\n```\n\n\n\n### Request & Response types\n\nThis library includes TypeScript definitions for all request params and response fields. You may import and use them like so:\n\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n environment: 'staging', // defaults to 'production'\n});\n\nconst plans: Beagle.PlanListResponse = await client.plans.list();\n```\n\nDocumentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors.\n\n\n\n\n\n## Handling errors\n\nWhen the library is unable to connect to the API,\nor if the API returns a non-success status code (i.e., 4xx or 5xx response),\na subclass of `APIError` will be thrown:\n\n\n```ts\nconst plans = await client.plans.list().catch(async (err) => {\n if (err instanceof Beagle.APIError) {\n console.log(err.status); // 400\n console.log(err.name); // BadRequestError\n console.log(err.headers); // {server: 'nginx', ...}\n } else {\n throw err;\n }\n});\n```\n\nError codes are as follows:\n\n| Status Code | Error Type |\n| ----------- | -------------------------- |\n| 400 | `BadRequestError` |\n| 401 | `AuthenticationError` |\n| 403 | `PermissionDeniedError` |\n| 404 | `NotFoundError` |\n| 422 | `UnprocessableEntityError` |\n| 429 | `RateLimitError` |\n| >=500 | `InternalServerError` |\n| N/A | `APIConnectionError` |\n\n### Retries\n\nCertain errors will be automatically retried 2 times by default, with a short exponential backoff.\nConnection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict,\n429 Rate Limit, and >=500 Internal errors will all be retried by default.\n\nYou can use the `maxRetries` option to configure or disable this:\n\n\n```js\n// Configure the default for all requests:\nconst client = new Beagle({\n maxRetries: 0, // default is 2\n});\n\n// Or, configure per-request:\nawait client.plans.list({\n maxRetries: 5,\n});\n```\n\n### Timeouts\n\nRequests time out after 1 minute by default. You can configure this with a `timeout` option:\n\n\n```ts\n// Configure the default for all requests:\nconst client = new Beagle({\n timeout: 20 * 1000, // 20 seconds (default is 1 minute)\n});\n\n// Override per-request:\nawait client.plans.list({\n timeout: 5 * 1000,\n});\n```\n\nOn timeout, an `APIConnectionTimeoutError` is thrown.\n\nNote that requests which time out will be [retried twice by default](#retries).\n\n\n\n\n\n## Advanced Usage\n\n### Accessing raw Response data (e.g., headers)\n\nThe \"raw\" `Response` returned by `fetch()` can be accessed through the `.asResponse()` method on the `APIPromise` type that all methods return.\nThis method returns as soon as the headers for a successful response are received and does not consume the response body, so you are free to write custom parsing or streaming logic.\n\nYou can also use the `.withResponse()` method to get the raw `Response` along with the parsed data.\nUnlike `.asResponse()` this method consumes the body, returning once it is parsed.\n\n\n```ts\nconst client = new Beagle();\n\nconst response = await client.plans.list().asResponse();\nconsole.log(response.headers.get('X-My-Header'));\nconsole.log(response.statusText); // access the underlying Response object\n\nconst { data: plans, response: raw } = await client.plans.list().withResponse();\nconsole.log(raw.headers.get('X-My-Header'));\nconsole.log(plans.data);\n```\n\n### Logging\n\n> [!IMPORTANT]\n> All log messages are intended for debugging only. The format and content of log messages\n> may change between releases.\n\n#### Log levels\n\nThe log level can be configured in two ways:\n\n1. Via the `BEAGLE_LOG` environment variable\n2. Using the `logLevel` client option (overrides the environment variable if set)\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n logLevel: 'debug', // Show all log messages\n});\n```\n\nAvailable log levels, from most to least verbose:\n\n- `'debug'` - Show debug messages, info, warnings, and errors\n- `'info'` - Show info messages, warnings, and errors\n- `'warn'` - Show warnings and errors (default)\n- `'error'` - Show only errors\n- `'off'` - Disable all logging\n\nAt the `'debug'` level, all HTTP requests and responses are logged, including headers and bodies.\nSome authentication-related headers are redacted, but sensitive data in request and response bodies\nmay still be visible.\n\n#### Custom logger\n\nBy default, this library logs to `globalThis.console`. You can also provide a custom logger.\nMost logging libraries are supported, including [pino](https://www.npmjs.com/package/pino), [winston](https://www.npmjs.com/package/winston), [bunyan](https://www.npmjs.com/package/bunyan), [consola](https://www.npmjs.com/package/consola), [signale](https://www.npmjs.com/package/signale), and [@std/log](https://jsr.io/@std/log). If your logger doesn't work, please open an issue.\n\nWhen providing a custom logger, the `logLevel` option still controls which messages are emitted, messages\nbelow the configured level will not be sent to your logger.\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\nimport pino from 'pino';\n\nconst logger = pino();\n\nconst client = new Beagle({\n logger: logger.child({ name: 'Beagle' }),\n logLevel: 'debug', // Send all messages to pino, allowing it to filter\n});\n```\n\n### Making custom/undocumented requests\n\nThis library is typed for convenient access to the documented API. If you need to access undocumented\nendpoints, params, or response properties, the library can still be used.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints, you can use `client.get`, `client.post`, and other HTTP verbs.\nOptions on the client, such as retries, will be respected when making these requests.\n\n```ts\nawait client.post('/some/path', {\n body: { some_prop: 'foo' },\n query: { some_query_arg: 'bar' },\n});\n```\n\n#### Undocumented request params\n\nTo make requests using undocumented parameters, you may use `// @ts-expect-error` on the undocumented\nparameter. This library doesn't validate at runtime that the request matches the type, so any extra values you\nsend will be sent as-is.\n\n```ts\nclient.plans.list({\n // ...\n // @ts-expect-error baz is not yet public\n baz: 'undocumented option',\n});\n```\n\nFor requests with the `GET` verb, any extra params will be in the query, all other requests will send the\nextra param in the body.\n\nIf you want to explicitly send an extra argument, you can do so with the `query`, `body`, and `headers` request\noptions.\n\n#### Undocumented response properties\n\nTo access undocumented response properties, you may access the response object with `// @ts-expect-error` on\nthe response object, or cast the response object to the requisite type. Like the request params, we do not\nvalidate or strip extra properties from the response from the API.\n\n### Customizing the fetch client\n\nBy default, this library expects a global `fetch` function is defined.\n\nIf you want to use a different `fetch` function, you can either polyfill the global:\n\n```ts\nimport fetch from 'my-fetch';\n\nglobalThis.fetch = fetch;\n```\n\nOr pass it to the client:\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\nimport fetch from 'my-fetch';\n\nconst client = new Beagle({ fetch });\n```\n\n### Fetch options\n\nIf you want to set custom `fetch` options without overriding the `fetch` function, you can provide a `fetchOptions` object when instantiating the client or making a request. (Request-specific options override client options.)\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n fetchOptions: {\n // `RequestInit` options\n },\n});\n```\n\n#### Configuring proxies\n\nTo modify proxy behavior, you can provide custom `fetchOptions` that add runtime-specific proxy\noptions to requests:\n\n **Node** [[docs](https://github.com/nodejs/undici/blob/main/docs/docs/api/ProxyAgent.md#example---proxyagent-with-fetch)]\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\nimport * as undici from 'undici';\n\nconst proxyAgent = new undici.ProxyAgent('http://localhost:8888');\nconst client = new Beagle({\n fetchOptions: {\n dispatcher: proxyAgent,\n },\n});\n```\n\n **Bun** [[docs](https://bun.sh/guides/http/proxy)]\n\n```ts\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n fetchOptions: {\n proxy: 'http://localhost:8888',\n },\n});\n```\n\n **Deno** [[docs](https://docs.deno.com/api/deno/~/Deno.createHttpClient)]\n\n```ts\nimport Beagle from 'npm:@corgi-tech/beagle';\n\nconst httpClient = Deno.createHttpClient({ proxy: { url: 'http://localhost:8888' } });\nconst client = new Beagle({\n fetchOptions: {\n client: httpClient,\n },\n});\n```\n\n## Frequently Asked Questions\n\n## Semantic versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes that only affect static types, without breaking runtime behavior.\n2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n3. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/corgi-tech/beagle-sdks/issues) with questions, bugs, or suggestions.\n\n## Requirements\n\nTypeScript >= 4.9 is supported.\n\nThe following runtimes are supported:\n\n- Web browsers (Up-to-date Chrome, Firefox, Safari, Edge, and more)\n- Node.js 20 LTS or later ([non-EOL](https://endoflife.date/nodejs)) versions.\n- Deno v1.28.0 or higher.\n- Bun 1.0 or later.\n- Cloudflare Workers.\n- Vercel Edge Runtime.\n- Jest 28 or greater with the `\"node\"` environment (`\"jsdom\"` is not supported at this time).\n- Nitro v2.6 or greater.\n\nNote that React Native is not supported at this time.\n\nIf you are interested in other runtime environments, please open or upvote an issue on GitHub.\n\n## Contributing\n\nSee [the contributing documentation](./CONTRIBUTING.md).\n", }, ]; diff --git a/scripts/bootstrap b/scripts/bootstrap index a8b69ff3..2e315f53 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,7 +4,7 @@ set -e cd "$(dirname "$0")/.." -if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "${SKIP_BREW:-}" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { echo -n "==> Install Homebrew dependencies? (y/N): " read -r response From 14bac3e858c0e5f2a22d2b6d46fdfd1f54ea68c0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 04:28:38 +0000 Subject: [PATCH 121/138] chore(internal): codegen related update --- packages/mcp-server/src/local-docs-search.ts | 572 +++++++++---------- scripts/utils/postprocess-files.cjs | 9 +- src/client.ts | 12 + 3 files changed, 306 insertions(+), 287 deletions(-) diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index f1bb2a08..3986ac90 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -63,38 +63,38 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## list\n\n`client.plans.list(): { data: plan[]; success: true; }`\n\n**get** `/api/plans`\n\nList all available insurance plans that tenants can be enrolled in.\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }[]; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }[]`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plans = await client.plans.list();\n\nconsole.log(plans);\n```", perLanguage: { - csharp: { - method: 'Plans.List', + typescript: { + method: 'client.plans.list', example: - 'PlanListParams parameters = new();\n\nvar plans = await client.Plans.List(parameters);\n\nConsole.WriteLine(plans);', + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst plans = await client.plans.list();\n\nconsole.log(plans.data);", }, - go: { - method: 'client.Plans.List', + python: { + method: 'plans.list', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tplans, err := client.Plans.List(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", plans.Data)\n}\n', - }, - http: { - example: 'curl https://developer.beagleforpm.com/api/plans \\\n -H "x-api-key: $BEAGLE_API_KEY"', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nplans = client.plans.list()\nprint(plans.data)', }, java: { method: 'plans().list', example: 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n PlanListResponse plans = client.plans().list();\n }\n}', }, - python: { - method: 'plans.list', + go: { + method: 'client.Plans.List', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nplans = client.plans.list()\nprint(plans.data)', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tplans, err := client.Plans.List(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", plans.Data)\n}\n', }, ruby: { method: 'plans.list', example: 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nplans = beagle.plans.list\n\nputs(plans)', }, - typescript: { - method: 'client.plans.list', + csharp: { + method: 'Plans.List', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst plans = await client.plans.list();\n\nconsole.log(plans.data);", + 'PlanListParams parameters = new();\n\nvar plans = await client.Plans.List(parameters);\n\nConsole.WriteLine(plans);', + }, + http: { + example: 'curl https://developer.beagleforpm.com/api/plans \\\n -H "x-api-key: $BEAGLE_API_KEY"', }, }, }, @@ -112,39 +112,39 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## retrieve\n\n`client.plans.retrieve(code: string): { data: plan; success: true; }`\n\n**get** `/api/plans/{code}`\n\nretrieve a specific plans details by its code.\n\n### Parameters\n\n- `code: string`\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plan = await client.plans.retrieve('code');\n\nconsole.log(plan);\n```", perLanguage: { - csharp: { - method: 'Plans.Retrieve', - example: - 'PlanRetrieveParams parameters = new() { Code = "code" };\n\nvar plan = await client.Plans.Retrieve(parameters);\n\nConsole.WriteLine(plan);', - }, - go: { - method: 'client.Plans.Get', + typescript: { + method: 'client.plans.retrieve', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tplan, err := client.Plans.Get(context.TODO(), "code")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", plan.Data)\n}\n', + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst plan = await client.plans.retrieve('code');\n\nconsole.log(plan.data);", }, - http: { + python: { + method: 'plans.retrieve', example: - 'curl https://developer.beagleforpm.com/api/plans/$CODE \\\n -H "x-api-key: $BEAGLE_API_KEY"', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nplan = client.plans.retrieve(\n "code",\n)\nprint(plan.data)', }, java: { method: 'plans().retrieve', example: 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanRetrieveParams;\nimport com.beagle.api.models.plans.PlanRetrieveResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n PlanRetrieveResponse plan = client.plans().retrieve("code");\n }\n}', }, - python: { - method: 'plans.retrieve', + go: { + method: 'client.Plans.Get', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nplan = client.plans.retrieve(\n "code",\n)\nprint(plan.data)', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tplan, err := client.Plans.Get(context.TODO(), "code")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", plan.Data)\n}\n', }, ruby: { method: 'plans.retrieve', example: 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nplan = beagle.plans.retrieve("code")\n\nputs(plan)', }, - typescript: { - method: 'client.plans.retrieve', + csharp: { + method: 'Plans.Retrieve', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst plan = await client.plans.retrieve('code');\n\nconsole.log(plan.data);", + 'PlanRetrieveParams parameters = new() { Code = "code" };\n\nvar plan = await client.Plans.Retrieve(parameters);\n\nConsole.WriteLine(plan);', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/plans/$CODE \\\n -H "x-api-key: $BEAGLE_API_KEY"', }, }, }, @@ -162,39 +162,39 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## retrieve\n\n`client.propertyManagers.retrieve(id: number): { data: property_manager; success: true; }`\n\n**get** `/api/property-managers/{id}`\n\nget a property manager by id.\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; totalUnits?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; totalUnits?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.retrieve(123);\n\nconsole.log(propertyManager);\n```", perLanguage: { - csharp: { - method: 'PropertyManagers.Retrieve', - example: - 'PropertyManagerRetrieveParams parameters = new() { ID = 123 };\n\nvar propertyManager = await client.PropertyManagers.Retrieve(parameters);\n\nConsole.WriteLine(propertyManager);', - }, - go: { - method: 'client.PropertyManagers.Get', + typescript: { + method: 'client.propertyManagers.retrieve', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tpropertyManager, err := client.PropertyManagers.Get(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", propertyManager.Data)\n}\n', + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst propertyManager = await client.propertyManagers.retrieve(123);\n\nconsole.log(propertyManager.data);", }, - http: { + python: { + method: 'property_managers.retrieve', example: - 'curl https://developer.beagleforpm.com/api/property-managers/$ID \\\n -H "x-api-key: $BEAGLE_API_KEY"', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nproperty_manager = client.property_managers.retrieve(\n 123,\n)\nprint(property_manager.data)', }, java: { method: 'propertyManagers().retrieve', example: 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.propertymanagers.PropertyManagerRetrieveParams;\nimport com.beagle.api.models.propertymanagers.PropertyManagerRetrieveResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n PropertyManagerRetrieveResponse propertyManager = client.propertyManagers().retrieve(123.0);\n }\n}', }, - python: { - method: 'property_managers.retrieve', + go: { + method: 'client.PropertyManagers.Get', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nproperty_manager = client.property_managers.retrieve(\n 123,\n)\nprint(property_manager.data)', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tpropertyManager, err := client.PropertyManagers.Get(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", propertyManager.Data)\n}\n', }, ruby: { method: 'property_managers.retrieve', example: 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nproperty_manager = beagle.property_managers.retrieve(123)\n\nputs(property_manager)', }, - typescript: { - method: 'client.propertyManagers.retrieve', + csharp: { + method: 'PropertyManagers.Retrieve', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst propertyManager = await client.propertyManagers.retrieve(123);\n\nconsole.log(propertyManager.data);", + 'PropertyManagerRetrieveParams parameters = new() { ID = 123 };\n\nvar propertyManager = await client.PropertyManagers.Retrieve(parameters);\n\nConsole.WriteLine(propertyManager);', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/property-managers/$ID \\\n -H "x-api-key: $BEAGLE_API_KEY"', }, }, }, @@ -220,39 +220,39 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## update\n\n`client.propertyManagers.update(id: number, addresses?: { city: string; state: string; street1: string; zip: string; street2?: string; }[], clickWrapAt?: number, contacts?: { email: string; name: object; phone?: string; }[], name?: string, totalUnits?: number): { data: property_manager; success: true; }`\n\n**patch** `/api/property-managers/{id}`\n\nupdate an existing property manager by ID\n\n(Note that when updating **contacts** or **addresses** you need to send the whole array you want to replace them with)\n\n### Parameters\n\n- `id: number`\n\n- `addresses?: { city: string; state: string; street1: string; zip: string; street2?: string; }[]`\n street addresses for each Property\n\n- `clickWrapAt?: number`\n unix timestamp (ms) of clickwrap agreement signature\n\n- `contacts?: { email: string; name: { first: string; last: string; }; phone?: string; }[]`\n contact information for each Property Manager\n\n- `name?: string`\n name of the Property Management Company\n\n- `totalUnits?: number`\n total number of units managed by this property manager\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; totalUnits?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; totalUnits?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.update(123);\n\nconsole.log(propertyManager);\n```", perLanguage: { - csharp: { - method: 'PropertyManagers.Update', - example: - 'PropertyManagerUpdateParams parameters = new() { ID = 123 };\n\nvar propertyManager = await client.PropertyManagers.Update(parameters);\n\nConsole.WriteLine(propertyManager);', - }, - go: { - method: 'client.PropertyManagers.Update', + typescript: { + method: 'client.propertyManagers.update', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tpropertyManager, err := client.PropertyManagers.Update(\n\t\tcontext.TODO(),\n\t\t123,\n\t\tbeagle.PropertyManagerUpdateParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", propertyManager.Data)\n}\n', + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst propertyManager = await client.propertyManagers.update(123);\n\nconsole.log(propertyManager.data);", }, - http: { + python: { + method: 'property_managers.update', example: - "curl https://developer.beagleforpm.com/api/property-managers/$ID \\\n -X PATCH \\\n -H 'Content-Type: application/json' \\\n -H \"x-api-key: $BEAGLE_API_KEY\" \\\n -d '{}'", + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nproperty_manager = client.property_managers.update(\n id=123,\n)\nprint(property_manager.data)', }, java: { method: 'propertyManagers().update', example: 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.propertymanagers.PropertyManagerUpdateParams;\nimport com.beagle.api.models.propertymanagers.PropertyManagerUpdateResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n PropertyManagerUpdateResponse propertyManager = client.propertyManagers().update(123.0);\n }\n}', }, - python: { - method: 'property_managers.update', + go: { + method: 'client.PropertyManagers.Update', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nproperty_manager = client.property_managers.update(\n id=123,\n)\nprint(property_manager.data)', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tpropertyManager, err := client.PropertyManagers.Update(\n\t\tcontext.TODO(),\n\t\t123,\n\t\tbeagle.PropertyManagerUpdateParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", propertyManager.Data)\n}\n', }, ruby: { method: 'property_managers.update', example: 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nproperty_manager = beagle.property_managers.update(123)\n\nputs(property_manager)', }, - typescript: { - method: 'client.propertyManagers.update', + csharp: { + method: 'PropertyManagers.Update', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst propertyManager = await client.propertyManagers.update(123);\n\nconsole.log(propertyManager.data);", + 'PropertyManagerUpdateParams parameters = new() { ID = 123 };\n\nvar propertyManager = await client.PropertyManagers.Update(parameters);\n\nConsole.WriteLine(propertyManager);', + }, + http: { + example: + "curl https://developer.beagleforpm.com/api/property-managers/$ID \\\n -X PATCH \\\n -H 'Content-Type: application/json' \\\n -H \"x-api-key: $BEAGLE_API_KEY\" \\\n -d '{}'", }, }, }, @@ -268,39 +268,39 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## delete\n\n`client.propertyManagers.delete(id: number): void`\n\n**delete** `/api/property-managers/{id}`\n\ndelete a property manager by ID.\n\n### Parameters\n\n- `id: number`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nawait client.propertyManagers.delete(123)\n```", perLanguage: { - csharp: { - method: 'PropertyManagers.Delete', - example: - 'PropertyManagerDeleteParams parameters = new() { ID = 123 };\n\nawait client.PropertyManagers.Delete(parameters);', - }, - go: { - method: 'client.PropertyManagers.Delete', + typescript: { + method: 'client.propertyManagers.delete', example: - 'package main\n\nimport (\n\t"context"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\terr := client.PropertyManagers.Delete(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nawait client.propertyManagers.delete(123);", }, - http: { + python: { + method: 'property_managers.delete', example: - 'curl https://developer.beagleforpm.com/api/property-managers/$ID \\\n -X DELETE \\\n -H "x-api-key: $BEAGLE_API_KEY"', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nclient.property_managers.delete(\n 123,\n)', }, java: { method: 'propertyManagers().delete', example: 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.propertymanagers.PropertyManagerDeleteParams;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n client.propertyManagers().delete(123.0);\n }\n}', }, - python: { - method: 'property_managers.delete', + go: { + method: 'client.PropertyManagers.Delete', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nclient.property_managers.delete(\n 123,\n)', + 'package main\n\nimport (\n\t"context"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\terr := client.PropertyManagers.Delete(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', }, ruby: { method: 'property_managers.delete', example: 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nresult = beagle.property_managers.delete(123)\n\nputs(result)', }, - typescript: { - method: 'client.propertyManagers.delete', + csharp: { + method: 'PropertyManagers.Delete', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nawait client.propertyManagers.delete(123);", + 'PropertyManagerDeleteParams parameters = new() { ID = 123 };\n\nawait client.PropertyManagers.Delete(parameters);', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/property-managers/$ID \\\n -X DELETE \\\n -H "x-api-key: $BEAGLE_API_KEY"', }, }, }, @@ -317,39 +317,39 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## list\n\n`client.propertyManagers.list(page?: number, size?: number): { data: object; success: true; }`\n\n**get** `/api/property-managers`\n\nlist all property managers, note this endpoint is paginated.\n\n### Parameters\n\n- `page?: number`\n Page number to fetch.\n\n- `size?: number`\n Number of items per page.\n\n### Returns\n\n- `{ data: { items: object[]; pagination: object; }; success: true; }`\n\n - `data: { items: { id: number; addresses: object[]; contacts: object[]; name: string; clickWrapAt?: number; totalUnits?: number; }[]; pagination: { page: number; pages: number; records: number; size: number; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManagers = await client.propertyManagers.list();\n\nconsole.log(propertyManagers);\n```", perLanguage: { - csharp: { - method: 'PropertyManagers.List', - example: - 'PropertyManagerListParams parameters = new();\n\nvar propertyManagers = await client.PropertyManagers.List(parameters);\n\nConsole.WriteLine(propertyManagers);', - }, - go: { - method: 'client.PropertyManagers.List', + typescript: { + method: 'client.propertyManagers.list', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tpropertyManagers, err := client.PropertyManagers.List(context.TODO(), beagle.PropertyManagerListParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", propertyManagers.Data)\n}\n', + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst propertyManagers = await client.propertyManagers.list();\n\nconsole.log(propertyManagers.data);", }, - http: { + python: { + method: 'property_managers.list', example: - 'curl https://developer.beagleforpm.com/api/property-managers \\\n -H "x-api-key: $BEAGLE_API_KEY"', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nproperty_managers = client.property_managers.list()\nprint(property_managers.data)', }, java: { method: 'propertyManagers().list', example: 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.propertymanagers.PropertyManagerListParams;\nimport com.beagle.api.models.propertymanagers.PropertyManagerListResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n PropertyManagerListResponse propertyManagers = client.propertyManagers().list();\n }\n}', }, - python: { - method: 'property_managers.list', + go: { + method: 'client.PropertyManagers.List', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nproperty_managers = client.property_managers.list()\nprint(property_managers.data)', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tpropertyManagers, err := client.PropertyManagers.List(context.TODO(), beagle.PropertyManagerListParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", propertyManagers.Data)\n}\n', }, ruby: { method: 'property_managers.list', example: 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nproperty_managers = beagle.property_managers.list\n\nputs(property_managers)', }, - typescript: { - method: 'client.propertyManagers.list', + csharp: { + method: 'PropertyManagers.List', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst propertyManagers = await client.propertyManagers.list();\n\nconsole.log(propertyManagers.data);", + 'PropertyManagerListParams parameters = new();\n\nvar propertyManagers = await client.PropertyManagers.List(parameters);\n\nConsole.WriteLine(propertyManagers);', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/property-managers \\\n -H "x-api-key: $BEAGLE_API_KEY"', }, }, }, @@ -373,39 +373,39 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## create\n\n`client.propertyManagers.create(addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[], contacts: { email: string; name: object; phone?: string; }[], name: string, clickWrapAt?: number, totalUnits?: number): { data: property_manager; success: true; }`\n\n**post** `/api/property-managers`\n\ncreate a new property manager.\n\n### Parameters\n\n- `addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]`\n street addresses for each Property\n\n- `contacts: { email: string; name: { first: string; last: string; }; phone?: string; }[]`\n contact information for each Property Manager\n\n- `name: string`\n name of the Property Management Company\n\n- `clickWrapAt?: number`\n unix timestamp (ms) of clickwrap agreement signature\n\n- `totalUnits?: number`\n total number of units managed by this property manager\n\n### Returns\n\n- `{ data: { id: number; addresses: address[]; contacts: contact[]; name: string; clickWrapAt?: number; totalUnits?: number; }; success: true; }`\n\n - `data: { id: number; addresses: { city: string; state: string; street1: string; zip: string; street2?: string; }[]; contacts: { email: string; name: object; phone?: string; }[]; name: string; clickWrapAt?: number; totalUnits?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst propertyManager = await client.propertyManagers.create({\n addresses: [{\n city: 'South Salt Lake',\n state: 'UT',\n street1: '123 Electric Ave.',\n zip: '84115',\n kind: 'place of business',\n}],\n contacts: [{\n email: 'mr.milchick@example.com',\n name: { first: 'Seth', last: 'Milchick' },\n kind: 'reporting',\n}],\n name: 'Lumon Apartments',\n});\n\nconsole.log(propertyManager);\n```", perLanguage: { - csharp: { - method: 'PropertyManagers.Create', - example: - 'PropertyManagerCreateParams parameters = new()\n{\n Addresses =\n [\n new()\n {\n City = "South Salt Lake",\n State = "UT",\n Street1 = "123 Electric Ave.",\n Zip = "84115",\n Street2 = "street2",\n Kind = Kind.PlaceOfBusiness,\n },\n ],\n Contacts =\n [\n new()\n {\n Email = "mr.milchick@example.com",\n Name = new()\n {\n First = "Seth",\n Last = "Milchick",\n },\n Phone = "(123) 456-7890",\n Kind = Kind.Reporting,\n },\n ],\n Name = "Lumon Apartments",\n};\n\nvar propertyManager = await client.PropertyManagers.Create(parameters);\n\nConsole.WriteLine(propertyManager);', - }, - go: { - method: 'client.PropertyManagers.New', + typescript: { + method: 'client.propertyManagers.create', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tpropertyManager, err := client.PropertyManagers.New(context.TODO(), beagle.PropertyManagerNewParams{\n\t\tAddresses: []beagle.PropertyManagerNewParamsAddress{{\n\t\t\tAddressParam: beagle.AddressParam{\n\t\t\t\tCity: "South Salt Lake",\n\t\t\t\tState: "UT",\n\t\t\t\tStreet1: "123 Electric Ave.",\n\t\t\t\tZip: "84115",\n\t\t\t},\n\t\t\tKind: "place of business",\n\t\t}},\n\t\tContacts: []beagle.PropertyManagerNewParamsContact{{\n\t\t\tContactParam: beagle.ContactParam{\n\t\t\t\tEmail: "mr.milchick@example.com",\n\t\t\t\tName: beagle.ContactNameParam{\n\t\t\t\t\tFirst: "Seth",\n\t\t\t\t\tLast: "Milchick",\n\t\t\t\t},\n\t\t\t},\n\t\t\tKind: "reporting",\n\t\t}},\n\t\tName: "Lumon Apartments",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", propertyManager.Data)\n}\n', + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst propertyManager = await client.propertyManagers.create({\n addresses: [\n {\n city: 'South Salt Lake',\n state: 'UT',\n street1: '123 Electric Ave.',\n zip: '84115',\n kind: 'place of business',\n },\n ],\n contacts: [\n {\n email: 'mr.milchick@example.com',\n name: { first: 'Seth', last: 'Milchick' },\n kind: 'reporting',\n },\n ],\n name: 'Lumon Apartments',\n});\n\nconsole.log(propertyManager.data);", }, - http: { + python: { + method: 'property_managers.create', example: - 'curl https://developer.beagleforpm.com/api/property-managers \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "addresses": [\n {\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Electric Ave.",\n "zip": "84115",\n "kind": "place of business"\n }\n ],\n "contacts": [\n {\n "email": "mr.milchick@example.com",\n "name": {\n "first": "Seth",\n "last": "Milchick"\n },\n "phone": "(123) 456-7890",\n "kind": "reporting"\n }\n ],\n "name": "Lumon Apartments"\n }\'', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nproperty_manager = client.property_managers.create(\n addresses=[{\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Electric Ave.",\n "zip": "84115",\n "kind": "place of business",\n }],\n contacts=[{\n "email": "mr.milchick@example.com",\n "name": {\n "first": "Seth",\n "last": "Milchick",\n },\n "kind": "reporting",\n }],\n name="Lumon Apartments",\n)\nprint(property_manager.data)', }, java: { method: 'propertyManagers().create', example: 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.propertymanagers.PropertyManagerCreateParams;\nimport com.beagle.api.models.propertymanagers.PropertyManagerCreateResponse;\nimport com.beagle.api.models.tenants.Contact;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n PropertyManagerCreateParams params = PropertyManagerCreateParams.builder()\n .addAddress(PropertyManagerCreateParams.Address.builder()\n .city("South Salt Lake")\n .state("UT")\n .street1("123 Electric Ave.")\n .zip("84115")\n .kind(PropertyManagerCreateParams.Address.Kind.PLACE_OF_BUSINESS)\n .build())\n .addContact(PropertyManagerCreateParams.Contact.builder()\n .email("mr.milchick@example.com")\n .name(Contact.Name.builder()\n .first("Seth")\n .last("Milchick")\n .build())\n .kind(PropertyManagerCreateParams.Contact.Kind.REPORTING)\n .build())\n .name("Lumon Apartments")\n .build();\n PropertyManagerCreateResponse propertyManager = client.propertyManagers().create(params);\n }\n}', }, - python: { - method: 'property_managers.create', + go: { + method: 'client.PropertyManagers.New', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nproperty_manager = client.property_managers.create(\n addresses=[{\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Electric Ave.",\n "zip": "84115",\n "kind": "place of business",\n }],\n contacts=[{\n "email": "mr.milchick@example.com",\n "name": {\n "first": "Seth",\n "last": "Milchick",\n },\n "kind": "reporting",\n }],\n name="Lumon Apartments",\n)\nprint(property_manager.data)', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tpropertyManager, err := client.PropertyManagers.New(context.TODO(), beagle.PropertyManagerNewParams{\n\t\tAddresses: []beagle.PropertyManagerNewParamsAddress{{\n\t\t\tAddressParam: beagle.AddressParam{\n\t\t\t\tCity: "South Salt Lake",\n\t\t\t\tState: "UT",\n\t\t\t\tStreet1: "123 Electric Ave.",\n\t\t\t\tZip: "84115",\n\t\t\t},\n\t\t\tKind: "place of business",\n\t\t}},\n\t\tContacts: []beagle.PropertyManagerNewParamsContact{{\n\t\t\tContactParam: beagle.ContactParam{\n\t\t\t\tEmail: "mr.milchick@example.com",\n\t\t\t\tName: beagle.ContactNameParam{\n\t\t\t\t\tFirst: "Seth",\n\t\t\t\t\tLast: "Milchick",\n\t\t\t\t},\n\t\t\t},\n\t\t\tKind: "reporting",\n\t\t}},\n\t\tName: "Lumon Apartments",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", propertyManager.Data)\n}\n', }, ruby: { method: 'property_managers.create', example: 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nproperty_manager = beagle.property_managers.create(\n addresses: [\n {city: "South Salt Lake", state: "UT", street1: "123 Electric Ave.", zip: "84115", kind: :"place of business"}\n ],\n contacts: [{email: "mr.milchick@example.com", name: {first: "Seth", last: "Milchick"}, kind: :reporting}],\n name: "Lumon Apartments"\n)\n\nputs(property_manager)', }, - typescript: { - method: 'client.propertyManagers.create', + csharp: { + method: 'PropertyManagers.Create', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst propertyManager = await client.propertyManagers.create({\n addresses: [\n {\n city: 'South Salt Lake',\n state: 'UT',\n street1: '123 Electric Ave.',\n zip: '84115',\n kind: 'place of business',\n },\n ],\n contacts: [\n {\n email: 'mr.milchick@example.com',\n name: { first: 'Seth', last: 'Milchick' },\n kind: 'reporting',\n },\n ],\n name: 'Lumon Apartments',\n});\n\nconsole.log(propertyManager.data);", + 'PropertyManagerCreateParams parameters = new()\n{\n Addresses =\n [\n new()\n {\n City = "South Salt Lake",\n State = "UT",\n Street1 = "123 Electric Ave.",\n Zip = "84115",\n Street2 = "street2",\n Kind = Kind.PlaceOfBusiness,\n },\n ],\n Contacts =\n [\n new()\n {\n Email = "mr.milchick@example.com",\n Name = new()\n {\n First = "Seth",\n Last = "Milchick",\n },\n Phone = "(123) 456-7890",\n Kind = Kind.Reporting,\n },\n ],\n Name = "Lumon Apartments",\n};\n\nvar propertyManager = await client.PropertyManagers.Create(parameters);\n\nConsole.WriteLine(propertyManager);', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/property-managers \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "addresses": [\n {\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Electric Ave.",\n "zip": "84115",\n "kind": "place of business"\n }\n ],\n "contacts": [\n {\n "email": "mr.milchick@example.com",\n "name": {\n "first": "Seth",\n "last": "Milchick"\n },\n "phone": "(123) 456-7890",\n "kind": "reporting"\n }\n ],\n "name": "Lumon Apartments"\n }\'', }, }, }, @@ -422,39 +422,39 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## retrieve\n\n`client.tenants.retrieve(id: number): { data: tenant; success: true; }`\n\n**get** `/api/tenants/{id}`\n\nretrieve a single tenant by their id.\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.retrieve(123);\n\nconsole.log(tenant);\n```", perLanguage: { - csharp: { - method: 'Tenants.Retrieve', - example: - 'TenantRetrieveParams parameters = new() { ID = 123 };\n\nvar tenant = await client.Tenants.Retrieve(parameters);\n\nConsole.WriteLine(tenant);', - }, - go: { - method: 'client.Tenants.Get', + typescript: { + method: 'client.tenants.retrieve', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\ttenant, err := client.Tenants.Get(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", tenant.Data)\n}\n', + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst tenant = await client.tenants.retrieve(123);\n\nconsole.log(tenant.data);", }, - http: { + python: { + method: 'tenants.retrieve', example: - 'curl https://developer.beagleforpm.com/api/tenants/$ID \\\n -H "x-api-key: $BEAGLE_API_KEY"', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\ntenant = client.tenants.retrieve(\n 123,\n)\nprint(tenant.data)', }, java: { method: 'tenants().retrieve', example: 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.tenants.TenantRetrieveParams;\nimport com.beagle.api.models.tenants.TenantRetrieveResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n TenantRetrieveResponse tenant = client.tenants().retrieve(123.0);\n }\n}', }, - python: { - method: 'tenants.retrieve', + go: { + method: 'client.Tenants.Get', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\ntenant = client.tenants.retrieve(\n 123,\n)\nprint(tenant.data)', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\ttenant, err := client.Tenants.Get(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", tenant.Data)\n}\n', }, ruby: { method: 'tenants.retrieve', example: 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\ntenant = beagle.tenants.retrieve(123)\n\nputs(tenant)', }, - typescript: { - method: 'client.tenants.retrieve', + csharp: { + method: 'Tenants.Retrieve', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst tenant = await client.tenants.retrieve(123);\n\nconsole.log(tenant.data);", + 'TenantRetrieveParams parameters = new() { ID = 123 };\n\nvar tenant = await client.Tenants.Retrieve(parameters);\n\nConsole.WriteLine(tenant);', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/tenants/$ID \\\n -H "x-api-key: $BEAGLE_API_KEY"', }, }, }, @@ -475,39 +475,39 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## update\n\n`client.tenants.update(id: number, address?: { city: string; state: string; street1: string; zip: string; street2?: string; }, contact?: { email: string; name: object; phone?: string; }): { data: tenant; success: true; }`\n\n**patch** `/api/tenants/{id}`\n\nupdate an existing tenant by their id.\n\n### Parameters\n\n- `id: number`\n\n- `address?: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `city: string`\n - `state: string`\n two letter state code, ie CA\n - `street1: string`\n - `zip: string`\n 5 digit US zip code, ie 94104\n - `street2?: string`\n\n- `contact?: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `email: string`\n - `name: { first: string; last: string; }`\n - `phone?: string`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.update(123);\n\nconsole.log(tenant);\n```", perLanguage: { - csharp: { - method: 'Tenants.Update', - example: - 'TenantUpdateParams parameters = new() { ID = 123 };\n\nvar tenant = await client.Tenants.Update(parameters);\n\nConsole.WriteLine(tenant);', - }, - go: { - method: 'client.Tenants.Update', + typescript: { + method: 'client.tenants.update', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\ttenant, err := client.Tenants.Update(\n\t\tcontext.TODO(),\n\t\t123,\n\t\tbeagle.TenantUpdateParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", tenant.Data)\n}\n', + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst tenant = await client.tenants.update(123);\n\nconsole.log(tenant.data);", }, - http: { + python: { + method: 'tenants.update', example: - "curl https://developer.beagleforpm.com/api/tenants/$ID \\\n -X PATCH \\\n -H 'Content-Type: application/json' \\\n -H \"x-api-key: $BEAGLE_API_KEY\" \\\n -d '{}'", + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\ntenant = client.tenants.update(\n id=123,\n)\nprint(tenant.data)', }, java: { method: 'tenants().update', example: 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.tenants.TenantUpdateParams;\nimport com.beagle.api.models.tenants.TenantUpdateResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n TenantUpdateResponse tenant = client.tenants().update(123.0);\n }\n}', }, - python: { - method: 'tenants.update', + go: { + method: 'client.Tenants.Update', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\ntenant = client.tenants.update(\n id=123,\n)\nprint(tenant.data)', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\ttenant, err := client.Tenants.Update(\n\t\tcontext.TODO(),\n\t\t123,\n\t\tbeagle.TenantUpdateParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", tenant.Data)\n}\n', }, ruby: { method: 'tenants.update', example: 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\ntenant = beagle.tenants.update(123)\n\nputs(tenant)', }, - typescript: { - method: 'client.tenants.update', + csharp: { + method: 'Tenants.Update', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst tenant = await client.tenants.update(123);\n\nconsole.log(tenant.data);", + 'TenantUpdateParams parameters = new() { ID = 123 };\n\nvar tenant = await client.Tenants.Update(parameters);\n\nConsole.WriteLine(tenant);', + }, + http: { + example: + "curl https://developer.beagleforpm.com/api/tenants/$ID \\\n -X PATCH \\\n -H 'Content-Type: application/json' \\\n -H \"x-api-key: $BEAGLE_API_KEY\" \\\n -d '{}'", }, }, }, @@ -523,39 +523,39 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## delete\n\n`client.tenants.delete(id: number): void`\n\n**delete** `/api/tenants/{id}`\n\ndelete an existing tenant by their id.\n\n### Parameters\n\n- `id: number`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nawait client.tenants.delete(123)\n```", perLanguage: { - csharp: { - method: 'Tenants.Delete', - example: - 'TenantDeleteParams parameters = new() { ID = 123 };\n\nawait client.Tenants.Delete(parameters);', - }, - go: { - method: 'client.Tenants.Delete', + typescript: { + method: 'client.tenants.delete', example: - 'package main\n\nimport (\n\t"context"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\terr := client.Tenants.Delete(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nawait client.tenants.delete(123);", }, - http: { + python: { + method: 'tenants.delete', example: - 'curl https://developer.beagleforpm.com/api/tenants/$ID \\\n -X DELETE \\\n -H "x-api-key: $BEAGLE_API_KEY"', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nclient.tenants.delete(\n 123,\n)', }, java: { method: 'tenants().delete', example: 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.tenants.TenantDeleteParams;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n client.tenants().delete(123.0);\n }\n}', }, - python: { - method: 'tenants.delete', + go: { + method: 'client.Tenants.Delete', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nclient.tenants.delete(\n 123,\n)', + 'package main\n\nimport (\n\t"context"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\terr := client.Tenants.Delete(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', }, ruby: { method: 'tenants.delete', example: 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nresult = beagle.tenants.delete(123)\n\nputs(result)', }, - typescript: { - method: 'client.tenants.delete', + csharp: { + method: 'Tenants.Delete', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nawait client.tenants.delete(123);", + 'TenantDeleteParams parameters = new() { ID = 123 };\n\nawait client.Tenants.Delete(parameters);', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/tenants/$ID \\\n -X DELETE \\\n -H "x-api-key: $BEAGLE_API_KEY"', }, }, }, @@ -573,38 +573,38 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## list\n\n`client.tenants.list(page?: number, propertyManagerId?: number, size?: number): { data: object; success: true; }`\n\n**get** `/api/tenants`\n\nlist all tenants, this endpoint is paginated and allows for queries by individual property manager.\n\n### Parameters\n\n- `page?: number`\n Page number to fetch.\n\n- `propertyManagerId?: number`\n\n- `size?: number`\n Number of items per page.\n\n### Returns\n\n- `{ data: { items: object[]; pagination: object; }; success: true; }`\n\n - `data: { items: { id: number; address: object; contact: object; }[]; pagination: { page: number; pages: number; records: number; size: number; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenants = await client.tenants.list();\n\nconsole.log(tenants);\n```", perLanguage: { - csharp: { - method: 'Tenants.List', + typescript: { + method: 'client.tenants.list', example: - 'TenantListParams parameters = new();\n\nvar tenants = await client.Tenants.List(parameters);\n\nConsole.WriteLine(tenants);', + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst tenants = await client.tenants.list();\n\nconsole.log(tenants.data);", }, - go: { - method: 'client.Tenants.List', + python: { + method: 'tenants.list', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\ttenants, err := client.Tenants.List(context.TODO(), beagle.TenantListParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", tenants.Data)\n}\n', - }, - http: { - example: 'curl https://developer.beagleforpm.com/api/tenants \\\n -H "x-api-key: $BEAGLE_API_KEY"', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\ntenants = client.tenants.list()\nprint(tenants.data)', }, java: { method: 'tenants().list', example: 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.tenants.TenantListParams;\nimport com.beagle.api.models.tenants.TenantListResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n TenantListResponse tenants = client.tenants().list();\n }\n}', }, - python: { - method: 'tenants.list', + go: { + method: 'client.Tenants.List', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\ntenants = client.tenants.list()\nprint(tenants.data)', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\ttenants, err := client.Tenants.List(context.TODO(), beagle.TenantListParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", tenants.Data)\n}\n', }, ruby: { method: 'tenants.list', example: 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\ntenants = beagle.tenants.list\n\nputs(tenants)', }, - typescript: { - method: 'client.tenants.list', + csharp: { + method: 'Tenants.List', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst tenants = await client.tenants.list();\n\nconsole.log(tenants.data);", + 'TenantListParams parameters = new();\n\nvar tenants = await client.Tenants.List(parameters);\n\nConsole.WriteLine(tenants);', + }, + http: { + example: 'curl https://developer.beagleforpm.com/api/tenants \\\n -H "x-api-key: $BEAGLE_API_KEY"', }, }, }, @@ -625,39 +625,39 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## create\n\n`client.tenants.create(address: { city: string; state: string; street1: string; zip: string; street2?: string; }, contact: { email: string; name: object; phone?: string; }, propertyManagerId: number): { data: tenant; success: true; }`\n\n**post** `/api/tenants`\n\ncreate a new tenant.\n\n### Parameters\n\n- `address: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `city: string`\n - `state: string`\n two letter state code, ie CA\n - `street1: string`\n - `zip: string`\n 5 digit US zip code, ie 94104\n - `street2?: string`\n\n- `contact: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `email: string`\n - `name: { first: string; last: string; }`\n - `phone?: string`\n\n- `propertyManagerId: number`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.create({\n address: {\n city: 'South Salt Lake',\n state: 'UT',\n street1: '123 Main St.',\n zip: '84115',\n},\n contact: {\n email: 'mark.s@example.com',\n name: { first: 'Mark', last: 'Scout' },\n},\n propertyManagerId: 123,\n});\n\nconsole.log(tenant);\n```", perLanguage: { - csharp: { - method: 'Tenants.Create', - example: - 'TenantCreateParams parameters = new()\n{\n Address = new()\n {\n City = "South Salt Lake",\n State = "UT",\n Street1 = "123 Main St.",\n Zip = "84115",\n Street2 = "Unit 3",\n },\n Contact = new()\n {\n Email = "mark.s@example.com",\n Name = new()\n {\n First = "Mark",\n Last = "Scout",\n },\n Phone = "(123) 456-7890",\n },\n PropertyManagerID = 123,\n};\n\nvar tenant = await client.Tenants.Create(parameters);\n\nConsole.WriteLine(tenant);', - }, - go: { - method: 'client.Tenants.New', + typescript: { + method: 'client.tenants.create', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\ttenant, err := client.Tenants.New(context.TODO(), beagle.TenantNewParams{\n\t\tAddress: beagle.AddressParam{\n\t\t\tCity: "South Salt Lake",\n\t\t\tState: "UT",\n\t\t\tStreet1: "123 Main St.",\n\t\t\tZip: "84115",\n\t\t},\n\t\tContact: beagle.ContactParam{\n\t\t\tEmail: "mark.s@example.com",\n\t\t\tName: beagle.ContactNameParam{\n\t\t\t\tFirst: "Mark",\n\t\t\t\tLast: "Scout",\n\t\t\t},\n\t\t},\n\t\tPropertyManagerID: 123,\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", tenant.Data)\n}\n', + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst tenant = await client.tenants.create({\n address: {\n city: 'South Salt Lake',\n state: 'UT',\n street1: '123 Main St.',\n zip: '84115',\n },\n contact: {\n email: 'mark.s@example.com',\n name: { first: 'Mark', last: 'Scout' },\n },\n propertyManagerId: 123,\n});\n\nconsole.log(tenant.data);", }, - http: { + python: { + method: 'tenants.create', example: - 'curl https://developer.beagleforpm.com/api/tenants \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "address": {\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Main St.",\n "zip": "84115",\n "street2": "Unit 3"\n },\n "contact": {\n "email": "mark.s@example.com",\n "name": {\n "first": "Mark",\n "last": "Scout"\n },\n "phone": "(123) 456-7890"\n },\n "propertyManagerId": 123\n }\'', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\ntenant = client.tenants.create(\n address={\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Main St.",\n "zip": "84115",\n },\n contact={\n "email": "mark.s@example.com",\n "name": {\n "first": "Mark",\n "last": "Scout",\n },\n },\n property_manager_id=123,\n)\nprint(tenant.data)', }, java: { method: 'tenants().create', example: 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.tenants.Address;\nimport com.beagle.api.models.tenants.Contact;\nimport com.beagle.api.models.tenants.TenantCreateParams;\nimport com.beagle.api.models.tenants.TenantCreateResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n TenantCreateParams params = TenantCreateParams.builder()\n .address(Address.builder()\n .city("South Salt Lake")\n .state("UT")\n .street1("123 Main St.")\n .zip("84115")\n .build())\n .contact(Contact.builder()\n .email("mark.s@example.com")\n .name(Contact.Name.builder()\n .first("Mark")\n .last("Scout")\n .build())\n .build())\n .propertyManagerId(123.0)\n .build();\n TenantCreateResponse tenant = client.tenants().create(params);\n }\n}', }, - python: { - method: 'tenants.create', + go: { + method: 'client.Tenants.New', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\ntenant = client.tenants.create(\n address={\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Main St.",\n "zip": "84115",\n },\n contact={\n "email": "mark.s@example.com",\n "name": {\n "first": "Mark",\n "last": "Scout",\n },\n },\n property_manager_id=123,\n)\nprint(tenant.data)', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\ttenant, err := client.Tenants.New(context.TODO(), beagle.TenantNewParams{\n\t\tAddress: beagle.AddressParam{\n\t\t\tCity: "South Salt Lake",\n\t\t\tState: "UT",\n\t\t\tStreet1: "123 Main St.",\n\t\t\tZip: "84115",\n\t\t},\n\t\tContact: beagle.ContactParam{\n\t\t\tEmail: "mark.s@example.com",\n\t\t\tName: beagle.ContactNameParam{\n\t\t\t\tFirst: "Mark",\n\t\t\t\tLast: "Scout",\n\t\t\t},\n\t\t},\n\t\tPropertyManagerID: 123,\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", tenant.Data)\n}\n', }, ruby: { method: 'tenants.create', example: 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\ntenant = beagle.tenants.create(\n address: {city: "South Salt Lake", state: "UT", street1: "123 Main St.", zip: "84115"},\n contact: {email: "mark.s@example.com", name: {first: "Mark", last: "Scout"}},\n property_manager_id: 123\n)\n\nputs(tenant)', }, - typescript: { - method: 'client.tenants.create', + csharp: { + method: 'Tenants.Create', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst tenant = await client.tenants.create({\n address: {\n city: 'South Salt Lake',\n state: 'UT',\n street1: '123 Main St.',\n zip: '84115',\n },\n contact: {\n email: 'mark.s@example.com',\n name: { first: 'Mark', last: 'Scout' },\n },\n propertyManagerId: 123,\n});\n\nconsole.log(tenant.data);", + 'TenantCreateParams parameters = new()\n{\n Address = new()\n {\n City = "South Salt Lake",\n State = "UT",\n Street1 = "123 Main St.",\n Zip = "84115",\n Street2 = "Unit 3",\n },\n Contact = new()\n {\n Email = "mark.s@example.com",\n Name = new()\n {\n First = "Mark",\n Last = "Scout",\n },\n Phone = "(123) 456-7890",\n },\n PropertyManagerID = 123,\n};\n\nvar tenant = await client.Tenants.Create(parameters);\n\nConsole.WriteLine(tenant);', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/tenants \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "address": {\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Main St.",\n "zip": "84115",\n "street2": "Unit 3"\n },\n "contact": {\n "email": "mark.s@example.com",\n "name": {\n "first": "Mark",\n "last": "Scout"\n },\n "phone": "(123) 456-7890"\n },\n "propertyManagerId": 123\n }\'', }, }, }, @@ -675,39 +675,39 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## retrieve\n\n`client.enrollments.retrieve(id: number): { data: enrollment; success: true; }`\n\n**get** `/api/enrollments/{id}`\n\nget a specific enrollment by its id.\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }`\n\n - `data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollment = await client.enrollments.retrieve(123);\n\nconsole.log(enrollment);\n```", perLanguage: { - csharp: { - method: 'Enrollments.Retrieve', - example: - 'EnrollmentRetrieveParams parameters = new() { ID = 123 };\n\nvar enrollment = await client.Enrollments.Retrieve(parameters);\n\nConsole.WriteLine(enrollment);', - }, - go: { - method: 'client.Enrollments.Get', + typescript: { + method: 'client.enrollments.retrieve', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tenrollment, err := client.Enrollments.Get(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", enrollment.Data)\n}\n', + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst enrollment = await client.enrollments.retrieve(123);\n\nconsole.log(enrollment.data);", }, - http: { + python: { + method: 'enrollments.retrieve', example: - 'curl https://developer.beagleforpm.com/api/enrollments/$ID \\\n -H "x-api-key: $BEAGLE_API_KEY"', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nenrollment = client.enrollments.retrieve(\n 123,\n)\nprint(enrollment.data)', }, java: { method: 'enrollments().retrieve', example: 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.enrollments.EnrollmentRetrieveParams;\nimport com.beagle.api.models.enrollments.EnrollmentRetrieveResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n EnrollmentRetrieveResponse enrollment = client.enrollments().retrieve(123.0);\n }\n}', }, - python: { - method: 'enrollments.retrieve', + go: { + method: 'client.Enrollments.Get', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nenrollment = client.enrollments.retrieve(\n 123,\n)\nprint(enrollment.data)', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tenrollment, err := client.Enrollments.Get(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", enrollment.Data)\n}\n', }, ruby: { method: 'enrollments.retrieve', example: 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nenrollment = beagle.enrollments.retrieve(123)\n\nputs(enrollment)', }, - typescript: { - method: 'client.enrollments.retrieve', + csharp: { + method: 'Enrollments.Retrieve', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst enrollment = await client.enrollments.retrieve(123);\n\nconsole.log(enrollment.data);", + 'EnrollmentRetrieveParams parameters = new() { ID = 123 };\n\nvar enrollment = await client.Enrollments.Retrieve(parameters);\n\nConsole.WriteLine(enrollment);', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/enrollments/$ID \\\n -H "x-api-key: $BEAGLE_API_KEY"', }, }, }, @@ -724,39 +724,39 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## lapse\n\n`client.enrollments.lapse(id: number): void`\n\n**delete** `/api/enrollments/{id}`\n\nlapses a specific enrollment for a tenant, note that if a tenant has multiple enrollments (e.g., SDR and TLL), each must be lapsed individually\n\n### Parameters\n\n- `id: number`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nawait client.enrollments.lapse(123)\n```", perLanguage: { - csharp: { - method: 'Enrollments.Lapse', - example: - 'EnrollmentLapseParams parameters = new() { ID = 123 };\n\nawait client.Enrollments.Lapse(parameters);', - }, - go: { - method: 'client.Enrollments.Lapse', + typescript: { + method: 'client.enrollments.lapse', example: - 'package main\n\nimport (\n\t"context"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\terr := client.Enrollments.Lapse(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nawait client.enrollments.lapse(123);", }, - http: { + python: { + method: 'enrollments.lapse', example: - 'curl https://developer.beagleforpm.com/api/enrollments/$ID \\\n -X DELETE \\\n -H "x-api-key: $BEAGLE_API_KEY"', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nclient.enrollments.lapse(\n 123,\n)', }, java: { method: 'enrollments().lapse', example: 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.enrollments.EnrollmentLapseParams;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n client.enrollments().lapse(123.0);\n }\n}', }, - python: { - method: 'enrollments.lapse', + go: { + method: 'client.Enrollments.Lapse', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nclient.enrollments.lapse(\n 123,\n)', + 'package main\n\nimport (\n\t"context"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\terr := client.Enrollments.Lapse(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', }, ruby: { method: 'enrollments.lapse', example: 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nresult = beagle.enrollments.lapse(123)\n\nputs(result)', }, - typescript: { - method: 'client.enrollments.lapse', + csharp: { + method: 'Enrollments.Lapse', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nawait client.enrollments.lapse(123);", + 'EnrollmentLapseParams parameters = new() { ID = 123 };\n\nawait client.Enrollments.Lapse(parameters);', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/enrollments/$ID \\\n -X DELETE \\\n -H "x-api-key: $BEAGLE_API_KEY"', }, }, }, @@ -774,39 +774,39 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## list\n\n`client.enrollments.list(page?: number, propertyManagerId?: number, size?: number): { data: object; success: true; }`\n\n**get** `/api/enrollments`\n\nlist all enrollments, this endpoint is paginated and allows for queries by individual property manager.\n\n### Parameters\n\n- `page?: number`\n Page number to fetch.\n\n- `propertyManagerId?: number`\n\n- `size?: number`\n Number of items per page.\n\n### Returns\n\n- `{ data: { items: object[]; pagination: object; }; success: true; }`\n\n - `data: { items: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }[]; pagination: { page: number; pages: number; records: number; size: number; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollments = await client.enrollments.list();\n\nconsole.log(enrollments);\n```", perLanguage: { - csharp: { - method: 'Enrollments.List', - example: - 'EnrollmentListParams parameters = new();\n\nvar enrollments = await client.Enrollments.List(parameters);\n\nConsole.WriteLine(enrollments);', - }, - go: { - method: 'client.Enrollments.List', + typescript: { + method: 'client.enrollments.list', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tenrollments, err := client.Enrollments.List(context.TODO(), beagle.EnrollmentListParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", enrollments.Data)\n}\n', + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst enrollments = await client.enrollments.list();\n\nconsole.log(enrollments.data);", }, - http: { + python: { + method: 'enrollments.list', example: - 'curl https://developer.beagleforpm.com/api/enrollments \\\n -H "x-api-key: $BEAGLE_API_KEY"', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nenrollments = client.enrollments.list()\nprint(enrollments.data)', }, java: { method: 'enrollments().list', example: 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.enrollments.EnrollmentListParams;\nimport com.beagle.api.models.enrollments.EnrollmentListResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n EnrollmentListResponse enrollments = client.enrollments().list();\n }\n}', }, - python: { - method: 'enrollments.list', + go: { + method: 'client.Enrollments.List', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nenrollments = client.enrollments.list()\nprint(enrollments.data)', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tenrollments, err := client.Enrollments.List(context.TODO(), beagle.EnrollmentListParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", enrollments.Data)\n}\n', }, ruby: { method: 'enrollments.list', example: 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nenrollments = beagle.enrollments.list\n\nputs(enrollments)', }, - typescript: { - method: 'client.enrollments.list', + csharp: { + method: 'Enrollments.List', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst enrollments = await client.enrollments.list();\n\nconsole.log(enrollments.data);", + 'EnrollmentListParams parameters = new();\n\nvar enrollments = await client.Enrollments.List(parameters);\n\nConsole.WriteLine(enrollments);', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/enrollments \\\n -H "x-api-key: $BEAGLE_API_KEY"', }, }, }, @@ -831,39 +831,39 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## create\n\n`client.enrollments.create(effectiveDate: string, plan: string, propertyManagerId: number, tenantId: number, note?: string, status?: 'Premium Paying' | 'Issued, Not Paid'): { data: enrollment; success: true; }`\n\n**post** `/api/enrollments`\n\ncreate a new enrollment for a tenant.\n\n### Parameters\n\n- `effectiveDate: string`\n the date the enrollment will begin, note enrollments cannot begin in the past\n\n- `plan: string`\n the plan name/code\n\n- `propertyManagerId: number`\n\n- `tenantId: number`\n\n- `note?: string`\n an optional note field, this can be used for easily appending metadata to enrollments\n\n- `status?: 'Premium Paying' | 'Issued, Not Paid'`\n the enrollment status — defaults to 'Issued, Not Paid' if not provided\n\n### Returns\n\n- `{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }`\n\n - `data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollment = await client.enrollments.create({\n effectiveDate: '2025-11-10T19:50:20.638Z',\n plan: 'TLL_100K_CONTENTS_5K_ACV',\n propertyManagerId: 123,\n tenantId: 123,\n});\n\nconsole.log(enrollment);\n```", perLanguage: { - csharp: { - method: 'Enrollments.Create', - example: - 'EnrollmentCreateParams parameters = new()\n{\n EffectiveDate = "2025-11-10T19:50:20.638Z",\n Plan = "TLL_100K_CONTENTS_5K_ACV",\n PropertyManagerID = 123,\n TenantID = 123,\n};\n\nvar enrollment = await client.Enrollments.Create(parameters);\n\nConsole.WriteLine(enrollment);', - }, - go: { - method: 'client.Enrollments.New', + typescript: { + method: 'client.enrollments.create', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tenrollment, err := client.Enrollments.New(context.TODO(), beagle.EnrollmentNewParams{\n\t\tEffectiveDate: "2025-11-10T19:50:20.638Z",\n\t\tPlan: "TLL_100K_CONTENTS_5K_ACV",\n\t\tPropertyManagerID: 123,\n\t\tTenantID: 123,\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", enrollment.Data)\n}\n', + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst enrollment = await client.enrollments.create({\n effectiveDate: '2025-11-10T19:50:20.638Z',\n plan: 'TLL_100K_CONTENTS_5K_ACV',\n propertyManagerId: 123,\n tenantId: 123,\n});\n\nconsole.log(enrollment.data);", }, - http: { + python: { + method: 'enrollments.create', example: - 'curl https://developer.beagleforpm.com/api/enrollments \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "effectiveDate": "2025-11-10T19:50:20.638Z",\n "plan": "TLL_100K_CONTENTS_5K_ACV",\n "propertyManagerId": 123,\n "tenantId": 123\n }\'', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nenrollment = client.enrollments.create(\n effective_date="2025-11-10T19:50:20.638Z",\n plan="TLL_100K_CONTENTS_5K_ACV",\n property_manager_id=123,\n tenant_id=123,\n)\nprint(enrollment.data)', }, java: { method: 'enrollments().create', example: 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.enrollments.EnrollmentCreateParams;\nimport com.beagle.api.models.enrollments.EnrollmentCreateResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n EnrollmentCreateParams params = EnrollmentCreateParams.builder()\n .effectiveDate("2025-11-10T19:50:20.638Z")\n .plan("TLL_100K_CONTENTS_5K_ACV")\n .propertyManagerId(123.0)\n .tenantId(123.0)\n .build();\n EnrollmentCreateResponse enrollment = client.enrollments().create(params);\n }\n}', }, - python: { - method: 'enrollments.create', + go: { + method: 'client.Enrollments.New', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nenrollment = client.enrollments.create(\n effective_date="2025-11-10T19:50:20.638Z",\n plan="TLL_100K_CONTENTS_5K_ACV",\n property_manager_id=123,\n tenant_id=123,\n)\nprint(enrollment.data)', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tenrollment, err := client.Enrollments.New(context.TODO(), beagle.EnrollmentNewParams{\n\t\tEffectiveDate: "2025-11-10T19:50:20.638Z",\n\t\tPlan: "TLL_100K_CONTENTS_5K_ACV",\n\t\tPropertyManagerID: 123,\n\t\tTenantID: 123,\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", enrollment.Data)\n}\n', }, ruby: { method: 'enrollments.create', example: 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nenrollment = beagle.enrollments.create(\n effective_date: "2025-11-10T19:50:20.638Z",\n plan: "TLL_100K_CONTENTS_5K_ACV",\n property_manager_id: 123,\n tenant_id: 123\n)\n\nputs(enrollment)', }, - typescript: { - method: 'client.enrollments.create', + csharp: { + method: 'Enrollments.Create', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst enrollment = await client.enrollments.create({\n effectiveDate: '2025-11-10T19:50:20.638Z',\n plan: 'TLL_100K_CONTENTS_5K_ACV',\n propertyManagerId: 123,\n tenantId: 123,\n});\n\nconsole.log(enrollment.data);", + 'EnrollmentCreateParams parameters = new()\n{\n EffectiveDate = "2025-11-10T19:50:20.638Z",\n Plan = "TLL_100K_CONTENTS_5K_ACV",\n PropertyManagerID = 123,\n TenantID = 123,\n};\n\nvar enrollment = await client.Enrollments.Create(parameters);\n\nConsole.WriteLine(enrollment);', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/enrollments \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "effectiveDate": "2025-11-10T19:50:20.638Z",\n "plan": "TLL_100K_CONTENTS_5K_ACV",\n "propertyManagerId": 123,\n "tenantId": 123\n }\'', }, }, }, @@ -880,39 +880,39 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## retrieve_certificate\n\n`client.enrollments.retrieveCertificate(id: number): string`\n\n**get** `/api/enrollments/{id}/certificate`\n\nget the certificate of enrollment for a given enrollment\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `string`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst response = await client.enrollments.retrieveCertificate(123);\n\nconsole.log(response);\n\nconst content = await response.blob()\nconsole.log(content)\n```", perLanguage: { - csharp: { - method: 'Enrollments.RetrieveCertificate', - example: - 'EnrollmentRetrieveCertificateParams parameters = new() { ID = 123 };\n\nvar response = await client.Enrollments.RetrieveCertificate(parameters);\n\nConsole.WriteLine(response);', - }, - go: { - method: 'client.Enrollments.GetCertificate', + typescript: { + method: 'client.enrollments.retrieveCertificate', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tresponse, err := client.Enrollments.GetCertificate(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst response = await client.enrollments.retrieveCertificate(123);\n\nconsole.log(response);\n\nconst content = await response.blob();\nconsole.log(content);", }, - http: { + python: { + method: 'enrollments.retrieve_certificate', example: - 'curl https://developer.beagleforpm.com/api/enrollments/$ID/certificate \\\n -H "x-api-key: $BEAGLE_API_KEY"', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nresponse = client.enrollments.retrieve_certificate(\n 123,\n)\nprint(response)\ncontent = response.read()\nprint(content)', }, java: { method: 'enrollments().retrieveCertificate', example: 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.core.http.HttpResponse;\nimport com.beagle.api.models.enrollments.EnrollmentRetrieveCertificateParams;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n HttpResponse response = client.enrollments().retrieveCertificate(123.0);\n }\n}', }, - python: { - method: 'enrollments.retrieve_certificate', + go: { + method: 'client.Enrollments.GetCertificate', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nresponse = client.enrollments.retrieve_certificate(\n 123,\n)\nprint(response)\ncontent = response.read()\nprint(content)', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tresponse, err := client.Enrollments.GetCertificate(context.TODO(), 123)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', }, ruby: { method: 'enrollments.retrieve_certificate', example: 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nresponse = beagle.enrollments.retrieve_certificate(123)\n\nputs(response)', }, - typescript: { - method: 'client.enrollments.retrieveCertificate', + csharp: { + method: 'Enrollments.RetrieveCertificate', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst response = await client.enrollments.retrieveCertificate(123);\n\nconsole.log(response);\n\nconst content = await response.blob();\nconsole.log(content);", + 'EnrollmentRetrieveCertificateParams parameters = new() { ID = 123 };\n\nvar response = await client.Enrollments.RetrieveCertificate(parameters);\n\nConsole.WriteLine(response);', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/enrollments/$ID/certificate \\\n -H "x-api-key: $BEAGLE_API_KEY"', }, }, }, @@ -929,39 +929,39 @@ const EMBEDDED_METHODS: MethodEntry[] = [ markdown: "## verify\n\n`client.insuranceVerification.verify(propertyManagerId: number, tenantId: number, urls: string[]): { message: 'insurance verification job scheduled'; }`\n\n**post** `/api/insurance-verification`\n\ntrigger a job to parse a tenants insurance document(s)\n\n### Parameters\n\n- `propertyManagerId: number`\n\n- `tenantId: number`\n\n- `urls: string[]`\n an array of presigned pdf urls for the tenants policy document(s)\n\n### Returns\n\n- `{ message: 'insurance verification job scheduled'; }`\n\n - `message: 'insurance verification job scheduled'`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst response = await client.insuranceVerification.verify({\n propertyManagerId: 0,\n tenantId: 0,\n urls: ['string'],\n});\n\nconsole.log(response);\n```", perLanguage: { - csharp: { - method: 'InsuranceVerification.Verify', - example: - 'InsuranceVerificationVerifyParams parameters = new()\n{\n PropertyManagerID = 0,\n TenantID = 0,\n Urls =\n [\n "string"\n ],\n};\n\nvar response = await client.InsuranceVerification.Verify(parameters);\n\nConsole.WriteLine(response);', - }, - go: { - method: 'client.InsuranceVerification.Verify', + typescript: { + method: 'client.insuranceVerification.verify', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tresponse, err := client.InsuranceVerification.Verify(context.TODO(), beagle.InsuranceVerificationVerifyParams{\n\t\tPropertyManagerID: 0,\n\t\tTenantID: 0,\n\t\tURLs: []string{"string"},\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Message)\n}\n', + "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst response = await client.insuranceVerification.verify({\n propertyManagerId: 0,\n tenantId: 0,\n urls: ['string'],\n});\n\nconsole.log(response.message);", }, - http: { + python: { + method: 'insurance_verification.verify', example: - 'curl https://developer.beagleforpm.com/api/insurance-verification \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "propertyManagerId": 0,\n "tenantId": 0,\n "urls": [\n "string"\n ]\n }\'', + 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nresponse = client.insurance_verification.verify(\n property_manager_id=0,\n tenant_id=0,\n urls=["string"],\n)\nprint(response.message)', }, java: { method: 'insuranceVerification().verify', example: 'package com.beagle.api.example;\n\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.insuranceverification.InsuranceVerificationVerifyParams;\nimport com.beagle.api.models.insuranceverification.InsuranceVerificationVerifyResponse;\n\npublic final class Main {\n private Main() {}\n\n public static void main(String[] args) {\n BeagleClient client = BeagleOkHttpClient.fromEnv();\n\n InsuranceVerificationVerifyParams params = InsuranceVerificationVerifyParams.builder()\n .propertyManagerId(0.0)\n .tenantId(0.0)\n .addUrl("string")\n .build();\n InsuranceVerificationVerifyResponse response = client.insuranceVerification().verify(params);\n }\n}', }, - python: { - method: 'insurance_verification.verify', + go: { + method: 'client.InsuranceVerification.Verify', example: - 'import os\nfrom beagle import Beagle\n\nclient = Beagle(\n api_key=os.environ.get("BEAGLE_API_KEY"), # This is the default and can be omitted\n)\nresponse = client.insurance_verification.verify(\n property_manager_id=0,\n tenant_id=0,\n urls=["string"],\n)\nprint(response.message)', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/beagle-go"\n\t"github.com/stainless-sdks/beagle-go/option"\n)\n\nfunc main() {\n\tclient := beagle.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tresponse, err := client.InsuranceVerification.Verify(context.TODO(), beagle.InsuranceVerificationVerifyParams{\n\t\tPropertyManagerID: 0,\n\t\tTenantID: 0,\n\t\tURLs: []string{"string"},\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Message)\n}\n', }, ruby: { method: 'insurance_verification.verify', example: 'require "beagle"\n\nbeagle = Beagle::Client.new(\n api_key: "My API Key",\n environment: "staging" # defaults to "production"\n)\n\nresponse = beagle.insurance_verification.verify(property_manager_id: 0, tenant_id: 0, urls: ["string"])\n\nputs(response)', }, - typescript: { - method: 'client.insuranceVerification.verify', + csharp: { + method: 'InsuranceVerification.Verify', example: - "import Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle({\n apiKey: process.env['BEAGLE_API_KEY'], // This is the default and can be omitted\n});\n\nconst response = await client.insuranceVerification.verify({\n propertyManagerId: 0,\n tenantId: 0,\n urls: ['string'],\n});\n\nconsole.log(response.message);", + 'InsuranceVerificationVerifyParams parameters = new()\n{\n PropertyManagerID = 0,\n TenantID = 0,\n Urls =\n [\n "string"\n ],\n};\n\nvar response = await client.InsuranceVerification.Verify(parameters);\n\nConsole.WriteLine(response);', + }, + http: { + example: + 'curl https://developer.beagleforpm.com/api/insurance-verification \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "propertyManagerId": 0,\n "tenantId": 0,\n "urls": [\n "string"\n ]\n }\'', }, }, }, diff --git a/scripts/utils/postprocess-files.cjs b/scripts/utils/postprocess-files.cjs index deae575e..a8cdeb7c 100644 --- a/scripts/utils/postprocess-files.cjs +++ b/scripts/utils/postprocess-files.cjs @@ -23,12 +23,19 @@ async function postprocess() { // strip out lib="dom", types="node", and types="react" references; these // are needed at build time, but would pollute the user's TS environment - const transformed = code.replace( + let transformed = code.replace( /^ *\/\/\/ * ' '.repeat(match.length - 1) + '\n', ); + // TypeScript's declaration emitter collapses /** @ts-ignore */ onto the same + // line as the type declaration, which doesn't work. So we convert to // @ts-ignore + // on its own line to properly suppresses errors. + if (file.endsWith('.d.ts') || file.endsWith('.d.mts') || file.endsWith('.d.cts')) { + transformed = transformed.replace(/\/\*\* @ts-ignore\b[^*]*\*\/ /gm, '// @ts-ignore\n'); + } + if (transformed !== code) { console.error(`wrote ${path.relative(process.cwd(), file)}`); await fs.promises.writeFile(file, transformed, 'utf8'); diff --git a/src/client.ts b/src/client.ts index 7b556947..a01b6643 100644 --- a/src/client.ts +++ b/src/client.ts @@ -243,6 +243,18 @@ export class Beagle { this.fetch = options.fetch ?? Shims.getDefaultFetch(); this.#encoder = Opts.FallbackEncoder; + const customHeadersEnv = readEnv('BEAGLE_CUSTOM_HEADERS'); + if (customHeadersEnv) { + const parsed: Record = {}; + for (const line of customHeadersEnv.split('\n')) { + const colon = line.indexOf(':'); + if (colon >= 0) { + parsed[line.substring(0, colon).trim()] = line.substring(colon + 1).trim(); + } + } + options.defaultHeaders = { ...parsed, ...options.defaultHeaders }; + } + this._options = options; this.apiKey = apiKey; From 77ae117e0b84e00817bb1aa7f84cdb39cd95796c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 04:02:22 +0000 Subject: [PATCH 122/138] chore(internal): codegen related update --- .github/workflows/release-doctor.yml | 1 - eslint.config.mjs | 3 --- package.json | 1 - scripts/fast-format | 9 +++----- scripts/format | 3 +-- scripts/lint | 3 +++ src/internal/types.ts | 14 ++++++------ yarn.lock | 32 ---------------------------- 8 files changed, 13 insertions(+), 53 deletions(-) diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index c188ebc6..e324435f 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -19,4 +19,3 @@ jobs: bash ./bin/check-release-environment env: NPM_TOKEN: ${{ secrets.BEAGLE_NPM_TOKEN || secrets.NPM_TOKEN }} - diff --git a/eslint.config.mjs b/eslint.config.mjs index 6c7b5e3a..9136cc9e 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,7 +1,6 @@ // @ts-check import tseslint from 'typescript-eslint'; import unusedImports from 'eslint-plugin-unused-imports'; -import prettier from 'eslint-plugin-prettier'; export default tseslint.config( { @@ -14,11 +13,9 @@ export default tseslint.config( plugins: { '@typescript-eslint': tseslint.plugin, 'unused-imports': unusedImports, - prettier, }, rules: { 'no-unused-vars': 'off', - 'prettier/prettier': 'error', 'unused-imports/no-unused-imports': 'error', 'no-restricted-imports': [ 'error', diff --git a/package.json b/package.json index b414d45b..2d686ad6 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,6 @@ "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", "eslint": "^9.39.1", - "eslint-plugin-prettier": "^5.4.1", "eslint-plugin-unused-imports": "^4.1.4", "iconv-lite": "^0.6.3", "jest": "^29.4.0", diff --git a/scripts/fast-format b/scripts/fast-format index 53721ac0..f1873aef 100755 --- a/scripts/fast-format +++ b/scripts/fast-format @@ -31,10 +31,7 @@ if ! [ -z "$ESLINT_FILES" ]; then fi echo "==> Running prettier --write" -# format things eslint didn't -PRETTIER_FILES="$(grep '\.\(js\|json\)$' "$FILE_LIST" || true)" -if ! [ -z "$PRETTIER_FILES" ]; then - echo "$PRETTIER_FILES" | xargs ./node_modules/.bin/prettier \ - --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern \ - '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' +if ! [ -z "$FILE_LIST" ]; then + cat "$FILE_LIST" | xargs ./node_modules/.bin/prettier \ + --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern --ignore-unknown fi diff --git a/scripts/format b/scripts/format index 7a756401..b1b2c17a 100755 --- a/scripts/format +++ b/scripts/format @@ -8,5 +8,4 @@ echo "==> Running eslint --fix" ./node_modules/.bin/eslint --fix . echo "==> Running prettier --write" -# format things eslint didn't -./node_modules/.bin/prettier --write --cache --cache-strategy metadata . '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' +./node_modules/.bin/prettier --write --cache --cache-strategy metadata . diff --git a/scripts/lint b/scripts/lint index 3ffb78a6..1f532548 100755 --- a/scripts/lint +++ b/scripts/lint @@ -4,6 +4,9 @@ set -e cd "$(dirname "$0")/.." +echo "==> Running prettier --check" +./node_modules/.bin/prettier --check . + echo "==> Running eslint" ./node_modules/.bin/eslint . diff --git a/src/internal/types.ts b/src/internal/types.ts index b668dfc0..a050513a 100644 --- a/src/internal/types.ts +++ b/src/internal/types.ts @@ -40,7 +40,6 @@ type OverloadedParameters = : T extends (...args: infer A) => unknown ? A : never; -/* eslint-disable */ /** * These imports attempt to get types from a parent package's dependencies. * Unresolved bare specifiers can trigger [automatic type acquisition][1] in some projects, which @@ -63,19 +62,18 @@ type OverloadedParameters = * * [1]: https://www.typescriptlang.org/tsconfig/#typeAcquisition */ -/** @ts-ignore For users with \@types/node */ +/** @ts-ignore For users with \@types/node */ /* prettier-ignore */ type UndiciTypesRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with undici */ +/** @ts-ignore For users with undici */ /* prettier-ignore */ type UndiciRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with \@types/bun */ +/** @ts-ignore For users with \@types/bun */ /* prettier-ignore */ type BunRequestInit = globalThis.FetchRequestInit; -/** @ts-ignore For users with node-fetch@2 */ +/** @ts-ignore For users with node-fetch@2 */ /* prettier-ignore */ type NodeFetch2RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ +/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ /* prettier-ignore */ type NodeFetch3RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users who use Deno */ +/** @ts-ignore For users who use Deno */ /* prettier-ignore */ type FetchRequestInit = NonNullable[1]>; -/* eslint-enable */ type RequestInits = | NotAny diff --git a/yarn.lock b/yarn.lock index f6eae3cd..18e7cbdc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -709,11 +709,6 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@pkgr/core@^0.2.4": - version "0.2.4" - resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.4.tgz#d897170a2b0ba51f78a099edccd968f7b103387c" - integrity sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw== - "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" @@ -1515,14 +1510,6 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -eslint-plugin-prettier@^5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.1.tgz#99b55d7dd70047886b2222fdd853665f180b36af" - integrity sha512-9dF+KuU/Ilkq27A8idRP7N2DH8iUR6qXcjF3FR2wETY21PZdBrIjwCau8oboyGj9b7etWmTGEeM8e7oOed6ZWg== - dependencies: - prettier-linter-helpers "^1.0.0" - synckit "^0.11.7" - eslint-plugin-unused-imports@^4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz#62ddc7446ccbf9aa7b6f1f0b00a980423cda2738" @@ -1674,11 +1661,6 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-diff@^1.1.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" - integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== - fast-glob@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" @@ -2841,13 +2823,6 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - prettier@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848" @@ -3144,13 +3119,6 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -synckit@^0.11.7: - version "0.11.8" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.8.tgz#b2aaae998a4ef47ded60773ad06e7cb821f55457" - integrity sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A== - dependencies: - "@pkgr/core" "^0.2.4" - test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" From 52de4bb952e65b0cbc6ef5831cace103b6ce4f33 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 04:24:45 +0000 Subject: [PATCH 123/138] chore(internal): codegen related update --- .prettierignore | 1 + .stats.yml | 2 +- packages/mcp-server/manifest.json | 8 ++++++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.prettierignore b/.prettierignore index 7cc13dd1..36afd3b3 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,6 +2,7 @@ CHANGELOG.md /ecosystem-tests/*/** /node_modules /deno +/packages/mcp-server/manifest.json # don't format tsc output, will break source maps dist diff --git a/.stats.yml b/.stats.yml index a9056371..171c2515 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 18 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi%2Fbeagle-ef5a755bad62f37f7c5aabda9301f138c4b3d16e9f3bc6b512fd116c18059365.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi/beagle-ef5a755bad62f37f7c5aabda9301f138c4b3d16e9f3bc6b512fd116c18059365.yml openapi_spec_hash: 7fdd09563daf05b0efbdd74f2bd391d1 config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/packages/mcp-server/manifest.json b/packages/mcp-server/manifest.json index 02df4f75..a8b45f2f 100644 --- a/packages/mcp-server/manifest.json +++ b/packages/mcp-server/manifest.json @@ -16,7 +16,9 @@ "entry_point": "index.js", "mcp_config": { "command": "node", - "args": ["${__dirname}/index.js"], + "args": [ + "${__dirname}/index.js" + ], "env": { "BEAGLE_API_KEY": "${user_config.BEAGLE_API_KEY}" } @@ -37,5 +39,7 @@ "node": ">=18.0.0" } }, - "keywords": ["api"] + "keywords": [ + "api" + ] } From cdc226ae775583f8a5daa454bb65d1abb922f815 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 03:26:45 +0000 Subject: [PATCH 124/138] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 171c2515..1457043a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 18 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi/beagle-ef5a755bad62f37f7c5aabda9301f138c4b3d16e9f3bc6b512fd116c18059365.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi/beagle-5ef40a5ea9b4d33997789e58615360e74266ad5b01dc77bb39e9d3850aedd861.yml openapi_spec_hash: 7fdd09563daf05b0efbdd74f2bd391d1 config_hash: a50e91a2233ab4faad057e676e3cfe49 From f7d0710eaf076b3cdd60715492cdca08da33ed00 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 03:58:18 +0000 Subject: [PATCH 125/138] chore(internal): codegen related update --- packages/mcp-server/src/local-docs-search.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 3986ac90..20cc597f 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -981,7 +981,7 @@ const EMBEDDED_READMES: { language: string; content: string }[] = [ { language: 'java', content: - '# Beagle Java API Library\n\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.beagle.api/beagle-java)](https://central.sonatype.com/artifact/com.beagle.api/beagle-java/0.0.1)\n[![javadoc](https://javadoc.io/badge2/com.beagle.api/beagle-java/0.0.1/javadoc.svg)](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1)\n\n\nThe Beagle Java SDK provides convenient access to the Beagle REST API from applications written in Java.\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\nJavadocs are available on [javadoc.io](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1).\n\n## Installation\n\n### Gradle\n\n~~~kotlin\nimplementation("com.beagle.api:beagle-java:0.0.1")\n~~~\n\n### Maven\n\n~~~xml\n\n com.beagle.api\n beagle-java\n 0.0.1\n\n~~~\n\n## Requirements\n\nThis library requires Java 8 or later.\n\n## Usage\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nPlanListResponse plans = client.plans().list();\n```\n\n## Client configuration\n\nConfigure the client using system properties or environment variables:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n```\n\nOr manually:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .apiKey("My API Key")\n .build();\n```\n\nOr using a combination of the two approaches:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n // Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n // Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\n .fromEnv()\n .apiKey("My API Key")\n .build();\n```\n\nSee this table for the available options:\n\n| Setter | System property | Environment variable | Required | Default value |\n| --------- | ---------------- | -------------------- | -------- | ------------------------------------- |\n| `apiKey` | `beagle.apiKey` | `BEAGLE_API_KEY` | true | - |\n| `baseUrl` | `beagle.baseUrl` | `BEAGLE_BASE_URL` | true | `"https://developer.beagleforpm.com"` |\n\nSystem properties take precedence over environment variables.\n\n> [!TIP]\n> Don\'t create more than one client in the same application. Each client has a connection pool and\n> thread pools, which are more efficient to share between requests.\n\n### Modifying configuration\n\nTo temporarily use a modified client configuration, while reusing the same connection and thread pools, call `withOptions()` on any client or service:\n\n```java\nimport com.beagle.api.client.BeagleClient;\n\nBeagleClient clientWithOptions = client.withOptions(optionsBuilder -> {\n optionsBuilder.baseUrl("https://example.com");\n optionsBuilder.maxRetries(42);\n});\n```\n\nThe `withOptions()` method does not affect the original client or service.\n\n## Requests and responses\n\nTo send a request to the Beagle API, build an instance of some `Params` class and pass it to the corresponding client method. When the response is received, it will be deserialized into an instance of a Java class.\n\nFor example, `client.plans().list(...)` should be called with an instance of `PlanListParams`, and it will return an instance of `PlanListResponse`.\n\n## Immutability\n\nEach class in the SDK has an associated [builder](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java) or factory method for constructing it.\n\nEach class is [immutable](https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html) once constructed. If the class has an associated builder, then it has a `toBuilder()` method, which can be used to convert it back to a builder for making a modified copy.\n\nBecause each class is immutable, builder modification will _never_ affect already built class instances.\n\n## Asynchronous execution\n\nThe default client is synchronous. To switch to asynchronous execution, call the `async()` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nCompletableFuture plans = client.async().plans().list();\n```\n\nOr create an asynchronous client from the beginning:\n\n```java\nimport com.beagle.api.client.BeagleClientAsync;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClientAsync;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClientAsync client = BeagleOkHttpClientAsync.fromEnv();\n\nCompletableFuture plans = client.plans().list();\n```\n\nThe asynchronous client supports the same options as the synchronous one, except most methods return `CompletableFuture`s.\n\n\n\n\n\n## Binary responses\n\nThe SDK defines methods that return binary responses, which are used for API responses that shouldn\'t necessarily be parsed, like non-JSON data.\n\nThese methods return [`HttpResponse`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpResponse.kt):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport com.beagle.api.models.enrollments.EnrollmentRetrieveCertificateParams;\n\nHttpResponse response = client.enrollments().retrieveCertificate(123.0);\n```\n\nTo save the response content to a file, use the [`Files.copy(...)`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#copy-java.io.InputStream-java.nio.file.Path-java.nio.file.CopyOption...-) method:\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.nio.file.StandardCopyOption;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n Files.copy(\n response.body(),\n Paths.get(path),\n StandardCopyOption.REPLACE_EXISTING\n );\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\nOr transfer the response content to any [`OutputStream`](https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n response.body().transferTo(Files.newOutputStream(Paths.get(path)));\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\n## Raw responses\n\nThe SDK defines methods that deserialize responses into instances of Java classes. However, these methods don\'t provide access to the response headers, status code, or the raw response body.\n\nTo access this data, prefix any HTTP method call on a client or service with `withRawResponse()`:\n\n```java\nimport com.beagle.api.core.http.Headers;\nimport com.beagle.api.core.http.HttpResponseFor;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\nHttpResponseFor plans = client.plans().withRawResponse().list();\n\nint statusCode = plans.statusCode();\nHeaders headers = plans.headers();\n```\n\nYou can still deserialize the response into an instance of a Java class if needed:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse parsedPlans = plans.parse();\n```\n\n## Error handling\n\nThe SDK throws custom unchecked exception types:\n\n- [`BeagleServiceException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleServiceException.kt): Base class for HTTP errors. See this table for which exception subclass is thrown for each HTTP status code:\n\n | Status | Exception |\n | ------ | -------------------------------------------------- |\n | 400 | [`BadRequestException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BadRequestException.kt) |\n | 401 | [`UnauthorizedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnauthorizedException.kt) |\n | 403 | [`PermissionDeniedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/PermissionDeniedException.kt) |\n | 404 | [`NotFoundException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/NotFoundException.kt) |\n | 422 | [`UnprocessableEntityException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnprocessableEntityException.kt) |\n | 429 | [`RateLimitException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/RateLimitException.kt) |\n | 5xx | [`InternalServerException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/InternalServerException.kt) |\n | others | [`UnexpectedStatusCodeException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnexpectedStatusCodeException.kt) |\n\n- [`BeagleIoException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleIoException.kt): I/O networking errors.\n\n- [`BeagleRetryableException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleRetryableException.kt): Generic error indicating a failure that could be retried by the client.\n\n- [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt): Failure to interpret successfully parsed data. For example, when accessing a property that\'s supposed to be required, but the API unexpectedly omitted it from the response.\n\n- [`BeagleException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleException.kt): Base class for all exceptions. Most errors will result in one of the previously mentioned ones, but completely generic errors may be thrown using the base class.\n\n\n\n## Logging\n\nThe SDK uses the standard [OkHttp logging interceptor](https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor).\n\nEnable logging by setting the `BEAGLE_LOG` environment variable to `info`:\n\n```sh\nexport BEAGLE_LOG=info\n```\n\nOr to `debug` for more verbose logging:\n\n```sh\nexport BEAGLE_LOG=debug\n```\n\n## ProGuard and R8\n\nAlthough the SDK uses reflection, it is still usable with [ProGuard](https://github.com/Guardsquare/proguard) and [R8](https://developer.android.com/topic/performance/app-optimization/enable-app-optimization) because `beagle-java-core` is published with a [configuration file](beagle-java-core/src/main/resources/META-INF/proguard/beagle-java-core.pro) containing [keep rules](https://www.guardsquare.com/manual/configuration/usage).\n\nProGuard and R8 should automatically detect and use the published rules, but you can also manually copy the keep rules if necessary.\n\n\n\n\n\n## Jackson\n\nThe SDK depends on [Jackson](https://github.com/FasterXML/jackson) for JSON serialization/deserialization. It is compatible with version 2.13.4 or higher, but depends on version 2.18.2 by default.\n\nThe SDK throws an exception if it detects an incompatible Jackson version at runtime (e.g. if the default version was overridden in your Maven or Gradle config).\n\nIf the SDK threw an exception, but you\'re _certain_ the version is compatible, then disable the version check using the `checkJacksonVersionCompatibility` on [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt).\n\n> [!CAUTION]\n> We make no guarantee that the SDK works correctly when the Jackson version check is disabled.\n\nAlso note that there are bugs in older Jackson versions that can affect the SDK. We don\'t work around all Jackson bugs ([example](https://github.com/FasterXML/jackson-databind/issues/3240)) and expect users to upgrade Jackson for those instead.\n\n## Network options\n\n### Retries\n\nThe SDK automatically retries 2 times by default, with a short exponential backoff between requests.\n\nOnly the following error types are retried:\n- Connection errors (for example, due to a network connectivity problem)\n- 408 Request Timeout\n- 409 Conflict\n- 429 Rate Limit\n- 5xx Internal\n\nThe API may also explicitly instruct the SDK to retry or not retry a request.\n\nTo set a custom number of retries, configure the client using the `maxRetries` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .maxRetries(4)\n .build();\n```\n\n### Timeouts\n\nRequests time out after 1 minute by default.\n\nTo set a custom timeout, configure the method call using the `timeout` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().timeout(Duration.ofSeconds(30)).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .timeout(Duration.ofSeconds(30))\n .build();\n```\n\n### Proxies\n\nTo route requests through a proxy, configure the client using the `proxy` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.net.InetSocketAddress;\nimport java.net.Proxy;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .proxy(new Proxy(\n Proxy.Type.HTTP, new InetSocketAddress(\n "https://example.com", 8080\n )\n ))\n .build();\n```\n\n### Connection pooling\n\nTo customize the underlying OkHttp connection pool, configure the client using the `maxIdleConnections` and `keepAliveDuration` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `maxIdleConnections` is set, then `keepAliveDuration` must be set, and vice versa.\n .maxIdleConnections(10)\n .keepAliveDuration(Duration.ofMinutes(2))\n .build();\n```\n\nIf both options are unset, OkHttp\'s default connection pool settings are used.\n\n### HTTPS\n\n> [!NOTE]\n> Most applications should not call these methods, and instead use the system defaults. The defaults include\n> special optimizations that can be lost if the implementations are modified.\n\nTo configure how HTTPS connections are secured, configure the client using the `sslSocketFactory`, `trustManager`, and `hostnameVerifier` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `sslSocketFactory` is set, then `trustManager` must be set, and vice versa.\n .sslSocketFactory(yourSSLSocketFactory)\n .trustManager(yourTrustManager)\n .hostnameVerifier(yourHostnameVerifier)\n .build();\n```\n\n### Environments\n\nThe SDK sends requests to the production by default. To send requests to a different environment, configure the client like so:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .staging()\n .build();\n```\n\n### Custom HTTP client\n\nThe SDK consists of three artifacts:\n- `beagle-java-core`\n - Contains core SDK logic\n - Does not depend on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleClient`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClient.kt), [`BeagleClientAsync`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsync.kt), [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt), and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), all of which can work with any HTTP client\n- `beagle-java-client-okhttp`\n - Depends on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) and [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), which provide a way to construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), respectively, using OkHttp\n- `beagle-java`\n - Depends on and exposes the APIs of both `beagle-java-core` and `beagle-java-client-okhttp`\n - Does not have its own logic\n\nThis structure allows replacing the SDK\'s default HTTP client without pulling in unnecessary dependencies.\n\n#### Customized [`OkHttpClient`](https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.html)\n\n> [!TIP]\n> Try the available [network options](#network-options) before replacing the default client.\n\nTo use a customized `OkHttpClient`:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Copy `beagle-java-client-okhttp`\'s [`OkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/OkHttpClient.kt) class into your code and customize it\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your customized client\n\n### Completely custom HTTP client\n\nTo use a completely custom HTTP client:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Write a class that implements the [`HttpClient`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpClient.kt) interface\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your new client class\n\n## Undocumented API functionality\n\nThe SDK is typed for convenient usage of the documented API. However, it also supports working with undocumented or not yet supported parts of the API.\n\n### Parameters\n\nTo set undocumented parameters, call the `putAdditionalHeader`, `putAdditionalQueryParam`, or `putAdditionalBodyProperty` methods on any `Params` class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder()\n .putAdditionalHeader("Secret-Header", "42")\n .putAdditionalQueryParam("secret_query_param", "42")\n .putAdditionalBodyProperty("secretProperty", JsonValue.from("42"))\n .build();\n```\n\nThese can be accessed on the built object later using the `_additionalHeaders()`, `_additionalQueryParams()`, and `_additionalBodyProperties()` methods.\n\nTo set undocumented parameters on _nested_ headers, query params, or body classes, call the `putAdditionalProperty` method on the nested class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.tenants.Address;\nimport com.beagle.api.models.tenants.TenantCreateParams;\n\nTenantCreateParams params = TenantCreateParams.builder()\n .address(Address.builder()\n .putAdditionalProperty("secretProperty", JsonValue.from("42"))\n .build())\n .build();\n```\n\nThese properties can be accessed on the nested built object later using the `_additionalProperties()` method.\n\nTo set a documented parameter or property to an undocumented or not yet supported _value_, pass a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) object to its setter:\n\n```java\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder().build();\n```\n\nThe most straightforward way to create a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) is using its `from(...)` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.List;\nimport java.util.Map;\n\n// Create primitive JSON values\nJsonValue nullValue = JsonValue.from(null);\nJsonValue booleanValue = JsonValue.from(true);\nJsonValue numberValue = JsonValue.from(42);\nJsonValue stringValue = JsonValue.from("Hello World!");\n\n// Create a JSON array value equivalent to `["Hello", "World"]`\nJsonValue arrayValue = JsonValue.from(List.of(\n "Hello", "World"\n));\n\n// Create a JSON object value equivalent to `{ "a": 1, "b": 2 }`\nJsonValue objectValue = JsonValue.from(Map.of(\n "a", 1,\n "b", 2\n));\n\n// Create an arbitrarily nested JSON equivalent to:\n// {\n// "a": [1, 2],\n// "b": [3, 4]\n// }\nJsonValue complexValue = JsonValue.from(Map.of(\n "a", List.of(\n 1, 2\n ),\n "b", List.of(\n 3, 4\n )\n));\n```\n\nNormally a `Builder` class\'s `build` method will throw [`IllegalStateException`](https://docs.oracle.com/javase/8/docs/api/java/lang/IllegalStateException.html) if any required parameter or property is unset.\n\nTo forcibly omit a required parameter or property, pass [`JsonMissing`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt):\n\n```java\nimport com.beagle.api.core.JsonMissing;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanRetrieveParams;\n\nPlanListParams params = PlanRetrieveParams.builder()\n .code(JsonMissing.of())\n .build();\n```\n\n### Response properties\n\nTo access undocumented response properties, call the `_additionalProperties()` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.Map;\n\nMap additionalProperties = client.plans().list(params)._additionalProperties();\nJsonValue secretPropertyValue = additionalProperties.get("secretProperty");\n\nString result = secretPropertyValue.accept(new JsonValue.Visitor<>() {\n @Override\n public String visitNull() {\n return "It\'s null!";\n }\n\n @Override\n public String visitBoolean(boolean value) {\n return "It\'s a boolean!";\n }\n\n @Override\n public String visitNumber(Number value) {\n return "It\'s a number!";\n }\n\n // Other methods include `visitMissing`, `visitString`, `visitArray`, and `visitObject`\n // The default implementation of each unimplemented method delegates to `visitDefault`, which throws by default, but can also be overridden\n});\n```\n\nTo access a property\'s raw JSON value, which may be undocumented, call its `_` prefixed method:\n\n```java\nimport com.beagle.api.core.JsonField;\nimport java.util.Optional;\n\nJsonField field = client.plans().list(params)._field();\n\nif (field.isMissing()) {\n // The property is absent from the JSON response\n} else if (field.isNull()) {\n // The property was set to literal null\n} else {\n // Check if value was provided as a string\n // Other methods include `asNumber()`, `asBoolean()`, etc.\n Optional jsonString = field.asString();\n\n // Try to deserialize into a custom type\n MyClass myObject = field.asUnknown().orElseThrow().convert(MyClass.class);\n}\n```\n\n### Response validation\n\nIn rare cases, the API may return a response that doesn\'t match the expected type. For example, the SDK may expect a property to contain a `String`, but the API could return something else.\n\nBy default, the SDK will not throw an exception in this case. It will throw [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt) only if you directly access the property.\n\nIf you would prefer to check that the response is completely well-typed upfront, then either call `validate()`:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(params).validate();\n```\n\nOr configure the method call to validate the response using the `responseValidation` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().responseValidation(true).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .responseValidation(true)\n .build();\n```\n\n## FAQ\n\n### Why don\'t you use plain `enum` classes?\n\nJava `enum` classes are not trivially [forwards compatible](https://www.stainless.com/blog/making-java-enums-forwards-compatible). Using them in the SDK could cause runtime exceptions if the API is updated to respond with a new enum value.\n\n### Why do you represent fields using `JsonField` instead of just plain `T`?\n\nUsing `JsonField` enables a few features:\n\n- Allowing usage of [undocumented API functionality](#undocumented-api-functionality)\n- Lazily [validating the API response against the expected shape](#response-validation)\n- Representing absent vs explicitly null values\n\n### Why don\'t you use [`data` classes](https://kotlinlang.org/docs/data-classes.html)?\n\nIt is not [backwards compatible to add new fields to a data class](https://kotlinlang.org/docs/api-guidelines-backward-compatibility.html#avoid-using-data-classes-in-your-api) and we don\'t want to introduce a breaking change every time we add a field to a class.\n\n### Why don\'t you use checked exceptions?\n\nChecked exceptions are widely considered a mistake in the Java programming language. In fact, they were omitted from Kotlin for this reason.\n\nChecked exceptions:\n\n- Are verbose to handle\n- Encourage error handling at the wrong level of abstraction, where nothing can be done about the error\n- Are tedious to propagate due to the [function coloring problem](https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function)\n- Don\'t play well with lambdas (also due to the function coloring problem)\n\n## Semantic versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n2. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/beagle-java/issues) with questions, bugs, or suggestions.\n', + '# Beagle Java API Library\n\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.beagle.api/beagle-java)](https://central.sonatype.com/artifact/com.beagle.api/beagle-java/0.0.1)\n[![javadoc](https://javadoc.io/badge2/com.beagle.api/beagle-java/0.0.1/javadoc.svg)](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1)\n\n\nThe Beagle Java SDK provides convenient access to the Beagle REST API from applications written in Java.\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\nJavadocs are available on [javadoc.io](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1).\n\n## Installation\n\n### Gradle\n\n~~~kotlin\nimplementation("com.beagle.api:beagle-java:0.0.1")\n~~~\n\n### Maven\n\n~~~xml\n\n com.beagle.api\n beagle-java\n 0.0.1\n\n~~~\n\n## Requirements\n\nThis library requires Java 8 or later.\n\n## Usage\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nPlanListResponse plans = client.plans().list();\n```\n\n## Client configuration\n\nConfigure the client using system properties or environment variables:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n```\n\nOr manually:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .apiKey("My API Key")\n .build();\n```\n\nOr using a combination of the two approaches:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n // Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n // Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\n .fromEnv()\n .apiKey("My API Key")\n .build();\n```\n\nSee this table for the available options:\n\n| Setter | System property | Environment variable | Required | Default value |\n| --------- | ---------------- | -------------------- | -------- | ------------------------------------- |\n| `apiKey` | `beagle.apiKey` | `BEAGLE_API_KEY` | true | - |\n| `baseUrl` | `beagle.baseUrl` | `BEAGLE_BASE_URL` | true | `"https://developer.beagleforpm.com"` |\n\nSystem properties take precedence over environment variables.\n\n> [!TIP]\n> Don\'t create more than one client in the same application. Each client has a connection pool and\n> thread pools, which are more efficient to share between requests.\n\n### Modifying configuration\n\nTo temporarily use a modified client configuration, while reusing the same connection and thread pools, call `withOptions()` on any client or service:\n\n```java\nimport com.beagle.api.client.BeagleClient;\n\nBeagleClient clientWithOptions = client.withOptions(optionsBuilder -> {\n optionsBuilder.baseUrl("https://example.com");\n optionsBuilder.maxRetries(42);\n});\n```\n\nThe `withOptions()` method does not affect the original client or service.\n\n## Requests and responses\n\nTo send a request to the Beagle API, build an instance of some `Params` class and pass it to the corresponding client method. When the response is received, it will be deserialized into an instance of a Java class.\n\nFor example, `client.plans().list(...)` should be called with an instance of `PlanListParams`, and it will return an instance of `PlanListResponse`.\n\n## Immutability\n\nEach class in the SDK has an associated [builder](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java) or factory method for constructing it.\n\nEach class is [immutable](https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html) once constructed. If the class has an associated builder, then it has a `toBuilder()` method, which can be used to convert it back to a builder for making a modified copy.\n\nBecause each class is immutable, builder modification will _never_ affect already built class instances.\n\n## Asynchronous execution\n\nThe default client is synchronous. To switch to asynchronous execution, call the `async()` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nCompletableFuture plans = client.async().plans().list();\n```\n\nOr create an asynchronous client from the beginning:\n\n```java\nimport com.beagle.api.client.BeagleClientAsync;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClientAsync;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClientAsync client = BeagleOkHttpClientAsync.fromEnv();\n\nCompletableFuture plans = client.plans().list();\n```\n\nThe asynchronous client supports the same options as the synchronous one, except most methods return `CompletableFuture`s.\n\n\n\n\n\n## Binary responses\n\nThe SDK defines methods that return binary responses, which are used for API responses that shouldn\'t necessarily be parsed, like non-JSON data.\n\nThese methods return [`HttpResponse`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpResponse.kt):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport com.beagle.api.models.enrollments.EnrollmentRetrieveCertificateParams;\n\nHttpResponse response = client.enrollments().retrieveCertificate(123.0);\n```\n\nTo save the response content to a file, use the [`Files.copy(...)`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#copy-java.io.InputStream-java.nio.file.Path-java.nio.file.CopyOption...-) method:\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.nio.file.StandardCopyOption;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n Files.copy(\n response.body(),\n Paths.get(path),\n StandardCopyOption.REPLACE_EXISTING\n );\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\nOr transfer the response content to any [`OutputStream`](https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n response.body().transferTo(Files.newOutputStream(Paths.get(path)));\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\n## Raw responses\n\nThe SDK defines methods that deserialize responses into instances of Java classes. However, these methods don\'t provide access to the response headers, status code, or the raw response body.\n\nTo access this data, prefix any HTTP method call on a client or service with `withRawResponse()`:\n\n```java\nimport com.beagle.api.core.http.Headers;\nimport com.beagle.api.core.http.HttpResponseFor;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\nHttpResponseFor plans = client.plans().withRawResponse().list();\n\nint statusCode = plans.statusCode();\nHeaders headers = plans.headers();\n```\n\nYou can still deserialize the response into an instance of a Java class if needed:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse parsedPlans = plans.parse();\n```\n\n## Error handling\n\nThe SDK throws custom unchecked exception types:\n\n- [`BeagleServiceException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleServiceException.kt): Base class for HTTP errors. See this table for which exception subclass is thrown for each HTTP status code:\n\n | Status | Exception |\n | ------ | -------------------------------------------------- |\n | 400 | [`BadRequestException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BadRequestException.kt) |\n | 401 | [`UnauthorizedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnauthorizedException.kt) |\n | 403 | [`PermissionDeniedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/PermissionDeniedException.kt) |\n | 404 | [`NotFoundException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/NotFoundException.kt) |\n | 422 | [`UnprocessableEntityException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnprocessableEntityException.kt) |\n | 429 | [`RateLimitException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/RateLimitException.kt) |\n | 5xx | [`InternalServerException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/InternalServerException.kt) |\n | others | [`UnexpectedStatusCodeException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnexpectedStatusCodeException.kt) |\n\n- [`BeagleIoException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleIoException.kt): I/O networking errors.\n\n- [`BeagleRetryableException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleRetryableException.kt): Generic error indicating a failure that could be retried by the client.\n\n- [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt): Failure to interpret successfully parsed data. For example, when accessing a property that\'s supposed to be required, but the API unexpectedly omitted it from the response.\n\n- [`BeagleException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleException.kt): Base class for all exceptions. Most errors will result in one of the previously mentioned ones, but completely generic errors may be thrown using the base class.\n\n\n\n## Logging\n\nThe SDK uses the standard [OkHttp logging interceptor](https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor).\n\nEnable logging by setting the `BEAGLE_LOG` environment variable to `info`:\n\n```sh\nexport BEAGLE_LOG=info\n```\n\nOr to `debug` for more verbose logging:\n\n```sh\nexport BEAGLE_LOG=debug\n```\n\n## ProGuard and R8\n\nAlthough the SDK uses reflection, it is still usable with [ProGuard](https://github.com/Guardsquare/proguard) and [R8](https://developer.android.com/topic/performance/app-optimization/enable-app-optimization) because `beagle-java-core` is published with a [configuration file](beagle-java-core/src/main/resources/META-INF/proguard/beagle-java-core.pro) containing [keep rules](https://www.guardsquare.com/manual/configuration/usage).\n\nProGuard and R8 should automatically detect and use the published rules, but you can also manually copy the keep rules if necessary.\n\n\n\n\n\n## Jackson\n\nThe SDK depends on [Jackson](https://github.com/FasterXML/jackson) for JSON serialization/deserialization. It is compatible with version 2.13.4 or higher, but depends on version 2.18.2 by default.\n\nThe SDK throws an exception if it detects an incompatible Jackson version at runtime (e.g. if the default version was overridden in your Maven or Gradle config).\n\nIf the SDK threw an exception, but you\'re _certain_ the version is compatible, then disable the version check using the `checkJacksonVersionCompatibility` on [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt).\n\n> [!CAUTION]\n> We make no guarantee that the SDK works correctly when the Jackson version check is disabled.\n\nAlso note that there are bugs in older Jackson versions that can affect the SDK. We don\'t work around all Jackson bugs ([example](https://github.com/FasterXML/jackson-databind/issues/3240)) and expect users to upgrade Jackson for those instead.\n\n## Network options\n\n### Retries\n\nThe SDK automatically retries 2 times by default, with a short exponential backoff between requests.\n\nOnly the following error types are retried:\n- Connection errors (for example, due to a network connectivity problem)\n- 408 Request Timeout\n- 409 Conflict\n- 429 Rate Limit\n- 5xx Internal\n\nThe API may also explicitly instruct the SDK to retry or not retry a request.\n\nTo set a custom number of retries, configure the client using the `maxRetries` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .maxRetries(4)\n .build();\n```\n\n### Timeouts\n\nRequests time out after 1 minute by default.\n\nTo set a custom timeout, configure the method call using the `timeout` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().timeout(Duration.ofSeconds(30)).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .timeout(Duration.ofSeconds(30))\n .build();\n```\n\n### Proxies\n\nTo route requests through a proxy, configure the client using the `proxy` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.net.InetSocketAddress;\nimport java.net.Proxy;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .proxy(new Proxy(\n Proxy.Type.HTTP, new InetSocketAddress(\n "https://example.com", 8080\n )\n ))\n .build();\n```\n\n### Connection pooling\n\nTo customize the underlying OkHttp connection pool, configure the client using the `maxIdleConnections` and `keepAliveDuration` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `maxIdleConnections` is set, then `keepAliveDuration` must be set, and vice versa.\n .maxIdleConnections(10)\n .keepAliveDuration(Duration.ofMinutes(2))\n .build();\n```\n\nIf both options are unset, OkHttp\'s default connection pool settings are used.\n\n### HTTPS\n\n> [!NOTE]\n> Most applications should not call these methods, and instead use the system defaults. The defaults include\n> special optimizations that can be lost if the implementations are modified.\n\nTo configure how HTTPS connections are secured, configure the client using the `sslSocketFactory`, `trustManager`, and `hostnameVerifier` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `sslSocketFactory` is set, then `trustManager` must be set, and vice versa.\n .sslSocketFactory(yourSSLSocketFactory)\n .trustManager(yourTrustManager)\n .hostnameVerifier(yourHostnameVerifier)\n .build();\n```\n\n### Environments\n\nThe SDK sends requests to the production by default. To send requests to a different environment, configure the client like so:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .staging()\n .build();\n```\n\n### Custom HTTP client\n\nThe SDK consists of three artifacts:\n- `beagle-java-core`\n - Contains core SDK logic\n - Does not depend on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleClient`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClient.kt), [`BeagleClientAsync`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsync.kt), [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt), and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), all of which can work with any HTTP client\n- `beagle-java-client-okhttp`\n - Depends on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) and [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), which provide a way to construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), respectively, using OkHttp\n- `beagle-java`\n - Depends on and exposes the APIs of both `beagle-java-core` and `beagle-java-client-okhttp`\n - Does not have its own logic\n\nThis structure allows replacing the SDK\'s default HTTP client without pulling in unnecessary dependencies.\n\n#### Customized [`OkHttpClient`](https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.html)\n\n> [!TIP]\n> Try the available [network options](#network-options) before replacing the default client.\n\nTo use a customized `OkHttpClient`:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Copy `beagle-java-client-okhttp`\'s [`OkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/OkHttpClient.kt) class into your code and customize it\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your customized client\n\n### Completely custom HTTP client\n\nTo use a completely custom HTTP client:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Write a class that implements the [`HttpClient`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpClient.kt) interface\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your new client class\n\n## Undocumented API functionality\n\nThe SDK is typed for convenient usage of the documented API. However, it also supports working with undocumented or not yet supported parts of the API.\n\n### Parameters\n\nTo set undocumented parameters, call the `putAdditionalHeader`, `putAdditionalQueryParam`, or `putAdditionalBodyProperty` methods on any `Params` class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder()\n .putAdditionalHeader("Secret-Header", "42")\n .putAdditionalQueryParam("secret_query_param", "42")\n .putAdditionalBodyProperty("secretProperty", JsonValue.from("42"))\n .build();\n```\n\nThese can be accessed on the built object later using the `_additionalHeaders()`, `_additionalQueryParams()`, and `_additionalBodyProperties()` methods.\n\nTo set undocumented parameters on _nested_ headers, query params, or body classes, call the `putAdditionalProperty` method on the nested class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.tenants.Address;\nimport com.beagle.api.models.tenants.TenantCreateParams;\n\nTenantCreateParams params = TenantCreateParams.builder()\n .address(Address.builder()\n .putAdditionalProperty("secretProperty", JsonValue.from("42"))\n .build())\n .build();\n```\n\nThese properties can be accessed on the nested built object later using the `_additionalProperties()` method.\n\nTo set a documented parameter or property to an undocumented or not yet supported _value_, pass a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) object to its setter:\n\n```java\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder().build();\n```\n\nThe most straightforward way to create a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) is using its `from(...)` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.List;\nimport java.util.Map;\n\n// Create primitive JSON values\nJsonValue nullValue = JsonValue.from(null);\nJsonValue booleanValue = JsonValue.from(true);\nJsonValue numberValue = JsonValue.from(42);\nJsonValue stringValue = JsonValue.from("Hello World!");\n\n// Create a JSON array value equivalent to `["Hello", "World"]`\nJsonValue arrayValue = JsonValue.from(List.of(\n "Hello", "World"\n));\n\n// Create a JSON object value equivalent to `{ "a": 1, "b": 2 }`\nJsonValue objectValue = JsonValue.from(Map.of(\n "a", 1,\n "b", 2\n));\n\n// Create an arbitrarily nested JSON equivalent to:\n// {\n// "a": [1, 2],\n// "b": [3, 4]\n// }\nJsonValue complexValue = JsonValue.from(Map.of(\n "a", List.of(\n 1, 2\n ),\n "b", List.of(\n 3, 4\n )\n));\n```\n\nNormally a `Builder` class\'s `build` method will throw [`IllegalStateException`](https://docs.oracle.com/javase/8/docs/api/java/lang/IllegalStateException.html) if any required parameter or property is unset.\n\nTo forcibly omit a required parameter or property, pass [`JsonMissing`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt):\n\n```java\nimport com.beagle.api.core.JsonMissing;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanRetrieveParams;\n\nPlanListParams params = PlanRetrieveParams.builder()\n .code(JsonMissing.of())\n .build();\n```\n\n### Response properties\n\nTo access undocumented response properties, call the `_additionalProperties()` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.Map;\n\nMap additionalProperties = client.plans().list(params)._additionalProperties();\nJsonValue secretPropertyValue = additionalProperties.get("secretProperty");\n\nString result = secretPropertyValue.accept(new JsonValue.Visitor<>() {\n @Override\n public String visitNull() {\n return "It\'s null!";\n }\n\n @Override\n public String visitBoolean(boolean value) {\n return "It\'s a boolean!";\n }\n\n @Override\n public String visitNumber(Number value) {\n return "It\'s a number!";\n }\n\n // Other methods include `visitMissing`, `visitString`, `visitArray`, and `visitObject`\n // The default implementation of each unimplemented method delegates to `visitDefault`, which throws by default, but can also be overridden\n});\n```\n\nTo access a property\'s raw JSON value, which may be undocumented, call its `_` prefixed method:\n\n```java\nimport com.beagle.api.core.JsonField;\nimport java.util.Optional;\n\nJsonField field = client.plans().list(params)._field();\n\nif (field.isMissing()) {\n // The property is absent from the JSON response\n} else if (field.isNull()) {\n // The property was set to literal null\n} else {\n // Check if value was provided as a string\n // Other methods include `asNumber()`, `asBoolean()`, etc.\n Optional jsonString = field.asString();\n\n // Try to deserialize into a custom type\n MyClass myObject = field.asUnknown().orElseThrow().convert(MyClass.class);\n}\n```\n\n### Response validation\n\nIn rare cases, the API may return a response that doesn\'t match the expected type. For example, the SDK may expect a property to contain a `String`, but the API could return something else.\n\nBy default, the SDK will not throw an exception in this case. It will throw [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt) only if you directly access the property.\n\nValidating the response is _not_ forwards compatible with new types from the API for existing fields.\n\nIf you would still prefer to check that the response is completely well-typed upfront, then either call `validate()`:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(params).validate();\n```\n\nOr configure the method call to validate the response using the `responseValidation` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().responseValidation(true).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .responseValidation(true)\n .build();\n```\n\n## FAQ\n\n### Why don\'t you use plain `enum` classes?\n\nJava `enum` classes are not trivially [forwards compatible](https://www.stainless.com/blog/making-java-enums-forwards-compatible). Using them in the SDK could cause runtime exceptions if the API is updated to respond with a new enum value.\n\n### Why do you represent fields using `JsonField` instead of just plain `T`?\n\nUsing `JsonField` enables a few features:\n\n- Allowing usage of [undocumented API functionality](#undocumented-api-functionality)\n- Lazily [validating the API response against the expected shape](#response-validation)\n- Representing absent vs explicitly null values\n\n### Why don\'t you use [`data` classes](https://kotlinlang.org/docs/data-classes.html)?\n\nIt is not [backwards compatible to add new fields to a data class](https://kotlinlang.org/docs/api-guidelines-backward-compatibility.html#avoid-using-data-classes-in-your-api) and we don\'t want to introduce a breaking change every time we add a field to a class.\n\n### Why don\'t you use checked exceptions?\n\nChecked exceptions are widely considered a mistake in the Java programming language. In fact, they were omitted from Kotlin for this reason.\n\nChecked exceptions:\n\n- Are verbose to handle\n- Encourage error handling at the wrong level of abstraction, where nothing can be done about the error\n- Are tedious to propagate due to the [function coloring problem](https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function)\n- Don\'t play well with lambdas (also due to the function coloring problem)\n\n## Semantic versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n2. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/beagle-java/issues) with questions, bugs, or suggestions.\n', }, { language: 'python', From 516b897c6fd16266a8ad5b3f0d1850053a08d454 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 6 May 2026 04:18:54 +0000 Subject: [PATCH 126/138] chore(internal): codegen related update --- packages/mcp-server/src/local-docs-search.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 20cc597f..a62d92a3 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -981,7 +981,7 @@ const EMBEDDED_READMES: { language: string; content: string }[] = [ { language: 'java', content: - '# Beagle Java API Library\n\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.beagle.api/beagle-java)](https://central.sonatype.com/artifact/com.beagle.api/beagle-java/0.0.1)\n[![javadoc](https://javadoc.io/badge2/com.beagle.api/beagle-java/0.0.1/javadoc.svg)](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1)\n\n\nThe Beagle Java SDK provides convenient access to the Beagle REST API from applications written in Java.\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\nJavadocs are available on [javadoc.io](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1).\n\n## Installation\n\n### Gradle\n\n~~~kotlin\nimplementation("com.beagle.api:beagle-java:0.0.1")\n~~~\n\n### Maven\n\n~~~xml\n\n com.beagle.api\n beagle-java\n 0.0.1\n\n~~~\n\n## Requirements\n\nThis library requires Java 8 or later.\n\n## Usage\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nPlanListResponse plans = client.plans().list();\n```\n\n## Client configuration\n\nConfigure the client using system properties or environment variables:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n```\n\nOr manually:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .apiKey("My API Key")\n .build();\n```\n\nOr using a combination of the two approaches:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n // Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n // Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\n .fromEnv()\n .apiKey("My API Key")\n .build();\n```\n\nSee this table for the available options:\n\n| Setter | System property | Environment variable | Required | Default value |\n| --------- | ---------------- | -------------------- | -------- | ------------------------------------- |\n| `apiKey` | `beagle.apiKey` | `BEAGLE_API_KEY` | true | - |\n| `baseUrl` | `beagle.baseUrl` | `BEAGLE_BASE_URL` | true | `"https://developer.beagleforpm.com"` |\n\nSystem properties take precedence over environment variables.\n\n> [!TIP]\n> Don\'t create more than one client in the same application. Each client has a connection pool and\n> thread pools, which are more efficient to share between requests.\n\n### Modifying configuration\n\nTo temporarily use a modified client configuration, while reusing the same connection and thread pools, call `withOptions()` on any client or service:\n\n```java\nimport com.beagle.api.client.BeagleClient;\n\nBeagleClient clientWithOptions = client.withOptions(optionsBuilder -> {\n optionsBuilder.baseUrl("https://example.com");\n optionsBuilder.maxRetries(42);\n});\n```\n\nThe `withOptions()` method does not affect the original client or service.\n\n## Requests and responses\n\nTo send a request to the Beagle API, build an instance of some `Params` class and pass it to the corresponding client method. When the response is received, it will be deserialized into an instance of a Java class.\n\nFor example, `client.plans().list(...)` should be called with an instance of `PlanListParams`, and it will return an instance of `PlanListResponse`.\n\n## Immutability\n\nEach class in the SDK has an associated [builder](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java) or factory method for constructing it.\n\nEach class is [immutable](https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html) once constructed. If the class has an associated builder, then it has a `toBuilder()` method, which can be used to convert it back to a builder for making a modified copy.\n\nBecause each class is immutable, builder modification will _never_ affect already built class instances.\n\n## Asynchronous execution\n\nThe default client is synchronous. To switch to asynchronous execution, call the `async()` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nCompletableFuture plans = client.async().plans().list();\n```\n\nOr create an asynchronous client from the beginning:\n\n```java\nimport com.beagle.api.client.BeagleClientAsync;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClientAsync;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClientAsync client = BeagleOkHttpClientAsync.fromEnv();\n\nCompletableFuture plans = client.plans().list();\n```\n\nThe asynchronous client supports the same options as the synchronous one, except most methods return `CompletableFuture`s.\n\n\n\n\n\n## Binary responses\n\nThe SDK defines methods that return binary responses, which are used for API responses that shouldn\'t necessarily be parsed, like non-JSON data.\n\nThese methods return [`HttpResponse`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpResponse.kt):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport com.beagle.api.models.enrollments.EnrollmentRetrieveCertificateParams;\n\nHttpResponse response = client.enrollments().retrieveCertificate(123.0);\n```\n\nTo save the response content to a file, use the [`Files.copy(...)`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#copy-java.io.InputStream-java.nio.file.Path-java.nio.file.CopyOption...-) method:\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.nio.file.StandardCopyOption;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n Files.copy(\n response.body(),\n Paths.get(path),\n StandardCopyOption.REPLACE_EXISTING\n );\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\nOr transfer the response content to any [`OutputStream`](https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n response.body().transferTo(Files.newOutputStream(Paths.get(path)));\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\n## Raw responses\n\nThe SDK defines methods that deserialize responses into instances of Java classes. However, these methods don\'t provide access to the response headers, status code, or the raw response body.\n\nTo access this data, prefix any HTTP method call on a client or service with `withRawResponse()`:\n\n```java\nimport com.beagle.api.core.http.Headers;\nimport com.beagle.api.core.http.HttpResponseFor;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\nHttpResponseFor plans = client.plans().withRawResponse().list();\n\nint statusCode = plans.statusCode();\nHeaders headers = plans.headers();\n```\n\nYou can still deserialize the response into an instance of a Java class if needed:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse parsedPlans = plans.parse();\n```\n\n## Error handling\n\nThe SDK throws custom unchecked exception types:\n\n- [`BeagleServiceException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleServiceException.kt): Base class for HTTP errors. See this table for which exception subclass is thrown for each HTTP status code:\n\n | Status | Exception |\n | ------ | -------------------------------------------------- |\n | 400 | [`BadRequestException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BadRequestException.kt) |\n | 401 | [`UnauthorizedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnauthorizedException.kt) |\n | 403 | [`PermissionDeniedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/PermissionDeniedException.kt) |\n | 404 | [`NotFoundException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/NotFoundException.kt) |\n | 422 | [`UnprocessableEntityException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnprocessableEntityException.kt) |\n | 429 | [`RateLimitException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/RateLimitException.kt) |\n | 5xx | [`InternalServerException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/InternalServerException.kt) |\n | others | [`UnexpectedStatusCodeException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnexpectedStatusCodeException.kt) |\n\n- [`BeagleIoException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleIoException.kt): I/O networking errors.\n\n- [`BeagleRetryableException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleRetryableException.kt): Generic error indicating a failure that could be retried by the client.\n\n- [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt): Failure to interpret successfully parsed data. For example, when accessing a property that\'s supposed to be required, but the API unexpectedly omitted it from the response.\n\n- [`BeagleException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleException.kt): Base class for all exceptions. Most errors will result in one of the previously mentioned ones, but completely generic errors may be thrown using the base class.\n\n\n\n## Logging\n\nThe SDK uses the standard [OkHttp logging interceptor](https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor).\n\nEnable logging by setting the `BEAGLE_LOG` environment variable to `info`:\n\n```sh\nexport BEAGLE_LOG=info\n```\n\nOr to `debug` for more verbose logging:\n\n```sh\nexport BEAGLE_LOG=debug\n```\n\n## ProGuard and R8\n\nAlthough the SDK uses reflection, it is still usable with [ProGuard](https://github.com/Guardsquare/proguard) and [R8](https://developer.android.com/topic/performance/app-optimization/enable-app-optimization) because `beagle-java-core` is published with a [configuration file](beagle-java-core/src/main/resources/META-INF/proguard/beagle-java-core.pro) containing [keep rules](https://www.guardsquare.com/manual/configuration/usage).\n\nProGuard and R8 should automatically detect and use the published rules, but you can also manually copy the keep rules if necessary.\n\n\n\n\n\n## Jackson\n\nThe SDK depends on [Jackson](https://github.com/FasterXML/jackson) for JSON serialization/deserialization. It is compatible with version 2.13.4 or higher, but depends on version 2.18.2 by default.\n\nThe SDK throws an exception if it detects an incompatible Jackson version at runtime (e.g. if the default version was overridden in your Maven or Gradle config).\n\nIf the SDK threw an exception, but you\'re _certain_ the version is compatible, then disable the version check using the `checkJacksonVersionCompatibility` on [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt).\n\n> [!CAUTION]\n> We make no guarantee that the SDK works correctly when the Jackson version check is disabled.\n\nAlso note that there are bugs in older Jackson versions that can affect the SDK. We don\'t work around all Jackson bugs ([example](https://github.com/FasterXML/jackson-databind/issues/3240)) and expect users to upgrade Jackson for those instead.\n\n## Network options\n\n### Retries\n\nThe SDK automatically retries 2 times by default, with a short exponential backoff between requests.\n\nOnly the following error types are retried:\n- Connection errors (for example, due to a network connectivity problem)\n- 408 Request Timeout\n- 409 Conflict\n- 429 Rate Limit\n- 5xx Internal\n\nThe API may also explicitly instruct the SDK to retry or not retry a request.\n\nTo set a custom number of retries, configure the client using the `maxRetries` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .maxRetries(4)\n .build();\n```\n\n### Timeouts\n\nRequests time out after 1 minute by default.\n\nTo set a custom timeout, configure the method call using the `timeout` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().timeout(Duration.ofSeconds(30)).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .timeout(Duration.ofSeconds(30))\n .build();\n```\n\n### Proxies\n\nTo route requests through a proxy, configure the client using the `proxy` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.net.InetSocketAddress;\nimport java.net.Proxy;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .proxy(new Proxy(\n Proxy.Type.HTTP, new InetSocketAddress(\n "https://example.com", 8080\n )\n ))\n .build();\n```\n\n### Connection pooling\n\nTo customize the underlying OkHttp connection pool, configure the client using the `maxIdleConnections` and `keepAliveDuration` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `maxIdleConnections` is set, then `keepAliveDuration` must be set, and vice versa.\n .maxIdleConnections(10)\n .keepAliveDuration(Duration.ofMinutes(2))\n .build();\n```\n\nIf both options are unset, OkHttp\'s default connection pool settings are used.\n\n### HTTPS\n\n> [!NOTE]\n> Most applications should not call these methods, and instead use the system defaults. The defaults include\n> special optimizations that can be lost if the implementations are modified.\n\nTo configure how HTTPS connections are secured, configure the client using the `sslSocketFactory`, `trustManager`, and `hostnameVerifier` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `sslSocketFactory` is set, then `trustManager` must be set, and vice versa.\n .sslSocketFactory(yourSSLSocketFactory)\n .trustManager(yourTrustManager)\n .hostnameVerifier(yourHostnameVerifier)\n .build();\n```\n\n### Environments\n\nThe SDK sends requests to the production by default. To send requests to a different environment, configure the client like so:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .staging()\n .build();\n```\n\n### Custom HTTP client\n\nThe SDK consists of three artifacts:\n- `beagle-java-core`\n - Contains core SDK logic\n - Does not depend on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleClient`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClient.kt), [`BeagleClientAsync`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsync.kt), [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt), and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), all of which can work with any HTTP client\n- `beagle-java-client-okhttp`\n - Depends on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) and [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), which provide a way to construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), respectively, using OkHttp\n- `beagle-java`\n - Depends on and exposes the APIs of both `beagle-java-core` and `beagle-java-client-okhttp`\n - Does not have its own logic\n\nThis structure allows replacing the SDK\'s default HTTP client without pulling in unnecessary dependencies.\n\n#### Customized [`OkHttpClient`](https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.html)\n\n> [!TIP]\n> Try the available [network options](#network-options) before replacing the default client.\n\nTo use a customized `OkHttpClient`:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Copy `beagle-java-client-okhttp`\'s [`OkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/OkHttpClient.kt) class into your code and customize it\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your customized client\n\n### Completely custom HTTP client\n\nTo use a completely custom HTTP client:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Write a class that implements the [`HttpClient`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpClient.kt) interface\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your new client class\n\n## Undocumented API functionality\n\nThe SDK is typed for convenient usage of the documented API. However, it also supports working with undocumented or not yet supported parts of the API.\n\n### Parameters\n\nTo set undocumented parameters, call the `putAdditionalHeader`, `putAdditionalQueryParam`, or `putAdditionalBodyProperty` methods on any `Params` class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder()\n .putAdditionalHeader("Secret-Header", "42")\n .putAdditionalQueryParam("secret_query_param", "42")\n .putAdditionalBodyProperty("secretProperty", JsonValue.from("42"))\n .build();\n```\n\nThese can be accessed on the built object later using the `_additionalHeaders()`, `_additionalQueryParams()`, and `_additionalBodyProperties()` methods.\n\nTo set undocumented parameters on _nested_ headers, query params, or body classes, call the `putAdditionalProperty` method on the nested class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.tenants.Address;\nimport com.beagle.api.models.tenants.TenantCreateParams;\n\nTenantCreateParams params = TenantCreateParams.builder()\n .address(Address.builder()\n .putAdditionalProperty("secretProperty", JsonValue.from("42"))\n .build())\n .build();\n```\n\nThese properties can be accessed on the nested built object later using the `_additionalProperties()` method.\n\nTo set a documented parameter or property to an undocumented or not yet supported _value_, pass a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) object to its setter:\n\n```java\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder().build();\n```\n\nThe most straightforward way to create a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) is using its `from(...)` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.List;\nimport java.util.Map;\n\n// Create primitive JSON values\nJsonValue nullValue = JsonValue.from(null);\nJsonValue booleanValue = JsonValue.from(true);\nJsonValue numberValue = JsonValue.from(42);\nJsonValue stringValue = JsonValue.from("Hello World!");\n\n// Create a JSON array value equivalent to `["Hello", "World"]`\nJsonValue arrayValue = JsonValue.from(List.of(\n "Hello", "World"\n));\n\n// Create a JSON object value equivalent to `{ "a": 1, "b": 2 }`\nJsonValue objectValue = JsonValue.from(Map.of(\n "a", 1,\n "b", 2\n));\n\n// Create an arbitrarily nested JSON equivalent to:\n// {\n// "a": [1, 2],\n// "b": [3, 4]\n// }\nJsonValue complexValue = JsonValue.from(Map.of(\n "a", List.of(\n 1, 2\n ),\n "b", List.of(\n 3, 4\n )\n));\n```\n\nNormally a `Builder` class\'s `build` method will throw [`IllegalStateException`](https://docs.oracle.com/javase/8/docs/api/java/lang/IllegalStateException.html) if any required parameter or property is unset.\n\nTo forcibly omit a required parameter or property, pass [`JsonMissing`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt):\n\n```java\nimport com.beagle.api.core.JsonMissing;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanRetrieveParams;\n\nPlanListParams params = PlanRetrieveParams.builder()\n .code(JsonMissing.of())\n .build();\n```\n\n### Response properties\n\nTo access undocumented response properties, call the `_additionalProperties()` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.Map;\n\nMap additionalProperties = client.plans().list(params)._additionalProperties();\nJsonValue secretPropertyValue = additionalProperties.get("secretProperty");\n\nString result = secretPropertyValue.accept(new JsonValue.Visitor<>() {\n @Override\n public String visitNull() {\n return "It\'s null!";\n }\n\n @Override\n public String visitBoolean(boolean value) {\n return "It\'s a boolean!";\n }\n\n @Override\n public String visitNumber(Number value) {\n return "It\'s a number!";\n }\n\n // Other methods include `visitMissing`, `visitString`, `visitArray`, and `visitObject`\n // The default implementation of each unimplemented method delegates to `visitDefault`, which throws by default, but can also be overridden\n});\n```\n\nTo access a property\'s raw JSON value, which may be undocumented, call its `_` prefixed method:\n\n```java\nimport com.beagle.api.core.JsonField;\nimport java.util.Optional;\n\nJsonField field = client.plans().list(params)._field();\n\nif (field.isMissing()) {\n // The property is absent from the JSON response\n} else if (field.isNull()) {\n // The property was set to literal null\n} else {\n // Check if value was provided as a string\n // Other methods include `asNumber()`, `asBoolean()`, etc.\n Optional jsonString = field.asString();\n\n // Try to deserialize into a custom type\n MyClass myObject = field.asUnknown().orElseThrow().convert(MyClass.class);\n}\n```\n\n### Response validation\n\nIn rare cases, the API may return a response that doesn\'t match the expected type. For example, the SDK may expect a property to contain a `String`, but the API could return something else.\n\nBy default, the SDK will not throw an exception in this case. It will throw [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt) only if you directly access the property.\n\nValidating the response is _not_ forwards compatible with new types from the API for existing fields.\n\nIf you would still prefer to check that the response is completely well-typed upfront, then either call `validate()`:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(params).validate();\n```\n\nOr configure the method call to validate the response using the `responseValidation` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().responseValidation(true).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .responseValidation(true)\n .build();\n```\n\n## FAQ\n\n### Why don\'t you use plain `enum` classes?\n\nJava `enum` classes are not trivially [forwards compatible](https://www.stainless.com/blog/making-java-enums-forwards-compatible). Using them in the SDK could cause runtime exceptions if the API is updated to respond with a new enum value.\n\n### Why do you represent fields using `JsonField` instead of just plain `T`?\n\nUsing `JsonField` enables a few features:\n\n- Allowing usage of [undocumented API functionality](#undocumented-api-functionality)\n- Lazily [validating the API response against the expected shape](#response-validation)\n- Representing absent vs explicitly null values\n\n### Why don\'t you use [`data` classes](https://kotlinlang.org/docs/data-classes.html)?\n\nIt is not [backwards compatible to add new fields to a data class](https://kotlinlang.org/docs/api-guidelines-backward-compatibility.html#avoid-using-data-classes-in-your-api) and we don\'t want to introduce a breaking change every time we add a field to a class.\n\n### Why don\'t you use checked exceptions?\n\nChecked exceptions are widely considered a mistake in the Java programming language. In fact, they were omitted from Kotlin for this reason.\n\nChecked exceptions:\n\n- Are verbose to handle\n- Encourage error handling at the wrong level of abstraction, where nothing can be done about the error\n- Are tedious to propagate due to the [function coloring problem](https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function)\n- Don\'t play well with lambdas (also due to the function coloring problem)\n\n## Semantic versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n2. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/beagle-java/issues) with questions, bugs, or suggestions.\n', + '# Beagle Java API Library\n\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.beagle.api/beagle-java)](https://central.sonatype.com/artifact/com.beagle.api/beagle-java/0.0.1)\n[![javadoc](https://javadoc.io/badge2/com.beagle.api/beagle-java/0.0.1/javadoc.svg)](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1)\n\n\nThe Beagle Java SDK provides convenient access to the Beagle REST API from applications written in Java.\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\nJavadocs are available on [javadoc.io](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1).\n\n## Installation\n\n### Gradle\n\n~~~kotlin\nimplementation("com.beagle.api:beagle-java:0.0.1")\n~~~\n\n### Maven\n\n~~~xml\n\n com.beagle.api\n beagle-java\n 0.0.1\n\n~~~\n\n## Requirements\n\nThis library requires Java 8 or later.\n\n## Usage\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nPlanListResponse plans = client.plans().list();\n```\n\n## Client configuration\n\nConfigure the client using system properties or environment variables:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n```\n\nOr manually:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .apiKey("My API Key")\n .build();\n```\n\nOr using a combination of the two approaches:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n // Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n // Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\n .fromEnv()\n .apiKey("My API Key")\n .build();\n```\n\nSee this table for the available options:\n\n| Setter | System property | Environment variable | Required | Default value |\n| --------- | ---------------- | -------------------- | -------- | ------------------------------------- |\n| `apiKey` | `beagle.apiKey` | `BEAGLE_API_KEY` | true | - |\n| `baseUrl` | `beagle.baseUrl` | `BEAGLE_BASE_URL` | true | `"https://developer.beagleforpm.com"` |\n\nSystem properties take precedence over environment variables.\n\n> [!TIP]\n> Don\'t create more than one client in the same application. Each client has a connection pool and\n> thread pools, which are more efficient to share between requests.\n\n### Modifying configuration\n\nTo temporarily use a modified client configuration, while reusing the same connection and thread pools, call `withOptions()` on any client or service:\n\n```java\nimport com.beagle.api.client.BeagleClient;\n\nBeagleClient clientWithOptions = client.withOptions(optionsBuilder -> {\n optionsBuilder.baseUrl("https://example.com");\n optionsBuilder.maxRetries(42);\n});\n```\n\nThe `withOptions()` method does not affect the original client or service.\n\n## Requests and responses\n\nTo send a request to the Beagle API, build an instance of some `Params` class and pass it to the corresponding client method. When the response is received, it will be deserialized into an instance of a Java class.\n\nFor example, `client.plans().list(...)` should be called with an instance of `PlanListParams`, and it will return an instance of `PlanListResponse`.\n\n## Immutability\n\nEach class in the SDK has an associated [builder](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java) or factory method for constructing it.\n\nEach class is [immutable](https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html) once constructed. If the class has an associated builder, then it has a `toBuilder()` method, which can be used to convert it back to a builder for making a modified copy.\n\nBecause each class is immutable, builder modification will _never_ affect already built class instances.\n\n## Asynchronous execution\n\nThe default client is synchronous. To switch to asynchronous execution, call the `async()` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nCompletableFuture plans = client.async().plans().list();\n```\n\nOr create an asynchronous client from the beginning:\n\n```java\nimport com.beagle.api.client.BeagleClientAsync;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClientAsync;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClientAsync client = BeagleOkHttpClientAsync.fromEnv();\n\nCompletableFuture plans = client.plans().list();\n```\n\nThe asynchronous client supports the same options as the synchronous one, except most methods return `CompletableFuture`s.\n\n\n\n\n\n## Binary responses\n\nThe SDK defines methods that return binary responses, which are used for API responses that shouldn\'t necessarily be parsed, like non-JSON data.\n\nThese methods return [`HttpResponse`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpResponse.kt):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport com.beagle.api.models.enrollments.EnrollmentRetrieveCertificateParams;\n\nHttpResponse response = client.enrollments().retrieveCertificate(123.0);\n```\n\nTo save the response content to a file, use the [`Files.copy(...)`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#copy-java.io.InputStream-java.nio.file.Path-java.nio.file.CopyOption...-) method:\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.nio.file.StandardCopyOption;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n Files.copy(\n response.body(),\n Paths.get(path),\n StandardCopyOption.REPLACE_EXISTING\n );\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\nOr transfer the response content to any [`OutputStream`](https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n response.body().transferTo(Files.newOutputStream(Paths.get(path)));\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\n## Raw responses\n\nThe SDK defines methods that deserialize responses into instances of Java classes. However, these methods don\'t provide access to the response headers, status code, or the raw response body.\n\nTo access this data, prefix any HTTP method call on a client or service with `withRawResponse()`:\n\n```java\nimport com.beagle.api.core.http.Headers;\nimport com.beagle.api.core.http.HttpResponseFor;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\nHttpResponseFor plans = client.plans().withRawResponse().list();\n\nint statusCode = plans.statusCode();\nHeaders headers = plans.headers();\n```\n\nYou can still deserialize the response into an instance of a Java class if needed:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse parsedPlans = plans.parse();\n```\n\n## Error handling\n\nThe SDK throws custom unchecked exception types:\n\n- [`BeagleServiceException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleServiceException.kt): Base class for HTTP errors. See this table for which exception subclass is thrown for each HTTP status code:\n\n | Status | Exception |\n | ------ | -------------------------------------------------- |\n | 400 | [`BadRequestException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BadRequestException.kt) |\n | 401 | [`UnauthorizedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnauthorizedException.kt) |\n | 403 | [`PermissionDeniedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/PermissionDeniedException.kt) |\n | 404 | [`NotFoundException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/NotFoundException.kt) |\n | 422 | [`UnprocessableEntityException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnprocessableEntityException.kt) |\n | 429 | [`RateLimitException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/RateLimitException.kt) |\n | 5xx | [`InternalServerException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/InternalServerException.kt) |\n | others | [`UnexpectedStatusCodeException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnexpectedStatusCodeException.kt) |\n\n- [`BeagleIoException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleIoException.kt): I/O networking errors.\n\n- [`BeagleRetryableException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleRetryableException.kt): Generic error indicating a failure that could be retried by the client.\n\n- [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt): Failure to interpret successfully parsed data. For example, when accessing a property that\'s supposed to be required, but the API unexpectedly omitted it from the response.\n\n- [`BeagleException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleException.kt): Base class for all exceptions. Most errors will result in one of the previously mentioned ones, but completely generic errors may be thrown using the base class.\n\n\n\n## Logging\n\nThe SDK uses the standard [OkHttp logging interceptor](https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor).\n\nEnable logging by setting the `BEAGLE_LOG` environment variable to `info`:\n\n```sh\nexport BEAGLE_LOG=info\n```\n\nOr to `debug` for more verbose logging:\n\n```sh\nexport BEAGLE_LOG=debug\n```\n\n## ProGuard and R8\n\nAlthough the SDK uses reflection, it is still usable with [ProGuard](https://github.com/Guardsquare/proguard) and [R8](https://developer.android.com/topic/performance/app-optimization/enable-app-optimization) because `beagle-java-core` is published with a [configuration file](beagle-java-core/src/main/resources/META-INF/proguard/beagle-java-core.pro) containing [keep rules](https://www.guardsquare.com/manual/configuration/usage).\n\nProGuard and R8 should automatically detect and use the published rules, but you can also manually copy the keep rules if necessary.\n\n\n\n\n\n## Jackson\n\nThe SDK depends on [Jackson](https://github.com/FasterXML/jackson) for JSON serialization/deserialization. It is compatible with version 2.13.4 or higher, but depends on version 2.18.2 by default.\n\nThe SDK throws an exception if it detects an incompatible Jackson version at runtime (e.g. if the default version was overridden in your Maven or Gradle config).\n\nIf the SDK threw an exception, but you\'re _certain_ the version is compatible, then disable the version check using the `checkJacksonVersionCompatibility` on [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt).\n\n> [!CAUTION]\n> We make no guarantee that the SDK works correctly when the Jackson version check is disabled.\n\nAlso note that there are bugs in older Jackson versions that can affect the SDK. We don\'t work around all Jackson bugs ([example](https://github.com/FasterXML/jackson-databind/issues/3240)) and expect users to upgrade Jackson for those instead.\n\n## Network options\n\n### Retries\n\nThe SDK automatically retries 2 times by default, with a short exponential backoff between requests.\n\nOnly the following error types are retried:\n- Connection errors (for example, due to a network connectivity problem)\n- 408 Request Timeout\n- 409 Conflict\n- 429 Rate Limit\n- 5xx Internal\n\nThe API may also explicitly instruct the SDK to retry or not retry a request.\n\nTo set a custom number of retries, configure the client using the `maxRetries` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .maxRetries(4)\n .build();\n```\n\n### Timeouts\n\nRequests time out after 1 minute by default.\n\nTo set a custom timeout, configure the method call using the `timeout` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().timeout(Duration.ofSeconds(30)).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .timeout(Duration.ofSeconds(30))\n .build();\n```\n\n### Proxies\n\nTo route requests through a proxy, configure the client using the `proxy` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.net.InetSocketAddress;\nimport java.net.Proxy;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .proxy(new Proxy(\n Proxy.Type.HTTP, new InetSocketAddress(\n "https://example.com", 8080\n )\n ))\n .build();\n```\n\nIf the proxy responds with `407 Proxy Authentication Required`, supply credentials by also configuring `proxyAuthenticator`:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.core.http.ProxyAuthenticator;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .proxy(...)\n // Or a custom implementation of `ProxyAuthenticator`.\n .proxyAuthenticator(ProxyAuthenticator.basic("username", "password"))\n .build();\n```\n\n### Connection pooling\n\nTo customize the underlying OkHttp connection pool, configure the client using the `maxIdleConnections` and `keepAliveDuration` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `maxIdleConnections` is set, then `keepAliveDuration` must be set, and vice versa.\n .maxIdleConnections(10)\n .keepAliveDuration(Duration.ofMinutes(2))\n .build();\n```\n\nIf both options are unset, OkHttp\'s default connection pool settings are used.\n\n### HTTPS\n\n> [!NOTE]\n> Most applications should not call these methods, and instead use the system defaults. The defaults include\n> special optimizations that can be lost if the implementations are modified.\n\nTo configure how HTTPS connections are secured, configure the client using the `sslSocketFactory`, `trustManager`, and `hostnameVerifier` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `sslSocketFactory` is set, then `trustManager` must be set, and vice versa.\n .sslSocketFactory(yourSSLSocketFactory)\n .trustManager(yourTrustManager)\n .hostnameVerifier(yourHostnameVerifier)\n .build();\n```\n\n### Environments\n\nThe SDK sends requests to the production by default. To send requests to a different environment, configure the client like so:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .staging()\n .build();\n```\n\n### Custom HTTP client\n\nThe SDK consists of three artifacts:\n- `beagle-java-core`\n - Contains core SDK logic\n - Does not depend on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleClient`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClient.kt), [`BeagleClientAsync`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsync.kt), [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt), and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), all of which can work with any HTTP client\n- `beagle-java-client-okhttp`\n - Depends on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) and [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), which provide a way to construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), respectively, using OkHttp\n- `beagle-java`\n - Depends on and exposes the APIs of both `beagle-java-core` and `beagle-java-client-okhttp`\n - Does not have its own logic\n\nThis structure allows replacing the SDK\'s default HTTP client without pulling in unnecessary dependencies.\n\n#### Customized [`OkHttpClient`](https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.html)\n\n> [!TIP]\n> Try the available [network options](#network-options) before replacing the default client.\n\nTo use a customized `OkHttpClient`:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Copy `beagle-java-client-okhttp`\'s [`OkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/OkHttpClient.kt) class into your code and customize it\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your customized client\n\n### Completely custom HTTP client\n\nTo use a completely custom HTTP client:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Write a class that implements the [`HttpClient`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpClient.kt) interface\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your new client class\n\n## Undocumented API functionality\n\nThe SDK is typed for convenient usage of the documented API. However, it also supports working with undocumented or not yet supported parts of the API.\n\n### Parameters\n\nTo set undocumented parameters, call the `putAdditionalHeader`, `putAdditionalQueryParam`, or `putAdditionalBodyProperty` methods on any `Params` class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder()\n .putAdditionalHeader("Secret-Header", "42")\n .putAdditionalQueryParam("secret_query_param", "42")\n .putAdditionalBodyProperty("secretProperty", JsonValue.from("42"))\n .build();\n```\n\nThese can be accessed on the built object later using the `_additionalHeaders()`, `_additionalQueryParams()`, and `_additionalBodyProperties()` methods.\n\nTo set undocumented parameters on _nested_ headers, query params, or body classes, call the `putAdditionalProperty` method on the nested class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.tenants.Address;\nimport com.beagle.api.models.tenants.TenantCreateParams;\n\nTenantCreateParams params = TenantCreateParams.builder()\n .address(Address.builder()\n .putAdditionalProperty("secretProperty", JsonValue.from("42"))\n .build())\n .build();\n```\n\nThese properties can be accessed on the nested built object later using the `_additionalProperties()` method.\n\nTo set a documented parameter or property to an undocumented or not yet supported _value_, pass a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) object to its setter:\n\n```java\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder().build();\n```\n\nThe most straightforward way to create a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) is using its `from(...)` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.List;\nimport java.util.Map;\n\n// Create primitive JSON values\nJsonValue nullValue = JsonValue.from(null);\nJsonValue booleanValue = JsonValue.from(true);\nJsonValue numberValue = JsonValue.from(42);\nJsonValue stringValue = JsonValue.from("Hello World!");\n\n// Create a JSON array value equivalent to `["Hello", "World"]`\nJsonValue arrayValue = JsonValue.from(List.of(\n "Hello", "World"\n));\n\n// Create a JSON object value equivalent to `{ "a": 1, "b": 2 }`\nJsonValue objectValue = JsonValue.from(Map.of(\n "a", 1,\n "b", 2\n));\n\n// Create an arbitrarily nested JSON equivalent to:\n// {\n// "a": [1, 2],\n// "b": [3, 4]\n// }\nJsonValue complexValue = JsonValue.from(Map.of(\n "a", List.of(\n 1, 2\n ),\n "b", List.of(\n 3, 4\n )\n));\n```\n\nNormally a `Builder` class\'s `build` method will throw [`IllegalStateException`](https://docs.oracle.com/javase/8/docs/api/java/lang/IllegalStateException.html) if any required parameter or property is unset.\n\nTo forcibly omit a required parameter or property, pass [`JsonMissing`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt):\n\n```java\nimport com.beagle.api.core.JsonMissing;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanRetrieveParams;\n\nPlanListParams params = PlanRetrieveParams.builder()\n .code(JsonMissing.of())\n .build();\n```\n\n### Response properties\n\nTo access undocumented response properties, call the `_additionalProperties()` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.Map;\n\nMap additionalProperties = client.plans().list(params)._additionalProperties();\nJsonValue secretPropertyValue = additionalProperties.get("secretProperty");\n\nString result = secretPropertyValue.accept(new JsonValue.Visitor<>() {\n @Override\n public String visitNull() {\n return "It\'s null!";\n }\n\n @Override\n public String visitBoolean(boolean value) {\n return "It\'s a boolean!";\n }\n\n @Override\n public String visitNumber(Number value) {\n return "It\'s a number!";\n }\n\n // Other methods include `visitMissing`, `visitString`, `visitArray`, and `visitObject`\n // The default implementation of each unimplemented method delegates to `visitDefault`, which throws by default, but can also be overridden\n});\n```\n\nTo access a property\'s raw JSON value, which may be undocumented, call its `_` prefixed method:\n\n```java\nimport com.beagle.api.core.JsonField;\nimport java.util.Optional;\n\nJsonField field = client.plans().list(params)._field();\n\nif (field.isMissing()) {\n // The property is absent from the JSON response\n} else if (field.isNull()) {\n // The property was set to literal null\n} else {\n // Check if value was provided as a string\n // Other methods include `asNumber()`, `asBoolean()`, etc.\n Optional jsonString = field.asString();\n\n // Try to deserialize into a custom type\n MyClass myObject = field.asUnknown().orElseThrow().convert(MyClass.class);\n}\n```\n\n### Response validation\n\nIn rare cases, the API may return a response that doesn\'t match the expected type. For example, the SDK may expect a property to contain a `String`, but the API could return something else.\n\nBy default, the SDK will not throw an exception in this case. It will throw [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt) only if you directly access the property.\n\nValidating the response is _not_ forwards compatible with new types from the API for existing fields.\n\nIf you would still prefer to check that the response is completely well-typed upfront, then either call `validate()`:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(params).validate();\n```\n\nOr configure the method call to validate the response using the `responseValidation` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().responseValidation(true).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .responseValidation(true)\n .build();\n```\n\n## FAQ\n\n### Why don\'t you use plain `enum` classes?\n\nJava `enum` classes are not trivially [forwards compatible](https://www.stainless.com/blog/making-java-enums-forwards-compatible). Using them in the SDK could cause runtime exceptions if the API is updated to respond with a new enum value.\n\n### Why do you represent fields using `JsonField` instead of just plain `T`?\n\nUsing `JsonField` enables a few features:\n\n- Allowing usage of [undocumented API functionality](#undocumented-api-functionality)\n- Lazily [validating the API response against the expected shape](#response-validation)\n- Representing absent vs explicitly null values\n\n### Why don\'t you use [`data` classes](https://kotlinlang.org/docs/data-classes.html)?\n\nIt is not [backwards compatible to add new fields to a data class](https://kotlinlang.org/docs/api-guidelines-backward-compatibility.html#avoid-using-data-classes-in-your-api) and we don\'t want to introduce a breaking change every time we add a field to a class.\n\n### Why don\'t you use checked exceptions?\n\nChecked exceptions are widely considered a mistake in the Java programming language. In fact, they were omitted from Kotlin for this reason.\n\nChecked exceptions:\n\n- Are verbose to handle\n- Encourage error handling at the wrong level of abstraction, where nothing can be done about the error\n- Are tedious to propagate due to the [function coloring problem](https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function)\n- Don\'t play well with lambdas (also due to the function coloring problem)\n\n## Semantic versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n2. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/beagle-java/issues) with questions, bugs, or suggestions.\n', }, { language: 'python', From d48674e4ff226a997fe0e791e908369cea5b149b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 8 May 2026 03:45:48 +0000 Subject: [PATCH 127/138] chore(internal): codegen related update --- packages/mcp-server/src/local-docs-search.ts | 10 +++++----- src/internal/utils/log.ts | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index a62d92a3..19d2b653 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -252,7 +252,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, http: { example: - "curl https://developer.beagleforpm.com/api/property-managers/$ID \\\n -X PATCH \\\n -H 'Content-Type: application/json' \\\n -H \"x-api-key: $BEAGLE_API_KEY\" \\\n -d '{}'", + 'curl https://developer.beagleforpm.com/api/property-managers/$ID \\\n -X PATCH \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "addresses": [\n {\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Electric Ave.",\n "zip": "84115",\n "kind": "place of business"\n }\n ],\n "clickWrapAt": 1773359774000,\n "contacts": [\n {\n "email": "mr.milchick@example.com",\n "name": {\n "first": "Seth",\n "last": "Milchick"\n },\n "phone": "(123) 456-7890",\n "kind": "reporting"\n }\n ],\n "name": "Lumon Apartments"\n }\'', }, }, }, @@ -405,7 +405,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, http: { example: - 'curl https://developer.beagleforpm.com/api/property-managers \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "addresses": [\n {\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Electric Ave.",\n "zip": "84115",\n "kind": "place of business"\n }\n ],\n "contacts": [\n {\n "email": "mr.milchick@example.com",\n "name": {\n "first": "Seth",\n "last": "Milchick"\n },\n "phone": "(123) 456-7890",\n "kind": "reporting"\n }\n ],\n "name": "Lumon Apartments"\n }\'', + 'curl https://developer.beagleforpm.com/api/property-managers \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "addresses": [\n {\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Electric Ave.",\n "zip": "84115",\n "kind": "place of business"\n }\n ],\n "contacts": [\n {\n "email": "mr.milchick@example.com",\n "name": {\n "first": "Seth",\n "last": "Milchick"\n },\n "phone": "(123) 456-7890",\n "kind": "reporting"\n }\n ],\n "name": "Lumon Apartments",\n "clickWrapAt": 1773359774000\n }\'', }, }, }, @@ -507,7 +507,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, http: { example: - "curl https://developer.beagleforpm.com/api/tenants/$ID \\\n -X PATCH \\\n -H 'Content-Type: application/json' \\\n -H \"x-api-key: $BEAGLE_API_KEY\" \\\n -d '{}'", + 'curl https://developer.beagleforpm.com/api/tenants/$ID \\\n -X PATCH \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "address": {\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Main St.",\n "zip": "84115",\n "street2": "Unit 3"\n },\n "contact": {\n "email": "mark.s@example.com",\n "name": {\n "first": "Mark",\n "last": "Scout"\n },\n "phone": "(123) 456-7890"\n }\n }\'', }, }, }, @@ -863,7 +863,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, http: { example: - 'curl https://developer.beagleforpm.com/api/enrollments \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "effectiveDate": "2025-11-10T19:50:20.638Z",\n "plan": "TLL_100K_CONTENTS_5K_ACV",\n "propertyManagerId": 123,\n "tenantId": 123\n }\'', + 'curl https://developer.beagleforpm.com/api/enrollments \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "effectiveDate": "2025-11-10T19:50:20.638Z",\n "plan": "TLL_100K_CONTENTS_5K_ACV",\n "propertyManagerId": 123,\n "tenantId": 123,\n "status": "Issued, Not Paid"\n }\'', }, }, }, @@ -981,7 +981,7 @@ const EMBEDDED_READMES: { language: string; content: string }[] = [ { language: 'java', content: - '# Beagle Java API Library\n\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.beagle.api/beagle-java)](https://central.sonatype.com/artifact/com.beagle.api/beagle-java/0.0.1)\n[![javadoc](https://javadoc.io/badge2/com.beagle.api/beagle-java/0.0.1/javadoc.svg)](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1)\n\n\nThe Beagle Java SDK provides convenient access to the Beagle REST API from applications written in Java.\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\nJavadocs are available on [javadoc.io](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1).\n\n## Installation\n\n### Gradle\n\n~~~kotlin\nimplementation("com.beagle.api:beagle-java:0.0.1")\n~~~\n\n### Maven\n\n~~~xml\n\n com.beagle.api\n beagle-java\n 0.0.1\n\n~~~\n\n## Requirements\n\nThis library requires Java 8 or later.\n\n## Usage\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nPlanListResponse plans = client.plans().list();\n```\n\n## Client configuration\n\nConfigure the client using system properties or environment variables:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n```\n\nOr manually:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .apiKey("My API Key")\n .build();\n```\n\nOr using a combination of the two approaches:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n // Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n // Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\n .fromEnv()\n .apiKey("My API Key")\n .build();\n```\n\nSee this table for the available options:\n\n| Setter | System property | Environment variable | Required | Default value |\n| --------- | ---------------- | -------------------- | -------- | ------------------------------------- |\n| `apiKey` | `beagle.apiKey` | `BEAGLE_API_KEY` | true | - |\n| `baseUrl` | `beagle.baseUrl` | `BEAGLE_BASE_URL` | true | `"https://developer.beagleforpm.com"` |\n\nSystem properties take precedence over environment variables.\n\n> [!TIP]\n> Don\'t create more than one client in the same application. Each client has a connection pool and\n> thread pools, which are more efficient to share between requests.\n\n### Modifying configuration\n\nTo temporarily use a modified client configuration, while reusing the same connection and thread pools, call `withOptions()` on any client or service:\n\n```java\nimport com.beagle.api.client.BeagleClient;\n\nBeagleClient clientWithOptions = client.withOptions(optionsBuilder -> {\n optionsBuilder.baseUrl("https://example.com");\n optionsBuilder.maxRetries(42);\n});\n```\n\nThe `withOptions()` method does not affect the original client or service.\n\n## Requests and responses\n\nTo send a request to the Beagle API, build an instance of some `Params` class and pass it to the corresponding client method. When the response is received, it will be deserialized into an instance of a Java class.\n\nFor example, `client.plans().list(...)` should be called with an instance of `PlanListParams`, and it will return an instance of `PlanListResponse`.\n\n## Immutability\n\nEach class in the SDK has an associated [builder](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java) or factory method for constructing it.\n\nEach class is [immutable](https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html) once constructed. If the class has an associated builder, then it has a `toBuilder()` method, which can be used to convert it back to a builder for making a modified copy.\n\nBecause each class is immutable, builder modification will _never_ affect already built class instances.\n\n## Asynchronous execution\n\nThe default client is synchronous. To switch to asynchronous execution, call the `async()` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nCompletableFuture plans = client.async().plans().list();\n```\n\nOr create an asynchronous client from the beginning:\n\n```java\nimport com.beagle.api.client.BeagleClientAsync;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClientAsync;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClientAsync client = BeagleOkHttpClientAsync.fromEnv();\n\nCompletableFuture plans = client.plans().list();\n```\n\nThe asynchronous client supports the same options as the synchronous one, except most methods return `CompletableFuture`s.\n\n\n\n\n\n## Binary responses\n\nThe SDK defines methods that return binary responses, which are used for API responses that shouldn\'t necessarily be parsed, like non-JSON data.\n\nThese methods return [`HttpResponse`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpResponse.kt):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport com.beagle.api.models.enrollments.EnrollmentRetrieveCertificateParams;\n\nHttpResponse response = client.enrollments().retrieveCertificate(123.0);\n```\n\nTo save the response content to a file, use the [`Files.copy(...)`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#copy-java.io.InputStream-java.nio.file.Path-java.nio.file.CopyOption...-) method:\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.nio.file.StandardCopyOption;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n Files.copy(\n response.body(),\n Paths.get(path),\n StandardCopyOption.REPLACE_EXISTING\n );\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\nOr transfer the response content to any [`OutputStream`](https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n response.body().transferTo(Files.newOutputStream(Paths.get(path)));\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\n## Raw responses\n\nThe SDK defines methods that deserialize responses into instances of Java classes. However, these methods don\'t provide access to the response headers, status code, or the raw response body.\n\nTo access this data, prefix any HTTP method call on a client or service with `withRawResponse()`:\n\n```java\nimport com.beagle.api.core.http.Headers;\nimport com.beagle.api.core.http.HttpResponseFor;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\nHttpResponseFor plans = client.plans().withRawResponse().list();\n\nint statusCode = plans.statusCode();\nHeaders headers = plans.headers();\n```\n\nYou can still deserialize the response into an instance of a Java class if needed:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse parsedPlans = plans.parse();\n```\n\n## Error handling\n\nThe SDK throws custom unchecked exception types:\n\n- [`BeagleServiceException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleServiceException.kt): Base class for HTTP errors. See this table for which exception subclass is thrown for each HTTP status code:\n\n | Status | Exception |\n | ------ | -------------------------------------------------- |\n | 400 | [`BadRequestException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BadRequestException.kt) |\n | 401 | [`UnauthorizedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnauthorizedException.kt) |\n | 403 | [`PermissionDeniedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/PermissionDeniedException.kt) |\n | 404 | [`NotFoundException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/NotFoundException.kt) |\n | 422 | [`UnprocessableEntityException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnprocessableEntityException.kt) |\n | 429 | [`RateLimitException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/RateLimitException.kt) |\n | 5xx | [`InternalServerException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/InternalServerException.kt) |\n | others | [`UnexpectedStatusCodeException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnexpectedStatusCodeException.kt) |\n\n- [`BeagleIoException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleIoException.kt): I/O networking errors.\n\n- [`BeagleRetryableException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleRetryableException.kt): Generic error indicating a failure that could be retried by the client.\n\n- [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt): Failure to interpret successfully parsed data. For example, when accessing a property that\'s supposed to be required, but the API unexpectedly omitted it from the response.\n\n- [`BeagleException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleException.kt): Base class for all exceptions. Most errors will result in one of the previously mentioned ones, but completely generic errors may be thrown using the base class.\n\n\n\n## Logging\n\nThe SDK uses the standard [OkHttp logging interceptor](https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor).\n\nEnable logging by setting the `BEAGLE_LOG` environment variable to `info`:\n\n```sh\nexport BEAGLE_LOG=info\n```\n\nOr to `debug` for more verbose logging:\n\n```sh\nexport BEAGLE_LOG=debug\n```\n\n## ProGuard and R8\n\nAlthough the SDK uses reflection, it is still usable with [ProGuard](https://github.com/Guardsquare/proguard) and [R8](https://developer.android.com/topic/performance/app-optimization/enable-app-optimization) because `beagle-java-core` is published with a [configuration file](beagle-java-core/src/main/resources/META-INF/proguard/beagle-java-core.pro) containing [keep rules](https://www.guardsquare.com/manual/configuration/usage).\n\nProGuard and R8 should automatically detect and use the published rules, but you can also manually copy the keep rules if necessary.\n\n\n\n\n\n## Jackson\n\nThe SDK depends on [Jackson](https://github.com/FasterXML/jackson) for JSON serialization/deserialization. It is compatible with version 2.13.4 or higher, but depends on version 2.18.2 by default.\n\nThe SDK throws an exception if it detects an incompatible Jackson version at runtime (e.g. if the default version was overridden in your Maven or Gradle config).\n\nIf the SDK threw an exception, but you\'re _certain_ the version is compatible, then disable the version check using the `checkJacksonVersionCompatibility` on [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt).\n\n> [!CAUTION]\n> We make no guarantee that the SDK works correctly when the Jackson version check is disabled.\n\nAlso note that there are bugs in older Jackson versions that can affect the SDK. We don\'t work around all Jackson bugs ([example](https://github.com/FasterXML/jackson-databind/issues/3240)) and expect users to upgrade Jackson for those instead.\n\n## Network options\n\n### Retries\n\nThe SDK automatically retries 2 times by default, with a short exponential backoff between requests.\n\nOnly the following error types are retried:\n- Connection errors (for example, due to a network connectivity problem)\n- 408 Request Timeout\n- 409 Conflict\n- 429 Rate Limit\n- 5xx Internal\n\nThe API may also explicitly instruct the SDK to retry or not retry a request.\n\nTo set a custom number of retries, configure the client using the `maxRetries` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .maxRetries(4)\n .build();\n```\n\n### Timeouts\n\nRequests time out after 1 minute by default.\n\nTo set a custom timeout, configure the method call using the `timeout` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().timeout(Duration.ofSeconds(30)).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .timeout(Duration.ofSeconds(30))\n .build();\n```\n\n### Proxies\n\nTo route requests through a proxy, configure the client using the `proxy` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.net.InetSocketAddress;\nimport java.net.Proxy;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .proxy(new Proxy(\n Proxy.Type.HTTP, new InetSocketAddress(\n "https://example.com", 8080\n )\n ))\n .build();\n```\n\nIf the proxy responds with `407 Proxy Authentication Required`, supply credentials by also configuring `proxyAuthenticator`:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.core.http.ProxyAuthenticator;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .proxy(...)\n // Or a custom implementation of `ProxyAuthenticator`.\n .proxyAuthenticator(ProxyAuthenticator.basic("username", "password"))\n .build();\n```\n\n### Connection pooling\n\nTo customize the underlying OkHttp connection pool, configure the client using the `maxIdleConnections` and `keepAliveDuration` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `maxIdleConnections` is set, then `keepAliveDuration` must be set, and vice versa.\n .maxIdleConnections(10)\n .keepAliveDuration(Duration.ofMinutes(2))\n .build();\n```\n\nIf both options are unset, OkHttp\'s default connection pool settings are used.\n\n### HTTPS\n\n> [!NOTE]\n> Most applications should not call these methods, and instead use the system defaults. The defaults include\n> special optimizations that can be lost if the implementations are modified.\n\nTo configure how HTTPS connections are secured, configure the client using the `sslSocketFactory`, `trustManager`, and `hostnameVerifier` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `sslSocketFactory` is set, then `trustManager` must be set, and vice versa.\n .sslSocketFactory(yourSSLSocketFactory)\n .trustManager(yourTrustManager)\n .hostnameVerifier(yourHostnameVerifier)\n .build();\n```\n\n### Environments\n\nThe SDK sends requests to the production by default. To send requests to a different environment, configure the client like so:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .staging()\n .build();\n```\n\n### Custom HTTP client\n\nThe SDK consists of three artifacts:\n- `beagle-java-core`\n - Contains core SDK logic\n - Does not depend on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleClient`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClient.kt), [`BeagleClientAsync`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsync.kt), [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt), and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), all of which can work with any HTTP client\n- `beagle-java-client-okhttp`\n - Depends on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) and [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), which provide a way to construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), respectively, using OkHttp\n- `beagle-java`\n - Depends on and exposes the APIs of both `beagle-java-core` and `beagle-java-client-okhttp`\n - Does not have its own logic\n\nThis structure allows replacing the SDK\'s default HTTP client without pulling in unnecessary dependencies.\n\n#### Customized [`OkHttpClient`](https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.html)\n\n> [!TIP]\n> Try the available [network options](#network-options) before replacing the default client.\n\nTo use a customized `OkHttpClient`:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Copy `beagle-java-client-okhttp`\'s [`OkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/OkHttpClient.kt) class into your code and customize it\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your customized client\n\n### Completely custom HTTP client\n\nTo use a completely custom HTTP client:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Write a class that implements the [`HttpClient`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpClient.kt) interface\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your new client class\n\n## Undocumented API functionality\n\nThe SDK is typed for convenient usage of the documented API. However, it also supports working with undocumented or not yet supported parts of the API.\n\n### Parameters\n\nTo set undocumented parameters, call the `putAdditionalHeader`, `putAdditionalQueryParam`, or `putAdditionalBodyProperty` methods on any `Params` class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder()\n .putAdditionalHeader("Secret-Header", "42")\n .putAdditionalQueryParam("secret_query_param", "42")\n .putAdditionalBodyProperty("secretProperty", JsonValue.from("42"))\n .build();\n```\n\nThese can be accessed on the built object later using the `_additionalHeaders()`, `_additionalQueryParams()`, and `_additionalBodyProperties()` methods.\n\nTo set undocumented parameters on _nested_ headers, query params, or body classes, call the `putAdditionalProperty` method on the nested class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.tenants.Address;\nimport com.beagle.api.models.tenants.TenantCreateParams;\n\nTenantCreateParams params = TenantCreateParams.builder()\n .address(Address.builder()\n .putAdditionalProperty("secretProperty", JsonValue.from("42"))\n .build())\n .build();\n```\n\nThese properties can be accessed on the nested built object later using the `_additionalProperties()` method.\n\nTo set a documented parameter or property to an undocumented or not yet supported _value_, pass a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) object to its setter:\n\n```java\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder().build();\n```\n\nThe most straightforward way to create a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) is using its `from(...)` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.List;\nimport java.util.Map;\n\n// Create primitive JSON values\nJsonValue nullValue = JsonValue.from(null);\nJsonValue booleanValue = JsonValue.from(true);\nJsonValue numberValue = JsonValue.from(42);\nJsonValue stringValue = JsonValue.from("Hello World!");\n\n// Create a JSON array value equivalent to `["Hello", "World"]`\nJsonValue arrayValue = JsonValue.from(List.of(\n "Hello", "World"\n));\n\n// Create a JSON object value equivalent to `{ "a": 1, "b": 2 }`\nJsonValue objectValue = JsonValue.from(Map.of(\n "a", 1,\n "b", 2\n));\n\n// Create an arbitrarily nested JSON equivalent to:\n// {\n// "a": [1, 2],\n// "b": [3, 4]\n// }\nJsonValue complexValue = JsonValue.from(Map.of(\n "a", List.of(\n 1, 2\n ),\n "b", List.of(\n 3, 4\n )\n));\n```\n\nNormally a `Builder` class\'s `build` method will throw [`IllegalStateException`](https://docs.oracle.com/javase/8/docs/api/java/lang/IllegalStateException.html) if any required parameter or property is unset.\n\nTo forcibly omit a required parameter or property, pass [`JsonMissing`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt):\n\n```java\nimport com.beagle.api.core.JsonMissing;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanRetrieveParams;\n\nPlanListParams params = PlanRetrieveParams.builder()\n .code(JsonMissing.of())\n .build();\n```\n\n### Response properties\n\nTo access undocumented response properties, call the `_additionalProperties()` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.Map;\n\nMap additionalProperties = client.plans().list(params)._additionalProperties();\nJsonValue secretPropertyValue = additionalProperties.get("secretProperty");\n\nString result = secretPropertyValue.accept(new JsonValue.Visitor<>() {\n @Override\n public String visitNull() {\n return "It\'s null!";\n }\n\n @Override\n public String visitBoolean(boolean value) {\n return "It\'s a boolean!";\n }\n\n @Override\n public String visitNumber(Number value) {\n return "It\'s a number!";\n }\n\n // Other methods include `visitMissing`, `visitString`, `visitArray`, and `visitObject`\n // The default implementation of each unimplemented method delegates to `visitDefault`, which throws by default, but can also be overridden\n});\n```\n\nTo access a property\'s raw JSON value, which may be undocumented, call its `_` prefixed method:\n\n```java\nimport com.beagle.api.core.JsonField;\nimport java.util.Optional;\n\nJsonField field = client.plans().list(params)._field();\n\nif (field.isMissing()) {\n // The property is absent from the JSON response\n} else if (field.isNull()) {\n // The property was set to literal null\n} else {\n // Check if value was provided as a string\n // Other methods include `asNumber()`, `asBoolean()`, etc.\n Optional jsonString = field.asString();\n\n // Try to deserialize into a custom type\n MyClass myObject = field.asUnknown().orElseThrow().convert(MyClass.class);\n}\n```\n\n### Response validation\n\nIn rare cases, the API may return a response that doesn\'t match the expected type. For example, the SDK may expect a property to contain a `String`, but the API could return something else.\n\nBy default, the SDK will not throw an exception in this case. It will throw [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt) only if you directly access the property.\n\nValidating the response is _not_ forwards compatible with new types from the API for existing fields.\n\nIf you would still prefer to check that the response is completely well-typed upfront, then either call `validate()`:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(params).validate();\n```\n\nOr configure the method call to validate the response using the `responseValidation` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().responseValidation(true).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .responseValidation(true)\n .build();\n```\n\n## FAQ\n\n### Why don\'t you use plain `enum` classes?\n\nJava `enum` classes are not trivially [forwards compatible](https://www.stainless.com/blog/making-java-enums-forwards-compatible). Using them in the SDK could cause runtime exceptions if the API is updated to respond with a new enum value.\n\n### Why do you represent fields using `JsonField` instead of just plain `T`?\n\nUsing `JsonField` enables a few features:\n\n- Allowing usage of [undocumented API functionality](#undocumented-api-functionality)\n- Lazily [validating the API response against the expected shape](#response-validation)\n- Representing absent vs explicitly null values\n\n### Why don\'t you use [`data` classes](https://kotlinlang.org/docs/data-classes.html)?\n\nIt is not [backwards compatible to add new fields to a data class](https://kotlinlang.org/docs/api-guidelines-backward-compatibility.html#avoid-using-data-classes-in-your-api) and we don\'t want to introduce a breaking change every time we add a field to a class.\n\n### Why don\'t you use checked exceptions?\n\nChecked exceptions are widely considered a mistake in the Java programming language. In fact, they were omitted from Kotlin for this reason.\n\nChecked exceptions:\n\n- Are verbose to handle\n- Encourage error handling at the wrong level of abstraction, where nothing can be done about the error\n- Are tedious to propagate due to the [function coloring problem](https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function)\n- Don\'t play well with lambdas (also due to the function coloring problem)\n\n## Semantic versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n2. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/beagle-java/issues) with questions, bugs, or suggestions.\n', + '# Beagle Java API Library\n\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.beagle.api/beagle-java)](https://central.sonatype.com/artifact/com.beagle.api/beagle-java/0.0.1)\n[![javadoc](https://javadoc.io/badge2/com.beagle.api/beagle-java/0.0.1/javadoc.svg)](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1)\n\n\nThe Beagle Java SDK provides convenient access to the Beagle REST API from applications written in Java.\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Beagle MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40corgi-tech%2Fbeagle-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjb3JnaS10ZWNoL2JlYWdsZS1tY3AiXSwiZW52Ijp7IkJFQUdMRV9BUElfS0VZIjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40corgi-tech%2Fbeagle-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40corgi-tech%2Fbeagle-mcp%22%5D%2C%22env%22%3A%7B%22BEAGLE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\nJavadocs are available on [javadoc.io](https://javadoc.io/doc/com.beagle.api/beagle-java/0.0.1).\n\n## Installation\n\n### Gradle\n\n~~~kotlin\nimplementation("com.beagle.api:beagle-java:0.0.1")\n~~~\n\n### Maven\n\n~~~xml\n\n com.beagle.api\n beagle-java\n 0.0.1\n\n~~~\n\n## Requirements\n\nThis library requires Java 8 or later.\n\n## Usage\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nPlanListResponse plans = client.plans().list();\n```\n\n## Client configuration\n\nConfigure the client using system properties or environment variables:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n```\n\nOr manually:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .apiKey("My API Key")\n .build();\n```\n\nOr using a combination of the two approaches:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n // Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n // Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\n .fromEnv()\n .apiKey("My API Key")\n .build();\n```\n\nSee this table for the available options:\n\n| Setter | System property | Environment variable | Required | Default value |\n| --------- | ---------------- | -------------------- | -------- | ------------------------------------- |\n| `apiKey` | `beagle.apiKey` | `BEAGLE_API_KEY` | true | - |\n| `baseUrl` | `beagle.baseUrl` | `BEAGLE_BASE_URL` | true | `"https://developer.beagleforpm.com"` |\n\nSystem properties take precedence over environment variables.\n\n> [!TIP]\n> Don\'t create more than one client in the same application. Each client has a connection pool and\n> thread pools, which are more efficient to share between requests.\n\n### Modifying configuration\n\nTo temporarily use a modified client configuration, while reusing the same connection and thread pools, call `withOptions()` on any client or service:\n\n```java\nimport com.beagle.api.client.BeagleClient;\n\nBeagleClient clientWithOptions = client.withOptions(optionsBuilder -> {\n optionsBuilder.baseUrl("https://example.com");\n optionsBuilder.maxRetries(42);\n});\n```\n\nThe `withOptions()` method does not affect the original client or service.\n\n## Requests and responses\n\nTo send a request to the Beagle API, build an instance of some `Params` class and pass it to the corresponding client method. When the response is received, it will be deserialized into an instance of a Java class.\n\nFor example, `client.plans().list(...)` should be called with an instance of `PlanListParams`, and it will return an instance of `PlanListResponse`.\n\n## Immutability\n\nEach class in the SDK has an associated [builder](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java) or factory method for constructing it.\n\nEach class is [immutable](https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html) once constructed. If the class has an associated builder, then it has a `toBuilder()` method, which can be used to convert it back to a builder for making a modified copy.\n\nBecause each class is immutable, builder modification will _never_ affect already built class instances.\n\n## Asynchronous execution\n\nThe default client is synchronous. To switch to asynchronous execution, call the `async()` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClient client = BeagleOkHttpClient.fromEnv();\n\nCompletableFuture plans = client.async().plans().list();\n```\n\nOr create an asynchronous client from the beginning:\n\n```java\nimport com.beagle.api.client.BeagleClientAsync;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClientAsync;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\nimport java.util.concurrent.CompletableFuture;\n\n// Configures using the `beagle.apiKey` and `beagle.baseUrl` system properties\n// Or configures using the `BEAGLE_API_KEY` and `BEAGLE_BASE_URL` environment variables\nBeagleClientAsync client = BeagleOkHttpClientAsync.fromEnv();\n\nCompletableFuture plans = client.plans().list();\n```\n\nThe asynchronous client supports the same options as the synchronous one, except most methods return `CompletableFuture`s.\n\n\n\n\n\n## Binary responses\n\nThe SDK defines methods that return binary responses, which are used for API responses that shouldn\'t necessarily be parsed, like non-JSON data.\n\nThese methods return [`HttpResponse`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpResponse.kt):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport com.beagle.api.models.enrollments.EnrollmentRetrieveCertificateParams;\n\nHttpResponse response = client.enrollments().retrieveCertificate(123.0);\n```\n\nTo save the response content to a file, use the [`Files.copy(...)`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#copy-java.io.InputStream-java.nio.file.Path-java.nio.file.CopyOption...-) method:\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.nio.file.StandardCopyOption;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n Files.copy(\n response.body(),\n Paths.get(path),\n StandardCopyOption.REPLACE_EXISTING\n );\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\nOr transfer the response content to any [`OutputStream`](https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html):\n\n```java\nimport com.beagle.api.core.http.HttpResponse;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\ntry (HttpResponse response = client.enrollments().retrieveCertificate(params)) {\n response.body().transferTo(Files.newOutputStream(Paths.get(path)));\n} catch (Exception e) {\n System.out.println("Something went wrong!");\n throw new RuntimeException(e);\n}\n```\n\n## Raw responses\n\nThe SDK defines methods that deserialize responses into instances of Java classes. However, these methods don\'t provide access to the response headers, status code, or the raw response body.\n\nTo access this data, prefix any HTTP method call on a client or service with `withRawResponse()`:\n\n```java\nimport com.beagle.api.core.http.Headers;\nimport com.beagle.api.core.http.HttpResponseFor;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanListResponse;\n\nHttpResponseFor plans = client.plans().withRawResponse().list();\n\nint statusCode = plans.statusCode();\nHeaders headers = plans.headers();\n```\n\nYou can still deserialize the response into an instance of a Java class if needed:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse parsedPlans = plans.parse();\n```\n\n## Error handling\n\nThe SDK throws custom unchecked exception types:\n\n- [`BeagleServiceException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleServiceException.kt): Base class for HTTP errors. See this table for which exception subclass is thrown for each HTTP status code:\n\n | Status | Exception |\n | ------ | -------------------------------------------------- |\n | 400 | [`BadRequestException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BadRequestException.kt) |\n | 401 | [`UnauthorizedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnauthorizedException.kt) |\n | 403 | [`PermissionDeniedException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/PermissionDeniedException.kt) |\n | 404 | [`NotFoundException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/NotFoundException.kt) |\n | 422 | [`UnprocessableEntityException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnprocessableEntityException.kt) |\n | 429 | [`RateLimitException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/RateLimitException.kt) |\n | 5xx | [`InternalServerException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/InternalServerException.kt) |\n | others | [`UnexpectedStatusCodeException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/UnexpectedStatusCodeException.kt) |\n\n- [`BeagleIoException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleIoException.kt): I/O networking errors.\n\n- [`BeagleRetryableException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleRetryableException.kt): Generic error indicating a failure that could be retried by the client.\n\n- [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt): Failure to interpret successfully parsed data. For example, when accessing a property that\'s supposed to be required, but the API unexpectedly omitted it from the response.\n\n- [`BeagleException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleException.kt): Base class for all exceptions. Most errors will result in one of the previously mentioned ones, but completely generic errors may be thrown using the base class.\n\n\n\n## Logging\n\nEnable logging by setting the `BEAGLE_LOG` environment variable to `info`:\n\n```sh\nexport BEAGLE_LOG=info\n```\n\nOr to `debug` for more verbose logging:\n\n```sh\nexport BEAGLE_LOG=debug\n```\n\nOr configure the client manually using the `logLevel` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.core.LogLevel;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .logLevel(LogLevel.INFO)\n .build();\n```\n\n## ProGuard and R8\n\nAlthough the SDK uses reflection, it is still usable with [ProGuard](https://github.com/Guardsquare/proguard) and [R8](https://developer.android.com/topic/performance/app-optimization/enable-app-optimization) because `beagle-java-core` is published with a [configuration file](beagle-java-core/src/main/resources/META-INF/proguard/beagle-java-core.pro) containing [keep rules](https://www.guardsquare.com/manual/configuration/usage).\n\nProGuard and R8 should automatically detect and use the published rules, but you can also manually copy the keep rules if necessary.\n\n\n\n\n\n## Jackson\n\nThe SDK depends on [Jackson](https://github.com/FasterXML/jackson) for JSON serialization/deserialization. It is compatible with version 2.13.4 or higher, but depends on version 2.18.2 by default.\n\nThe SDK throws an exception if it detects an incompatible Jackson version at runtime (e.g. if the default version was overridden in your Maven or Gradle config).\n\nIf the SDK threw an exception, but you\'re _certain_ the version is compatible, then disable the version check using the `checkJacksonVersionCompatibility` on [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt).\n\n> [!CAUTION]\n> We make no guarantee that the SDK works correctly when the Jackson version check is disabled.\n\nAlso note that there are bugs in older Jackson versions that can affect the SDK. We don\'t work around all Jackson bugs ([example](https://github.com/FasterXML/jackson-databind/issues/3240)) and expect users to upgrade Jackson for those instead.\n\n## Network options\n\n### Retries\n\nThe SDK automatically retries 2 times by default, with a short exponential backoff between requests.\n\nOnly the following error types are retried:\n- Connection errors (for example, due to a network connectivity problem)\n- 408 Request Timeout\n- 409 Conflict\n- 429 Rate Limit\n- 5xx Internal\n\nThe API may also explicitly instruct the SDK to retry or not retry a request.\n\nTo set a custom number of retries, configure the client using the `maxRetries` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .maxRetries(4)\n .build();\n```\n\n### Timeouts\n\nRequests time out after 1 minute by default.\n\nTo set a custom timeout, configure the method call using the `timeout` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().timeout(Duration.ofSeconds(30)).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .timeout(Duration.ofSeconds(30))\n .build();\n```\n\n### Proxies\n\nTo route requests through a proxy, configure the client using the `proxy` method:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.net.InetSocketAddress;\nimport java.net.Proxy;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .proxy(new Proxy(\n Proxy.Type.HTTP, new InetSocketAddress(\n "https://example.com", 8080\n )\n ))\n .build();\n```\n\nIf the proxy responds with `407 Proxy Authentication Required`, supply credentials by also configuring `proxyAuthenticator`:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport com.beagle.api.core.http.ProxyAuthenticator;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .proxy(...)\n // Or a custom implementation of `ProxyAuthenticator`.\n .proxyAuthenticator(ProxyAuthenticator.basic("username", "password"))\n .build();\n```\n\n### Connection pooling\n\nTo customize the underlying OkHttp connection pool, configure the client using the `maxIdleConnections` and `keepAliveDuration` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\nimport java.time.Duration;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `maxIdleConnections` is set, then `keepAliveDuration` must be set, and vice versa.\n .maxIdleConnections(10)\n .keepAliveDuration(Duration.ofMinutes(2))\n .build();\n```\n\nIf both options are unset, OkHttp\'s default connection pool settings are used.\n\n### HTTPS\n\n> [!NOTE]\n> Most applications should not call these methods, and instead use the system defaults. The defaults include\n> special optimizations that can be lost if the implementations are modified.\n\nTo configure how HTTPS connections are secured, configure the client using the `sslSocketFactory`, `trustManager`, and `hostnameVerifier` methods:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n // If `sslSocketFactory` is set, then `trustManager` must be set, and vice versa.\n .sslSocketFactory(yourSSLSocketFactory)\n .trustManager(yourTrustManager)\n .hostnameVerifier(yourHostnameVerifier)\n .build();\n```\n\n### Environments\n\nThe SDK sends requests to the production by default. To send requests to a different environment, configure the client like so:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .staging()\n .build();\n```\n\n### Custom HTTP client\n\nThe SDK consists of three artifacts:\n- `beagle-java-core`\n - Contains core SDK logic\n - Does not depend on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleClient`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClient.kt), [`BeagleClientAsync`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsync.kt), [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt), and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), all of which can work with any HTTP client\n- `beagle-java-client-okhttp`\n - Depends on [OkHttp](https://square.github.io/okhttp)\n - Exposes [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) and [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), which provide a way to construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) and [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), respectively, using OkHttp\n- `beagle-java`\n - Depends on and exposes the APIs of both `beagle-java-core` and `beagle-java-client-okhttp`\n - Does not have its own logic\n\nThis structure allows replacing the SDK\'s default HTTP client without pulling in unnecessary dependencies.\n\n#### Customized [`OkHttpClient`](https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.html)\n\n> [!TIP]\n> Try the available [network options](#network-options) before replacing the default client.\n\nTo use a customized `OkHttpClient`:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Copy `beagle-java-client-okhttp`\'s [`OkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/OkHttpClient.kt) class into your code and customize it\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your customized client\n\n### Completely custom HTTP client\n\nTo use a completely custom HTTP client:\n\n1. Replace your [`beagle-java` dependency](#installation) with `beagle-java-core`\n2. Write a class that implements the [`HttpClient`](beagle-java-core/src/main/kotlin/com/beagle/api/core/http/HttpClient.kt) interface\n3. Construct [`BeagleClientImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientImpl.kt) or [`BeagleClientAsyncImpl`](beagle-java-core/src/main/kotlin/com/beagle/api/client/BeagleClientAsyncImpl.kt), similarly to [`BeagleOkHttpClient`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClient.kt) or [`BeagleOkHttpClientAsync`](beagle-java-client-okhttp/src/main/kotlin/com/beagle/api/client/okhttp/BeagleOkHttpClientAsync.kt), using your new client class\n\n## Undocumented API functionality\n\nThe SDK is typed for convenient usage of the documented API. However, it also supports working with undocumented or not yet supported parts of the API.\n\n### Parameters\n\nTo set undocumented parameters, call the `putAdditionalHeader`, `putAdditionalQueryParam`, or `putAdditionalBodyProperty` methods on any `Params` class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder()\n .putAdditionalHeader("Secret-Header", "42")\n .putAdditionalQueryParam("secret_query_param", "42")\n .putAdditionalBodyProperty("secretProperty", JsonValue.from("42"))\n .build();\n```\n\nThese can be accessed on the built object later using the `_additionalHeaders()`, `_additionalQueryParams()`, and `_additionalBodyProperties()` methods.\n\nTo set undocumented parameters on _nested_ headers, query params, or body classes, call the `putAdditionalProperty` method on the nested class:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport com.beagle.api.models.tenants.Address;\nimport com.beagle.api.models.tenants.TenantCreateParams;\n\nTenantCreateParams params = TenantCreateParams.builder()\n .address(Address.builder()\n .putAdditionalProperty("secretProperty", JsonValue.from("42"))\n .build())\n .build();\n```\n\nThese properties can be accessed on the nested built object later using the `_additionalProperties()` method.\n\nTo set a documented parameter or property to an undocumented or not yet supported _value_, pass a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) object to its setter:\n\n```java\nimport com.beagle.api.models.plans.PlanListParams;\n\nPlanListParams params = PlanListParams.builder().build();\n```\n\nThe most straightforward way to create a [`JsonValue`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt) is using its `from(...)` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.List;\nimport java.util.Map;\n\n// Create primitive JSON values\nJsonValue nullValue = JsonValue.from(null);\nJsonValue booleanValue = JsonValue.from(true);\nJsonValue numberValue = JsonValue.from(42);\nJsonValue stringValue = JsonValue.from("Hello World!");\n\n// Create a JSON array value equivalent to `["Hello", "World"]`\nJsonValue arrayValue = JsonValue.from(List.of(\n "Hello", "World"\n));\n\n// Create a JSON object value equivalent to `{ "a": 1, "b": 2 }`\nJsonValue objectValue = JsonValue.from(Map.of(\n "a", 1,\n "b", 2\n));\n\n// Create an arbitrarily nested JSON equivalent to:\n// {\n// "a": [1, 2],\n// "b": [3, 4]\n// }\nJsonValue complexValue = JsonValue.from(Map.of(\n "a", List.of(\n 1, 2\n ),\n "b", List.of(\n 3, 4\n )\n));\n```\n\nNormally a `Builder` class\'s `build` method will throw [`IllegalStateException`](https://docs.oracle.com/javase/8/docs/api/java/lang/IllegalStateException.html) if any required parameter or property is unset.\n\nTo forcibly omit a required parameter or property, pass [`JsonMissing`](beagle-java-core/src/main/kotlin/com/beagle/api/core/Values.kt):\n\n```java\nimport com.beagle.api.core.JsonMissing;\nimport com.beagle.api.models.plans.PlanListParams;\nimport com.beagle.api.models.plans.PlanRetrieveParams;\n\nPlanListParams params = PlanRetrieveParams.builder()\n .code(JsonMissing.of())\n .build();\n```\n\n### Response properties\n\nTo access undocumented response properties, call the `_additionalProperties()` method:\n\n```java\nimport com.beagle.api.core.JsonValue;\nimport java.util.Map;\n\nMap additionalProperties = client.plans().list(params)._additionalProperties();\nJsonValue secretPropertyValue = additionalProperties.get("secretProperty");\n\nString result = secretPropertyValue.accept(new JsonValue.Visitor<>() {\n @Override\n public String visitNull() {\n return "It\'s null!";\n }\n\n @Override\n public String visitBoolean(boolean value) {\n return "It\'s a boolean!";\n }\n\n @Override\n public String visitNumber(Number value) {\n return "It\'s a number!";\n }\n\n // Other methods include `visitMissing`, `visitString`, `visitArray`, and `visitObject`\n // The default implementation of each unimplemented method delegates to `visitDefault`, which throws by default, but can also be overridden\n});\n```\n\nTo access a property\'s raw JSON value, which may be undocumented, call its `_` prefixed method:\n\n```java\nimport com.beagle.api.core.JsonField;\nimport java.util.Optional;\n\nJsonField field = client.plans().list(params)._field();\n\nif (field.isMissing()) {\n // The property is absent from the JSON response\n} else if (field.isNull()) {\n // The property was set to literal null\n} else {\n // Check if value was provided as a string\n // Other methods include `asNumber()`, `asBoolean()`, etc.\n Optional jsonString = field.asString();\n\n // Try to deserialize into a custom type\n MyClass myObject = field.asUnknown().orElseThrow().convert(MyClass.class);\n}\n```\n\n### Response validation\n\nIn rare cases, the API may return a response that doesn\'t match the expected type. For example, the SDK may expect a property to contain a `String`, but the API could return something else.\n\nBy default, the SDK will not throw an exception in this case. It will throw [`BeagleInvalidDataException`](beagle-java-core/src/main/kotlin/com/beagle/api/errors/BeagleInvalidDataException.kt) only if you directly access the property.\n\nValidating the response is _not_ forwards compatible with new types from the API for existing fields.\n\nIf you would still prefer to check that the response is completely well-typed upfront, then either call `validate()`:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(params).validate();\n```\n\nOr configure the method call to validate the response using the `responseValidation` method:\n\n```java\nimport com.beagle.api.models.plans.PlanListResponse;\n\nPlanListResponse plans = client.plans().list(RequestOptions.builder().responseValidation(true).build());\n```\n\nOr configure the default for all method calls at the client level:\n\n```java\nimport com.beagle.api.client.BeagleClient;\nimport com.beagle.api.client.okhttp.BeagleOkHttpClient;\n\nBeagleClient client = BeagleOkHttpClient.builder()\n .fromEnv()\n .responseValidation(true)\n .build();\n```\n\n## FAQ\n\n### Why don\'t you use plain `enum` classes?\n\nJava `enum` classes are not trivially [forwards compatible](https://www.stainless.com/blog/making-java-enums-forwards-compatible). Using them in the SDK could cause runtime exceptions if the API is updated to respond with a new enum value.\n\n### Why do you represent fields using `JsonField` instead of just plain `T`?\n\nUsing `JsonField` enables a few features:\n\n- Allowing usage of [undocumented API functionality](#undocumented-api-functionality)\n- Lazily [validating the API response against the expected shape](#response-validation)\n- Representing absent vs explicitly null values\n\n### Why don\'t you use [`data` classes](https://kotlinlang.org/docs/data-classes.html)?\n\nIt is not [backwards compatible to add new fields to a data class](https://kotlinlang.org/docs/api-guidelines-backward-compatibility.html#avoid-using-data-classes-in-your-api) and we don\'t want to introduce a breaking change every time we add a field to a class.\n\n### Why don\'t you use checked exceptions?\n\nChecked exceptions are widely considered a mistake in the Java programming language. In fact, they were omitted from Kotlin for this reason.\n\nChecked exceptions:\n\n- Are verbose to handle\n- Encourage error handling at the wrong level of abstraction, where nothing can be done about the error\n- Are tedious to propagate due to the [function coloring problem](https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function)\n- Don\'t play well with lambdas (also due to the function coloring problem)\n\n## Semantic versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n2. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/beagle-java/issues) with questions, bugs, or suggestions.\n', }, { language: 'python', diff --git a/src/internal/utils/log.ts b/src/internal/utils/log.ts index a0504019..dec09bfd 100644 --- a/src/internal/utils/log.ts +++ b/src/internal/utils/log.ts @@ -106,8 +106,9 @@ export const formatRequestDetails = (details: { ([name, value]) => [ name, ( - name.toLowerCase() === 'x-api-key' || name.toLowerCase() === 'authorization' || + name.toLowerCase() === 'api-key' || + name.toLowerCase() === 'x-api-key' || name.toLowerCase() === 'cookie' || name.toLowerCase() === 'set-cookie' ) ? From 6f0df5be92a58371b17915bc82e305e5be5f5cc6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 8 May 2026 15:18:45 +0000 Subject: [PATCH 128/138] feat(api): api update --- .stats.yml | 4 ++-- packages/mcp-server/src/local-docs-search.ts | 4 ++-- src/resources/tenants.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1457043a..09378062 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 18 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi/beagle-5ef40a5ea9b4d33997789e58615360e74266ad5b01dc77bb39e9d3850aedd861.yml -openapi_spec_hash: 7fdd09563daf05b0efbdd74f2bd391d1 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi/beagle-e08c879c5f5edd4d9850efeda59ff99203cacc3878a94fe83444ee68ddc7729a.yml +openapi_spec_hash: 448f9f08294d3a084630d77365ee6401 config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 19d2b653..5d9df04a 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -473,7 +473,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ ], response: '{ data: { id: number; address: address; contact: contact; }; success: true; }', markdown: - "## update\n\n`client.tenants.update(id: number, address?: { city: string; state: string; street1: string; zip: string; street2?: string; }, contact?: { email: string; name: object; phone?: string; }): { data: tenant; success: true; }`\n\n**patch** `/api/tenants/{id}`\n\nupdate an existing tenant by their id.\n\n### Parameters\n\n- `id: number`\n\n- `address?: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `city: string`\n - `state: string`\n two letter state code, ie CA\n - `street1: string`\n - `zip: string`\n 5 digit US zip code, ie 94104\n - `street2?: string`\n\n- `contact?: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `email: string`\n - `name: { first: string; last: string; }`\n - `phone?: string`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.update(123);\n\nconsole.log(tenant);\n```", + "## update\n\n`client.tenants.update(id: number, address?: { city: string; state: string; street1: string; zip: string; street2?: string; }, contact?: { email: string; name: object; phone?: string; }): { data: tenant; success: true; }`\n\n**patch** `/api/tenants/{id}`\n\nupdate an existing tenant by their id.\n\n### Parameters\n\n- `id: number`\n\n- `address?: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `city: string`\n - `state: string`\n two letter state code, ie CA\n - `street1: string`\n - `zip: string`\n US ZIP or ZIP+4. For example: '94104' or '94104-1234'\n - `street2?: string`\n\n- `contact?: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `email: string`\n - `name: { first: string; last: string; }`\n - `phone?: string`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.update(123);\n\nconsole.log(tenant);\n```", perLanguage: { typescript: { method: 'client.tenants.update', @@ -623,7 +623,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ ], response: '{ data: { id: number; address: address; contact: contact; }; success: true; }', markdown: - "## create\n\n`client.tenants.create(address: { city: string; state: string; street1: string; zip: string; street2?: string; }, contact: { email: string; name: object; phone?: string; }, propertyManagerId: number): { data: tenant; success: true; }`\n\n**post** `/api/tenants`\n\ncreate a new tenant.\n\n### Parameters\n\n- `address: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `city: string`\n - `state: string`\n two letter state code, ie CA\n - `street1: string`\n - `zip: string`\n 5 digit US zip code, ie 94104\n - `street2?: string`\n\n- `contact: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `email: string`\n - `name: { first: string; last: string; }`\n - `phone?: string`\n\n- `propertyManagerId: number`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.create({\n address: {\n city: 'South Salt Lake',\n state: 'UT',\n street1: '123 Main St.',\n zip: '84115',\n},\n contact: {\n email: 'mark.s@example.com',\n name: { first: 'Mark', last: 'Scout' },\n},\n propertyManagerId: 123,\n});\n\nconsole.log(tenant);\n```", + "## create\n\n`client.tenants.create(address: { city: string; state: string; street1: string; zip: string; street2?: string; }, contact: { email: string; name: object; phone?: string; }, propertyManagerId: number): { data: tenant; success: true; }`\n\n**post** `/api/tenants`\n\ncreate a new tenant.\n\n### Parameters\n\n- `address: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `city: string`\n - `state: string`\n two letter state code, ie CA\n - `street1: string`\n - `zip: string`\n US ZIP or ZIP+4. For example: '94104' or '94104-1234'\n - `street2?: string`\n\n- `contact: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `email: string`\n - `name: { first: string; last: string; }`\n - `phone?: string`\n\n- `propertyManagerId: number`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.create({\n address: {\n city: 'South Salt Lake',\n state: 'UT',\n street1: '123 Main St.',\n zip: '84115',\n},\n contact: {\n email: 'mark.s@example.com',\n name: { first: 'Mark', last: 'Scout' },\n},\n propertyManagerId: 123,\n});\n\nconsole.log(tenant);\n```", perLanguage: { typescript: { method: 'client.tenants.create', diff --git a/src/resources/tenants.ts b/src/resources/tenants.ts index a2474581..ced09b7c 100644 --- a/src/resources/tenants.ts +++ b/src/resources/tenants.ts @@ -103,7 +103,7 @@ export interface Address { street1: string; /** - * 5 digit US zip code, ie 94104 + * US ZIP or ZIP+4. For example: '94104' or '94104-1234' */ zip: string; From fec1f3c507df6780b0e93d6ff07310f383b533e6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 8 May 2026 16:18:44 +0000 Subject: [PATCH 129/138] feat(api): api update --- .stats.yml | 4 +- packages/mcp-server/src/local-docs-search.ts | 43 +++++++++++++------- src/resources/enrollments.ts | 13 ++++++ src/resources/tenants.ts | 12 ++++++ tests/api-resources/enrollments.test.ts | 20 +++++++++ tests/api-resources/tenants.test.ts | 2 + 6 files changed, 78 insertions(+), 16 deletions(-) diff --git a/.stats.yml b/.stats.yml index 09378062..9b71a0fe 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 18 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi/beagle-e08c879c5f5edd4d9850efeda59ff99203cacc3878a94fe83444ee68ddc7729a.yml -openapi_spec_hash: 448f9f08294d3a084630d77365ee6401 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi/beagle-54871bab8d880e5f2d06830c746eb892f76a26d39b80311e65abb0196fddbbbc.yml +openapi_spec_hash: f9bab149d06098f3371751141879c9de config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 5d9df04a..56b9668d 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -418,9 +418,10 @@ const EMBEDDED_METHODS: MethodEntry[] = [ stainlessPath: '(resource) tenants > (method) retrieve', qualified: 'client.tenants.retrieve', params: ['id: number;'], - response: '{ data: { id: number; address: address; contact: contact; }; success: true; }', + response: + '{ data: { id: number; address: address; contact: contact; expectedMoveInDate?: string; expectedMoveOutDate?: string; }; success: true; }', markdown: - "## retrieve\n\n`client.tenants.retrieve(id: number): { data: tenant; success: true; }`\n\n**get** `/api/tenants/{id}`\n\nretrieve a single tenant by their id.\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.retrieve(123);\n\nconsole.log(tenant);\n```", + "## retrieve\n\n`client.tenants.retrieve(id: number): { data: tenant; success: true; }`\n\n**get** `/api/tenants/{id}`\n\nretrieve a single tenant by their id.\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; expectedMoveInDate?: string; expectedMoveOutDate?: string; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; expectedMoveInDate?: string; expectedMoveOutDate?: string; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.retrieve(123);\n\nconsole.log(tenant);\n```", perLanguage: { typescript: { method: 'client.tenants.retrieve', @@ -470,10 +471,13 @@ const EMBEDDED_METHODS: MethodEntry[] = [ 'id: number;', 'address?: { city: string; state: string; street1: string; zip: string; street2?: string; };', 'contact?: { email: string; name: { first: string; last: string; }; phone?: string; };', + 'expectedMoveInDate?: string;', + 'expectedMoveOutDate?: string;', ], - response: '{ data: { id: number; address: address; contact: contact; }; success: true; }', + response: + '{ data: { id: number; address: address; contact: contact; expectedMoveInDate?: string; expectedMoveOutDate?: string; }; success: true; }', markdown: - "## update\n\n`client.tenants.update(id: number, address?: { city: string; state: string; street1: string; zip: string; street2?: string; }, contact?: { email: string; name: object; phone?: string; }): { data: tenant; success: true; }`\n\n**patch** `/api/tenants/{id}`\n\nupdate an existing tenant by their id.\n\n### Parameters\n\n- `id: number`\n\n- `address?: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `city: string`\n - `state: string`\n two letter state code, ie CA\n - `street1: string`\n - `zip: string`\n US ZIP or ZIP+4. For example: '94104' or '94104-1234'\n - `street2?: string`\n\n- `contact?: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `email: string`\n - `name: { first: string; last: string; }`\n - `phone?: string`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.update(123);\n\nconsole.log(tenant);\n```", + "## update\n\n`client.tenants.update(id: number, address?: { city: string; state: string; street1: string; zip: string; street2?: string; }, contact?: { email: string; name: object; phone?: string; }, expectedMoveInDate?: string, expectedMoveOutDate?: string): { data: tenant; success: true; }`\n\n**patch** `/api/tenants/{id}`\n\nupdate an existing tenant by their id.\n\n### Parameters\n\n- `id: number`\n\n- `address?: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `city: string`\n - `state: string`\n two letter state code, ie CA\n - `street1: string`\n - `zip: string`\n US ZIP or ZIP+4. For example: '94104' or '94104-1234'\n - `street2?: string`\n\n- `contact?: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `email: string`\n - `name: { first: string; last: string; }`\n - `phone?: string`\n\n- `expectedMoveInDate?: string`\n\n- `expectedMoveOutDate?: string`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; expectedMoveInDate?: string; expectedMoveOutDate?: string; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; expectedMoveInDate?: string; expectedMoveOutDate?: string; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.update(123);\n\nconsole.log(tenant);\n```", perLanguage: { typescript: { method: 'client.tenants.update', @@ -571,7 +575,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ params: ['page?: number;', 'propertyManagerId?: number;', 'size?: number;'], response: '{ data: { items: object[]; pagination: object; }; success: true; }', markdown: - "## list\n\n`client.tenants.list(page?: number, propertyManagerId?: number, size?: number): { data: object; success: true; }`\n\n**get** `/api/tenants`\n\nlist all tenants, this endpoint is paginated and allows for queries by individual property manager.\n\n### Parameters\n\n- `page?: number`\n Page number to fetch.\n\n- `propertyManagerId?: number`\n\n- `size?: number`\n Number of items per page.\n\n### Returns\n\n- `{ data: { items: object[]; pagination: object; }; success: true; }`\n\n - `data: { items: { id: number; address: object; contact: object; }[]; pagination: { page: number; pages: number; records: number; size: number; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenants = await client.tenants.list();\n\nconsole.log(tenants);\n```", + "## list\n\n`client.tenants.list(page?: number, propertyManagerId?: number, size?: number): { data: object; success: true; }`\n\n**get** `/api/tenants`\n\nlist all tenants, this endpoint is paginated and allows for queries by individual property manager.\n\n### Parameters\n\n- `page?: number`\n Page number to fetch.\n\n- `propertyManagerId?: number`\n\n- `size?: number`\n Number of items per page.\n\n### Returns\n\n- `{ data: { items: object[]; pagination: object; }; success: true; }`\n\n - `data: { items: { id: number; address: object; contact: object; expectedMoveInDate?: string; expectedMoveOutDate?: string; }[]; pagination: { page: number; pages: number; records: number; size: number; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenants = await client.tenants.list();\n\nconsole.log(tenants);\n```", perLanguage: { typescript: { method: 'client.tenants.list', @@ -620,10 +624,13 @@ const EMBEDDED_METHODS: MethodEntry[] = [ 'address: { city: string; state: string; street1: string; zip: string; street2?: string; };', 'contact: { email: string; name: { first: string; last: string; }; phone?: string; };', 'propertyManagerId: number;', + 'expectedMoveInDate?: string;', + 'expectedMoveOutDate?: string;', ], - response: '{ data: { id: number; address: address; contact: contact; }; success: true; }', + response: + '{ data: { id: number; address: address; contact: contact; expectedMoveInDate?: string; expectedMoveOutDate?: string; }; success: true; }', markdown: - "## create\n\n`client.tenants.create(address: { city: string; state: string; street1: string; zip: string; street2?: string; }, contact: { email: string; name: object; phone?: string; }, propertyManagerId: number): { data: tenant; success: true; }`\n\n**post** `/api/tenants`\n\ncreate a new tenant.\n\n### Parameters\n\n- `address: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `city: string`\n - `state: string`\n two letter state code, ie CA\n - `street1: string`\n - `zip: string`\n US ZIP or ZIP+4. For example: '94104' or '94104-1234'\n - `street2?: string`\n\n- `contact: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `email: string`\n - `name: { first: string; last: string; }`\n - `phone?: string`\n\n- `propertyManagerId: number`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.create({\n address: {\n city: 'South Salt Lake',\n state: 'UT',\n street1: '123 Main St.',\n zip: '84115',\n},\n contact: {\n email: 'mark.s@example.com',\n name: { first: 'Mark', last: 'Scout' },\n},\n propertyManagerId: 123,\n});\n\nconsole.log(tenant);\n```", + "## create\n\n`client.tenants.create(address: { city: string; state: string; street1: string; zip: string; street2?: string; }, contact: { email: string; name: object; phone?: string; }, propertyManagerId: number, expectedMoveInDate?: string, expectedMoveOutDate?: string): { data: tenant; success: true; }`\n\n**post** `/api/tenants`\n\ncreate a new tenant.\n\n### Parameters\n\n- `address: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `city: string`\n - `state: string`\n two letter state code, ie CA\n - `street1: string`\n - `zip: string`\n US ZIP or ZIP+4. For example: '94104' or '94104-1234'\n - `street2?: string`\n\n- `contact: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `email: string`\n - `name: { first: string; last: string; }`\n - `phone?: string`\n\n- `propertyManagerId: number`\n\n- `expectedMoveInDate?: string`\n\n- `expectedMoveOutDate?: string`\n\n### Returns\n\n- `{ data: { id: number; address: address; contact: contact; expectedMoveInDate?: string; expectedMoveOutDate?: string; }; success: true; }`\n\n - `data: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; expectedMoveInDate?: string; expectedMoveOutDate?: string; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst tenant = await client.tenants.create({\n address: {\n city: 'South Salt Lake',\n state: 'UT',\n street1: '123 Main St.',\n zip: '84115',\n},\n contact: {\n email: 'mark.s@example.com',\n name: { first: 'Mark', last: 'Scout' },\n},\n propertyManagerId: 123,\n});\n\nconsole.log(tenant);\n```", perLanguage: { typescript: { method: 'client.tenants.create', @@ -671,9 +678,9 @@ const EMBEDDED_METHODS: MethodEntry[] = [ qualified: 'client.enrollments.retrieve', params: ['id: number;'], response: - '{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }', + '{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; product?: string; tenant?: tenant; }; success: true; }', markdown: - "## retrieve\n\n`client.enrollments.retrieve(id: number): { data: enrollment; success: true; }`\n\n**get** `/api/enrollments/{id}`\n\nget a specific enrollment by its id.\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }`\n\n - `data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollment = await client.enrollments.retrieve(123);\n\nconsole.log(enrollment);\n```", + "## retrieve\n\n`client.enrollments.retrieve(id: number): { data: enrollment; success: true; }`\n\n**get** `/api/enrollments/{id}`\n\nget a specific enrollment by its id.\n\n### Parameters\n\n- `id: number`\n\n### Returns\n\n- `{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; product?: string; tenant?: tenant; }; success: true; }`\n\n - `data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; product?: string; tenant?: { id: number; address: address; contact: contact; expectedMoveInDate?: string; expectedMoveOutDate?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollment = await client.enrollments.retrieve(123);\n\nconsole.log(enrollment);\n```", perLanguage: { typescript: { method: 'client.enrollments.retrieve', @@ -769,10 +776,16 @@ const EMBEDDED_METHODS: MethodEntry[] = [ 'list all enrollments, this endpoint is paginated and allows for queries by individual property manager.', stainlessPath: '(resource) enrollments > (method) list', qualified: 'client.enrollments.list', - params: ['page?: number;', 'propertyManagerId?: number;', 'size?: number;'], + params: [ + 'page?: number;', + 'product?: string;', + 'propertyManagerId?: number;', + 'size?: number;', + 'status?: string;', + ], response: '{ data: { items: object[]; pagination: object; }; success: true; }', markdown: - "## list\n\n`client.enrollments.list(page?: number, propertyManagerId?: number, size?: number): { data: object; success: true; }`\n\n**get** `/api/enrollments`\n\nlist all enrollments, this endpoint is paginated and allows for queries by individual property manager.\n\n### Parameters\n\n- `page?: number`\n Page number to fetch.\n\n- `propertyManagerId?: number`\n\n- `size?: number`\n Number of items per page.\n\n### Returns\n\n- `{ data: { items: object[]; pagination: object; }; success: true; }`\n\n - `data: { items: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }[]; pagination: { page: number; pages: number; records: number; size: number; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollments = await client.enrollments.list();\n\nconsole.log(enrollments);\n```", + "## list\n\n`client.enrollments.list(page?: number, product?: string, propertyManagerId?: number, size?: number, status?: string): { data: object; success: true; }`\n\n**get** `/api/enrollments`\n\nlist all enrollments, this endpoint is paginated and allows for queries by individual property manager.\n\n### Parameters\n\n- `page?: number`\n Page number to fetch.\n\n- `product?: string`\n\n- `propertyManagerId?: number`\n\n- `size?: number`\n Number of items per page.\n\n- `status?: string`\n\n### Returns\n\n- `{ data: { items: object[]; pagination: object; }; success: true; }`\n\n - `data: { items: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; product?: string; tenant?: object; }[]; pagination: { page: number; pages: number; records: number; size: number; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollments = await client.enrollments.list();\n\nconsole.log(enrollments);\n```", perLanguage: { typescript: { method: 'client.enrollments.list', @@ -824,12 +837,14 @@ const EMBEDDED_METHODS: MethodEntry[] = [ 'propertyManagerId: number;', 'tenantId: number;', 'note?: string;', + 'product?: string;', "status?: 'Premium Paying' | 'Issued, Not Paid';", + 'tenant?: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; expectedMoveInDate?: string; expectedMoveOutDate?: string; };', ], response: - '{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }', + '{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; product?: string; tenant?: tenant; }; success: true; }', markdown: - "## create\n\n`client.enrollments.create(effectiveDate: string, plan: string, propertyManagerId: number, tenantId: number, note?: string, status?: 'Premium Paying' | 'Issued, Not Paid'): { data: enrollment; success: true; }`\n\n**post** `/api/enrollments`\n\ncreate a new enrollment for a tenant.\n\n### Parameters\n\n- `effectiveDate: string`\n the date the enrollment will begin, note enrollments cannot begin in the past\n\n- `plan: string`\n the plan name/code\n\n- `propertyManagerId: number`\n\n- `tenantId: number`\n\n- `note?: string`\n an optional note field, this can be used for easily appending metadata to enrollments\n\n- `status?: 'Premium Paying' | 'Issued, Not Paid'`\n the enrollment status — defaults to 'Issued, Not Paid' if not provided\n\n### Returns\n\n- `{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }; success: true; }`\n\n - `data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollment = await client.enrollments.create({\n effectiveDate: '2025-11-10T19:50:20.638Z',\n plan: 'TLL_100K_CONTENTS_5K_ACV',\n propertyManagerId: 123,\n tenantId: 123,\n});\n\nconsole.log(enrollment);\n```", + "## create\n\n`client.enrollments.create(effectiveDate: string, plan: string, propertyManagerId: number, tenantId: number, note?: string, product?: string, status?: 'Premium Paying' | 'Issued, Not Paid', tenant?: { id: number; address: address; contact: contact; expectedMoveInDate?: string; expectedMoveOutDate?: string; }): { data: enrollment; success: true; }`\n\n**post** `/api/enrollments`\n\ncreate a new enrollment for a tenant.\n\n### Parameters\n\n- `effectiveDate: string`\n the date the enrollment will begin, note enrollments cannot begin in the past\n\n- `plan: string`\n the plan name/code\n\n- `propertyManagerId: number`\n\n- `tenantId: number`\n\n- `note?: string`\n an optional note field, this can be used for easily appending metadata to enrollments\n\n- `product?: string`\n\n- `status?: 'Premium Paying' | 'Issued, Not Paid'`\n the enrollment status — defaults to 'Issued, Not Paid' if not provided\n\n- `tenant?: { id: number; address: { city: string; state: string; street1: string; zip: string; street2?: string; }; contact: { email: string; name: object; phone?: string; }; expectedMoveInDate?: string; expectedMoveOutDate?: string; }`\n - `id: number`\n - `address: { city: string; state: string; street1: string; zip: string; street2?: string; }`\n - `contact: { email: string; name: { first: string; last: string; }; phone?: string; }`\n - `expectedMoveInDate?: string`\n - `expectedMoveOutDate?: string`\n\n### Returns\n\n- `{ data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; product?: string; tenant?: tenant; }; success: true; }`\n\n - `data: { id: number; effectiveDate: string; plan: string; propertyManagerId: number; status: string; tenantId: number; note?: string; product?: string; tenant?: { id: number; address: address; contact: contact; expectedMoveInDate?: string; expectedMoveOutDate?: string; }; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst enrollment = await client.enrollments.create({\n effectiveDate: '2025-11-10T19:50:20.638Z',\n plan: 'TLL_100K_CONTENTS_5K_ACV',\n propertyManagerId: 123,\n tenantId: 123,\n});\n\nconsole.log(enrollment);\n```", perLanguage: { typescript: { method: 'client.enrollments.create', @@ -863,7 +878,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, http: { example: - 'curl https://developer.beagleforpm.com/api/enrollments \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "effectiveDate": "2025-11-10T19:50:20.638Z",\n "plan": "TLL_100K_CONTENTS_5K_ACV",\n "propertyManagerId": 123,\n "tenantId": 123,\n "status": "Issued, Not Paid"\n }\'', + 'curl https://developer.beagleforpm.com/api/enrollments \\\n -H \'Content-Type: application/json\' \\\n -H "x-api-key: $BEAGLE_API_KEY" \\\n -d \'{\n "effectiveDate": "2025-11-10T19:50:20.638Z",\n "plan": "TLL_100K_CONTENTS_5K_ACV",\n "propertyManagerId": 123,\n "tenantId": 123,\n "status": "Issued, Not Paid",\n "tenant": {\n "id": 123,\n "address": {\n "city": "South Salt Lake",\n "state": "UT",\n "street1": "123 Main St.",\n "zip": "84115",\n "street2": "Unit 3"\n },\n "contact": {\n "email": "mark.s@example.com",\n "name": {\n "first": "Mark",\n "last": "Scout"\n },\n "phone": "(123) 456-7890"\n }\n }\n }\'', }, }, }, diff --git a/src/resources/enrollments.ts b/src/resources/enrollments.ts index 36347447..510846d4 100644 --- a/src/resources/enrollments.ts +++ b/src/resources/enrollments.ts @@ -3,6 +3,7 @@ import { APIResource } from '../core/resource'; import * as EnrollmentsAPI from './enrollments'; import * as PropertyManagersAPI from './property-managers'; +import * as TenantsAPI from './tenants'; import { APIPromise } from '../core/api-promise'; import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; @@ -126,6 +127,10 @@ export interface Enrollment { * enrollments */ note?: string; + + product?: string; + + tenant?: TenantsAPI.Tenant; } export interface EnrollmentCreateResponse { @@ -175,10 +180,14 @@ export interface EnrollmentCreateParams { */ note?: string; + product?: string; + /** * the enrollment status — defaults to 'Issued, Not Paid' if not provided */ status?: 'Premium Paying' | 'Issued, Not Paid'; + + tenant?: TenantsAPI.Tenant; } export interface EnrollmentListParams { @@ -187,12 +196,16 @@ export interface EnrollmentListParams { */ page?: number; + product?: string | null; + propertyManagerId?: number; /** * Number of items per page. */ size?: number; + + status?: string | null; } export declare namespace Enrollments { diff --git a/src/resources/tenants.ts b/src/resources/tenants.ts index ced09b7c..7a93fedd 100644 --- a/src/resources/tenants.ts +++ b/src/resources/tenants.ts @@ -132,6 +132,10 @@ export interface Tenant { address: Address; contact: Contact; + + expectedMoveInDate?: string; + + expectedMoveOutDate?: string; } export interface TenantCreateResponse { @@ -172,12 +176,20 @@ export interface TenantCreateParams { contact: Contact; propertyManagerId: number; + + expectedMoveInDate?: string; + + expectedMoveOutDate?: string; } export interface TenantUpdateParams { address?: Address; contact?: Contact; + + expectedMoveInDate?: string; + + expectedMoveOutDate?: string; } export interface TenantListParams { diff --git a/tests/api-resources/enrollments.test.ts b/tests/api-resources/enrollments.test.ts index 53221226..8f1c3416 100644 --- a/tests/api-resources/enrollments.test.ts +++ b/tests/api-resources/enrollments.test.ts @@ -33,7 +33,25 @@ describe('resource enrollments', () => { propertyManagerId: 123, tenantId: 123, note: 'note', + product: 'product', status: 'Issued, Not Paid', + tenant: { + id: 123, + address: { + city: 'South Salt Lake', + state: 'UT', + street1: '123 Main St.', + zip: '84115', + street2: 'Unit 3', + }, + contact: { + email: 'mark.s@example.com', + name: { first: 'Mark', last: 'Scout' }, + phone: '(123) 456-7890', + }, + expectedMoveInDate: 'expectedMoveInDate', + expectedMoveOutDate: 'expectedMoveOutDate', + }, }); }); @@ -68,8 +86,10 @@ describe('resource enrollments', () => { client.enrollments.list( { page: 1, + product: 'product', propertyManagerId: 1, size: 1, + status: 'status', }, { path: '/_stainless_unknown_path' }, ), diff --git a/tests/api-resources/tenants.test.ts b/tests/api-resources/tenants.test.ts index cd73890a..814892f6 100644 --- a/tests/api-resources/tenants.test.ts +++ b/tests/api-resources/tenants.test.ts @@ -48,6 +48,8 @@ describe('resource tenants', () => { phone: '(123) 456-7890', }, propertyManagerId: 123, + expectedMoveInDate: 'expectedMoveInDate', + expectedMoveOutDate: 'expectedMoveOutDate', }); }); From d49d7e5e4a552e90b6b3c14788a8ca6dea09c004 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 02:35:39 +0000 Subject: [PATCH 130/138] chore(internal): codegen related update --- .github/workflows/ci.yml | 14 +++++++------- .github/workflows/publish-npm.yml | 4 ++-- .github/workflows/release-doctor.yml | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 926fb73e..d603b8b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,10 +21,10 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/beagle-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} 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 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: '22' @@ -43,10 +43,10 @@ jobs: contents: read id-token: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: '22' @@ -61,7 +61,7 @@ jobs: github.repository == 'stainless-sdks/beagle-typescript' && !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc - uses: actions/github-script@v8 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: core.setOutput('github_token', await core.getIDToken()); @@ -91,10 +91,10 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/beagle-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: '22' diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 62727506..e7340e04 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -20,10 +20,10 @@ jobs: contents: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node - uses: actions/setup-node@v3 + uses: actions/setup-node@3235b876344d2a9aa001b8d1453c930bba69e610 # v3.9.1 with: node-version: '20' diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index e324435f..cb7328b1 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'corgi-tech/beagle-sdks' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Check release environment run: | From 005dc9ef1631dc82e17411f8428d80d4457f80cc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 19 May 2026 02:29:11 +0000 Subject: [PATCH 131/138] chore(internal): codegen related update --- package.json | 2 +- packages/mcp-server/package.json | 2 +- packages/mcp-server/yarn.lock | 6 +++--- src/core/pagination.ts | 8 ++++---- tests/uploads.test.ts | 1 - yarn.lock | 6 +++--- 6 files changed, 12 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 2d686ad6..e5673b77 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "publint": "^0.2.12", "ts-jest": "^29.1.0", "ts-node": "^10.5.0", - "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz", + "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.11/tsc-multi.tgz", "tsconfig-paths": "^4.0.0", "tslib": "^2.8.1", "typescript": "5.8.3", diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 7cd44103..a1bfd42d 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -74,7 +74,7 @@ "ts-jest": "^29.1.0", "ts-morph": "^19.0.0", "ts-node": "^10.5.0", - "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz", + "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.11/tsc-multi.tgz", "tsconfig-paths": "^4.0.0" }, "imports": { diff --git a/packages/mcp-server/yarn.lock b/packages/mcp-server/yarn.lock index c7e37692..c6b17b02 100644 --- a/packages/mcp-server/yarn.lock +++ b/packages/mcp-server/yarn.lock @@ -3921,9 +3921,9 @@ ts-node@^10.5.0: v8-compile-cache-lib "^3.0.1" yn "3.1.1" -"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz": - version "1.1.9" - resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz#777f6f5d9e26bf0e94e5170990dd3a841d6707cd" +"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.11/tsc-multi.tgz": + version "1.1.11" + resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.11/tsc-multi.tgz#010247051be13b55abdc98f787c017285149f4f2" dependencies: debug "^4.3.7" fast-glob "^3.3.2" diff --git a/src/core/pagination.ts b/src/core/pagination.ts index aa09f157..f9fe8fa3 100644 --- a/src/core/pagination.ts +++ b/src/core/pagination.ts @@ -166,7 +166,7 @@ export class PropertyManagersPagination nextPageRequestOptions(): PageRequestOptions | null { const currentPage = this.pagination?.page ?? 1; - if (currentPage >= this.pagination?.pages) { + if (this.pagination.pages != null && currentPage >= this.pagination.pages) { return null; } @@ -236,7 +236,7 @@ export class TenantsPagination extends AbstractPage implements Tenan nextPageRequestOptions(): PageRequestOptions | null { const currentPage = this.pagination?.page ?? 1; - if (currentPage >= this.pagination?.pages) { + if (this.pagination.pages != null && currentPage >= this.pagination.pages) { return null; } @@ -309,7 +309,7 @@ export class EnrollmentsPagination nextPageRequestOptions(): PageRequestOptions | null { const currentPage = this.pagination?.page ?? 1; - if (currentPage >= this.pagination?.pages) { + if (this.pagination.pages != null && currentPage >= this.pagination.pages) { return null; } @@ -382,7 +382,7 @@ export class WebhookEndpointsPagination nextPageRequestOptions(): PageRequestOptions | null { const currentPage = this.pagination?.page ?? 1; - if (currentPage >= this.pagination?.pages) { + if (this.pagination.pages != null && currentPage >= this.pagination.pages) { return null; } diff --git a/tests/uploads.test.ts b/tests/uploads.test.ts index c8befc47..b995cd86 100644 --- a/tests/uploads.test.ts +++ b/tests/uploads.test.ts @@ -1,7 +1,6 @@ import fs from 'fs'; import type { ResponseLike } from '@corgi-tech/beagle/internal/to-file'; import { toFile } from '@corgi-tech/beagle/core/uploads'; -import { File } from 'node:buffer'; class MyClass { name: string = 'foo'; diff --git a/yarn.lock b/yarn.lock index 18e7cbdc..00842e32 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3192,9 +3192,9 @@ ts-node@^10.5.0: v8-compile-cache-lib "^3.0.0" yn "3.1.1" -"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz": - version "1.1.9" - resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz#777f6f5d9e26bf0e94e5170990dd3a841d6707cd" +"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.11/tsc-multi.tgz": + version "1.1.11" + resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.11/tsc-multi.tgz#010247051be13b55abdc98f787c017285149f4f2" dependencies: debug "^4.3.7" fast-glob "^3.3.2" From 42a0b38101cd39e519a17d860f906d2ad12a4a55 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 19 May 2026 21:54:59 +0000 Subject: [PATCH 132/138] feat(api): api update --- .stats.yml | 4 ++-- packages/mcp-server/src/local-docs-search.ts | 8 ++++---- src/resources/plans.ts | 15 +++++++++++++++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9b71a0fe..a2708e34 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 18 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi/beagle-54871bab8d880e5f2d06830c746eb892f76a26d39b80311e65abb0196fddbbbc.yml -openapi_spec_hash: f9bab149d06098f3371751141879c9de +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi/beagle-b3de6ee51ac929555b3e0c201ef381ed68072be3cb9ffb78b1a909b7cb3ff0aa.yml +openapi_spec_hash: 6adafdb19b2dd40a7f3bae20cd5e6953 config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 56b9668d..a7afc06e 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -59,9 +59,9 @@ const EMBEDDED_METHODS: MethodEntry[] = [ stainlessPath: '(resource) plans > (method) list', qualified: 'client.plans.list', response: - '{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }[]; success: true; }', + '{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }[]; success: true; }', markdown: - "## list\n\n`client.plans.list(): { data: plan[]; success: true; }`\n\n**get** `/api/plans`\n\nList all available insurance plans that tenants can be enrolled in.\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }[]; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }[]`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plans = await client.plans.list();\n\nconsole.log(plans);\n```", + "## list\n\n`client.plans.list(): { data: plan[]; success: true; }`\n\n**get** `/api/plans`\n\nList all available insurance plans that tenants can be enrolled in.\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }[]; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }[]`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plans = await client.plans.list();\n\nconsole.log(plans);\n```", perLanguage: { typescript: { method: 'client.plans.list', @@ -108,9 +108,9 @@ const EMBEDDED_METHODS: MethodEntry[] = [ qualified: 'client.plans.retrieve', params: ['code: string;'], response: - '{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }; success: true; }', + '{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }; success: true; }', markdown: - "## retrieve\n\n`client.plans.retrieve(code: string): { data: plan; success: true; }`\n\n**get** `/api/plans/{code}`\n\nretrieve a specific plans details by its code.\n\n### Parameters\n\n- `code: string`\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; value?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plan = await client.plans.retrieve('code');\n\nconsole.log(plan);\n```", + "## retrieve\n\n`client.plans.retrieve(code: string): { data: plan; success: true; }`\n\n**get** `/api/plans/{code}`\n\nretrieve a specific plans details by its code.\n\n### Parameters\n\n- `code: string`\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plan = await client.plans.retrieve('code');\n\nconsole.log(plan);\n```", perLanguage: { typescript: { method: 'client.plans.retrieve', diff --git a/src/resources/plans.ts b/src/resources/plans.ts index 1d115692..b66f1be4 100644 --- a/src/resources/plans.ts +++ b/src/resources/plans.ts @@ -47,6 +47,21 @@ export interface Plan { */ liability?: number; + /** + * the maximum monthly rent for a Rent Guarantee plan band. + */ + rentBandMax?: number; + + /** + * the minimum monthly rent for a Rent Guarantee plan band. + */ + rentBandMin?: number; + + /** + * the Rent Guarantee plan term in months, when applicable. + */ + termMonths?: number; + /** * general value field, this is currently used for SDR and SDD plans for the * replacement or discount value. From 5c36448ceff1f3707c24c9ddd48f7abb9dd1f54f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 20 May 2026 19:18:04 +0000 Subject: [PATCH 133/138] feat(api): api update --- .stats.yml | 4 ++-- packages/mcp-server/src/local-docs-search.ts | 10 ++++++---- src/resources/plans.ts | 13 +++++++++++-- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/.stats.yml b/.stats.yml index a2708e34..279c9ffe 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 18 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi/beagle-b3de6ee51ac929555b3e0c201ef381ed68072be3cb9ffb78b1a909b7cb3ff0aa.yml -openapi_spec_hash: 6adafdb19b2dd40a7f3bae20cd5e6953 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi/beagle-b40fd165ae9a643658ef01a9c9ef8685f2922c2e63d83e049fc379daf22616c2.yml +openapi_spec_hash: c579a5a6bf932a9c550dd71b064ee700 config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index a7afc06e..90787a70 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -55,13 +55,14 @@ const EMBEDDED_METHODS: MethodEntry[] = [ endpoint: '/api/plans', httpMethod: 'get', summary: 'List Plans', - description: 'List all available insurance plans that tenants can be enrolled in.', + description: + 'List all available insurance plans that tenants can be enrolled in. Rent Guarantee plans are priced by lease term and monthly rent range. They are client-specific and only appear when enabled for your API key. For example, RG_3M_RENT_750_1000 is a 3-month Rent Guarantee plan for monthly rent between $750 and $1,000. Rent Guarantee plan codes use the format RG_{term}M_RENT_{min}_{max}.', stainlessPath: '(resource) plans > (method) list', qualified: 'client.plans.list', response: '{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }[]; success: true; }', markdown: - "## list\n\n`client.plans.list(): { data: plan[]; success: true; }`\n\n**get** `/api/plans`\n\nList all available insurance plans that tenants can be enrolled in.\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }[]; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }[]`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plans = await client.plans.list();\n\nconsole.log(plans);\n```", + "## list\n\n`client.plans.list(): { data: plan[]; success: true; }`\n\n**get** `/api/plans`\n\nList all available insurance plans that tenants can be enrolled in. Rent Guarantee plans are priced by lease term and monthly rent range. They are client-specific and only appear when enabled for your API key. For example, RG_3M_RENT_750_1000 is a 3-month Rent Guarantee plan for monthly rent between $750 and $1,000. Rent Guarantee plan codes use the format RG_{term}M_RENT_{min}_{max}.\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }[]; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }[]`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plans = await client.plans.list();\n\nconsole.log(plans);\n```", perLanguage: { typescript: { method: 'client.plans.list', @@ -103,14 +104,15 @@ const EMBEDDED_METHODS: MethodEntry[] = [ endpoint: '/api/plans/{code}', httpMethod: 'get', summary: 'Get Plan', - description: 'retrieve a specific plans details by its code.', + description: + "Retrieve a specific plan's details by its code. Rent Guarantee plans are priced by lease term and monthly rent range, and are only available when enabled for your API key. For example, RG_3M_RENT_750_1000 is a 3-month Rent Guarantee plan for monthly rent between $750 and $1,000. Rent Guarantee plan codes use the format RG_{term}M_RENT_{min}_{max}.", stainlessPath: '(resource) plans > (method) retrieve', qualified: 'client.plans.retrieve', params: ['code: string;'], response: '{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }; success: true; }', markdown: - "## retrieve\n\n`client.plans.retrieve(code: string): { data: plan; success: true; }`\n\n**get** `/api/plans/{code}`\n\nretrieve a specific plans details by its code.\n\n### Parameters\n\n- `code: string`\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plan = await client.plans.retrieve('code');\n\nconsole.log(plan);\n```", + "## retrieve\n\n`client.plans.retrieve(code: string): { data: plan; success: true; }`\n\n**get** `/api/plans/{code}`\n\nRetrieve a specific plan's details by its code. Rent Guarantee plans are priced by lease term and monthly rent range, and are only available when enabled for your API key. For example, RG_3M_RENT_750_1000 is a 3-month Rent Guarantee plan for monthly rent between $750 and $1,000. Rent Guarantee plan codes use the format RG_{term}M_RENT_{min}_{max}.\n\n### Parameters\n\n- `code: string`\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plan = await client.plans.retrieve('code');\n\nconsole.log(plan);\n```", perLanguage: { typescript: { method: 'client.plans.retrieve', diff --git a/src/resources/plans.ts b/src/resources/plans.ts index b66f1be4..71d6bb10 100644 --- a/src/resources/plans.ts +++ b/src/resources/plans.ts @@ -10,14 +10,23 @@ import { path } from '../internal/utils/path'; */ export class Plans extends APIResource { /** - * retrieve a specific plans details by its code. + * Retrieve a specific plan's details by its code. Rent Guarantee plans are priced + * by lease term and monthly rent range, and are only available when enabled for + * your API key. For example, RG*3M_RENT_750_1000 is a 3-month Rent Guarantee plan + * for monthly rent between $750 and $1,000. Rent Guarantee plan codes use the + * format RG*{term}M*RENT*{min}\_{max}. */ retrieve(code: string, options?: RequestOptions): APIPromise { return this._client.get(path`/api/plans/${code}`, options); } /** - * List all available insurance plans that tenants can be enrolled in. + * List all available insurance plans that tenants can be enrolled in. Rent + * Guarantee plans are priced by lease term and monthly rent range. They are + * client-specific and only appear when enabled for your API key. For example, + * RG*3M_RENT_750_1000 is a 3-month Rent Guarantee plan for monthly rent between + * $750 and $1,000. Rent Guarantee plan codes use the format + * RG*{term}M*RENT*{min}\_{max}. */ list(options?: RequestOptions): APIPromise { return this._client.get('/api/plans', options); From 0c269da5d141f9bfeb3cf436155a4dcfaa99175c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 20 May 2026 22:17:50 +0000 Subject: [PATCH 134/138] feat(api): api update --- .stats.yml | 4 +-- packages/mcp-server/src/local-docs-search.ts | 8 +++--- src/resources/plans.ts | 28 ++++++++++---------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.stats.yml b/.stats.yml index 279c9ffe..c31d9ad5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 18 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi/beagle-b40fd165ae9a643658ef01a9c9ef8685f2922c2e63d83e049fc379daf22616c2.yml -openapi_spec_hash: c579a5a6bf932a9c550dd71b064ee700 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/corgi/beagle-561a4b9ddd891c8254be3d774ba13871197ce79b11e00ad692e591f991290fc3.yml +openapi_spec_hash: 9a6cedbb9cea871f5d9c5634cf3f5f2a config_hash: a50e91a2233ab4faad057e676e3cfe49 diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 90787a70..19fc8b30 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -56,13 +56,13 @@ const EMBEDDED_METHODS: MethodEntry[] = [ httpMethod: 'get', summary: 'List Plans', description: - 'List all available insurance plans that tenants can be enrolled in. Rent Guarantee plans are priced by lease term and monthly rent range. They are client-specific and only appear when enabled for your API key. For example, RG_3M_RENT_750_1000 is a 3-month Rent Guarantee plan for monthly rent between $750 and $1,000. Rent Guarantee plan codes use the format RG_{term}M_RENT_{min}_{max}.', + "List all insurance plans available to your API key. Plan availability, coverage details, and pricing can vary by client configuration. Use the plan's name/code when creating enrollments.", stainlessPath: '(resource) plans > (method) list', qualified: 'client.plans.list', response: '{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }[]; success: true; }', markdown: - "## list\n\n`client.plans.list(): { data: plan[]; success: true; }`\n\n**get** `/api/plans`\n\nList all available insurance plans that tenants can be enrolled in. Rent Guarantee plans are priced by lease term and monthly rent range. They are client-specific and only appear when enabled for your API key. For example, RG_3M_RENT_750_1000 is a 3-month Rent Guarantee plan for monthly rent between $750 and $1,000. Rent Guarantee plan codes use the format RG_{term}M_RENT_{min}_{max}.\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }[]; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }[]`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plans = await client.plans.list();\n\nconsole.log(plans);\n```", + "## list\n\n`client.plans.list(): { data: plan[]; success: true; }`\n\n**get** `/api/plans`\n\nList all insurance plans available to your API key. Plan availability, coverage details, and pricing can vary by client configuration. Use the plan's name/code when creating enrollments.\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }[]; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }[]`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plans = await client.plans.list();\n\nconsole.log(plans);\n```", perLanguage: { typescript: { method: 'client.plans.list', @@ -105,14 +105,14 @@ const EMBEDDED_METHODS: MethodEntry[] = [ httpMethod: 'get', summary: 'Get Plan', description: - "Retrieve a specific plan's details by its code. Rent Guarantee plans are priced by lease term and monthly rent range, and are only available when enabled for your API key. For example, RG_3M_RENT_750_1000 is a 3-month Rent Guarantee plan for monthly rent between $750 and $1,000. Rent Guarantee plan codes use the format RG_{term}M_RENT_{min}_{max}.", + "Retrieve a specific plan's details by its code. Plans are only returned when they are available to your API key, and pricing can vary by client configuration.", stainlessPath: '(resource) plans > (method) retrieve', qualified: 'client.plans.retrieve', params: ['code: string;'], response: '{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }; success: true; }', markdown: - "## retrieve\n\n`client.plans.retrieve(code: string): { data: plan; success: true; }`\n\n**get** `/api/plans/{code}`\n\nRetrieve a specific plan's details by its code. Rent Guarantee plans are priced by lease term and monthly rent range, and are only available when enabled for your API key. For example, RG_3M_RENT_750_1000 is a 3-month Rent Guarantee plan for monthly rent between $750 and $1,000. Rent Guarantee plan codes use the format RG_{term}M_RENT_{min}_{max}.\n\n### Parameters\n\n- `code: string`\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plan = await client.plans.retrieve('code');\n\nconsole.log(plan);\n```", + "## retrieve\n\n`client.plans.retrieve(code: string): { data: plan; success: true; }`\n\n**get** `/api/plans/{code}`\n\nRetrieve a specific plan's details by its code. Plans are only returned when they are available to your API key, and pricing can vary by client configuration.\n\n### Parameters\n\n- `code: string`\n\n### Returns\n\n- `{ data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }; success: true; }`\n\n - `data: { description: string; name: string; rate: number; contents?: number; liability?: number; rentBandMax?: number; rentBandMin?: number; termMonths?: number; value?: number; }`\n - `success: true`\n\n### Example\n\n```typescript\nimport Beagle from '@corgi-tech/beagle';\n\nconst client = new Beagle();\n\nconst plan = await client.plans.retrieve('code');\n\nconsole.log(plan);\n```", perLanguage: { typescript: { method: 'client.plans.retrieve', diff --git a/src/resources/plans.ts b/src/resources/plans.ts index 71d6bb10..970f3d3d 100644 --- a/src/resources/plans.ts +++ b/src/resources/plans.ts @@ -10,23 +10,18 @@ import { path } from '../internal/utils/path'; */ export class Plans extends APIResource { /** - * Retrieve a specific plan's details by its code. Rent Guarantee plans are priced - * by lease term and monthly rent range, and are only available when enabled for - * your API key. For example, RG*3M_RENT_750_1000 is a 3-month Rent Guarantee plan - * for monthly rent between $750 and $1,000. Rent Guarantee plan codes use the - * format RG*{term}M*RENT*{min}\_{max}. + * Retrieve a specific plan's details by its code. Plans are only returned when + * they are available to your API key, and pricing can vary by client + * configuration. */ retrieve(code: string, options?: RequestOptions): APIPromise { return this._client.get(path`/api/plans/${code}`, options); } /** - * List all available insurance plans that tenants can be enrolled in. Rent - * Guarantee plans are priced by lease term and monthly rent range. They are - * client-specific and only appear when enabled for your API key. For example, - * RG*3M_RENT_750_1000 is a 3-month Rent Guarantee plan for monthly rent between - * $750 and $1,000. Rent Guarantee plan codes use the format - * RG*{term}M*RENT*{min}\_{max}. + * List all insurance plans available to your API key. Plan availability, coverage + * details, and pricing can vary by client configuration. Use the plan's name/code + * when creating enrollments. */ list(options?: RequestOptions): APIPromise { return this._client.get('/api/plans', options); @@ -57,17 +52,22 @@ export interface Plan { liability?: number; /** - * the maximum monthly rent for a Rent Guarantee plan band. + * for approved-partner Rent Guarantee plans, the maximum monthly rent covered by + * this rent band. Rent Guarantee plan codes use the format + * RG*{term}M_RENT*{min}\_{max}; for example, RG_3M_RENT_750_1000 covers a 3-month + * term with monthly rent from $750 to $1,000. */ rentBandMax?: number; /** - * the minimum monthly rent for a Rent Guarantee plan band. + * for approved-partner Rent Guarantee plans, the minimum monthly rent covered by + * this rent band. */ rentBandMin?: number; /** - * the Rent Guarantee plan term in months, when applicable. + * for approved-partner Rent Guarantee plans, the lease term in months. Match this + * to the tenant's lease term when choosing a plan. */ termMonths?: number; From 8592006382aaaab8abd85c5a4515ba6ab225da6d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 26 May 2026 02:04:21 +0000 Subject: [PATCH 135/138] fix: treat text/plan with format: binary as raw upload --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 00842e32..06fc1085 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1215,9 +1215,9 @@ baseline-browser-mapping@^2.9.0: integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== brace-expansion@^2.0.2: - version "2.1.0" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.0.tgz#4f41a41190216ee36067ec381526fe9539c4f0ae" - integrity sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w== + version "2.1.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.1.tgz#c68b1c4111c76aae3a6fba55d496cee10c39dad8" + integrity sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA== dependencies: balanced-match "^1.0.0" From 5c4f119f0667c84a2568b389f96b0c5c967fa3d9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 29 May 2026 02:21:51 +0000 Subject: [PATCH 136/138] chore(internal): codegen related update --- scripts/build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build b/scripts/build index d66231b0..43cb20e1 100755 --- a/scripts/build +++ b/scripts/build @@ -52,6 +52,6 @@ fi # build all sub-packages for dir in packages/*; do if [ -d "$dir" ]; then - (cd "$dir" && yarn install && yarn build) + (cd "$dir" && yarn install --pure-lockfile && yarn build) fi done From 2d6cec653e60c235ce151ed55f179bdc6751a5c3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 02:07:49 +0000 Subject: [PATCH 137/138] fix(client): send content-type header for requests with an omitted optional body --- src/client.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/client.ts b/src/client.ts index a01b6643..e269a36e 100644 --- a/src/client.ts +++ b/src/client.ts @@ -766,11 +766,19 @@ export class Beagle { return () => controller.abort(); } - private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): { + private buildBody({ options }: { options: FinalRequestOptions }): { bodyHeaders: HeadersLike; body: BodyInit | undefined; } { + const { body, headers: rawHeaders } = options; if (!body) { + // A resource method always passes a `body` key when its operation defines a + // request body, even if the caller omitted an optional body param. Keep the + // content-type for those, and only elide it for operations with no body at + // all (e.g. GET/DELETE). + if (body == null && 'body' in options) { + return this.#encoder({ body, headers: buildHeaders([rawHeaders]) }); + } return { bodyHeaders: undefined, body: undefined }; } const headers = buildHeaders([rawHeaders]); From 1c3f8703544ead9797944ce34ba43a8d965d86ae Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 02:09:20 +0000 Subject: [PATCH 138/138] release: 2.0.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 192 ++++++++++++++++++++++++++++++ package.json | 2 +- packages/mcp-server/manifest.json | 2 +- packages/mcp-server/package.json | 2 +- packages/mcp-server/src/server.ts | 2 +- src/version.ts | 2 +- 7 files changed, 198 insertions(+), 6 deletions(-) create mode 100644 CHANGELOG.md diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 67dcd73f..895bf0e3 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.1-alpha.0" + ".": "2.0.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..980351f9 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,192 @@ +# Changelog + +## 2.0.0 (2026-06-17) + +Full Changelog: [v0.0.1-alpha.0...v2.0.0](https://github.com/corgi-tech/beagle-sdks/compare/v0.0.1-alpha.0...v2.0.0) + +### Features + +* **api:** add webhooks & insurance verification ([8149e9c](https://github.com/corgi-tech/beagle-sdks/commit/8149e9c8f5013101ee1b11565d95bc4c6407f846)) +* **api:** api update ([0c269da](https://github.com/corgi-tech/beagle-sdks/commit/0c269da5d141f9bfeb3cf436155a4dcfaa99175c)) +* **api:** api update ([5c36448](https://github.com/corgi-tech/beagle-sdks/commit/5c36448ceff1f3707c24c9ddd48f7abb9dd1f54f)) +* **api:** api update ([42a0b38](https://github.com/corgi-tech/beagle-sdks/commit/42a0b38101cd39e519a17d860f906d2ad12a4a55)) +* **api:** api update ([fec1f3c](https://github.com/corgi-tech/beagle-sdks/commit/fec1f3c507df6780b0e93d6ff07310f383b533e6)) +* **api:** api update ([6f0df5b](https://github.com/corgi-tech/beagle-sdks/commit/6f0df5be92a58371b17915bc82e305e5be5f5cc6)) +* **api:** api update ([69cd92b](https://github.com/corgi-tech/beagle-sdks/commit/69cd92bb960311538f857859a99bfd75191be650)) +* **api:** api update ([3b62b6d](https://github.com/corgi-tech/beagle-sdks/commit/3b62b6d6f4dccf2b11aec39e363fae8ebc9f1e60)) +* **api:** api update ([dd8e619](https://github.com/corgi-tech/beagle-sdks/commit/dd8e619d252ab2568fd779a79449789628f6eb4c)) +* **api:** api update ([d60812e](https://github.com/corgi-tech/beagle-sdks/commit/d60812edd7fba4a49d43cd19f05f5c0a0cdc19eb)) +* **api:** api update ([9a160cf](https://github.com/corgi-tech/beagle-sdks/commit/9a160cf9ab6b99e57419fe01d6ee38a9278ad558)) +* **api:** api update ([ff22357](https://github.com/corgi-tech/beagle-sdks/commit/ff2235783f30d1331d845693dbdd1347bc4b4795)) +* **api:** api update ([23c1441](https://github.com/corgi-tech/beagle-sdks/commit/23c144132a69e9703f64c1700ab693dcee45dac4)) +* **api:** api update ([df35c3f](https://github.com/corgi-tech/beagle-sdks/commit/df35c3f62a43d2cb86a96e00614568e7f1ec2c65)) +* **api:** api update ([dabc9a7](https://github.com/corgi-tech/beagle-sdks/commit/dabc9a7d69d81803d8ace73720b62f6002eac2f3)) +* **api:** api update ([1757c43](https://github.com/corgi-tech/beagle-sdks/commit/1757c430c970516be9002d1f6c341e123193a54a)) +* **api:** api update ([d467235](https://github.com/corgi-tech/beagle-sdks/commit/d4672351a7941a0395c9b23baaff9cacc179b93e)) +* **api:** api update ([7477c2d](https://github.com/corgi-tech/beagle-sdks/commit/7477c2dbdd36f8ab00abb2dc0b34864417a09558)) +* **api:** api update ([6700d42](https://github.com/corgi-tech/beagle-sdks/commit/6700d42958cc9db8ce4e13667d6e960b035a813c)) +* **api:** api update ([e17398f](https://github.com/corgi-tech/beagle-sdks/commit/e17398f8d36c6a5f4d4f1cda0f47957b2f9aa76b)) +* **api:** api update ([2bb87b2](https://github.com/corgi-tech/beagle-sdks/commit/2bb87b26625aac745e42fc2ef606ad6acce5e6a8)) +* **api:** api update ([9e66c0b](https://github.com/corgi-tech/beagle-sdks/commit/9e66c0b05880780f87299cd2cea9ae0e81d6ef25)) +* **api:** api update ([2a8eeca](https://github.com/corgi-tech/beagle-sdks/commit/2a8eecaa6191beac6da67a2be4ad820b2b9b2450)) +* **api:** manual updates ([b34cc40](https://github.com/corgi-tech/beagle-sdks/commit/b34cc40199fbf95a29f862317c8cbd8c17f4be8b)) +* **api:** pagination to readme ([af15627](https://github.com/corgi-tech/beagle-sdks/commit/af156274e9a58cadb3fae6da02c45211218b0d3c)) +* **api:** test cleanup on webhook endpoint shapes ([9c55bea](https://github.com/corgi-tech/beagle-sdks/commit/9c55bea27f36f88963b6f5871fe782edee7f7497)) +* **api:** update via SDK Studio ([8b15707](https://github.com/corgi-tech/beagle-sdks/commit/8b15707e6f80fd03e815e73f8751c9a3d9564148)) +* **api:** update via SDK Studio ([93c377f](https://github.com/corgi-tech/beagle-sdks/commit/93c377f9bcec660e053d242e5985c4145f73cebd)) +* **api:** update via SDK Studio ([e6ebc26](https://github.com/corgi-tech/beagle-sdks/commit/e6ebc2632bec4667cc6b4de5c7cd0c2af54cf3c2)) +* **api:** update via SDK Studio ([3e0ec8d](https://github.com/corgi-tech/beagle-sdks/commit/3e0ec8dd48f106ceca16908d6e7858cb1b7363ac)) +* **api:** update via SDK Studio ([b5a69d1](https://github.com/corgi-tech/beagle-sdks/commit/b5a69d1a994a018668be8254dab658a754616db8)) +* **api:** update via SDK Studio ([9b14796](https://github.com/corgi-tech/beagle-sdks/commit/9b14796531547df45f091696005a78ae34702cc6)) +* **api:** update via SDK Studio ([89182da](https://github.com/corgi-tech/beagle-sdks/commit/89182da970016190ad315ffbadcb34285af09754)) +* **api:** update via SDK Studio ([2b9b95c](https://github.com/corgi-tech/beagle-sdks/commit/2b9b95c2b89b8832be15cdeaa5a34ad3cd7d57c0)) +* **api:** update via SDK Studio ([c4da553](https://github.com/corgi-tech/beagle-sdks/commit/c4da553d9d4ce8295ddf8444db1248889f54cbae)) +* **api:** update via SDK Studio ([5e544fc](https://github.com/corgi-tech/beagle-sdks/commit/5e544fc2d293862013faa86f5c4321eeb65f034c)) +* **api:** update via SDK Studio ([7f7d437](https://github.com/corgi-tech/beagle-sdks/commit/7f7d437702e6dddbc3f71f0b59ae469bcf662028)) +* **client:** add support for endpoint-specific base URLs ([12d7a7a](https://github.com/corgi-tech/beagle-sdks/commit/12d7a7a41360d437dd6c7b76c6d8cfe7e3bb58a4)) +* **mcp:** add code execution tool ([1269066](https://github.com/corgi-tech/beagle-sdks/commit/1269066e553182727ad21f6458022e6d83f35cab)) +* **mcp:** add logging when environment variable is set ([845ad08](https://github.com/corgi-tech/beagle-sdks/commit/845ad086e76de9a3e4e5bd5cdca12771c51c02f6)) +* **mcp:** add option to infer mcp client ([1aa1c09](https://github.com/corgi-tech/beagle-sdks/commit/1aa1c092c2892d5ccf86f67936b847e6b1900ca9)) +* **mcp:** add unix socket option for remote MCP ([9b0fb4c](https://github.com/corgi-tech/beagle-sdks/commit/9b0fb4c376c1d5909bb956dca146532574744d7d)) +* **mcp:** allow setting logging level ([1a551d1](https://github.com/corgi-tech/beagle-sdks/commit/1a551d182e06c6d83d5b5a56abfecbf53728b195)) +* **mcp:** expose client options in `streamableHTTPApp` ([9b6b5ee](https://github.com/corgi-tech/beagle-sdks/commit/9b6b5ee4ca24115f8723fb85733a1137d2e042f4)) +* **mcp:** fallback for void-typed methods ([9df18b9](https://github.com/corgi-tech/beagle-sdks/commit/9df18b9b58478de4dfa6a52f31e504ffab0b8ad2)) +* **mcp:** implement support for binary responses ([457b771](https://github.com/corgi-tech/beagle-sdks/commit/457b771d93b6d61909fc6d18ca299cf6eaad3e7c)) +* **mcp:** parse query string as mcp client options in mcp server ([913561f](https://github.com/corgi-tech/beagle-sdks/commit/913561f27fbaa093f44c8b7a32c2b921d8bb621a)) +* **mcp:** remote server with passthru auth ([08c8116](https://github.com/corgi-tech/beagle-sdks/commit/08c8116423ba4e0fe4f8f73c64de5ac45ea0aea2)) +* **mcp:** set X-Stainless-MCP header ([a9a55d5](https://github.com/corgi-tech/beagle-sdks/commit/a9a55d578a4c341ed0fc81f7a015581509194704)) +* **mcp:** support filtering tool results by a jq expression ([f4996f0](https://github.com/corgi-tech/beagle-sdks/commit/f4996f0ebfe928dbb382e1adfb3de2e56644be80)) + + +### Bug Fixes + +* **client:** explicitly copy fetch in withOptions ([6549425](https://github.com/corgi-tech/beagle-sdks/commit/654942593380202fa00df5be51143eba81da112a)) +* **client:** get fetchOptions type more reliably ([b493b26](https://github.com/corgi-tech/beagle-sdks/commit/b493b26282497995feeaeb771a4574e284a4e567)) +* **client:** send content-type header for requests with an omitted optional body ([2d6cec6](https://github.com/corgi-tech/beagle-sdks/commit/2d6cec653e60c235ce151ed55f179bdc6751a5c3)) +* compat with more runtimes ([d55ea65](https://github.com/corgi-tech/beagle-sdks/commit/d55ea654fe9046bd2d8b9ee862dba00dbacb194c)) +* **mcp:** avoid sending `jq_filter` to base API ([1f865ce](https://github.com/corgi-tech/beagle-sdks/commit/1f865ceabad29ea8ea696c4553ddd096b3a26c19)) +* **mcp:** include required section for top-level properties and support naming transformations ([e9ffc0e](https://github.com/corgi-tech/beagle-sdks/commit/e9ffc0ed916dfe1d31e71e716106c828812e7059)) +* **mcp:** relax input type for asTextContextResult ([0fc1bad](https://github.com/corgi-tech/beagle-sdks/commit/0fc1bad413b3171b03e941df0f7fc0efe9d77f42)) +* **mcp:** reverse validJson capability option and limit scope ([bd146b5](https://github.com/corgi-tech/beagle-sdks/commit/bd146b56ffd0cde779cfc7d8ed67ac730599a916)) +* **mcp:** support jq filtering on cloudflare workers ([180be3d](https://github.com/corgi-tech/beagle-sdks/commit/180be3d22bc81db6ed84550dfa768c6959611d39)) +* publish script — handle NPM errors correctly ([3cf171d](https://github.com/corgi-tech/beagle-sdks/commit/3cf171df9c776f8bb7c6bee4e0f735de5b48062b)) +* treat text/plan with format: binary as raw upload ([8592006](https://github.com/corgi-tech/beagle-sdks/commit/8592006382aaaab8abd85c5a4515ba6ab225da6d)) + + +### Chores + +* add docs to RequestOptions type ([2b4bf74](https://github.com/corgi-tech/beagle-sdks/commit/2b4bf74f010ff4aaf5d938749754bc598f1697e7)) +* add package to package.json ([0f2b02d](https://github.com/corgi-tech/beagle-sdks/commit/0f2b02d59a17e84238fdedffae2e880dfb6984e4)) +* adjust eslint.config.mjs ignore pattern ([268fc7f](https://github.com/corgi-tech/beagle-sdks/commit/268fc7f0a41f18ad0630d0e3b1fb1b5c5a595740)) +* avoid type error in certain environments ([c2488b6](https://github.com/corgi-tech/beagle-sdks/commit/c2488b6e29a721fc22b04498a691da5e4266bc2e)) +* change publish docs url ([5226de4](https://github.com/corgi-tech/beagle-sdks/commit/5226de443388f1a2bc9bb7f636c4fb3ba9c9b505)) +* ci build action ([c24a150](https://github.com/corgi-tech/beagle-sdks/commit/c24a15020445287f2bbbc840d0cd5367079a8587)) +* **ci:** enable for pull requests ([92aaedf](https://github.com/corgi-tech/beagle-sdks/commit/92aaedff0002fb02460065292b973d0f44800f94)) +* **ci:** only run for pushes and fork pull requests ([608e883](https://github.com/corgi-tech/beagle-sdks/commit/608e883362fba20a007ccdbb1d742b3fa76e0b91)) +* **client:** improve path param validation ([334ab9c](https://github.com/corgi-tech/beagle-sdks/commit/334ab9cff9ab1f527ec33fa3b1e5371f30a50f78)) +* **client:** qualify global Blob ([bca52b4](https://github.com/corgi-tech/beagle-sdks/commit/bca52b4ab63b8ad10207c10e3b91bf745e842919)) +* **client:** refactor imports ([bcb6e5e](https://github.com/corgi-tech/beagle-sdks/commit/bcb6e5ee13135bead90e57b00f1a2e98c44f58cf)) +* configure new SDK language ([b9ee214](https://github.com/corgi-tech/beagle-sdks/commit/b9ee2140c2996771561ce50b616249cba930cf0b)) +* configure new SDK language ([f9210d8](https://github.com/corgi-tech/beagle-sdks/commit/f9210d829fd150f0e8d9c4376d3e37996d9a19e8)) +* **deps:** bump eslint-plugin-prettier ([a05d9c3](https://github.com/corgi-tech/beagle-sdks/commit/a05d9c387dd734d32d84e51438d095bb65b0b8fe)) +* **deps:** update dependency @types/node to v20.17.58 ([f1f23d5](https://github.com/corgi-tech/beagle-sdks/commit/f1f23d5d2ef771d8ee07eccef54fce0091923bf3)) +* **docs:** use top-level-await in example snippets ([d28eba3](https://github.com/corgi-tech/beagle-sdks/commit/d28eba32d2514892f49e68647437e2b2a96156ea)) +* **internal:** add pure annotations, make base APIResource abstract ([bafb575](https://github.com/corgi-tech/beagle-sdks/commit/bafb575b158eceedc5e3f9d5b938de69e120b6ed)) +* **internal:** codegen related update ([5c4f119](https://github.com/corgi-tech/beagle-sdks/commit/5c4f119f0667c84a2568b389f96b0c5c967fa3d9)) +* **internal:** codegen related update ([005dc9e](https://github.com/corgi-tech/beagle-sdks/commit/005dc9ef1631dc82e17411f8428d80d4457f80cc)) +* **internal:** codegen related update ([d49d7e5](https://github.com/corgi-tech/beagle-sdks/commit/d49d7e5e4a552e90b6b3c14788a8ca6dea09c004)) +* **internal:** codegen related update ([d48674e](https://github.com/corgi-tech/beagle-sdks/commit/d48674e4ff226a997fe0e791e908369cea5b149b)) +* **internal:** codegen related update ([516b897](https://github.com/corgi-tech/beagle-sdks/commit/516b897c6fd16266a8ad5b3f0d1850053a08d454)) +* **internal:** codegen related update ([f7d0710](https://github.com/corgi-tech/beagle-sdks/commit/f7d0710eaf076b3cdd60715492cdca08da33ed00)) +* **internal:** codegen related update ([52de4bb](https://github.com/corgi-tech/beagle-sdks/commit/52de4bb952e65b0cbc6ef5831cace103b6ce4f33)) +* **internal:** codegen related update ([77ae117](https://github.com/corgi-tech/beagle-sdks/commit/77ae117e0b84e00817bb1aa7f84cdb39cd95796c)) +* **internal:** codegen related update ([14bac3e](https://github.com/corgi-tech/beagle-sdks/commit/14bac3e858c0e5f2a22d2b6d46fdfd1f54ea68c0)) +* **internal:** codegen related update ([a435a45](https://github.com/corgi-tech/beagle-sdks/commit/a435a4578c8992d07627a8d746317b4737401d42)) +* **internal:** codegen related update ([ac5e463](https://github.com/corgi-tech/beagle-sdks/commit/ac5e4635baa292446c0ac188467401aac01fd2a7)) +* **internal:** codegen related update ([46f241e](https://github.com/corgi-tech/beagle-sdks/commit/46f241ecc68ec680b7ce8b1f4e6971328a95b625)) +* **internal:** codegen related update ([e9f78b1](https://github.com/corgi-tech/beagle-sdks/commit/e9f78b10d52231401dab603ec28a5c934063dc9a)) +* **internal:** codegen related update ([3731058](https://github.com/corgi-tech/beagle-sdks/commit/37310585b45733f820ba36bf7accd30b5abe2c30)) +* **internal:** codegen related update ([f8e55dc](https://github.com/corgi-tech/beagle-sdks/commit/f8e55dc9a6aca74d52d2137f9c4ef711801a818d)) +* **internal:** codegen related update ([a964764](https://github.com/corgi-tech/beagle-sdks/commit/a964764acd8d0ff492707aee8b4aaeb0d25f261c)) +* **internal:** codegen related update ([0811822](https://github.com/corgi-tech/beagle-sdks/commit/08118229a18bc20e69ff03e53fb69b2f5dd6cbd5)) +* **internal:** codegen related update ([e76d478](https://github.com/corgi-tech/beagle-sdks/commit/e76d478464cad7d133de1759662af827074ccb5a)) +* **internal:** codegen related update ([5062a2c](https://github.com/corgi-tech/beagle-sdks/commit/5062a2c25ad7601b8d0da820cd2f500757828885)) +* **internal:** codegen related update ([b749c77](https://github.com/corgi-tech/beagle-sdks/commit/b749c77c8a7bcec61090e4ffed69a9af715ec390)) +* **internal:** codegen related update ([1456ba6](https://github.com/corgi-tech/beagle-sdks/commit/1456ba62ee4641021cb2aef893588bffc71d791e)) +* **internal:** codegen related update ([4b5a662](https://github.com/corgi-tech/beagle-sdks/commit/4b5a6626ff1f3ce289c7a2bc25b3fb200f6beeaf)) +* **internal:** codegen related update ([5b04161](https://github.com/corgi-tech/beagle-sdks/commit/5b0416129e941ab2cf00b73a3748d9edc491fb94)) +* **internal:** codegen related update ([d1bdeb7](https://github.com/corgi-tech/beagle-sdks/commit/d1bdeb77d1a6d0e46e67e6d4865f7d0da0d689a7)) +* **internal:** codegen related update ([94258ad](https://github.com/corgi-tech/beagle-sdks/commit/94258adedfbaf1272f7d137b5e10b5b9270c3b5a)) +* **internal:** codegen related update ([440ae15](https://github.com/corgi-tech/beagle-sdks/commit/440ae1570850aa44c6e74c1b0ef5266589e7c883)) +* **internal:** codegen related update ([7e137eb](https://github.com/corgi-tech/beagle-sdks/commit/7e137eba30e258562dcafff4078da074e20ff482)) +* **internal:** codegen related update ([b0f7b26](https://github.com/corgi-tech/beagle-sdks/commit/b0f7b26a49fbfbf9bf5223f29419417be2db7214)) +* **internal:** codegen related update ([64360c0](https://github.com/corgi-tech/beagle-sdks/commit/64360c0082d42f064984c9f4deb37e0004c1c9fa)) +* **internal:** codegen related update ([be604b5](https://github.com/corgi-tech/beagle-sdks/commit/be604b5893ff914f86c895ea90d22baaddc8535d)) +* **internal:** codegen related update ([37d999e](https://github.com/corgi-tech/beagle-sdks/commit/37d999e60811093717bbe1d5ff8def0042c9b359)) +* **internal:** codegen related update ([522fc90](https://github.com/corgi-tech/beagle-sdks/commit/522fc908bf543d920f7d6e1dd17b16a233532064)) +* **internal:** codegen related update ([ba5a41e](https://github.com/corgi-tech/beagle-sdks/commit/ba5a41e81c157bc49fda7d9bff1ab01e960d4bfc)) +* **internal:** codegen related update ([40f63e2](https://github.com/corgi-tech/beagle-sdks/commit/40f63e208dd454a7f2d68ebe64e419b7f1becb3a)) +* **internal:** codegen related update ([9bb2822](https://github.com/corgi-tech/beagle-sdks/commit/9bb2822d8a46d582cd0042ee5b22dc837cd8babc)) +* **internal:** codegen related update ([f51ff81](https://github.com/corgi-tech/beagle-sdks/commit/f51ff818983d9d6474a8b367e8d3d9c8ddec1429)) +* **internal:** codegen related update ([7247d7b](https://github.com/corgi-tech/beagle-sdks/commit/7247d7ba2bf1e0a328d1a04a8d6754b70798a2ad)) +* **internal:** codegen related update ([e3d038e](https://github.com/corgi-tech/beagle-sdks/commit/e3d038e4263c54d5f76209f881b25292b5451dfe)) +* **internal:** codegen related update ([d01b7ab](https://github.com/corgi-tech/beagle-sdks/commit/d01b7ab283ec4fa0e8bb75b394ec699e8faa074d)) +* **internal:** codegen related update ([e0d836a](https://github.com/corgi-tech/beagle-sdks/commit/e0d836ab92ff11783082dc87b1c82e8f290cba7c)) +* **internal:** codegen related update ([82117a6](https://github.com/corgi-tech/beagle-sdks/commit/82117a62e14c3a1ac72fc3c632c7fb21b7934d94)) +* **internal:** codegen related update ([94390bc](https://github.com/corgi-tech/beagle-sdks/commit/94390bc6b29e976c0a83036f1bb11a111cad63ba)) +* **internal:** codegen related update ([8bd9741](https://github.com/corgi-tech/beagle-sdks/commit/8bd9741143afb8665684c198b15d08ae54c5d6a1)) +* **internal:** codegen related update ([0051b46](https://github.com/corgi-tech/beagle-sdks/commit/0051b46e8c6000d1938afea968f748d4941b08f7)) +* **internal:** codegen related update ([6cfc7a2](https://github.com/corgi-tech/beagle-sdks/commit/6cfc7a2759e7509d7b58253a835629598da380a2)) +* **internal:** codegen related update ([3c63419](https://github.com/corgi-tech/beagle-sdks/commit/3c63419f86cd723812abc2984d6ca518f32d8ad4)) +* **internal:** codegen related update ([e54e04f](https://github.com/corgi-tech/beagle-sdks/commit/e54e04f77fc224bd3488ac7ef09738788af68071)) +* **internal:** codegen related update ([f141204](https://github.com/corgi-tech/beagle-sdks/commit/f141204909ece06b927458df3dc99c23d3f0a3ee)) +* **internal:** codegen related update ([b346b4a](https://github.com/corgi-tech/beagle-sdks/commit/b346b4a57a5aaf2b7531daf166e5ba375c98e2f9)) +* **internal:** codegen related update ([198914f](https://github.com/corgi-tech/beagle-sdks/commit/198914f82467d8c6500b9f93f899d873c07550ff)) +* **internal:** codegen related update ([4737470](https://github.com/corgi-tech/beagle-sdks/commit/473747085794925217e3c7e9e78acb21319cd87e)) +* **internal:** codegen related update ([cb1b2de](https://github.com/corgi-tech/beagle-sdks/commit/cb1b2de75afc69765dc42d832b5a6cac991061b0)) +* **internal:** codegen related update ([c51b535](https://github.com/corgi-tech/beagle-sdks/commit/c51b5357383a5a86f6592d8af2b9ccd3e357c29e)) +* **internal:** codegen related update ([a880b1a](https://github.com/corgi-tech/beagle-sdks/commit/a880b1a570f52404fab4d0fcc47f4dc4867e89eb)) +* **internal:** codegen related update ([4077f6d](https://github.com/corgi-tech/beagle-sdks/commit/4077f6d678b4bfdf8744a00eece23c95ac55dc16)) +* **internal:** codegen related update ([16d3d7b](https://github.com/corgi-tech/beagle-sdks/commit/16d3d7bcc7a5220540f4aa8e83212e84da468713)) +* **internal:** codegen related update ([98aac60](https://github.com/corgi-tech/beagle-sdks/commit/98aac60cf6ad782f8fd720d59e4edf8938409eb5)) +* **internal:** codegen related update ([ef25521](https://github.com/corgi-tech/beagle-sdks/commit/ef25521707cb8fa31d9df40ce441eef11ccd105e)) +* **internal:** codegen related update ([a10002e](https://github.com/corgi-tech/beagle-sdks/commit/a10002e54a632b7f5d0cd01d5c53314f7883f3c2)) +* **internal:** codegen related update ([c9154b5](https://github.com/corgi-tech/beagle-sdks/commit/c9154b5f6fba930499648e4b8669e2d13916c6b8)) +* **internal:** codegen related update ([4eb7b49](https://github.com/corgi-tech/beagle-sdks/commit/4eb7b49c60ac79cd3e0270ca2c43eac0444bda94)) +* **internal:** codegen related update ([26017f0](https://github.com/corgi-tech/beagle-sdks/commit/26017f0bd142599771f2e63665bf317131db31bb)) +* **internal:** codegen related update ([394b044](https://github.com/corgi-tech/beagle-sdks/commit/394b04426e6469324b8bc42a1ad94b70b64666a1)) +* **internal:** codegen related update ([f28b947](https://github.com/corgi-tech/beagle-sdks/commit/f28b947295c7808fe071081c6f2a856cfc124661)) +* **internal:** fix MCP Dockerfiles so they can be built without buildkit ([f15f82d](https://github.com/corgi-tech/beagle-sdks/commit/f15f82d8febe62f4c13529feea47c012e8d397f9)) +* **internal:** fix MCP Dockerfiles so they can be built without buildkit ([29a6f08](https://github.com/corgi-tech/beagle-sdks/commit/29a6f084bf441b4c61979f944fdab9c65bf0c8a3)) +* **internal:** fix readablestream types in node 20 ([153e54c](https://github.com/corgi-tech/beagle-sdks/commit/153e54cfa4b3bf0a1e39f4e925119b54a5e92d0e)) +* **internal:** formatting change ([15c4306](https://github.com/corgi-tech/beagle-sdks/commit/15c4306447ee4b4c5ca0e56d6ca29c21f5b6b81c)) +* **internal:** make MCP code execution location configurable via a flag ([de56d4a](https://github.com/corgi-tech/beagle-sdks/commit/de56d4a0f82afcc062322e36e8fab75d2e53bde1)) +* **internal:** make mcp-server publishing public by defaut ([4ea87da](https://github.com/corgi-tech/beagle-sdks/commit/4ea87dae173727b8986c870617f082cb9f05d239)) +* **internal:** move publish config ([b5d9c06](https://github.com/corgi-tech/beagle-sdks/commit/b5d9c06694a66d1c3785238ee392a9576b7dbcf8)) +* **internal:** refactor array check ([e721304](https://github.com/corgi-tech/beagle-sdks/commit/e7213041b460d7fd3cafb0c30aa32a9cf5222d67)) +* **internal:** remove redundant imports config ([00033c0](https://github.com/corgi-tech/beagle-sdks/commit/00033c0b2ea16c042bdc0d2ce1405875f833b10a)) +* **internal:** update comment in script ([23b9927](https://github.com/corgi-tech/beagle-sdks/commit/23b9927106007dbe0f20607802049ba138b87df0)) +* **internal:** update global Error reference ([f2029a0](https://github.com/corgi-tech/beagle-sdks/commit/f2029a0d8e693520ead61b89b9e8516f5956f93f)) +* **internal:** update jest config ([968f16f](https://github.com/corgi-tech/beagle-sdks/commit/968f16f1be5f373bdb651f9ffd8ebad80915d983)) +* **internal:** upgrade @modelcontextprotocol/sdk and hono ([b7ed22d](https://github.com/corgi-tech/beagle-sdks/commit/b7ed22d46820f5f6e4c0a94fde9abe8e0d0d3dfb)) +* make some internal functions async ([03dca37](https://github.com/corgi-tech/beagle-sdks/commit/03dca37a869de6f32a9ea7db5a3478fd2fbcc2e4)) +* **mcp-server:** increase local docs search result count from 5 to 10 ([ac3f8d4](https://github.com/corgi-tech/beagle-sdks/commit/ac3f8d44484c8467f83f3cd1bc59c68b0221406d)) +* **mcp:** add cors to oauth metadata route ([2810aab](https://github.com/corgi-tech/beagle-sdks/commit/2810aabc88f2ea8693242e1a64448eb776b7c549)) +* **mcp:** correctly update version in sync with sdk ([3631698](https://github.com/corgi-tech/beagle-sdks/commit/363169875585a0166881b7b11a12a096a11a388c)) +* **mcp:** document remote server in README.md ([03fd93c](https://github.com/corgi-tech/beagle-sdks/commit/03fd93c9d0ca98f782ebc099daed25817249b434)) +* **mcp:** formatting ([96e93b3](https://github.com/corgi-tech/beagle-sdks/commit/96e93b33f65a890973af7ef80ee18052d60163a4)) +* **mcp:** minor cleanup of types and package.json ([e8a0802](https://github.com/corgi-tech/beagle-sdks/commit/e8a08021d50b3988cd70f0580d4d42422f5b47ea)) +* **mcp:** provides high-level initMcpServer function and exports known clients ([7f2e621](https://github.com/corgi-tech/beagle-sdks/commit/7f2e6216ed98f9f684b7354a228744bdf14b7cf1)) +* **mcp:** refactor streamable http transport ([5667ecd](https://github.com/corgi-tech/beagle-sdks/commit/5667ecd222a0c35e996521a08e995d18ce0d5be3)) +* **mcp:** rework imports in tools ([9d6e556](https://github.com/corgi-tech/beagle-sdks/commit/9d6e556504b526cb6b76cb190f0ee7fe01f68711)) +* **mcp:** up tsconfig lib version to es2022 ([7677185](https://github.com/corgi-tech/beagle-sdks/commit/767718501422e254729875742c8270dd7d91181d)) +* **mcp:** update package.json ([e99397d](https://github.com/corgi-tech/beagle-sdks/commit/e99397d9130edff0386eb934326798ba27d328a9)) +* **mcp:** update README ([5c2b02c](https://github.com/corgi-tech/beagle-sdks/commit/5c2b02cc28ea854c4203099f5e1e0cdeb89c29fd)) +* **mcp:** update types ([5be8de2](https://github.com/corgi-tech/beagle-sdks/commit/5be8de2a75dde75febba09c8e1465e820863dc8a)) +* **readme:** update badges ([501f0ba](https://github.com/corgi-tech/beagle-sdks/commit/501f0ba759def316457bcfedb99cc06bd4ddb602)) +* **readme:** use better example snippet for undocumented params ([84490d0](https://github.com/corgi-tech/beagle-sdks/commit/84490d07e47c61b75314b2f25bd3a5b2fd51f3d4)) +* **ts:** reorder package.json imports ([cae3b82](https://github.com/corgi-tech/beagle-sdks/commit/cae3b820bd235b08a073ea4a5f19e84e8dfda76f)) +* update @stainless-api/prism-cli to v5.15.0 ([8010fd8](https://github.com/corgi-tech/beagle-sdks/commit/8010fd881bd4714255779795cf55a4f04fb6f71d)) +* update CI script ([c045122](https://github.com/corgi-tech/beagle-sdks/commit/c045122557e3da1c7a19264db20607e8e3d5d5f8)) +* update SDK settings ([296405d](https://github.com/corgi-tech/beagle-sdks/commit/296405deb7599b4067ce68a0d3e59952d5e3a606)) +* update SDK settings ([7944dbc](https://github.com/corgi-tech/beagle-sdks/commit/7944dbcad7e324e6c3e368f59f5099efdf5f8b9e)) diff --git a/package.json b/package.json index e5673b77..835cfbae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@corgi-tech/beagle", - "version": "0.0.1-alpha.0", + "version": "2.0.0", "description": "The official TypeScript library for the Beagle API", "author": "Beagle <>", "types": "dist/index.d.ts", diff --git a/packages/mcp-server/manifest.json b/packages/mcp-server/manifest.json index a8b45f2f..2b467b9b 100644 --- a/packages/mcp-server/manifest.json +++ b/packages/mcp-server/manifest.json @@ -1,7 +1,7 @@ { "dxt_version": "0.2", "name": "@corgi-tech/beagle-mcp", - "version": "0.0.1-alpha.0", + "version": "2.0.0", "description": "The official MCP Server for the Beagle API", "author": { "name": "Beagle" diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index a1bfd42d..1ae62eb0 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -1,6 +1,6 @@ { "name": "@corgi-tech/beagle-mcp", - "version": "0.0.1-alpha.0", + "version": "2.0.0", "description": "The official MCP Server for the Beagle API", "author": "Beagle <>", "types": "dist/index.d.ts", diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 81931ad5..a503c5b6 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -29,7 +29,7 @@ export const newMcpServer = async ({ new McpServer( { name: 'corgi_tech_beagle_api', - version: '0.0.1-alpha.0', + version: '2.0.0', }, { instructions: await getInstructions({ stainlessApiKey, customInstructionsPath }), diff --git a/src/version.ts b/src/version.ts index db692bc9..d66dc1ba 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.0.1-alpha.0'; // x-release-please-version +export const VERSION = '2.0.0'; // x-release-please-version