diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml new file mode 100644 index 0000000..c13364e --- /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 == 'AlexK420/mcpdata' && (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 + diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000..466df71 --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.1.0" +} diff --git a/.stats.yml b/.stats.yml index 4e5bf8f..9ccc1c6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 40 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/alex-org%2Fdatanewton-9a672e96630ea01df8f98685d606644cfbb1b99058df75c70cee8f222eed7204.yml openapi_spec_hash: 6c1bfc2e1523a275c2f8246e2004d30c -config_hash: 2aea0249f23849f8c3cee4c82ad3453f +config_hash: f46f6d0fb04fa34b3c440e5fac06807d diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..0904ce3 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,52 @@ +# Changelog + +## 0.1.0 (2025-12-20) + +Full Changelog: [v0.0.1...v0.1.0](https://github.com/AlexK420/mcpdata/compare/v0.0.1...v0.1.0) + +### ⚠ BREAKING CHANGES + +* **mcp:** remove deprecated tool schemes +* **mcp:** **Migration:** To migrate, simply modify the command used to invoke the MCP server. Currently, the only supported tool scheme is code mode. Now, starting the server with just `node /path/to/mcp/server` or `npx package-name` will invoke code tools: changing your command to one of these is likely all you will need to do. + +### Features + +* **mcp:** add detail field to docs search tool ([4b2017b](https://github.com/AlexK420/mcpdata/commit/4b2017b55610adec8b1a46b2d37d12703df9b47f)) +* **mcp:** add typescript check to code execution tool ([5066987](https://github.com/AlexK420/mcpdata/commit/5066987adf78a9796d7bab03826a46f6262dbad4)) +* **mcp:** enable optional code execution tool on http mcp servers ([72af577](https://github.com/AlexK420/mcpdata/commit/72af577677c3997c6b9deb3cbe55f0783f12dc6a)) +* **mcp:** handle code mode calls in the Stainless API ([839ac88](https://github.com/AlexK420/mcpdata/commit/839ac88fbd1df74deca3e4895e3584b39d7fb8c3)) +* **mcp:** return logs on code tool errors ([41d5fd2](https://github.com/AlexK420/mcpdata/commit/41d5fd29e71193adbca5ea8e9fa4c7cc2173cf33)) + + +### Bug Fixes + +* **mcp:** add client instantiation options to code tool ([5555bbd](https://github.com/AlexK420/mcpdata/commit/5555bbd7d126b51692f036eebe12ad0840c54ef4)) +* **mcpb:** pin @anthropic-ai/mcpb version ([990298f](https://github.com/AlexK420/mcpdata/commit/990298fcc57b030ae1f78d7ba385ec5d9624f91d)) +* **mcp:** correct code tool API endpoint ([d7df03a](https://github.com/AlexK420/mcpdata/commit/d7df03a0cd7a5522e3dfff87f4b07ea60e16b260)) +* **mcp:** pass base url to code tool ([f1b4e0f](https://github.com/AlexK420/mcpdata/commit/f1b4e0f55332e801de9ba9d1ed594890f5a5f3b7)) +* **mcp:** return correct lines on typescript errors ([986864a](https://github.com/AlexK420/mcpdata/commit/986864ae236a763a5f37699eb32b3a5db4a791e8)) +* **mcp:** return tool execution error on api error ([6459934](https://github.com/AlexK420/mcpdata/commit/6459934e52ba9f580b96314cfa2a3d3157e53256)) +* **mcp:** return tool execution error on jq failure ([fe28a35](https://github.com/AlexK420/mcpdata/commit/fe28a35e4398286ca2a262969fff5d76573e425a)) + + +### Chores + +* **client:** fix logger property type ([e9faa7a](https://github.com/AlexK420/mcpdata/commit/e9faa7a2b1cc9fa6ea4bec052bfba825261c06e9)) +* configure new SDK language ([a930fd0](https://github.com/AlexK420/mcpdata/commit/a930fd0832c1d8ef3fd888df75ec19b122bb2ade)) +* **internal:** codegen related update ([83728c6](https://github.com/AlexK420/mcpdata/commit/83728c61575af28520a137f8f09a30273a40d58b)) +* **internal:** codegen related update ([b9aa6fc](https://github.com/AlexK420/mcpdata/commit/b9aa6fcd48973b44d9e719ec0d100a18379d9384)) +* **internal:** codegen related update ([ec870f5](https://github.com/AlexK420/mcpdata/commit/ec870f58a106701cec6f695c485dc1a9622e421c)) +* **internal:** codegen related update ([35c5956](https://github.com/AlexK420/mcpdata/commit/35c5956900f002543fc8782f748cd0fc5aa54594)) +* **internal:** codegen related update ([2bcff40](https://github.com/AlexK420/mcpdata/commit/2bcff4090eacb07af1a4de4679726ec05020bf89)) +* **internal:** grammar fix (it's -> its) ([4e37db8](https://github.com/AlexK420/mcpdata/commit/4e37db84dd2fd317a15243277ebb9c90d165bb78)) +* **internal:** upgrade eslint ([97681ab](https://github.com/AlexK420/mcpdata/commit/97681abb1098977c32bdb1a9ee82548d500dbd1e)) +* mcp code tool explicit error message when missing a run function ([f3e1d63](https://github.com/AlexK420/mcpdata/commit/f3e1d63b1e17ea6b6daca88b19afdcf08d46f803)) +* **mcp:** add friendlier MCP code tool errors on incorrect method invocations ([5ead6bc](https://github.com/AlexK420/mcpdata/commit/5ead6bc9cca93e80715d0278e41c29a6939e6e4b)) +* **mcp:** add line numbers to code tool errors ([3a5a56c](https://github.com/AlexK420/mcpdata/commit/3a5a56c4595482567f3596f34e7c620ee4de0749)) +* **mcp:** clarify http auth error ([e26147e](https://github.com/AlexK420/mcpdata/commit/e26147edf9215e2524946a442b5dfc6d4a41cb54)) +* **mcp:** remove deprecated tool schemes ([5627a82](https://github.com/AlexK420/mcpdata/commit/5627a82b2cff281d6b1a786056c4e2bf7a154e2e)) +* **mcp:** update lockfile ([7f2e41d](https://github.com/AlexK420/mcpdata/commit/7f2e41df2d8a8697cc6f9617b34f08e40770685e)) +* **mcp:** upgrade jq-web ([977d40c](https://github.com/AlexK420/mcpdata/commit/977d40c3e6e9a19168d445200509d6364018a7ea)) +* update SDK settings ([62283ae](https://github.com/AlexK420/mcpdata/commit/62283aed01b3bb3bc408946faeb1f62c9ea9864d)) +* use latest @modelcontextprotocol/sdk ([733071a](https://github.com/AlexK420/mcpdata/commit/733071a72ccfacc4edb2387d1f839f32d2b75938)) +* use structured error when code execution tool errors ([9b50e98](https://github.com/AlexK420/mcpdata/commit/9b50e982056247d81e175e5c2a00d14c1e4b1acd)) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3181889..71b8dcc 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/datanewton-typescript.git +$ npm install git+ssh://git@github.com:AlexK420/mcpdata.git ``` Alternatively, to link a local copy of the repo: ```sh # Clone -$ git clone https://www.github.com/stainless-sdks/datanewton-typescript -$ cd datanewton-typescript +$ git clone https://www.github.com/AlexK420/mcpdata +$ cd mcpdata # With yarn $ yarn link diff --git a/README.md b/README.md index 68034fc..d90c621 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/datanewton-typescript.git +npm install git+ssh://git@github.com:AlexK420/mcpdata.git ``` > [!NOTE] @@ -338,7 +338,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/datanewton-typescript/issues) with questions, bugs, or suggestions. +We are keen for your feedback; please open an [issue](https://www.github.com/AlexK420/mcpdata/issues) with questions, bugs, or suggestions. ## Requirements diff --git a/bin/check-release-environment b/bin/check-release-environment new file mode 100644 index 0000000..6b43775 --- /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 fffcadf..39d1c8e 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,12 @@ { "name": "datanewton", - "version": "0.0.1", + "version": "0.1.0", "description": "The official TypeScript library for the Datanewton API", "author": "Datanewton <>", "types": "dist/index.d.ts", "main": "dist/index.js", "type": "commonjs", - "repository": "github:stainless-sdks/datanewton-typescript", + "repository": "github:AlexK420/mcpdata", "license": "Apache-2.0", "packageManager": "yarn@1.22.22", "files": [ @@ -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/packages/mcp-server/README.md b/packages/mcp-server/README.md index d48b660..b305489 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/datanewton-typescript.git -cd datanewton-typescript +git clone git@github.com:AlexK420/mcpdata.git +cd mcpdata ./scripts/bootstrap ./scripts/build ``` @@ -40,11 +40,7 @@ For clients with a configuration JSON, it might look something like this: "mcpServers": { "datanewton_api": { "command": "node", - "args": [ - "/path/to/local/datanewton-typescript/packages/mcp-server", - "--client=claude", - "--tools=dynamic" - ], + "args": ["/path/to/local/mcpdata/packages/mcp-server"], "env": { "DATANEWTON_API_KEY": "My API Key" } @@ -53,97 +49,22 @@ For clients with a configuration JSON, it might look something like this: } ``` -## Exposing endpoints to your MCP Client +## Code Mode -There are two 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 +- 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. - -### 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 @@ -170,298 +91,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 "datanewton-mcp/server"; - -// import a specific tool -import createTaxpayerStatuses from "datanewton-mcp/tools/taxpayer-statuses/create-taxpayer-statuses"; - -// 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: [createTaxpayerStatuses, myCustomEndpoint] }); -``` - -## Available Tools - -The following tools are available in this MCP server. - -### Resource `taxpayer_statuses`: - -- `create_taxpayer_statuses` (`write`): Получить данные о статусе самозанятого налогоплательщика по ИНН - -### Resource `suggestions`: - -- `create_suggestions` (`write`): Получить список первых 10 подходящих контрагентов, соответствующих входному значению - - Поддерживаются следующие виды поиска: - - - `ОГРН` - - `ИНН` - - `Название ЮЛ/ИП, в том числе неполное наименование (например, "Датаном" вместо "Датаномика")` - - `Транслитерированное название ЮЛ` - - `Название ЮЛ, написанное в неправильной раскладке клавиатуры` - - `Неточное название ЮЛ/ИП (с опечатками)` - -### Resource `ogrns_by_address`: - -- `create_ogrns_by_address` (`write`): Получить список компаний по заданному адресу - -### Resource `leases`: - -- `create_leases` (`write`): Получить данные о договорах лизинга по заданным условиям - -### Resource `filters_preview`: - -- `create_filters_preview` (`write`): Получить краткую информацию (предпросмотр) по фильтрам/условиям: оквэд, регионы и т.д. - -### Resource `batch_changes`: - -- `create_batch_changes` (`write`): Получить изменения по списку контрагентов с определенной даты. - Можно смотреть изменения за день, за неделю, за квартал, а также за произвольный период времени. - Можно получить историю изменений выбранных параметров за произвольный период времени. - Отслеживаются: - - - ИНН, ОГРН, КПП - - Статус по ЕГРЮЛ/ЕГРИП - - Название: - - Полное - - Краткое - - Организационно-правовая форма (ОПФ) - - Код ОПФ по ЕГРЮЛ - - Адрес местонахождения - - Единоличный исполнительный орган: - - Руководитель - - Управляющая компания - - Участники - - Уставный капитал: - - Размер - - Тип - - Реестр МСП: - - Статус - - Категория отнесения - - Недостоверность: - - Учредителей - - Руководителей - - Управляющей компании - - Адреса - - Дисквалификация: - - Учредителей - - Руководителей - - Налоговые режимы - - Бухгалтерская (финансовая) отчетность - - ОКВЭД (добавление, изменение, удаление) - - Максимальное количество контрагентов в одном запросе - 500. - Для получения ключа к этой точке API [напишите нам](mailto:info@datanomica.org). - -### Resource `batch_cards`: - -- `create_batch_cards` (`write`): Получить информацию о нескольких организациях одним запросом (до 5 000 контрагентов в запросе), отправив список ИНН/ОГРН - -### Resource `batch_cards_by_filters`: - -- `create_batch_cards_by_filters` (`write`): Получить данные контрагентов по фильтрам/условиям: оквэды, регионы и т.д. - -### Resource `arbitration`: - -- `get_courts_arbitration` (`read`): Получить справочник арбитражных судов: полный список наименований арбитражных судов РФ и количество дел, рассмотренных и рассматриваемых в данных инстанциях -- `get_dispute_categories_arbitration` (`read`): Получить справочник арбитражных споров (категорий), относящихся к компетенции арбитражных судов: категории споров и количество дел в данных категориях -- `get_document_types_arbitration` (`read`): Получить справочник типов документов арбитражных дел: полный список документов (судебных актов), изданных арбитражными судами, а также их количество - -### Resource `arbitration.batch_cases`: - -- `create_arbitration_batch_cases` (`write`): Получить данные об арбитражных делах с возможностью фильтрации - -### Resource `tax_info`: - -- `retrieve_tax_info` (`read`): Получить информацию об уплаченных налогах, задолженностях и штрафах, налоговых нарушениях по ИНН/ОГРН - -### Resource `sro_membership`: - -- `retrieve_sro_membership` (`read`): Получить информацию о членстве в СРО НОСТРОЙ/НОПРИЗ - -### Resource `risks`: - -- `list_risks` (`read`): Получить список рисков по контрагенту - - **Возможные значения** - - **Негативные списки: (NEGATIVE_LISTS)** - - - `owner_inaccuracy` — Недостоверность учредителя - - `disqualified_managers` — Руководитель дисквалифицирован - - `in_sanctions_ofac` — Находится в санкционном списке OFAC - - `illegal_rewards` — Находится в реестре ЮЛ, привлеченных за незаконное вознаграждение - - `address_inaccuracy` — Недостоверность адреса - - `manager_inaccuracy` — Недостоверность руководителя - - `in_sanctions_uk` — Находится в санкционном списке UK - - `in_sanctions_eu` — Находится в санкционном списке EU - - `false_info` — Недостоверные данные по ЕГРЮЛ. Если в ЕГР есть отметка о недостоверности любого из блоков: адрес, участник, руководитель, управляющая компания. - - `disqualified_owners` — Участник дисквалифицирован - - `unscrupulous_manager` — Руководитель в РНП - - `unscrupulous_owner` — Участник в РНП - - `unscrupulous_supplier_223` — Состоит в реестре недобросовестных поставщиков по ФЗ 223 - - `unscrupulous_supplier_615` — Состоит в реестре недобросовестных поставщиков по ПП 615 - - `unscrupulous_supplier_44` — Состоит в реестре недобросовестных поставщиков по ФЗ 44 - - `disqualified_individual` — ИП дисквалифицирован - - `management_company_inaccuracy` — Недостоверность управляющей компании - - `fin_illegal` — Имеет признаки нелегальной деятельности на финансовом рынке - - **Признаки однодневок: (ONE_DAY_COMPANY)** - - - `fns_migration` — Миграция между ФНС (более 2 за 12 месяцев) - - `mass_address` — Массовый юридический адрес. Под массовым юридическим адресом понимается факт регистрации 5 и более компаний с точностью до офиса/помещения/комнаты - - `mass_okveds` — ОКВЭДов более 30 - - `company_age` — Возраст менее 1 года - - `default_capital_table` — Уставный капитал 10 000 ₽ - - `owner_change` — Учредитель сменился менее 1 года назад - - `mass_owner` — Массовый учредитель (более 5) - - `manager_change` — Руководитель сменился менее 1 года назад - - `management_company_change` — Управляющая компания сменилась менее 1 года назад - - `workers_amount` — Численность работников 0 или 1 - - `mass_manager` — Массовый руководитель (более 5) - - `tax_debts` — Имеет налоговую задолженность - - `tax_offences` — Имеет налоговые нарушения - - **Иные факты: (OTHER_FACTS)** - - - `has_licenses` — Имеет действующие лицензии - - `has_declarations` — Имеет действующие Декларации соответствия - - `owners_information_limited` — Ограничение доступа к сведениям в ЕГРЮЛ об участнике - - `zero_intangible_assets` — Нулевая балансовая стоимость нематериальных активов, за последний год - - `zero_fixed_assets` — Нулевая балансовая стоимость основных средств, за последний год - - `has_certifications` — Имеет действующие Сертификаты соответствия - - `management_companies_information_limited` — Ограничение доступа к сведениям в ЕГРЮЛ об управляющей компании - - `has_government_contracts` — Является поставщиком по госконтрактам - - `managers_information_limited` — Ограничение доступа к сведениям в ЕГРЮЛ о руководителе - - `information_limited` — Ограничение доступа к сведениям в ЕГРЮЛ - - `debt` — Сумма к взысканию по исполнительным производствам превышает 300 000 руб - - `status_egrul` — Статус в ЕГРЮЛ, требующий внимания - - `status_egrip` — Статус в ЕГРИП, требующий внимания - - **Сведения о банкротстве: (BANKRUPTCY)** - - - `has_bankruptcy_messages` — Есть сообщения о банкротстве за последний год - -### Resource `paid_taxes`: - -- `list_paid_taxes` (`read`): Получить данные об уплаченных налогах по ИНН/ОГРН - -### Resource `okpd_list`: - -- `list_okpd_list` (`read`): Получить список всех ОКПД (ОКПД2) компании, на основании данных в ЕИС Закупки - -### Resource `nko_reestr`: - -- `retrieve_nko_reestr` (`read`): Получить информацию о принадлежности контрагента к НКО - -### Resource `links`: - -- `list_links` (`read`): Получить связи контрагента (до 2-го уровня включительно): руководители, участники, ИП - -### Resource `government_contracts`: - -- `list_government_contracts` (`read`): Получить данные о госконтрактах контрагента по информации из ЕИС Закупки - -### Resource `government_contracts_stat`: - -- `retrieve_government_contracts_stat` (`read`): Получить статистику по госконтрактам контрагента по информации из ЕИС Закупки - -### Resource `finance`: - -- `retrieve_finance` (`read`): Получить данные отчетов о финансовых результатах организации - -### Resource `regions`: - -- `list_regions` (`read`): Получить справочник регионов России - -### Resource `dictionary`: - -- `list_lease_classifier_dictionary` (`read`): Получить классификатор лизинговых договоров: код лизинга, его наименование и количество заключенных договоров с данным кодом -- `list_licenses_dictionary` (`read`): Получить справочник кодов и типов лицензий -- `list_okveds_dictionary` (`read`): Получить справочник ОКВЭДов -- `list_regions_dictionary` (`read`): Получить справочник регионов России - -### Resource `dictionary.procurement`: - -- `list_okpd2_dictionary_procurement` (`read`): Получить общероссийский классификатор продукции по видам экономической деятельности (ОКПД2) - -### Resource `dictionary.arbitration`: - -- `list_courts_dictionary_arbitration` (`read`): Получить справочник арбитражных судов: полный список наименований арбитражных судов РФ и количество дел, рассмотренных и рассматриваемых в данных инстанциях -- `list_dispute_categories_dictionary_arbitration` (`read`): Получить справочник арбитражных споров (категорий), относящихся к компетенции арбитражных судов: категории споров и количество дел в данных категориях -- `list_document_types_dictionary_arbitration` (`read`): Получить справочник типов документов арбитражных дел: полный список документов (судебных актов), изданных арбитражными судами, а также их количество - -### Resource `procurement`: - -- `retrieve_okpd2_procurement` (`read`): Получить общероссийский классификатор продукции по видам экономической деятельности (ОКПД2) - -### Resource `okveds`: - -- `list_okveds` (`read`): Получить справочник ОКВЭДов - -### Resource `licenses`: - -- `list_licenses` (`read`): Получить справочник кодов и типов лицензий - -### Resource `lease_classifier`: - -- `retrieve_lease_classifier` (`read`): Получить классификатор лизинговых договоров: код лизинга, его наименование и количество заключенных договоров с данным кодом - -### Resource `counterparty`: - -- `retrieve_counterparty` (`read`): Получить общую информацию о контрагенте из ЕГРЮЛ/ЕГРИП. Конкретное наполнение зависит от переданных секций, описание которых приведено в параметрах запроса. - -### Resource `corporate_actions`: - -- `list_corporate_actions` (`read`): Получить данные о корпоративных действиях из ФедРесурса - -### Resource `blocked_bank_accounts`: - -- `list_blocked_bank_accounts` (`read`): Получить структурированные данные о решениях ФНС о приостановлении операций по счетам юридических лиц и ИП - -### Resource `bankruptcy`: - -- `retrieve_bankruptcy` (`read`): Получить признаки банкротства контрагента - -### Resource `arbitration_cases`: - -- `list_arbitration_cases` (`read`): Получить данные о судебных делах контрагента с возможностью фильтрации diff --git a/packages/mcp-server/manifest.json b/packages/mcp-server/manifest.json index 647c6ae..fcb0979 100644 --- a/packages/mcp-server/manifest.json +++ b/packages/mcp-server/manifest.json @@ -8,9 +8,9 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/stainless-sdks/datanewton-typescript.git" + "url": "git+https://github.com/AlexK420/mcpdata.git" }, - "homepage": "https://github.com/stainless-sdks/datanewton-typescript/tree/main/packages/mcp-server#readme", + "homepage": "https://github.com/AlexK420/mcpdata/tree/main/packages/mcp-server#readme", "server": { "type": "node", "entry_point": "index.js", diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 99dea7a..f38fd0c 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -1,6 +1,6 @@ { "name": "datanewton-mcp", - "version": "0.0.1", + "version": "0.1.0", "description": "The official MCP Server for the Datanewton API", "author": "Datanewton <>", "types": "dist/index.d.ts", @@ -8,10 +8,10 @@ "type": "commonjs", "repository": { "type": "git", - "url": "git+https://github.com/stainless-sdks/datanewton-typescript.git", + "url": "git+https://github.com/AlexK420/mcpdata.git", "directory": "packages/mcp-server" }, - "homepage": "https://github.com/stainless-sdks/datanewton-typescript/tree/main/packages/mcp-server#readme", + "homepage": "https://github.com/AlexK420/mcpdata/tree/main/packages/mcp-server#readme", "license": "Apache-2.0", "packageManager": "yarn@1.22.22", "private": false, @@ -32,12 +32,14 @@ "dependencies": { "datanewton": "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", - "jq-web": "https://github.com/stainless-api/jq-web/releases/download/v0.8.6/jq-web.tar.gz", + "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", + "typescript": "5.8.3", "yargs": "^17.7.2", "zod": "^3.25.20", "zod-to-json-schema": "^3.24.5", @@ -47,7 +49,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", @@ -64,8 +66,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": { "datanewton-mcp": ".", 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 15ce7f5..0000000 --- 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-types.ts b/packages/mcp-server/src/code-tool-types.ts index d43eea1..7b80387 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 deleted file mode 100644 index bcbb447..0000000 --- a/packages/mcp-server/src/code-tool-worker.ts +++ /dev/null @@ -1,46 +0,0 @@ -// 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 { Datanewton } from 'datanewton'; - -const fetch = async (req: Request): Promise => { - const { opts, code } = (await req.json()) as WorkerInput; - const client = new Datanewton({ - ...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 index e988339..ac6af47 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -1,145 +1,61 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { dirname } from 'node:path'; -import { pathToFileURL } from 'node:url'; -import Datanewton, { ClientOptions } from 'datanewton'; -import { Endpoint, ContentBlock, Metadata } from './tools/types'; - +import { McpTool, Metadata, ToolCallResult, asTextContentResult } from './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. * - * 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. * * @param endpoints - The endpoints to include in the list. */ -export async function codeTool(): Promise { +export function codeTool(): McpTool { 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.', + '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: Datanewton, 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), + 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({ + DATANEWTON_API_KEY: readEnv('DATANEWTON_API_KEY'), + DATANEWTON_BASE_URL: readEnv('DATANEWTON_BASE_URL'), + }), }, + body: JSON.stringify({ + project_name: 'datanewton', + client_opts: {}, + 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 && 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(); + 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/compat.ts b/packages/mcp-server/src/compat.ts deleted file mode 100644 index f84053c..0000000 --- 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 eb8d540..5e2bdd6 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'; @@ -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'], @@ -42,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()); }; diff --git a/packages/mcp-server/src/dynamic-tools.ts b/packages/mcp-server/src/dynamic-tools.ts deleted file mode 100644 index f501d94..0000000 --- a/packages/mcp-server/src/dynamic-tools.ts +++ /dev/null @@ -1,159 +0,0 @@ -import Datanewton from 'datanewton'; -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 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 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 Datanewton TypeScript API', - inputSchema: zodToInputSchema(listEndpointsSchema), - }, - handler: async ( - client: Datanewton, - 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 Datanewton 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: Datanewton, 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 Datanewton 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: Datanewton, - 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 1aa9a40..0000000 --- a/packages/mcp-server/src/filtering.ts +++ /dev/null @@ -1,14 +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); -} diff --git a/packages/mcp-server/src/headers.ts b/packages/mcp-server/src/headers.ts index c748993..4937a54 100644 --- a/packages/mcp-server/src/headers.ts +++ b/packages/mcp-server/src/headers.ts @@ -11,7 +11,9 @@ export const parseAuthHeaders = (req: IncomingMessage): Partial = case 'Bearer': return { apiKey: req.headers.authorization.slice('Bearer '.length) }; default: - throw new Error(`Unsupported authorization scheme`); + throw new Error( + 'Unsupported authorization scheme. Expected the "Authorization" header to be a supported scheme (Bearer).', + ); } } diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index ec34ab4..2366d8f 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,14 +27,13 @@ const newServer = ({ ...clientOptions, ...authOptions, }, - 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/index.ts b/packages/mcp-server/src/index.ts index 4850a0e..0f6dd42 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 4fe3b98..6c8bb8d 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, transport, port: argv.port, socket: argv.socket, @@ -284,183 +72,21 @@ 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(['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; return { - client: queryOptions.client ?? defaultOptions.client, - includeDynamicTools: dynamicTools, - includeAllTools: allTools, - includeCodeTools: undefined, includeDocsTools: docsTools, - filters, - capabilities: clientCapabilities, }; } - -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 0feb3c9..b82c011 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -2,39 +2,26 @@ 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 'datanewton'; import Datanewton from 'datanewton'; -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 'datanewton'; -export { endpoints } from './tools'; export const newMcpServer = () => new McpServer( { name: 'datanewton_api', - version: '0.0.1', + version: '0.1.0', }, { capabilities: { tools: {}, logging: {} } }, ); @@ -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') => @@ -96,26 +64,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) => { @@ -145,47 +110,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: Datanewton, 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 d902a5b..f07696f 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 7e516de..0000000 --- a/packages/mcp-server/src/tools.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './tools/index'; diff --git a/packages/mcp-server/src/tools/arbitration-cases/list-arbitration-cases.ts b/packages/mcp-server/src/tools/arbitration-cases/list-arbitration-cases.ts deleted file mode 100644 index dce7396..0000000 --- a/packages/mcp-server/src/tools/arbitration-cases/list-arbitration-cases.ts +++ /dev/null @@ -1,118 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'arbitration_cases', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/arbitrationCases', - operationId: '5_getArbitrationCase_1', -}; - -export const tool: Tool = { - name: 'list_arbitration_cases', - description: 'Получить данные о судебных делах контрагента с возможностью фильтрации\n', - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - company_role: { - type: 'string', - description: - 'Роль компании \n\n**Возможные значения**:\n- `RESPONDENT` - Ответчик\n- `PLAINTIFF` - Истец\n- `THIRD_PARTY` - Третье лицо\n- `INTERESTED_PERSONS` - Заинтересованное лицо\n- `CREDITOR` - Кредитор\n- `APPLICANT` - Заявитель\n- `OTHER` - Иное лицо\n- `ALL` - Все', - enum: [ - 'RESPONDENT', - 'PLAINTIFF', - 'THIRD_PARTY', - 'INTERESTED_PERSONS', - 'CREDITOR', - 'APPLICANT', - 'DEBTOR', - 'CREDITOR_CURRENT_PAYMENTS', - 'OTHER', - 'ALL', - ], - }, - dispute: { - type: 'string', - description: - 'Арбитражный спор \n\n**Возможные значения**:\n- `ABSENT` - отсутствует(0)\n- `HAS_LEGAL_SIGNIFICANCE` - об установлении фактов, имеющих юридическое значение(1)\n- `ADMINISTRATIVE_OFFENCES` - об административных правонарушениях(2)\n- `CIVIL_LAW_DISPUTES` - экономические споры по гражданским правоотношениям(3)\n- `BANKRUPTCY_ORGANIZATIONS_AND_CITIZENS` - о несостоятельности (банкротстве) организаций и граждан(4)\n- `ECONOMIC_DISPUTES_ON_PUBLIC_LEGAL_RELATIONS` - (экономические споры по административным и иным публичным правоотношениям (исключая споры об административных правонарушениях)(5)\n- `ENFORCMENT_OF_FOREIGN_JUDGMENTS` - о признании и приведении в исполнение решений иностранных судов и иностранных арбитражных решений(6)\n- `OTHER` - иное(7)\n- `ADMINISTRATIVE_DISPUTE` - административный спор(8)\n- `CHALLENGING_COURT_DECISIONS` - об оспаривании решений трет. судов и о выдаче исп. листов на принудительное исполнение решений трет. судов(9)\n- `DISCIPLINARY_DISPUTES` - дисциплинарные споры(10)\n- `ECONOMIC_DISPUTES` - экономические споры по административным правоотношениям(11)', - enum: [ - 'ABSENT', - 'HAS_LEGAL_SIGNIFICANCE', - 'ADMINISTRATIVE_OFFENCES', - 'CIVIL_LAW_DISPUTES', - 'BANKRUPTCY_ORGANIZATIONS_AND_CITIZENS', - 'ECONOMIC_DISPUTES_ON_PUBLIC_LEGAL_RELATIONS', - 'ENFORCMENT_OF_FOREIGN_JUDGMENTS', - 'OTHER', - 'ADMINISTRATIVE_DISPUTE', - 'CHALLENGING_COURT_DECISIONS', - 'DISCIPLINARY_DISPUTES', - 'ECONOMIC_DISPUTES', - ], - }, - end_date: { - type: 'string', - description: 'Дата окончания дела.', - }, - inn: { - type: 'string', - description: 'ИНН организации или ИП. Должен быть указан, если не указан ОГРН/ОГРНИП.', - }, - limit: { - type: 'integer', - description: 'Количество сообщений на странице(максимум 1000).', - }, - need_document: { - type: 'boolean', - description: 'Возвращать список документов вынесенных судом или поданных сторонами.', - }, - offset: { - type: 'integer', - description: 'Отступ страницы', - }, - ogrn: { - type: 'string', - description: 'ОГРН или ОГРНИП. Должен быть указан, если не указан ИНН.', - }, - start_date: { - type: 'string', - description: 'Дата начала дела.', - }, - status: { - type: 'string', - description: - 'Статус дела \n\n**Возможные значения**:\n- `OPEN` - Дело рассматривается(0)\n- `CLOSE` - Дело завершено(1)', - enum: ['CLOSE', 'OPEN'], - }, - updated_at_from: { - type: 'string', - description: 'Дата изменения с', - }, - year: { - type: 'string', - description: 'Год дела.', - }, - }, - required: ['key'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const body = args as any; - return asTextContentResult(await client.arbitrationCases.list(body)); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/arbitration/batch-cases/create-arbitration-batch-cases.ts b/packages/mcp-server/src/tools/arbitration/batch-cases/create-arbitration-batch-cases.ts deleted file mode 100644 index ab44d0e..0000000 --- a/packages/mcp-server/src/tools/arbitration/batch-cases/create-arbitration-batch-cases.ts +++ /dev/null @@ -1,137 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'arbitration.batch_cases', - operation: 'write', - tags: [], - httpMethod: 'post', - httpPath: '/v1/arbitration/batchCases', - operationId: '26_getBatchCases_1', -}; - -export const tool: Tool = { - name: 'create_arbitration_batch_cases', - description: 'Получить данные об арбитражных делах с возможностью фильтрации', - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - limit: { - type: 'integer', - description: - 'Лимит запрошенных арбитражных дел в запросе (значение должно быть > 0, обязательный для заполнения параметр)', - }, - offset: { - type: 'integer', - description: - 'Смещение (для пагинации, отступ в указанное количество дел) (значение должно быть >= 0, обязательный для заполнения параметр)', - }, - case_num: { - type: 'string', - description: 'Номер дела', - }, - court: { - type: 'string', - description: 'Наименование суда', - }, - dispute: { - type: 'string', - description: - 'Арбитражный спор.\n\n**Допустимые значения:**\n- `0` - Отсутствует\n- `1` - Об установлении фактов, имеющих юридическое значение\n- `2` - Об административных правонарушениях\n- `3` - Экономические споры по гражданским правоотношениям\n- `4` - О несостоятельности (банкротстве) организаций и граждан\n- `5` - Экономические споры по административным и иным публичным правоотношениям (исключая споры об административных правонарушениях)\n- `6` - О признании и приведении в исполнение решений иностранных судов и иностранных арбитражных решений\n- `7` - Иное\n- `8` - Административный спор\n- `9` - Об оспаривании решений трет. судов и о выдаче исп. листов на принудительное исполнение решений трет. судов\n- `10` - Дисциплинарные споры\n- `11` - Экономические споры по административным правоотношениям', - enum: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'], - }, - doc_type: { - type: 'string', - description: - 'Тип документа.\n\n**Допустимые значения:**\n- `Определение`\n- `Заявление`\n- `Решения и постановления`\n- `Заявление (исковое заявление)`\n- `Решение`\n- `Прочие судебные документы`\n- `Жалоба`\n- `Апелляционная жалоба`\n- `Постановление апелляционной инстанции`\n- `Информация о принятом судебном акте`\n- `Письмо`\n- `Решение в виде резолютивной части (ст. 229 АПК)`\n- `Решение (резолютивная часть)`\n- `Судебный приказ`\n- `Постановление кассационной инстанции`\n- `Кассационная жалоба`\n- `Постановление апелляционной инстанции (резолютивная часть)`\n- `Определение (резолютивная часть)`\n- `Определение (протокольное)`\n- `Ходатайства`\n- `Ходатайство (заявление)`\n- `Судебное поручение`\n- `Постановление кассационной инстанции (резолютивная часть)`\n- `Определение в виде резолютивной части (ст. 229 АПК)`\n- `Постановление апелляции`\n- `Постановление кассации`\n- `Определение в виде резолютивной части (ст. 229 АПК, ст. 60 ФЗ О несостоятельности)`\n- `Жалоба на определение суда кассационной инстанции`\n- `События`\n- `Постановление апелляционной инстанции (дополнительное)`\n- `Запрос`\n- `Исполнительный лист`\n- `Определение Верховного Суда РФ`\n- `Постановление кассационной инстанции (дополнительное)`\n- `Решение (дополнительное - резолютивная часть)`\n- `Дополнение к делу`\n- `Определение Судебной коллегии ВС РФ`\n- `Ответ заявителю`\n- `Постановление Президиума ВАС РФ`\n- `Постановление апелляционной инстанции (дополнительное - резолютивная часть)`\n- `Решение (дополнительное)`\n- `Отзыв на …`\n- `Переписка по делу`\n- `Представления`\n- `Протокол`\n- `Материалы по делу`\n- `Получение дела`\n- `Переадресация дела`\n- `Справка на возврат госпошлины`\n- `Судебный приказ (дубликат)`\n- `Отзыв`\n- `Постановление судебного пристава-исполнителя`\n- `Распоряжение председателя суда (председателя судебной коллегии, председателя судебного состава)`\n- `Дополнительное решение`\n- `Постановление Верховного Суда РФ`\n- `Взыскание госпошлины`\n- `Исполнительный лист (дубликат)`\n- `Постановление СПИ`\n- `Постановление кассационной инстанции (дополнительное - резолютивная часть)`\n- `Событие`', - }, - need_document: { - type: 'boolean', - description: 'Включение документов в ответ', - }, - order: { - type: 'string', - description: - 'Направление сортировки.\n\n**Допустимые значения:**\n- `ASC` – возрастание\n- `DESC` – убывание (по умолчанию)', - enum: ['ASC', 'DESC'], - }, - participant: { - type: 'string', - description: 'Участник дела (наименование, ОГРН, ИНН)', - }, - role: { - type: 'string', - description: - 'Роль участника в деле.\n\n**Допустимые значения:**\n- `RESPONDENT` – Ответчик\n- `PLAINTIFF` – Истец\n- `THIRD_PARTY` – Третье лицо\n- `INTERESTED_PERSONS` – Заинтересованное лицо\n- `CREDITOR` – Кредитор\n- `APPLICANT` – Заявитель\n- `DEBTOR` – Должник\n- `CREDITOR_CURRENT_PAYMENTS` – Кредитор по текущим платежам\n- `OTHER` – Иная роль в деле', - enum: [ - 'RESPONDENT', - 'PLAINTIFF', - 'THIRD_PARTY', - 'INTERESTED_PERSONS', - 'CREDITOR', - 'APPLICANT', - 'DEBTOR', - 'CREDITOR_CURRENT_PAYMENTS', - 'OTHER', - ], - }, - sort: { - type: 'string', - description: - 'Поле для сортировки арбитражных дел\n\n**Допустимые значения:**\n- `date_start` – дата начала дела (по умолчанию)\n- `sum` – цена иска', - enum: ['date_start', 'sum'], - }, - start_date_from: { - type: 'string', - description: 'Нижняя граница диапазона даты начала дела (дата начала дела с, в формате YYYY-MM-DD)', - format: 'date', - }, - start_date_to: { - type: 'string', - description: 'Верхняя граница диапазона даты начала дела (дата начала дела по, в формате YYYY-MM-DD)', - format: 'date', - }, - status: { - type: 'string', - description: - 'Статус дела.\n\n**Допустимые значения:**\n- `0` - Дело рассматривается\n- `1` - Дело завершено', - enum: ['0', '1'], - }, - sum_from: { - type: 'integer', - description: 'Нижняя граница диапазона цены иска (сумма от)', - }, - sum_to: { - type: 'integer', - description: 'Верхняя граница диапазона цены иска (сумма до)', - }, - updated_at_from: { - type: 'string', - description: 'Нижняя граница периода обновления арбитражных дел (в формате YYYY-MM-DD)', - format: 'date', - }, - updated_at_to: { - type: 'string', - description: 'Верхняя граница периода обновления арбитражных дел (в формате YYYY-MM-DD)', - format: 'date', - }, - }, - required: ['key', 'limit', 'offset'], - }, - annotations: {}, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const body = args as any; - return asTextContentResult(await client.arbitration.batchCases.create(body)); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/arbitration/get-courts-arbitration.ts b/packages/mcp-server/src/tools/arbitration/get-courts-arbitration.ts deleted file mode 100644 index 930918f..0000000 --- a/packages/mcp-server/src/tools/arbitration/get-courts-arbitration.ts +++ /dev/null @@ -1,44 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'arbitration', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/arbitration/courts-dictionary', - operationId: '28_getArbitrationCasesCourtsDictionary_1', -}; - -export const tool: Tool = { - name: 'get_courts_arbitration', - 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\nПолучить справочник арбитражных судов: полный список наименований арбитражных судов РФ и количество дел, рассмотренных и рассматриваемых в данных инстанциях\n\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/arbitration_get_courts_response',\n $defs: {\n arbitration_get_courts_response: {\n type: 'object',\n description: 'Статистика по арбитражного суда',\n properties: {\n count: {\n type: 'integer',\n description: 'Количество рассмотренных и рассматриваемых арбитражных дел в данной инстанции'\n },\n name: {\n type: 'string',\n description: 'Наименование арбитражного суда (инстанции)'\n }\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: Datanewton, args: Record | undefined) => { - const { jq_filter } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.arbitration.getCourts())); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/arbitration/get-dispute-categories-arbitration.ts b/packages/mcp-server/src/tools/arbitration/get-dispute-categories-arbitration.ts deleted file mode 100644 index bc7c5a1..0000000 --- a/packages/mcp-server/src/tools/arbitration/get-dispute-categories-arbitration.ts +++ /dev/null @@ -1,44 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'arbitration', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/arbitration/dispute-categories-dictionary', - operationId: '30_getArbitrationCasesDisputesDictionary_1', -}; - -export const tool: Tool = { - name: 'get_dispute_categories_arbitration', - 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\nПолучить справочник арбитражных споров (категорий), относящихся к компетенции арбитражных судов: категории споров и количество дел в данных категориях\n\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/arbitration_get_dispute_categories_response',\n $defs: {\n arbitration_get_dispute_categories_response: {\n type: 'object',\n description: 'Статистика по категории спора в арбитражных делах',\n properties: {\n code: {\n type: 'string',\n description: 'Код категории спора'\n },\n count: {\n type: 'integer',\n description: 'Количество рассмотренных и рассматриваемых арбитражных дел в данной категории'\n },\n name: {\n type: 'string',\n description: 'Наименование категории спора'\n }\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: Datanewton, args: Record | undefined) => { - const { jq_filter } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.arbitration.getDisputeCategories())); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/arbitration/get-document-types-arbitration.ts b/packages/mcp-server/src/tools/arbitration/get-document-types-arbitration.ts deleted file mode 100644 index 91e1ec8..0000000 --- a/packages/mcp-server/src/tools/arbitration/get-document-types-arbitration.ts +++ /dev/null @@ -1,44 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'arbitration', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/arbitration/document-types-dictionary', - operationId: '29_getArbitrationCasesDocTypesDictionary_1', -}; - -export const tool: Tool = { - name: 'get_document_types_arbitration', - 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\nПолучить справочник типов документов арбитражных дел: полный список документов (судебных актов), изданных арбитражными судами, а также их количество\n\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/arbitration_get_document_types_response',\n $defs: {\n arbitration_get_document_types_response: {\n type: 'object',\n description: 'Статистика по типу документов в арбитражных делах',\n properties: {\n count: {\n type: 'integer',\n description: 'Количество оформленных документов данного типа'\n },\n name: {\n type: 'string',\n description: 'Наименование судебного акта (тип документа)'\n }\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: Datanewton, args: Record | undefined) => { - const { jq_filter } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.arbitration.getDocumentTypes())); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/bankruptcy/retrieve-bankruptcy.ts b/packages/mcp-server/src/tools/bankruptcy/retrieve-bankruptcy.ts deleted file mode 100644 index db9a2e9..0000000 --- a/packages/mcp-server/src/tools/bankruptcy/retrieve-bankruptcy.ts +++ /dev/null @@ -1,64 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'bankruptcy', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/bankruptcy', - operationId: '17_getBankruptcy', -}; - -export const tool: Tool = { - name: 'retrieve_bankruptcy', - 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\nПолучить признаки банкротства контрагента\n\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/bankruptcy_retrieve_response',\n $defs: {\n bankruptcy_retrieve_response: {\n type: 'object',\n description: 'Ответ: банкротства',\n properties: {\n available_count: {\n type: 'integer',\n description: 'Количество доступных запросов'\n },\n data: {\n type: 'array',\n description: 'Данные',\n items: {\n type: 'object',\n description: 'Банкротство',\n properties: {\n content: {\n type: 'string',\n description: 'Текст сообщения'\n },\n guid: {\n type: 'string',\n description: 'GUID сообщения'\n },\n number: {\n type: 'string',\n description: 'Номер сообщения'\n },\n participants: {\n type: 'array',\n description: 'Участники сообщения, лица упомянутые в сообщении',\n items: {\n type: 'object',\n description: 'Участник',\n properties: {\n full_name: {\n type: 'string',\n description: 'Наименование/ФИО'\n },\n inn: {\n type: 'string',\n description: 'ИНН'\n },\n ogrn: {\n type: 'string',\n description: 'ОГРН/ОГРНИП'\n },\n role: {\n type: 'string',\n description: 'Роль участника (не заполняется для публикатора)',\n enum: [ 'Mortgagor',\n 'Mortgagee',\n 'Guarantor',\n 'Principal',\n 'Beneficiary',\n 'OtherGuaranteeContractor',\n 'Lessor',\n 'Lessee',\n 'MonetaryClient',\n 'MonetaryDebtor',\n 'FinancialAgent',\n 'Seller',\n 'Buyer',\n 'Grantor',\n 'Concessionaire',\n 'EstateOwner',\n 'Debtor',\n 'CommonParticipant',\n 'ReorganizationCompany',\n 'Sro',\n 'Expert',\n 'Creditor',\n 'Appraiser',\n 'Customer',\n 'Owner',\n 'Auditee',\n 'Auditor',\n 'Renter',\n 'Landlord',\n 'Founder',\n 'ParticipantWithRightToBuyBack',\n 'ObligedParty',\n 'ParticipantInterestedInRightsRestriction',\n 'ParticipantWithRestrictedRights',\n 'ParticipantHoldingItem',\n 'DebtCollector',\n 'Organizer',\n 'ControllingPerson',\n 'ControlledNonResidentCompany',\n 'Company',\n 'TradeOrganizer'\n ]\n },\n type: {\n type: 'string',\n description: 'Тип участника',\n enum: [ 'Company',\n 'IndividualEntrepreneur',\n 'Person',\n 'Appraiser',\n 'NonResidentCompany',\n 'ForeignSystem',\n 'Notary'\n ]\n }\n }\n }\n },\n publish_date: {\n type: 'string',\n description: 'Дата публикации сообщения'\n },\n publisher: {\n type: 'object',\n description: 'Участник',\n properties: {\n full_name: {\n type: 'string',\n description: 'Наименование/ФИО'\n },\n inn: {\n type: 'string',\n description: 'ИНН'\n },\n ogrn: {\n type: 'string',\n description: 'ОГРН/ОГРНИП'\n },\n role: {\n type: 'string',\n description: 'Роль участника (не заполняется для публикатора)',\n enum: [ 'Mortgagor',\n 'Mortgagee',\n 'Guarantor',\n 'Principal',\n 'Beneficiary',\n 'OtherGuaranteeContractor',\n 'Lessor',\n 'Lessee',\n 'MonetaryClient',\n 'MonetaryDebtor',\n 'FinancialAgent',\n 'Seller',\n 'Buyer',\n 'Grantor',\n 'Concessionaire',\n 'EstateOwner',\n 'Debtor',\n 'CommonParticipant',\n 'ReorganizationCompany',\n 'Sro',\n 'Expert',\n 'Creditor',\n 'Appraiser',\n 'Customer',\n 'Owner',\n 'Auditee',\n 'Auditor',\n 'Renter',\n 'Landlord',\n 'Founder',\n 'ParticipantWithRightToBuyBack',\n 'ObligedParty',\n 'ParticipantInterestedInRightsRestriction',\n 'ParticipantWithRestrictedRights',\n 'ParticipantHoldingItem',\n 'DebtCollector',\n 'Organizer',\n 'ControllingPerson',\n 'ControlledNonResidentCompany',\n 'Company',\n 'TradeOrganizer'\n ]\n },\n type: {\n type: 'string',\n description: 'Тип участника',\n enum: [ 'Company',\n 'IndividualEntrepreneur',\n 'Person',\n 'Appraiser',\n 'NonResidentCompany',\n 'ForeignSystem',\n 'Notary'\n ]\n }\n }\n },\n type_description: {\n type: 'string',\n description: 'Тип сообщения (описание)'\n },\n type_name: {\n type: 'string',\n description: 'Тип сообщения',\n enum: [ 'CreditorIntentionGoToCourt',\n 'DebtorIntentionGoToCourt',\n 'BankruptcyArticle8',\n 'BankruptcyArticle9',\n 'AssetImpairment',\n 'AppearanceOfBankruptcySigns',\n 'DebtorBankruptcyCourtNotification',\n 'FirmSupervisionPutIn',\n 'MoratoriumRejection'\n ]\n }\n }\n }\n },\n limit: {\n type: 'integer',\n description: 'Размер страницы'\n },\n offset: {\n type: 'integer',\n description: 'Смещение страницы'\n },\n total: {\n type: 'integer',\n description: 'Всего записей'\n }\n }\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - inn: { - type: 'string', - description: 'ИНН организации или ИП. Должен быть указан, если не указан ОГРН/ОГРНИП.', - }, - limit: { - type: 'integer', - description: 'Количество договоров на странице(максимум 1000).', - }, - offset: { - type: 'integer', - description: 'Отступ страницы', - }, - ogrn: { - type: 'string', - description: 'ОГРН или ОГРНИП. Должен быть указан, если не указан ИНН.', - }, - 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: ['key'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.bankruptcy.retrieve(body))); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/batch-cards-by-filters/create-batch-cards-by-filters.ts b/packages/mcp-server/src/tools/batch-cards-by-filters/create-batch-cards-by-filters.ts deleted file mode 100644 index dc945ee..0000000 --- a/packages/mcp-server/src/tools/batch-cards-by-filters/create-batch-cards-by-filters.ts +++ /dev/null @@ -1,509 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'batch_cards_by_filters', - operation: 'write', - tags: [], - httpMethod: 'post', - httpPath: '/v1/batchCardsByFilters', - operationId: '18_batchCounterpartiesByFilters', -}; - -export const tool: Tool = { - name: 'create_batch_cards_by_filters', - description: 'Получить данные контрагентов по фильтрам/условиям: оквэды, регионы и т.д.', - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - limit: { - type: 'integer', - description: 'Лимит.', - }, - offset: { - type: 'integer', - description: 'Оффсет.', - }, - contact_conditions_operator: { - type: 'string', - description: - 'Тип объединения условий контактной информации (AND - все условия должны выполняться, OR - хотя бы одно)', - enum: ['AND', 'OR'], - }, - contracts: { - type: 'object', - description: 'Запрос по контрактам', - properties: { - contract_date_from: { - type: 'string', - description: 'Дата заключения контракта: С (включительно)', - format: 'date', - }, - contract_date_to: { - type: 'string', - description: 'Дата заключения контракта: По (включительно)', - format: 'date', - }, - contract_type: { - type: 'string', - description: 'Тип контракта (FZ44, FZ223 и др.)', - enum: ['FZ44', 'FZ223', 'ALL'], - }, - has_contracts: { - type: 'boolean', - description: 'Наличие контрактов', - }, - max_price: { - type: 'number', - description: 'Максимальная сумма контракта', - }, - min_price: { - type: 'number', - description: 'Минимальная сумма контракта', - }, - okpd2_codes: { - type: 'array', - description: 'Коды ОКПД2 предмета контракта', - items: { - type: 'string', - description: 'Коды ОКПД2 предмета контракта', - }, - }, - only_active: { - type: 'boolean', - description: 'Только активные контракты', - }, - region_code: { - type: 'string', - description: 'Регион (код субъекта РФ)', - }, - role: { - type: 'string', - description: 'Роль контрагента', - enum: ['SUPPLIER', 'CUSTOMER'], - }, - search_terms: { - type: 'array', - description: 'Поисковые термины (каждый элемент — отдельное условие ИЛИ)', - items: { - type: 'string', - description: 'Поисковые термины (каждый элемент — отдельное условие ИЛИ)', - }, - }, - search_text: { - type: 'string', - description: 'Ключевые слова для поиска в предмете контракта', - }, - }, - }, - counterparty_type: { - type: 'string', - description: 'Возможные типы контрагентов', - enum: ['ul', 'ip', 'fl', 'all'], - }, - egr_statuses: { - type: 'array', - description: 'Статус компании в ЕГРЮЛ', - items: { - type: 'string', - description: 'Статус компании в ЕГРЮЛ', - }, - }, - establishment_date_from: { - type: 'string', - description: 'Дата создания компании: с', - format: 'date', - }, - establishment_date_to: { - type: 'string', - description: 'Дата создания компании: по', - format: 'date', - }, - exclude_okveds: { - type: 'array', - description: - 'Исключить список ОКВЭД (компаний с какими оквэдами быть не должно) для выгрузки. По умолчанию применяется только к основным ОКВЭД, для применения к дополнительным необходимо устанавливать свойство exclude_only_main_okveds = false.', - items: { - type: 'string', - description: - 'Исключить список ОКВЭД (компаний с какими оквэдами быть не должно) для выгрузки. По умолчанию применяется только к основным ОКВЭД, для применения к дополнительным необходимо устанавливать свойство exclude_only_main_okveds = false.', - }, - }, - exclude_only_main_okveds: { - type: 'boolean', - description: - 'Применять поле exclude_okveds только к основным ОКВЭД компаний. По умолчанию true - исключать из выборке только те компании, у которых значения exclude_okveds среди основных ОКВЭД', - }, - finance_report_year: { - type: 'integer', - description: - 'По какому отчетному финансовому году применяем фильтр по выручке/прибыли. Если 0, то смотрим за последний известный год (когда компания подавала отчетность)', - }, - finance_request: { - type: 'object', - description: 'Запрос по финансам', - properties: { - metrics: { - type: 'array', - description: 'Финансовые метрики для анализа', - items: { - type: 'string', - description: 'Финансовые метрики для анализа', - enum: ['Выручка', 'Чистая прибыль', 'INCOME', 'NET_INCOME'], - }, - }, - growth_from: { - type: 'number', - description: 'Динамика выбранных метрик: рост от (в %)', - }, - growth_to: { - type: 'number', - description: 'Динамика выбранных метрик: рост до (в %)', - }, - year_by_year: { - type: 'boolean', - description: - 'Применять условия по росту к каждому году (год к году), а не только к первому и последнему', - }, - years_count: { - type: 'integer', - description: 'Количество лет для анализа динамики', - }, - }, - required: ['metrics'], - }, - has_income: { - type: 'boolean', - description: 'Флаг - выгружать только те, у которых есть выручка', - }, - income_from: { - type: 'number', - description: 'Выручка за последний год (в тыс. рублей): с', - }, - income_to: { - type: 'number', - description: 'Выручка за последний год (в тыс. рублей): по', - }, - leases: { - type: 'object', - description: 'Запрос по договорам лизинга', - properties: { - role: { - type: 'string', - description: 'Роль контрагента', - enum: ['Lessor', 'Lessee'], - }, - classifier_codes: { - type: 'array', - description: 'Коды типа лизинга из классификатора (справочника)', - items: { - type: 'string', - description: 'Коды типа лизинга из классификатора (справочника)', - }, - }, - contract_date_from: { - type: 'string', - description: 'Дата заключения договора: С (включительно)', - format: 'date', - }, - contract_date_to: { - type: 'string', - description: 'Дата заключения договора: По (включительно)', - format: 'date', - }, - excluded_text: { - type: 'string', - description: 'Слова-исключения в реквизитах договора', - }, - has_leases: { - type: 'boolean', - description: 'Наличие договоров лизинга', - }, - only_active: { - type: 'boolean', - description: 'Только активные договора', - }, - search_terms: { - type: 'array', - description: 'Поисковые термины (каждый элемент — отдельное условие ИЛИ) в реквизитах договора ', - items: { - type: 'string', - description: - 'Поисковые термины (каждый элемент — отдельное условие ИЛИ) в реквизитах договора ', - }, - }, - search_text: { - type: 'string', - description: 'Ключевые слова для поиска в реквизитах договора', - }, - stop_date_from: { - type: 'string', - description: 'Дата прекращения договора: С (включительно)', - format: 'date', - }, - stop_date_to: { - type: 'string', - description: 'Дата прекращения договора: По (включительно)', - format: 'date', - }, - }, - required: ['role'], - }, - licenses: { - type: 'array', - description: 'Список номеров лицензий', - items: { - type: 'integer', - description: 'Список номеров лицензий', - }, - }, - msp_categories: { - type: 'array', - description: - 'Категории МСП. Возможные варианты: 0 - не в МСП (никогда не состоял или вышел), 1 - микропредприятие, 2 - малое предприятие, 3 - среднее предприятие ', - items: { - type: 'string', - description: - 'Категории МСП. Возможные варианты: 0 - не в МСП (никогда не состоял или вышел), 1 - микропредприятие, 2 - малое предприятие, 3 - среднее предприятие ', - }, - }, - net_income_from: { - type: 'number', - description: 'Прибыль за последний год (в тыс. рублей): с', - }, - net_income_to: { - type: 'number', - description: 'Прибыль за последний год (в тыс. рублей): по', - }, - okveds: { - type: 'array', - description: 'Список ОКВЭД для выгрузки', - items: { - type: 'string', - description: 'Список ОКВЭД для выгрузки', - }, - }, - only_active: { - type: 'boolean', - description: 'Флаг - только действующие компании', - }, - only_it_companies: { - type: 'boolean', - description: 'Вернуть только аккредитованные ИТ-компании', - }, - only_main_okveds: { - type: 'boolean', - description: - 'Поиск указанных в поле "okveds" видов деятельности среди основных ОКВЭДов компаний. По умолчанию true.', - }, - only_msp_innovative: { - type: 'boolean', - description: 'Производство инновационной, высокотехнологичной продукции', - }, - only_msp_partner: { - type: 'boolean', - description: 'Является партнером', - }, - only_msp_social: { - type: 'boolean', - description: 'Социальное предприятие', - }, - only_nopriz_members: { - type: 'boolean', - description: 'Только члены СРО НОПРИЗ', - }, - only_nostroy_members: { - type: 'boolean', - description: 'Только члены СРО НОСТРОЙ', - }, - only_with_bfo: { - type: 'boolean', - description: 'Только с наличием данных БФО за выбранный год', - }, - only_with_emails: { - type: 'boolean', - description: 'Наличие у контрагента минимум одной электронной почты', - }, - only_with_phones: { - type: 'boolean', - description: 'Наличие у контрагента минимум одного номера телефона', - }, - only_with_websites: { - type: 'boolean', - description: 'Наличие у контрагента минимум одного сайта', - }, - opf_codes: { - type: 'array', - description: 'Код ОПФ или тип контрагента (ip, ul)', - items: { - type: 'string', - description: 'Код ОПФ или тип контрагента (ip, ul)', - }, - }, - region_codes: { - type: 'array', - description: 'Коды регионов', - items: { - type: 'string', - description: 'Коды регионов', - }, - }, - rosaccreditations: { - type: 'object', - description: 'Реестр деклараций/сертификатов соответствия', - properties: { - applicant_type: { - type: 'array', - description: 'Тип заявителя', - items: { - type: 'string', - description: 'Тип заявителя', - enum: [ - 'Продавец', - 'Изготовитель', - 'Иcполнитель', - 'Уполномоченное изготовителем лицо', - 'Поставщик', - ], - }, - }, - description: { - type: 'string', - description: 'Слова в описании документа Росаккредитации', - }, - search_terms: { - type: 'array', - description: - 'Поисковые термины (каждый элемент — отдельное условие ИЛИ) в описании документа Росаккредитации ', - items: { - type: 'string', - description: - 'Поисковые термины (каждый элемент — отдельное условие ИЛИ) в описании документа Росаккредитации ', - }, - }, - statuses: { - type: 'array', - description: 'Статус декларации или сертификата', - items: { - type: 'string', - description: 'Статус декларации или сертификата', - enum: [ - 'Архивный', - 'Возобновлён', - 'Выдано предписание', - 'Действует', - 'Недействителен', - 'Прекращён', - 'Приостановлен', - 'Продлен', - 'Направлено уведомление о прекращении', - 'Черновик', - 'Ожидает проверки оператора реестра', - ], - }, - }, - type: { - type: 'string', - description: 'Тип документа', - enum: ['Декларация', 'Сертификат', 'Декларация или сертификат'], - }, - }, - }, - search_terms: { - type: 'array', - description: 'Поисковые термины (каждый элемент — отдельное условие ИЛИ) для свободного поиска ', - items: { - type: 'string', - description: 'Поисковые термины (каждый элемент — отдельное условие ИЛИ) для свободного поиска ', - }, - }, - search_text: { - type: 'string', - description: 'Свободное поле поиска', - }, - ssch_from: { - type: 'integer', - description: 'Численность сотрудников: от', - }, - ssch_to: { - type: 'integer', - description: 'Численность сотрудников: по', - }, - support_forms: { - type: 'array', - description: 'Список видов/форм поддержки', - items: { - type: 'integer', - description: 'Список видов/форм поддержки', - }, - }, - vacancies: { - type: 'object', - description: 'Запрос по вакансиям', - properties: { - excluded_text: { - type: 'string', - description: 'Слово в названии или описании вакансии, которого быть не должно', - }, - has_vacancies: { - type: 'boolean', - description: 'Наличие вакансий', - }, - only_active: { - type: 'boolean', - description: 'Вакансия должна быть активной', - }, - only_name: { - type: 'boolean', - description: - 'Искать поисковые слова/термины (или слова исключения) только в названии вакансии (без описания). То есть, применять условия text, search_terms, excluded_text только к названию вакансии (значение true) или к названию и описанию (значение false, по умолчанию)', - }, - salary_max: { - type: 'number', - description: 'Зарплата: до', - }, - salary_min: { - type: 'number', - description: 'Зарплата: от', - }, - search_terms: { - type: 'array', - description: - 'Поисковые термины (каждый элемент — отдельное условие ИЛИ) в названии или описании вакансии', - items: { - type: 'string', - description: - 'Поисковые термины (каждый элемент — отдельное условие ИЛИ) в названии или описании вакансии', - }, - }, - source: { - type: 'string', - description: 'Источник вакансий', - enum: ['HH_VACANCIES', 'VACANCIES', 'ALL'], - }, - text: { - type: 'string', - description: 'Слово в названии или описании вакансии', - }, - }, - }, - }, - required: ['key', 'limit', 'offset'], - }, - annotations: {}, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const body = args as any; - return asTextContentResult(await client.batchCardsByFilters.create(body)); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/batch-cards/create-batch-cards.ts b/packages/mcp-server/src/tools/batch-cards/create-batch-cards.ts deleted file mode 100644 index dccc8e3..0000000 --- a/packages/mcp-server/src/tools/batch-cards/create-batch-cards.ts +++ /dev/null @@ -1,45 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'batch_cards', - operation: 'write', - tags: [], - httpMethod: 'post', - httpPath: '/v1/batchCards', - operationId: '3_getBatchCounterpatriesByInnsOrOgrns', -}; - -export const tool: Tool = { - name: 'create_batch_cards', - description: - 'Получить информацию о нескольких организациях одним запросом (до 5 000 контрагентов в запросе), отправив список ИНН/ОГРН', - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - source_inns_or_ogrns: { - type: 'array', - items: { - type: 'string', - }, - }, - }, - required: ['key'], - }, - annotations: {}, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const body = args as any; - return asTextContentResult(await client.batchCards.create(body)); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/batch-changes/create-batch-changes.ts b/packages/mcp-server/src/tools/batch-changes/create-batch-changes.ts deleted file mode 100644 index 1f07498..0000000 --- a/packages/mcp-server/src/tools/batch-changes/create-batch-changes.ts +++ /dev/null @@ -1,109 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'batch_changes', - operation: 'write', - tags: [], - httpMethod: 'post', - httpPath: '/v1/batchChanges', - operationId: '4_getBatchCompanyChanges', -}; - -export const tool: Tool = { - name: 'create_batch_changes', - description: - 'Получить изменения по списку контрагентов с определенной даты. \nМожно смотреть изменения за день, за неделю, за квартал, а также за произвольный период времени. \nМожно получить историю изменений выбранных параметров за произвольный период времени. \nОтслеживаются:\n- ИНН, ОГРН, КПП\n- Статус по ЕГРЮЛ/ЕГРИП\n- Название:\n - Полное\n - Краткое\n - Организационно-правовая форма (ОПФ)\n - Код ОПФ по ЕГРЮЛ\n- Адрес местонахождения\n- Единоличный исполнительный орган:\n - Руководитель\n - Управляющая компания\n- Участники\n- Уставный капитал:\n - Размер\n - Тип\n- Реестр МСП:\n - Статус\n - Категория отнесения\n- Недостоверность:\n - Учредителей\n - Руководителей\n - Управляющей компании\n - Адреса\n- Дисквалификация:\n - Учредителей\n - Руководителей\n- Налоговые режимы\n- Бухгалтерская (финансовая) отчетность\n- ОКВЭД (добавление, изменение, удаление)\n\nМаксимальное количество контрагентов в одном запросе - 500.\nДля получения ключа к этой точке API [напишите нам](mailto:info@datanomica.org).', - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - include_history: { - type: 'boolean', - description: 'Включить историю изменений параметра', - }, - ogrns: { - type: 'array', - description: 'ОГРН компаний, по которым нужно получить изменения', - items: { - type: 'string', - description: 'ОГРН компаний, по которым нужно получить изменения', - }, - }, - param_types: { - type: 'array', - description: - 'Параметры мониторинга. \n**Возможные значения типа изменений**:\n- `REPORT` — Бух/Фин отчетность (публикация нового отчета);\n- `MSP_STATUS` — статус МСП;\n- `MSP_CATEGORY` — категория МСП;\n- `MANAGEMENT_COMPANY` — данные управляющей компании;\n- `OGRN` — ОГРН;\n- `INN` — ИНН;\n- `KPP` — КПП;\n- `FULL_NAME` — полное наименования компании;\n- `SHORT_NAME` — краткое наименования компании;\n- `OPF` — ОПФ (организационно-правовой формы) компании;\n- `OPF_CODE` — код ОПФ;\n- `ADDRESS_FALSE_INFO` — признак недостоверности адреса;\n- `OKVED` — ОКВЭД;\n- `OWNERS` — участники;\n- `MANAGERS` — руководители;\n- `EGR_STATUS` — статус организации в ЕГРЮЛ/ЕГРИП;\n- `COUNTERPARTY_CREATION` — факт создания организации;\n- `REG_ADDRESS` — адрес местонахождения организации;\n- `CAPITAL_TABLE_SIZE` — размер уставного капитала;\n- `CAPITAL_TABLE_TYPE` — тип уставного капитала;\n- `DISQUALIFIED_OWNER` — дисквалификация участника;\n- `DISQUALIFIED_MANAGER` — дисквалификация руководителей;\n- `OWNERS_FALSE_INFO` — признак недостоверности участников;\n- `MANAGERS_FALSE_INFO` — признак недостоверности руководителей;\n- `MANAGEMENT_COMPANY_FALSE_INFO` — признак недостоверности управляющей компании;\n- `TAX_MODE_ESHN_SIGN` — налоговый режим (ЕСХН);\n- `TAX_MODE_USN_SIGN` — налоговый режим (УСН);\n- `TAX_MODE_ENVD_SIGN` — налоговый режим (ЕНДВ);\n- `TAX_MODE_SRP_SIGN` — налоговый режим (СРП);\n- `TAX_MODE_AUSN_SIGN` — налоговый режим (АУСН);\n- `ALL` — все параметры', - items: { - type: 'string', - description: - 'Параметры мониторинга. \n**Возможные значения типа изменений**:\n- `REPORT` — Бух/Фин отчетность (публикация нового отчета);\n- `MSP_STATUS` — статус МСП;\n- `MSP_CATEGORY` — категория МСП;\n- `MANAGEMENT_COMPANY` — данные управляющей компании;\n- `OGRN` — ОГРН;\n- `INN` — ИНН;\n- `KPP` — КПП;\n- `FULL_NAME` — полное наименования компании;\n- `SHORT_NAME` — краткое наименования компании;\n- `OPF` — ОПФ (организационно-правовой формы) компании;\n- `OPF_CODE` — код ОПФ;\n- `ADDRESS_FALSE_INFO` — признак недостоверности адреса;\n- `OKVED` — ОКВЭД;\n- `OWNERS` — участники;\n- `MANAGERS` — руководители;\n- `EGR_STATUS` — статус организации в ЕГРЮЛ/ЕГРИП;\n- `COUNTERPARTY_CREATION` — факт создания организации;\n- `REG_ADDRESS` — адрес местонахождения организации;\n- `CAPITAL_TABLE_SIZE` — размер уставного капитала;\n- `CAPITAL_TABLE_TYPE` — тип уставного капитала;\n- `DISQUALIFIED_OWNER` — дисквалификация участника;\n- `DISQUALIFIED_MANAGER` — дисквалификация руководителей;\n- `OWNERS_FALSE_INFO` — признак недостоверности участников;\n- `MANAGERS_FALSE_INFO` — признак недостоверности руководителей;\n- `MANAGEMENT_COMPANY_FALSE_INFO` — признак недостоверности управляющей компании;\n- `TAX_MODE_ESHN_SIGN` — налоговый режим (ЕСХН);\n- `TAX_MODE_USN_SIGN` — налоговый режим (УСН);\n- `TAX_MODE_ENVD_SIGN` — налоговый режим (ЕНДВ);\n- `TAX_MODE_SRP_SIGN` — налоговый режим (СРП);\n- `TAX_MODE_AUSN_SIGN` — налоговый режим (АУСН);\n- `ALL` — все параметры', - enum: [ - 'REPORT', - 'MSP_STATUS', - 'MSP_CATEGORY', - 'MANAGEMENT_COMPANY', - 'OGRN', - 'INN', - 'KPP', - 'FULL_NAME', - 'SHORT_NAME', - 'OPF', - 'OPF_CODE', - 'ADDRESS_FALSE_INFO', - 'OKVED', - 'OWNERS', - 'MANAGERS', - 'EGR_STATUS', - 'COUNTERPARTY_CREATION', - 'REG_ADDRESS', - 'CAPITAL_TABLE_SIZE', - 'CAPITAL_TABLE_TYPE', - 'DISQUALIFIED_OWNER', - 'DISQUALIFIED_MANAGER', - 'OWNERS_FALSE_INFO', - 'MANAGERS_FALSE_INFO', - 'MANAGEMENT_COMPANY_FALSE_INFO', - 'TAX_MODE_ESHN_SIGN', - 'TAX_MODE_USN_SIGN', - 'TAX_MODE_ENVD_SIGN', - 'TAX_MODE_SRP_SIGN', - 'TAX_MODE_AUSN_SIGN', - 'BANKRUPTCY', - 'CASE_RESPONDENT', - 'CASE_PLAINTIFF', - 'CASE_THIRD_PARTY', - 'CASE_INTERESTED_PERSONS', - 'CASE_CREDITOR', - 'CASE_APPLICANT', - 'CASE_DEBTOR', - 'CASE_CREDITOR_CURRENT_PAYMENTS', - 'CASE_OTHER', - 'ALL', - ], - }, - }, - start_date: { - type: 'string', - description: 'Дата начала мониторинга изменений', - format: 'date', - }, - }, - required: ['key'], - }, - annotations: {}, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const body = args as any; - return asTextContentResult(await client.batchChanges.create(body)); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/blocked-bank-accounts/list-blocked-bank-accounts.ts b/packages/mcp-server/src/tools/blocked-bank-accounts/list-blocked-bank-accounts.ts deleted file mode 100644 index f816ec3..0000000 --- a/packages/mcp-server/src/tools/blocked-bank-accounts/list-blocked-bank-accounts.ts +++ /dev/null @@ -1,56 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'blocked_bank_accounts', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/blockedBankAccounts', - operationId: '31_getBlockedBankAccounts', -}; - -export const tool: Tool = { - name: 'list_blocked_bank_accounts', - 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\nПолучить структурированные данные о решениях ФНС о приостановлении операций по счетам юридических лиц и ИП\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/blocked_bank_account_list_response',\n $defs: {\n blocked_bank_account_list_response: {\n type: 'object',\n description: 'Информация о решениях налоговых органов о приостановлении операций по счетам компании',\n properties: {\n available_count: {\n type: 'integer',\n description: 'Количество доступных запросов'\n },\n blockages: {\n type: 'array',\n description: 'Информация о блокировках',\n items: {\n type: 'object',\n description: 'Информация о блокировке',\n properties: {\n bank_bic: {\n type: 'string',\n description: 'БИК банка'\n },\n code_tax_inspection: {\n type: 'string',\n description: 'Код налогового органа'\n },\n decision_date: {\n type: 'string',\n description: 'Дата приостановления операции по счетам',\n format: 'date'\n },\n decision_number: {\n type: 'string',\n description: 'Номер приостановления операции по счетам'\n },\n reason_code: {\n type: 'string',\n description: 'Код основания'\n }\n }\n }\n },\n check_date: {\n type: 'string',\n description: 'Дата и время выполнения live-запроса в ФНС',\n format: 'date-time'\n },\n inn: {\n type: 'string',\n description: 'ИНН, по которому получены данные'\n },\n message: {\n type: 'string',\n description: 'Сообщение о наличии блокировок'\n },\n ogrn: {\n type: 'string',\n description: 'ОГРН, по которому получены данные'\n },\n total_blockages_count: {\n type: 'integer',\n description: 'Общее количество найденных записей'\n }\n }\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - inn: { - type: 'string', - description: 'ИНН организации. Должен быть указан, если не указан ОГРН.', - }, - ogrn: { - type: 'string', - description: 'ОГРН или ОГРНИП. Должен быть указан, если не указан ИНН.', - }, - 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: ['key'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.blockedBankAccounts.list(body))); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/corporate-actions/list-corporate-actions.ts b/packages/mcp-server/src/tools/corporate-actions/list-corporate-actions.ts deleted file mode 100644 index dd176be..0000000 --- a/packages/mcp-server/src/tools/corporate-actions/list-corporate-actions.ts +++ /dev/null @@ -1,94 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'corporate_actions', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/corporateActions', - operationId: '12_getFedResource', -}; - -export const tool: Tool = { - name: 'list_corporate_actions', - description: 'Получить данные о корпоративных действиях из ФедРесурса\n', - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - date_from: { - type: 'string', - description: 'Дата публикации от', - }, - date_to: { - type: 'string', - description: 'Дата публикации до', - }, - group: { - type: 'string', - description: 'Группа типов: CapitalChange | RegisterAction | Shareholders | Other', - enum: ['CapitalChange', 'RegisterAction', 'Shareholders', 'Other'], - }, - inn: { - type: 'string', - description: 'ИНН организации или ИП. Должен быть указан, если не указан ОГРН/ОГРНИП.', - }, - limit: { - type: 'integer', - description: 'Количество сообщений на странице(максимум 1000).', - }, - offset: { - type: 'integer', - description: 'Отступ страницы', - }, - ogrn: { - type: 'string', - description: 'ОГРН или ОГРНИП. Должен быть указан, если не указан ИНН.', - }, - type: { - type: 'string', - description: 'Тип сообщения: FirmAuthorizedCapitalDecrease | FirmAuthorizedCapitalIncrease |...', - enum: [ - 'FirmAuthorizedCapitalDecrease', - 'FirmAuthorizedCapitalIncrease', - 'FirmSharesAcquisition', - 'FirmLiquidation', - 'FirmReorganization', - 'FirmRegisterExcludeTermination', - 'FirmAutonomousInstitutionCreation', - 'FirmCreated', - 'FirmRegisterExclude', - 'StopOfBusiness', - 'FirmAuthoritiesChange', - 'UnreliableInformation', - 'IntentionExerciseTheRightsOfShareholderNonResident', - 'SatisfactionExerciseTheRightsOfShareholderNonResident', - 'FirmMembersMeeting', - 'SaleOrLeaseEnterprise', - 'AnyOther', - 'RevocationOfPowerAttorney', - 'IntentionInheritanceOfLandProperty', - ], - }, - }, - required: ['key'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const body = args as any; - return asTextContentResult(await client.corporateActions.list(body)); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/counterparty/retrieve-counterparty.ts b/packages/mcp-server/src/tools/counterparty/retrieve-counterparty.ts deleted file mode 100644 index 169aa04..0000000 --- a/packages/mcp-server/src/tools/counterparty/retrieve-counterparty.ts +++ /dev/null @@ -1,68 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'counterparty', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/counterparty', - operationId: '1_getCompanyData', -}; - -export const tool: Tool = { - name: 'retrieve_counterparty', - description: - 'Получить общую информацию о контрагенте из ЕГРЮЛ/ЕГРИП. Конкретное наполнение зависит от переданных секций, описание которых приведено в параметрах запроса.', - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - filters: { - type: 'array', - description: - 'Перечень дополнительных секций с данными, которые нужно включить в ответ, разделённые запятой.\nЕсли не указан, то возвращается общая информация об организации (названия, дата регистрации, КПП, статус, уставный капитал).\n**Возможные значения**:\n- `ROSSTAT_BLOCK` — данные о кодах Росстата (ОКПО, ОКАТО, ОКФС, ОКТМО, ОКОГУ, ОКОПФ);\n- `ADDRESS_BLOCK` — данные о юридическом адресе и отметках из ЕГРЮЛ;\n- `MANAGER_BLOCK` — данные о руководителях организации, имеющих право действовать от имени ЮЛ без доверенности;\n- `OWNER_BLOCK` — данные об учредителях и участниках организации (физических лицах, российских ЮЛ, иностранных ЮЛ, ПИФах, государственных учреждениях и субъектах РФ, инвестиционных товариществах);\n- `OKVED_BLOCK` — данные об основных и дополнительных видах экономической деятельности (кодах ОКВЭД) организации;\n- `NEGATIVE_LISTS_BLOCK` — данные о присутствии контрагента (в том числе руководителей, учредителей) в негативных списках: дисквалификация, недостоверные сведения, РНП и т.д.;\n- `WORKERS_COUNT_BLOCK` — данные о среднесписочной численности сотрудников по годам;\n- `CONTACT_BLOCK` — данные о контактах (email, web-сайт, телефон)', - items: { - type: 'string', - enum: [ - 'ROSSTAT_BLOCK', - 'ADDRESS_BLOCK', - 'MANAGER_BLOCK', - 'OWNER_BLOCK', - 'OKVED_BLOCK', - 'NEGATIVE_LISTS_BLOCK', - 'WORKERS_COUNT_BLOCK', - 'CONTACT_BLOCK', - ], - }, - }, - inn: { - type: 'string', - description: - 'ИНН организации или ИП. Должен быть указан, если не указан ОГРН/ОГРНИП. В случае определения нескольких организаций с этим ИНН (например, при наличии филиалов) будет возвращена информация по головной организации.', - }, - ogrn: { - type: 'string', - description: 'ОГРН или ОГРНИП. Должен быть указан, если не указан ИНН.', - }, - }, - required: ['key'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const body = args as any; - return asTextContentResult(await client.counterparty.retrieve(body)); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/dictionary/arbitration/list-courts-dictionary-arbitration.ts b/packages/mcp-server/src/tools/dictionary/arbitration/list-courts-dictionary-arbitration.ts deleted file mode 100644 index bddf04d..0000000 --- a/packages/mcp-server/src/tools/dictionary/arbitration/list-courts-dictionary-arbitration.ts +++ /dev/null @@ -1,44 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'dictionary.arbitration', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/dictionary/arbitration/courts', - operationId: '28_getArbitrationCasesCourtsDictionary', -}; - -export const tool: Tool = { - name: 'list_courts_dictionary_arbitration', - 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\nПолучить справочник арбитражных судов: полный список наименований арбитражных судов РФ и количество дел, рассмотренных и рассматриваемых в данных инстанциях\n\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/arbitration_list_courts_response',\n $defs: {\n arbitration_list_courts_response: {\n type: 'object',\n description: 'Статистика по арбитражного суда',\n properties: {\n count: {\n type: 'integer',\n description: 'Количество рассмотренных и рассматриваемых арбитражных дел в данной инстанции'\n },\n name: {\n type: 'string',\n description: 'Наименование арбитражного суда (инстанции)'\n }\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: Datanewton, args: Record | undefined) => { - const { jq_filter } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.dictionary.arbitration.listCourts())); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/dictionary/arbitration/list-dispute-categories-dictionary-arbitration.ts b/packages/mcp-server/src/tools/dictionary/arbitration/list-dispute-categories-dictionary-arbitration.ts deleted file mode 100644 index 6c4dd38..0000000 --- a/packages/mcp-server/src/tools/dictionary/arbitration/list-dispute-categories-dictionary-arbitration.ts +++ /dev/null @@ -1,46 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'dictionary.arbitration', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/dictionary/arbitration/dispute-categories', - operationId: '30_getArbitrationCasesDisputesDictionary', -}; - -export const tool: Tool = { - name: 'list_dispute_categories_dictionary_arbitration', - 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\nПолучить справочник арбитражных споров (категорий), относящихся к компетенции арбитражных судов: категории споров и количество дел в данных категориях\n\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/arbitration_list_dispute_categories_response',\n $defs: {\n arbitration_list_dispute_categories_response: {\n type: 'object',\n description: 'Статистика по категории спора в арбитражных делах',\n properties: {\n code: {\n type: 'string',\n description: 'Код категории спора'\n },\n count: {\n type: 'integer',\n description: 'Количество рассмотренных и рассматриваемых арбитражных дел в данной категории'\n },\n name: {\n type: 'string',\n description: 'Наименование категории спора'\n }\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: Datanewton, args: Record | undefined) => { - const { jq_filter } = args as any; - return asTextContentResult( - await maybeFilter(jq_filter, await client.dictionary.arbitration.listDisputeCategories()), - ); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/dictionary/arbitration/list-document-types-dictionary-arbitration.ts b/packages/mcp-server/src/tools/dictionary/arbitration/list-document-types-dictionary-arbitration.ts deleted file mode 100644 index 500abb4..0000000 --- a/packages/mcp-server/src/tools/dictionary/arbitration/list-document-types-dictionary-arbitration.ts +++ /dev/null @@ -1,46 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'dictionary.arbitration', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/dictionary/arbitration/document-types', - operationId: '29_getArbitrationCasesDocTypesDictionary', -}; - -export const tool: Tool = { - name: 'list_document_types_dictionary_arbitration', - 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\nПолучить справочник типов документов арбитражных дел: полный список документов (судебных актов), изданных арбитражными судами, а также их количество\n\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/arbitration_list_document_types_response',\n $defs: {\n arbitration_list_document_types_response: {\n type: 'object',\n description: 'Статистика по типу документов в арбитражных делах',\n properties: {\n count: {\n type: 'integer',\n description: 'Количество оформленных документов данного типа'\n },\n name: {\n type: 'string',\n description: 'Наименование судебного акта (тип документа)'\n }\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: Datanewton, args: Record | undefined) => { - const { jq_filter } = args as any; - return asTextContentResult( - await maybeFilter(jq_filter, await client.dictionary.arbitration.listDocumentTypes()), - ); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/dictionary/list-lease-classifier-dictionary.ts b/packages/mcp-server/src/tools/dictionary/list-lease-classifier-dictionary.ts deleted file mode 100644 index 766ac12..0000000 --- a/packages/mcp-server/src/tools/dictionary/list-lease-classifier-dictionary.ts +++ /dev/null @@ -1,44 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'dictionary', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/dictionary/lease-classifier', - operationId: '24_getLeaseClassifierDictionary_1', -}; - -export const tool: Tool = { - name: 'list_lease_classifier_dictionary', - 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\nПолучить классификатор лизинговых договоров: код лизинга, его наименование и количество заключенных договоров с данным кодом\n\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/dictionary_list_lease_classifier_response',\n $defs: {\n dictionary_list_lease_classifier_response: {\n type: 'object',\n properties: {\n data: {\n type: 'array',\n items: {\n type: 'object',\n description: 'Код - расшифровка - количество',\n properties: {\n code: {\n type: 'string',\n description: 'Значение кода'\n },\n count: {\n type: 'integer',\n description: 'Количество'\n },\n group: {\n type: 'string',\n description: 'Группа, к которой относится код'\n },\n group_code: {\n type: 'string',\n description: 'Код группы, к которой относится код'\n },\n name: {\n type: 'string',\n description: 'Расшифровка кода'\n },\n type: {\n type: 'string',\n description: 'Тип контрагента: ip или ul'\n }\n }\n }\n }\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: Datanewton, args: Record | undefined) => { - const { jq_filter } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.dictionary.listLeaseClassifier())); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/dictionary/list-licenses-dictionary.ts b/packages/mcp-server/src/tools/dictionary/list-licenses-dictionary.ts deleted file mode 100644 index 4886ca0..0000000 --- a/packages/mcp-server/src/tools/dictionary/list-licenses-dictionary.ts +++ /dev/null @@ -1,44 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'dictionary', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/dictionary/licenses', - operationId: '23_getLicensesDictionary_1', -}; - -export const tool: Tool = { - name: 'list_licenses_dictionary', - 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\nПолучить справочник кодов и типов лицензий\n\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/dictionary_list_licenses_response',\n $defs: {\n dictionary_list_licenses_response: {\n type: 'object',\n properties: {\n data: {\n type: 'array',\n items: {\n type: 'object',\n description: 'Код - расшифровка - количество',\n properties: {\n code: {\n type: 'string',\n description: 'Значение кода'\n },\n count: {\n type: 'integer',\n description: 'Количество'\n },\n group: {\n type: 'string',\n description: 'Группа, к которой относится код'\n },\n group_code: {\n type: 'string',\n description: 'Код группы, к которой относится код'\n },\n name: {\n type: 'string',\n description: 'Расшифровка кода'\n },\n type: {\n type: 'string',\n description: 'Тип контрагента: ip или ul'\n }\n }\n }\n }\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: Datanewton, args: Record | undefined) => { - const { jq_filter } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.dictionary.listLicenses())); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/dictionary/list-okveds-dictionary.ts b/packages/mcp-server/src/tools/dictionary/list-okveds-dictionary.ts deleted file mode 100644 index c492d2e..0000000 --- a/packages/mcp-server/src/tools/dictionary/list-okveds-dictionary.ts +++ /dev/null @@ -1,44 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'dictionary', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/dictionary/okveds', - operationId: '22_getOkvedsDictionary', -}; - -export const tool: Tool = { - name: 'list_okveds_dictionary', - 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\nПолучить справочник ОКВЭДов\n\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/dictionary_list_okveds_response',\n $defs: {\n dictionary_list_okveds_response: {\n type: 'object',\n description: 'ОКВЭД, имеет вложенную структуру',\n properties: {\n all_children_code: {\n type: 'array',\n items: {\n type: 'string'\n }\n },\n children: {\n type: 'array',\n description: 'Дочерние записи ОКВЭД',\n items: {\n $ref: '#/$defs/okved1'\n }\n },\n code: {\n type: 'string',\n description: 'Код ОКВЭД'\n },\n count: {\n type: 'integer',\n description: 'Количество действующих юридических лиц, у которых главный ОКВЭД равен name (с учетом дочерних)'\n },\n direct_count: {\n type: 'integer',\n description: 'Количество действующих юридических лиц, у которых главный ОКВЭД равен name (без учета дочерних)'\n },\n group: {\n type: 'string',\n description: 'Группа: A-U'\n },\n level: {\n type: 'integer'\n },\n name: {\n type: 'string',\n description: 'Наименование ОКВЭД'\n }\n }\n },\n okved1: {\n type: 'object',\n description: 'ОКВЭД, имеет вложенную структуру',\n properties: {\n all_children_code: {\n type: 'array',\n items: {\n type: 'string'\n }\n },\n children: {\n type: 'array',\n description: 'Дочерние записи ОКВЭД',\n items: {\n $ref: '#/$defs/okved1'\n }\n },\n code: {\n type: 'string',\n description: 'Код ОКВЭД'\n },\n count: {\n type: 'integer',\n description: 'Количество действующих юридических лиц, у которых главный ОКВЭД равен name (с учетом дочерних)'\n },\n direct_count: {\n type: 'integer',\n description: 'Количество действующих юридических лиц, у которых главный ОКВЭД равен name (без учета дочерних)'\n },\n group: {\n type: 'string',\n description: 'Группа: A-U'\n },\n level: {\n type: 'integer'\n },\n name: {\n type: 'string',\n description: 'Наименование ОКВЭД'\n }\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: Datanewton, args: Record | undefined) => { - const { jq_filter } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.dictionary.listOkveds())); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/dictionary/list-regions-dictionary.ts b/packages/mcp-server/src/tools/dictionary/list-regions-dictionary.ts deleted file mode 100644 index 4229be2..0000000 --- a/packages/mcp-server/src/tools/dictionary/list-regions-dictionary.ts +++ /dev/null @@ -1,44 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'dictionary', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/dictionary/regions', - operationId: '16_getRegionsDictionary_1', -}; - -export const tool: Tool = { - name: 'list_regions_dictionary', - 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\nПолучить справочник регионов России\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/dictionary_list_regions_response',\n $defs: {\n dictionary_list_regions_response: {\n type: 'object',\n description: 'Федеральный округ с регионами',\n properties: {\n name: {\n type: 'string'\n },\n regions: {\n type: 'array',\n items: {\n type: 'object',\n description: 'Регион',\n properties: {\n code: {\n type: 'string'\n },\n name: {\n type: 'string'\n }\n }\n }\n }\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: Datanewton, args: Record | undefined) => { - const { jq_filter } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.dictionary.listRegions())); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/dictionary/procurement/list-okpd2-dictionary-procurement.ts b/packages/mcp-server/src/tools/dictionary/procurement/list-okpd2-dictionary-procurement.ts deleted file mode 100644 index 18c35c9..0000000 --- a/packages/mcp-server/src/tools/dictionary/procurement/list-okpd2-dictionary-procurement.ts +++ /dev/null @@ -1,44 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'dictionary.procurement', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/dictionary/procurement/okpd2', - operationId: '27_getOkpd2Dictionary_1', -}; - -export const tool: Tool = { - name: 'list_okpd2_dictionary_procurement', - 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\nПолучить общероссийский классификатор продукции по видам экономической деятельности (ОКПД2)\n\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/procurement_list_okpd2_response',\n $defs: {\n procurement_list_okpd2_response: {\n type: 'object',\n properties: {\n data: {\n type: 'array',\n items: {\n type: 'object',\n description: 'Код - расшифровка - количество',\n properties: {\n code: {\n type: 'string',\n description: 'Значение кода'\n },\n count: {\n type: 'integer',\n description: 'Количество'\n },\n group: {\n type: 'string',\n description: 'Группа, к которой относится код'\n },\n group_code: {\n type: 'string',\n description: 'Код группы, к которой относится код'\n },\n name: {\n type: 'string',\n description: 'Расшифровка кода'\n },\n type: {\n type: 'string',\n description: 'Тип контрагента: ip или ul'\n }\n }\n }\n }\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: Datanewton, args: Record | undefined) => { - const { jq_filter } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.dictionary.procurement.listOkpd2())); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/filters-preview/create-filters-preview.ts b/packages/mcp-server/src/tools/filters-preview/create-filters-preview.ts deleted file mode 100644 index 485d330..0000000 --- a/packages/mcp-server/src/tools/filters-preview/create-filters-preview.ts +++ /dev/null @@ -1,509 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'filters_preview', - operation: 'write', - tags: [], - httpMethod: 'post', - httpPath: '/v1/filtersPreview', - operationId: '25_filtersPreview', -}; - -export const tool: Tool = { - name: 'create_filters_preview', - description: 'Получить краткую информацию (предпросмотр) по фильтрам/условиям: оквэд, регионы и т.д.', - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - limit: { - type: 'integer', - description: 'Лимит.', - }, - offset: { - type: 'integer', - description: 'Оффсет.', - }, - contact_conditions_operator: { - type: 'string', - description: - 'Тип объединения условий контактной информации (AND - все условия должны выполняться, OR - хотя бы одно)', - enum: ['AND', 'OR'], - }, - contracts: { - type: 'object', - description: 'Запрос по контрактам', - properties: { - contract_date_from: { - type: 'string', - description: 'Дата заключения контракта: С (включительно)', - format: 'date', - }, - contract_date_to: { - type: 'string', - description: 'Дата заключения контракта: По (включительно)', - format: 'date', - }, - contract_type: { - type: 'string', - description: 'Тип контракта (FZ44, FZ223 и др.)', - enum: ['FZ44', 'FZ223', 'ALL'], - }, - has_contracts: { - type: 'boolean', - description: 'Наличие контрактов', - }, - max_price: { - type: 'number', - description: 'Максимальная сумма контракта', - }, - min_price: { - type: 'number', - description: 'Минимальная сумма контракта', - }, - okpd2_codes: { - type: 'array', - description: 'Коды ОКПД2 предмета контракта', - items: { - type: 'string', - description: 'Коды ОКПД2 предмета контракта', - }, - }, - only_active: { - type: 'boolean', - description: 'Только активные контракты', - }, - region_code: { - type: 'string', - description: 'Регион (код субъекта РФ)', - }, - role: { - type: 'string', - description: 'Роль контрагента', - enum: ['SUPPLIER', 'CUSTOMER'], - }, - search_terms: { - type: 'array', - description: 'Поисковые термины (каждый элемент — отдельное условие ИЛИ)', - items: { - type: 'string', - description: 'Поисковые термины (каждый элемент — отдельное условие ИЛИ)', - }, - }, - search_text: { - type: 'string', - description: 'Ключевые слова для поиска в предмете контракта', - }, - }, - }, - counterparty_type: { - type: 'string', - description: 'Возможные типы контрагентов', - enum: ['ul', 'ip', 'fl', 'all'], - }, - egr_statuses: { - type: 'array', - description: 'Статус компании в ЕГРЮЛ', - items: { - type: 'string', - description: 'Статус компании в ЕГРЮЛ', - }, - }, - establishment_date_from: { - type: 'string', - description: 'Дата создания компании: с', - format: 'date', - }, - establishment_date_to: { - type: 'string', - description: 'Дата создания компании: по', - format: 'date', - }, - exclude_okveds: { - type: 'array', - description: - 'Исключить список ОКВЭД (компаний с какими оквэдами быть не должно) для выгрузки. По умолчанию применяется только к основным ОКВЭД, для применения к дополнительным необходимо устанавливать свойство exclude_only_main_okveds = false.', - items: { - type: 'string', - description: - 'Исключить список ОКВЭД (компаний с какими оквэдами быть не должно) для выгрузки. По умолчанию применяется только к основным ОКВЭД, для применения к дополнительным необходимо устанавливать свойство exclude_only_main_okveds = false.', - }, - }, - exclude_only_main_okveds: { - type: 'boolean', - description: - 'Применять поле exclude_okveds только к основным ОКВЭД компаний. По умолчанию true - исключать из выборке только те компании, у которых значения exclude_okveds среди основных ОКВЭД', - }, - finance_report_year: { - type: 'integer', - description: - 'По какому отчетному финансовому году применяем фильтр по выручке/прибыли. Если 0, то смотрим за последний известный год (когда компания подавала отчетность)', - }, - finance_request: { - type: 'object', - description: 'Запрос по финансам', - properties: { - metrics: { - type: 'array', - description: 'Финансовые метрики для анализа', - items: { - type: 'string', - description: 'Финансовые метрики для анализа', - enum: ['Выручка', 'Чистая прибыль', 'INCOME', 'NET_INCOME'], - }, - }, - growth_from: { - type: 'number', - description: 'Динамика выбранных метрик: рост от (в %)', - }, - growth_to: { - type: 'number', - description: 'Динамика выбранных метрик: рост до (в %)', - }, - year_by_year: { - type: 'boolean', - description: - 'Применять условия по росту к каждому году (год к году), а не только к первому и последнему', - }, - years_count: { - type: 'integer', - description: 'Количество лет для анализа динамики', - }, - }, - required: ['metrics'], - }, - has_income: { - type: 'boolean', - description: 'Флаг - выгружать только те, у которых есть выручка', - }, - income_from: { - type: 'number', - description: 'Выручка за последний год (в тыс. рублей): с', - }, - income_to: { - type: 'number', - description: 'Выручка за последний год (в тыс. рублей): по', - }, - leases: { - type: 'object', - description: 'Запрос по договорам лизинга', - properties: { - role: { - type: 'string', - description: 'Роль контрагента', - enum: ['Lessor', 'Lessee'], - }, - classifier_codes: { - type: 'array', - description: 'Коды типа лизинга из классификатора (справочника)', - items: { - type: 'string', - description: 'Коды типа лизинга из классификатора (справочника)', - }, - }, - contract_date_from: { - type: 'string', - description: 'Дата заключения договора: С (включительно)', - format: 'date', - }, - contract_date_to: { - type: 'string', - description: 'Дата заключения договора: По (включительно)', - format: 'date', - }, - excluded_text: { - type: 'string', - description: 'Слова-исключения в реквизитах договора', - }, - has_leases: { - type: 'boolean', - description: 'Наличие договоров лизинга', - }, - only_active: { - type: 'boolean', - description: 'Только активные договора', - }, - search_terms: { - type: 'array', - description: 'Поисковые термины (каждый элемент — отдельное условие ИЛИ) в реквизитах договора ', - items: { - type: 'string', - description: - 'Поисковые термины (каждый элемент — отдельное условие ИЛИ) в реквизитах договора ', - }, - }, - search_text: { - type: 'string', - description: 'Ключевые слова для поиска в реквизитах договора', - }, - stop_date_from: { - type: 'string', - description: 'Дата прекращения договора: С (включительно)', - format: 'date', - }, - stop_date_to: { - type: 'string', - description: 'Дата прекращения договора: По (включительно)', - format: 'date', - }, - }, - required: ['role'], - }, - licenses: { - type: 'array', - description: 'Список номеров лицензий', - items: { - type: 'integer', - description: 'Список номеров лицензий', - }, - }, - msp_categories: { - type: 'array', - description: - 'Категории МСП. Возможные варианты: 0 - не в МСП (никогда не состоял или вышел), 1 - микропредприятие, 2 - малое предприятие, 3 - среднее предприятие ', - items: { - type: 'string', - description: - 'Категории МСП. Возможные варианты: 0 - не в МСП (никогда не состоял или вышел), 1 - микропредприятие, 2 - малое предприятие, 3 - среднее предприятие ', - }, - }, - net_income_from: { - type: 'number', - description: 'Прибыль за последний год (в тыс. рублей): с', - }, - net_income_to: { - type: 'number', - description: 'Прибыль за последний год (в тыс. рублей): по', - }, - okveds: { - type: 'array', - description: 'Список ОКВЭД для выгрузки', - items: { - type: 'string', - description: 'Список ОКВЭД для выгрузки', - }, - }, - only_active: { - type: 'boolean', - description: 'Флаг - только действующие компании', - }, - only_it_companies: { - type: 'boolean', - description: 'Вернуть только аккредитованные ИТ-компании', - }, - only_main_okveds: { - type: 'boolean', - description: - 'Поиск указанных в поле "okveds" видов деятельности среди основных ОКВЭДов компаний. По умолчанию true.', - }, - only_msp_innovative: { - type: 'boolean', - description: 'Производство инновационной, высокотехнологичной продукции', - }, - only_msp_partner: { - type: 'boolean', - description: 'Является партнером', - }, - only_msp_social: { - type: 'boolean', - description: 'Социальное предприятие', - }, - only_nopriz_members: { - type: 'boolean', - description: 'Только члены СРО НОПРИЗ', - }, - only_nostroy_members: { - type: 'boolean', - description: 'Только члены СРО НОСТРОЙ', - }, - only_with_bfo: { - type: 'boolean', - description: 'Только с наличием данных БФО за выбранный год', - }, - only_with_emails: { - type: 'boolean', - description: 'Наличие у контрагента минимум одной электронной почты', - }, - only_with_phones: { - type: 'boolean', - description: 'Наличие у контрагента минимум одного номера телефона', - }, - only_with_websites: { - type: 'boolean', - description: 'Наличие у контрагента минимум одного сайта', - }, - opf_codes: { - type: 'array', - description: 'Код ОПФ или тип контрагента (ip, ul)', - items: { - type: 'string', - description: 'Код ОПФ или тип контрагента (ip, ul)', - }, - }, - region_codes: { - type: 'array', - description: 'Коды регионов', - items: { - type: 'string', - description: 'Коды регионов', - }, - }, - rosaccreditations: { - type: 'object', - description: 'Реестр деклараций/сертификатов соответствия', - properties: { - applicant_type: { - type: 'array', - description: 'Тип заявителя', - items: { - type: 'string', - description: 'Тип заявителя', - enum: [ - 'Продавец', - 'Изготовитель', - 'Иcполнитель', - 'Уполномоченное изготовителем лицо', - 'Поставщик', - ], - }, - }, - description: { - type: 'string', - description: 'Слова в описании документа Росаккредитации', - }, - search_terms: { - type: 'array', - description: - 'Поисковые термины (каждый элемент — отдельное условие ИЛИ) в описании документа Росаккредитации ', - items: { - type: 'string', - description: - 'Поисковые термины (каждый элемент — отдельное условие ИЛИ) в описании документа Росаккредитации ', - }, - }, - statuses: { - type: 'array', - description: 'Статус декларации или сертификата', - items: { - type: 'string', - description: 'Статус декларации или сертификата', - enum: [ - 'Архивный', - 'Возобновлён', - 'Выдано предписание', - 'Действует', - 'Недействителен', - 'Прекращён', - 'Приостановлен', - 'Продлен', - 'Направлено уведомление о прекращении', - 'Черновик', - 'Ожидает проверки оператора реестра', - ], - }, - }, - type: { - type: 'string', - description: 'Тип документа', - enum: ['Декларация', 'Сертификат', 'Декларация или сертификат'], - }, - }, - }, - search_terms: { - type: 'array', - description: 'Поисковые термины (каждый элемент — отдельное условие ИЛИ) для свободного поиска ', - items: { - type: 'string', - description: 'Поисковые термины (каждый элемент — отдельное условие ИЛИ) для свободного поиска ', - }, - }, - search_text: { - type: 'string', - description: 'Свободное поле поиска', - }, - ssch_from: { - type: 'integer', - description: 'Численность сотрудников: от', - }, - ssch_to: { - type: 'integer', - description: 'Численность сотрудников: по', - }, - support_forms: { - type: 'array', - description: 'Список видов/форм поддержки', - items: { - type: 'integer', - description: 'Список видов/форм поддержки', - }, - }, - vacancies: { - type: 'object', - description: 'Запрос по вакансиям', - properties: { - excluded_text: { - type: 'string', - description: 'Слово в названии или описании вакансии, которого быть не должно', - }, - has_vacancies: { - type: 'boolean', - description: 'Наличие вакансий', - }, - only_active: { - type: 'boolean', - description: 'Вакансия должна быть активной', - }, - only_name: { - type: 'boolean', - description: - 'Искать поисковые слова/термины (или слова исключения) только в названии вакансии (без описания). То есть, применять условия text, search_terms, excluded_text только к названию вакансии (значение true) или к названию и описанию (значение false, по умолчанию)', - }, - salary_max: { - type: 'number', - description: 'Зарплата: до', - }, - salary_min: { - type: 'number', - description: 'Зарплата: от', - }, - search_terms: { - type: 'array', - description: - 'Поисковые термины (каждый элемент — отдельное условие ИЛИ) в названии или описании вакансии', - items: { - type: 'string', - description: - 'Поисковые термины (каждый элемент — отдельное условие ИЛИ) в названии или описании вакансии', - }, - }, - source: { - type: 'string', - description: 'Источник вакансий', - enum: ['HH_VACANCIES', 'VACANCIES', 'ALL'], - }, - text: { - type: 'string', - description: 'Слово в названии или описании вакансии', - }, - }, - }, - }, - required: ['key', 'limit', 'offset'], - }, - annotations: {}, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const body = args as any; - return asTextContentResult(await client.filtersPreview.create(body)); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/finance/retrieve-finance.ts b/packages/mcp-server/src/tools/finance/retrieve-finance.ts deleted file mode 100644 index c67d1f0..0000000 --- a/packages/mcp-server/src/tools/finance/retrieve-finance.ts +++ /dev/null @@ -1,49 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'finance', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/finance', - operationId: '2_getFinanceInfo', -}; - -export const tool: Tool = { - name: 'retrieve_finance', - description: 'Получить данные отчетов о финансовых результатах организации', - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - inn: { - type: 'string', - description: - 'ИНН организации. Должен быть указан, если не указан ОГРН. В случае определения нескольких организаций с этим ИНН (например, при наличии филиалов) будет возвращена информация по головной организации.', - }, - ogrn: { - type: 'string', - description: 'ОГРН или ОГРНИП. Должен быть указан, если не указан ИНН.', - }, - }, - required: ['key'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const body = args as any; - return asTextContentResult(await client.finance.retrieve(body)); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/government-contracts-stat/retrieve-government-contracts-stat.ts b/packages/mcp-server/src/tools/government-contracts-stat/retrieve-government-contracts-stat.ts deleted file mode 100644 index 7664d29..0000000 --- a/packages/mcp-server/src/tools/government-contracts-stat/retrieve-government-contracts-stat.ts +++ /dev/null @@ -1,74 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'government_contracts_stat', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/governmentContractsStat', - operationId: '7_getGovernmentContractsStat', -}; - -export const tool: Tool = { - name: 'retrieve_government_contracts_stat', - 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\nПолучить статистику по госконтрактам контрагента по информации из ЕИС Закупки\n\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/government_contracts_stat_retrieve_response',\n $defs: {\n government_contracts_stat_retrieve_response: {\n type: 'object',\n description: 'Данные по статистике о госконтрактах',\n properties: {\n error: {\n type: 'object',\n description: 'Исключительная ситуация',\n properties: {\n code: {\n type: 'integer',\n description: 'Код ошибки. Например: 1 - контрагент по заданным параметрам не найден'\n },\n message: {\n type: 'string',\n description: 'Описание'\n },\n source: {\n type: 'object',\n description: 'Параметры - входные данные, вызвавшие исключительную ситуацию',\n additionalProperties: true\n }\n }\n },\n stat: {\n type: 'array',\n description: 'Статистика',\n items: {\n type: 'object',\n description: 'Статистика',\n properties: {\n amount: {\n type: 'integer',\n description: 'Количество контрактов'\n },\n count_with_penalty: {\n type: 'integer',\n description: 'Количество контрактов с неустойкой'\n },\n penalty_sum: {\n type: 'number',\n description: 'Сумма неустоек'\n },\n sum: {\n type: 'number',\n description: 'Сумма'\n },\n year: {\n type: 'string',\n description: 'Год'\n }\n }\n }\n },\n status_canceled: {\n type: 'integer',\n description: 'Аннулирован'\n },\n status_execution: {\n type: 'integer',\n description: 'Исполнение'\n },\n status_execution_completed: {\n type: 'integer',\n description: 'Исполнение завершено'\n },\n status_execution_terminated: {\n type: 'integer',\n description: 'Исполнение прекращено'\n }\n }\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - ogrn: { - type: 'string', - description: 'ОГРН или ОГРНИП. Должен быть указан, если не указан ИНН.', - }, - type: { - type: 'string', - description: - 'Тип госконтрактов\n**Возможные значения**:\n- `FZ44` - ФЗ-44\n- `FZ223` - ФЗ-223\n- `PP615` - ПП-615\n- `ALL` - Все типы', - enum: [ - 'FZ44', - 'FZ223', - 'PP615', - 'FZ44_API', - 'FZ223_API', - 'PP615_API', - 'P_FZ44', - 'P_FZ44_API', - 'P_FZ223_API', - 'P_PP615', - 'RNP_FZ44', - 'RNP_FZ223', - 'ALL', - ], - }, - 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: ['key', 'ogrn', 'type'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - return asTextContentResult( - await maybeFilter(jq_filter, await client.governmentContractsStat.retrieve(body)), - ); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/government-contracts/list-government-contracts.ts b/packages/mcp-server/src/tools/government-contracts/list-government-contracts.ts deleted file mode 100644 index 536bd65..0000000 --- a/packages/mcp-server/src/tools/government-contracts/list-government-contracts.ts +++ /dev/null @@ -1,163 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'government_contracts', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/governmentContracts', - operationId: '8_getGovernmentContracts', -}; - -export const tool: Tool = { - name: 'list_government_contracts', - description: 'Получить данные о госконтрактах контрагента по информации из ЕИС Закупки\n', - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - types: { - type: 'array', - description: - 'Тип госконтрактов (может быть несколько)\n\n\n\n**Возможные значения**:\n- `FZ44` - ФЗ-44\n- `FZ223` - ФЗ-223\n- `PP615` - ПП-615\n- `ALL` - Все типы', - items: { - type: 'string', - enum: ['FZ44', 'FZ223', 'ALL'], - }, - }, - company_name: { - type: 'string', - description: 'Наименование участника', - }, - end_date: { - type: 'string', - description: 'Дата конца действия контракта', - }, - inn: { - type: 'string', - description: 'ИНН организации или ИП. Должен быть указан, если не указан ОГРН/ОГРНИП.', - }, - limit: { - type: 'integer', - description: 'Количество дел на странице(максимум 1000).', - }, - offset: { - type: 'integer', - description: 'Отступ страницы.', - }, - ogrn: { - type: 'string', - description: 'ОГРН или ОГРНИП. Должен быть указан, если не указан ИНН.', - }, - order: { - type: 'string', - description: - 'Тип сортировки госконтрактов, если поле sort указано\n \n**Возможные значения**:\n- `ASC` - по возрастанию\n- `DESC` - по убыванию', - enum: ['ASC', 'DESC'], - }, - penalty_sum_high: { - type: 'number', - description: 'Сумма до', - }, - penalty_sum_low: { - type: 'number', - description: 'Сумма от', - }, - penalty_types: { - type: 'array', - description: 'Тип неустойки\n \n**Возможные значения**:\n\n\n- `F` - штраф\n- `I` - пени', - items: { - type: 'string', - description: 'Тип штрафа/неустойки', - enum: ['I', 'F'], - }, - }, - price_high: { - type: 'number', - description: 'Сумма до', - }, - price_low: { - type: 'number', - description: 'Сумма от', - }, - purchase_type_info_code: { - type: 'object', - properties: { - type: { - type: 'string', - description: - 'Способ закупки\n \n**Возможные значения**:\n\n\nдля FZ44: \n- `11011` - открытый конкурс\n- `11021` - конкурс с ограниченным участием\n- `11031` - двухэтапный конкурс\n- `12011` - электронный аукцион\n- `13011` - запрос котировок\n- `14011` - запрос предложений\n- `20000` - закупка у единственного поставщика (подрядчика, исполнителя)\n- `30000` - способ определения поставщика (подрядчика, исполнителя),\n установленный Правительством Российской Федерации\n в соответствии со статьей 111 Федерального закона\n- `11044` - закрытый конкурс в электронной форме\n- `11054` - закрытый конкурс с ограниченным участием в электронной форме\n- `11064` - закрытый двухэтапный конкурс в электронной форме\n- `12024` - закрытый аукцион в электронной форме\n- `40000` - закупка товара у единственного поставщика на сумму, предусмотренную частью 12 статьи 93 Закона № 44-ФЗ\n \nдля FZ223: \n- `11011` - конкурс\n- `12012` - аукцион\n- `30000` - закупка у единственного поставщика/подрядчика/исполнителя\n- `40000` - иной способ закупки, предусмотренный правовым актом заказчика, указанным в части 1 статьи 2 Федерального закона\n \nдля PP615: \n- `12011` - электронный аукцион', - enum: [ - '11011', - '11021', - '11031', - '11044', - '11054', - '11064', - '12011', - '12012', - '12024', - '13011', - '14011', - '20000', - '30000', - '40000', - ], - }, - }, - }, - reg_number: { - type: 'string', - description: 'Номер закупки или контракта', - }, - role: { - type: 'string', - description: - 'Роль компании в контракте\n\n\n\n**Возможные значения**:\n- `CUSTOMER` - Заказчик\n- `SUPPLIER` - Поставщик\n- `ALL` - Все роли', - enum: ['CUSTOMER', 'SUPPLIER', 'ALL'], - }, - sort: { - type: 'string', - description: - 'Поле для сортировки госконтрактов\n \n**Возможные значения**:\n- `DATE` - по дате\n- `PRICE` - по цене', - enum: ['DATE', 'PRICE'], - }, - start_date: { - type: 'string', - description: 'Дата начала действия контракта', - }, - statuses: { - type: 'array', - description: - 'Статусы контракта\n \n**Возможные значения**:\n- `E` - Исполнение\n- `IN` - Аннулирован\n- `EC` - Исполнение завершено\n- `ET` - Исполнение прекращено', - items: { - type: 'string', - enum: ['E', 'IN', 'EC', 'ET'], - }, - }, - subject_contract: { - type: 'string', - description: 'Предмет контракта', - }, - }, - required: ['key', 'types'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const body = args as any; - return asTextContentResult(await client.governmentContracts.list(body)); -}; - -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 d7bb33c..0000000 --- a/packages/mcp-server/src/tools/index.ts +++ /dev/null @@ -1,149 +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 create_taxpayer_statuses from './taxpayer-statuses/create-taxpayer-statuses'; -import create_suggestions from './suggestions/create-suggestions'; -import create_ogrns_by_address from './ogrns-by-address/create-ogrns-by-address'; -import create_leases from './leases/create-leases'; -import create_filters_preview from './filters-preview/create-filters-preview'; -import create_batch_changes from './batch-changes/create-batch-changes'; -import create_batch_cards from './batch-cards/create-batch-cards'; -import create_batch_cards_by_filters from './batch-cards-by-filters/create-batch-cards-by-filters'; -import get_courts_arbitration from './arbitration/get-courts-arbitration'; -import get_dispute_categories_arbitration from './arbitration/get-dispute-categories-arbitration'; -import get_document_types_arbitration from './arbitration/get-document-types-arbitration'; -import create_arbitration_batch_cases from './arbitration/batch-cases/create-arbitration-batch-cases'; -import retrieve_tax_info from './tax-info/retrieve-tax-info'; -import retrieve_sro_membership from './sro-membership/retrieve-sro-membership'; -import list_risks from './risks/list-risks'; -import list_paid_taxes from './paid-taxes/list-paid-taxes'; -import list_okpd_list from './okpd-list/list-okpd-list'; -import retrieve_nko_reestr from './nko-reestr/retrieve-nko-reestr'; -import list_links from './links/list-links'; -import list_government_contracts from './government-contracts/list-government-contracts'; -import retrieve_government_contracts_stat from './government-contracts-stat/retrieve-government-contracts-stat'; -import retrieve_finance from './finance/retrieve-finance'; -import list_regions from './regions/list-regions'; -import list_lease_classifier_dictionary from './dictionary/list-lease-classifier-dictionary'; -import list_licenses_dictionary from './dictionary/list-licenses-dictionary'; -import list_okveds_dictionary from './dictionary/list-okveds-dictionary'; -import list_regions_dictionary from './dictionary/list-regions-dictionary'; -import list_okpd2_dictionary_procurement from './dictionary/procurement/list-okpd2-dictionary-procurement'; -import list_courts_dictionary_arbitration from './dictionary/arbitration/list-courts-dictionary-arbitration'; -import list_dispute_categories_dictionary_arbitration from './dictionary/arbitration/list-dispute-categories-dictionary-arbitration'; -import list_document_types_dictionary_arbitration from './dictionary/arbitration/list-document-types-dictionary-arbitration'; -import retrieve_okpd2_procurement from './procurement/retrieve-okpd2-procurement'; -import list_okveds from './okveds/list-okveds'; -import list_licenses from './licenses/list-licenses'; -import retrieve_lease_classifier from './lease-classifier/retrieve-lease-classifier'; -import retrieve_counterparty from './counterparty/retrieve-counterparty'; -import list_corporate_actions from './corporate-actions/list-corporate-actions'; -import list_blocked_bank_accounts from './blocked-bank-accounts/list-blocked-bank-accounts'; -import retrieve_bankruptcy from './bankruptcy/retrieve-bankruptcy'; -import list_arbitration_cases from './arbitration-cases/list-arbitration-cases'; - -export const endpoints: Endpoint[] = []; - -function addEndpoint(endpoint: Endpoint) { - endpoints.push(endpoint); -} - -addEndpoint(create_taxpayer_statuses); -addEndpoint(create_suggestions); -addEndpoint(create_ogrns_by_address); -addEndpoint(create_leases); -addEndpoint(create_filters_preview); -addEndpoint(create_batch_changes); -addEndpoint(create_batch_cards); -addEndpoint(create_batch_cards_by_filters); -addEndpoint(get_courts_arbitration); -addEndpoint(get_dispute_categories_arbitration); -addEndpoint(get_document_types_arbitration); -addEndpoint(create_arbitration_batch_cases); -addEndpoint(retrieve_tax_info); -addEndpoint(retrieve_sro_membership); -addEndpoint(list_risks); -addEndpoint(list_paid_taxes); -addEndpoint(list_okpd_list); -addEndpoint(retrieve_nko_reestr); -addEndpoint(list_links); -addEndpoint(list_government_contracts); -addEndpoint(retrieve_government_contracts_stat); -addEndpoint(retrieve_finance); -addEndpoint(list_regions); -addEndpoint(list_lease_classifier_dictionary); -addEndpoint(list_licenses_dictionary); -addEndpoint(list_okveds_dictionary); -addEndpoint(list_regions_dictionary); -addEndpoint(list_okpd2_dictionary_procurement); -addEndpoint(list_courts_dictionary_arbitration); -addEndpoint(list_dispute_categories_dictionary_arbitration); -addEndpoint(list_document_types_dictionary_arbitration); -addEndpoint(retrieve_okpd2_procurement); -addEndpoint(list_okveds); -addEndpoint(list_licenses); -addEndpoint(retrieve_lease_classifier); -addEndpoint(retrieve_counterparty); -addEndpoint(list_corporate_actions); -addEndpoint(list_blocked_bank_accounts); -addEndpoint(retrieve_bankruptcy); -addEndpoint(list_arbitration_cases); - -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/lease-classifier/retrieve-lease-classifier.ts b/packages/mcp-server/src/tools/lease-classifier/retrieve-lease-classifier.ts deleted file mode 100644 index 3c433ef..0000000 --- a/packages/mcp-server/src/tools/lease-classifier/retrieve-lease-classifier.ts +++ /dev/null @@ -1,44 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'lease_classifier', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/lease_classifier', - operationId: '24_getLeaseClassifierDictionary', -}; - -export const tool: Tool = { - name: 'retrieve_lease_classifier', - 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\nПолучить классификатор лизинговых договоров: код лизинга, его наименование и количество заключенных договоров с данным кодом\n\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/lease_classifier_retrieve_response',\n $defs: {\n lease_classifier_retrieve_response: {\n type: 'object',\n properties: {\n data: {\n type: 'array',\n items: {\n type: 'object',\n description: 'Код - расшифровка - количество',\n properties: {\n code: {\n type: 'string',\n description: 'Значение кода'\n },\n count: {\n type: 'integer',\n description: 'Количество'\n },\n group: {\n type: 'string',\n description: 'Группа, к которой относится код'\n },\n group_code: {\n type: 'string',\n description: 'Код группы, к которой относится код'\n },\n name: {\n type: 'string',\n description: 'Расшифровка кода'\n },\n type: {\n type: 'string',\n description: 'Тип контрагента: ip или ul'\n }\n }\n }\n }\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: Datanewton, args: Record | undefined) => { - const { jq_filter } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.leaseClassifier.retrieve())); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/leases/create-leases.ts b/packages/mcp-server/src/tools/leases/create-leases.ts deleted file mode 100644 index c6df659..0000000 --- a/packages/mcp-server/src/tools/leases/create-leases.ts +++ /dev/null @@ -1,97 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'leases', - operation: 'write', - tags: [], - httpMethod: 'post', - httpPath: '/v1/leases', - operationId: '11_getLeases', -}; - -export const tool: Tool = { - name: 'create_leases', - description: 'Получить данные о договорах лизинга по заданным условиям\n', - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - limit: { - type: 'integer', - description: 'Лимит.', - }, - offset: { - type: 'integer', - description: 'Оффсет.', - }, - classifier_codes: { - type: 'array', - description: 'Коды типа лизинга из классификатора (справочника)', - items: { - type: 'string', - description: 'Коды типа лизинга из классификатора (справочника)', - }, - }, - lease_end_from: { - type: 'string', - description: 'Дата прекращения договора: С (включительно)', - format: 'date', - }, - lease_end_to: { - type: 'string', - description: 'Дата прекращения договора: По (включительно)', - format: 'date', - }, - lease_start_from: { - type: 'string', - description: 'Дата заключения договора: С (включительно)', - format: 'date', - }, - lease_start_to: { - type: 'string', - description: 'Дата заключения договора: По (включит ельно)', - format: 'date', - }, - only_active: { - type: 'boolean', - description: 'Только активные договора', - }, - order: { - type: 'string', - description: 'Порядок сортировки', - enum: ['ASC', 'DESC'], - }, - search_text: { - type: 'string', - description: 'Ключевые слова для поиска в реквизитах договора', - }, - sort: { - type: 'string', - description: 'Поле для сортировки результата', - enum: ['date_start', 'date_end'], - }, - updated_after: { - type: 'string', - description: 'Дата последнего изменения: С (включительно)', - format: 'date-time', - }, - }, - required: ['key', 'limit', 'offset'], - }, - annotations: {}, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const body = args as any; - return asTextContentResult(await client.leases.create(body)); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/licenses/list-licenses.ts b/packages/mcp-server/src/tools/licenses/list-licenses.ts deleted file mode 100644 index ab29ee8..0000000 --- a/packages/mcp-server/src/tools/licenses/list-licenses.ts +++ /dev/null @@ -1,44 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'licenses', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/licenses', - operationId: '23_getLicensesDictionary', -}; - -export const tool: Tool = { - name: 'list_licenses', - 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\nПолучить справочник кодов и типов лицензий\n\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/license_list_response',\n $defs: {\n license_list_response: {\n type: 'object',\n properties: {\n data: {\n type: 'array',\n items: {\n type: 'object',\n description: 'Код - расшифровка - количество',\n properties: {\n code: {\n type: 'string',\n description: 'Значение кода'\n },\n count: {\n type: 'integer',\n description: 'Количество'\n },\n group: {\n type: 'string',\n description: 'Группа, к которой относится код'\n },\n group_code: {\n type: 'string',\n description: 'Код группы, к которой относится код'\n },\n name: {\n type: 'string',\n description: 'Расшифровка кода'\n },\n type: {\n type: 'string',\n description: 'Тип контрагента: ip или ul'\n }\n }\n }\n }\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: Datanewton, args: Record | undefined) => { - const { jq_filter } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.licenses.list())); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/links/list-links.ts b/packages/mcp-server/src/tools/links/list-links.ts deleted file mode 100644 index f7ae2f6..0000000 --- a/packages/mcp-server/src/tools/links/list-links.ts +++ /dev/null @@ -1,57 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'links', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/links', - operationId: '10_getLinks', -}; - -export const tool: Tool = { - name: 'list_links', - 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\nПолучить связи контрагента (до 2-го уровня включительно): руководители, участники, ИП\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/link_list_response',\n $defs: {\n link_list_response: {\n type: 'object',\n description: 'Граф связей. Содержит список узлов и список связей между ними. Идентификация между связями и узлами производится по ИНН',\n properties: {\n available_count: {\n type: 'integer',\n description: 'Количество доступных запросов'\n },\n edge_types: {\n type: 'array',\n description: 'Типы связей, по которым был построен граф',\n items: {\n type: 'string',\n description: 'Типы связей, по которым был построен граф',\n enum: [ 'OWNER',\n 'MANAGER',\n 'INDIVIDUAL',\n 'HISTORY_OWNER',\n 'HISTORY_MANAGER'\n ]\n }\n },\n edges: {\n type: 'array',\n description: 'Список связей (ребер графа). Содержит информацию об связи между вершинами графа, включая ИНН связанных узлов',\n items: {\n type: 'object',\n description: 'Связь между узлами. Содержит информацию о связанных узлах (ИНН исходного и результирующего узла), уровень связи от корня (начиная с 0), тип связи, значение (описание)',\n properties: {\n inn_source: {\n type: 'string',\n description: 'ИНН исходного узла'\n },\n inn_target: {\n type: 'string',\n description: 'ИНН результирующего узла'\n },\n level: {\n type: 'integer',\n description: 'Уровень (начиная с 0 от корня)'\n },\n type: {\n type: 'string',\n description: 'Тип связи',\n enum: [ 'OWNER',\n 'MANAGER',\n 'INDIVIDUAL',\n 'HISTORY_OWNER',\n 'HISTORY_MANAGER'\n ]\n },\n value: {\n type: 'string',\n description: 'Значение (описание) связи'\n }\n }\n }\n },\n edges_count: {\n type: 'integer',\n description: 'количество связей'\n },\n inn_root: {\n type: 'string',\n description: 'ИНН главной вершины (корня) графа, начиная с которой он был построен'\n },\n max_level: {\n type: 'integer',\n description: 'Сколько уровней связей было построено, начиная c 0 от корня'\n },\n nodes: {\n type: 'array',\n description: 'Список узлов (вершин графа). Содержит информацию об участниках связей (ЮЛ, ИП, ФЛ). Для каждого указан ИНН (для ЮЛ/ИП также указывается ОГРН), название и статус.',\n items: {\n type: 'object',\n description: 'Узел связи. Содержит информацию об участнике связи: тип (ФЛ, ЮЛ, ИП), ИНН, ОГРН (для ЮЛ/ИП), наименование, статус',\n properties: {\n activity_kind: {\n type: 'string',\n description: 'Основной ОКВЭД, код'\n },\n activity_kind_dsc: {\n type: 'string',\n description: 'Основной ОКВЭД, описание'\n },\n inn: {\n type: 'string',\n description: 'ИНН'\n },\n name: {\n type: 'string',\n description: 'Наименование'\n },\n ogrn: {\n type: 'string',\n description: 'ОГРН'\n },\n status: {\n type: 'string',\n description: 'Статус',\n enum: [ '0',\n '1',\n '-1'\n ]\n },\n type: {\n type: 'string',\n description: 'Тип',\n enum: [ 'UL',\n 'IP',\n 'FL'\n ]\n }\n }\n }\n },\n nodes_count: {\n type: 'integer',\n description: 'количество узлов'\n },\n ogrn_root: {\n type: 'string',\n description: 'ОГРН главной вершины (корня) графа, начиная с которой он был построен'\n }\n }\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - ogrn: { - type: 'string', - description: 'ОГРН или ОГРНИП', - }, - level: { - type: 'integer', - description: - 'Уровень до которого ищем связи, не более 2 (если больше 2, то будет использоваться 2, если меньше 0, то будет использоваться 0). Если не задан, то считается равным 2', - }, - 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: ['key', 'ogrn'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.links.list(body))); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/nko-reestr/retrieve-nko-reestr.ts b/packages/mcp-server/src/tools/nko-reestr/retrieve-nko-reestr.ts deleted file mode 100644 index 977586b..0000000 --- a/packages/mcp-server/src/tools/nko-reestr/retrieve-nko-reestr.ts +++ /dev/null @@ -1,56 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'nko_reestr', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/nkoReestr', - operationId: '15_getNkoReestr', -}; - -export const tool: Tool = { - name: 'retrieve_nko_reestr', - 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\nПолучить информацию о принадлежности контрагента к НКО\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/nko_reestr_retrieve_response',\n $defs: {\n nko_reestr_retrieve_response: {\n type: 'object',\n description: 'Реестр НКО',\n properties: {\n available_count: {\n type: 'integer',\n description: 'Количество доступных запросов'\n },\n error: {\n type: 'object',\n description: 'Исключительная ситуация',\n properties: {\n code: {\n type: 'integer',\n description: 'Код ошибки. Например: 1 - контрагент по заданным параметрам не найден'\n },\n message: {\n type: 'string',\n description: 'Описание'\n },\n source: {\n type: 'object',\n description: 'Параметры - входные данные, вызвавшие исключительную ситуацию',\n additionalProperties: true\n }\n }\n },\n nko_info: {\n type: 'array',\n items: {\n type: 'object',\n description: 'Записи из реестра НКО',\n properties: {\n address: {\n type: 'string',\n description: 'Адрес'\n },\n forma: {\n type: 'string',\n description: 'Наименование вида организационно-правовой формы организации'\n },\n name: {\n type: 'string',\n description: 'Полное наименование организации'\n },\n nko_id: {\n type: 'integer',\n description: 'Идентификатор записи'\n },\n ogrn_date: {\n type: 'string',\n description: 'Дата вступления организации в реестр'\n },\n reestr_name: {\n type: 'string',\n description: 'Наименование реестра, в который входит организация'\n },\n reg_number: {\n type: 'string',\n description: 'Номер, присваиваемый организации в системе'\n },\n region: {\n type: 'string',\n description: 'Регион, в котором осуществляет деятельность НКО'\n },\n status_nko: {\n type: 'string',\n description: 'Статус НКО',\n enum: [ 'Исключена',\n 'Зарегистрирована'\n ]\n }\n }\n }\n }\n }\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - inn: { - type: 'string', - description: 'ИНН организации или ИП. Должен быть указан, если не указан ОГРН/ОГРНИП.', - }, - ogrn: { - type: 'string', - description: 'ОГРН или ОГРНИП. Должен быть указан, если не указан ИНН.', - }, - 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: ['key'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.nkoReestr.retrieve(body))); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/ogrns-by-address/create-ogrns-by-address.ts b/packages/mcp-server/src/tools/ogrns-by-address/create-ogrns-by-address.ts deleted file mode 100644 index 21be931..0000000 --- a/packages/mcp-server/src/tools/ogrns-by-address/create-ogrns-by-address.ts +++ /dev/null @@ -1,58 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'ogrns_by_address', - operation: 'write', - tags: [], - httpMethod: 'post', - httpPath: '/v1/ogrnsByAddress', - operationId: '32_ogrnsByAddress', -}; - -export const tool: Tool = { - name: 'create_ogrns_by_address', - 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\nПолучить список компаний по заданному адресу\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/ogrns_by_address_create_response',\n $defs: {\n ogrns_by_address_create_response: {\n type: 'object',\n description: 'Результат поиска компаний по адресу',\n properties: {\n available_count: {\n type: 'integer',\n description: 'Количество доступных запросов'\n },\n counterparties: {\n type: 'array',\n description: 'Список компаний',\n items: {\n type: 'object',\n description: 'Список компаний',\n properties: {\n active: {\n type: 'boolean',\n description: 'Признак активности контрагента (действующий/недействующий)'\n },\n activity_kind: {\n type: 'string',\n description: 'Основной ОКВЭД'\n },\n activity_kind_dsc: {\n type: 'string',\n description: 'Описание основного вида деятельности'\n },\n activity_kind_industry_code: {\n type: 'string',\n description: 'Код основного вида деятельности'\n },\n activity_kind_mode: {\n type: 'string',\n description: 'Тип основного ОКВЭД (new/old): new - после изменений 2014 года, old - до него'\n },\n address: {\n type: 'string',\n description: 'Адрес'\n },\n charter_capital: {\n type: 'string',\n description: 'Уставный капитал'\n },\n enable_email_notification: {\n type: 'boolean',\n description: 'Присылать уведомления на почту'\n },\n establishment_date: {\n type: 'string',\n description: 'Дата регистрации'\n },\n fin_report_year: {\n type: 'integer',\n description: 'Последний год сданной отчетности БФО'\n },\n groups: {\n type: 'object',\n description: 'Блок с информацией о группах (холдинги)',\n properties: {\n holding: {\n type: 'object',\n properties: {\n ogrn: {\n type: 'string'\n },\n share: {\n type: 'number'\n },\n size: {\n type: 'integer'\n }\n }\n },\n holding_by_active: {\n type: 'object',\n properties: {\n ogrn: {\n type: 'string'\n },\n share: {\n type: 'number'\n },\n size: {\n type: 'integer'\n }\n }\n },\n metagroup: {\n type: 'object',\n properties: {\n ogrn: {\n type: 'string'\n },\n share: {\n type: 'number'\n },\n size: {\n type: 'integer'\n }\n }\n },\n metagroup_by_active: {\n type: 'object',\n properties: {\n ogrn: {\n type: 'string'\n },\n share: {\n type: 'number'\n },\n size: {\n type: 'integer'\n }\n }\n },\n network: {\n type: 'object',\n properties: {\n ogrn: {\n type: 'string'\n },\n share: {\n type: 'number'\n },\n size: {\n type: 'integer'\n }\n }\n },\n network_by_active: {\n type: 'object',\n properties: {\n ogrn: {\n type: 'string'\n },\n share: {\n type: 'number'\n },\n size: {\n type: 'integer'\n }\n }\n }\n }\n },\n inn: {\n type: 'string',\n description: 'ИНН контрагента'\n },\n last_income: {\n type: 'number',\n description: 'Выручка за последний отчетный год (в тыс. рублей)'\n },\n manager_name: {\n type: 'string',\n description: 'Руководитель'\n },\n manager_position: {\n type: 'string',\n description: 'Должность руководителя'\n },\n match: {\n type: 'string',\n description: 'Что совпало в поиске (значение)'\n },\n match_actual: {\n type: 'boolean',\n description: 'Совпадение по актуальным данным или историческим (например, бывшим руководителям)'\n },\n match_dsc: {\n type: 'string',\n description: 'Тип/описание совпадения - что именно совпало (какое поле/домен)'\n },\n name: {\n type: 'string',\n description: 'Наименование контрагента (краткое, при его отсутствии - полное)'\n },\n ogrn: {\n type: 'string',\n description: 'ОГРН контрагента'\n },\n region: {\n type: 'string',\n description: 'Регион'\n },\n region_code: {\n type: 'string',\n description: 'Регион (код)'\n },\n type: {\n type: 'string',\n description: 'Тип: ul - ЮЛ, ip - ИП'\n }\n }\n }\n },\n error: {\n type: 'object',\n description: 'Исключительная ситуация',\n properties: {\n code: {\n type: 'integer',\n description: 'Код ошибки. Например: 1 - контрагент по заданным параметрам не найден'\n },\n message: {\n type: 'string',\n description: 'Описание'\n },\n source: {\n type: 'object',\n description: 'Параметры - входные данные, вызвавшие исключительную ситуацию',\n additionalProperties: true\n }\n }\n },\n limit: {\n type: 'integer',\n description: 'Лимит записей на страницу (limit)'\n },\n offset: {\n type: 'integer',\n description: 'Смещение выборки (offset)'\n },\n total: {\n type: 'integer',\n description: 'Общее количество компаний по запросу'\n }\n }\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - address: { - type: 'string', - description: 'Адрес', - }, - limit: { - type: 'integer', - description: 'Количество записей (максимум 100)', - }, - offset: { - type: 'integer', - description: 'Смещение выборки (offset)', - }, - 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: ['key', 'address'], - }, - annotations: {}, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.ogrnsByAddress.create(body))); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/okpd-list/list-okpd-list.ts b/packages/mcp-server/src/tools/okpd-list/list-okpd-list.ts deleted file mode 100644 index 11abe54..0000000 --- a/packages/mcp-server/src/tools/okpd-list/list-okpd-list.ts +++ /dev/null @@ -1,56 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'okpd_list', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/okpdList', - operationId: '13_getOKPDList', -}; - -export const tool: Tool = { - name: 'list_okpd_list', - 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\nПолучить список всех ОКПД (ОКПД2) компании, на основании данных в ЕИС Закупки\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/okpd_list_list_response',\n $defs: {\n okpd_list_list_response: {\n type: 'object',\n description: 'Данные об ОКПД огранизации',\n properties: {\n available_count: {\n type: 'integer',\n description: 'Количество доступных запросов'\n },\n data: {\n type: 'array',\n description: 'Список ОКПД огранизации',\n items: {\n type: 'object',\n description: 'Данные об ОКПД организации',\n properties: {\n number: {\n type: 'string',\n description: 'Номер позиции'\n },\n okpd_code: {\n type: 'string',\n description: 'Код ОКПД'\n },\n okpd_name: {\n type: 'string',\n description: 'Наименование ОКПД'\n },\n okpd2_code: {\n type: 'string',\n description: 'Код ОКПД2'\n },\n okpd2_name: {\n type: 'string',\n description: 'Наименование ОКПД2'\n }\n }\n }\n },\n error: {\n type: 'object',\n description: 'Исключительная ситуация',\n properties: {\n code: {\n type: 'integer',\n description: 'Код ошибки. Например: 1 - контрагент по заданным параметрам не найден'\n },\n message: {\n type: 'string',\n description: 'Описание'\n },\n source: {\n type: 'object',\n description: 'Параметры - входные данные, вызвавшие исключительную ситуацию',\n additionalProperties: true\n }\n }\n }\n }\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - inn: { - type: 'string', - description: 'ИНН организации или ИП. Должен быть указан, если не указан ОГРН/ОГРНИП.', - }, - ogrn: { - type: 'string', - description: 'ОГРН или ОГРНИП. Должен быть указан, если не указан ИНН.', - }, - 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: ['key'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.okpdList.list(body))); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/okveds/list-okveds.ts b/packages/mcp-server/src/tools/okveds/list-okveds.ts deleted file mode 100644 index 46405f7..0000000 --- a/packages/mcp-server/src/tools/okveds/list-okveds.ts +++ /dev/null @@ -1,44 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'okveds', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/okveds', - operationId: '22_getOkvedsDictionary_1', -}; - -export const tool: Tool = { - name: 'list_okveds', - 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\nПолучить справочник ОКВЭДов\n\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/okved_list_response',\n $defs: {\n okved_list_response: {\n type: 'object',\n description: 'ОКВЭД, имеет вложенную структуру',\n properties: {\n all_children_code: {\n type: 'array',\n items: {\n type: 'string'\n }\n },\n children: {\n type: 'array',\n description: 'Дочерние записи ОКВЭД',\n items: {\n $ref: '#/$defs/okved1'\n }\n },\n code: {\n type: 'string',\n description: 'Код ОКВЭД'\n },\n count: {\n type: 'integer',\n description: 'Количество действующих юридических лиц, у которых главный ОКВЭД равен name (с учетом дочерних)'\n },\n direct_count: {\n type: 'integer',\n description: 'Количество действующих юридических лиц, у которых главный ОКВЭД равен name (без учета дочерних)'\n },\n group: {\n type: 'string',\n description: 'Группа: A-U'\n },\n level: {\n type: 'integer'\n },\n name: {\n type: 'string',\n description: 'Наименование ОКВЭД'\n }\n }\n },\n okved1: {\n type: 'object',\n description: 'ОКВЭД, имеет вложенную структуру',\n properties: {\n all_children_code: {\n type: 'array',\n items: {\n type: 'string'\n }\n },\n children: {\n type: 'array',\n description: 'Дочерние записи ОКВЭД',\n items: {\n $ref: '#/$defs/okved1'\n }\n },\n code: {\n type: 'string',\n description: 'Код ОКВЭД'\n },\n count: {\n type: 'integer',\n description: 'Количество действующих юридических лиц, у которых главный ОКВЭД равен name (с учетом дочерних)'\n },\n direct_count: {\n type: 'integer',\n description: 'Количество действующих юридических лиц, у которых главный ОКВЭД равен name (без учета дочерних)'\n },\n group: {\n type: 'string',\n description: 'Группа: A-U'\n },\n level: {\n type: 'integer'\n },\n name: {\n type: 'string',\n description: 'Наименование ОКВЭД'\n }\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: Datanewton, args: Record | undefined) => { - const { jq_filter } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.okveds.list())); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/paid-taxes/list-paid-taxes.ts b/packages/mcp-server/src/tools/paid-taxes/list-paid-taxes.ts deleted file mode 100644 index c9599eb..0000000 --- a/packages/mcp-server/src/tools/paid-taxes/list-paid-taxes.ts +++ /dev/null @@ -1,56 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'paid_taxes', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/paidTaxes', - operationId: '9_getPaidTaxes', -}; - -export const tool: Tool = { - name: 'list_paid_taxes', - 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\nПолучить данные об уплаченных налогах по ИНН/ОГРН\n\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/paid_tax_list_response',\n $defs: {\n paid_tax_list_response: {\n type: 'object',\n description: 'Данные об уплаченных налогах',\n properties: {\n available_count: {\n type: 'integer',\n description: 'Количество доступных запросов'\n },\n data: {\n type: 'array',\n description: 'Данные о уплаченных налогах',\n items: {\n type: 'object',\n description: 'Данные об уплаченных налогах',\n properties: {\n doc_date: {\n type: 'string',\n description: 'Дата формирования документа'\n },\n report_date: {\n type: 'string',\n description: 'Дата, по состоянию на которую, подготовлены данные для публикации (в ней указан отчетный год)'\n },\n tax_info_list: {\n type: 'array',\n description: 'Список уплаченных налогов',\n items: {\n type: 'object',\n description: 'Информация о налоге',\n properties: {\n taxName: {\n type: 'string',\n description: 'Наименование налога'\n },\n taxValue: {\n type: 'string',\n description: ' Сумма уплаченного налога (в рублях)'\n }\n }\n }\n }\n }\n }\n },\n error: {\n type: 'object',\n description: 'Исключительная ситуация',\n properties: {\n code: {\n type: 'integer',\n description: 'Код ошибки. Например: 1 - контрагент по заданным параметрам не найден'\n },\n message: {\n type: 'string',\n description: 'Описание'\n },\n source: {\n type: 'object',\n description: 'Параметры - входные данные, вызвавшие исключительную ситуацию',\n additionalProperties: true\n }\n }\n }\n }\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - inn: { - type: 'string', - description: 'ИНН организации или ИП. Должен быть указан, если не указан ОГРН/ОГРНИП.', - }, - ogrn: { - type: 'string', - description: 'ОГРН или ОГРНИП. Должен быть указан, если не указан ИНН.', - }, - 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: ['key'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.paidTaxes.list(body))); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/procurement/retrieve-okpd2-procurement.ts b/packages/mcp-server/src/tools/procurement/retrieve-okpd2-procurement.ts deleted file mode 100644 index 777ecd5..0000000 --- a/packages/mcp-server/src/tools/procurement/retrieve-okpd2-procurement.ts +++ /dev/null @@ -1,44 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'procurement', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/procurement/okpd2', - operationId: '27_getOkpd2Dictionary', -}; - -export const tool: Tool = { - name: 'retrieve_okpd2_procurement', - 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\nПолучить общероссийский классификатор продукции по видам экономической деятельности (ОКПД2)\n\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/procurement_retrieve_okpd2_response',\n $defs: {\n procurement_retrieve_okpd2_response: {\n type: 'object',\n properties: {\n data: {\n type: 'array',\n items: {\n type: 'object',\n description: 'Код - расшифровка - количество',\n properties: {\n code: {\n type: 'string',\n description: 'Значение кода'\n },\n count: {\n type: 'integer',\n description: 'Количество'\n },\n group: {\n type: 'string',\n description: 'Группа, к которой относится код'\n },\n group_code: {\n type: 'string',\n description: 'Код группы, к которой относится код'\n },\n name: {\n type: 'string',\n description: 'Расшифровка кода'\n },\n type: {\n type: 'string',\n description: 'Тип контрагента: ip или ul'\n }\n }\n }\n }\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: Datanewton, args: Record | undefined) => { - const { jq_filter } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.procurement.retrieveOkpd2())); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/regions/list-regions.ts b/packages/mcp-server/src/tools/regions/list-regions.ts deleted file mode 100644 index 0b5d4d5..0000000 --- a/packages/mcp-server/src/tools/regions/list-regions.ts +++ /dev/null @@ -1,44 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'regions', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/regions', - operationId: '16_getRegionsDictionary', -}; - -export const tool: Tool = { - name: 'list_regions', - 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\nПолучить справочник регионов России\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/region_list_response',\n $defs: {\n region_list_response: {\n type: 'object',\n description: 'Федеральный округ с регионами',\n properties: {\n name: {\n type: 'string'\n },\n regions: {\n type: 'array',\n items: {\n type: 'object',\n description: 'Регион',\n properties: {\n code: {\n type: 'string'\n },\n name: {\n type: 'string'\n }\n }\n }\n }\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: Datanewton, args: Record | undefined) => { - const { jq_filter } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.regions.list())); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/risks/list-risks.ts b/packages/mcp-server/src/tools/risks/list-risks.ts deleted file mode 100644 index 2995512..0000000 --- a/packages/mcp-server/src/tools/risks/list-risks.ts +++ /dev/null @@ -1,56 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'risks', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/risks', - operationId: '20_getRisks', -}; - -export const tool: Tool = { - name: 'list_risks', - 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\nПолучить список рисков по контрагенту\n\n**Возможные значения**\n\n**Негативные списки: (NEGATIVE_LISTS)**\n\n - `owner_inaccuracy` — Недостоверность учредителя\n - `disqualified_managers` — Руководитель дисквалифицирован\n - `in_sanctions_ofac` — Находится в санкционном списке OFAC\n - `illegal_rewards` — Находится в реестре ЮЛ, привлеченных за незаконное вознаграждение\n - `address_inaccuracy` — Недостоверность адреса\n - `manager_inaccuracy` — Недостоверность руководителя\n - `in_sanctions_uk` — Находится в санкционном списке UK\n - `in_sanctions_eu` — Находится в санкционном списке EU\n - `false_info` — Недостоверные данные по ЕГРЮЛ. Если в ЕГР есть отметка о недостоверности любого из блоков: адрес, участник, руководитель, управляющая компания.\n - `disqualified_owners` — Участник дисквалифицирован\n - `unscrupulous_manager` — Руководитель в РНП\n - `unscrupulous_owner` — Участник в РНП\n - `unscrupulous_supplier_223` — Состоит в реестре недобросовестных поставщиков по ФЗ 223\n - `unscrupulous_supplier_615` — Состоит в реестре недобросовестных поставщиков по ПП 615\n - `unscrupulous_supplier_44` — Состоит в реестре недобросовестных поставщиков по ФЗ 44\n - `disqualified_individual` — ИП дисквалифицирован\n - `management_company_inaccuracy` — Недостоверность управляющей компании\n - `fin_illegal` — Имеет признаки нелегальной деятельности на финансовом рынке\n\n**Признаки однодневок: (ONE_DAY_COMPANY)**\n\n - `fns_migration` — Миграция между ФНС (более 2 за 12 месяцев)\n - `mass_address` — Массовый юридический адрес. Под массовым юридическим адресом понимается факт регистрации 5 и более компаний с точностью до офиса/помещения/комнаты\n - `mass_okveds` — ОКВЭДов более 30\n - `company_age` — Возраст менее 1 года\n - `default_capital_table` — Уставный капитал 10 000 ₽\n - `owner_change` — Учредитель сменился менее 1 года назад\n - `mass_owner` — Массовый учредитель (более 5)\n - `manager_change` — Руководитель сменился менее 1 года назад\n - `management_company_change` — Управляющая компания сменилась менее 1 года назад\n - `workers_amount` — Численность работников 0 или 1\n - `mass_manager` — Массовый руководитель (более 5)\n - `tax_debts` — Имеет налоговую задолженность\n - `tax_offences` — Имеет налоговые нарушения\n\n**Иные факты: (OTHER_FACTS)**\n\n - `has_licenses` — Имеет действующие лицензии\n - `has_declarations` — Имеет действующие Декларации соответствия\n - `owners_information_limited` — Ограничение доступа к сведениям в ЕГРЮЛ об участнике\n - `zero_intangible_assets` — Нулевая балансовая стоимость нематериальных активов, за последний год\n - `zero_fixed_assets` — Нулевая балансовая стоимость основных средств, за последний год\n - `has_certifications` — Имеет действующие Сертификаты соответствия\n - `management_companies_information_limited` — Ограничение доступа к сведениям в ЕГРЮЛ об управляющей компании\n - `has_government_contracts` — Является поставщиком по госконтрактам\n - `managers_information_limited` — Ограничение доступа к сведениям в ЕГРЮЛ о руководителе\n - `information_limited` — Ограничение доступа к сведениям в ЕГРЮЛ\n - `debt` — Сумма к взысканию по исполнительным производствам превышает 300 000 руб\n - `status_egrul` — Статус в ЕГРЮЛ, требующий внимания\n - `status_egrip` — Статус в ЕГРИП, требующий внимания\n\n**Сведения о банкротстве: (BANKRUPTCY)**\n\n - `has_bankruptcy_messages` — Есть сообщения о банкротстве за последний год\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/risk_list_response',\n $defs: {\n risk_list_response: {\n type: 'object',\n description: 'Информация о рисках контрагента',\n properties: {\n available_count: {\n type: 'integer',\n description: 'Количество доступных запросов'\n },\n flags: {\n type: 'array',\n description: 'Список рисков',\n items: {\n type: 'object',\n description: 'Показатель риска',\n properties: {\n category: {\n type: 'integer',\n description: 'категория (приоритет) для признаков: 0 - высший (красный), 1 - средний (желтый), остальное - 2. 0 и 1 устанавливается только для негативных признаков.'\n },\n comment: {\n type: 'string',\n description: 'расширенный комментарий'\n },\n description: {\n type: 'string',\n description: 'описание признака'\n },\n details: {\n type: 'array',\n description: 'дополнительная информация',\n items: {\n type: 'array',\n description: 'дополнительная информация',\n items: {\n type: 'object',\n description: 'Дополнительная информация',\n properties: {\n name: {\n type: 'string',\n description: 'название'\n },\n value: {\n type: 'string',\n description: 'значение'\n },\n value_type: {\n type: 'string',\n description: 'тип значения',\n enum: [ 'string',\n 'date',\n 'boolean',\n 'url'\n ]\n }\n }\n }\n }\n },\n name: {\n type: 'string',\n description: 'наименование признака'\n },\n positive: {\n type: 'boolean',\n description: 'является ли позитивным фактором'\n },\n type: {\n type: 'string',\n description: 'тип показателя',\n enum: [ 'NEGATIVE_LISTS',\n 'ONE_DAY_COMPANY',\n 'OTHER_FACTS',\n 'BANKRUPTCY'\n ]\n },\n value: {\n type: 'boolean',\n description: 'значение true/false'\n }\n }\n }\n },\n ogrn: {\n type: 'string',\n description: 'ОГРН компании'\n }\n }\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - inn: { - type: 'string', - description: 'ИНН организации или ИП. Должен быть указан, если не указан ОГРН/ОГРНИП.', - }, - ogrn: { - type: 'string', - description: 'ОГРН или ОГРНИП. Должен быть указан, если не указан ИНН.', - }, - 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: ['key'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.risks.list(body))); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/sro-membership/retrieve-sro-membership.ts b/packages/mcp-server/src/tools/sro-membership/retrieve-sro-membership.ts deleted file mode 100644 index 80d3be0..0000000 --- a/packages/mcp-server/src/tools/sro-membership/retrieve-sro-membership.ts +++ /dev/null @@ -1,78 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'sro_membership', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/sroMembership', - operationId: '14_getSroMembership', -}; - -export const tool: Tool = { - name: 'retrieve_sro_membership', - 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\nПолучить информацию о членстве в СРО НОСТРОЙ/НОПРИЗ\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/sro_membership_retrieve_response',\n $defs: {\n sro_membership_retrieve_response: {\n type: 'object',\n properties: {\n available_count: {\n type: 'integer',\n description: 'Количество доступных запросов'\n },\n sro_infos: {\n type: 'array',\n description: 'Данные',\n items: {\n type: 'object',\n description: 'Данные',\n properties: {\n checks: {\n type: 'array',\n description: 'Проверки',\n items: {\n type: 'object',\n description: 'Проверки',\n properties: {\n date: {\n type: 'string',\n description: 'Дата окончания проверки'\n },\n facts: {\n type: 'string',\n description: 'Факты применения мер дисциплинарного воздействия'\n },\n result: {\n type: 'string',\n description: 'Результат проверки члена СРО'\n },\n type: {\n type: 'string',\n description: 'Тип проверки'\n }\n }\n }\n },\n ensures: {\n type: 'array',\n description: 'Страхование',\n items: {\n type: 'object',\n description: 'Страхование',\n properties: {\n company: {\n type: 'string',\n description: 'Наименование страховой компании'\n },\n phones: {\n type: 'string',\n description: 'Контактные телефоны'\n },\n place: {\n type: 'string',\n description: 'Место нахождения'\n },\n subject: {\n type: 'string',\n description: 'Предмет договора страхования'\n },\n sum: {\n type: 'string',\n description: 'Размер страховой суммы'\n }\n }\n }\n },\n fund: {\n type: 'object',\n description: 'Информация о КФ',\n properties: {\n fund_compensate: {\n type: 'number',\n description: 'Размер взноса в компенсационный фонд возмещения вреда'\n },\n fund_secure: {\n type: 'number',\n description: 'Размер взноса в компенсационный фонд обеспечения договорных обязательств'\n }\n }\n },\n info: {\n type: 'object',\n description: 'Общая информация',\n properties: {\n accordance: {\n type: 'string',\n description: 'Сведения о соответствии условиям членства в СРО'\n },\n address: {\n type: 'string',\n description: 'Адрес'\n },\n phones: {\n type: 'string',\n description: 'Контактные телефоны'\n },\n reg_number: {\n type: 'string',\n description: 'Регистрационный номер в реестре СРО'\n },\n sro_date: {\n type: 'string',\n description: 'Дата регистрации в реестре СРО',\n format: 'date'\n },\n sro_id: {\n type: 'string',\n description: 'Идентификатор СРО'\n },\n sro_name: {\n type: 'string',\n description: 'Наименование СРО'\n },\n sro_ogrn: {\n type: 'string',\n description: 'ОГРН СРО'\n },\n stop_date: {\n type: 'string',\n description: 'Дата прекращения членства',\n format: 'date'\n },\n stop_reason: {\n type: 'string',\n description: 'Основание прекращения членства'\n },\n type: {\n type: 'string',\n description: 'Тип(реестр) СРО',\n enum: [ 'НОСТРОЙ',\n 'НОПРИЗ'\n ]\n }\n }\n },\n right: {\n type: 'object',\n description: 'Сведения о наличии права',\n properties: {\n atomic_relation: {\n type: 'string',\n description: 'В отношении объектов использования атомной энергии'\n },\n build_relation: {\n type: 'string',\n description: 'В отношении объектов капитального строительства (кроме особо опасных, технически сложных и уникальных объектов, объектов использования атомной энергии)'\n },\n danger_relation: {\n type: 'string',\n description: 'В отношении особо опасных, технически сложных и уникальных объектов капитального строительства (кроме объектов использования атомной энергии)'\n },\n decision_num_date: {\n type: 'string',\n description: 'Основание наделения правом'\n },\n work_obligations: {\n type: 'string',\n description: 'Размер обязательств по договорам подряда с использованием конкурентных способов заключения договоров (уровень ответственности)'\n },\n work_price: {\n type: 'string',\n description: 'Стоимость работ по одному договору подряда (уровень ответственности)'\n }\n }\n }\n }\n }\n }\n }\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - accordance: { - type: 'boolean', - description: - 'Сведения о соответствии:\ntrue - только соответствующие,\nfalse - только несоответствующие', - }, - inn: { - type: 'string', - description: 'ИНН организации или ИП. Должен быть указан, если не указан ОГРН/ОГРНИП.', - }, - ogrn: { - type: 'string', - description: 'ОГРН или ОГРНИП. Должен быть указан, если не указан ИНН.', - }, - order: { - type: 'boolean', - description: 'Порядок сортировки по дате регистрации:\ntrue - прямой,\nfalse - обратный', - }, - sro_name_like: { - type: 'string', - description: 'Фильтр наименования СРО', - }, - status: { - type: 'boolean', - description: 'Статус членства:\ntrue - только активные,\nfalse - только прекращённые', - }, - type: { - type: 'string', - description: 'Реестр СРО: НОСТРОЙ | НОПРИЗ', - enum: ['НОСТРОЙ', 'НОПРИЗ'], - }, - 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: ['key'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.sroMembership.retrieve(body))); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/suggestions/create-suggestions.ts b/packages/mcp-server/src/tools/suggestions/create-suggestions.ts deleted file mode 100644 index a865a13..0000000 --- a/packages/mcp-server/src/tools/suggestions/create-suggestions.ts +++ /dev/null @@ -1,59 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'suggestions', - operation: 'write', - tags: [], - httpMethod: 'post', - httpPath: '/v1/suggestions', - operationId: '21_getSuggestions', -}; - -export const tool: Tool = { - name: 'create_suggestions', - 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\nПолучить список первых 10 подходящих контрагентов, соответствующих входному значению \n\nПоддерживаются следующие виды поиска: \n - `ОГРН` \n - `ИНН` \n - `Название ЮЛ/ИП, в том числе неполное наименование (например, \"Датаном\" вместо \"Датаномика\")` \n - `Транслитерированное название ЮЛ` \n - `Название ЮЛ, написанное в неправильной раскладке клавиатуры` \n - `Неточное название ЮЛ/ИП (с опечатками)`\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/suggestion_create_response',\n $defs: {\n suggestion_create_response: {\n type: 'object',\n description: 'Ответ в подсказках с набором подходящих запросу контрагентов',\n properties: {\n available_count: {\n type: 'integer',\n description: 'Количество доступных запросов'\n },\n count: {\n type: 'object',\n properties: {\n ip: {\n type: 'integer'\n },\n total: {\n type: 'integer'\n },\n ul: {\n type: 'integer'\n }\n }\n },\n data: {\n type: 'array',\n items: {\n type: 'object',\n description: 'Список компаний',\n properties: {\n active: {\n type: 'boolean',\n description: 'Признак активности контрагента (действующий/недействующий)'\n },\n activity_kind: {\n type: 'string',\n description: 'Основной ОКВЭД'\n },\n activity_kind_dsc: {\n type: 'string',\n description: 'Описание основного вида деятельности'\n },\n activity_kind_industry_code: {\n type: 'string',\n description: 'Код основного вида деятельности'\n },\n activity_kind_mode: {\n type: 'string',\n description: 'Тип основного ОКВЭД (new/old): new - после изменений 2014 года, old - до него'\n },\n address: {\n type: 'string',\n description: 'Адрес'\n },\n charter_capital: {\n type: 'string',\n description: 'Уставный капитал'\n },\n enable_email_notification: {\n type: 'boolean',\n description: 'Присылать уведомления на почту'\n },\n establishment_date: {\n type: 'string',\n description: 'Дата регистрации'\n },\n fin_report_year: {\n type: 'integer',\n description: 'Последний год сданной отчетности БФО'\n },\n groups: {\n type: 'object',\n description: 'Блок с информацией о группах (холдинги)',\n properties: {\n holding: {\n type: 'object',\n properties: {\n ogrn: {\n type: 'string'\n },\n share: {\n type: 'number'\n },\n size: {\n type: 'integer'\n }\n }\n },\n holding_by_active: {\n type: 'object',\n properties: {\n ogrn: {\n type: 'string'\n },\n share: {\n type: 'number'\n },\n size: {\n type: 'integer'\n }\n }\n },\n metagroup: {\n type: 'object',\n properties: {\n ogrn: {\n type: 'string'\n },\n share: {\n type: 'number'\n },\n size: {\n type: 'integer'\n }\n }\n },\n metagroup_by_active: {\n type: 'object',\n properties: {\n ogrn: {\n type: 'string'\n },\n share: {\n type: 'number'\n },\n size: {\n type: 'integer'\n }\n }\n },\n network: {\n type: 'object',\n properties: {\n ogrn: {\n type: 'string'\n },\n share: {\n type: 'number'\n },\n size: {\n type: 'integer'\n }\n }\n },\n network_by_active: {\n type: 'object',\n properties: {\n ogrn: {\n type: 'string'\n },\n share: {\n type: 'number'\n },\n size: {\n type: 'integer'\n }\n }\n }\n }\n },\n inn: {\n type: 'string',\n description: 'ИНН контрагента'\n },\n last_income: {\n type: 'number',\n description: 'Выручка за последний отчетный год (в тыс. рублей)'\n },\n manager_name: {\n type: 'string',\n description: 'Руководитель'\n },\n manager_position: {\n type: 'string',\n description: 'Должность руководителя'\n },\n match: {\n type: 'string',\n description: 'Что совпало в поиске (значение)'\n },\n match_actual: {\n type: 'boolean',\n description: 'Совпадение по актуальным данным или историческим (например, бывшим руководителям)'\n },\n match_dsc: {\n type: 'string',\n description: 'Тип/описание совпадения - что именно совпало (какое поле/домен)'\n },\n name: {\n type: 'string',\n description: 'Наименование контрагента (краткое, при его отсутствии - полное)'\n },\n ogrn: {\n type: 'string',\n description: 'ОГРН контрагента'\n },\n region: {\n type: 'string',\n description: 'Регион'\n },\n region_code: {\n type: 'string',\n description: 'Регион (код)'\n },\n type: {\n type: 'string',\n description: 'Тип: ul - ЮЛ, ip - ИП'\n }\n }\n }\n }\n }\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - search_query: { - type: 'string', - description: 'Поисковое значение (ОГРН/ИНН/наименование)', - }, - is_active: { - type: 'boolean', - description: 'Признак, позволяющий искать только среди действующих контрагентов', - }, - type: { - type: 'string', - description: 'Возможные типы контрагентов', - enum: ['ul', 'ip', 'fl', 'all'], - }, - 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: ['key', 'search_query'], - }, - annotations: {}, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.suggestions.create(body))); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/tax-info/retrieve-tax-info.ts b/packages/mcp-server/src/tools/tax-info/retrieve-tax-info.ts deleted file mode 100644 index 1f836bd..0000000 --- a/packages/mcp-server/src/tools/tax-info/retrieve-tax-info.ts +++ /dev/null @@ -1,56 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'tax_info', - operation: 'read', - tags: [], - httpMethod: 'get', - httpPath: '/v1/taxInfo', - operationId: '22_getTaxInfo', -}; - -export const tool: Tool = { - name: 'retrieve_tax_info', - 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\nПолучить информацию об уплаченных налогах, задолженностях и штрафах, налоговых нарушениях по ИНН/ОГРН\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/tax_info_retrieve_response',\n $defs: {\n tax_info_retrieve_response: {\n type: 'object',\n description: 'Информация об уплаченных налогах, задолженностях и штрафах, налоговых нарушениях',\n properties: {\n available_count: {\n type: 'integer',\n description: 'Количество доступных запросов'\n },\n company_name: {\n type: 'string',\n description: 'Наименование компании'\n },\n error: {\n type: 'object',\n description: 'Исключительная ситуация',\n properties: {\n code: {\n type: 'integer',\n description: 'Код ошибки. Например: 1 - контрагент по заданным параметрам не найден'\n },\n message: {\n type: 'string',\n description: 'Описание'\n },\n source: {\n type: 'object',\n description: 'Параметры - входные данные, вызвавшие исключительную ситуацию',\n additionalProperties: true\n }\n }\n },\n fines_debts: {\n type: 'array',\n description: 'Данные о задолженностях и штрафах',\n items: {\n type: 'object',\n description: 'Данные о задолженностях и штрафах',\n properties: {\n arrears_sum_infos: {\n type: 'array',\n description: 'Сведения о задолженности по налогам, пеням и штрафам',\n items: {\n type: 'object',\n description: 'Сведения о налогах',\n properties: {\n fine_sum: {\n type: 'number',\n description: 'Сумма штрафа'\n },\n penalty_sum: {\n type: 'number',\n description: 'Сумма пени'\n },\n tax_arrears_sum: {\n type: 'number',\n description: 'Сумма недоимки по налогу'\n },\n tax_name: {\n type: 'string',\n description: 'Наименование налога (сбора, страховых взносов), денежного взыскания'\n },\n total_sum: {\n type: 'number',\n description: 'Общая сумма недоимки по налогу, пени и штрафу'\n }\n }\n }\n },\n doc_creation_date: {\n type: 'string',\n description: 'Дата формирования документа',\n format: 'date-time'\n },\n doc_preparation_date: {\n type: 'string',\n description: 'Дата, по состоянию на которую, подготовлены данные для публикации',\n format: 'date-time'\n }\n }\n }\n },\n paid_taxes: {\n type: 'array',\n description: 'Данные об уплаченных налогах',\n items: {\n type: 'object',\n description: 'Данные об уплаченных налогах',\n properties: {\n doc_date: {\n type: 'string',\n description: 'Дата формирования документа'\n },\n report_date: {\n type: 'string',\n description: 'Дата, по состоянию на которую, подготовлены данные для публикации (в ней указан отчетный год)'\n },\n tax_info_list: {\n type: 'array',\n description: 'Список уплаченных налогов',\n items: {\n type: 'object',\n description: 'Информация о налоге',\n properties: {\n taxName: {\n type: 'string',\n description: 'Наименование налога'\n },\n taxValue: {\n type: 'string',\n description: ' Сумма уплаченного налога (в рублях)'\n }\n }\n }\n }\n }\n }\n },\n tax_offences: {\n type: 'array',\n description: 'Данные о налоговых нарушениях',\n items: {\n type: 'object',\n description: 'Данные о налоговых нарушениях',\n properties: {\n doc_date: {\n type: 'string',\n description: 'Дата документа',\n format: 'date-time'\n },\n status_date: {\n type: 'string',\n description: 'Дата, по состоянию на которую, подготовлены данные для публикации',\n format: 'date-time'\n },\n sum: {\n type: 'number',\n description: 'Сумма штрафа'\n }\n }\n }\n }\n }\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - inn: { - type: 'string', - description: 'ИНН организации или ИП. Должен быть указан, если не указан ОГРН/ОГРНИП.', - }, - ogrn: { - type: 'string', - description: 'ОГРН или ОГРНИП. Должен быть указан, если не указан ИНН.', - }, - 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: ['key'], - }, - annotations: { - readOnlyHint: true, - }, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.taxInfo.retrieve(body))); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/taxpayer-statuses/create-taxpayer-statuses.ts b/packages/mcp-server/src/tools/taxpayer-statuses/create-taxpayer-statuses.ts deleted file mode 100644 index 91cf0f6..0000000 --- a/packages/mcp-server/src/tools/taxpayer-statuses/create-taxpayer-statuses.ts +++ /dev/null @@ -1,54 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { maybeFilter } from 'datanewton-mcp/filtering'; -import { Metadata, asTextContentResult } from 'datanewton-mcp/tools/types'; - -import { Tool } from '@modelcontextprotocol/sdk/types.js'; -import Datanewton from 'datanewton'; - -export const metadata: Metadata = { - resource: 'taxpayer_statuses', - operation: 'write', - tags: [], - httpMethod: 'post', - httpPath: '/v1/taxpayerStatuses', - operationId: '6_getTaxpayerStatuses', -}; - -export const tool: Tool = { - name: 'create_taxpayer_statuses', - 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\nПолучить данные о статусе самозанятого налогоплательщика по ИНН\n\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/taxpayer_status_create_response',\n $defs: {\n taxpayer_status_create_response: {\n type: 'object',\n description: 'Статусы самозанятых',\n properties: {\n available_count: {\n type: 'integer',\n description: 'Количество доступных запросов'\n },\n data: {\n type: 'array',\n description: 'Статусы самозанятых',\n items: {\n type: 'object',\n description: 'Статус самозанятого налогоплательщика',\n properties: {\n inn: {\n type: 'string',\n description: 'ИНН'\n },\n status_date: {\n type: 'string',\n description: 'Дата статуса самозанятого',\n format: 'date-time'\n },\n taxpayer: {\n type: 'boolean'\n }\n }\n }\n }\n }\n }\n }\n}\n```", - inputSchema: { - type: 'object', - properties: { - key: { - type: 'string', - description: 'API-ключ.', - }, - inns: { - type: 'array', - description: 'Список ИНН', - items: { - type: 'string', - description: 'Список ИНН', - }, - }, - 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: ['key'], - }, - annotations: {}, -}; - -export const handler = async (client: Datanewton, args: Record | undefined) => { - const { jq_filter, ...body } = args as any; - return asTextContentResult(await maybeFilter(jq_filter, await client.taxpayerStatuses.create(body))); -}; - -export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/tools/types.ts b/packages/mcp-server/src/types.ts similarity index 91% rename from packages/mcp-server/src/tools/types.ts rename to packages/mcp-server/src/types.ts index 57bf89e..aa37e08 100644 --- a/packages/mcp-server/src/tools/types.ts +++ b/packages/mcp-server/src/types.ts @@ -87,6 +87,18 @@ export async function asBinaryContentResult(response: Response): Promise { - 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 08963af..0000000 --- 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 a8a5b81..532666a 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,337 +10,35 @@ 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); - - cleanup(); - }); - - it('should parse exclusion filters', () => { - const cleanup = mockArgv([ - '--no-tool=exclude-tool', - '--no-resource=exclude-resource', - '--no-operation=write', - '--no-tag=exclude-tag', - ]); - - 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[]); + expect(result.transport).toBe('stdio'); 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', - ]); + it('using http transport with a port', () => { + const cleanup = mockArgv(['--transport=http', '--port=2222']); 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, - 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); + const defaultOptions = {}; - 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', () => { + it('default parsing should be empty', () => { const query = ''; const result = parseQueryOptions(defaultOptions, query); - expect(result).toEqual(defaultOptions); + expect(result).toBe({}); }); it('should handle invalid query string gracefully', () => { @@ -351,168 +47,4 @@ describe('parseQueryOptions', () => { // 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 = { - 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 cfff24a..0000000 --- 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 966d057..38be884 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,9 +2761,14 @@ 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" +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" js-tokens@^4.0.0: version "4.0.0" @@ -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== diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 0000000..b190980 --- /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/client.ts b/src/client.ts index 184a38d..6c50373 100644 --- a/src/client.ts +++ b/src/client.ts @@ -205,7 +205,7 @@ export class Datanewton { baseURL: string; maxRetries: number; timeout: number; - logger: Logger | undefined; + logger: Logger; logLevel: LogLevel | undefined; fetchOptions: MergedRequestInit | undefined; diff --git a/src/version.ts b/src/version.ts index ecebcdd..1baa228 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.0.1'; +export const VERSION = '0.1.0'; // x-release-please-version diff --git a/yarn.lock b/yarn.lock index 8311caf..5f56a20 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"