Skip to main content
Glama
stampchain-io

Stampchain MCP Server

Official

get_recent_sales

Retrieve recent stamp sales with enhanced transaction details to analyze market activity and track blockchain transactions.

Instructions

Retrieve recent stamp sales with enhanced transaction details (v2.3 feature)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
stamp_idNoFilter by specific stamp ID
dayRangeNoNumber of days to look back for sales
fullDetailsNoEnable enhanced transaction information
pageNoPage number
page_sizeNoItems per page
sort_orderNoSort order by timestampDESC

Implementation Reference

  • The execute method in GetRecentSalesTool implements the core handler logic for the get_recent_sales tool, including parameter validation, API call to fetch sales data, response formatting, and error handling.
    public async execute(params: GetRecentSalesParams, context?: ToolContext): Promise<ToolResponse> {
      try {
        context?.logger?.info('Executing get_recent_sales tool', { params });
    
        // Validate parameters
        const validatedParams = this.validateParams(params);
    
        // Use API client from context if available, otherwise use instance client
        const client = context?.apiClient || this.apiClient;
    
        // Check if v2.3 features are available
        const features = client.getFeatureAvailability();
        if (!features.recentSales) {
          return textResponse(
            'Recent sales data is not available in the current API version. Please upgrade to v2.3 or later.'
          );
        }
    
        // Get recent sales data
        const salesData: RecentSalesResponse = await client.getRecentSales(validatedParams);
    
        if (!salesData.data || salesData.data.length === 0) {
          return textResponse('No recent sales found for the specified criteria');
        }
    
        // Format the response
        const lines = [
          `Recent Sales (${salesData.data.length} results, ${validatedParams.dayRange} days):`,
        ];
        lines.push('---');
    
        salesData.data.forEach((sale, index) => {
          lines.push(`${index + 1}. Stamp #${sale.stamp_id}`);
          lines.push(`   Transaction: ${sale.tx_hash}`);
          lines.push(`   Block: ${sale.block_index}`);
          lines.push(`   Price: ${sale.price_btc} BTC`);
          if (sale.price_usd) {
            lines.push(`   Price USD: $${sale.price_usd.toFixed(2)}`);
          }
          if (sale.buyer_address) {
            lines.push(`   Buyer: ${sale.buyer_address}`);
          }
          if (sale.time_ago) {
            lines.push(`   Time: ${sale.time_ago}`);
          }
          if (sale.dispenser_address) {
            lines.push(`   Dispenser: ${sale.dispenser_address}`);
          }
          lines.push('');
        });
    
        // Add metadata
        lines.push('Metadata:');
        lines.push(`- Day Range: ${salesData.metadata.dayRange} days`);
        lines.push(`- Last Updated: ${new Date(salesData.metadata.lastUpdated).toISOString()}`);
        lines.push(`- Total Results: ${salesData.metadata.total}`);
        lines.push(`- Last Block: ${salesData.last_block}`);
    
        return textResponse(lines.join('\n'));
      } catch (error) {
        context?.logger?.error('Error executing get_recent_sales tool', { error });
    
        if (error instanceof ValidationError) {
          throw error;
        }
    
        if (error instanceof ToolExecutionError) {
          throw error;
        }
    
        // Pass through the original error message for API errors
        if (error instanceof Error) {
          throw new ToolExecutionError(error.message, this.name, error);
        }
    
        throw new ToolExecutionError('Failed to retrieve recent sales data', this.name, error);
      }
  • Zod schema definition for input parameters of the get_recent_sales tool, including validation rules for filters like stamp_id, dayRange, pagination, and sorting.
    export const GetRecentSalesParamsSchema = z.object({
      stamp_id: z.number().int().positive().optional(),
      dayRange: z.number().int().min(1).max(365).optional().default(30),
      fullDetails: z.boolean().optional().default(false),
      page: z.number().int().min(1).optional().default(1),
      page_size: z.number().int().min(1).max(100).optional().default(20),
      sort_order: z.enum(['ASC', 'DESC']).optional().default('DESC'),
    });
    
    export type GetRecentSalesParams = z.infer<typeof GetRecentSalesParamsSchema>;
  • Registration of GetRecentSalesTool class in the stampTools export object under the 'get_recent_sales' key for tool discovery and instantiation.
    export const stampTools = {
      get_stamp: GetStampTool,
      search_stamps: SearchStampsTool,
      get_recent_stamps: GetRecentStampsTool,
      get_recent_sales: GetRecentSalesTool,
      get_market_data: GetMarketDataTool,
      get_stamp_market_data: GetStampMarketDataTool,
    };
  • Factory function createStampTools that instantiates GetRecentSalesTool with API client and registers it under 'get_recent_sales' for use in tool servers.
    export function createStampTools(apiClient?: StampchainClient) {
      return {
        get_stamp: new GetStampTool(apiClient),
        search_stamps: new SearchStampsTool(apiClient),
        get_recent_stamps: new GetRecentStampsTool(apiClient),
        get_recent_sales: new GetRecentSalesTool(apiClient),
        get_market_data: new GetMarketDataTool(apiClient),
        get_stamp_market_data: new GetStampMarketDataTool(apiClient),
      };
    }
  • StampchainClient.getRecentSales method that performs the actual API request for recent sales data, with version fallback and error handling, called by the tool handler.
    async getRecentSales(params: RecentSalesQueryParams = {}): Promise<RecentSalesResponse> {
      const features = this.getFeatureAvailability();
    
      if (!features.recentSales) {
        // Fallback for older API versions - use regular stamps endpoint
        this.logger.info('Recent sales not available in this API version, using fallback');
        const stamps = await this.searchStamps({
          limit: params.page_size || 20,
          sort_order: params.sort_order || 'DESC',
        });
    
        // Transform to match RecentSalesResponse format
        return {
          data: stamps.map((stamp) => ({
            tx_hash: stamp.tx_hash,
            block_index: stamp.block_index,
            stamp_id: stamp.stamp || 0,
            price_btc: typeof stamp.floorPrice === 'number' ? stamp.floorPrice : 0,
            price_usd: stamp.floorPriceUSD || null,
            timestamp: stamp.block_index, // Use block_index as timestamp approximation
          })),
          metadata: {
            dayRange: params.dayRange || 30,
            lastUpdated: Date.now(),
            total: stamps.length,
          },
          last_block: stamps[0]?.block_index || 0,
        };
      }
    
      return this.executeWithFallback(
        () =>
          this.client.get<RecentSalesResponse>('/stamps/recentSales', { params }).then((r) => r.data),
        async () => {
          // Fallback implementation for when v2.3 endpoint fails
          const stamps = await this.searchStamps({
            limit: params.page_size || 20,
            sort_order: params.sort_order || 'DESC',
          });
    
          return {
            data: stamps.map((stamp) => ({
              tx_hash: stamp.tx_hash,
              block_index: stamp.block_index,
              stamp_id: stamp.stamp || 0,
              price_btc: typeof stamp.floorPrice === 'number' ? stamp.floorPrice : 0,
              price_usd: stamp.floorPriceUSD || null,
              timestamp: stamp.block_index,
            })),
            metadata: {
              dayRange: params.dayRange || 30,
              lastUpdated: Date.now(),
              total: stamps.length,
            },
            last_block: stamps[0]?.block_index || 0,
          };
        }
      );
    }
Behavior2/5

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

With no annotations provided, the description carries full burden but lacks critical behavioral details. It doesn't disclose whether this is a read-only operation, potential rate limits, authentication requirements, or what happens when parameters are omitted. The mention of 'enhanced transaction details' hints at richer output but doesn't specify format or limitations.

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, efficient sentence that front-loads the core purpose. However, it could be more structured by explicitly mentioning key parameters like date range filtering, which is implied but not stated.

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?

For a tool with 6 parameters, no annotations, and no output schema, the description is inadequate. It doesn't explain return values, error conditions, or how parameters interact (e.g., combining stamp_id with dayRange). The mention of 'v2.3 feature' is useful but doesn't compensate for missing behavioral 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 minimal value beyond implying 'enhanced transaction details' relates to the 'fullDetails' parameter, but doesn't explain what 'enhanced' means or provide additional context about parameter interactions.

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 verb 'retrieve' and resource 'recent stamp sales', specifying it provides 'enhanced transaction details' as a v2.3 feature. It distinguishes from siblings like 'get_recent_stamps' by focusing on sales rather than stamps themselves, though it doesn't explicitly mention this distinction.

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 like 'get_market_data' or 'get_recent_stamps'. It mentions 'enhanced transaction details' as a feature but doesn't explain when this is preferable over simpler queries or other sales-related tools.

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/stampchain-io/stampchain-mcp'

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