Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -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 475 pre-built adapters, with a focus on ERP and e-commerce
It ships 477 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,
Expand Down
6 changes: 3 additions & 3 deletions README.de.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<p align="center">
<img src="https://raw.githubusercontent.com/HelpCode-ai/anythingmcp/badges/banner.de.png" alt="AnythingMCP macht ERP-, E-Commerce-, REST-, SOAP- und SQL-Systeme zu MCP-Tools für Claude und ChatGPT: 475 Connectors, 20 davon ohne API-Schlüssel." width="100%" />
<img src="https://raw.githubusercontent.com/HelpCode-ai/anythingmcp/badges/banner.de.png" alt="AnythingMCP macht ERP-, E-Commerce-, REST-, SOAP- und SQL-Systeme zu MCP-Tools für Claude und ChatGPT: 477 Connectors, 20 davon ohne API-Schlüssel." width="100%" />
</p>

<h1 align="center">AnythingMCP: selbst gehostetes MCP-Gateway</h1>
Expand All @@ -19,7 +19,7 @@

<p align="center">
<strong>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.</strong><br/>
Es bringt 475 fertige Adapter mit, darunter SAP, Etsy, weclapp und Amazon Seller; 20 davon kommen ohne API-Schlüssel aus.
Es bringt 477 fertige Adapter mit, darunter SAP, Etsy, weclapp und Amazon Seller; 20 davon kommen ohne API-Schlüssel aus.
</p>

<p align="center">
Expand Down Expand Up @@ -111,7 +111,7 @@ Tools werden zur Laufzeit registriert, ohne Neustart. `{{VAR}}`-Werte pro Connec

## Connector-Katalog

475 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.
477 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 |
|---|---|
Expand Down
6 changes: 3 additions & 3 deletions README.ja.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<p align="center">
<img src="https://raw.githubusercontent.com/HelpCode-ai/anythingmcp/badges/banner.ja.png" alt="AnythingMCP は ERP、E コマース、REST、SOAP、SQL の各システムを Claude と ChatGPT 用の MCP ツールに変換します。475 のコネクター、うち 20 は API キー不要。" width="100%" />
<img src="https://raw.githubusercontent.com/HelpCode-ai/anythingmcp/badges/banner.ja.png" alt="AnythingMCP は ERP、E コマース、REST、SOAP、SQL の各システムを Claude と ChatGPT 用の MCP ツールに変換します。477 のコネクター、うち 20 は API キー不要。" width="100%" />
</p>

<h1 align="center">AnythingMCP:セルフホスト型 MCP ゲートウェイ</h1>
Expand All @@ -19,7 +19,7 @@

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

<p align="center">
Expand Down Expand Up @@ -111,7 +111,7 @@ amd64 ではイメージの取得に約 30 秒、その 24 秒後に API が利

## コネクターカタログ

475 個のアダプターで 2,400 以上のツールを提供しています。どのアダプターにも [anythingmcp.com/ja/guides](https://anythingmcp.com/ja/guides) に 7 言語の設定ガイドがあります。
477 個のアダプターで 2,400 以上のツールを提供しています。どのアダプターにも [anythingmcp.com/ja/guides](https://anythingmcp.com/ja/guides) に 7 言語の設定ガイドがあります。

| カテゴリー | 例 |
|---|---|
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<p align="center">
<img src="https://raw.githubusercontent.com/HelpCode-ai/anythingmcp/badges/banner.png" alt="AnythingMCP turns ERP, e-commerce, REST, SOAP and SQL systems into MCP tools for Claude and ChatGPT: 475 connectors, 20 of them with no API key." width="100%" />
<img src="https://raw.githubusercontent.com/HelpCode-ai/anythingmcp/badges/banner.png" alt="AnythingMCP turns ERP, e-commerce, REST, SOAP and SQL systems into MCP tools for Claude and ChatGPT: 477 connectors, 20 of them with no API key." width="100%" />
</p>

<h1 align="center">AnythingMCP: self-hosted MCP gateway</h1>
Expand All @@ -19,7 +19,7 @@

<p align="center">
<strong>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.</strong><br/>
It ships 475 ready connectors, among them SAP, Etsy, weclapp and Amazon Seller, and 20 of them need no API key.
It ships 477 ready connectors, among them SAP, Etsy, weclapp and Amazon Seller, and 20 of them need no API key.
</p>

<p align="center">
Expand Down Expand Up @@ -103,7 +103,7 @@ Tools register at runtime, without a restart. Per-connector `{{VAR}}` values are

## Connector catalog

475 adapters, exposing 2,400+ tools. Every one has a setup guide on [anythingmcp.com/guides](https://anythingmcp.com/guides), in seven languages.
477 adapters, exposing 2,400+ tools. Every one has a setup guide on [anythingmcp.com/guides](https://anythingmcp.com/guides), in seven languages.

| Category | Examples |
|---|---|
Expand Down
6 changes: 3 additions & 3 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<p align="center">
<img src="https://raw.githubusercontent.com/HelpCode-ai/anythingmcp/badges/banner.zh-CN.png" alt="AnythingMCP 将 ERP、电子商务、REST、SOAP 和 SQL 系统转化为 Claude 和 ChatGPT 可用的 MCP 工具:475 个连接器,其中 20 个无需 API 密钥。" width="100%" />
<img src="https://raw.githubusercontent.com/HelpCode-ai/anythingmcp/badges/banner.zh-CN.png" alt="AnythingMCP 将 ERP、电子商务、REST、SOAP 和 SQL 系统转化为 Claude 和 ChatGPT 可用的 MCP 工具:477 个连接器,其中 20 个无需 API 密钥。" width="100%" />
</p>

<h1 align="center">AnythingMCP:自行托管的 MCP 网关</h1>
Expand All @@ -19,7 +19,7 @@

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

<p align="center">
Expand Down Expand Up @@ -111,7 +111,7 @@ docker compose up -d

## 连接器目录

共 475 个适配器,提供 2,400 多个工具。每个适配器都在 [anythingmcp.com/zh/guides](https://anythingmcp.com/zh/guides) 上提供七种语言的配置指南。
共 477 个适配器,提供 2,400 多个工具。每个适配器都在 [anythingmcp.com/zh/guides](https://anythingmcp.com/zh/guides) 上提供七种语言的配置指南。

| 类别 | 示例 |
|---|---|
Expand Down
9 changes: 8 additions & 1 deletion docs/connectors/proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,14 @@ rate-limited APIs. Default is `false`.

Adapters shipped with `useProxy: true` today: Deutsche Bahn, Sorare,
OpenTable, Resy, Untappd, idealista, Trenitalia, ImmobilienScout24, Etsy,
Mercado Libre.
Mercado Libre, Playtomic.

A `LOGIN_TOKEN` connector logs in through the proxy when the tool call that
needs the token is proxied, so the login leaves from the same address as the
call. Playtomic is why: it answers a login from a datacenter IP with a 403
page, so a proxied tool whose login went out directly never got a token.
Like every proxied request, the login's TLS is terminated by the proxy, so
the credentials in its body pass through it.

For GraphQL adapters, if any tool opts in, the auto-injected
`<slug>_graphql_query` / `_mutation` / `_subscription` helpers inherit the
Expand Down
2 changes: 1 addition & 1 deletion glama.json
Original file line number Diff line number Diff line change
Expand Up @@ -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. 475 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. 477 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."
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "anythingmcp",
"version": "0.37.0",
"description": "Turn any REST/OpenAPI, SOAP/WSDL, GraphQL, OData or SQL API into MCP tools for Claude, ChatGPT and Copilot, no code. 475 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. 477 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": {
Expand Down
13 changes: 13 additions & 0 deletions packages/backend/src/adapters/adapters.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,19 @@ export class AdaptersController {
return { items: await this.adaptersService.popularConnectors(req.user.organizationId) };
}

@Get('match-url')
@ApiOperation({
summary: 'Catalog connectors for an API base URL',
description:
'The listed adapters whose API lives at the given URL (matched by host, then base path), best first, ' +
'so the custom connector form can offer the ready-made connector. An unparseable URL returns none.',
})
@ApiQuery({ name: 'url', required: true })
matchUrl(@Query('url') url: string | undefined) {
if (typeof url !== 'string') throw new BadRequestException('url is required');
return { matches: this.adaptersService.matchByUrl(url) };
}

@Get('starter-pack')
@ApiOperation({
summary: 'Connectors offered to a new workspace',
Expand Down
17 changes: 17 additions & 0 deletions packages/backend/src/adapters/adapters.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,14 @@ import { storableBaseUrl } from '../connectors/catalog-env-rebuild.util';
import { describeDiscoveredTools, mergeDiscoveredMcpTools } from './mcp-adapter.util';
import { deriveToolAnnotations } from '../mcp-server/tool-annotations';
import { mcpToolPrefixOf } from '../connectors/mcp-connector-config.util';
import { matchCatalogUrl, UrlMatch, UrlMatchCandidate } from './catalog-url-match';

@Injectable()
export class AdaptersService {
private readonly logger = new Logger(AdaptersService.name);
private readonly encryptionKey: string;
private readonly publicCatalogCache = new Map<string, SerializedBody>();
private urlMatchCandidates: UrlMatchCandidate[] | null = null;

constructor(
private readonly prisma: PrismaService,
Expand Down Expand Up @@ -95,6 +97,21 @@ export class AdaptersService {
return entry;
}

/**
* The listed adapters that serve the API at `url`, for the custom connector
* form: someone typing a base URL the catalog knows is offered the
* ready-made connector (see catalog-url-match.ts).
*/
matchByUrl(url: string): UrlMatch[] {
this.urlMatchCandidates ??= this.listAll().flatMap((a) => {
const baseUrl = getAdapter(a.slug)?.connector?.baseUrl;
return typeof baseUrl === 'string'
? [{ slug: a.slug, name: a.name, icon: a.icon, description: a.description, toolCount: a.toolCount, baseUrl }]
: [];
});
return matchCatalogUrl(url, this.urlMatchCandidates);
}

/** Setup instructions of one listed adapter, for its marketplace page. */
publicInstructions(slug: string): { slug: string; instructions: string | null } {
const adapter = this.getBySlug(slug);
Expand Down
108 changes: 108 additions & 0 deletions packages/backend/src/adapters/catalog-url-match.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { hostPattern, matchCatalogUrl, UrlMatchCandidate, URL_MATCH_MAX } from './catalog-url-match';
import { getAdapter, listAdapters } from './catalog';

const candidate = (slug: string, baseUrl: string, toolCount = 5): UrlMatchCandidate => ({
slug,
name: slug,
icon: slug,
description: '',
toolCount,
baseUrl,
});

describe('hostPattern', () => {
it('keeps a fixed host as it is, without www', () => {
expect(hostPattern('https://www.example.com/api/v1')).toMatchObject({
exact: 'example.com',
path: '/api/v1',
});
});

it('turns a variable label into a wildcard while a domain is left', () => {
const p = hostPattern('https://{{SHOP}}.myshopify.com/admin/api/2025-01');
expect(p?.exact).toBeNull();
expect(p?.regex?.test('acme.myshopify.com')).toBe(true);
expect(p?.regex?.test('myshopify.com.evil.io')).toBe(false);
});

it('matches nothing when the host is only a variable', () => {
expect(hostPattern('{{ODOO_URL}}')).toBeNull();
expect(hostPattern('https://{{HOST}}/api')).toBeNull();
});

it('cuts the base path at its first variable', () => {
expect(hostPattern('https://api.example.com/v1/{{ACCOUNT}}/items')?.path).toBe('/v1');
});
});

describe('matchCatalogUrl', () => {
const list = [
candidate('graph-a', 'https://graph.example.com/v1/ads', 18),
candidate('graph-b', 'https://graph.example.com/v1', 20),
candidate('shop', 'https://{{SHOP}}.shop.example.com', 12),
candidate('other', 'https://api.other.com', 3),
];

it('accepts a URL typed without a scheme', () => {
expect(matchCatalogUrl('api.other.com/v2', list).map((m) => m.slug)).toEqual(['other']);
});

it('keeps only the adapters whose base path the URL starts with, when any', () => {
expect(matchCatalogUrl('https://graph.example.com/v1/ads/123', list).map((m) => m.slug)).toEqual([
'graph-a',
'graph-b',
]);
});

it('lists every adapter on the host when no base path fits, most tools first', () => {
expect(matchCatalogUrl('https://graph.example.com/v9', list).map((m) => m.slug)).toEqual([
'graph-b',
'graph-a',
]);
});

it('matches a tenant host against a variable label', () => {
expect(matchCatalogUrl('https://acme.shop.example.com/x', list).map((m) => m.slug)).toEqual(['shop']);
});

it('returns nothing for junk, local hosts and unknown APIs', () => {
expect(matchCatalogUrl('', list)).toEqual([]);
expect(matchCatalogUrl('not a url', list)).toEqual([]);
expect(matchCatalogUrl('http://localhost:8080', list)).toEqual([]);
expect(matchCatalogUrl('ftp://api.other.com', list)).toEqual([]);
expect(matchCatalogUrl('https://api.unknown.dev', list)).toEqual([]);
});

it('never returns more than the cap', () => {
const many = Array.from({ length: 12 }, (_, i) => candidate(`a${i}`, 'https://same.example.com'));
expect(matchCatalogUrl('https://same.example.com', many)).toHaveLength(URL_MATCH_MAX);
});
});

describe('matchCatalogUrl on the real catalog', () => {
const catalog: UrlMatchCandidate[] = listAdapters()
.filter((a) => !getAdapter(a.slug)?.unlisted)
.map((a) => ({
slug: a.slug,
name: a.name,
icon: a.icon,
description: a.description,
toolCount: a.toolCount,
baseUrl: getAdapter(a.slug)!.connector.baseUrl,
}));
const slugsFor = (url: string) => matchCatalogUrl(url, catalog).map((m) => m.slug);

// Base URLs of custom connectors users built by hand on the Cloud in
// October 2026, for APIs the catalog already covered.
it.each([
['https://api-v2.fattureincloud.it', 'fatture-in-cloud'],
['https://api.printify.com/v1', 'printify'],
['https://api.printful.com', 'printful'],
['https://api.pinterest.com/v5', 'pinterest'],
['https://cloud-api.yandex.net/v1/disk', 'yandex-disk'],
['https://openapi.etsy.com/v3', 'etsy'],
['https://api.telegram.org/file/bot{{TELEGRAM_BOT_TOKEN}}', 'telegram-bot'],
])('offers the catalog connector for %s', (url, slug) => {
expect(slugsFor(url)).toContain(slug);
});
});
Loading
Loading