Coming from Mastra
mcpd is a free, self-hosted alternative to Mastra's observability and to its durable workflows. This page says where it is ahead, where it is behind, and how to move.
What this is
Mastra is an agent framework: agents, workflows, memory, RAG and observability, in one TypeScript dependency. mcpd is a daemon beside your code: it holds a workflow between its steps and records every step, and it leaves the models, the prompts and the tools to you. It is not a framework around your agent, and it is written to stay out of one.
That difference decides most of what follows. Mastra's observability knows about your agent because it is inside it. mcpd knows about your agent because your agent emits OpenTelemetry, which means it also works for the services around your agent, and for agents that were never written in TypeScript.
The differences that matter
The workflow's bodies stay in your process, in any language
Both run durable workflows. Mastra's steps are TypeScript functions inside the Mastra process, suspended and resumed through its storage. mcpd's definition is data the daemon holds, and its step bodies are code your process holds, claimed one lease at a time through an HTTP protocol that six SDKs speak and any language can. The daemon never sees a model, a prompt or a credential, and a body can change without the definition changing.
What the daemon does hold is the part that has to survive: the cursor, the journal, the retry budget, the timers, and a wait for an event that may take a week to arrive. A run outlives the process that started it and the worker that served its last step. See Workflows.
It receives OpenTelemetry rather than exporting it from one framework
This is the whole thesis. Mastra's observability exports from inside a Mastra application, so what it can see is what that application does, in the language it is written in. mcpd is the collector: it receives OTLP from any OpenTelemetry SDK, in any language, with no mcpd code in your application, and records the services around the agent as readily as the agent.
It also emits OTLP, so mcpd can sit in the middle of a pipeline you already have rather than at the end of one you have to build. See Forwarding.
Redaction covers all six signals
Mastra's SensitiveDataFilter is a span processor. It runs on
spans and nothing else, so a key passed to a structured log, or a secret
quoted in a score's reason or a piece of feedback, reaches every exporter
unredacted.
mcpd redacts spans, logs, metric labels, scores, feedback and aspect notes, on by default, before anything is written and before anything is forwarded.
Its key matching is also a substring rather than an exact name, so
awsSecretAccessKey and X-API-Key are caught by the
rules for secret and x-api-key. A rule set that
requires the whole name to match misses both.
Be clear about the limit: redaction matches on the name of a field, not on the shape of its contents. A token pasted into the middle of a prompt, or into a URL stored under a harmless key, is not removed by either tool. Redaction reduces what you leak by accident. It is not a guarantee.
What mcpd adds for that case is a scorer rather than a filter. The built-in
no_leaked_secret reads a run's answer and matches on the shape
of a credential, so a key that made it into a completion is at least
reported to you. See Regression
testing.
-
Decode
OTLP or native, gzip or plain
-
Sample
Decided once, at the root
-
Redact
Before anything is written
-
Price
From the configured price book
-
Store
One transaction per batch
Redaction is stage three, not a cleanup job. A value that a rule matches never reaches storage at all.
Sampling is deterministic
Mastra's ratio sampling calls Math.random(). Every replica
behind a load balancer therefore decides differently about the same trace,
and a run that crosses two services can be kept by one and dropped by the
other.
mcpd hashes the trace id, so every instance reaches the same answer with no coordination and a kept trace is kept whole. The daemon's flags reach two strategies, keep everything and this deterministic fraction; a tail strategy that would keep every error whatever the rate says exists in the policy type and is not reachable from the command line in this build. See Sampling.
The rest, briefly
| Area | What mcpd does |
|---|---|
| Deployment | One static binary with the store and the interface compiled in. No Node, no sidecar. |
| Storage | SQLite for a laptop, Postgres or ClickHouse for a team. All three tested against a real server in CI. |
| Search | Full text over every stored prompt and completion. |
| Metrics | Aggregated at ingest, with exact quantiles and exemplars back to a run. |
| Cost | Priced at ingest and stored. Cached tokens charged at their own rate. An unknown model is left unpriced rather than reported as free. |
| SDKs | TypeScript, Python, Rust, Go, Kotlin and Elixir, generated from one specification so they cannot drift. Each carries a workflow builder and a worker. |
| Workflows | Nine constructs, held by the daemon: steps, agent turns, sleeps, waits on events, parallel branches, foreach, bounded loops and child runs. Retries, effects and limits are per step. A conformance suite serves the same run from all six languages. |
| Evaluation | Thirteen deterministic scorers, plus model-graded scoring against any OpenAI-shaped endpoint. Datasets captured from production runs, and experiment comparison that reports its sample size. |
| Licence | Apache-2.0. Self-hosted with no account, or free hosted at mcpd.sh. |
Where mcpd is behind
Stated here rather than left for you to discover, because a comparison that only lists wins is an advertisement.
- Not a framework around your code. Mastra gives you agents, memory, RAG and a model router in one dependency. mcpd gives you the durable run and the record of it, and leaves models, prompts and tools to your code. If you want one dependency that does everything, Mastra is the one dependency.
- No named vendor exporters. Mastra ships integrations for Langfuse, LangSmith, Braintrust, Arize, Datadog and others by name. mcpd forwards OTLP, which reaches most of them through one implementation, but a destination that speaks only its own protocol is out of reach.
- No SSO, SCIM or RBAC. Authentication is six API key scopes and a project list per key. Put it behind the identity proxy you already run.
The full account, updated as things land, is in PARITY.md.
Moving over
If your agent already emits OpenTelemetry, this is two environment variables. mcpd speaks OTLP over HTTP, on the endpoints every OpenTelemetry SDK already knows how to talk to. Traces can be JSON or protobuf; logs and metrics must be JSON.
point an existing OpenTelemetry setup at mcpd
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
export OTEL_EXPORTER_OTLP_PROTOCOL=http/json The protocol line matters. Port 4317 is conventionally gRPC, and mcpd speaks HTTP on it, so an SDK left on its gRPC default connects to the right port and fails. OpenTelemetry goes through this and the rest of the settings.
Run both for a fortnight. mcpd forwards the spans it stores on to whatever you were using before, so you can compare the two on the same traces rather than on a migration you cannot undo. It forwards spans only: logs, metrics, scores, feedback and aspect notes stay in mcpd.
keep the old destination while you decide
mcpd serve --forward-endpoint https://your-existing-collector If your agent does not emit OpenTelemetry yet, start with Quickstart, or pick your language under Instrument in the sidebar.
How this comparison was made
The Mastra claims on this page come from reading its source in August 2026, not from its documentation and not from running a benchmark. There are no performance numbers here because we have not measured any we would stand behind.
Mastra is actively developed and any of this can stop being true. If you find something out of date, it is a bug in this page: open an issue and it will be corrected.
Next
- Pointing an existing collector at mcpd: OpenTelemetry.
- What is removed before anything is stored: Redaction and retention.
- Running it for a team: Docker and Kubernetes.