Market Structure MCP: Tool Contracts

Market Structure MCP: Tool Contracts

This document defines the API contracts for Market Structure MCP tools. All tools consume raw data from Core Government Data MCP and produce decision-ready analytical outputs.

Common Input Types

NAICS Code

  • Type: string
  • Format: 2-6 digits (e.g., "54", "5412", "541211")
  • Normalization: Leading zeros stripped (e.g., "0054""54")
  • Validation: Must be valid NAICS code
  • Examples: "54" (Professional Services), "541211" (CPA firms)

Geography

  • Type: string
  • Format: "{type}:{code}" or "{type}:*"
  • Supported Types:
    • "us:*" - National (all United States)
    • "state:{fips}" - State (e.g., "state:06" for California)
    • "metropolitan statistical area:{cbsa}" - MSA (e.g., "metropolitan statistical area:31080" for Los Angeles)
    • "county:{fips}" - County (e.g., "county:06037" for Los Angeles County)
  • Examples: "us:*", "state:06", "metropolitan statistical area:31080"

Year

  • Type: integer
  • Format: 4-digit year (e.g., 2023)
  • Range: Typically 2010-2023 (varies by dataset)
  • Validation: Must be within dataset availability range

Year Range

  • Type: object
  • Format: { "start_year": integer, "end_year": integer }
  • Validation: start_year <= end_year, both within dataset range
  • Example: { "start_year": 2020, "end_year": 2023 }

Firm Size

  • Type: string
  • Format: Predefined categories
  • Values:
    • "small" - 0-49 employees
    • "medium" - 50-249 employees
    • "large" - 250+ employees
    • "micro" - 0-4 employees (future)
    • "enterprise" - 500+ employees (future)

Common Output Types

Provenance Envelope

Every tool response includes a provenance object:

{
  "provenance": {
    "sources": Array<{
      "agency": string,           // e.g., "Census Bureau"
      "dataset": string,           // e.g., "BDS"
      "dataset_id": string,        // e.g., "BDS_2023"
      "release_date": string,      // ISO date: "2024-03-15"
      "variables": string[],       // e.g., ["ESTABS_ENTRY", "ESTABS_EXIT"]
      "url": string                // Optional: link to dataset documentation
    }>,
    "transforms": string[],        // List of transform steps applied
    "units": {
      "currency": string,          // e.g., "USD"
      "inflation_base_year": integer,  // e.g., 2023
      "geography": string          // Normalized geography code
    },
    "methodology": string          // Brief description of calculation method
  }
}

Success Response

{
  "success": true,
  "data": {
    // Tool-specific data fields
  },
  "provenance": { /* ProvenanceEnvelope */ }
}

Error Response

{
  "success": false,
  "error": {
    "error_code": string,          // e.g., "data_not_available"
    "message": string,             // Human-readable error message
    "retry_after": integer | null, // Seconds to wait before retry (if applicable)
    "suggestions": string[]        // Optional: suggestions for fixing the error
  }
}

Tool Contracts

1. get_market_size

Get market size in USD for a given industry and geography.

Signature:

get_market_size(
  naics: string,
  geography: string,
  year: integer
) -> SuccessResponse | ErrorResponse

Input Parameters:

Parameter Type Required Description
naics string Yes NAICS code (2-6 digits)
geography string Yes Geography code (e.g., "us:*", "state:06")
year integer Yes Year (4-digit, e.g., 2023)

Success Response Data:

{
  "success": true,
  "data": {
    "market_size_usd": number,        // Total market size in USD
    "num_firms": integer,             // Total number of firms
    "avg_firm_size_usd": number,      // Average firm size (revenue) in USD
    "naics": string,                  // Normalized NAICS code
    "geography": string,              // Normalized geography code
    "year": integer                   // Year
  },
  "provenance": { /* ProvenanceEnvelope */ }
}

Example:

{
  "success": true,
  "data": {
    "market_size_usd": 1250000000000,
    "num_firms": 125000,
    "avg_firm_size_usd": 10000000,
    "naics": "54",
    "geography": "us:*",
    "year": 2023
  },
  "provenance": {
    "sources": [
      {
        "agency": "Census Bureau",
        "dataset": "ABS",
        "dataset_id": "ABS_2023",
        "release_date": "2024-03-15",
        "variables": ["RCPTOT", "ESTAB"]
      }
    ],
    "transforms": [
      "Normalized NAICS code: '0054' → '54'",
      "Aggregated total receipts from ABS",
      "Adjusted for inflation to 2023 base year"
    ],
    "units": {
      "currency": "USD",
      "inflation_base_year": 2023,
      "geography": "us:*"
    },
    "methodology": "Market size calculated as sum of total receipts (RCPTOT) from ABS, adjusted for inflation to 2023 base year using BLS CPI."
  }
}

Error Codes:

  • data_not_available - Data suppressed or not available for this NAICS/geography/year
  • invalid_naics - Invalid NAICS code
  • invalid_geography - Invalid geography code
  • invalid_year - Year outside dataset range
  • api_error - Upstream API failure

Non-Goals:

  • Does NOT compute TAM/SAM/SOM breakdowns (handled by product layer)
  • Does NOT forecast future market size
  • Does NOT compare markets (use multiple calls)

2. get_firm_counts

Get firm counts by size category for a given industry and geography.

Signature:

get_firm_counts(
  naics: string,
  geography: string,
  year: integer
) -> SuccessResponse | ErrorResponse

Input Parameters:

Parameter Type Required Description
naics string Yes NAICS code (2-6 digits)
geography string Yes Geography code
year integer Yes Year (4-digit)

Success Response Data:

{
  "success": true,
  "data": {
    "firm_counts": {
      "0-4": integer,      // Firms with 0-4 employees
      "5-9": integer,      // Firms with 5-9 employees
      "10-19": integer,    // Firms with 10-19 employees
      "20-49": integer,    // Firms with 20-49 employees
      "50-99": integer,    // Firms with 50-99 employees
      "100-249": integer,  // Firms with 100-249 employees
      "250-499": integer,  // Firms with 250-499 employees
      "500+": integer      // Firms with 500+ employees
    },
    "total_firms": integer,  // Sum of all firm counts
    "naics": string,
    "geography": string,
    "year": integer
  },
  "provenance": { /* ProvenanceEnvelope */ }
}

Example:

{
  "success": true,
  "data": {
    "firm_counts": {
      "0-4": 25000,
      "5-9": 15000,
      "10-19": 5000,
      "20-49": 3000,
      "50-99": 1000,
      "100-249": 500,
      "250-499": 200,
      "500+": 150
    },
    "total_firms": 50850,
    "naics": "54",
    "geography": "us:*",
    "year": 2023
  },
  "provenance": {
    "sources": [
      {
        "agency": "Census Bureau",
        "dataset": "CBP",
        "dataset_id": "CBP_2023",
        "release_date": "2024-06-01",
        "variables": ["ESTAB", "EMP"]
      }
    ],
    "transforms": [
      "Normalized NAICS code: '0054' → '54'",
      "Aggregated establishment counts by employment size category from CBP"
    ],
    "units": {
      "currency": null,
      "inflation_base_year": null,
      "geography": "us:*"
    },
    "methodology": "Firm counts aggregated from CBP establishment data, grouped by employment size categories."
  }
}

Error Codes: Same as get_market_size

Non-Goals:

  • Does NOT compute market share (requires revenue data)
  • Does NOT filter by firm characteristics (use product layer)

3. get_entry_exit_rates

Get business entry and exit rates for a given industry and geography over a time range.

Signature:

get_entry_exit_rates(
  naics: string,
  geography: string,
  year_range: { start_year: integer, end_year: integer }
) -> SuccessResponse | ErrorResponse

Input Parameters:

Parameter Type Required Description
naics string Yes NAICS code (2-6 digits)
geography string Yes Geography code
year_range object Yes { start_year: integer, end_year: integer }

Success Response Data:

{
  "success": true,
  "data": {
    "entry_rate": number,           // Entry rate (0.0-1.0, e.g., 0.1 = 10%)
    "exit_rate": number,            // Exit rate (0.0-1.0)
    "net_formation_rate": number,   // Net formation rate (entry - exit)
    "entry_count": integer,         // Total establishments entered
    "exit_count": integer,         // Total establishments exited
    "total_establishments": integer, // Average establishments over period
    "yearly_rates": [               // Optional: Year-by-year breakdown
      {
        "year": integer,
        "entry_rate": number,
        "exit_rate": number,
        "net_formation_rate": number
      }
    ],
    "naics": string,
    "geography": string,
    "year_range": {
      "start_year": integer,
      "end_year": integer
    }
  },
  "provenance": { /* ProvenanceEnvelope */ }
}

Example:

{
  "success": true,
  "data": {
    "entry_rate": 0.10,
    "exit_rate": 0.07,
    "net_formation_rate": 0.03,
    "entry_count": 5000,
    "exit_count": 3500,
    "total_establishments": 50000,
    "yearly_rates": [
      {
        "year": 2020,
        "entry_rate": 0.08,
        "exit_rate": 0.09,
        "net_formation_rate": -0.01
      },
      {
        "year": 2021,
        "entry_rate": 0.12,
        "exit_rate": 0.06,
        "net_formation_rate": 0.06
      },
      {
        "year": 2022,
        "entry_rate": 0.11,
        "exit_rate": 0.07,
        "net_formation_rate": 0.04
      },
      {
        "year": 2023,
        "entry_rate": 0.09,
        "exit_rate": 0.08,
        "net_formation_rate": 0.01
      }
    ],
    "naics": "54",
    "geography": "us:*",
    "year_range": {
      "start_year": 2020,
      "end_year": 2023
    }
  },
  "provenance": {
    "sources": [
      {
        "agency": "Census Bureau",
        "dataset": "BDS",
        "dataset_id": "BDS_2020_2023",
        "release_date": "2024-03-15",
        "variables": ["ESTABS_ENTRY", "ESTABS_EXIT", "ESTABS"]
      }
    ],
    "transforms": [
      "Normalized NAICS code: '0054' → '54'",
      "Calculated entry rate as ESTABS_ENTRY / ESTABS",
      "Calculated exit rate as ESTABS_EXIT / ESTABS",
      "Aggregated across year range"
    ],
    "units": {
      "currency": null,
      "inflation_base_year": null,
      "geography": "us:*"
    },
    "methodology": "Entry and exit rates calculated from BDS establishment entry/exit data, averaged over the specified year range."
  }
}

Error Codes: Same as get_market_size, plus:

  • invalid_year_range - Invalid year range (start > end or outside dataset range)

Non-Goals:

  • Does NOT forecast future entry/exit rates
  • Does NOT compare industries (use multiple calls)

4. get_market_fragmentation

Get market fragmentation/concentration metrics.

Signature:

get_market_fragmentation(
  naics: string,
  geography: string,
  year: integer
) -> SuccessResponse | ErrorResponse

Input Parameters:

Parameter Type Required Description
naics string Yes NAICS code (2-6 digits)
geography string Yes Geography code
year integer Yes Year (4-digit)

Success Response Data:

{
  "success": true,
  "data": {
    "hhi": number,                  // Herfindahl-Hirschman Index (0-10000)
    "top4_concentration": number,   // Top 4 firm concentration ratio (0-100%)
    "top8_concentration": number,   // Top 8 firm concentration ratio (0-100%)
    "fragmentation_score": number, // Fragmentation score (0-100, higher = more fragmented)
    "total_firms": integer,
    "naics": string,
    "geography": string,
    "year": integer
  },
  "provenance": { /* ProvenanceEnvelope */ }
}

Example:

{
  "success": true,
  "data": {
    "hhi": 1250.50,
    "top4_concentration": 35.25,
    "top8_concentration": 48.75,
    "fragmentation_score": 87.50,
    "total_firms": 50000,
    "naics": "54",
    "geography": "us:*",
    "year": 2023
  },
  "provenance": {
    "sources": [
      {
        "agency": "Census Bureau",
        "dataset": "ABS",
        "dataset_id": "ABS_2023",
        "release_date": "2024-03-15",
        "variables": ["RCPTOT", "ESTAB"]
      }
    ],
    "transforms": [
      "Normalized NAICS code: '0054' → '54'",
      "Calculated HHI as sum of squared market shares",
      "Calculated top 4/8 concentration ratios",
      "Computed fragmentation score: 100 * (1 - HHI/10000)"
    ],
    "units": {
      "currency": "USD",
      "inflation_base_year": 2023,
      "geography": "us:*"
    },
    "methodology": "HHI calculated from firm revenue shares (RCPTOT) from ABS. Fragmentation score is normalized HHI (0-100 scale, higher = more fragmented)."
  }
}

Error Codes: Same as get_market_size

Non-Goals:

  • Does NOT identify specific firms (requires firm-level data)
  • Does NOT compute market share for individual firms

5. get_market_reachability

Get addressable market segments by firm size.

Signature:

get_market_reachability(
  naics: string,
  geography: string,
  firm_size: string
) -> SuccessResponse | ErrorResponse

Input Parameters:

Parameter Type Required Description
naics string Yes NAICS code (2-6 digits)
geography string Yes Geography code
firm_size string Yes Firm size category ("small", "medium", "large")

Success Response Data:

{
  "success": true,
  "data": {
    "addressable_firms": integer,        // Number of addressable firms
    "addressable_revenue_usd": number,   // Addressable revenue in USD
    "reachability_pct": number,         // Reachability percentage (0-100)
    "total_firms": integer,              // Total firms in market
    "total_revenue_usd": number,        // Total market revenue
    "firm_size": string,                // Normalized firm size category
    "size_range": string,               // Human-readable size range (e.g., "0-49 employees")
    "addressable_categories": string[], // CBP categories included (e.g., ["0-4", "5-9", "10-19", "20-49"])
    "naics": string,
    "geography": string,
    "year": integer                     // Most recent year available
  },
  "provenance": { /* ProvenanceEnvelope */ }
}

Example:

{
  "success": true,
  "data": {
    "addressable_firms": 48000,
    "addressable_revenue_usd": 1200000000000.00,
    "reachability_pct": 96.00,
    "total_firms": 50000,
    "total_revenue_usd": 1250000000000,
    "firm_size": "small",
    "size_range": "0-49 employees",
    "addressable_categories": ["0-4", "5-9", "10-19", "20-49"],
    "naics": "54",
    "geography": "us:*",
    "year": 2023
  },
  "provenance": {
    "sources": [
      {
        "agency": "Census Bureau",
        "dataset": "CBP",
        "dataset_id": "CBP_2023",
        "release_date": "2024-06-01",
        "variables": ["ESTAB", "PAYANN"]
      },
      {
        "agency": "Census Bureau",
        "dataset": "ABS",
        "dataset_id": "ABS_2023",
        "release_date": "2024-03-15",
        "variables": ["RCPTOT"]
      }
    ],
    "transforms": [
      "Normalized NAICS code: '0054' → '54'",
      "Mapped firm_size 'small' to CBP categories: 0-4, 5-9, 10-19, 20-49",
      "Aggregated firm counts and revenue for addressable categories",
      "Calculated reachability as addressable_firms / total_firms"
    ],
    "units": {
      "currency": "USD",
      "inflation_base_year": 2023,
      "geography": "us:*"
    },
    "methodology": "Addressable market calculated by aggregating firms in specified size categories from CBP and revenue from ABS. Reachability is the percentage of total market addressable."
  }
}

Error Codes: Same as get_market_size, plus:

  • invalid_firm_size - Invalid firm size category

Non-Goals:

  • Does NOT compute TAM/SAM/SOM (requires product-level logic)
  • Does NOT filter by other firm characteristics

Common Error Codes

Error Code Description HTTP Equivalent Retryable
data_not_available Data suppressed or not available 404 No
invalid_naics Invalid NAICS code 400 No
invalid_geography Invalid geography code 400 No
invalid_year Year outside dataset range 400 No
invalid_year_range Invalid year range 400 No
invalid_firm_size Invalid firm size category 400 No
api_error Upstream API failure 502 Yes
computation_error Analysis computation failed 500 No
rate_limit_exceeded Rate limit exceeded 429 Yes (with retry_after)

Versioning

  • Current Version: v1.0.0
  • Breaking Changes: New major version (e.g., v2.0.0)
  • New Features: New minor version (e.g., v1.1.0)
  • Bug Fixes: New patch version (e.g., v1.0.1)

References