diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 633b0458..87242b3c 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -5,7 +5,7 @@ contact_links: about: For anything that isn't a clear bug or feature request — please use Discussions so the answer helps everyone else too. - name: 📚 Documentation & Guides url: https://anythingmcp.com - about: Setup guides for all 190 adapters and every AI client, in seven languages. + about: Setup guides for all 191 adapters and every AI client, in seven languages. - name: 🔐 Security vulnerabilities url: https://github.com/HelpCode-ai/anythingmcp/blob/main/SECURITY.md about: Please do NOT open a public issue. Follow the security disclosure policy. diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 6cc8c79c..fb4a1697 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -65,7 +65,7 @@ jobs: readme-filepath: ./README.md # Docker Hub caps this at 100 characters and shows it in search # results; the repo's was left at the truncated default. - short-description: "190 connectors + any REST/SOAP/GraphQL/SQL as MCP tools for Claude & ChatGPT. Self-hosted, AGPL." + short-description: "191 connectors + any REST/SOAP/GraphQL/SQL as MCP tools for Claude & ChatGPT. Self-hosted, AGPL." - name: Set Docker Hub categories env: diff --git a/CITATION.cff b/CITATION.cff index 4278f47a..9bf310d1 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -13,7 +13,7 @@ abstract: > server that exposes REST, SOAP/WSDL and GraphQL APIs, SQL/NoSQL databases and other MCP servers as tools for AI clients such as Claude, ChatGPT, Google Gemini, GitHub Copilot and Cursor, without writing code. It ships - 190 pre-built adapters (Deutsche Bahn, DATEV, weclapp, DHL, Shopware, + 191 pre-built adapters (Deutsche Bahn, DATEV, weclapp, DHL, Shopware, Personio, Handelsregister, etc.), a per-workspace knowledge graph served over MCP, per-tool response mapping, OAuth2/RBAC/SSO/SCIM governance, an audit log and a visual tool editor. diff --git a/README.md b/README.md index f42fd9fa..0f7a2dab 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@
-
+
Give Claude, ChatGPT and Copilot safe access to the software your company already runs.
- 190 ready adapters, any REST/SOAP/GraphQL/SQL system without code, on your own infrastructure — and it learns how your systems connect.
+ 191 ready adapters, any REST/SOAP/GraphQL/SQL system without code, on your own infrastructure — and it learns how your systems connect.
@@ -36,7 +36,7 @@ docker compose up -d # → http://localhost:3000
Three words appear throughout and mean three different things:
-- an **adapter** is one of the 190 JSON definitions that ship in this repo — DATEV, weclapp, DHL, Deutsche Bahn, Shopware, Personio, Handelsregister and the rest. 20 of them need no API key at all; the others ask for your credentials at import.
+- an **adapter** is one of the 191 JSON definitions that ship in this repo — DATEV, weclapp, DHL, Deutsche Bahn, Shopware, Personio, Handelsregister and the rest. 20 of them need no API key at all; the others ask for your credentials at import.
- a **connector** is an adapter, or your own OpenAPI spec / Postman collection / WSDL / GraphQL endpoint / database, once you have configured it in your workspace. Anything you can point at, in minutes, without writing an MCP server.
- an **MCP server** is the URL you hand to Claude. It exposes the connectors you assign to it, and nothing else.
@@ -260,7 +260,7 @@ AI clients speak MCP, but your systems speak REST, SOAP, GraphQL and SQL. Writin
## The adapter catalog
-190 adapters, exposing 1,800+ tools. **20 need no API key**; the rest ask for your credentials at import and the tools are available immediately. Every one has a setup guide on [anythingmcp.com/guides](https://anythingmcp.com/guides), in seven languages.
+191 adapters, exposing 1,800+ tools. **20 need no API key**; the rest ask for your credentials at import and the tools are available immediately. Every one has a setup guide on [anythingmcp.com/guides](https://anythingmcp.com/guides), in seven languages.
| Category | Examples |
|---|---|
diff --git a/glama.json b/glama.json
index dd4813b7..32e23415 100644
--- a/glama.json
+++ b/glama.json
@@ -3,5 +3,5 @@
"maintainers": [
"keysersoft"
],
- "description": "Give Claude, ChatGPT and Copilot safe access to the software your company already runs. 190 pre-built adapters (Deutsche Bahn, DATEV, weclapp, DHL, Shopware, Personio\u2026) plus any REST, SOAP/WSDL, GraphQL or SQL system as MCP tools, no code. Self-hosted, knowledge graph, per-tool response mapping, OAuth2/RBAC/SSO/audit. Open source under AGPL-3.0."
+ "description": "Give Claude, ChatGPT and Copilot safe access to the software your company already runs. 191 pre-built adapters (Deutsche Bahn, DATEV, weclapp, DHL, Shopware, Personio\u2026) plus any REST, SOAP/WSDL, GraphQL or SQL system as MCP tools, no code. 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 e83c5c25..aa74e720 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "anythingmcp",
"version": "0.9.0",
- "description": "Give Claude, ChatGPT and Copilot safe access to the software your company already runs. 190 pre-built adapters plus any REST, SOAP/WSDL, GraphQL or SQL system as MCP tools, no code. Self-hosted, open source (AGPL-3.0).",
+ "description": "Give Claude, ChatGPT and Copilot safe access to the software your company already runs. 191 pre-built adapters plus any REST, SOAP/WSDL, GraphQL or SQL system as MCP tools, no code. 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 3ee6efdb..5e20c9c3 100644
--- a/packages/backend/src/adapters/catalog.ts
+++ b/packages/backend/src/adapters/catalog.ts
@@ -152,6 +152,7 @@ import * as sapConcur from './intl/sap-concur.json';
import * as sapS4hanaCloud from './intl/sap-s4hana-cloud.json';
import * as savvycal from './intl/savvycal.json';
import * as sendgrid from './intl/sendgrid.json';
+import * as sentry from './intl/sentry.json';
import * as signwell from './intl/signwell.json';
import * as slab from './intl/slab.json';
import * as snov from './intl/snov.json';
@@ -458,6 +459,7 @@ const RAW_ADAPTERS: AdapterDefinition[] = [
sapS4hanaCloud as unknown as AdapterDefinition,
savvycal as unknown as AdapterDefinition,
sendgrid as unknown as AdapterDefinition,
+ sentry as unknown as AdapterDefinition,
signwell as unknown as AdapterDefinition,
slab as unknown as AdapterDefinition,
snov as unknown as AdapterDefinition,
diff --git a/packages/backend/src/adapters/intl/sentry.json b/packages/backend/src/adapters/intl/sentry.json
new file mode 100644
index 00000000..88e2effe
--- /dev/null
+++ b/packages/backend/src/adapters/intl/sentry.json
@@ -0,0 +1,175 @@
+{
+ "slug": "sentry",
+ "name": "Sentry",
+ "description": "Inspect Sentry projects, issues, and error events.",
+ "instructions": "Connect to Sentry's hosted REST API to investigate projects, issues, and error events using four read-only tools.\n\nSetup: Create a Sentry personal authentication token under User settings > Personal Tokens with org:read and event:read scopes. Supply it as SENTRY_AUTH_TOKEN, and your organization ID or URL slug (the `acme` in sentry.io/organizations/acme) as SENTRY_ORG, when configuring this connector. The organization goes into every path for you, so no tool asks the model for it. org:read permits listing organization projects; event:read permits reading issues and their events. Access remains limited by the token owner's permissions. Authentication uses the Authorization: Bearer header. This adapter targets https://sentry.io/api/0.\n\nWorkflow: Use sentry_list_projects to discover project IDs and slugs, then sentry_list_issues to find issues. Pass the returned issue id, rather than shortId, to sentry_get_issue or sentry_list_issue_events. An issue groups related errors; events are individual occurrences. Set full=true when listing events to include full event bodies and stack traces; Sentry then caps the page size at 10.\n\nFiltering: sentry_list_issues defaults to unresolved issues when query is omitted. Use project to select one project and statsPeriod to narrow the time range, for example 24h or 14d.\n\nPagination: the list tools ask for Sentry's Link header, so each response carries `_pagination` next to the body. Call again with cursor = `_pagination.nextCursor` and repeat until `_pagination` is absent, which means that was the last page. Never invent a cursor value.\n\nSelf-hosted Sentry: this adapter targets sentry.io. If you run your own Sentry, change the connector's base URL to your instance's /api/0 after installing; everything else is identical.",
+ "region": "intl",
+ "category": "monitoring",
+ "icon": "sentry",
+ "docsUrl": "https://docs.sentry.io/api/",
+ "requiredEnvVars": [
+ "SENTRY_AUTH_TOKEN",
+ "SENTRY_ORG"
+ ],
+ "connector": {
+ "name": "Sentry API",
+ "type": "REST",
+ "baseUrl": "https://sentry.io/api/0",
+ "authType": "BEARER_TOKEN",
+ "authConfig": {
+ "token": "{{SENTRY_AUTH_TOKEN}}"
+ }
+ },
+ "tools": [
+ {
+ "name": "sentry_list_projects",
+ "description": "List one page of projects in a Sentry organization. Returns project IDs, slugs, names, and platforms. Optionally filter by project name or slug.",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "query": {
+ "type": "string",
+ "description": "Filter projects by name or slug, for example 'backend'."
+ },
+ "per_page": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 100,
+ "description": "Number of projects per page. Sentry defaults to 100; maximum 100."
+ },
+ "cursor": {
+ "type": "string",
+ "description": "Pagination cursor. Omit for the first page, then pass `_pagination.nextCursor` from the previous response and repeat until `_pagination` is absent, which means you are on the last page. Do not invent a cursor value."
+ }
+ }
+ },
+ "endpointMapping": {
+ "method": "GET",
+ "path": "/organizations/{{SENTRY_ORG}}/projects/",
+ "queryParams": {
+ "query": "$query",
+ "per_page": "$per_page",
+ "cursor": "$cursor"
+ },
+ "exposeHeaders": [
+ "link",
+ "x-sentry-rate-limit-remaining"
+ ]
+ }
+ },
+ {
+ "name": "sentry_list_issues",
+ "description": "List one page of issues in a Sentry organization. Returns issue IDs, titles, statuses, and occurrence counts. Use an issue ID with sentry_get_issue to investigate further.",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "project": {
+ "type": "string",
+ "description": "Filter to one project ID or slug from sentry_list_projects. Omit for all accessible projects."
+ },
+ "query": {
+ "type": "string",
+ "description": "Sentry issue search, for example 'is:unresolved'. Omit to use Sentry's default unresolved-issue filter."
+ },
+ "statsPeriod": {
+ "type": "string",
+ "description": "Relative time range, for example '24h' or '14d'."
+ },
+ "limit": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 100,
+ "description": "Maximum number of issues to return, up to 100."
+ },
+ "cursor": {
+ "type": "string",
+ "description": "Pagination cursor. Omit for the first page, then pass `_pagination.nextCursor` from the previous response and repeat until `_pagination` is absent, which means you are on the last page. Do not invent a cursor value."
+ }
+ }
+ },
+ "endpointMapping": {
+ "method": "GET",
+ "path": "/organizations/{{SENTRY_ORG}}/issues/",
+ "queryParams": {
+ "project": "$project",
+ "query": "$query",
+ "statsPeriod": "$statsPeriod",
+ "limit": "$limit",
+ "cursor": "$cursor"
+ },
+ "exposeHeaders": [
+ "link",
+ "x-sentry-rate-limit-remaining"
+ ]
+ }
+ },
+ {
+ "name": "sentry_get_issue",
+ "description": "Retrieve details for a Sentry issue, including status, occurrence statistics, and a summary of the latest event.",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "issue_id": {
+ "type": "string",
+ "description": "Issue ID from the 'id' field returned by sentry_list_issues, for example '123456'. Use the ID, not the shortId such as 'BACKEND-42'."
+ }
+ },
+ "required": [
+ "issue_id"
+ ]
+ },
+ "endpointMapping": {
+ "method": "GET",
+ "path": "/organizations/{{SENTRY_ORG}}/issues/{issue_id}/"
+ }
+ },
+ {
+ "name": "sentry_list_issue_events",
+ "description": "List one page of error events belonging to a Sentry issue. Set full to true to include full event bodies and stack traces.",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "issue_id": {
+ "type": "string",
+ "description": "Issue ID from sentry_list_issues, for example '123456'."
+ },
+ "statsPeriod": {
+ "type": "string",
+ "description": "Relative time range, for example '24h' or '14d'."
+ },
+ "full": {
+ "type": "boolean",
+ "description": "Include full event bodies and stack traces. When true, Sentry caps the page size at 10."
+ },
+ "per_page": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 100,
+ "description": "Events per page. Default and maximum 100, capped at 10 when full is true."
+ },
+ "cursor": {
+ "type": "string",
+ "description": "Pagination cursor. Omit for the first page, then pass `_pagination.nextCursor` from the previous response and repeat until `_pagination` is absent, which means you are on the last page. Do not invent a cursor value."
+ }
+ },
+ "required": [
+ "issue_id"
+ ]
+ },
+ "endpointMapping": {
+ "method": "GET",
+ "path": "/organizations/{{SENTRY_ORG}}/issues/{issue_id}/events/",
+ "queryParams": {
+ "statsPeriod": "$statsPeriod",
+ "full": "$full",
+ "per_page": "$per_page",
+ "cursor": "$cursor"
+ },
+ "exposeHeaders": [
+ "link",
+ "x-sentry-rate-limit-remaining"
+ ]
+ }
+ }
+ ]
+}
diff --git a/packages/backend/src/adapters/intl/sentry.live.spec.ts b/packages/backend/src/adapters/intl/sentry.live.spec.ts
new file mode 100644
index 00000000..26373a58
--- /dev/null
+++ b/packages/backend/src/adapters/intl/sentry.live.spec.ts
@@ -0,0 +1,165 @@
+/**
+ * Opt-in live tests using a disposable Sentry project.
+ *
+ * Required environment variables:
+ * SENTRY_AUTH_TOKEN — personal token with org:read and event:read
+ * SENTRY_TEST_ORG — organization ID or slug, injected as the SENTRY_ORG env var
+ * SENTRY_TEST_PROJECT_ID — project containing the test issue
+ * SENTRY_TEST_ISSUE_ID — unresolved issue in that project
+ * SENTRY_TEST_EVENT_ID — exception event with a stack trace in that issue
+ *
+ * Use a small test project: list assertions inspect only the first page.
+ * The event must be among the first ten events returned for the issue.
+ *
+ * From the repository root:
+ * RUN_SENTRY_LIVE=1 npm test --workspace=packages/backend -- --runInBand --watch=false adapters/intl/sentry.live.spec.ts
+ *
+ * These tests only read existing data; they do not create test fixtures.
+ */
+
+import { AxiosError } from "axios";
+import * as adapter from "./sentry.json";
+import { RestEngine } from "../../connectors/engines/rest.engine";
+import { OAuth2TokenService } from "../../connectors/engines/oauth2-token.service";
+import { LoginTokenService } from "../../connectors/engines/login-token.service";
+
+// Normal test runs skip requests to Sentry.
+const describeLive =
+ process.env.RUN_SENTRY_LIVE === "1" ? describe : describe.skip;
+
+describeLive("Sentry adapter — live API", () => {
+ const engine = new RestEngine(
+ {} as OAuth2TokenService,
+ {} as LoginTokenService,
+ );
+
+ beforeAll(() => {
+ for (const name of [
+ "SENTRY_AUTH_TOKEN",
+ "SENTRY_TEST_ORG",
+ "SENTRY_TEST_PROJECT_ID",
+ "SENTRY_TEST_ISSUE_ID",
+ "SENTRY_TEST_EVENT_ID",
+ ]) {
+ if (!process.env[name]?.trim()) {
+ throw new Error(`Set ${name} before running Sentry live tests`);
+ }
+ }
+ });
+
+ function withOrg