[INSTALL]

Install Vesta

Install the SDK and call instrument() once. Pick your language and framework for the exact steps.

[QUICKSTART]

Set it up

[01]

Install

shell
pip install vesta-sdk

Requires Python 3.12 or newer. The only runtime dependency is OpenTelemetry.

[02]

Instrument your server

server.py
import vesta
from mcp.server.lowlevel import Server

server = Server("my-server")
# register your tools, then:

vesta.instrument(
    server,
    api_key="vsk_live_...",
    session_context=lambda request: {
        # who the end user is. Omit on authenticated surfaces — Vesta
        # derives a pseudonymous user_id from the token automatically.
        "user_id": user_id_from(request),
    },
)

Call instrument() after your tools are registered and before the server starts serving. The call is idempotent and fail-open; an error in the SDK never reaches the request path. session_context is optional and attaches per-session dimensions.

[CONFIG]

What you're setting

api_key

Authenticates your surface to Vesta. One key per MCP server, prefixed vsk_. Keep it in an environment variable or secret store, not in your source.

endpoint

The ingest URL traces are sent to. Defaults to Vesta's hosted ingest. Set it to a collector in your own Azure or GCP tenant to keep all trace data inside your boundary.

session_context

A callable, run once per session. Returns a user_id for the end user — plus any user attributes you genuinely segment by (Vesta defines no fixed set). Authenticated surfaces already get a pseudonymous user_id from the OAuth token automatically, so set it yourself only on an unauthenticated surface. Optional.

args / responses

Redaction rules for tool arguments and responses. Both are redacted by default. See Privacy and redaction below to capture or scrub specific fields.

[PRIVACY]

Privacy and redaction

Redaction runs inside your own process, before anything is sent. Raw payloads never leave your environment. By default Vesta redacts every tool argument and response value, so you get the shape of each call, the tool name, the timing and the errors, but not the contents.

If you open capture up, a built-in denylist still scrubs common sensitive fields by name, like email, password, ssn, credit_card, api_keyand auth tokens. It's the lowest-precedence rule, so widening capture doesn't quietly start sending PII unless you name a sensitive field yourself.

Configuring your own rules is recommended for tighter control. Capture the non-sensitive fields you want to analyse, hash the ones you need joinable but not readable, redact or truncate the rest. Rules apply per field, so the policy is yours to set as coarsely or precisely as you like.

redaction.py
from vesta import RedactionConfig, Field

# arguments and responses are redacted by default.
# capture only the non-sensitive fields you want to analyse.
args = RedactionConfig(
    default="redact",
    rules=[
        Field("query").capture(),       # the agent's search text
        Field("category").capture(),
        Field("account_id").hash(),     # joinable, not readable
    ],
)

vesta.instrument(server, api_key="vsk_live_...", args=args)

Selectors: Field, Tool, Prompt, Resource, Method. Actions: capture(), redact(), hash(), truncate(n). Pass responses= for response payloads. Run it against a self-hosted endpoint and raw data never leaves your cloud at all.

[SUPPORT]

Languages & frameworks

Pythonofficial mcp SDK and FastMCP
TypeScriptofficial MCP SDK
Transportsstreamable HTTP, SSE and stdio
Embedded serverslibrary-embedded, over stdio
[GOOD TO KNOW]

How it behaves

  • Runs inside your server process. Never imports Vesta internals at runtime.
  • Idempotent. Call it twice and the second call is a no-op.
  • Fail-open. An error in Vesta never reaches your request path.
  • OpenTelemetry under the hood. Traces export asynchronously over OTLP.
[EARLY ACCESS]

One call and you can see your surface.