Armature MCP Analytics for Elixir
Important
This is an unofficial, community-maintained package created by MarkMarine. It is not affiliated with or endorsed by Armature.
Privacy-conscious, framework-neutral integration with Armature analytics for Elixir MCP servers. The published package is available on Hex.pm, with API documentation on HexDocs.
The library:
- decorates MCP tool schemas with optional conversation telemetry;
- strips that telemetry before validation and handler execution;
- emits bounded, redacted schema-v1
session_initandtool_callevents; - retries transient ingest failures without breaking tool handlers; and
- provides the default-on
request_capabilitytool for unmet-demand signals.
It works with JSON-style tool definitions and does not require a particular Elixir MCP framework.
Installation
Add armature_mcp_analytics to mix.exs:
def deps do
[
{:armature_mcp_analytics, "~> 0.1.0"}
]
end
To follow the repository directly instead of Hex:
{:armature_mcp_analytics,
github: "MarkMarine/armature_mcp_analytics",
tag: "v0.1.0"}
Configuration
Set these only in the server deployment environment:
ANALYTICS_INGEST_API_KEY=your-ingest-key
ANALYTICS_INGEST_URL=https://app.armature.tech/api/mcp-analytics/ingest
The URL above is the US endpoint. EU accounts must set:
ANALYTICS_INGEST_URL=https://eu.armature.tech/api/mcp-analytics/ingest
Missing API keys intentionally no-op, which keeps local development simple. Never expose the ingest key to MCP clients or browser code.
Supervision
Add the recorder to your application's 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}
]
Use :background for long-lived OTP applications and call
Armature.MCP.Analytics.flush/0 during an orderly shutdown when practical.
Use delivery: :await for short-lived commands and serverless request
handlers.
Instrument a dispatcher
Decorate the tool list before returning tools/list:
tools = Armature.MCP.Analytics.decorate_tools(tools)
This adds the request_capability tool by default. Disable it with:
tools = Armature.MCP.Analytics.decorate_tools(tools, request_capability: false)
Wrap normal tool dispatch so the handler receives its original arguments:
context = %{
actor_seed: authenticated_subject,
session_id: mcp_session_id,
client_info: client_info,
client_capabilities: client_capabilities,
protocol_version: protocol_version,
request_meta: request_meta
}
Armature.MCP.Analytics.track(tool_name, raw_arguments, context, fn clean_arguments ->
dispatch_tool(tool_name, clean_arguments)
end)
Only provide context.request_id when it is a genuine, globally unique
per-invocation idempotency key. Do not pass a JSON-RPC message id: those
counters are frequently reused across sessions and can cause deduplication
collisions.
If a customer tool already defines a top-level telemetry argument, pass its
tool definition in the context. The library will preserve the native field:
context = Map.put(context, :tool_definition, tool_definition)
Route the helper tool with:
Armature.MCP.Analytics.MCP.handle_request_capability(arguments)
Privacy and failure behavior
Before serialization, the library:
- redacts common credential fields and high-confidence token patterns;
- removes large base64 payloads;
- bounds previews, metadata, and total sanitization work; and
- hashes actor identifiers before transmission.
You can mutate or drop a whole event with :redact_event:
{Armature.MCP.Analytics,
redact_event: fn event ->
update_in(event, ["metadata"], &Map.drop(&1, ["request_meta"]))
end}
Delivery failures go to :on_error and never replace tool results:
{Armature.MCP.Analytics,
on_error: fn error ->
Logger.warning("Analytics delivery failed",
code: error.code,
status: error.status
)
end}
Do not log the batch, API key, or raw HTTP response in an error callback.
Verify a live MCP server
After deployment, run Armature's content-free doctor with the same regional environment variables:
npx @armature-tech/mcp-analytics doctor --url https://your-server.example/mcp
The doctor checks the MCP handshake, served tool schemas, and ingest authentication without sending customer content.
Development
mix deps.get
mix check
See CONTRIBUTING.md for the contribution workflow.
Releasing
Releases are created from GitHub Actions with the Publish release workflow:
- Update
@versioninmix.exsand document the release inCHANGELOG.md. - Commit the changes to
mainand ensure CI passes. - Configure the repository secret
HEX_API_KEYwith permission to publisharmature_mcp_analytics. - Run Actions → Publish release → Run workflow and enter the exact version.
The workflow verifies the requested version matches mix.exs, runs the full
check and coverage gates, publishes the versioned Hex package if it does not
already exist, and creates the matching vVERSION GitHub release. Reruns are
safe when the Hex version or GitHub release already exists.
License
MIT. See LICENSE.