trackmcp
Back to directory
raditotev

agent-trust

View on GitHub

AgentTrust is a pure MCP-only reputation and trust scoring server for AI agents.

0 stars PythonOthers Updated Mar 22, 2026

Documentation

AgentTrust

Reputation and trust scoring service for AI agents, exposed entirely as an MCP server. Evaluate counterparties before transacting, report interaction outcomes, issue portable trust certificates, and detect Sybil attacks.

Table of Contents


Quickstart

1. Connect to the MCP server

Add AgentTrust to your MCP client configuration:

json
{
  "mcpServers": {
    "agent-trust": {
      "url": "https://agent-trust.radi.pro/mcp"
    }
  }
}

Or for local development via stdio:

json
{
  "mcpServers": {
    "agent-trust": {
      "command": "uv",
      "args": ["run", "python", "-m", "agent_trust.server"]
    }
  }
}

2. Register your agent

code
register_agent(display_name="my-agent", capabilities=["search", "summarize"])

Response:

json
{
  "agent_id": "550e8400-e29b-41d4-a716-446655440000",
  "source": "standalone",
  "scopes": ["trust.read", "trust.report"],
  "created": true,
  "public_key_hex": "a1b2c3...",
  "private_key_hex": "d4e5f6...",
  "warning": "Key pair auto-generated. Store private_key_hex securely."
}

Store the `private_key_hex` immediately -- it is shown only once.

3. Generate an access token

code
generate_agent_token(
  agent_id="550e8400-...",
  private_key_hex="d4e5f6..."
)

Response:

json
{
  "access_token": "eyJ...",
  "expires_at": "2026-03-20T13:00:00+00:00",
  "ttl_minutes": 60,
  "agent_id": "550e8400-..."
}

4. Check trust before transacting

code
check_trust(agent_id="counterparty-uuid")

5. Report interaction outcomes

code
report_interaction(
  counterparty_id="counterparty-uuid",
  interaction_type="transaction",
  outcome="success",
  access_token="eyJ..."
)

Both parties should report for mutual confirmation (higher credibility).


Connecting to the MCP Server

AgentTrust supports two MCP transports:

TransportUse caseEndpoint
Streamable HTTPRemote agents, production`https://agent-trust.radi.pro/mcp`
stdioLocal development, MCP Inspector`uv run python -m agent_trust.server`

Authentication

AgentTrust supports two authentication methods. Many tools work without authentication, but reporting interactions, filing disputes, and issuing attestations require it.

AgentAuth (preferred)

Obtain a bearer token from AgentAuth and pass it as `access_token`. This provides the full set of scopes:

ScopeGrants
`trust.read`Score breakdowns, pending confirmations
`trust.report`Report and confirm interactions
`trust.dispute.file`File disputes
`trust.dispute.resolve`Resolve disputes (arbitrators)
`trust.attest.issue`Issue signed attestations
`trust.admin`Alert subscriptions

Standalone (Ed25519)

Register with `register_agent` and generate tokens with `generate_agent_token`. Provides `trust.read` and `trust.report` scopes. You can upgrade to AgentAuth later via `link_agentauth`.

No authentication

Tools marked as "Auth: none" work without any token. Useful for checking trust scores and verifying attestations.


Tools Reference

Discovery

`discover`

Auth: none

Returns the complete service catalog: available tools, auth methods, score types, interaction types, rate limits, and a quickstart guide. Call this first when connecting.

code
discover()

Agent Management

`register_agent`

Auth: none

Register a new agent in the trust network. Three paths:

1. AgentAuth -- pass `access_token` from AgentAuth

2. Standalone -- pass your own `public_key_hex` (hex-encoded Ed25519 public key)

3. Auto-generate -- omit both to get a keypair generated for you

ParameterTypeRequiredDescription
`display_name`stringnoHuman-readable name (max 200 chars)
`capabilities`list[string]noTags like `["search", "code-review"]` (max 50)
`metadata`dictnoArbitrary key-value data (max 10KB)
`access_token`stringnoAgentAuth bearer token
`public_key_hex`stringnoHex-encoded Ed25519 public key
code
register_agent(
  display_name="my-search-agent",
  capabilities=["search", "summarize"]
)

`generate_agent_token`

Auth: none (uses private key directly)

Generate a signed JWT access token for standalone agents.

ParameterTypeRequiredDescription
`agent_id`stringyesUUID from `register_agent`
`private_key_hex`stringyes64 hex chars, Ed25519 private key
`ttl_minutes`intnoToken lifetime, default 60, max 1440
code
generate_agent_token(
  agent_id="550e8400-...",
  private_key_hex="d4e5f6...",
  ttl_minutes=120
)

`whoami`

Auth: required

Check your identity, current trust scores, and scopes.

ParameterTypeRequiredDescription
`access_token`stringnoAgentAuth bearer token
`public_key_hex`stringnoHex-encoded public key
code
whoami(access_token="eyJ...")

`get_agent_profile`

Auth: none (authenticated calls get extra detail)

Retrieve the public profile for any agent.

ParameterTypeRequiredDescription
`agent_id`stringyesUUID to look up
`access_token`stringnoFor additional details
code
get_agent_profile(agent_id="550e8400-...")

`search_agents`

Auth: none

Search agents by trust score, capabilities, and interaction count.

ParameterTypeRequiredDescription
`min_score`floatnoMinimum score 0.0-1.0 (default 0.0)
`score_type`stringno`overall`, `reliability`, `responsiveness`, `honesty`, or `domain:*`
`capabilities`list[string]noRequired capabilities (must have ALL)
`min_interactions`intnoMinimum interaction count
`limit`intnoMax results, default 20, max 100
code
search_agents(min_score=0.7, capabilities=["code-review"], limit=10)

Auth: required (AgentAuth token)

Link an existing standalone profile to an AgentAuth identity, merging interaction history. The canonical `agent_id` after linking is always the original standalone UUID — the AgentAuth UUID is stored as `agentauth_id` in metadata.

ParameterTypeRequiredDescription
`access_token`stringyesAgentAuth bearer token
`public_key_hex`stringyesPublic key from standalone registration
`signed_proof`stringyesJWT signed with private key (claims: `sub`, `action`, `iat`)
`dry_run`boolnoValidate everything without committing changes (default `false`)

Response:

json
{
  "agent_id": "550e8400-...",
  "canonical_agent_id": "550e8400-...",
  "agentauth_id": "aa-uuid-...",
  "merged": true,
  "message": "Standalone profile successfully linked to AgentAuth identity. ..."
}

On `dry_run=true`: returns `would_link_agent_id`, `agentauth_id`, `current_scores`, `interaction_count`, `capabilities`, and `message` — no changes are persisted.

Error codes: `invalid_input`, `proof_sig_invalid`, `proof_expired`, `key_not_found`, `already_linked`, `authentication_failed`.

Auth: required (AgentAuth token)

Preflight check: validate a `link_agentauth` proof without writing to the database. Runs the same validation steps (token authenticity, key lookup, proof signature, expiry, already-linked check) but never persists any changes. Use this before calling `link_agentauth` to confirm everything is in order.

ParameterTypeRequiredDescription
`access_token`stringyesAgentAuth bearer token
`public_key_hex`stringyesHex-encoded Ed25519 public key of the standalone agent
`signed_proof`stringyesJWT signed with the standalone private key
code
verify_link_proof(
  access_token="eyJ...",
  public_key_hex="a1b2c3...",
  signed_proof="eyJ..."
)

Response:

json
{
  "valid": true,
  "checks": {
    "token_valid": true,
    "key_found": true,
    "proof_sig_valid": true,
    "proof_not_expired": true,
    "already_linked": false
  },
  "agent_id": "550e8400-..."
}

`agent_status`

Auth: required

One-call status snapshot combining identity, trust scores, pending confirmation count, and active attestations. Useful as a dashboard or health check.

ParameterTypeRequiredDescription
`access_token`stringnoAgentAuth bearer token
`public_key_hex`stringnoHex-encoded Ed25519 public key (standalone agents)
code
agent_status(access_token="eyJ...")

Response:

json
{
  "agent_id": "550e8400-...",
  "agentauth_linked": true,
  "scores": {"overall": 0.73, "reliability": 0.81},
  "scopes": ["trust.read", "trust.report"],
  "pending_confirmations": 2,
  "active_attestations": [
    {
      "attestation_id": "b1c2d3e4-...",
      "valid_until": "2026-03-21T12:00:00+00:00",
      "seconds_remaining": 86400
    }
  ]
}

Trust Scoring

`check_trust`

Auth: none (authenticated calls with `trust.read` scope get `factor_breakdown`)

Primary tool for evaluating an agent before a transaction. Returns a score (0.0-1.0), confidence (0.0-1.0), interaction count, and a plain-language explanation.

ParameterTypeRequiredDescription
`agent_id`stringyesUUID to evaluate
`score_type`stringnoDefault `overall`
`access_token`stringnoFor factor breakdown
code
check_trust(agent_id="550e8400-...", score_type="reliability")

Response:

json
{
  "agent_id": "550e8400-...",
  "score_type": "reliability",
  "score": 0.82,
  "confidence": 0.71,
  "interaction_count": 15,
  "explanation": "High trust score with 15 interactions. Mostly positive.",
  "computed_at": "2026-03-20T12:00:00+00:00"
}

> A score of 0.5 with confidence 0.05 means "unknown", not "average". Low confidence means few interactions -- treat with caution.

`check_trust_batch`

Auth: none

Check trust scores for up to 20 agents in a single call.

ParameterTypeRequiredDescription
`agent_ids`list[string]yesUp to 20 UUIDs
`score_type`stringnoDefault `overall`
code
check_trust_batch(agent_ids=["uuid-1", "uuid-2", "uuid-3"])

`compare_agents`

Auth: none

Rank up to 10 agents side-by-side by score.

ParameterTypeRequiredDescription
`agent_ids`list[string]yesUp to 10 UUIDs
`score_type`stringnoDefault `overall`
code
compare_agents(agent_ids=["uuid-1", "uuid-2"], score_type="honesty")

`get_score_breakdown`

Auth: required (`trust.read` scope)

Detailed Bayesian factors behind a score: raw score, dispute penalty, alpha/beta parameters, interaction weights.

ParameterTypeRequiredDescription
`agent_id`stringyesUUID
`access_token`stringyesToken with `trust.read` scope
code
get_score_breakdown(agent_id="550e8400-...", access_token="eyJ...")

Interaction Reporting

`report_interaction`

Auth: required (`trust.report` scope)

Report the outcome of an interaction with another agent. Both parties should report for mutual confirmation -- one-sided reports carry less weight.

ParameterTypeRequiredDescription
`counterparty_id`stringyesUUID of the other agent
`interaction_type`stringyes`transaction`, `delegation`, `query`, or `collaboration`
`outcome`stringyes`success`, `failure`, `timeout`, or `partial`
`access_token`stringyesToken with `trust.report` scope
`context`dictnoMetadata like `{"amount": 100, "task_type": "code-review"}` (max 10KB)
`evidence_hash`stringnoSHA-256 hex hash of supporting evidence (64 chars)
code
report_interaction(
  counterparty_id="550e8400-...",
  interaction_type="transaction",
  outcome="success",
  access_token="eyJ...",
  context={"amount": 100, "task_type": "code-review"}
)

Response:

json
{
  "interaction_id": "a1b2c3d4-...",
  "reporter_id": "my-agent-uuid",
  "counterparty_id": "550e8400-...",
  "outcome": "success",
  "mutually_confirmed": false,
  "reported_at": "2026-03-20T12:00:00+00:00"
}

`confirm_interaction`

Auth: required (`trust.report` scope)

Confirm a counterparty's interaction report. Creates mutual confirmation, which increases the report's weight in score computation.

ParameterTypeRequiredDescription
`interaction_id`stringyesUUID from the other agent's `report_interaction`
`outcome`stringyesYour view: `success`, `failure`, `timeout`, or `partial`
`access_token`stringyesToken with `trust.report` scope
`context`dictnoAdditional context from your perspective
code
confirm_interaction(
  interaction_id="a1b2c3d4-...",
  outcome="success",
  access_token="eyJ..."
)

`list_pending_confirmations`

Auth: required

List interactions reported by other agents that await your confirmation.

ParameterTypeRequiredDescription
`access_token`stringyesYour access token
`since_days`intnoLookback window, default 30, max 365
`limit`intnoMax results, default 50, max 200
code
list_pending_confirmations(access_token="eyJ...")

`get_interaction_history`

Auth: required

Retrieve interaction history for an agent.

ParameterTypeRequiredDescription
`agent_id`stringyesUUID
`interaction_type`stringnoFilter by type
`outcome`stringnoFilter by outcome
`since_days`intnoLookback window, default 90, max 365
`limit`intnoMax results, default 50, max 200
`access_token`stringyesYour access token
code
get_interaction_history(
  agent_id="550e8400-...",
  interaction_type="transaction",
  since_days=30,
  access_token="eyJ..."
)

Disputes

`file_dispute`

Auth: required (`trust.dispute.file` scope)

Challenge an interaction outcome you believe was reported incorrectly.

ParameterTypeRequiredDescription
`interaction_id`stringyesUUID of the disputed interaction
`reason`stringyesExplanation (max 5000 chars)
`access_token`stringyesToken with `trust.dispute.file` scope
`evidence`dictnoSupporting evidence (max 10KB)
code
file_dispute(
  interaction_id="a1b2c3d4-...",
  reason="The task was completed successfully but reported as failure",
  access_token="eyJ..."
)

Limits: max 10 disputes per day, max 30 open disputes at once. Agents with 5+ dismissed disputes are blocked from filing new ones (24h cooldown after each dismissal).

`resolve_dispute`

Auth: required (`trust.dispute.resolve` scope, arbitrators only)

Resolve an open dispute. Requires AgentAuth permission check.

ParameterTypeRequiredDescription
`dispute_id`stringyesUUID of the dispute
`resolution`stringyes`upheld`, `dismissed`, or `split`
`access_token`stringyesArbitrator's token
`resolution_note`stringnoExplanation (max 2000 chars)
code
resolve_dispute(
  dispute_id="d1e2f3...",
  resolution="upheld",
  access_token="eyJ...",
  resolution_note="Evidence confirms task was completed"
)

Attestations

`issue_attestation`

Auth: required (`trust.attest.issue` scope)

Issue a portable, Ed25519-signed JWT capturing an agent's current trust scores. The agent can present this to third parties who verify the signature without querying AgentTrust.

ParameterTypeRequiredDescription
`agent_id`stringyesUUID of the agent to attest
`access_token`stringyesToken with `trust.attest.issue` scope
`ttl_hours`intnoValidity period, default 12, range 1-72
code
issue_attestation(
  agent_id="550e8400-...",
  access_token="eyJ...",
  ttl_hours=24
)

Response:

json
{
  "attestation_id": "b1c2d3e4-...",
  "subject_agent_id": "550e8400-...",
  "jwt_token": "eyJ...",
  "score_snapshot": {
    "overall": {"score": 0.82, "confidence": 0.71},
    "reliability": {"score": 0.85, "confidence": 0.65}
  },
  "valid_from": "2026-03-20T12:00:00+00:00",
  "valid_until": "2026-03-21T12:00:00+00:00"
}

`list_my_attestations`

Auth: required

List your active (non-expired, non-revoked) attestations. Each entry includes the attestation ID, validity window, seconds remaining, and the score snapshot captured at issuance.

ParameterTypeRequiredDescription
`access_token`stringnoAgentAuth bearer token
`public_key_hex`stringnoHex-encoded Ed25519 public key (standalone agents)
code
list_my_attestations(access_token="eyJ...")

Response:

json
{
  "agent_id": "550e8400-...",
  "attestations": [
    {
      "attestation_id": "b1c2d3e4-...",
      "issued_at": "2026-03-20T12:00:00+00:00",
      "valid_until": "2026-03-21T12:00:00+00:00",
      "seconds_remaining": 86400,
      "score_snapshot": {"overall": {"score": 0.82, "confidence": 0.71}}
    }
  ],
  "count": 1
}

`verify_attestation`

Auth: none

Verify an attestation JWT's signature, expiry, and revocation status. No authentication needed -- this is designed for third-party verification.

ParameterTypeRequiredDescription
`jwt_token`stringyesJWT from `issue_attestation`
code
verify_attestation(jwt_token="eyJ...")

Response:

json
{
  "valid": true,
  "attestation_id": "b1c2d3e4-...",
  "subject_agent_id": "550e8400-...",
  "score_snapshot": {"overall": {"score": 0.82, "confidence": 0.71}},
  "issued_at": "2026-03-20T12:00:00+00:00",
  "valid_until": "2026-03-21T12:00:00+00:00",
  "seconds_remaining": 43200
}

Sybil Detection

`sybil_check`

Auth: none

Detect potential Sybil behavior: ring reporting (mutual positive feedback loops), burst registration (many agents in a short window), and suspicious delegation chains.

ParameterTypeRequiredDescription
`agent_id`stringyesUUID to check
code
sybil_check(agent_id="550e8400-...")

Response:

json
{
  "agent_id": "550e8400-...",
  "risk_score": 0.15,
  "is_suspicious": false,
  "is_high_risk": false,
  "signals": [],
  "checked_at": "2026-03-20T12:00:00+00:00"
}

When signals are detected:

json
{
  "signals": [
    {
      "signal_type": "ring_reporting",
      "severity": "high",
      "description": "Mutual positive feedback loop detected",
      "evidence": {"ring_size": 3, "agents": ["uuid-1", "uuid-2", "uuid-3"]}
    }
  ]
}

Resources

MCP resources provide read-only access to trust data via URI templates:

URIDescription
`trust://agents/{agent_id}/score`Current trust scores in all categories
`trust://agents/{agent_id}/history`Interaction history summary (last 90 days)
`trust://agents/{agent_id}/attestations`Active (non-expired, non-revoked) attestations
`trust://leaderboard/{score_type}`Top 50 agents ranked by score type
`trust://disputes/{dispute_id}`Full details of a specific dispute
`trust://health`Service health: DB, Redis, AgentAuth, worker queue

Prompts

Pre-built prompt templates for common evaluation workflows:

PromptParametersDescription
`evaluate_counterparty_prompt``agent_id`, `transaction_value`, `transaction_type`Structured evaluation before a transaction
`explain_score_change_prompt``agent_id`Investigate why a trust score changed
`dispute_assessment_prompt``dispute_id`Structured assessment for dispute arbitration

Score Types

TypeBased onDescription
`overall`All interaction typesComposite score
`reliability`Transaction, delegation, collaborationDoes the agent deliver?
`responsiveness`Query, delegationDoes the agent respond timely?
`honesty`CollaborationIs the agent truthful?
`domain:*`CustomDomain-specific scores (e.g., `domain:code-review`)

Scores use a Bayesian Beta distribution with exponential time decay (90-day half-life) and dispute penalties. Scores range from 0.0 to 1.0, paired with a confidence value:

  • High score + high confidence = trustworthy, well-established agent
  • High score + low confidence = looks good but too few interactions to be sure
  • 0.5 score + near-zero confidence = unknown agent (prior), not "average"

Rate Limits

Requests are rate-limited per agent per minute, with higher limits for more trusted agents:

Trust LevelRequests/min
Root (AgentAuth)120
Delegated90
Standalone60
Ephemeral30
Unauthenticated10

Additional limits on specific operations:

  • Interaction reports: max 10 per pair per day, 1 per type per pair per hour
  • Disputes filed: max 10 per day, max 30 open at once
  • Dispute targets: max 10 open disputes per target

Self-Hosting

Prerequisites

  • Python 3.13+
  • PostgreSQL 16
  • Redis 7
  • uv package manager

Setup

bash
# Clone and install
git clone 
cd agent-trust
uv sync

# Start infrastructure
docker compose up -d postgres redis

# Generate server signing key (first time only)
uv run python scripts/generate_keypair.py

# Run database migrations
uv run alembic upgrade head

# (Optional) Register scopes with AgentAuth
AGENTAUTH_ACCESS_TOKEN= uv run python scripts/register_scopes.py

Environment Variables

Create a `.env` file:

bash
DATABASE_URL=postgresql+asyncpg://agent_trust:agent_trust@localhost:5432/agent_trust
REDIS_URL=redis://localhost:6379/0
SIGNING_KEY_PATH=keys/service.key

# Auth: "agentauth", "standalone", or "both" (default: both)
AUTH_PROVIDER=both
AGENTAUTH_MCP_URL=https://agentauth.radi.pro/mcp
AGENTAUTH_ACCESS_TOKEN=

# Scoring
SCORE_HALF_LIFE_DAYS=90
DISPUTE_PENALTY=0.03
ATTESTATION_TTL_HOURS=24

# Transport: "stdio" or "streamable-http"
MCP_TRANSPORT=stdio
MCP_PORT=8000

# Production
ENVIRONMENT=development  # set to "production" to bind 0.0.0.0
LOG_LEVEL=INFO
JSON_LOGS=false

Running

bash
# Local development (stdio)
uv run python -m agent_trust.server

# Production (HTTP)
uv run python -m agent_trust.server --transport streamable-http --port 8000

# Background worker (score recomputation, attestation expiry)
uv run python scripts/run_worker.py

# Test with MCP Inspector
uv run mcp dev src/agent_trust/server.py

Docker

Run the full stack with Docker Compose:

bash
docker compose up -d

This starts PostgreSQL, Redis, the MCP server (port 8140), the background worker, Prometheus (port 9090), and Grafana (port 3001).

Tests

bash
uv run pytest                          # all tests
uv run pytest tests/test_tools/ -v     # MCP tools
uv run pytest tests/test_engine/ -v    # score algorithm
uv run pytest tests/test_auth/ -v      # authentication
uv run pytest tests/test_integration/  # end-to-end

Frequently asked questions

What is agent-trust?

agent-trust is AgentTrust is a pure MCP-only reputation and trust scoring server for AI agents.

How do I install agent-trust?

Open the GitHub repository and follow its README. Most MCP servers are added to your client's MCP config, then called by your agent.

Is agent-trust open source?

Yes — it is hosted on GitHub at https://github.com/raditotev/agent-trust.

Related MCP tools

Run your own MCP server? See who uses it and what to fix.

Measure it with TrackMCP