Skip to main content
Glama

generate_non_fungible_post_condition

Create mandatory NFT transfer post-conditions for SIP-009 tokens to ensure secure blockchain transactions by specifying ownership requirements.

Instructions

Generate a non-fungible token post-condition for SIP-009 NFTs. Post-conditions are MANDATORY for all NFT transfers.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
assetNameYesThe NFT asset name (usually same as contract name)
conditionCodeYesThe condition type ('owns' or 'does_not_own')
contractAddressYesThe NFT contract address
contractNameYesThe NFT contract name
principalYesThe Stacks address for the post-condition
tokenIdYesThe NFT token ID

Implementation Reference

  • The complete tool object for 'generate_non_fungible_post_condition', including the execute handler that generates formatted documentation, TypeScript implementation code, Clarity contract requirements, and security notes for SIP-009 non-fungible post-conditions.
    export const generateNonFungiblePostConditionTool: Tool<undefined, typeof NonFungiblePostConditionScheme> = {
      name: "generate_non_fungible_post_condition",
      description: "Generate a non-fungible token post-condition for SIP-009 NFTs. Post-conditions are MANDATORY for all NFT transfers.",
      parameters: NonFungiblePostConditionScheme,
      execute: async (args, context) => {
        try {
          await recordTelemetry({ action: "generate_non_fungible_post_condition" }, context);
          
          return `# Non-Fungible Token Post-Condition
    
    ## Configuration
    - **Principal**: ${args.principal}
    - **Condition**: ${args.conditionCode}
    - **Token ID**: ${args.tokenId}
    - **Asset**: ${args.contractAddress}.${args.contractName}.${args.assetName}
    
    ## TypeScript Implementation
    
    \`\`\`typescript
    import {
      makeStandardNonFungiblePostCondition,
      NonFungibleConditionCode,
      createAssetInfo,
      uintCV
    } from '@stacks/transactions';
    
    const postCondition = makeStandardNonFungiblePostCondition(
      '${args.principal}',
      NonFungibleConditionCode.${args.conditionCode === 'owns' ? 'Owns' : 'DoesNotOwn'},
      createAssetInfo(
        '${args.contractAddress}',
        '${args.contractName}',
        '${args.assetName}'
      ),
      uintCV(${args.tokenId})
    );
    
    // Use in transaction
    const postConditions = [postCondition];
    
    await openContractCall({
      // ... other parameters
      postConditions,
      postConditionMode: PostConditionMode.Deny, // REQUIRED for security
    });
    \`\`\`
    
    ## Clarity Contract Requirements
    
    For this post-condition to work, the contract must use native asset functions:
    
    \`\`\`clarity
    ;; REQUIRED: Native non-fungible token definition
    (define-non-fungible-token ${args.assetName} uint)
    
    ;; REQUIRED: Use nft-transfer? for transfers
    (define-public (transfer (token-id uint) (sender principal) (recipient principal))
      (begin
        ;; ... validation logic ...
        (try! (nft-transfer? ${args.assetName} token-id sender recipient))
        ;; ... rest of function ...
      )
    )
    \`\`\`
    
    ## Usage Patterns
    - **${args.conditionCode === 'owns' ? 'Owns' : 'DoesNotOwn'}**: ${args.conditionCode === 'owns' 
        ? `${args.principal} will own NFT #${args.tokenId} after transaction` 
        : `${args.principal} will NOT own NFT #${args.tokenId} after transaction`}
    
    ## Security Notes
    - ✅ This post-condition guarantees ownership state for NFT #${args.tokenId}
    - ✅ Transaction will fail if ownership doesn't match expectation
    - ✅ Protects against unauthorized NFT movements
    - ⚠️  Always verify current ownership before creating conditions`;
          
        } catch (error) {
          return `❌ Failed to generate non-fungible post-condition: ${error}`;
        }
      },
    };
  • Zod input schema (NonFungiblePostConditionScheme) defining parameters for generating non-fungible post-conditions: principal, conditionCode (owns/does_not_own), tokenId, contractAddress, contractName, assetName.
    const NonFungiblePostConditionScheme = z.object({
      principal: z.string().describe("The Stacks address for the post-condition"),
      conditionCode: NonFungibleConditionCodeScheme.describe("The condition type ('owns' or 'does_not_own')"),
      tokenId: z.number().describe("The NFT token ID"),
      contractAddress: z.string().describe("The NFT contract address"),
      contractName: z.string().describe("The NFT contract name"),
      assetName: z.string().describe("The NFT asset name (usually same as contract name)"),
    });
  • Registers the generateNonFungiblePostConditionTool (named 'generate_non_fungible_post_condition') with the FastMCP server instance.
    server.addTool(generateNonFungiblePostConditionTool);
Behavior3/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It states that post-conditions are 'MANDATORY,' which implies this is a required step for compliance or security in NFT transfers. However, it doesn't describe what the tool outputs, error conditions, or any side effects, leaving gaps in behavioral understanding.

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

Conciseness5/5

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

The description is extremely concise—two sentences that are front-loaded with the core purpose and usage rule. Every word earns its place, with no redundancy or unnecessary elaboration, making it efficient for an agent to parse.

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

Completeness4/5

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

Given the complexity (6 required parameters for a specialized blockchain operation) and no output schema, the description is reasonably complete. It clarifies the tool's role in NFT transfers and the mandatory nature of post-conditions, but it could improve by hinting at the output format or linking to related tools like 'generate_sip009_transfer' for broader context.

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 already documents all 6 parameters thoroughly. The description adds no additional parameter semantics beyond what's in the schema, such as explaining relationships between parameters (e.g., how assetName relates to contractName) or usage examples. This meets the baseline of 3 when schema coverage is high.

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

Purpose5/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 a non-fungible token post-condition for SIP-009 NFTs.' It specifies the exact resource (SIP-009 NFT post-conditions) and distinguishes it from sibling tools like 'generate_fungible_post_condition' and 'generate_stx_post_condition' by focusing on NFTs rather than fungible tokens or STX.

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

Usage Guidelines5/5

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

The description provides explicit usage guidance: 'Post-conditions are MANDATORY for all NFT transfers.' This tells the agent when to use this tool (for NFT transfers) and implies it should not be used for other types of transactions, offering clear context without naming alternatives directly.

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/exponentlabshq/stacks-clarity-mcp'

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