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.