Community-maintained, framework-neutral Armature analytics instrumentation for MCP servers.
This package is unofficial and is not affiliated with or endorsed by Armature.
The module decorates JSON-style MCP tool definitions, removes Armature's optional telemetry argument before a tool handler runs, and records the result without allowing analytics delivery failures to break the handler.
Add the recorder to your supervision tree:
children = [
{Armature.MCP.Analytics,
api_key: System.get_env("ANALYTICS_INGEST_API_KEY"),
ingest_url: System.get_env("ANALYTICS_INGEST_URL"),
delivery: :background}
]Then decorate tools and wrap dispatch:
tools = Armature.MCP.Analytics.decorate_tools(tools)
Armature.MCP.Analytics.track("lookup", arguments, context, fn clean_arguments ->
lookup(clean_arguments)
end)context may contain :actor_seed, :session_id, :client_info,
:client_capabilities, :protocol_version, :request_meta, and a genuine
per-invocation :request_id. Do not use a JSON-RPC message id as the request
id because those counters are commonly reused across sessions.
Summary
Functions
Decorates MCP tool definitions with telemetry and, by default, unmet-demand reporting.
Flushes queued background events.
Removes and normalizes Armature telemetry from raw MCP arguments.
Records one MCP session initialization event.
Starts an analytics recorder.
Runs a tool handler with clean arguments and records its outcome.
Types
Functions
Decorates MCP tool definitions with telemetry and, by default, unmet-demand reporting.
@spec flush(GenServer.server()) :: :ok
Flushes queued background events.
Removes and normalizes Armature telemetry from raw MCP arguments.
@spec record_session(GenServer.server(), context()) :: :ok
Records one MCP session initialization event.
@spec start_link(keyword()) :: GenServer.on_start()
Starts an analytics recorder.
@spec track(GenServer.server(), String.t(), map(), context(), (map() -> result)) :: result when result: term()
Runs a tool handler with clean arguments and records its outcome.
The handler's return value and exception behavior are preserved. Analytics
errors are reported through the recorder's :on_error callback and never
replace the tool result.