From ce2db72f7cf698c676497baf42555b6f865c2b54 Mon Sep 17 00:00:00 2001 From: GallaGit <230304929+GallaGit@users.noreply.github.com> Date: Tue, 13 Oct 2026 16:40:42 +0200 Subject: [PATCH 1/3] feat(adapters): add read-only Qonto business banking adapter (#1013) Adds fr/qonto.json with 7 GET tools against the Qonto Business API v2 (login:secret-key Authorization header), a static + RUN_QONTO_LIVE=1 sandbox spec, the Qonto logo, regenerated catalog and bumped counts. Closes #1013 --- CITATION.cff | 2 +- README.de.md | 6 +- README.ja.md | 6 +- README.md | 6 +- README.zh-CN.md | 6 +- glama.json | 2 +- package.json | 2 +- packages/backend/src/adapters/catalog.ts | 2 + packages/backend/src/adapters/fr/qonto.json | 339 ++++++++++++++++++ .../src/adapters/fr/qonto.live.spec.ts | 90 +++++ .../public/logos/connectors/qonto.svg | 8 + server.json | 2 +- 12 files changed, 455 insertions(+), 16 deletions(-) create mode 100644 packages/backend/src/adapters/fr/qonto.json create mode 100644 packages/backend/src/adapters/fr/qonto.live.spec.ts create mode 100644 packages/frontend/public/logos/connectors/qonto.svg diff --git a/CITATION.cff b/CITATION.cff index 374b0800f..903622e2b 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -13,7 +13,7 @@ abstract: > server that turns REST/OpenAPI, SOAP/WSDL and GraphQL APIs, SQL/NoSQL databases and other MCP servers into tools for AI clients such as Claude, ChatGPT, Google Gemini, GitHub Copilot and Cursor, without writing code. - It ships 385 pre-built adapters, with a focus on ERP and e-commerce + It ships 386 pre-built adapters, with a focus on ERP and e-commerce systems (SAP Business One, Odoo, Xentral, JTL-Wawi, weclapp, Shopware, WooCommerce, Amazon Seller, Kaufland, OTTO, etc.), a per-workspace knowledge graph served over MCP, per-tool response mapping, diff --git a/README.de.md b/README.de.md index e8dfd34c4..79d8216a9 100644 --- a/README.de.md +++ b/README.de.md @@ -1,5 +1,5 @@

- AnythingMCP macht ERP-, E-Commerce-, REST-, SOAP- und SQL-Systeme zu MCP-Tools für Claude und ChatGPT: 385 Connectors, 19 davon ohne API-Schlüssel. + AnythingMCP macht ERP-, E-Commerce-, REST-, SOAP- und SQL-Systeme zu MCP-Tools für Claude und ChatGPT: 386 Connectors, 19 davon ohne API-Schlüssel.

AnythingMCP: selbst gehostetes MCP-Gateway

@@ -19,7 +19,7 @@

AnythingMCP ist ein quelloffenes, selbst gehostetes MCP-Gateway, das jedes REST-/OpenAPI-, SOAP-, GraphQL-, OData- oder SQL-System in MCP-Tools für Claude, ChatGPT und Copilot verwandelt, ohne dass du einen MCP-Server programmierst.
- Es bringt 385 fertige Adapter mit, darunter SAP, Etsy, weclapp und Amazon Seller; 19 davon kommen ohne API-Schlüssel aus. + Es bringt 386 fertige Adapter mit, darunter SAP, Etsy, weclapp und Amazon Seller; 19 davon kommen ohne API-Schlüssel aus.

@@ -111,7 +111,7 @@ Tools werden zur Laufzeit registriert, ohne Neustart. `{{VAR}}`-Werte pro Connec ## Connector-Katalog -385 Adapter mit über 2.400 Tools. Zu jedem gibt es eine Einrichtungsanleitung auf [anythingmcp.com/de/guides](https://anythingmcp.com/de/guides), in sieben Sprachen. +386 Adapter mit über 2.400 Tools. Zu jedem gibt es eine Einrichtungsanleitung auf [anythingmcp.com/de/guides](https://anythingmcp.com/de/guides), in sieben Sprachen. | Kategorie | Beispiele | |---|---| diff --git a/README.ja.md b/README.ja.md index 160126d55..7f859c881 100644 --- a/README.ja.md +++ b/README.ja.md @@ -1,5 +1,5 @@

- AnythingMCP は ERP、E コマース、REST、SOAP、SQL の各システムを Claude と ChatGPT 用の MCP ツールに変換します。385 のコネクター、うち 19 は API キー不要。 + AnythingMCP は ERP、E コマース、REST、SOAP、SQL の各システムを Claude と ChatGPT 用の MCP ツールに変換します。386 のコネクター、うち 19 は API キー不要。

AnythingMCP:セルフホスト型 MCP ゲートウェイ

@@ -19,7 +19,7 @@

AnythingMCP は、オープンソースのセルフホスト型 MCP ゲートウェイです。MCP サーバーを書かずに、REST/OpenAPI、SOAP、GraphQL、OData、SQL のあらゆるシステムを Claude、ChatGPT、Copilot 用の MCP ツールに変換します。
- SAP、Etsy、weclapp、Amazon Seller などを含む 385 種類の既製アダプターを同梱しており、うち 19 は API キー不要です。 + SAP、Etsy、weclapp、Amazon Seller などを含む 386 種類の既製アダプターを同梱しており、うち 19 は API キー不要です。

@@ -111,7 +111,7 @@ amd64 ではイメージの取得に約 30 秒、その 24 秒後に API が利 ## コネクターカタログ -385 個のアダプターで 2,400 以上のツールを提供しています。どのアダプターにも [anythingmcp.com/ja/guides](https://anythingmcp.com/ja/guides) に 7 言語の設定ガイドがあります。 +386 個のアダプターで 2,400 以上のツールを提供しています。どのアダプターにも [anythingmcp.com/ja/guides](https://anythingmcp.com/ja/guides) に 7 言語の設定ガイドがあります。 | カテゴリー | 例 | |---|---| diff --git a/README.md b/README.md index 20ddb830e..90b8f1ade 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- AnythingMCP turns ERP, e-commerce, REST, SOAP and SQL systems into MCP tools for Claude and ChatGPT: 385 connectors, 19 of them with no API key. + AnythingMCP turns ERP, e-commerce, REST, SOAP and SQL systems into MCP tools for Claude and ChatGPT: 386 connectors, 19 of them with no API key.

AnythingMCP: self-hosted MCP gateway

@@ -19,7 +19,7 @@

AnythingMCP is an open-source, self-hosted MCP gateway that turns any REST/OpenAPI, SOAP, GraphQL, OData or SQL system into MCP tools for Claude, ChatGPT and Copilot, without writing an MCP server.
- It ships 385 ready connectors, among them SAP, Etsy, weclapp and Amazon Seller, and 19 of them need no API key. + It ships 386 ready connectors, among them SAP, Etsy, weclapp and Amazon Seller, and 19 of them need no API key.

@@ -103,7 +103,7 @@ Tools register at runtime, without a restart. Per-connector `{{VAR}}` values are ## Connector catalog -385 adapters, exposing 2,400+ tools. Every one has a setup guide on [anythingmcp.com/guides](https://anythingmcp.com/guides), in seven languages. +386 adapters, exposing 2,400+ tools. Every one has a setup guide on [anythingmcp.com/guides](https://anythingmcp.com/guides), in seven languages. | Category | Examples | |---|---| diff --git a/README.zh-CN.md b/README.zh-CN.md index ef1e7f4d7..02199444c 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -1,5 +1,5 @@

- AnythingMCP 将 ERP、电子商务、REST、SOAP 和 SQL 系统转化为 Claude 和 ChatGPT 可用的 MCP 工具:385 个连接器,其中 19 个无需 API 密钥。 + AnythingMCP 将 ERP、电子商务、REST、SOAP 和 SQL 系统转化为 Claude 和 ChatGPT 可用的 MCP 工具:386 个连接器,其中 19 个无需 API 密钥。

AnythingMCP:自行托管的 MCP 网关

@@ -19,7 +19,7 @@

AnythingMCP 是一个开源、可自行托管的 MCP 网关,无需编写 MCP 服务器,即可将任意 REST/OpenAPI、SOAP、GraphQL、OData 或 SQL 系统转化为 Claude、ChatGPT 和 Copilot 可用的 MCP 工具。
- 它自带 385 个现成适配器,涵盖 SAP、Etsy、weclapp 和 Amazon Seller 等,其中 19 个无需 API 密钥。 + 它自带 386 个现成适配器,涵盖 SAP、Etsy、weclapp 和 Amazon Seller 等,其中 19 个无需 API 密钥。

@@ -111,7 +111,7 @@ docker compose up -d ## 连接器目录 -共 385 个适配器,提供 2,400 多个工具。每个适配器都在 [anythingmcp.com/zh/guides](https://anythingmcp.com/zh/guides) 上提供七种语言的配置指南。 +共 386 个适配器,提供 2,400 多个工具。每个适配器都在 [anythingmcp.com/zh/guides](https://anythingmcp.com/zh/guides) 上提供七种语言的配置指南。 | 类别 | 示例 | |---|---| diff --git a/glama.json b/glama.json index 2182a599e..f97a21102 100644 --- a/glama.json +++ b/glama.json @@ -3,5 +3,5 @@ "maintainers": [ "helpcodeai" ], - "description": "Turn any REST/OpenAPI, SOAP/WSDL, GraphQL, OData or SQL API into MCP tools for Claude, ChatGPT and Copilot, no code. 385 pre-built adapters for ERP and e-commerce (SAP S/4HANA, SAP Business One, Odoo, Xentral, JTL-Wawi, weclapp, Shopware, WooCommerce, Amazon Seller, Kaufland, OTTO\u2026) and more. Self-hosted, knowledge graph, per-tool response mapping, OAuth2/RBAC/SSO/audit. Open source under AGPL-3.0." + "description": "Turn any REST/OpenAPI, SOAP/WSDL, GraphQL, OData or SQL API into MCP tools for Claude, ChatGPT and Copilot, no code. 386 pre-built adapters for ERP and e-commerce (SAP S/4HANA, SAP Business One, Odoo, Xentral, JTL-Wawi, weclapp, Shopware, WooCommerce, Amazon Seller, Kaufland, OTTO\u2026) and more. Self-hosted, knowledge graph, per-tool response mapping, OAuth2/RBAC/SSO/audit. Open source under AGPL-3.0." } diff --git a/package.json b/package.json index c1c3d4614..5c3e99bd6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "anythingmcp", "version": "0.28.0", - "description": "Turn any REST/OpenAPI, SOAP/WSDL, GraphQL, OData or SQL API into MCP tools for Claude, ChatGPT and Copilot, no code. 385 pre-built adapters for ERP, e-commerce and more (SAP S/4HANA, SAP Business One, Odoo, Xentral, JTL-Wawi, Shopware, WooCommerce, Amazon Seller). Self-hosted, open source (AGPL-3.0).", + "description": "Turn any REST/OpenAPI, SOAP/WSDL, GraphQL, OData or SQL API into MCP tools for Claude, ChatGPT and Copilot, no code. 386 pre-built adapters for ERP, e-commerce and more (SAP S/4HANA, SAP Business One, Odoo, Xentral, JTL-Wawi, Shopware, WooCommerce, Amazon Seller). Self-hosted, open source (AGPL-3.0).", "private": true, "license": "AGPL-3.0-only", "engines": { diff --git a/packages/backend/src/adapters/catalog.ts b/packages/backend/src/adapters/catalog.ts index 993b84de2..fc45ab1a8 100644 --- a/packages/backend/src/adapters/catalog.ts +++ b/packages/backend/src/adapters/catalog.ts @@ -383,6 +383,7 @@ import * as quipu from './es/quipu.json'; import * as axonaut from './fr/axonaut.json'; import * as dolibarr from './fr/dolibarr.json'; import * as pennylane from './fr/pennylane.json'; +import * as qonto from './fr/qonto.json'; import * as sellsy from './fr/sellsy.json'; import * as afasProfit from './nl/afas-profit.json'; import * as exactOnline from './nl/exact-online.json'; @@ -984,6 +985,7 @@ const RAW_ADAPTERS: AdapterDefinition[] = [ axonaut as unknown as AdapterDefinition, dolibarr as unknown as AdapterDefinition, pennylane as unknown as AdapterDefinition, + qonto as unknown as AdapterDefinition, sellsy as unknown as AdapterDefinition, afasProfit as unknown as AdapterDefinition, exactOnline as unknown as AdapterDefinition, diff --git a/packages/backend/src/adapters/fr/qonto.json b/packages/backend/src/adapters/fr/qonto.json new file mode 100644 index 000000000..14901a4eb --- /dev/null +++ b/packages/backend/src/adapters/fr/qonto.json @@ -0,0 +1,339 @@ +{ + "slug": "qonto", + "name": "Qonto", + "description": "Qonto — French business account for SMBs and freelancers: organization and bank accounts, transactions, client and supplier invoices, clients and quotes. Official Business API v2, read-only, login:secret-key API key. 7 tools.", + "instructions": "This connector reads your **Qonto** business account through the official Business API: organization and bank accounts, transactions, client invoices, supplier invoices, clients and quotes. It is **read-only**: every tool is a GET, so it cannot send transfers, add beneficiaries, touch cards or create, edit or delete invoices.\n\n**Getting the credentials**\n1. Sign in to the Qonto web app (https://app.qonto.com) and, if you have several organizations, pick the one to connect.\n2. Open **Integrations & Partnerships → API key** and click **Generate** if no secret key exists yet.\n3. Put the **login** (sign-in, e.g. `pied-piper-7132`) in `QONTO_LOGIN` and the **secret key** in `QONTO_SECRET_KEY`.\n\n**How authentication works**: Qonto expects `Authorization: :`. This looks like HTTP Basic but is not: no Base64 and no `Bearer` prefix. A 401 almost always means a wrong login or secret.\n\n**Bank data is sensitive.** The connector sees every bank account of the organization. Assign it only to MCP servers whose users are allowed to see the company's bank accounts and transactions.\n\n**Workflow**: call `qonto_get_organization` first to get the bank account `id` (or IBAN); `qonto_list_transactions` works on one account at a time and needs one of them.\n\n**Pagination**: list tools take `page` and `per_page` (1 to 100, default 100); responses carry `meta.next_page` and `meta.total_pages`.\n\n**Amounts**: transactions expose `amount` and `amount_cents`; prefer the cents for arithmetic.\n\n**Sandbox**: create an application on the Qonto Developer Portal (https://developers.qonto.com) to get a sandbox organization and a personal staging token. After install, edit the connector: set the base URL to `https://thirdparty-sandbox.staging.qonto.co/v2` and add the header `X-Qonto-Staging-Token: ` (case-sensitive). Without it, sandbox calls return a OneLogin HTML page instead of JSON. The staging token is not accepted in production.\n\n**Cloud reachability**: thirdparty.qonto.com is public with a valid certificate.", + "region": "fr", + "category": "banking", + "icon": "qonto", + "docsUrl": "https://docs.qonto.com/", + "requiredEnvVars": [ + "QONTO_LOGIN", + "QONTO_SECRET_KEY" + ], + "probe": { + "tool": "qonto_get_organization" + }, + "connector": { + "name": "Qonto Business API v2", + "type": "REST", + "baseUrl": "https://thirdparty.qonto.com/v2", + "authType": "API_KEY", + "authConfig": { + "headerName": "Authorization", + "apiKey": "{{QONTO_LOGIN}}:{{QONTO_SECRET_KEY}}" + }, + "headers": { + "Accept": "application/json" + } + }, + "tools": [ + { + "name": "qonto_get_organization", + "description": "Get the Qonto organization: legal name, slug and every bank account with its id, IBAN, BIC, currency, balance and status. Call this first: qonto_list_transactions needs a bank account id or IBAN from here.", + "parameters": { + "type": "object", + "properties": {} + }, + "endpointMapping": { + "method": "GET", + "path": "/organization" + } + }, + { + "name": "qonto_list_transactions", + "description": "List transactions of ONE bank account. Requires bank_account_id or iban taken from qonto_get_organization first. Filter by settled/emitted date range, side (credit/debit), status and operation type; paginated with page/per_page.", + "parameters": { + "type": "object", + "properties": { + "bank_account_id": { + "type": "string", + "description": "Bank account id from qonto_get_organization. Takes precedence over iban when both are set." + }, + "iban": { + "type": "string", + "description": "IBAN of the bank account, from qonto_get_organization." + }, + "settled_at_from": { + "type": "string", + "description": "ISO 8601 timestamp; only transactions settled at or after it." + }, + "settled_at_to": { + "type": "string", + "description": "ISO 8601 timestamp; only transactions settled at or before it." + }, + "emitted_at_from": { + "type": "string", + "description": "ISO 8601 timestamp; only transactions emitted at or after it." + }, + "emitted_at_to": { + "type": "string", + "description": "ISO 8601 timestamp; only transactions emitted at or before it." + }, + "side": { + "type": "string", + "description": "credit (money in) or debit (money out)." + }, + "status": { + "type": "string", + "description": "Transaction status, e.g. pending, declined, completed (sent as status[])." + }, + "operation_type": { + "type": "string", + "description": "Operation type, e.g. card, transfer, direct_debit, income (sent as operation_type[])." + }, + "with_attachments": { + "type": "boolean", + "description": "true to keep only transactions with attachments, false for those without." + }, + "sort_by": { + "type": "string", + "description": "Sort order, e.g. settled_at:desc." + }, + "page": { + "type": "integer", + "description": "Page number, starting at 1 (Qonto default 1)." + }, + "per_page": { + "type": "integer", + "description": "Items per page, 1 to 100 (Qonto default 100)." + } + } + }, + "endpointMapping": { + "method": "GET", + "path": "/transactions", + "queryParams": { + "bank_account_id": "$bank_account_id", + "iban": "$iban", + "settled_at_from": "$settled_at_from", + "settled_at_to": "$settled_at_to", + "emitted_at_from": "$emitted_at_from", + "emitted_at_to": "$emitted_at_to", + "side": "$side", + "status[]": "$status", + "operation_type[]": "$operation_type", + "with_attachments": "$with_attachments", + "sort_by": "$sort_by", + "page": "$page", + "per_page": "$per_page" + } + } + }, + { + "name": "qonto_get_transaction", + "description": "Get one transaction by its id: amount, currency, side, counterparty, label, status, operation type, dates, category and attachment ids. Use ids returned by qonto_list_transactions.", + "parameters": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Transaction id (UUID) from qonto_list_transactions." + } + }, + "required": [ + "id" + ] + }, + "endpointMapping": { + "method": "GET", + "path": "/transactions/{id}" + } + }, + { + "name": "qonto_list_client_invoices", + "description": "List the client invoices the organization issued from Qonto, filtered by status and by due date, creation or update date ranges. Answers questions like unpaid invoices due this week.", + "parameters": { + "type": "object", + "properties": { + "status": { + "type": "string", + "description": "Invoice status, e.g. draft, unpaid, paid, canceled (filter[status])." + }, + "due_date_from": { + "type": "string", + "description": "Date YYYY-MM-DD; due on or after (filter[due_date_from])." + }, + "due_date_to": { + "type": "string", + "description": "Date YYYY-MM-DD; due on or before (filter[due_date_to])." + }, + "created_at_from": { + "type": "string", + "description": "ISO 8601; created on or after (filter[created_at_from])." + }, + "created_at_to": { + "type": "string", + "description": "ISO 8601; created on or before (filter[created_at_to])." + }, + "sort_by": { + "type": "string", + "description": "Sort order, e.g. created_at:desc." + }, + "page": { + "type": "integer", + "description": "Page number, starting at 1 (Qonto default 1)." + }, + "per_page": { + "type": "integer", + "description": "Items per page, 1 to 100 (Qonto default 100)." + } + } + }, + "endpointMapping": { + "method": "GET", + "path": "/client_invoices", + "queryParams": { + "filter[status]": "$status", + "filter[due_date_from]": "$due_date_from", + "filter[due_date_to]": "$due_date_to", + "filter[created_at_from]": "$created_at_from", + "filter[created_at_to]": "$created_at_to", + "sort_by": "$sort_by", + "page": "$page", + "per_page": "$per_page" + } + } + }, + { + "name": "qonto_list_supplier_invoices", + "description": "List supplier invoices received in Qonto, filtered by status, creation date and a free-text query (supplier name, invoice number). Useful to find bills to pay or missing documents.", + "parameters": { + "type": "object", + "properties": { + "status": { + "type": "string", + "description": "Supplier invoice status, e.g. to_review, to_pay, paid (filter[status])." + }, + "created_at_from": { + "type": "string", + "description": "ISO 8601; created on or after (filter[created_at_from])." + }, + "created_at_to": { + "type": "string", + "description": "ISO 8601; created on or before (filter[created_at_to])." + }, + "query": { + "type": "string", + "description": "Free-text search over supplier name, invoice number and similar fields." + }, + "sort_by": { + "type": "string", + "description": "Sort order, e.g. created_at:desc." + }, + "page": { + "type": "integer", + "description": "Page number, starting at 1 (Qonto default 1)." + }, + "per_page": { + "type": "integer", + "description": "Items per page, 1 to 100 (Qonto default 100)." + } + } + }, + "endpointMapping": { + "method": "GET", + "path": "/supplier_invoices", + "queryParams": { + "filter[status]": "$status", + "filter[created_at_from]": "$created_at_from", + "filter[created_at_to]": "$created_at_to", + "query": "$query", + "sort_by": "$sort_by", + "page": "$page", + "per_page": "$per_page" + } + } + }, + { + "name": "qonto_list_clients", + "description": "List the clients (customers) in the Qonto invoicing address book, optionally filtered by name, VAT number or email. Returns ids, contact data and billing addresses.", + "parameters": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Filter by client name (filter[name])." + }, + "vat_number": { + "type": "string", + "description": "Filter by VAT number (filter[vat_number])." + }, + "email": { + "type": "string", + "description": "Filter by email (filter[email])." + }, + "sort_by": { + "type": "string", + "description": "Sort order, e.g. name:asc." + }, + "page": { + "type": "integer", + "description": "Page number, starting at 1 (Qonto default 1)." + }, + "per_page": { + "type": "integer", + "description": "Items per page, 1 to 100 (Qonto default 100)." + } + } + }, + "endpointMapping": { + "method": "GET", + "path": "/clients", + "queryParams": { + "filter[name]": "$name", + "filter[vat_number]": "$vat_number", + "filter[email]": "$email", + "sort_by": "$sort_by", + "page": "$page", + "per_page": "$per_page" + } + } + }, + { + "name": "qonto_list_quotes", + "description": "List the quotes (devis) created in Qonto, filtered by status and creation date range, with client, amounts, validity and status. Read-only: it cannot create or send quotes.", + "parameters": { + "type": "object", + "properties": { + "status": { + "type": "string", + "description": "Quote status, e.g. pending_approval, approved, canceled (filter[status])." + }, + "created_at_from": { + "type": "string", + "description": "ISO 8601; created on or after (filter[created_at_from])." + }, + "created_at_to": { + "type": "string", + "description": "ISO 8601; created on or before (filter[created_at_to])." + }, + "sort_by": { + "type": "string", + "description": "Sort order, e.g. created_at:desc." + }, + "page": { + "type": "integer", + "description": "Page number, starting at 1 (Qonto default 1)." + }, + "per_page": { + "type": "integer", + "description": "Items per page, 1 to 100 (Qonto default 100)." + } + } + }, + "endpointMapping": { + "method": "GET", + "path": "/quotes", + "queryParams": { + "filter[status]": "$status", + "filter[created_at_from]": "$created_at_from", + "filter[created_at_to]": "$created_at_to", + "sort_by": "$sort_by", + "page": "$page", + "per_page": "$per_page" + } + } + } + ] +} diff --git a/packages/backend/src/adapters/fr/qonto.live.spec.ts b/packages/backend/src/adapters/fr/qonto.live.spec.ts new file mode 100644 index 000000000..e4e175234 --- /dev/null +++ b/packages/backend/src/adapters/fr/qonto.live.spec.ts @@ -0,0 +1,90 @@ +import * as adapter from './qonto.json'; + +const a = adapter as unknown as { + category: string; + requiredEnvVars: string[]; + instructions: string; + probe: { tool: string }; + connector: { baseUrl: string; authType: string; authConfig: Record }; + tools: Array<{ name: string; description: string; endpointMapping: { method: string; path: string } }>; +}; + +// Values from docs.qonto.com: "API key" authentication page, "Pagination", +// "Accessing the Sandbox environment" and the Business API v2 reference. +describe('qonto adapter — static spec conformance', () => { + it('calls the production Business API v2', () => + expect(a.connector.baseUrl).toBe('https://thirdparty.qonto.com/v2')); + + it('sends login:secret-key in Authorization, no Bearer, no Base64', () => { + expect(a.connector.authType).toBe('API_KEY'); + expect(a.connector.authConfig.headerName).toBe('Authorization'); + expect(a.connector.authConfig.apiKey).toBe('{{QONTO_LOGIN}}:{{QONTO_SECRET_KEY}}'); + expect(a.connector.authConfig.apiKey).toContain(':'); + expect(a.connector.authConfig.apiKey).not.toMatch(/bearer|basic/i); + expect(a.requiredEnvVars).toEqual(['QONTO_LOGIN', 'QONTO_SECRET_KEY']); + }); + + it('only reads: every tool is a GET', () => { + for (const tool of a.tools) { + expect(['POST', 'PUT', 'PATCH', 'DELETE']).not.toContain(tool.endpointMapping.method); + expect(tool.endpointMapping.method).toBe('GET'); + } + }); + + it('uses the documented endpoint paths', () => { + expect(Object.fromEntries(a.tools.map((t) => [t.name, t.endpointMapping.path]))).toEqual({ + qonto_get_organization: '/organization', + qonto_list_transactions: '/transactions', + qonto_get_transaction: '/transactions/{id}', + qonto_list_client_invoices: '/client_invoices', + qonto_list_supplier_invoices: '/supplier_invoices', + qonto_list_clients: '/clients', + qonto_list_quotes: '/quotes', + }); + }); + + it('is a banking adapter probed with the organization', () => { + expect(a.category).toBe('banking'); + expect(a.probe.tool).toBe('qonto_get_organization'); + }); + + it('tells the agent to fetch a bank account before listing transactions', () => { + const tx = a.tools.find((t) => t.name === 'qonto_list_transactions')!; + expect(tx.description).toContain('qonto_get_organization'); + }); + + it('documents the sandbox host and staging header', () => { + expect(a.instructions).toContain('https://thirdparty-sandbox.staging.qonto.co/v2'); + expect(a.instructions).toContain('X-Qonto-Staging-Token'); + }); +}); + +// Opt-in live check against the Qonto sandbox. Needs QONTO_LOGIN, +// QONTO_SECRET_KEY and QONTO_STAGING_TOKEN; QONTO_BASE_URL overrides the host. +const live = process.env.RUN_QONTO_LIVE === '1'; +(live ? describe : describe.skip)('qonto — live (sandbox)', () => { + const base = process.env.QONTO_BASE_URL ?? 'https://thirdparty-sandbox.staging.qonto.co/v2'; + const headers: Record = { + Authorization: `${process.env.QONTO_LOGIN}:${process.env.QONTO_SECRET_KEY}`, + Accept: 'application/json', + }; + if (process.env.QONTO_STAGING_TOKEN) headers['X-Qonto-Staging-Token'] = process.env.QONTO_STAGING_TOKEN; + + let accountId: string | undefined; + + it('reads the organization and its bank accounts', async () => { + const res = await fetch(`${base}/organization`, { headers }); + expect(res.status).toBe(200); + const body = (await res.json()) as { organization: { bank_accounts: Array<{ id: string }> } }; + accountId = body.organization.bank_accounts[0]?.id; + expect(accountId).toBeTruthy(); + }); + + it('lists transactions of the first bank account', async () => { + const res = await fetch(`${base}/transactions?bank_account_id=${accountId}&per_page=5`, { headers }); + expect(res.status).toBe(200); + const body = (await res.json()) as { transactions: unknown[]; meta: { current_page: number } }; + expect(Array.isArray(body.transactions)).toBe(true); + expect(body.meta.current_page).toBe(1); + }); +}); diff --git a/packages/frontend/public/logos/connectors/qonto.svg b/packages/frontend/public/logos/connectors/qonto.svg new file mode 100644 index 000000000..c12a668ec --- /dev/null +++ b/packages/frontend/public/logos/connectors/qonto.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/server.json b/server.json index 33ecf0ec1..bfe893eb2 100644 --- a/server.json +++ b/server.json @@ -2,7 +2,7 @@ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", "name": "io.github.HelpCode-ai/anythingmcp", "title": "AnythingMCP", - "description": "Any REST/SOAP/GraphQL/OData/SQL API as MCP tools for Claude & ChatGPT. 385 connectors: SAP, ERP.", + "description": "Any REST/SOAP/GraphQL/OData/SQL API as MCP tools for Claude & ChatGPT. 386 connectors: SAP, ERP.", "repository": { "url": "https://github.com/HelpCode-ai/anythingmcp", "source": "github" From 2994eea557f2ce305a6093ea4e629bb66da09501 Mon Sep 17 00:00:00 2001 From: GallaGit <230304929+GallaGit@users.noreply.github.com> Date: Tue, 13 Oct 2026 16:57:25 +0200 Subject: [PATCH 2/3] fix(adapters): refine Qonto tool docs and filters after review (#1013) - soften bank_account_id/iban wording (recommended, pending verification) - transactions: document completed-only default, add reversed, one status per call - client invoices: add filter[updated_at_from/to] - supplier invoices: use to_review instead of deprecated to_pay, expose query_fields --- packages/backend/src/adapters/fr/qonto.json | 27 ++++++++++++++----- .../src/adapters/fr/qonto.live.spec.ts | 7 +++++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/packages/backend/src/adapters/fr/qonto.json b/packages/backend/src/adapters/fr/qonto.json index 14901a4eb..9527d8f40 100644 --- a/packages/backend/src/adapters/fr/qonto.json +++ b/packages/backend/src/adapters/fr/qonto.json @@ -2,7 +2,7 @@ "slug": "qonto", "name": "Qonto", "description": "Qonto — French business account for SMBs and freelancers: organization and bank accounts, transactions, client and supplier invoices, clients and quotes. Official Business API v2, read-only, login:secret-key API key. 7 tools.", - "instructions": "This connector reads your **Qonto** business account through the official Business API: organization and bank accounts, transactions, client invoices, supplier invoices, clients and quotes. It is **read-only**: every tool is a GET, so it cannot send transfers, add beneficiaries, touch cards or create, edit or delete invoices.\n\n**Getting the credentials**\n1. Sign in to the Qonto web app (https://app.qonto.com) and, if you have several organizations, pick the one to connect.\n2. Open **Integrations & Partnerships → API key** and click **Generate** if no secret key exists yet.\n3. Put the **login** (sign-in, e.g. `pied-piper-7132`) in `QONTO_LOGIN` and the **secret key** in `QONTO_SECRET_KEY`.\n\n**How authentication works**: Qonto expects `Authorization: :`. This looks like HTTP Basic but is not: no Base64 and no `Bearer` prefix. A 401 almost always means a wrong login or secret.\n\n**Bank data is sensitive.** The connector sees every bank account of the organization. Assign it only to MCP servers whose users are allowed to see the company's bank accounts and transactions.\n\n**Workflow**: call `qonto_get_organization` first to get the bank account `id` (or IBAN); `qonto_list_transactions` works on one account at a time and needs one of them.\n\n**Pagination**: list tools take `page` and `per_page` (1 to 100, default 100); responses carry `meta.next_page` and `meta.total_pages`.\n\n**Amounts**: transactions expose `amount` and `amount_cents`; prefer the cents for arithmetic.\n\n**Sandbox**: create an application on the Qonto Developer Portal (https://developers.qonto.com) to get a sandbox organization and a personal staging token. After install, edit the connector: set the base URL to `https://thirdparty-sandbox.staging.qonto.co/v2` and add the header `X-Qonto-Staging-Token: ` (case-sensitive). Without it, sandbox calls return a OneLogin HTML page instead of JSON. The staging token is not accepted in production.\n\n**Cloud reachability**: thirdparty.qonto.com is public with a valid certificate.", + "instructions": "This connector reads your **Qonto** business account through the official Business API: organization and bank accounts, transactions, client invoices, supplier invoices, clients and quotes. It is **read-only**: every tool is a GET, so it cannot send transfers, add beneficiaries, touch cards or create, edit or delete invoices.\n\n**Getting the credentials**\n1. Sign in to the Qonto web app (https://app.qonto.com) and, if you have several organizations, pick the one to connect.\n2. Open **Integrations & Partnerships → API key** and click **Generate** if no secret key exists yet.\n3. Put the **login** (sign-in, e.g. `pied-piper-7132`) in `QONTO_LOGIN` and the **secret key** in `QONTO_SECRET_KEY`.\n\n**How authentication works**: Qonto expects `Authorization: :`. This looks like HTTP Basic but is not: no Base64 and no `Bearer` prefix. A 401 almost always means a wrong login or secret.\n\n**Bank data is sensitive.** The connector sees every bank account of the organization. Assign it only to MCP servers whose users are allowed to see the company's bank accounts and transactions.\n\n**Workflow**: call `qonto_get_organization` first to get the bank account `id` (or IBAN); `qonto_list_transactions` lists one account at a time; passing `bank_account_id` or `iban` is recommended (whether Qonto rejects a call without them is pending verification).\n\n**Pagination**: list tools take `page` and `per_page` (1 to 100, default 100); responses carry `meta.next_page` and `meta.total_pages`.\n\n**Amounts**: transactions expose `amount` and `amount_cents`; prefer the cents for arithmetic.\n\n**Sandbox**: create an application on the Qonto Developer Portal (https://developers.qonto.com) to get a sandbox organization and a personal staging token. After install, edit the connector: set the base URL to `https://thirdparty-sandbox.staging.qonto.co/v2` and add the header `X-Qonto-Staging-Token: ` (case-sensitive). Without it, sandbox calls return a OneLogin HTML page instead of JSON. The staging token is not accepted in production.\n\n**Cloud reachability**: thirdparty.qonto.com is public with a valid certificate.", "region": "fr", "category": "banking", "icon": "qonto", @@ -42,7 +42,7 @@ }, { "name": "qonto_list_transactions", - "description": "List transactions of ONE bank account. Requires bank_account_id or iban taken from qonto_get_organization first. Filter by settled/emitted date range, side (credit/debit), status and operation type; paginated with page/per_page.", + "description": "List transactions of one bank account. Pass bank_account_id or iban (recommended; call qonto_get_organization first to get them, a call without them is pending verification). Without a status filter Qonto returns only completed transactions. Filter by date range, side, status and operation type; paginated.", "parameters": { "type": "object", "properties": { @@ -76,7 +76,7 @@ }, "status": { "type": "string", - "description": "Transaction status, e.g. pending, declined, completed (sent as status[])." + "description": "One status per call: pending, declined, completed or reversed (sent as status[]). When omitted, Qonto returns only completed transactions, so set it to see pending or declined ones." }, "operation_type": { "type": "string", @@ -177,6 +177,14 @@ "per_page": { "type": "integer", "description": "Items per page, 1 to 100 (Qonto default 100)." + }, + "updated_at_from": { + "type": "string", + "description": "ISO 8601; updated on or after (filter[updated_at_from])." + }, + "updated_at_to": { + "type": "string", + "description": "ISO 8601; updated on or before (filter[updated_at_to])." } } }, @@ -189,6 +197,8 @@ "filter[due_date_to]": "$due_date_to", "filter[created_at_from]": "$created_at_from", "filter[created_at_to]": "$created_at_to", + "filter[updated_at_from]": "$updated_at_from", + "filter[updated_at_to]": "$updated_at_to", "sort_by": "$sort_by", "page": "$page", "per_page": "$per_page" @@ -197,13 +207,13 @@ }, { "name": "qonto_list_supplier_invoices", - "description": "List supplier invoices received in Qonto, filtered by status, creation date and a free-text query (supplier name, invoice number). Useful to find bills to pay or missing documents.", + "description": "List supplier invoices received in Qonto, filtered by status, creation date and a free-text query over the fields named in query_fields. Useful to find bills to review or pay, or missing documents.", "parameters": { "type": "object", "properties": { "status": { "type": "string", - "description": "Supplier invoice status, e.g. to_review, to_pay, paid (filter[status])." + "description": "Supplier invoice status, e.g. to_review, to_approve, awaiting_payment, pending, paid (filter[status]). to_pay is deprecated by Qonto; use to_review." }, "created_at_from": { "type": "string", @@ -215,7 +225,11 @@ }, "query": { "type": "string", - "description": "Free-text search over supplier name, invoice number and similar fields." + "description": "Free-text search; Qonto applies it to the fields listed in query_fields." + }, + "query_fields": { + "type": "string", + "description": "Comma-separated fields searched by query, e.g. supplier_name,amount,file_name,invoice_number." }, "sort_by": { "type": "string", @@ -239,6 +253,7 @@ "filter[created_at_from]": "$created_at_from", "filter[created_at_to]": "$created_at_to", "query": "$query", + "query_fields": "$query_fields", "sort_by": "$sort_by", "page": "$page", "per_page": "$per_page" diff --git a/packages/backend/src/adapters/fr/qonto.live.spec.ts b/packages/backend/src/adapters/fr/qonto.live.spec.ts index e4e175234..d762caa56 100644 --- a/packages/backend/src/adapters/fr/qonto.live.spec.ts +++ b/packages/backend/src/adapters/fr/qonto.live.spec.ts @@ -51,6 +51,13 @@ describe('qonto adapter — static spec conformance', () => { it('tells the agent to fetch a bank account before listing transactions', () => { const tx = a.tools.find((t) => t.name === 'qonto_list_transactions')!; expect(tx.description).toContain('qonto_get_organization'); + expect(tx.description).toContain('only completed'); + }); + + it('does not suggest the deprecated to_pay supplier invoice status as a filter', () => { + const si = a.tools.find((t) => t.name === 'qonto_list_supplier_invoices')!; + expect(JSON.stringify(si)).toContain('to_review'); + expect(JSON.stringify(si)).toContain('query_fields'); }); it('documents the sandbox host and staging header', () => { From 91940c1bffab2be2a607019a96e6237a5647215d Mon Sep 17 00:00:00 2001 From: GallaGit <230304929+GallaGit@users.noreply.github.com> Date: Wed, 14 Oct 2026 22:10:51 +0200 Subject: [PATCH 3/3] fix(adapters): mark Qonto unverified and encode transaction id path param (#1013) --- packages/backend/src/adapters/fr/qonto.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/adapters/fr/qonto.json b/packages/backend/src/adapters/fr/qonto.json index 9527d8f40..039224d99 100644 --- a/packages/backend/src/adapters/fr/qonto.json +++ b/packages/backend/src/adapters/fr/qonto.json @@ -2,7 +2,7 @@ "slug": "qonto", "name": "Qonto", "description": "Qonto — French business account for SMBs and freelancers: organization and bank accounts, transactions, client and supplier invoices, clients and quotes. Official Business API v2, read-only, login:secret-key API key. 7 tools.", - "instructions": "This connector reads your **Qonto** business account through the official Business API: organization and bank accounts, transactions, client invoices, supplier invoices, clients and quotes. It is **read-only**: every tool is a GET, so it cannot send transfers, add beneficiaries, touch cards or create, edit or delete invoices.\n\n**Getting the credentials**\n1. Sign in to the Qonto web app (https://app.qonto.com) and, if you have several organizations, pick the one to connect.\n2. Open **Integrations & Partnerships → API key** and click **Generate** if no secret key exists yet.\n3. Put the **login** (sign-in, e.g. `pied-piper-7132`) in `QONTO_LOGIN` and the **secret key** in `QONTO_SECRET_KEY`.\n\n**How authentication works**: Qonto expects `Authorization: :`. This looks like HTTP Basic but is not: no Base64 and no `Bearer` prefix. A 401 almost always means a wrong login or secret.\n\n**Bank data is sensitive.** The connector sees every bank account of the organization. Assign it only to MCP servers whose users are allowed to see the company's bank accounts and transactions.\n\n**Workflow**: call `qonto_get_organization` first to get the bank account `id` (or IBAN); `qonto_list_transactions` lists one account at a time; passing `bank_account_id` or `iban` is recommended (whether Qonto rejects a call without them is pending verification).\n\n**Pagination**: list tools take `page` and `per_page` (1 to 100, default 100); responses carry `meta.next_page` and `meta.total_pages`.\n\n**Amounts**: transactions expose `amount` and `amount_cents`; prefer the cents for arithmetic.\n\n**Sandbox**: create an application on the Qonto Developer Portal (https://developers.qonto.com) to get a sandbox organization and a personal staging token. After install, edit the connector: set the base URL to `https://thirdparty-sandbox.staging.qonto.co/v2` and add the header `X-Qonto-Staging-Token: ` (case-sensitive). Without it, sandbox calls return a OneLogin HTML page instead of JSON. The staging token is not accepted in production.\n\n**Cloud reachability**: thirdparty.qonto.com is public with a valid certificate.", + "instructions": "This connector reads your **Qonto** business account through the official Business API: organization and bank accounts, transactions, client invoices, supplier invoices, clients and quotes. It is **read-only**: every tool is a GET, so it cannot send transfers, add beneficiaries, touch cards or create, edit or delete invoices.\n\n**Getting the credentials**\n1. Sign in to the Qonto web app (https://app.qonto.com) and, if you have several organizations, pick the one to connect.\n2. Open **Integrations & Partnerships → API key** and click **Generate** if no secret key exists yet.\n3. Put the **login** (sign-in, e.g. `pied-piper-7132`) in `QONTO_LOGIN` and the **secret key** in `QONTO_SECRET_KEY`.\n\n**How authentication works**: Qonto expects `Authorization: :`. This looks like HTTP Basic but is not: no Base64 and no `Bearer` prefix. A 401 almost always means a wrong login or secret.\n\n**Bank data is sensitive.** The connector sees every bank account of the organization. Assign it only to MCP servers whose users are allowed to see the company's bank accounts and transactions.\n\n**Workflow**: call `qonto_get_organization` first to get the bank account `id` (or IBAN); `qonto_list_transactions` lists one account at a time; passing `bank_account_id` or `iban` is recommended (whether Qonto rejects a call without them is pending verification).\n\n**Pagination**: list tools take `page` and `per_page` (1 to 100, default 100); responses carry `meta.next_page` and `meta.total_pages`.\n\n**Amounts**: transactions expose `amount` and `amount_cents`; prefer the cents for arithmetic.\n\n**Unverified.** This adapter has not been exercised against a live Qonto account yet. Two points still need confirming with a real account: the exact `Authorization: :` header format, and whether `/transactions` requires `bank_account_id` or `iban`. A correction from anyone running it against a real organization is welcome.\n\n**Sandbox**: create an application on the Qonto Developer Portal (https://developers.qonto.com) to get a sandbox organization and a personal staging token. After install, edit the connector: set the base URL to `https://thirdparty-sandbox.staging.qonto.co/v2` and add the header `X-Qonto-Staging-Token: ` (case-sensitive). Without it, sandbox calls return a OneLogin HTML page instead of JSON. The staging token is not accepted in production.\n\n**Cloud reachability**: thirdparty.qonto.com is public with a valid certificate.", "region": "fr", "category": "banking", "icon": "qonto", @@ -137,7 +137,8 @@ }, "endpointMapping": { "method": "GET", - "path": "/transactions/{id}" + "path": "/transactions/{id}", + "encodePathParams": true } }, {