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';
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden for behavioral disclosure. It mentions 'security features' and 'human-readable instructions,' but lacks details on permissions, side effects, rate limits, or error handling. For a tool that generates requests (likely involving data processing), this is insufficient to inform the agent about operational risks or requirements.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, well-structured sentence that efficiently conveys the core functionality. It front-loads the main action ('Generate complete presentation request flows') and lists key features without redundancy. However, it could be slightly more concise by integrating the features more seamlessly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (8 parameters, nested objects, no output schema, and no annotations), the description is inadequate. It doesn't explain what the tool returns, how errors are handled, or the implications of generating 'wallet-ready requests.' For a tool with significant input complexity and no structured behavioral hints, more context is needed to guide effective use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents all 8 parameters. The description adds minimal value beyond the schema, mentioning 'DIF PEX v2.0 definitions' and 'multiple format support,' which loosely relate to parameters like 'presentationDefinition' and 'requestFormat.' This meets the baseline for high schema coverage but doesn't provide additional semantic context.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Generate complete presentation request flows with DIF PEX v2.0 definitions.' It specifies the verb ('generate'), resource ('presentation request flows'), and technical standard ('DIF PEX v2.0'). However, it doesn't explicitly differentiate from sibling tools like 'create_presentation_definition' or 'submit_presentation,' which reduces it from a perfect score.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It mentions features like 'wallet-ready requests' and 'multiple format support,' but doesn't specify prerequisites, use cases, or contrast with sibling tools such as 'create_presentation_definition' or 'submit_presentation.' This leaves the agent without clear direction on tool selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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