Skip to main content
Glama
AlyssonM

HiveAuth MCP Server

by AlyssonM

generate_presentation_request

Create secure wallet-ready presentation requests with DIF PEX v2.0 definitions, including human-readable instructions and multiple format support for verifiable credential verification.

Instructions

Generate complete presentation request flows with DIF PEX v2.0 definitions. Creates wallet-ready requests with security features, human-readable instructions, and multiple format support.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
presentationDefinitionYesDIF PEX Presentation Definition
verifierDidNoDID of the verifier requesting the presentation
callbackUrlNoURL where presentation should be submitted
challengeNoChallenge nonce for presentation security
domainNoDomain for presentation binding
expiresInNoRequest expiration time in seconds (1 minute to 24 hours)
requestFormatNoFormat for the presentation requestjson
includeInstructionsNoWhether to include human-readable instructions

Implementation Reference

  • The core handler function that implements the generate_presentation_request tool. It validates input using the schema, generates a presentation request structure (DIF PEX v2.0 compatible), supports JWT/JSON formats, analyzes complexity, generates instructions, and returns a detailed markdown-formatted result with usage instructions and security features.
    export async function generatePresentationRequest(args: unknown): Promise<CallToolResult> { const validation = validateAndSanitizeInput( TOOL_SCHEMAS.generate_presentation_request, args, 'generate_presentation_request' ); if (!validation.success) { return createValidationErrorResult(validation.error!); } const data = validation.data!; const startTime = Date.now(); try { const { presentationDefinition, verifierDid, callbackUrl, challenge, domain, expiresIn, requestFormat, includeInstructions } = data; // Generate unique challenge if not provided const requestChallenge = challenge || randomBytes(32).toString('hex'); // Calculate expiration time const now = new Date(); const expiresAt = new Date(now.getTime() + expiresIn! * 1000); // Generate request ID const requestId = `pex_req_${randomBytes(16).toString('hex')}`; // Create the presentation request structure const presentationRequest = { id: requestId, type: 'PresentationRequest', from: verifierDid || 'unknown_verifier', created_time: now.toISOString(), expires_time: expiresAt.toISOString(), challenge: requestChallenge, domain: domain, presentation_definition: presentationDefinition, callback_url: callbackUrl, format: requestFormat }; // Generate human-readable instructions const instructions = includeInstructions ? generateInstructions(presentationDefinition) : null; // Create different formats based on requestFormat let formattedRequest: any; let contentType: string; if (requestFormat! === 'jwt') { // For JWT format, we'd typically sign this, but for demo purposes we'll show the structure const jwtPayload = { iss: verifierDid || 'unknown_verifier', aud: 'credential_holder', iat: Math.floor(now.getTime() / 1000), exp: Math.floor(expiresAt.getTime() / 1000), nonce: requestChallenge, presentation_definition: presentationDefinition, callback_url: callbackUrl }; formattedRequest = { format: 'jwt', jwt_header: { alg: 'EdDSA', typ: 'JWT', kid: verifierDid ? `${verifierDid}#key-1` : 'verification_key' }, jwt_payload: jwtPayload, note: 'In production, this would be a signed JWT token' }; contentType = 'application/jwt'; } else { formattedRequest = presentationRequest; contentType = 'application/json'; } // Analyze the request complexity const analysisResults = analyzePresentationRequest(presentationDefinition); const processingTime = Date.now() - startTime; return { content: [ { type: 'text', text: `✅ **Presentation Request Generated Successfully** **Request Overview:** • **Request ID:** ${requestId} • **Format:** ${requestFormat!.toUpperCase()} • **Content Type:** ${contentType} • **Processing Time:** ${processingTime}ms • **Expires:** ${expiresAt.toISOString()} (in ${Math.round(expiresIn! / 60)} minutes) **🎯 Request Details:** • **Verifier DID:** ${verifierDid || 'Not specified'} • **Challenge:** ${requestChallenge.substring(0, 16)}... (${requestChallenge.length} chars) • **Domain:** ${domain || 'Not specified'} • **Callback URL:** ${callbackUrl || 'Not specified'} **📋 Presentation Definition Analysis:** • **Definition ID:** ${presentationDefinition.id} • **Purpose:** ${presentationDefinition.purpose || 'Not specified'} • **Input Descriptors:** ${presentationDefinition.input_descriptors.length} • **Complexity:** ${analysisResults.complexity} • **Estimated Response Time:** ${analysisResults.estimatedTime} **🔍 Requirements Summary:** ${analysisResults.requirementsSummary.map((req: any, index: number) => `${index + 1}. **${req.id}**: ${req.description}` ).join('\n')} ${includeInstructions ? `**📖 Human-Readable Instructions:** ${instructions} ` : ''}**📄 Generated Request:** \`\`\`json ${JSON.stringify(formattedRequest, null, 2)} \`\`\` **🚀 Usage Instructions:** **For Wallet Integration:** 1. Present this request to the credential holder's wallet 2. The wallet should evaluate available credentials against the presentation definition 3. User selects which credentials to include in the response 4. Wallet creates a verifiable presentation matching the requirements 5. Presentation is submitted to the callback URL (if provided) **For API Integration:** \`\`\`javascript // Send request to wallet/holder const response = await fetch(walletEndpoint, { method: 'POST', headers: { 'Content-Type': '${contentType}', 'Accept': 'application/json' }, body: JSON.stringify(${requestFormat! === 'jwt' ? 'formattedRequest.jwt_payload' : 'formattedRequest'}) }); \`\`\` **For QR Code Generation:** The request can be encoded as a QR code for mobile wallet scanning: \`\`\` presentation-request://${Buffer.from(JSON.stringify(formattedRequest)).toString('base64')} \`\`\` **🔒 Security Features:** • **Challenge-Response:** ${requestChallenge ? 'Implemented' : 'Not used'} • **Domain Binding:** ${domain ? 'Configured' : 'Not configured'} • **Time-bound:** ${expiresIn!}s expiration • **Request Integrity:** ${requestFormat! === 'jwt' ? 'JWT signed (in production)' : 'JSON format'} **🔧 Verification Steps:** 1. **Receive Presentation:** Wait for holder to submit presentation 2. **Validate Challenge:** Ensure challenge matches this request 3. **Check Expiration:** Verify presentation submitted before expiry 4. **Evaluate Compliance:** Use \`evaluate_presentation\` tool to check requirements 5. **Verify Signatures:** Validate all credential and presentation signatures ${analysisResults.recommendations.length > 0 ? `**💡 Optimization Recommendations:** ${analysisResults.recommendations.map((rec, index) => `${index + 1}. ${rec}`).join('\n')} ` : ''}🎉 **Request ready for deployment!** Share this with credential holders or integrate into your verification workflow. ` } ] }; } catch (error: any) { const processingTime = Date.now() - startTime; return { content: [ { type: 'text', text: `❌ **Presentation Request Generation Error** **Error:** ${error.message} **Processing Time:** ${processingTime}ms **Tool:** generate_presentation_request **📋 Input Summary:** • **Definition ID:** ${data.presentationDefinition.id} • **Request Format:** ${data.requestFormat} • **Verifier DID:** ${data.verifierDid || 'Not specified'} • **Expires In:** ${data.expiresIn}s **🔧 Troubleshooting:** 1. **Definition Validity:** Ensure presentation definition is valid DIF PEX v2.0 format 2. **URL Validation:** Check that callback URL is properly formatted if provided 3. **DID Format:** Verify verifier DID follows proper DID specification 4. **Time Bounds:** Ensure expiresIn is reasonable (60s - 24h) **🌐 Common Issues:** • Invalid presentation definition structure • Malformed callback URL • Unrealistic expiration times • Missing required fields in input descriptors For assistance, validate your presentation definition using the \`validate_presentation_definition\` tool first.` } ], isError: true }; } }
  • Zod input schema for validating the tool parameters, including presentationDefinition (required DIF PEX v2.0), optional verifier DID, callback URL, challenge, domain, expiration (default 3600s), format (jwt/json), and instructions flag.
    export const GeneratePresentationRequestInputSchema = z.object({ presentationDefinition: PresentationDefinitionSchema, verifierDid: z.string().optional().describe('DID of the verifier requesting the presentation'), callbackUrl: z.string().url('Callback URL must be valid').optional().describe('URL where presentation should be submitted'), challenge: z.string().optional().describe('Challenge nonce for presentation security'), domain: z.string().optional().describe('Domain for presentation binding'), expiresIn: z.number().int().min(60).max(86400).default(3600).describe('Request expiration time in seconds (1 minute to 24 hours)'), requestFormat: z.enum(['jwt', 'json']).default('json').describe('Format for the presentation request'), includeInstructions: z.boolean().default(true).describe('Whether to include human-readable instructions') });
  • src/index.ts:119-120 (registration)
    Tool dispatch/registration in the main MCP server switch statement, mapping the tool name to the handler function call.
    case 'generate_presentation_request': return await generatePresentationRequest(args);
  • TOOL_SCHEMAS mapping that registers the schema for use in tool metadata and validation.
    generate_presentation_request: GeneratePresentationRequestInputSchema
  • src/index.ts:32-32 (registration)
    Import statement that brings the handler into the main server module for dispatch.
    import { generatePresentationRequest } from './tools/generatePresentationRequest.js';

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/AlyssonM/hiveauth-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server