Argosvix — AI agent observability (87 tools)

by argosvix

189 downloads
Not rated
GitHub

About

Observability MCP server for AI agents - 87 tools to query LLM cost/errors/latency and operate alerts, budgets, evals from Claude/Cursor

Details

Author
argosvix
Downloads
189
Categories
AI

- 87 tools covering observability read/write and autonomous AI-ops actions (e.g., get_account_health, detect_anomaly, propose_alert_rules)
- Runtime control plane with budget gates, policy gates, and human-approval gates
- HTTP transport with per-request API key auth and security notes
- Profile toggling (ARGOSVIX_MCP_PROFILE=core) to expose only 11 essential tools for tight context budgets
- Resource subscriptions for real-time updates (stdio only, poll every 60s)
- English and Japanese descriptions via ARGOSVIX_MCP_LANG environment variable

Setting up with Highlight

This MCP is not yet compatible with Highlight’s one-click setup. However, you can still use it with Highlight by following these steps:

  1. Download and install Highlight from highlightai.com/download
  2. Navigate to the plugins tab and select "Add Custom Plugin"
  3. Configure the plugin with the settings below
    Plugin Name Argosvix — AI agent observability (87 tools)
    Command (node, npx, python, etc.)

    Please refer to the README for specific instructions on how to obtain API keys or other required environment variables.

  4. Enable "Start Automatically" if you want the plugin to start when Highlight launches

From the repository

Install globally with npm install -g @argosvix/mcp-server. Configure your MCP client (e.g., Claude Desktop or Cursor) by setting the ARGOSVIX_API_KEY environment variable in the server config. Optionally, start with --http for remote HTTP transport on port 3000. The server supports both stdio (subprocess) and HTTP (remote/self-host) transports.

query_calls

Retrieve recent LLM call records captured by Argosvix. Filterable by provider / model / time range / tag (tagKey + tagValue pair). Defaults to the last 24 hours, 100 records.

get_cost_summary

Return cost / call count / token aggregates per time range, with a per-provider breakdown. When groupBy="none" is specified, a per-provider breakdown is still returned for backend compatibility (check the response.total field for the overall sum).

list_alerts

Return the list of configured alerts plus trigger history within the last 24 hours.

list_proposals

Return the unresolved improvement proposals found by the Argosvix guardian (quality drift / reliability anomalies / cost switching / safety / silencing noisy alerts). Approving, dismissing, and executing happen in the dashboard inbox (agents can only read and converse).

get_proposal_thread

Return the thread for a proposal (the questions asked so far and the AI's replies). Get proposalId from list_proposals.

reply_proposal

Post a question about a proposal and get the AI's reply (same as the inbox conversation). Explanation only — nothing is executed. Get proposalId from list_proposals.

silence_alert

Temporarily mute an alert (stops notification delivery). Defaults to 24 hours; pass an ISO-8601 timestamp as until for a custom expiry. Pass the alertId obtained from list_alerts.

unsilence_alert

Unmute a currently silenced alert.

create_alert

Create a new alert rule. Watches for cost / error rate / latency / anomaly threshold breaches and notifies the specified channels. Example: "notify me by email when daily cost exceeds $10". channelKinds is an array of channel kinds to enable; channelTargets is an object keyed by those kinds holding the destinations (e.g. channelKinds:["email"], channelTargets:{"email":"dev@example.com"}). Every kind listed in channelKinds must have a destination in channelTargets. anomaly_* types interpret thresholdValue as a standard-deviation multiplier (0.5-10, e.g. 3 = 3 sigma). The Free plan allows the email channel only and up to 3 alerts (the backend returns 403 beyond that).

update_alert

Update an existing alert's settings (PATCH /v1/alerts/:id). alertType (the watched metric type) is immutable — to change it, create a new alert and then delete the old one (completing the alert lifecycle). Threshold / evaluation window / notification channels / name / enabled flag / composite conditions can be partially updated (all fields optional). Example phrasing: "lower the monthly budget alert threshold from $100 to $50" / "add Slack as a notification channel".

delete_alert

Delete an alert (DELETE /v1/alerts/:id). Related alert_events are CASCADE-deleted too. To guard against accidental deletion, checking the details with get_alert first is recommended. If you only want to pause an alert, prefer silence_alert (mute) or update_alert with enabled=false instead of delete (both are recoverable).

get_alert

Return the detailed configuration of an alert and its recent trigger history. Pass the alertId obtained from list_alerts. Use it to check the threshold / notification channels / silence state / when it fired.

list_alert_events

Return alert trigger events, newest first. Account-wide (recent firings of all alerts) by default; pass alertId to narrow to one alert. Use for questions like "which alerts fired recently and how often?" or "when did the cost alert go off?". Each event's id can be passed directly to the acknowledge_alert tool. acknowledgedAt / acknowledgedBy are null if not yet acknowledged. Each event includes a snapshot of thresholdValue / windowMinutes / alertType at firing time (so the firing-time conditions survive later rule edits). For the next page, pass the last event's triggeredAt + id as beforeTriggeredAt + beforeId (keyset cursor).

acknowledge_alert

Mark an individual alert firing (event) as handled / acknowledged. Unlike silence_alert (which temporarily mutes the whole alert rule), ack is a per-event receipt — future firings of the same rule are still delivered as usual. Pass the id obtained from list_alert_events as eventId. Re-acking an already acknowledged event does not overwrite the existing ack info (the first acknowledgedAt / acknowledgedBy) and returns 200 (idempotent; distinguishable via the alreadyAcknowledged flag).

list_annotations_for_call

Return the annotations attached to an LLM call (records[].id from query_calls). An annotation is a user-authored evaluation (rating / comment / label); each annotation includes annotationText / label / qualityScore / createdAt / updatedAt. Use to check whether a call has human review attached or what past reviews said. Independent of the Pro+ plaintext feature (annotations work without plaintext storage enabled).

list_annotations_by_label

Return annotations carrying the given label, newest first (account-wide, up to 100). Use for things like collecting calls rated "good" or listing human reviews labeled "bug". Labels are ASCII letters / digits / underscore / hyphen only ([a-zA-Z0-9_-], up to 64 chars).

get_annotation

Fetch one annotation by id (obtained from list_annotations_*). Includes annotationText / label / qualityScore / callId / createdAt / updatedAt / createdByUserId. Ids belonging to other accounts return 404 (structural defense).

create_annotation

Create a new annotation (human review / labeling) for an LLM call. Specify at least one of annotationText / label / qualityScore (an "empty annotation" gets 400 from the backend). Example phrasing: "Claude, label this call 'badly-summarized' with quality 2", or bulk-apply positive / negative labels for an eval loop. Combined with the eval baseline runner (run_eval), annotations can calibrate eval criteria as ground truth.

update_annotation

Partially update an annotation's annotationText / label / qualityScore (PATCH /v1/annotations/:id). callId is immutable. For fixing a label or re-scoring quality from 4 to 5, etc. Pass annotations[].id obtained from list_annotations_for_call as annotationId.

delete_annotation

Delete an annotation (DELETE /v1/annotations/:id). No other rows depend on it, so there is no CASCADE impact. To guard against accidental deletion, checking the details with get_annotation first is recommended.

list_eval_criteria

Return the list of LLM-as-judge evaluation criteria. Includes the 5 global defaults (helpfulness / accuracy / relevance / safety / conciseness) plus the custom criteria created in your account. Each criterion has id / name / rubric (the instruction text for the judge) / scaleMin / scaleMax. Use before running an eval to see which axes are available. The Free plan can read all criteria (creating custom ones is Pro+ only, but existing rows stay visible after downgrade).

get_eval_criterion

Fetch one criterion's detail (name / rubric / scaleMin / scaleMax / createdAt) by id. The id comes from list_eval_criteria.criteria[].id. Both global defaults (accountId NULL) and your account's custom criteria are accepted; other accounts' customs return 404 (structural defense).

create_eval_criterion

Create one custom eval criterion in your account (Pro+ only). name + rubric + scaleMin + scaleMax are required. Same name already existing in the account = 409. A name matching a global default is structurally allowed (UNIQUE (account_id, name) separates it from account_id IS NULL). type defaults to 'llm_judge' (judge LLM scoring). Specifying a deterministic evaluator type (exact_match / contains / regex / json_schema / json_path) scores without calling an LLM — free and instant (pass -> scaleMax / fail -> scaleMin). Deterministic types require config. The path an AI agent takes when it decides "add this criterion" while evaluating your own workloads.

update_eval_criterion

Update a custom criterion in your account with a full replace (Pro+ only, PATCH /v1/eval-criteria/:id). name + rubric + scaleMin + scaleMax are required (not a partial update — all fields are overwritten). type / config are also fully replaced (omitting them reverts to 'llm_judge' / no config). Deterministic types require config. Global defaults (account_id IS NULL) are structurally out of scope (404); other accounts' customs are 404 too. Name collision within the account = 409.

get_llm_budget

Get the current monthly LLM feature budget (the LLM cost cap covering the 3 axes: safety classifier + secondary PII audit + eval baseline runner). Response = { budgetUsd, spentUsd, remainingUsd, periodStart, defaultBudgetUsd, minBudgetUsd, maxBudgetUsd }. Readable on Free and Pro+ alike; used when an AI agent decides "have we hit 80% of budget?" / "should we raise it?". Default $5/month; auto-resets at month boundaries (per YYYY-MM).

raise_llm_budget

Raise or lower the monthly LLM feature budget (Pro+ only). Range $5 - $500 (hard cap against runaway spend), in $0.01 increments. Existing spend carries over; auto-resets at month boundaries. Example phrasing: "we hit 80% of the budget — raise it to $30 just for this month" / "we overspent — lower next month to $10". A new value below current spend is accepted (remaining simply becomes 0; counting restarts from 0 next month).

get_budget_gate

Get the runtime budget gate settings (part of the runtime control plane) plus this month's LLM spend. Response = { gates: [{ id, projectId, monthlyLimitUsd, enforceMode, enabled, ... }], spentUsdThisMonth, monthStart, ttlSeconds }. monthStart is the UTC month start. The same source the SDK's budgetGate opt-in evaluates before execution. Distinct from get_llm_budget (which caps Argosvix's internal AI feature costs) — this one is a monthly cap on your own LLM spend. Example phrasing: "how much budget gate headroom is left this month?" / "is the gate set to fail_open?"

create_budget_gate

Create a runtime budget gate (Pro+ only). Sets a monthly LLM spend limit (USD) for the account; the SDK (budgetGate opt-in) blocks over-limit calls before execution. Enforcement is optimistic (spend is cached for 60 seconds and in-flight calls pass, so the limit is a guideline that can be exceeded, not a strict hard cap). enforceMode = fail_open (default; calls pass when the backend is unreachable) / fail_closed (calls are blocked when unreachable; a cold start where the SDK has never fetched the config additionally requires the SDK-side failClosed opt-in). Omitting projectId = an account-wide gate (only one; 409 if one exists). Specifying projectId = a gate for that project only (ANDed with the account gate — the strictest limit wins; one per project). Specifying tagKey + tagValue = a gate for calls carrying that tag (e.g. tagKey=service / tagValue=checkout caps the monthly spend of service=checkout. ANDed with the account gate; one per (tagKey,tagValue)). tagKey/tagValue must be specified together and are mutually exclusive with projectId. Example phrasing: "create a budget gate at $50/month" / "cap project X at $10/month" / "cap the service=checkout tag at $20/month"

update_budget_gate

Update a runtime budget gate (Pro+ only). Partially updates any of monthlyLimitUsd / enforceMode / enabled. Example phrasing: "raise the limit to $100" / "disable the gate temporarily" / "switch to fail_closed"

delete_budget_gate

Delete a runtime budget gate (Pro+ only). After deletion the SDK's pre-execution enforcement is disabled. To pause temporarily, prefer update_budget_gate with enabled: false.

request_approval

Create an approval request in the human approval gate (part of the runtime control plane; Pro+ only). Call it before dangerous operations (deletion / money transfer / account closure etc.); the account owner gets an email notification and a human approves or denies via the dashboard or the email link. Important: no MCP tool exists to approve or deny (an AI agent cannot self-approve its own request). Poll the result with get_approval. Expiry after timeoutSeconds (default 3600) counts as denied. Server-side consumption: passing approvalId to a dangerous mutation tool (bulk_delete_calls / purge_expired_plaintext / retry_failed_webhook / auto_silence_noisy_alert / extend_customer_trial / apply_promo_code_to_customer) makes the backend verify action match + approved + within expiry + unconsumed, and consume it on execution (1 approval = 1 execution). In that case create the request with an action exactly matching the target tool name. Example phrasing: "deleting user usr_123 is a dangerous operation — get human approval first"

get_approval

Get the current state of an approval request. status = pending / approved / denied / expired. Do not perform the target operation unless the status is approved (default-deny). Dangerous mutation tools also support server-side consumption via their approvalId param (see the request_approval description).

list_approvals

List approval requests (latest 50). status filter = pending (default) / approved / denied / expired / all.

get_policy_gate

Get the runtime policy gate settings (part of the runtime control plane). Response = { policy: { id, modelAllowlist, blockPii, blockSecrets, enforceMode, enabled, ... } | null }. The config the SDK's policyGate opt-in evaluates locally before each LLM call (exact-match model allowlist + blocking on PII / secret detection). Example phrasing: "what model restrictions are active right now?" / "is PII blocking enabled?"

create_policy_gate

Create a runtime policy gate (Pro+ only). Configures an account-wide model allowlist / PII block / secret block; the SDK (policyGate opt-in) blocks violating calls before execution. At least one rule (modelAllowlist / blockPii / blockSecrets) is required. One per account (409 if one exists). A redact mode is not supported (block only). Example phrasing: "only allow gpt-5.5 and claude-fable-5" / "block calls containing PII"

update_policy_gate

Update a runtime policy gate (Pro+ only). Partially updates modelAllowlist (null clears the restriction) / blockPii / blockSecrets / enforceMode / enabled. Example phrasing: "add gpt-4o-mini to the allowlist" / "enable secret blocking"

delete_policy_gate

Delete a runtime policy gate (Pro+ only). To pause temporarily, prefer update_policy_gate with enabled: false.

test_webhook

Send one fabricated alert to the given URL as a test delivery (Pro+ only). Main use: checking that a webhook URL is reachable before registering it. SSRF defense requires https and rejects private / loopback / cloud-metadata IPs. When secret is provided, an HMAC-SHA256 signature (X-Argosvix-Signature) is attached. Rate limit = 5/min per account (60s sliding window; may be exceeded across worker instances). response.delivered = whether the receiver returned 2xx within 5s; false means an invalid URL / timeout / 5xx / network error.

delete_eval_criterion

Delete a custom criterion in your account (Pro+ only, DELETE /v1/eval-criteria/:id, 204). Global defaults (account_id IS NULL) are structurally out of scope = 404; other accounts are 404 too. WARNING: all past eval_run score rows for this criterion (eval_scores) are physically deleted at the same time via ON DELETE CASCADE — historical comparisons and score trend analysis become permanently impossible. This is not a tool for an AI agent to call casually while tidying up criteria; only proceed when the user has explicitly confirmed the past run scores are not needed. If you only want to rename, using update_eval_criterion (full replace) with name + rubric + scaleMin + scaleMax preserves the history.

list_webhooks

List the registered outbound event webhooks (GET /v1/webhooks). Each webhook includes id / url / hasSecret / enabled / eventTypes / lastStatus / consecutiveFailures etc. (the secret itself is never returned). This is the subscription surface that notifies external endpoints of account events (approval requests, proposal execution / reversal) via signed POSTs. Readable on Free.

create_webhook

Register one outbound event webhook (Pro+ only, POST /v1/webhooks). url (HTTPS required; SSRF defense rejects private/loopback) + optional secret (HMAC-SHA256 signing key) + eventTypes (array of event kinds to subscribe to; omitted / empty = subscribe to everything). Up to 10 per account. Delivery payload = { event, eventId, occurredAt, accountId, data }; with a secret set, an X-Argosvix-Signature header is attached.

update_webhook

Partially update an outbound event webhook (Pro+ only, PATCH /v1/webhooks/:id). Only the specified fields change (url / secret / eventTypes / description / enabled). Omit secret to keep the current value; sending an empty string "" removes the signature (null cannot be sent through this schema). Re-enabling with enabled=true also resets the consecutive-failure counter. Other accounts' webhooks return 404. webhookId is the id from list_webhooks.

delete_webhook

Delete an outbound event webhook (Pro+ only, DELETE /v1/webhooks/:id). Other accounts' webhooks return 404. webhookId is the id from list_webhooks.

list_prompts

List the prompt templates the user has registered. Each prompt includes id / name / version / template / variables / labels / description / createdAt. Filter by a label such as "production" (?label=xxx), or fetch all versions of one name (?name=xxx). Up to 200 entries; sort = name ASC + created_at DESC. The main path for an AI agent to read and use prompts the user registered in the dashboard.

get_prompt

Fetch one prompt's detail by id. Use prompts[].id from list_prompts as-is. Includes template + variables + labels + description; scoped to your account (structurally enforced by a backend WHERE clause — other accounts' ids return 404). Same endpoint as the argosvix://prompts/{id} resource template.

create_prompt

Register one new prompt template (Pro+ only). name + version + template are required; variables / labels / description are optional. An existing (name, version) pair returns 409 (UNIQUE constraint). Used when an AI agent auto-registers templates for evals / experiments.

update_prompt

Partially update an existing prompt's template / variables / labels / description (Pro+ only, PATCH /v1/prompts/:id). name + version are immutable (change them via rename_prompt). promptId is required; only the fields you pass are updated. Used by AI agents for label moves (promoting 'staging' to 'production') and small patch edits.

rename_prompt

Change an existing prompt's name + version (Pro+ only, POST /v1/prompts/:id/rename). Main use is typo fixes ('customer_supprt' to 'customer_support'). Collision with an existing (name, version) in the account = 409. Since update_prompt never changes name/version by contract, rename is a separate tool for semantic separation.

delete_prompt

Delete an existing prompt (Pro+ only, DELETE /v1/prompts/:id, 204 No Content). Scoped to your account (other accounts' ids return 404). WARNING: physical delete with no restore; past eval_runs' prompt_registry_id is SET NULL, losing the trace of which prompt template each run used (history comparisons can no longer be linked). Even when sunsetting an old version in a rotation, while past run traces remain it is safer to do a logical sunset via update_prompt with labels such as 'sunset'.

deploy_prompt

Deploy a specific prompt version to a label (an environment such as production / staging) (Pro+ only, POST /v1/prompts/:id/deploy). If a deployment already exists, the prior version is kept as previous and rollback_prompt can revert in one step. Re-deploying the same version does not create a previous entry. Labels are per prompt name (each name has its own production version).

rollback_prompt

Revert the prompt deployed to a label to the previous version (Pro+ only, POST /v1/prompts/deployments/rollback). 409 when there is no previous version (first deployment only), and 409 when the previous version has already been deleted. After reverting, another rollback toggles back (current / previous swap).

get_deployed_prompt

Resolve and return the prompt version currently deployed to the given environment (name + label) (GET /v1/prompts/resolve, available on Free). The main runtime path for an agent to fetch the "production prompt". Returns that version's template / variables / labels / version. 404 when nothing is deployed.

list_prompt_deployments

List the current deployment states (GET /v1/prompts/deployments, available on Free). Each row = { promptName, label, currentVersion, canRollback, deployedAt }. Narrow by name / label (omit both for everything).

list_safety_assessments

List the assessments written by the safety classifier (OpenAI Moderation). source includes 'cron' (periodic batch) / 'mcp' (classify_calls_batch on-demand) / 'human_override' / 'api' / 'auto'. With callId = all classifier assessments for that call; without callId = account-wide, flagged first then most recent. In environments without OPENAI_API_KEY provisioned the cron does not run and this returns an empty array (classify_calls_batch also returns 503). Precondition: safety classification is disabled by default (a service-side staged rollout switch); no assessments are generated until it is enabled for your account. An empty array means "not enabled / nothing flagged", not a failure. AI agents use this to review recently flagged calls or to check policy-violation candidates for a specific call.

get_safety_assessment

Fetch one assessment's detail by id. Use assessments[].id from list_safety_assessments as-is. Includes labels (array of flagged categories) + score (max category score 0-1) + reasoning + classifier_id + source. Same endpoint as the argosvix://safety-assessments/{id} resource template.

list_eval_runs

List the eval baseline runner's run history. Scoped to your account, most recent first. Includes summary.scoredCount / failedCount / meanScoreByCriterion, so an AI agent can grasp recent eval result summaries and per-criterion score trends in one call. Free users can read past runs too.

get_eval_run

Fetch one eval run's detail plus the list of per-(criterion x call) scores. Use runs[].id from list_eval_runs as-is. The scores array includes score (an integer within the criterion's scale) + reasoning (the judge's rationale). Same endpoint as the argosvix://eval-runs/{id} resource template.

get_percentiles

Get percentile metrics over calls (POST /v1/query/percentiles). metric = 'latency' (ms) or 'cost' (USD); either a single value for the whole range, or a time series with groupBy='day'/'hour'/'minute'. Example phrasing: "daily p95 latency trend for last week". Percentiles are computed with the nearest-rank method.

list_projects

List your account's active projects (GET /v1/projects, archived excluded). Supports per-environment observation such as dev / staging / prod. Pro allows 5 projects / Team unlimited; Free has the default project only.

list_members

List a Team account's members (GET /v1/memberships, removed members excluded). Read-only tool returning each member's email / role (admin/member/viewer) / status / joined-at. Invitations, role changes, and removals are privilege operations and intentionally not exposed over MCP (use the dashboard, or a future approval-gate flow).

create_project

Create a new project (POST /v1/projects). name = display name; slug = a short URL-safe identifier (/^[a-z][a-z0-9-]{0,31}$/). Pro caps at 5 projects, Team unlimited, Free cannot create (403). As a mutation, session-authenticated requests enforce Origin/Referer (dashboard-driven).

rename_project

Update an existing project's name / slug (PATCH /v1/projects/:id). Specify either or both. slug keeps the URL-safe constraint (/^[a-z][a-z0-9-]{0,31}$/). Renaming the default project is allowed.

delete_project

Soft-delete a project (DELETE /v1/projects/:id; sets archived_at for a logical delete). The default project cannot be deleted (400, keeping accounts.default_project_id referentially consistent). After archiving, calls / alerts remain as-is (past observations are kept); route new records to another project.

classify_calls_batch

Batch safety-classify unclassified calls on demand (via OpenAI Moderation, POST /v1/safety-assessments/scan-batch). Complements the cron (every 15 min, 50 records) with a "right now" path — an AI agent can finish "classify all of last week's calls" in one prompt. Pro+ only (Free relies on the cron); the backend enforces the plan gate and budget gate. maxRecords (1-100, default 50); returns { scanned, assessed, flagged, failures, skipped }. Recorded with source='mcp' (distinguished from cron entries, so the dashboard can visualize on-demand classification). Audit: emits a safety.scan_batch_run event to the audit log.

propose_eval_criteria

Have an LLM judge (gpt-4o-mini) propose eval criterion candidates from a one-line useCaseHint (e.g. "customer support bot") and optional sampleCallIds (representative calls from your account, up to 5) (POST /v1/eval-criteria/propose). An AI agent can finish "propose criteria to measure our prompt quality" in one prompt. Pro+ only (the backend enforces the plan gate + budget gate); nothing is INSERTed (propose only — adoption is a separate step via create_eval_criterion, structurally limiting LLM-hallucination impact). Decrypt failures for sampleCallIds are reported in partialFailures (the LLM call still runs without samples). Privacy note for prompt samples: with sampleCallIds, the backend decrypts those calls' prompt/response and sends excerpts (1500 chars each) to OpenAI gpt-4o-mini. If the sampled calls originally went to OpenAI this is a re-send to the same vendor, but note that samples from other providers (e.g. Gemini / Mistral) are newly sent to OpenAI. If that is a concern, run with useCaseHint only. Results are advisory: the returned criteria are LLM proposals and may include semantically weak rubrics (overuse of "helpful", duplicates) even when structurally valid. User review before adoption is recommended; do not feed them blindly into create_eval_criterion. Returns { criteria: [{ name (snake_case 32 chars), rubric (1-200), scaleMin (=1), scaleMax (5 or 10), reasoning (1-200) }], partialFailures: string[], budgetSpentUsd, proposedRawCount (raw count returned by the LLM), droppedCount (entries removed by the validator) }. Audit: emits an eval.propose_criteria event to the audit log.

purge_expired_plaintext

Bulk-purge your account's plaintext records older than olderThanDays (POST /v1/tier2/plaintext/purge-expired). Consistent with the Terms of Service v2.1 "retainable up to 90 days" (automatic retention); an AI agent can finish "auto-purge plaintext older than 30 days" in one prompt. dryRun=true (the safe default to reach for) returns the count plus 5 sample call_ids; dryRun=false performs the actual UPDATE. Emit-then-UPDATE ordering plus a deterministic idempotencyId (sha1(endpoint+accountId+olderThanDays+cutoff_date)) gives webhook-retry-equivalent semantics. Pro+ plan only (Free gets 403). An actual purge (dryRun=false) requires approvalId — obtain human approval via request_approval (action: 'purge_expired_plaintext') first, because NULLing plaintext is irreversible. Only your own account is purged. Returns (dryRun=true) { dryRun: true, targetCount, cutoffTimestamp, olderThanDays, sampleTargetCallIds }; (dryRun=false) { dryRun: false, purgedCount, cutoffTimestamp, olderThanDays, purgedAt }. Audit: emits tier2.purge_expired_plaintext.

retry_failed_webhook

Mark failed Stripe webhook events (the billing_dead_letter table) for reprocessing in the audit log (POST /v1/tier2/webhook-events/retry). Finishes "retry all the Stripe webhooks that failed transiently last week" in one prompt. Select targets by eventIds (specific events, up to 100) or fromTimestamp/toTimestamp (range, 7-day cap). dryRun=true previews the list; dryRun=false records a 'marked_for_manual_redispatch' entry per event in the audit log (the actual retry is then performed manually by Argosvix operations; fully automatic re-dispatch is planned for a later release). Emits use a deterministic idempotencyId (sha1(endpoint+accountId+eventId)); duplicate runs with the same args are silently skipped. Internal operations tool (billing-webhook recovery); customer accounts receive 403. billing_dead_letter is an internal cross-account table and actual re-dispatch stays manual, so there is no plan to open this up. Returns (dryRun=true) { dryRun: true, targetCount, events: [{eventId, eventType, reason, receivedAt}] }; (dryRun=false) { dryRun: false, targetCount, succeeded: string[], failed: [{eventId, reason}], skipped: string[], narrative, retriedAt }. Audit: emits tier2.retry_failed_webhook per event.

auto_silence_noisy_alert

Bulk-silence noisy alerts that fired repeatedly in the past hour (POST /v1/tier2/alerts/auto-silence). Finishes "this alert fired 50 times in the past hour — silence it for an hour" in one prompt. Specify exactly one of alertId (silence a single alert) or byVolumeThreshold (all alerts with N+ firings in the past hour). silenceDurationMinutes is 5-1440 (5 minutes to 24 hours), default 60. An optional reason can be attached. dryRun=true previews the targets with fireCount; dryRun=false UPDATEs alerts.silenced_until and emits an audit event per alert (tier2.auto_silence_noisy_alert). Because this is a reversible mutation (the existing unsilence_alert can undo it) with strict per-account scoping (other accounts' alerts are unaffected), no special authorization is required — Pro+ accounts can call it directly. Returns (dryRun=true) { dryRun: true, targetCount, silenceUntil, silenceDurationMinutes, lookbackStart, targets: [{alertId, name, fireCount}] }; (dryRun=false) { dryRun: false, targetCount, silenceUntil, silenceDurationMinutes, succeeded: string[], failed: [{alertId, reason}], skipped: string[], reason }. idempotencyId = sha1(endpoint+accountId+alertId+silenceUntil truncated to the minute), coalescing duplicate runs within the same minute.

extend_customer_trial

Extend your account's Stripe subscription trial by 1-30 days (POST /v1/tier2/trial/extend). Internal operations tool (support use); customer accounts receive 403. Trial extension directly affects revenue, so there is no plan to open it up. Cumulative cap of 60 days (aggregated from the last 30 days of audit logs); 409 unless status='trialing'. dryRun must be passed explicitly (guards against accidental mutation via an implicit false); when dryRun=false, idempotencyKey is also required (16-128 alphanumeric plus '_-'). Re-calling with the same key returns the cached result via the tier2_idempotency table (structurally preventing retry double-extends). dryRun=true previews previousTrialEnd / newTrialEnd / the cumulative total only (no Stripe call); dryRun=false performs the actual Stripe mutation plus the accounts_subscription sync update.

apply_promo_code_to_customer

Apply a user-facing promotion code already registered in Stripe (e.g. 'LAUNCH50') to your account's Stripe subscription (POST /v1/tier2/promo/apply). Internal operations tool (support use); customer accounts receive 403. It will not be opened up without terms covering economically impactful operations (timing undecided). 409 if an active discount already exists (structural defense against stacking), and 409 when the status is canceled / incomplete_expired. Redemption is delegated to Stripe via promotion_code (applying coupons directly is forbidden as a constraint bypass); dryRun must be passed explicitly, and idempotencyKey is required when dryRun=false. Re-calls with the same key return the cached result via the tier2_idempotency table, structurally serializing concurrent applies. dryRun=true previews resolution + the active-discount check + the estimated discount only (no Stripe mutation); dryRun=false applies the promotion code.

detect_anomaly

Compare the current window against a baseline window (the immediately preceding window of the same length) and detect anomalies across 4 axes: cost / latency / error_rate / call_volume — lets an AI grasp "is anything off?" in one prompt. Sensitivity is tunable via threshold: sensitive (1.5x) / normal (2x, default) / conservative (3x). 0-4 detections, each with a narrative. Returns { window, threshold, multiplier (the numeric factor behind threshold), current: {...}, baseline: {...}, anomalies: [{ axis, severity: 'minor'|'major'|'critical', current, baseline, ratio, narrative }], partialFailures?: string[] (axes that failed to fetch, as 'current:xxx' / 'baseline:xxx'; omitted when everything succeeds) }. errorRate is evaluated and displayed as a percent (0-100), matching the backend aggregate unit. Insufficient baseline data (fewer than 10 records in the period) yields anomalies: [] plus a warning message (this path omits multiplier; partialFailures is optional in the same way).

propose_alert_rules

Analyze the call patterns over the past lookbackDays (7-30, default 14) and propose recommended alert rules for cost / latency / error_rate / anomaly as JSON. Applying them is a separate step via create_alert after customer confirmation (propose only — zero side effects). Rules whose type already exists are normally not proposed (existing types are fetched via list_alerts); however, if the list_alerts fetch fails, the existing set is treated as empty and overlapping proposals may be returned (failed axes are reported in partialFailures). Returns { lookbackDays, baseline: {meanDailyCost (USD), p95Latency (ms), errorRate (percent 0-100), dailyCalls, totalCalls}, proposals: [{ name, alertType, thresholdValue, windowMinutes, reasoning }], skipped: [{ alertType, reason }], partialFailures?: string[] (axes that failed to fetch; omitted when everything succeeds) }. The thresholdValue of an error_rate proposal is also a percent (consistent with backend create_alert).

get_account_health

Get a health summary of your LLM infrastructure in one call. Fetches 4 existing endpoints in parallel (aggregate_calls / get_percentiles / get_llm_budget / list_audit_log) and compresses them into one response. Returns { window, totals: {calls, costUsd, errorRate (percent 0-100)}, latency: {p50, p95, p99 (ms)}, budget: {used, limit, percentUsed (0-100)}, recentEvents: count, summary: 'ok' | 'warn' | 'critical', partialFailures?: string[] (axes that failed to fetch; omitted when everything succeeds) }. critical = errorRate>=10% / budget>=90% / p95>=10s; warn = >=3% / >=70% / >=3s. Example phrasing: "how is our LLM infra doing right now?" — answered in one prompt. Pure read aggregator (no new backend endpoint); individual endpoint failures return partial results (one axis timing out does not block the summary; failed axes are listed in partialFailures).

aggregate_calls

Get an aggregation cube over calls (POST /v1/query/aggregate). groupBy (provider / model / day / hour / minute / tag / error) x metric (cost / latency / tokens / input_tokens / output_tokens / cached_tokens / cache_savings / count / error_rate) — e.g. "aggregate this month's cost by model" in one call. tag mode requires tagKey (alphanumerics plus _ - only, e.g. 'env' / 'feature'). error mode aggregates only error rows by error string (which errors, how many; metric=count recommended). hour mode caps at 168h / minute mode at 60min (400 beyond). cost = SUM(cost_usd) / latency = AVG(latency_ms) / tokens = SUM(total_tokens) / input_tokens = SUM(prompt_tokens) / output_tokens = SUM(completion_tokens) / cached_tokens = SUM(cached_read_tokens) / cache_savings = SUM(cache_savings_usd) / count = COUNT(*) / error_rate = errors / total. Returns { groups: [{key, value, count}], total: {value, count} }.

list_audit_log

List the audit log (GET /v1/audit-log). Scoped to your account; admin role only (viewer/member get 403). Lets an AI agent autonomously review recent operation history such as invitations / API key revocations / project changes. Filters = eventType ('invitation.created' / 'api_key.revoked' etc.) / targetKind / actorUserId / from / to. Supports cursor pagination (nextCursor format = 'created_at|id'), max limit 200.

list_saved_views

List the saved views (GET /v1/saved-views). A saved view is a named combination of frequently used /calls page filters (startDate/endDate/provider/model/limit). Enables phrasing like "show calls with my usual last-week OpenAI filter". Per account, max 20.

create_saved_view

Create a new saved view, or overwrite when the name exists (POST /v1/saved-views). name is unique within the account. filter follows the SavedViewFilter shape (startDate / endDate / provider / model / limit / preset / sortBy? / sortOrder?). Lets an AI agent save frequently used filters under a name — e.g. create a "last 7 days, GPT-4 only" view and recall it later.

delete_saved_view

Delete the saved view with the given id (DELETE /v1/saved-views/:id). Scoped to your account.

export_calls

Large-batch export of calls (POST /v1/query/export). Higher limit than query_calls (per-plan max records: Free 1000 / Pro 50000); available on all plans. Filter axes = startTime / endTime / provider / model plus limit. Example phrasing: "pull all of last month's GPT-4 calls and analyze the trends" — one call. The result format is the same JSON as query_calls (the AI can feed it straight into CSV / statistics).

bulk_delete_calls

Bulk-delete the given call ids (max 100), scoped to your account (POST /v1/calls/bulk-delete). Useful for cleaning up junk calls accumulated during development and testing. dryRun=true returns the matched count before deleting. The delete is one atomic SQL statement; a bulk_deleted event is recorded in the audit log. Per FK constraints, related traces / annotations / scores are cascade-deleted via ON DELETE.

compare_eval_runs

Compare two eval runs (baseline / candidate) and return per-criterion mean score deltas + the failed count delta + a verdict (GET /v1/eval-runs/compare). Lets an AI agent grasp "how did the candidate change relative to the baseline" in one call, for prompt-improvement measurement and regression detection. verdict = improved / regressed / mixed / unchanged. The failed count treats scores <= 2 as "failed". Same account only.

run_eval

Start a new eval run immediately (POST /v1/eval-runs). Scores the most recent N calls against the 5 default criteria (plus up to 8 custom criteria) using gpt-4o-mini. Pro+ only (Free gets 403); environments without OPENAI_API_KEY provisioned return 500 from the backend. Precondition: only calls with plaintext storage (the content-storage opt-in) ON are scored. With the opt-in OFF (the default) there are zero candidates and the run returns summary.scoredCount=0 with reason='no_plaintext_calls' (gating, not a failure). Cost: about $0.01 per run (20 calls x 5 criteria = 100 LLM calls); e.g. 30 runs/month is about $0.30.

list_eval_datasets

List your account's golden datasets (GET /v1/eval-datasets). Each dataset has a name / description / item count / frozen state. A golden dataset is a fixed test set with expected outputs — the population run_eval_dataset pushes through a target model to measure regression A/B.

get_eval_dataset

Fetch one dataset's detail plus all of its items (GET /v1/eval-datasets/:id). datasetId is list_eval_datasets.datasets[].id.

create_eval_dataset

Create a golden dataset (POST /v1/eval-datasets, Pro+ only). items can carry up to 20 test cases with expected outputs. Up to 50 datasets per account. frozen=true freezes the population (items can no longer be changed or unfrozen — fixing comparability for regression verdicts).

run_eval_dataset

Run a golden dataset against a target model and produce a regression verdict (POST /v1/eval-datasets/:id/run, Pro+ only). Feeds each item's inputText to targetModel, has gpt-4o-mini score the outputs against the default criteria plus expectedOutput, and records eval_scores (regression A/B). Results can be compared across runs with compare_eval_runs. Run records are excluded from production cost / analytics / alert aggregation. Cost: item count x criteria count LLM calls. 503 in environments without OPENAI_API_KEY provisioned.

delete_eval_dataset

Delete a golden dataset (DELETE /v1/eval-datasets/:id, Pro+ only). Items are cascade-deleted. Past eval runs / scores remain.

get_daily_readthrough

Fetch a Readthrough issue (Argosvix's agent reads one trending OSS repo per day via the GitHub API and records what it found). Public data tool — works without an API key. Omit date = latest issue; date (YYYY-MM-DD) = that issue. Response = { issue: { date, repo: { owner, name, url, language?, license?, stars? }, oneLiner, oneLinerEn?, keyFiles: [{ path, why, whyEn? }], highlights, cautions, generation?, traceId?, generatedAt } }. A reading guide, not a review — "files worth reading", "design highlights", "facts to check before adopting". Use for: "what's today's featured OSS repo?" "what should I check before adopting this repo?"

get_synth_daily

Fetch Synth Daily issue data (a daily AI digest produced by Argosvix's own agent pipeline). Public data tool — works without an API key (alongside get_daily_readthrough). Omit date = latest issue; date (YYYY-MM-DD) = that issue. Response = { issue: { date, scoop, items: [{ rank, name, desc, why, sourceUrl, metric, nameEn?, descEn?, whyEn? }], generatedAt } }. desc/why are Japanese, descEn/whyEn are English. metric carries first-party numbers (e.g. '+4,349 stars/day'). Use for: "what's new in AI today?" "any new models or price cuts?"

Claude Desktop / Cursor

Paste into your MCP client config file to install this server.

{
    "mcpServers": {
        "argosvix \u2014 ai agent observability (87 tools)": {
            "argosvix": {
                "command": "npx",
                "args": [
                    "-y",
                    "@argosvix/mcp-server"
                ],
                "env": {
                    "ARGOSVIX_API_KEY": "argk_..."
                }
            }
        }
    }
}

McpServers

{
    "argosvix": {
        "command": "npx",
        "args": [
            "-y",
            "@argosvix/mcp-server"
        ],
        "env": {
            "ARGOSVIX_API_KEY": "argk_..."
        }
    }
}

@argosvix/mcp-server

v0.30.0-alpha.10 — Argosvix MCP server lets AI agents (Claude Desktop, Cursor, Codex CLI, custom MCP clients) query, manage, and operate their LLM observability data directly from the conversation. Supports both stdio (subprocess) and HTTP (remote / self-host) transports.

Surface: 87 tools (84 generally available + 3 founder-ops scoped) / 3 resources / 8 resource templates / 3 prompts. Autonomous-AI-ops endpoints (get_account_health / detect_anomaly / propose_alert_rules / classify_calls_batch / propose_eval_criteria) plus runtime control plane (budget gates / policy gates / human-approval gates) complete the "agent that can both observe AND act" narrative. Release history is available on npm.

npm version
License: MIT

Why

You're already sending LLM calls through @argosvix/sdk or the Python SDK. Now ask Claude / Cursor questions like:

- "What was my OpenAI cost over the past 24h?"
- "Which alerts are firing right now?"
- "Show me the 20 most expensive calls today."

No dashboard tab-switching. The agent fetches the data via this MCP server using your Argosvix API key.

Install

npm install -g @argosvix/mcp-server

Configure (Claude Desktop)

Edit your Claude Desktop config:

- macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
- Windows: %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "argosvix": {
      "command": "argosvix-mcp",
      "env": {
        "ARGOSVIX_API_KEY": "argk_..."
      }
    }
  }
}

Restart Claude Desktop. All 87 tools appear under the argosvix__ prefix (e.g. argosvix__query_calls, argosvix__get_account_health, argosvix__create_budget_gate).

> No API key yet? The server also starts without ARGOSVIX_API_KEY in introspection-only mode (since v0.30.0-alpha.14): all 87 tools are listed so you can evaluate the surface, and any tool call returns instructions for getting a key at https://dashboard.argosvix.com/api-keys.

Configure (Cursor)

Edit ~/.cursor/mcp.json:

{
  "mcpServers": {
    "argosvix": {
      "command": "argosvix-mcp",
      "env": {
        "ARGOSVIX_API_KEY": "argk_..."
      }
    }
  }
}

Tool profile (ARGOSVIX_MCP_PROFILE)

The default profile is full (all 87 tools). If your MCP client's context budget is tight, set ARGOSVIX_MCP_PROFILE=core to expose only the 11 essentials for day-to-day operations:

query_calls · aggregate_calls · get_cost_summary · get_percentiles · get_account_health · detect_anomaly · list_alerts · create_alert · silence_alert · unsilence_alert · get_deployed_prompt

{
  "mcpServers": {
    "argosvix": {
      "command": "argosvix-mcp",
      "env": {
        "ARGOSVIX_API_KEY": "argk_...",
        "ARGOSVIX_MCP_PROFILE": "core"
      }
    }
  }
}

Works in both stdio and HTTP transports. Unknown values fall back to full with a warning on stderr.

Description language (ARGOSVIX_MCP_LANG)

Tool, resource, and prompt descriptions returned by tools/list / resources/list /
prompts/list are in English by default. Set ARGOSVIX_MCP_LANG=ja to get the original
Japanese descriptions instead. Unset or unknown values fall back to en (with a warning
on stderr for unknown values). Tool names, input schemas, and behavior are identical in
both languages — only the human/agent-facing description text changes.

{
  "mcpServers": {
    "argosvix": {
      "command": "argosvix-mcp",
      "env": {
        "ARGOSVIX_API_KEY": "argk_...",
        "ARGOSVIX_MCP_LANG": "ja"
      }
    }
  }
}

Works in both stdio and HTTP transports.

Tools (highlights)

87 tools in total — the full list is returned by tools/list. A sample of the core read / write surface:

| Tool | Purpose | Type |
|---|---|---|
| query_calls | Recent LLM call records, filterable by provider / model / time range | read |
| get_cost_summary | Aggregate cost / calls / tokens by provider or model | read |
| list_alerts | Configured alerts + recent trigger status | read |
| get_alert | Detail of a specific alert + recent trigger history | read |
| list_alert_events | Alert trigger events across the account (notification history) | read |
| silence_alert | Mute a specific alert (= temporary notification stop, default 24h) | write |
| unsilence_alert | Resume notifications for a previously muted alert | write |
| create_alert | Create a new alert rule (cost / error rate / latency / anomaly) | write |
| acknowledge_alert | Mark a specific alert event as acknowledged (idempotent, orthogonal to silence) | write |

Resources (Phase 3, expanded in 0.5.0-alpha.1)

Resources expose read-only snapshots that AI agents can pull into context without an explicit tool call.

| URI | Purpose |
|---|---|
| argosvix://account | Plan / quota / current-month record usage / retention snapshot (non-sensitive, Bearer-only) |
| argosvix://alerts/active | Snapshot of currently enabled alerts |
| argosvix://cost/today | Last-24h cost breakdown by provider (with response.total) |

Resource templates (Phase 3, expanded in 0.8.0-alpha.1)

Resource templates let agents construct dynamic URIs from a known id. The server enforces account scope via PK lookup on the backend, so cross-account ids return 404.

| URI template | Purpose |
|---|---|
| argosvix://calls/{id} | Single LLM call record (provider / model / tokens / cost / latency / tags / error / trace_id). Plug in any id from query_calls results. |
| argosvix://alerts/{id} | Single alert rule (name / type / threshold / window / channelKinds / sleep / enabled / silencedUntil) + recent 20 trigger events. Plug in any id from list_alerts results. channelTargets (notification destinations) is structurally dropped. |
| argosvix://traces/{id} | Single trace = all spans grouped by trace_id (LLM call time-series). Top 50 spans only (LLM context budget cap); errorDetails / requestMeta are structurally dropped. Plug in any traceId from query_calls results. |

Prompts (Phase 3, new in 0.4.0-alpha.1)

Prompts are reusable templates the user can launch as slash commands.

| Name | Purpose |
|---|---|
| cost_review | Compare 24h / 7d / 30d cost trends and flag anomalies |
| alert_audit | Audit current alert rules and propose improvements |
| incident_triage | Investigate recent error / latency anomalies (default last 24h) |

Subscriptions (= v0.10, stdio only)

resources.subscribe capability is declared in stdio mode. Clients can subscribe to one or more of the static resources below; the server polls each subscribed resource every 60 seconds and emits notifications/resources/updated when the content hash changes.

Subscribable URIs (resource templates such as argosvix://calls/{id} are not subscribable):

- argosvix://account
- argosvix://alerts/active
- argosvix://cost/today

HTTP transport (= argosvix-mcp --http) does not declare subscribe and rejects subscribe requests, since per-request stateless mode cannot keep a subscription set or deliver server-initiated notifications. Use stdio for live updates.

listChanged is intentionally not declared: the resource list is fixed for the server lifetime.

Implementation notes (v0.10):
- Single-flight guard: a slow polling cycle does not start a concurrent next cycle (= no overlapping readResource calls).
- Unsubscribe / shutdown race: per-URI re-check before fetch and before notify, plus an isShuttingDown flag, so notifications are not emitted for URIs removed mid-cycle.
- Failure handling: fetch and notify failures are silent (next cycle retries). With ARGOSVIX_MCP_DEBUG=1 the server logs { uri, errorClass } to stderr — error messages are intentionally not logged to avoid leaking upstream payload text.
- Tests: 150 unit tests (incl. overlap single-flight + unsubscribe / shutdown race + invalid URI → McpError(InvalidParams) + axis 4 Tier 1 dispatcher coverage).

Privacy

The MCP server sends queries to https://ingest.argosvix.com using your API key. No prompts or completions are exposed — only metadata (tokens, cost, latency, model name, your tags).

Development

npm install
npm run build
npm test

License

MIT © Yuto Makihara (Argosvix). See LICENSE.

HTTP transport (new in 0.3.0-alpha.1)

The server can also run as a remote MCP endpoint over HTTP, suitable for
self-hosting or multi-tenant scenarios where API key is supplied per request.

```bash

No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.