Releases: HelpCode-ai/anythingmcp
Release list
v0.4.1 — Playtomic API migration & Lite connector
Fixes
Playtomic connectors restored. Playtomic moved its API to api.app.playtomic.io (dropping the /api prefix) and closed anonymous access around 2026-07-31, which broke both shipped Playtomic connectors — old paths returned 404, and the previously-public club-search/availability endpoints now return 401 without a Bearer token.
playtomic(full, 13 tools) — repointedbaseUrl+loginUrlto the new host, dropped/apifrom all tool paths. TheLOGIN_TOKENemail+password → JWT flow was already correct.playtomic-public→ "Playtomic (Lite)" — converted fromauthType: NONEtoLOGIN_TOKEN. The 4 read-only tools (club search, club details, availability, sport configuration) now require a free Playtomic account (PLAYTOMIC_EMAIL+PLAYTOMIC_PASSWORD) — no API key, no club membership. Generic pricing preserved.- Removed
playtomic-publicfrom the zero-credential onboarding demo (it now requires login).
Notes
- Auth uses the Bearer token alone — verified end-to-end against a real account (login + all data/personal endpoints return
200). No User-Agent /X-Requested-Withspoofing. The existingLOGIN_TOKENengine handles login, encrypted token caching, and refresh. - Website guides/marketplace copy updated separately to reflect the free-account requirement.
Verification: backend lint/typecheck/test/build green (PR #468); Playtomic conformance specs 10/10.
v0.4.0 — per-tool response mapping
New: Response Mapping
Tools can now shape the API response before it reaches the AI client. Optional, per tool, and off by default — a tool without a mapping behaves exactly as before.
Upstream endpoints routinely return far more than a tool needs. A Datto RMM device carries up to 300 UDF fields, IPs and remote-control URLs when the tool only wants hostname, site, OS and status. Every extra byte is billed to the agent's context window and exposed to a third-party model. A response mapping declares what a tool actually publishes, separately from what the API returns.
{
"responseMapping": {
"transform": {
"select": {
"page": { "count": "$.pageDetails.count", "totalCount": "$.pageDetails.totalCount" },
"devices": {
"$from": "$.devices[*]",
"$select": {
"id": "id",
"hostname": "hostname",
"category": "deviceType.category",
"antivirusStatus": "antivirus.antivirusStatus"
}
},
"source": "= datto-rmm"
},
"exclude": ["devices[*].udf"]
}
}
}Two modes. select is a declarative output template — leaves are paths ($.a.b, items[*].id, list[-1].x), = literal statics, or { $from, $select } to reshape every element of an array. expression with "mode": "jmespath" gives you full JMESPath for computed values (length(devices)) and filters (devices[?online == `false`]). Both support include/exclude path pruning, maxBytes and fallbackToRaw.
A path that does not resolve leaves its key out rather than emitting null — that is what keeps mapped responses small.
Applies to every connector type: REST, SOAP, GraphQL, SQL and bridged MCP servers.
Preview against a real response. In the tool editor under Response Mapping, "Preview with last real response" maps the most recent recorded response for that tool — without calling the API again — and shows raw ↔ mapped side by side with the size delta. The tool playground gains Mapped/Raw tabs.
API. GET/PATCH /api/connectors/:id/tools/:toolId/response-mapping to read, set or clear a mapping (leaving cacheTtl and followUp untouched), and POST .../preview-mapping for a dry run. The tool test endpoint now returns mapped and size accounting alongside the unchanged raw result. A malformed transform is rejected with a 400 at save time instead of silently degrading at call time.
Safety. A mapping that fails never breaks a working tool: the raw response is returned and a warning is logged. Set fallbackToRaw: false if you would rather see the error.
Fixes
{"type": "json", "fields": [...]}finally works. This shape has been documented since the first release and was never implemented — any tool configured with it silently returned the full response. It now behaves astransform.include.- Saving a tool from the UI no longer wipes its response mapping. The editor rebuilt
responseMappingfromcacheTtlalone, and the connector page never passed the stored value in, socacheTtlandfollowUpwere discarded on the first save from the GUI. Same bug class as thebodyMappingfix in v0.3.9. structuredContentwas empty for every tool with afollowUpworkflow hint. It was rebuilt by re-parsing the result text, and the appended hint text broke that parse, silently yielding{}. The executor now hands back the object directly.- Editing a mapping takes effect immediately. The response cache now stores the raw upstream response (key prefix bumped to
tool_cache:v2:) instead of the rendered text, so a change no longer waits out the remainingcacheTtl. outputSchemanow matches what clients receive: it is re-inferred from the mapped shape and dropped when the transform changes.
Upgrade notes
No migration. The configuration lives under the existing mcp_tools.response_mapping JSON column in a new transform key, so adapter JSON, import/export, catalog re-sync and the version fingerprint are unaffected.
Tools with a cacheTtl will take one extra cache miss on their first call after the upgrade, because of the cache key prefix bump. Everything else is unchanged.
Verification
81 new tests; full suite green at 207 suites / 3562 tests. Verified end to end against a live API through a real MCP session: unmapped output byte-identical, mapped output 4543 → 384 bytes (−92%), broken mappings falling back to raw without failing the call, and cache edits taking effect on the next call.
v0.3.9 — bodyTemplate interpolation & connector editor fixes
Fixes
-
Caller-context and env variables now work in a
bodyTemplate(#453):interpolateConnectorConfig()coveredbaseUrl, headers,path,queryParamsandbodyMapping— but notbodyTemplate, which the REST engine then rendered with tool arguments only.{{amcp.user_email}}therefore reached the target system verbatim. Note this was broader than the caller-context feature: plain{{ENV_VAR}}in a body template had been silently broken for as long as body templates existed.Substituted values are escaped for their JSON string context, so a quote or backslash in a value cannot terminate the surrounding string and inject syntax. A bare numeric placeholder such as
{"limit": {{MAX}}}still yields valid JSON, and${param}placeholders are left untouched for the engine to render afterwards with its own escaping. -
OAuth2 endpoints are editable again (#453): a connector switched to
OAUTH2after creation has noauthorizationUrl, and the edit form only exposed client id and secret — so it could never be authorized (No authorization URL configured for this connector) and had to be rebuilt from scratch. Authorization URL, Token URL and Scopes are now shown and editable, pre-filled from the stored configuration and saved through the merge endpoint so issued tokens survive the edit. -
Nested
bodyMappingis no longer invisible or silently destroyed (#453): the field editor can only express a flatparam → $parammapping. Anything else — nested objects, arrays, literal values,{{variables}}— rendered as an empty Body Fields section, and saving rebuilt the mapping from the visible fields, discarding the rest. Such a mapping is now detected and shown in a new Body Mapping (JSON) mode that round-trips it verbatim. Invalid JSON blocks saving with an inline message instead of throwing, and the live preview no longer crashes on a half-typed document. -
The Test button explains empty caller-context values (#453): it does not run through an authenticated MCP session, so
{{amcp.*}}resolves to empty and a perfectly good tool looks broken. The test result now says so when the tool uses those variables.
Upgrading
No schema changes and no configuration changes. If you worked around the bodyTemplate limitation by moving the payload into a nested bodyMapping, that keeps working unchanged — and is now editable from the UI.
Verification: backend 3475 tests green, typecheck clean; frontend typecheck + build + e2e clean.
Docs: docs/tool-definition.md corrected — it stated the variables applied to "the endpoint mapping" while bodyTemplate was in fact excluded.
Thanks to Dominik Muhlke (pikoworks) for a precise report that pinpointed the exact call path for each of these.
v0.3.8 — OAuth2 token-endpoint authentication method
Features
-
OAuth2 token-endpoint authentication method is now selectable (#452): some providers only accept client credentials as an HTTP Basic header at the token endpoint (
client_secret_basic, RFC 6749 §2.3.1) and answer401to credentials sent in the request body. The engine has honouredtokenAuthMethodsince v0.3.5 — for the authorization-code exchange and later refreshes — but it could only be set by hand-craftingauthConfig, which made it effectively unreachable.The connector form now offers Token endpoint authentication on create and edit: client secret in body (default) or HTTP Basic header. Two endpoints back it:
GET /api/connectors/:id/oauth-configCurrent non-secret settings. The client secret and issued tokens are never returned — only hasClientSecret/hasAccessToken/hasRefreshToken.PATCH /api/connectors/:id/oauth-configPartial update, merged into the existing authConfig.The PATCH merges rather than replaces on purpose:
authConfigalso holds the issued access/refresh tokens and the endpoints captured during authorization, so a full write would silently destroy a working authorization. Omitted fields keep their value;tokenAuthMethod: ""resets to the default.Reported by a user connecting Datto RMM (
merlot-api.centrastage.net); DATEV requires the same. Verified read-only against Datto's token endpoint: credentials in the body return401withWWW-Authenticate: Basic realm="oauth2/client", while the Basic header passes client authentication.
Fixes
- OAuth2 client credentials were never saved from the connector edit page (#452): the Client ID and Client Secret inputs were rendered but silently discarded —
buildAuthConfig()had noOAUTH2case and fell through to returningundefined. The placeholder even read "Leave empty to keep current", which made the no-op look intentional. They now persist through the merge endpoint. - The auth-method selector is pre-filled from the stored configuration; without that, saving any unrelated field would have silently reset a connector already configured for HTTP Basic.
Maintenance
Dependency updates across the Prisma, Sentry, Radix UI, Playwright, ESLint/Prettier and Jest groups, plus soap and next.
Upgrading
No schema changes and no configuration changes. Existing OAuth2 connectors keep their current behaviour; switch a connector to HTTP Basic only if its provider requires it, then re-run Authorize with Provider so a token is fetched the new way.
Verification: backend 3469 tests green (+12 covering merge semantics, the empty-body no-op, non-OAuth2 rejection, role enforcement, and that the GET leaks neither secret nor tokens), typecheck clean; frontend typecheck + build + e2e clean.
Docs: docs/connectors/rest.md — new Token endpoint authentication section with a Datto RMM example.
v0.3.7 — MCP tool annotations & caller-context variables
Features
-
MCP tool annotations (#438): tools are now advertised with the spec's
ToolAnnotations(title,readOnlyHint,destructiveHint,idempotentHint,openWorldHint), so an agent can tell a probe-safe tool from a mutating one before calling it. The hints are derived from what each connector already declares — the HTTP verb for REST,query/mutationfor GraphQL, the connector'sreadOnlyflag and the SQL text for databases — and annotations reported by an upstream MCP server are now passed through instead of being discarded.Derivation is deliberately conservative about
readOnlyHint: only the protocol may assert it. Wrongly claiming read-only would invite an agent to call a mutating tool freely, whereas omitting the hint only makes it more careful, so tool names are used solely to refinedestructiveHint. The one case no heuristic can settle — a read-only search exposed overPOST— is handled by a per-tool override, editable from the new Hints panel on the connector page or viaGET/PATCH /api/connectors/:id/tools/:toolId/annotations. Overrides survive a re-import; upstream MCP annotations refresh on re-import, since that server is authoritative about its own tools.Per the MCP spec these are advisory hints — clients must not base trust decisions on them. Enforcement stays in roles and per-tool access.
-
Caller-context variables
{{amcp.*}}(#438): connectors often front a service-based API while users authenticate individually (OAuth, per-user MCP API keys), leaving the target system unable to record who actually asked. The calling identity can now be forwarded explicitly in headers, query parameters, the body and the path — e.g.X-Requested-By: {{amcp.user_email}}— withuser_email,user_id,org_id,server_id,server_name,auth_methodandapi_key_name.The values are resolved server-side and merged after the workspace's own environment variables, so neither a connector variable nor a tool argument can spoof them. Forwarding is opt-in (identity is personal data). Where there is no user — instance-wide static credentials, anonymous mode — a variable resolves to an empty string rather than leaking a literal placeholder, and a misspelled reserved variable is rejected when the tool is saved.
Fixes
- Reserved-variable scanning made linear (#438): the
{{amcp.*}}scanner used a pattern that backtracks polynomially on adversarial brace runs (CodeQLjs/polynomial-redos). It runs over operator-supplied tool configuration, so the pattern now uses quantifiers over disjoint character classes. - Transient TLS and proxy failures are retried (#437):
EPROTOhandshake errors and421 Misdirected Requestresponses are retried instead of surfacing as tool errors.
Upgrading
Adds one additive, nullable column (mcp_tools.annotations); migrations run automatically on container start. No configuration changes required — annotations appear on existing tools with no action needed.
Verification: backend 3460 tests green, typecheck clean; frontend typecheck + build clean; annotation derivation verified inside the running container against real production tool definitions.
Docs: docs/tool-definition.md — new sections Tool Annotations and Caller-Context Variables.
v0.3.6 — DATEV sandbox connector & OAuth refresh hardening
Features
- DATEV Online APIs (Sandbox) connector (#436): a dedicated, pre-configured marketplace adapter for DATEV's sandbox environment (openidsandbox authorize, sandbox-api token,
platform-sandbox/v2API paths,client_secret_basic). Every DATEV app must run in the sandbox until DATEV grants production approval — this removes the error-prone manual URL/path editing the single production adapter required. Generated from the production adapter so the tool definitions never drift.
Fixes
- REST OAuth connectors: tools now work immediately after authorization (#436): the freshly-issued access token is loaded into the in-memory MCP registry right after it is stored. Previously the reload lived inside the MCP tool-discovery block, which throws for non-MCP (REST/GraphQL) servers, so a just-authorized REST connector kept serving with a stale, token-less snapshot and returned 401s.
- Token refresh hardened for rolling refresh tokens (#436): the refresh flow re-reads the freshest refresh token from the DB instead of a stale registry snapshot (providers like DATEV rotate the refresh token on every use), and the OAuth callback merges issued tokens into the existing authConfig instead of replacing it (preserving
authorizationUrl/scopesfor re-authorization).
Verification: backend typecheck + lint clean; src/connectors + src/auth 389 tests pass (new regression tests for the reload and rolling-refresh paths); DATEV sandbox endpoints + client_secret_basic verified read-only against DATEV.
v0.3.5 — DATEV OAuth token exchange (client_secret_basic)
Fixes
- DATEV connector OAuth token exchange (#419): DATEV's token endpoint requires HTTP Basic client authentication (
WWW-Authenticate: Basic) and rejects body-supplied credentials with401 invalid_client. The connector authorization-code exchange previously sentclient_id/client_secretonly in the request body, so every DATEV confidential client failed at the token step. Added a per-connectortokenAuthMethod(basic| defaultpost); the DATEV adapter now usesbasic, applied to both the initial code exchange and token refresh. Default behaviour is unchanged for all other connectors.
Verification: confirmed read-only against DATEV's sandbox token endpoint (correct per DATEV's own OIDC discovery); backend typecheck + lint clean; connector OAuth tests 22/22 (3 new).
Note: a valid DATEV client secret is still required end-to-end — this release fixes the authentication method that was blocking all DATEV token exchanges.
v0.3.4 — MCP OAuth consent screen & CSRF hardening
Security
- MCP OAuth consent screen + login CSRF (#417): the MCP authorization login page now shows which client and which redirect destination is being authorized before credentials are entered, with an explicit Cancel/deny action that aborts the flow. This closes a consent-phishing vector where a client registered via open Dynamic Client Registration could obtain a user's organization-scoped authorization code with no informed consent. Adds double-submit CSRF protection to the login form. Active only under
MCP_AUTH_MODE=oauth2/both; inert in the default self-hostedlegacyconfiguration.
Features
- Optional per-tool
responseMapping.followUpworkflow hint (#416) - Connectors: expose
LOGIN_TOKENauth and custom headers in the GUI - Connectors: GTIN/barcode lookup adapter (#386)
- Cloud: Stripe billing portal — manage your subscription from the app
Fixes
- Cloud: unblock the Deutsche Bahn connector (dbweb profile + Zyte egress) (#402)
- Email: workspace-SMTP UX — timeouts, delivery fallback, invite reuse, editable config; org-aware SMTP with system fallback
- Deploy: raise healthcheck
start_periodso live deploys stop reporting false failures
Notes
This release also folds in the previously-unreleased 0.3.1–0.3.3 changes since v0.3.0, plus 21 dependency updates.
Verification: backend typecheck clean; src/auth 50/50 tests pass (7 new for consent/CSRF); lint clean; CI green on merge.
v0.3.0 — Redesign (sidebar app shell), cloud onboarding/conversion & KG improvements
Highlights
Redesign — sidebar app shell
- New design system (Geist fonts, refreshed token palette) and shared UI primitives.
- Left sidebar navigation with grouped sections, org switcher and mobile drawer, replacing the top nav across the app.
- Two-column MCP server detail with a sticky "Connect your MCP client" panel and a dedicated GitHub Copilot quick-connect (VS Code, Visual Studio desktop, JetBrains…).
- Numerous UX fixes: sticky footer, header back-links, fixed-sidebar scroll bug, refreshed login/onboarding.
Cloud onboarding & trial→paid conversion (cloud-only)
- Deterministic, idempotent trial activation on email verification (removes the no-license signup race); self-healing license wall.
- Value-oriented end-of-trial emails (3-day / last-day / expired, with a build recap) and a value-aware trial banner.
- Knowledge graph & skills surfaced as the differentiator in onboarding and a live-count dashboard teaser.
Knowledge graph
- Opt-in auto-apply of high-confidence AI-suggested connections (mirrors skill auto-apply; no extra AI cost).
All cloud-only features are gated and inert in self-hosted; no new recurring AI cost. Builds on the recent Copilot-Studio MCP transport/OAuth compatibility work.
v0.2.6 — Copilot Studio Streamable MCP compatibility
Fixed
- Microsoft Copilot Studio could not finalize an MCP connection or list tools. Verified against a Copilot-compatible reference server (Microsoft Learn Docs MCP): the streamable endpoint must return SSE-framed responses (
Content-Type: text/event-stream) on POST and 405 on a bare GET. AnythingMCP returnedapplication/jsonand401respectively. Now: responses are SSE-framed by default (setMCP_STREAMABLE_JSON_RESPONSE=truefor the old behaviour) and a GET to the MCP endpoint returns the transport's 405 instead of an auth 401. Spec-compliant clients (e.g. Claude) are unaffected.