get_verifiable_credential
Generate a W3C Verifiable Credential for AI agents to prove identity and enable interoperability with any VC verifier using wallet address.
Instructions
Get a W3C Verifiable Credential for an agent. Returns the agent passport in W3C VC Data Model 2.0 format, interoperable with any VC verifier. Free.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| wallet_address | Yes | Agent wallet address (0x... or Solana base58) |
Implementation Reference
- src/mcp-server.js:569-600 (handler)The handler for the 'get_verifiable_credential' MCP tool, which utilizes generatePassport to build and return a Verifiable Credential.
async ({ wallet_address }) => { try { const passport = generatePassport(wallet_address); if (!passport) { return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: 'No active agent found for this wallet' }, null, 2) }] }; } const agent = passport.agent; const reputation = passport.reputation; const stamp = passport.stamp; const accountability = passport.accountability; const now = new Date().toISOString(); const vc = { '@context': ['https://www.w3.org/ns/credentials/v2', 'https://agentstamp.org/ns/credentials/v1'], type: ['VerifiableCredential', 'AgentTrustCredential'], issuer: { id: 'did:web:agentstamp.org', name: 'AgentStamp' }, validFrom: now, validUntil: agent.expires_at, credentialSubject: { id: `did:pkh:eip155:8453:${agent.wallet_address}`, type: 'AIAgent', name: agent.name, trustScore: reputation?.score || 0, trustTier: reputation?.label || 'new', humanSponsor: accountability?.human_sponsor || null, stamp: stamp ? { tier: stamp.tier, valid: stamp.valid } : null, }, credentialStatus: { id: `https://agentstamp.org/api/v1/trust/check/${agent.wallet_address}`, type: 'AgentStampTrustCheck', }, - src/mcp-server.js:562-568 (registration)Registration of the 'get_verifiable_credential' tool in the MCP server.
// --- Tool: get_verifiable_credential --- server.tool( 'get_verifiable_credential', 'Get a W3C Verifiable Credential for an agent. Returns the agent passport in W3C VC Data Model 2.0 format, interoperable with any VC verifier. Free.', { wallet_address: z.string().describe('Agent wallet address (0x... or Solana base58)'), }, - src/passport.js:20-140 (helper)Helper function that resolves wallet information, gathers agent data, and constructs a signed agent passport object.
function generatePassport(walletAddress) { const db = getDb(); // Resolve to primary wallet and get all linked wallets const resolvedWallet = resolvePrimaryWallet(walletAddress); const walletInfo = getAllLinkedWallets(resolvedWallet); const allWallets = walletInfo.all; const placeholders = allWallets.map(() => '?').join(','); // Find agent across all linked wallets const agent = db.prepare( `SELECT * FROM agents WHERE wallet_address IN (${placeholders}) AND status = 'active' ORDER BY registered_at ASC LIMIT 1` ).get(...allWallets); if (!agent) return null; // Get best stamp across all linked wallets let stamp = null; const bestStamp = db.prepare( `SELECT id, tier, issued_at, expires_at, revoked FROM stamps WHERE wallet_address IN (${placeholders}) AND revoked = 0 AND expires_at > datetime('now') ORDER BY CASE tier WHEN 'gold' THEN 1 WHEN 'silver' THEN 2 WHEN 'bronze' THEN 3 WHEN 'free' THEN 4 ELSE 5 END LIMIT 1` ).get(...allWallets); if (bestStamp) stamp = bestStamp; else if (agent.stamp_id) { stamp = db.prepare( 'SELECT id, tier, issued_at, expires_at, revoked FROM stamps WHERE id = ?' ).get(agent.stamp_id); } // Compute reputation const reputation = computeReputation(agent.id); // Parse stored JSON fields const capabilities = JSON.parse(agent.capabilities || '[]'); const protocols = JSON.parse(agent.protocols || '[]'); const metadata = JSON.parse(agent.metadata || '{}'); // Build the passport document const now = new Date().toISOString(); const passportData = { // Header version: '1.0', type: 'AgentPassport', issued_at: now, issuer: 'https://agentstamp.org', // Identity agent: { id: agent.id, name: agent.name, description: agent.description, wallet_address: agent.wallet_address, category: agent.category, capabilities, protocols, endpoint_url: agent.endpoint_url, status: agent.status, registered_at: agent.registered_at, expires_at: agent.expires_at, }, // Accountability accountability: { human_sponsor: agent.human_sponsor || null, ai_act_risk_level: agent.ai_act_risk_level || null, transparency_declaration: agent.transparency_declaration ? (() => { try { return JSON.parse(agent.transparency_declaration); } catch { return null; } })() : null, }, // Stamp verification stamp: stamp ? { id: stamp.id, tier: stamp.tier, issued_at: stamp.issued_at, expires_at: stamp.expires_at, valid: !stamp.revoked && new Date(stamp.expires_at) > new Date(), verify_url: `https://agentstamp.org/api/v1/stamp/verify/${stamp.id}`, } : null, // Reputation reputation: reputation ? { score: reputation.score, label: reputation.label, breakdown: reputation.breakdown, } : null, // A2A Agent Card (Google's agent-to-agent protocol) a2a: buildA2ACard(agent, capabilities, protocols, stamp, reputation), // Linked wallets (cross-chain portability) wallets: { primary: walletInfo.primary, linked: walletInfo.linked.map(l => ({ address: l.linked_wallet, chain: l.chain_hint || null, linked_at: l.linked_at, })), }, // MCP metadata mcp: { server_url: agent.endpoint_url || null, capabilities: capabilities, supported_protocols: protocols, }, // Verification info verification: { public_key: getPublicKey(), algorithm: 'Ed25519', verify_endpoint: 'https://agentstamp.org/.well-known/passport-public-key', }, }; // Sign the entire passport const signature = signCertificate(passportData); return { ...passportData, signature, }; }