Devlish programs are structured English that compiles to bytecode. The source you read is the source that runs. Below are full working examples across every major feature of the language, from basic variables to real-world programs that process files, call APIs, and serve as LLM tools.
The simplest Devlish program. Ask prompts for input (or receives it as JSON when called as a tool). Print outputs a value.
Ask "What is your name?" as name
Print "Hello, " joined with name joined with "!"
Variables are created with equals. Math uses natural English operators: plus, minus, times, divided by.
Ask "Hours worked?" as hours
Ask "Hourly rate?" as rate
gross_pay equals hours times rate
tax equals gross_pay times 0.22
net_pay equals gross_pay minus tax
Print "Gross pay: $" joined with gross_pay
Print "Tax (22%): $" joined with tax
Print "Net pay: $" joined with net_pay
Branching uses If and Otherwise. Conditions read like English sentences. Indentation defines blocks.
Ask "Customer age?" as age
Ask "Has membership card?" as has_card
If age is less than 12
discount equals 0.50
Print "Child discount: 50%"
Otherwise if age is greater than 65
discount equals 0.30
Print "Senior discount: 30%"
Otherwise if has_card is "yes"
discount equals 0.10
Print "Member discount: 10%"
Otherwise
discount equals 0
Print "No discount applies"
ticket_price equals 20
final_price equals ticket_price minus (ticket_price times discount)
Print "Final price: $" joined with final_price
Records are structured key-value pairs. Create them with record with, access fields with of, and update with with ... updated.
# Create a record
customer equals record with "Acme Corp" as name and "enterprise" as tier and 500000 as deal_size
# Access fields
Print "Customer: " joined with name of customer
Print "Tier: " joined with tier of customer
# Update a field (creates a new record, records are immutable)
upgraded_customer equals customer with "premium" as tier updated
Print "New tier: " joined with tier of upgraded_customer
# Nested records
address equals record with "123 Main St" as street and "Dallas" as city and "TX" as state
full_customer equals customer with address as billing_address updated
Print "City: " joined with city of billing_address of full_customer
Lists hold ordered collections. Build them with list of, filter with where, and transform with map ... using.
# Build a list
scores equals list of 85 and 92 and 78 and 95 and 88 and 71 and 99
# Filter: keep only scores above 80
high_scores equals filter scores where item is greater than 80
Print "High scores: " joined with high_scores
# Map: add 5 bonus points to each score
boosted equals map scores using item plus 5
Print "Boosted: " joined with boosted
# Count
Print "Total scores: " joined with count of scores
Print "High scores count: " joined with count of high_scores
# Lists of records
invoices equals list of (record with "INV-001" as id and 1500 as amount) and (record with "INV-002" as id and 3200 as amount) and (record with "INV-003" as id and 800 as amount)
# Filter records
large_invoices equals filter invoices where amount of item is greater than 1000
Print "Large invoices: " joined with count of large_invoices
Sort lists with sort ... by. Works on plain values and on record fields.
products equals list of (record with "Widget" as name and 29.99 as price) and (record with "Gadget" as name and 14.99 as price) and (record with "Doohickey" as name and 49.99 as price)
# Sort by price ascending
by_price equals sort products by price
Print "Cheapest: " joined with name of first of by_price
# Sort by name
by_name equals sort products by name
For each product in by_name
Print name of product joined with ": $" joined with price of product
Reduce collapses a list into a single value. Use it for sums, averages, and custom aggregations.
transactions equals list of 1200 and 850 and 3400 and 2100 and 675
# Sum
total equals reduce transactions from 0 using accumulator plus item
Print "Total: $" joined with total
# Average
average equals total divided by count of transactions
Print "Average: $" joined with average
# Find maximum
max_val equals reduce transactions from 0 using (If item is greater than accumulator then item Otherwise accumulator)
Print "Largest transaction: $" joined with max_val
# Reduce records: sum a field
line_items equals list of (record with "Hosting" as desc and 500 as cost) and (record with "Support" as desc and 200 as cost) and (record with "License" as desc and 1500 as cost)
invoice_total equals reduce line_items from 0 using accumulator plus cost of item
Print "Invoice total: $" joined with invoice_total
The must be constraint halts execution with a clear error if a value does not meet requirements. Use it for guardrails on inputs.
Ask "Loan amount?" as loan_amount
Ask "Applicant credit score?" as credit_score
Ask "Annual income?" as income
# Validate inputs: program halts with an error if any fail
loan_amount must be greater than 0
credit_score must be between 300 and 850
income must be greater than 0
# Debt-to-income ratio check
max_monthly_payment equals income divided by 12 times 0.36
requested_monthly equals loan_amount divided by 360
If requested_monthly is greater than max_monthly_payment
Print "DENIED: Monthly payment exceeds 36% DTI limit"
Print "Maximum loan at this income: $" joined with (max_monthly_payment times 360)
Otherwise
Print "APPROVED: DTI ratio within limits"
Print "Monthly payment: $" joined with requested_monthly
Require checks a condition and provides a domain-specific error message when it fails. Useful for business rule validation that needs to explain why.
Ask "Project capacity (MW)?" as capacity_mw
Ask "Placed in service date (year)?" as service_year
Ask "Has prevailing wage certification?" as has_pw
# Business rules for ITC eligibility
Require capacity_mw is greater than 0 or fail with "Capacity must be positive"
Require service_year is greater than 2022 or fail with "Project must be placed in service after 2022 for IRA credits"
# Prevailing wage requirement for projects over 1 MW
If capacity_mw is greater than 1
Require has_pw is "yes" or fail with "Projects over 1 MW require prevailing wage certification for full credit"
# Calculate credit rate
If capacity_mw is less than or equal to 1
credit_rate equals 0.30
Otherwise if has_pw is "yes"
credit_rate equals 0.30
Otherwise
credit_rate equals 0.06
basis equals capacity_mw times 1200000
credit equals basis times credit_rate
Print "ITC credit amount: $" joined with credit
Try and Otherwise let you attempt an operation and gracefully handle failure. The program continues running with a fallback value or action.
Ask "File path?" as file_path
# Try to read the file; fall back gracefully if it does not exist
Try
data equals Read JSON from file_path
record_count equals count of records of data
Print "Loaded " joined with record_count joined with " records"
Otherwise
Print "Warning: Could not read " joined with file_path joined with ", using defaults"
data equals record with list of as records and 0 as total
# Try multiple sources with fallback chain
Try
config equals Read JSON from "/etc/app/config.json"
Otherwise
Try
config equals Read JSON from "./config.json"
Otherwise
config equals record with 8080 as port and "info" as log_level and "localhost" as host
Print "Running on port: " joined with port of config
Devlish treats JSON as a native data format. Read it into records and lists; write structured data back out.
# Read a JSON file into a variable
clients equals Read JSON from "/data/clients.json"
# Access nested data
For each client in clients
Print name of client joined with " (" joined with tier of client joined with ")"
# Build new data and export
active_clients equals filter clients where status of item is "active"
summary equals record with count of active_clients as active_count and count of clients as total_count
# Write JSON back to disk
Export summary to "/reports/client_summary.json"
# Write a list of records
Export active_clients to "/reports/active_clients.json"
Read CSV files as lists of records (one record per row, column headers become field names). Filter, transform, and export results.
# Read CSV: each row becomes a record with header-named fields
transactions equals Read CSV from "/data/transactions.csv"
Print "Total rows: " joined with count of transactions
# Filter to only completed transactions over $1000
large_completed equals filter transactions where status of item is "completed" and amount of item is greater than 1000
Print "Large completed: " joined with count of large_completed
# Calculate total revenue
revenue equals reduce large_completed from 0 using accumulator plus amount of item
Print "Revenue from large deals: $" joined with revenue
# Build a summary report and export as CSV
report_rows equals map large_completed using record with id of item as transaction_id and name of item as customer and amount of item as value
Export report_rows to "/reports/large_transactions.csv"
Extract text from PDF files for classification, search, or compliance checks.
# Extract all text from a PDF
content equals Read PDF text from "/inbox/contract_draft.pdf"
# Check for required clauses
has_indemnity equals content contains "indemnification"
has_termination equals content contains "termination for cause"
has_governing_law equals content contains "governing law"
Print "Indemnification clause: " joined with has_indemnity
Print "Termination clause: " joined with has_termination
Print "Governing law clause: " joined with has_governing_law
# Flag missing sections
missing equals list of
If has_indemnity is false
missing equals missing with "indemnification" appended
If has_termination is false
missing equals missing with "termination for cause" appended
If has_governing_law is false
missing equals missing with "governing law" appended
If count of missing is greater than 0
Print "WARNING: Missing required clauses: " joined with missing
Otherwise
Print "All required clauses present"
Read specific cells or ranges from Excel spreadsheets. Useful for extracting values from financial models and reports.
# Read specific cells from an XLSX file
project_name equals Read XLSX cell "B1" from "/models/solar_project.xlsx"
capacity_mw equals Read XLSX cell "B3" from "/models/solar_project.xlsx"
capex_per_watt equals Read XLSX cell "B4" from "/models/solar_project.xlsx"
annual_production equals Read XLSX cell "B7" from "/models/solar_project.xlsx"
Print "Project: " joined with project_name
Print "Capacity: " joined with capacity_mw joined with " MW"
# Calculate total CapEx
total_capex equals capacity_mw times 1000000 times capex_per_watt
Print "Total CapEx: $" joined with total_capex
# Validate model assumptions
capex_per_watt must be between 0.50 and 2.00
capacity_mw must be greater than 0
# Read a range for monthly production data
# (each cell individually for targeted extraction)
jan_prod equals Read XLSX cell "C10" from "/models/solar_project.xlsx"
feb_prod equals Read XLSX cell "C11" from "/models/solar_project.xlsx"
q1_total equals jan_prod plus feb_prod
Print "Q1 partial production: " joined with q1_total joined with " MWh"
Make HTTP GET requests and parse the JSON response into records you can work with.
# Permissions:
# HTTP requests to "api.census.gov"
Ask "Latitude?" as lat
Ask "Longitude?" as lng
# Build the URL and make the request
base_url equals "https://geocoding.geo.census.gov/geocoder/geographies/coordinates"
params equals record with lat as x and lng as y and "Public_AR_Current" as benchmark and "Current_Current" as vintage
Get the url at base_url with params as response
# Parse the result
tract equals tract of geographies of first of addressMatches of result of response
county equals county of geographies of first of addressMatches of result of response
Print "Census tract: " joined with tract
Print "County: " joined with county
Send data to an API endpoint. The payload is built as a record and sent as JSON.
# Permissions:
# HTTP requests to "api.example.com"
Ask "Customer email?" as email
Ask "Plan name?" as plan
Ask "Monthly amount?" as amount
# Build the subscription payload
payload equals record with email as customer_email and plan as plan_id and amount as monthly_rate and "active" as status
# POST to the API
Post to "https://api.example.com/v1/subscriptions" with payload as result
# Check the response
subscription_id equals id of result
Print "Created subscription: " joined with subscription_id
Print "Status: " joined with status of result
Wrap API calls in Try blocks to handle network failures, rate limits, and unexpected responses.
# Permissions:
# HTTP requests to "api.weather.gov"
# HTTP requests to "api.backup-weather.com"
Ask "City?" as city
# Try the primary API; fall back to secondary
Try
Get the url at "https://api.weather.gov/points/" joined with city as weather_data
temperature equals temperature of properties of weather_data
forecast equals shortForecast of properties of weather_data
Print city joined with ": " joined with temperature joined with "F, " joined with forecast
Otherwise
Try
Get the url at "https://api.backup-weather.com/v1/current?city=" joined with city as backup_data
temperature equals temp of backup_data
Print city joined with ": " joined with temperature joined with "F (from backup source)"
Otherwise
Print "ERROR: Both weather APIs are unavailable"
Fail with record with "api_unavailable" as code and "Could not reach any weather data source" as message
A minimal tool that receives JSON input, does a calculation, and returns a structured response to the calling LLM.
# Tool: calculate_discount
# Input: {"customer_tier": "enterprise", "deal_size": 500000}
Ask "Customer tier?" as customer_tier
Ask "Deal size?" as deal_size
# Determine discount rate by tier
If customer_tier is "enterprise"
rate equals 0.15
Otherwise if customer_tier is "premium"
rate equals 0.10
Otherwise
rate equals 0.05
discount_amount equals deal_size times rate
final_price equals deal_size minus discount_amount
Respond with record with discount_amount as discount and final_price as total and rate as rate_applied and customer_tier as tier
When input is invalid or the operation cannot complete, return a structured error the LLM can parse and correct.
# Tool: validate_tax_credit
# Input: {"credit_amount": 50000, "project_type": "solar", "year": 2025}
Ask "Credit amount?" as credit_amount
Ask "Project type?" as project_type
Ask "Tax year?" as year
# Validate inputs with structured errors
If credit_amount is less than or equal to 0
Fail with record with "invalid_amount" as code and "Credit amount must be positive" as message
valid_types equals list of "solar" and "wind" and "storage" and "geothermal"
If valid_types does not contain project_type
Fail with record with "invalid_type" as code and "Unknown project type" as message and valid_types as allowed_types
If year is less than 2023
Fail with record with "invalid_year" as code and "IRA credits require tax year 2023 or later" as message and 2023 as minimum_year
# All validations passed
max_credit equals credit_amount times 0.30
Respond with record with true as valid and max_credit as maximum_credit and project_type as type and year as tax_year
A Checkpoint pauses execution and returns the current state to the LLM or human reviewer. Execution resumes only after approval.
# Tool: process_large_payment
# Input: {"vendor": "Acme Inc", "amount": 150000, "invoice_id": "INV-2025-847"}
Ask "Vendor name?" as vendor
Ask "Payment amount?" as amount
Ask "Invoice ID?" as invoice_id
# Validate basics
Require amount is greater than 0 or fail with "Amount must be positive"
# Auto-approve small payments; checkpoint large ones
If amount is greater than 50000
review_context equals record with vendor as vendor_name and amount as payment_amount and invoice_id as reference and "Payment exceeds $50,000 auto-approval threshold" as reason
Checkpoint "Large payment requires approval before processing" saving review_context
# If we reach here, payment was approved (either auto or via checkpoint)
confirmation equals record with invoice_id as reference and amount as amount_processed and vendor as paid_to and "completed" as status
Print "Payment processed: " joined with invoice_id
Respond with confirmation
A complete tool file with permission declarations, input validation, API calls, and structured output. This is what a production MCP tool looks like.
# Permissions:
# HTTP requests to "geocoding.geo.census.gov"
# HTTP requests to "developer.nrel.gov"
# Read files from "/data/appendix/"
#
# Boundaries:
# No file writes
# No network access outside declared hosts
#
# Callers:
# Any MCP client
Ask "Latitude?" as latitude
Ask "Longitude?" as longitude
# Validate coordinate ranges
Require latitude is between -90 and 90 or fail with "Latitude must be between -90 and 90"
Require longitude is between -180 and 180 or fail with "Longitude must be between -180 and 180"
# Step 1: Reverse geocode to census tract
census_url equals "https://geocoding.geo.census.gov/geocoder/geographies/coordinates"
Try
Get the url at census_url with record with latitude as x and longitude as y as census_response
tract_id equals geoid of result of census_response
Otherwise
Fail with record with "geocoding_failed" as code and "Census Bureau API did not return a tract for these coordinates" as message
# Step 2: Check energy community status via DOE
Try
Get the url at "https://developer.nrel.gov/api/energy-communities/v1/check" with record with tract_id as tract as doe_response
Otherwise
Fail with record with "doe_api_failed" as code and "Could not reach DOE energy community database" as message
is_eligible equals eligible of doe_response
category equals category of doe_response
# Step 3: Cross-reference IRS appendix for coal closure communities
appendix_data equals Read JSON from "/data/appendix/coal_closures.json"
coal_match equals filter appendix_data where tract of item is tract_id
is_coal_closure equals count of coal_match is greater than 0
# Build final response
result equals record with is_eligible as eligible and category as community_type and tract_id as census_tract and is_coal_closure as coal_closure_match and latitude as lat and longitude as lng
If is_eligible
Respond with result
Otherwise
Fail with record with "not_eligible" as code and tract_id as census_tract and "Location is not in a designated energy community" as reason
Iterate over a list and perform actions on each item. Combine with conditions to process only matching elements.
projects equals list of (record with "Alpha" as name and 5.2 as capacity_mw and "solar" as type) and (record with "Beta" as name and 12.0 as capacity_mw and "wind" as type) and (record with "Gamma" as name and 0.8 as capacity_mw and "solar" as type) and (record with "Delta" as name and 25.0 as capacity_mw and "storage" as type)
total_solar_mw equals 0
large_projects equals list of
For each project in projects
Print "Reviewing: " joined with name of project joined with " (" joined with capacity_mw of project joined with " MW)"
# Accumulate solar capacity
If type of project is "solar"
total_solar_mw equals total_solar_mw plus capacity_mw of project
# Collect large projects
If capacity_mw of project is greater than 10
large_projects equals large_projects with project appended
Print "Total solar capacity: " joined with total_solar_mw joined with " MW"
Print "Large projects (over 10 MW): " joined with count of large_projects
Repeat an action until a condition is met. The While loop checks its condition before each iteration.
# Compound interest calculator: how many years to double?
principal equals 10000
rate equals 0.07
target equals principal times 2
current equals principal
years equals 0
While current is less than target
current equals current times (1 plus rate)
years equals years plus 1
Print "Year " joined with years joined with ": $" joined with current
Print "Investment doubles in " joined with years joined with " years at 7% annual return"
# Fibonacci sequence up to a limit
limit equals 1000
a equals 0
b equals 1
sequence equals list of 0 and 1
While b is less than limit
next equals a plus b
sequence equals sequence with next appended
a equals b
b equals next
Print "Fibonacci up to " joined with limit joined with ": " joined with sequence
Process multi-dimensional data by nesting loops. Inner loops can reference the outer loop's current item.
# Portfolio analysis: multiple investors, each with multiple holdings
investors equals list of (record with "Fund A" as name and (list of (record with "PROJ-1" as id and 2500000 as value) and (record with "PROJ-2" as id and 1800000 as value)) as holdings) and (record with "Fund B" as name and (list of (record with "PROJ-3" as id and 5000000 as value) and (record with "PROJ-1" as id and 3200000 as value) and (record with "PROJ-4" as id and 900000 as value)) as holdings)
grand_total equals 0
For each investor in investors
investor_total equals 0
Print "--- " joined with name of investor joined with " ---"
For each holding in holdings of investor
Print " " joined with id of holding joined with ": $" joined with value of holding
investor_total equals investor_total plus value of holding
Print " Subtotal: $" joined with investor_total
grand_total equals grand_total plus investor_total
Print "Grand total across all investors: $" joined with grand_total
Define reusable logic with Define method. Methods accept parameters and return values with Return.
# Define a method to calculate tax credit
Define method calculate_itc with capacity_mw and has_prevailing_wage and is_domestic_content
base_rate equals 0.06
If has_prevailing_wage is true
base_rate equals 0.30
bonus equals 0
If is_domestic_content is true
bonus equals 0.10
total_rate equals base_rate plus bonus
basis equals capacity_mw times 1200000
credit equals basis times total_rate
Return record with credit as amount and total_rate as effective_rate and basis as cost_basis
# Use the method
result equals calculate_itc with 5.0 and true and true
Print "ITC credit: $" joined with amount of result
Print "Effective rate: " joined with effective_rate of result
result_no_bonus equals calculate_itc with 5.0 and true and false
Print "Without domestic content: $" joined with amount of result_no_bonus
Methods can call other methods. This lets you decompose complex logic into small, readable steps.
# Method to check if a year is a leap year
Define method is_leap_year with year
If year modulo 400 is 0
Return true
If year modulo 100 is 0
Return false
If year modulo 4 is 0
Return true
Return false
# Method to get days in a month
Define method days_in_month with month and year
If month is 2
If is_leap_year with year
Return 29
Otherwise
Return 28
If (list of 4 and 6 and 9 and 11) contains month
Return 30
Return 31
# Method to calculate days between two dates in the same year
Define method days_remaining_in_year with month and day and year
remaining equals days_in_month with month and year
remaining equals remaining minus day
current_month equals month plus 1
While current_month is less than or equal to 12
remaining equals remaining plus (days_in_month with current_month and year)
current_month equals current_month plus 1
Return remaining
# Use the composed methods
days_left equals days_remaining_in_year with 7 and 18 and 2026
Print "Days remaining in 2026: " joined with days_left
leap_check equals is_leap_year with 2028
Print "2028 is a leap year: " joined with leap_check
Mark methods as private to prevent external callers from invoking them directly. They can only be called by other methods in the same file.
# Public method: the tool interface
Define method assess_risk with deal_size and credit_score and years_in_business
score equals calculate_risk_score with deal_size and credit_score and years_in_business
tier equals assign_tier with score
Return record with score as risk_score and tier as risk_tier and deal_size as amount
# Private: internal scoring logic not exposed to callers
Define private method calculate_risk_score with deal_size and credit_score and years_in_business
base_score equals credit_score divided by 10
If deal_size is greater than 1000000
base_score equals base_score minus 5
If years_in_business is greater than 10
base_score equals base_score plus 10
Return base_score
# Private: tier assignment logic
Define private method assign_tier with score
If score is greater than 80
Return "low_risk"
If score is greater than 60
Return "moderate_risk"
Return "high_risk"
# Only the public method is callable from outside
result equals assess_risk with 500000 and 720 and 8
Print "Risk tier: " joined with risk_tier of result
Print "Score: " joined with risk_score of result
Scans a directory for receipt files, classifies them by vendor, extracts amounts, and copies them into organized folders. A practical automation script.
# Permissions:
# Read files from "/inbox/receipts/"
# Write files to "/archive/receipts/"
# Scan inbox for PDF receipts
files equals list files in "/inbox/receipts/"
pdf_files equals filter files where item ends with ".pdf"
Print "Found " joined with count of pdf_files joined with " receipts to process"
processed equals 0
total_amount equals 0
categories equals record with 0 as travel and 0 as meals and 0 as software and 0 as other
For each file in pdf_files
# Extract text from each receipt
content equals Read PDF text from file
# Classify by keywords
If content contains "airline" or content contains "hotel" or content contains "Uber"
category equals "travel"
Otherwise if content contains "restaurant" or content contains "lunch" or content contains "dinner"
category equals "meals"
Otherwise if content contains "subscription" or content contains "license" or content contains "SaaS"
category equals "software"
Otherwise
category equals "other"
# Extract amount (simplified: look for dollar pattern)
amount equals extract number after "$" from content
# Update running totals
total_amount equals total_amount plus amount
old_val equals category of categories
categories equals categories with (old_val plus amount) as category updated
# Copy to categorized archive folder
destination equals "/archive/receipts/" joined with category joined with "/" joined with file
Copy file to destination
processed equals processed plus 1
Print " " joined with file joined with " -> " joined with category joined with " ($" joined with amount joined with ")"
Print "---"
Print "Processed: " joined with processed joined with " receipts"
Print "Total spend: $" joined with total_amount
Print "By category: " joined with categories
Respond with record with processed as files_processed and total_amount as total_spend and categories as breakdown
Reads an XLSX financial model, validates expected values against actuals, and checkpoints for human review if discrepancies exceed thresholds.
# Permissions:
# Read files from "/deals/active/"
#
# Callers:
# Any MCP client
Ask "Deal folder?" as deal_folder
Ask "Expected total?" as expected_total
base_path equals "/deals/active/" joined with deal_folder
# Read key cells from the financial model
model_path equals base_path joined with "/model.xlsx"
stated_total equals Read XLSX cell "F25" from model_path
capacity equals Read XLSX cell "B3" from model_path
price_per_watt equals Read XLSX cell "B4" from model_path
annual_production equals Read XLSX cell "B8" from model_path
# Verify internal consistency
calculated_total equals capacity times 1000000 times price_per_watt
variance equals stated_total minus calculated_total
variance_pct equals variance divided by stated_total times 100
Print "Stated total: $" joined with stated_total
Print "Calculated total: $" joined with calculated_total
Print "Variance: " joined with variance_pct joined with "%"
# Check against expected value
expected_variance equals stated_total minus expected_total
expected_variance_pct equals expected_variance divided by expected_total times 100
issues equals list of
If variance_pct is greater than 1 or variance_pct is less than -1
issues equals issues with "Internal model variance exceeds 1%" appended
If expected_variance_pct is greater than 5 or expected_variance_pct is less than -5
issues equals issues with "Stated total differs from expected by more than 5%" appended
If annual_production is less than or equal to 0
issues equals issues with "Annual production is zero or negative" appended
# Checkpoint if issues found
If count of issues is greater than 0
review_data equals record with deal_folder as deal and issues as problems_found and stated_total as model_total and expected_total as expected and variance_pct as internal_variance_pct
Checkpoint "Invoice verification found issues requiring review" saving review_data
# All checks passed (or reviewer approved)
Respond with record with true as verified and deal_folder as deal and stated_total as confirmed_total and count of issues as issues_found and issues as issue_details
A production-grade MCP tool that calls two federal APIs, cross-references a local IRS appendix file, and returns a structured eligibility determination. This is the kind of program Devlish was built for.
# Permissions:
# HTTP requests to "geocoding.geo.census.gov"
# HTTP requests to "developer.nrel.gov"
# Read files from "/data/irs-appendix/"
#
# Boundaries:
# No file writes
# No network access outside declared hosts
#
# Callers:
# Any MCP client
Ask "Latitude?" as latitude
Ask "Longitude?" as longitude
Ask "Project type?" as project_type
# Input validation
Require latitude is between -90 and 90 or fail with "Invalid latitude"
Require longitude is between -180 and 180 or fail with "Invalid longitude"
valid_types equals list of "solar" and "wind" and "storage" and "geothermal" and "biogas"
Require valid_types contains project_type or fail with "Invalid project type"
# Step 1: Reverse geocode coordinates to census tract
Try
census_params equals record with latitude as x and longitude as y and "Public_AR_Current" as benchmark
Get the url at "https://geocoding.geo.census.gov/geocoder/geographies/coordinates" with census_params as geo_result
tract_id equals geoid of tract of geographies of first of addressMatches of result of geo_result
state_fips equals state of geographies of first of addressMatches of result of geo_result
county_name equals county of geographies of first of addressMatches of result of geo_result
Otherwise
Fail with record with "geocoding_failed" as code and "Could not determine census tract for given coordinates" as message and latitude as lat and longitude as lng
Print "Census tract: " joined with tract_id
Print "County: " joined with county_name
# Step 2: Check DOE energy community database
Try
doe_params equals record with tract_id as tract and project_type as technology
Get the url at "https://developer.nrel.gov/api/energy-communities/v1/check" with doe_params as doe_result
ec_eligible equals eligible of doe_result
ec_category equals category of doe_result
ec_basis equals basis of doe_result
Otherwise
Fail with record with "doe_unavailable" as code and "DOE energy community API is not responding" as message
# Step 3: Cross-reference IRS Appendix A (coal closure communities)
appendix_a equals Read JSON from "/data/irs-appendix/appendix_a_coal_closures.json"
coal_matches equals filter appendix_a where fips_tract of item is tract_id
is_coal_closure equals count of coal_matches is greater than 0
# Step 4: Check brownfield status from Appendix B
appendix_b equals Read JSON from "/data/irs-appendix/appendix_b_brownfields.json"
brownfield_matches equals filter appendix_b where census_tract of item is tract_id
is_brownfield equals count of brownfield_matches is greater than 0
# Step 5: Determine bonus credit eligibility
bonus_eligible equals ec_eligible or is_coal_closure or is_brownfield
bonus_amount equals 0
If bonus_eligible
bonus_amount equals 0.10
# Build comprehensive result
result equals record with bonus_eligible as eligible and ec_category as primary_category and tract_id as census_tract and county_name as county and state_fips as state and is_coal_closure as coal_closure and is_brownfield as brownfield and bonus_amount as adder_rate and project_type as technology
If bonus_eligible
Print "ELIGIBLE: " joined with ec_category
Respond with result
Otherwise
Fail with record with "not_eligible" as code and tract_id as census_tract and county_name as county and "Location does not qualify as an energy community under any category" as reason
Try these examples in the playground, or build your own.
Open the Playground Learn about MCP tools View source on GitHub