MCP tools

Numbers checked against the live data on

The MCP server at https://mcp.open-climate.ai/mcp exposes 15 tools: 12 for the model and 3 that only the in-chat widgets call. One, search_emission_factors, answers a question about one item. The rest take a file of purchase or activity lines, match each line to an emission factor and return the totals. To connect, see Connect over MCP.

A platform that mounts the server behind its own reaches a narrower set, without search_emission_factors: see Integrate our MCP.

How the tools chain#

For one to five items, call search_emission_factors once per item. For more items, a ledger or a file, use the chain:

step tool returns
1. Get the lines in upload_inline_rows (50 rows or fewer) or prepare_upload (a file) upload_id
2. Read the file's shape plan_emission_factor_mapping suggested sheet, header row, columns, file context
3. Decode jargon, optional create_lexicon domain, lexicon
4. Start the job map_procurement_items_to_emission_factors job_id
5. Wait check_emission_factor_mapping_progress status, stage, percent
6. Read the result get_emission_factor_mapping_result, then read_emission_factor_mapping_result_file download URL, report_stats, rows

Every later tool takes the upload_id or job_id verbatim. Never pass a file path or URL in their place. No tool returns where a file is stored: an upload is named by its upload_id and its filename, a result by its job_id and its download URL.

The shared envelope#

prepare_upload, plan_emission_factor_mapping, create_lexicon and get_emission_factor_mapping_result return these five fields beside their own.

field type meaning
next_step object or null The next call, when exactly one is unambiguous and required.
requires_followup object or null The client must compute a value and forward it on its next call, for example the file context.
plan_id string or null A handle to a server-side artefact the next tool consumes. Lives at most 1 hour.
warnings array of string Notes that do not block the next call.
needs_clarification array of string Questions to ask the user before you continue. When it is not empty, next_step is absent.

Each tool also returns a prose content[0].text that says what to do next, so a client can act on the text alone.

get_emission_factor_mcp_server_info#

Reports which build of the server you reached and which tools it registered. Read-only, no side effects. Use it to check a new connection.

Inputs. None.

Output.

field type meaning
name string Server name.
package_version string Version of the server package.
git_sha string or null Short commit at start, when known.
git_dirty boolean or null Whether the source tree had uncommitted changes at start.
started_at string UTC time the process started.
pid integer Process id.
transport string http or stdio.
tool_names array of string Every registered tool.

search_emission_factors#

Finds emission factors for one item, such as "a factor for a laptop", "hotel night in Spain" or "steel rebar per tonne". It reads the same ranking and licence rules as the factor explorer. Read-only, no side effects.

Call it once per item, for up to five items. For more, or for a ledger or a file, use the chain: it maps every line in one job.

Inputs.

input type required default meaning
query string yes The one item, in plain words, 1 to 200 characters.
alternative_phrasings array of string no [] Up to 3 other wordings of the same item: a synonym, the LCA or trade term, a translation. Their rankings are fused into one list. Never a different item.
location string or null no A country or region name to favour, such as France, up to 80 characters. It boosts, it never filters.
unit_family array of string or null no Keep only factors per this kind of quantity: monetary, mass, energy, count, area, volume, distance, length, freight, passenger, freight_container, duration, area_time, accommodation or length_time.
region_code array of string or null no Exact region codes: ISO 3166 alpha-2, GLOBAL, EUROPE or EU27. FR does not match an EU27 or GLOBAL factor, so add GLOBAL as a fallback.
library array of string or null no Library codes, such as desnz or ademe. Set it only when the user names a library.
boundary_preset array of string or null no Life-cycle scope: cradle_to_gate, cradle_to_shelf, full_lifecycle, direct_only, energy_full_chain, upstream_slice, production_slice, use_slice, eol_slice, end_of_life_waste, supply_chain_only or credit.
is_epd boolean or null no true for product-specific EPDs only, false for no EPDs.
year integer or null no Reference year, 1990 to 2100. Omitted, each factor's latest year.
limit integer no 10 Factors to return, 1 to 25.

Note. Settle the quantity first and pass it as unit_family. A laptop has factors per piece (count), per kg (mass) and per euro spent (monetary), and they are not interchangeable.

Output.

field type meaning
phrasings array of string The phrasings searched, query first, repeats removed.
total_matches integer or null Top-level factors the first phrasing matched in all.
results array The factors, best first, one row per top-level factor. Fields below.
hint string or null What to try next when the results are empty or thin.

Each entry in results:

field type meaning
slug string Stable factor id, the key of its page.
url string The factor's public page: method, source and parts.
activity string or null What the factor measures.
parent_activity string or null The top-level factor this row is a part of, when it is one.
library string Publishing library code.
region_code string or null Geography the factor is for.
kgco2e_per_unit number or null kg CO2e per one unit_code, AR6 GWP100 where derivable. Null when value_withheld_reason is set.
unit_code string or null The denominator unit.
unit_family string or null The denominator's kind.
system_boundary string or null Life-cycle stages covered.
reference_year integer or null Year the value describes.
license_tier string open, copyleft, restricted or prohibited.
value_withheld_reason string or null Why the value is not served, licence or pending. Null when it is served.
found_by array of integer or null Indexes into phrasings of the phrasings that ranked this factor.

prepare_upload#

Mints a short-lived upload URL for a .csv, .xls or .xlsx file. Use it when the model cannot see every row, or when there are more than 50. In a host that renders MCP Apps widgets, a drag-and-drop widget appears. Other clients get a curl one-liner in the text.

Inputs. None. The widget reads the file name when the user picks the file.

Output. The envelope, plus:

field type meaning
upload_id string The UUID every later tool takes.
upload_url string Where to POST the file as multipart/form-data, field file. Bound to you for 1 hour.
upload_token string Capability token the widget forwards to upload_inline_file.
widget_url string The upload widget. Headless clients ignore it.
expires_at string UTC time the URL and token stop working.
fallback_curl string The curl command for a headless client.
max_inline_bytes integer Largest file the widget sends inline. A bigger file opens widget_url in a new tab.

Wait until the upload has finished before you call plan_emission_factor_mapping.

upload_inline_rows#

Stores rows the model can already see as a CSV and registers them like a file. Use it for 50 rows or fewer, whether the user pasted them or attached a small file.

Inputs.

input type required meaning
rows array of object yes One object per row, {column: value}. Strict cap of 50 rows. Send every row; never sample.
header array of string yes Column names in source order.
filename string yes Name for display. The stored object is always <stem>.csv.

Output.

field type meaning
upload_id string The UUID every later tool takes.
filename string Stored name, <stem>.csv.
row_count integer Rows stored.
bytes_stored integer Size of the CSV.

plan_emission_factor_mapping#

Profiles an uploaded file and proposes how to read it: sheet, header row, trailing rows to drop, useful columns. One short model call also infers the file's currency, the buyer's country and a two-to-three sentence description. Read-only.

Inputs.

input type required default meaning
upload_id string yes From prepare_upload or upload_inline_rows.
skip_file_context boolean no false Skip the currency, country and description inference. Set it only when the user has stated them.

Output. The envelope, plus:

field type meaning
upload_id string Echoed.
filename string File name.
format string xlsx, xls or csv.
size_bytes integer File size.
sheets array Per sheet: header candidates, per-column profile, preview rows.
suggested object or null Best-guess shape, with a nested file_context. Null when no sheet looked like data.
confidence number Confidence in the header pick, 0 when there is none.

Watch out. The profiler assumes one header row and one table per sheet. Check suggested against the preview rows. A total row whose amount a block of the file's own rows adds up to is skipped as aggregate_row. A total the job cannot check, because it has no label or sits on a separate summary sheet, double counts: drop it.

On some deployments suggested.file_context is null and requires_followup is set. The client then infers the currency, country and description itself and passes them to the mapping tool.

create_lexicon#

Decodes a file's opaque vocabulary once, such as brand names, internal abbreviations and dense technical terms, so each row is matched with those terms already explained. Optional. Call it when the descriptions are full of codes; skip it for plain language.

Inputs.

input type required default meaning
upload_id string yes The upload to scan.
force_refresh boolean no false Rebuild instead of reusing a cached lexicon.

Output. The envelope, plus:

field type meaning
upload_id string Echoed.
domain string or null The file's domain. Null when the client builds the lexicon.
lexicon array Decoded entries. Empty when the client builds the lexicon, or when nothing was opaque.
lexicon_audit object or null How the lexicon was built.

On most deployments this tool returns requires_followup instead: the client reads the file with read_procurement_input_file, builds the lexicon, and forwards domain and lexicon in file_context.

read_procurement_input_file#

Returns the uploaded rows as objects with the original columns, so the client can scan every row. Read-only.

Inputs.

input type required default meaning
upload_id string yes The upload to read.
row_limit integer no 5000 Rows to return, 1 to 20000.

Output.

field type meaning
upload_id string Echoed.
filename string File name.
row_count integer Rows in the file, before truncation.
columns array of string Column names in file order.
rows array of object The rows. null is an empty cell.
truncated boolean True when only the first truncation_limit rows came back.
truncation_limit integer or null The cap applied.

map_procurement_items_to_emission_factors#

Matches every row of the upload to an emission factor. Asynchronous: it returns a job_id at once, and the result is not ready yet. Do not start a second job for the same file while one runs.

Inputs.

input type required meaning
upload_id string yes From prepare_upload or upload_inline_rows.
sheet_name string or null no Spreadsheets only. Pass suggested.sheet_name.
header_row integer or null no Header row, counted from 0. Pass suggested.header_row.
skip_trailing_rows integer or null no Rows to drop at the end.
useful_columns array of string or null no Columns to read. Never pass synthetic col_N names.
file_context object or null no File-level context, below.

file_context fields, all optional:

field type meaning
currency string ISO 4217 code, such as DKK.
country string Buyer country, ISO 3166-1 alpha-2, such as DK.
monetary_scale string thousands or millions when amounts are stated that way.
reporting_year integer Year the ledger's activity belongs to, 1990 to 2100. It is the fallback factor year for lines that state none. Set it only when known.
input_description string Two to three sentences on the company's sector and the file.
measure_pairs array Which column holds a measure's number and which its unit or currency. An empty array means no pair applies; omitting it lets the server nominate pairs.
supplier_column string Header of the supplier or vendor column, from suggested.file_context. Lines from one supplier are kept together.
family_column string Header of the product-family or category column, from suggested.file_context. Used to keep a family's lines together when no supplier column is named.
domain string From create_lexicon.
lexicon array From create_lexicon.

Output.

field type meaning
job_id string The job to poll.
status string Always queued.
submitted_at string UTC submission time.
warnings array of string Notes on how the job was queued, for example that it runs without a currency.
message string What to do next.

check_emission_factor_mapping_progress#

Reports how far a job has got. Read-only. Wait at least retry_after_seconds between calls.

Inputs. job_id (string, required).

Output.

field type meaning
job_id string Echoed.
status string queued, running, succeeded or failed.
stage string or null While running: parsing, then mapping, then auditing.
processed_rows integer Rows done.
total_rows integer Rows in the file.
percent number 100 × processed ÷ total.
queue_position integer or null Place in the queue while queued, counted from 0.
started_at string or null UTC start.
finished_at string or null UTC end.
last_progress_at string or null Time of the last progress report.
elapsed_running_seconds number or null Seconds since start.
seconds_since_last_progress number or null Seconds since the last progress report.
retry_after_seconds number 15 while the job runs, 0 once it has finished.
error_message string or null Why a job failed.

Note. During auditing, percent is 100 while the file-level check still runs. That is not a stuck job. In any other stage, a large seconds_since_last_progress is.

get_emission_factor_mapping_result#

Returns the download link and a summary report for a succeeded job. It errors on any other status. In a host that renders widgets, an emissions dashboard appears from the same data.

Inputs. job_id (string, required).

Output.

field type meaning
job_id string Echoed.
status string Always succeeded.
row_count integer Rows in the result.
download_url string Link to the result file.
elapsed_seconds number or null Processing time.
report_stats object or null Summary, below. Null only when the file could not be read.

It also returns the envelope.

report_stats carries total_rows, matched_rows, unmatched_rows, match_rate_pct, by_library (rows per library), emissions_by_library (kg CO2e per library), total_emissions_kgco2e, emissions_column, rows_with_emissions, rows_missing_emissions, skip_reason_counts, no_match_reason_counts, excluded_used_good_rows, aggregate_rows_skipped (total rows skipped so the purchases they sum are not counted twice; they are inside total_rows), confidence_bucket_counts, top_emitters (the ten largest rows) and emissions_by_ef (the 15 largest factors).

read_emission_factor_mapping_result_file#

Returns result rows as objects, so the client can filter, count and sum them. The row shape depends on the factors the job matched on and on your key.

A partner key, or a job that did not match on open_ef factors, gets the uploaded columns plus a fixed set of 106 pipeline columns. A column the file lacks is left out.

  • Nine describe the line: ef_library (the route that ran, not a library), confidence, no_match_reason, reformulation_item_nature, review_reason, basis_fallback, agent_reasoning, detected_quantities and quantity_conversion_detail.
  • Eighty are sixteen columns repeated for each of the five ranked candidates, named final_top_1_ to final_top_5_: ef_fingerprint, ef_keyword, ef_attribute, ef_unit, ef_data_source (the library the factor came from), ef_value_kgco2e_per_native_unit, quantity_in_ef_native_unit, magnitude_applied, total_emissions_kgco2e, total_emissions_skip_reason, score, freight_distance_basis, freight_reconciled_tonne_km, dataset_name, dataset_version and value_withheld_reason (licence or pending; a withheld value is null and left out of every sum, never 0). Rank 1 is the match the job chose; ranks 2 to 5 are the alternatives it weighed, which is what lets you re-rank a line without running the job again.
  • Two explain the library choice: final_top_1_library_choice_reason (why rank 1 beat a candidate from another library, region or year) and final_top_1_value_outlier (true when rank 1's value sits far from its activity group's centre).
  • Fifteen identify the product and place the line in a GHG scope: product_registry_supplier, product_registry_product, product_registry_product_id, classifier_variant, classifier_offering_kind, and ten ghg_* columns, such as ghg_scope_slots and ghg_scope_state.

When an open_ef job is read with a partner key, each row also carries final_top_1_open_ef_slug, final_top_1_open_ef_source_key, final_top_1_open_ef_release, final_top_1_open_ef_region_code and final_top_1_open_ef_boundary_preset.

An open_ef job read with any other key, OAuth sign-in included, returns the API's /v2/ row instead: row_index, the uploaded columns, flat final_top_1_ columns on the factor API's names (final_top_1_slug, final_top_1_factor_api_url, final_top_1_library, final_top_1_unit_code, final_top_1_value_co2e_normalized, final_top_1_quantity_in_factor_unit and more), the nine line columns above, and candidates, a list of up to five ranked factor objects.

Inputs.

input type required default meaning
job_id string yes A succeeded job.
row_limit integer no 500 Rows to return, 1 to 2000.

Output. job_id, filename, row_count (before truncation), columns, rows (null is empty or no match), truncated and truncation_limit, as in read_procurement_input_file.

list_emission_factor_mapping_jobs#

Lists your recent jobs, newest first. Use it to recover a lost job_id.

Inputs.

input type required default meaning
limit integer no 20 Jobs to return, 1 to 200.
status string or null no Only jobs in this status: queued, running, succeeded or failed.

Output. jobs, an array with job_id, status, created_at, started_at, finished_at, processed_rows, total_rows, filename and error_message per job. filename is the name of the uploaded file.

Widget-only tools#

These three are declared for the in-chat widgets. A host that honours the declaration keeps them away from the model, and a model should not call them.

upload_inline_file#

The upload widget sends a picked file's bytes through the host with this tool, so the bytes never enter the conversation.

input type required meaning
upload_id string yes From prepare_upload.
upload_token string yes From prepare_upload.
filename string yes The picked file's name, no path separators.
data_base64 string yes The bytes, standard base64.
content_type string or null no MIME type, echoed only.

Returns upload_id, filename, content_type and bytes_stored.

get_upload_status#

The widget calls this when a conversation reopens, to redraw a finished upload. Read-only.

Inputs: upload_id and upload_token, both required. Returns upload_id, is_resolved, and once the bytes have landed filename, content_type and bytes_stored (all null before).

download_emission_factor_mapping_result_file#

The dashboard's download button fetches the result file with this tool. A model shares download_url from get_emission_factor_mapping_result instead.

Input: job_id, required. Returns job_id, filename, mime_type and base64_content.

  • Connect over MCP
  • Call the API
  • API reference: the generated contract for the same /v2/ endpoints the tools call, with a console that sends a real request to the sandbox or production from your browser, using your own key.