A wrapper for the Google Travel Impact Model API, providing tools to calculate flight emissions.
Project description
Travel Impact Model MCP Server
A Model Context Protocol (MCP) server that wraps the Google Travel Impact Model API, providing tools to calculate flight emissions for typical flights, specific flights, and Scope 3 reporting.
What is this?
This MCP server allows AI assistants (Claude, Gemini, etc.) to calculate flight emissions using Google's Travel Impact Model API. Instead of manually calling the API, your AI assistant can automatically look up emissions data when helping with travel planning or sustainability reporting.
Use cases:
- Compare flight options by environmental impact
- Calculate emissions for corporate travel reporting
- Generate Scope 3 GHG emissions reports
- Make data-driven decisions about sustainable travel
Features
- 6 tools for calculating flight emissions
- Batch processing support for efficient multi-flight queries
- Scope 3 reporting compatible (WTW, TTW, WTT emissions)
- Streamable HTTP transport for multi-client support
Demo
Watch how to use this MCP server with Claude Code to:
- Calculate typical flight emissions between airports
- Compare specific flights for environmental impact
- Generate Scope 3 emissions reports from CSV data
Installation
Prerequisites
- Google Travel Impact Model API key
- Docker (recommended) or Python 3.12+
Option 1: Quick Start (Recommended)
Run directly using uvx (no installation required):
# Set your API key first
export TRAVEL_IMPACT_MODEL_API_KEY=your_api_key_here
# Run the MCP server
uvx mcp-tim-wrapper
Option 2: Docker Container
Run the server immediately using the pre-built image from GitHub Container Registry:
docker run -p 8080:8080 \
-e TRAVEL_IMPACT_MODEL_API_KEY=your_api_key_here \
ghcr.io/abahgat/timcp:latest
The server will be available at http://localhost:8080/mcp.
Option 3: Docker Compose (Clone & Run)
- Clone the repository:
git clone https://github.com/yourusername/timcp.git
cd timcp
- Create a
.envfile with your API key:
echo "TRAVEL_IMPACT_MODEL_API_KEY=your_api_key_here" > .env
Note: The
.envfile is in.gitignoreto prevent committing secrets.
- Start the server:
docker-compose up
The server is now running at http://localhost:8080/mcp.
Option 4: Local Development
- Clone the repository:
git clone https://github.com/yourusername/timcp.git
cd timcp
- Install with uv (recommended):
uv venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
uv pip install -e .
Or with pip:
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
pip install -e .
- Create a
.envfile with your API key:
echo "TRAVEL_IMPACT_MODEL_API_KEY=your_api_key_here" > .env
Then load it:
set -a; source .env; set +a
Note: The
.envfile is in.gitignoreto prevent committing secrets.
- Run the server (Stdio):
mcp-tim-wrapper
Or run the server (HTTP):
uvicorn mcp_tim_wrapper.main:app --host 127.0.0.1 --port 8080
The server is now running at http://localhost:8080/mcp.
Quick Start
Configuring MCP Clients
Claude Desktop
Add to your config file:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Using uvx (Recommended):
{
"mcpServers": {
"tim": {
"command": "uvx",
"args": [
"mcp-tim-wrapper"
],
"env": {
"TRAVEL_IMPACT_MODEL_API_KEY": "your_api_key_here"
}
}
}
}
Using Docker/HTTP:
{
"mcpServers": {
"tim": {
"url": "http://localhost:8080/mcp"
}
}
}
Claude Code
Using Stdio:
claude mcp add tim -- uvx mcp-tim-wrapper
Using HTTP:
claude mcp add --transport http tim http://localhost:8080/mcp
Gemini CLI
gemini mcp add --transport http --scope project tim http://localhost:8080/mcp
Use --scope user for global configuration instead of project-specific.
Other MCP Clients
Point your client to the MCP endpoint: http://localhost:8080/mcp
Available Tools
| Tool | Description | Use When |
|---|---|---|
tim_get_typical_flight_emissions |
Average emissions between two airports based on historical data | You want general estimates without specific flight details |
tim_get_specific_flight_emissions |
Emissions for a specific flight number on a future date | You're comparing actual flight options for booking |
tim_get_scope3_flight_emissions |
GHG emissions for Scope 3 reporting (past flights only) | You need WTW/TTW/WTT breakdowns for sustainability reports |
tim_get_typical_flight_emissions_batch |
Batch version for multiple airport pairs | Processing many routes at once |
tim_get_specific_flight_emissions_batch |
Batch version for multiple future flights | Comparing many flight options efficiently |
tim_get_scope3_flight_emissions_batch |
Batch version for multiple past flights | Generating quarterly/annual emissions reports |
Usage Examples
Get Typical Flight Emissions
Request emissions estimate for flights between two airports:
{
"tool": "tim_get_typical_flight_emissions",
"arguments": {
"origin": "BOS",
"destination": "LAX"
}
}
Response:
{
"typicalFlightEmissions": [
{
"market": {
"origin": "BOS",
"destination": "LAX"
},
"emissionsGramsPerPax": {
"economy": 150000,
"premiumEconomy": 225000,
"business": 435000,
"first": 600000
}
}
],
"modelVersion": {
"major": 1,
"minor": 9,
"patch": 0
}
}
Get Specific Flight Emissions
Request emissions for a specific flight (must be a future date):
{
"tool": "tim_get_specific_flight_emissions",
"arguments": {
"origin": "SFO",
"destination": "LHR",
"operating_carrier_code": "UA",
"flight_number": 901,
"departure_year": 2026,
"departure_month": 3,
"departure_day": 15
}
}
Response:
{
"flightEmissions": [
{
"flight": {
"origin": "SFO",
"destination": "LHR",
"operatingCarrierCode": "UA",
"flightNumber": 901,
"departureDate": {
"year": 2026,
"month": 3,
"day": 15
}
},
"emissionsGramsPerPax": {
"economy": 500000,
"premiumEconomy": 750000,
"business": 1450000,
"first": 2000000
}
}
],
"modelVersion": {
"major": 1,
"minor": 9,
"patch": 0
}
}
Get Scope 3 Flight Emissions
Request emissions for past travel (Scope 3 reporting). You must provide either origin/destination OR distance_km:
Using origin/destination:
{
"tool": "tim_get_scope3_flight_emissions",
"arguments": {
"departure_year": 2024,
"departure_month": 10,
"departure_day": 15,
"cabin_class": "ECONOMY",
"origin": "JFK",
"destination": "SFO"
}
}
Using distance:
{
"tool": "tim_get_scope3_flight_emissions",
"arguments": {
"departure_year": 2024,
"departure_month": 10,
"departure_day": 15,
"cabin_class": "BUSINESS",
"distance_km": "5000"
}
}
Response:
{
"flightEmissions": [
{
"flight": {
"departureDate": {
"year": 2024,
"month": 10,
"day": 15
},
"cabinClass": "ECONOMY",
"origin": "JFK",
"destination": "SFO"
},
"wtwEmissionsGramsPerPax": "123456",
"ttwEmissionsGramsPerPax": "100000",
"wttEmissionsGramsPerPax": "23456",
"source": "TIM_EMISSIONS"
}
],
"modelVersion": {
"major": 2,
"minor": 0,
"patch": 0
}
}
Batch Processing
For multiple queries, use batch endpoints for efficiency:
Request:
{
"tool": "tim_get_typical_flight_emissions_batch",
"arguments": {
"markets": [
{"origin": "JFK", "destination": "LAX"},
{"origin": "SFO", "destination": "LHR"},
{"origin": "ORD", "destination": "CDG"}
]
}
}
Response:
{
"typicalFlightEmissions": [
{
"market": {
"origin": "JFK",
"destination": "LAX"
},
"emissionsGramsPerPax": {
"economy": 180000,
"premiumEconomy": 270000,
"business": 522000,
"first": 720000
}
},
{
"market": {
"origin": "SFO",
"destination": "LHR"
},
"emissionsGramsPerPax": {
"economy": 550000,
"premiumEconomy": 825000,
"business": 1595000,
"first": 2200000
}
},
{
"market": {
"origin": "ORD",
"destination": "CDG"
},
"emissionsGramsPerPax": {
"economy": 480000,
"premiumEconomy": 720000,
"business": 1392000,
"first": 1920000
}
}
],
"modelVersion": {
"major": 1,
"minor": 9,
"patch": 0
}
}
Scope 3 Batch Example:
Process multiple past flights for sustainability reporting:
{
"tool": "tim_get_scope3_flight_emissions_batch",
"arguments": {
"flights": [
{
"departureDate": {"year": 2024, "month": 1, "day": 15},
"origin": "BOS",
"destination": "SFO",
"carrierCode": "B6",
"flightNumber": 333,
"cabinClass": "ECONOMY"
},
{
"departureDate": {"year": 2024, "month": 2, "day": 3},
"origin": "BOS",
"destination": "LAX",
"carrierCode": "DL",
"flightNumber": 318,
"cabinClass": "BUSINESS"
}
]
}
}
This returns WTW (well-to-wake), TTW (tank-to-wake), and WTT (well-to-tank) emissions for each flight, essential for accurate Scope 3 GHG reporting.
Error Handling
The server returns ToolError for various error conditions:
Invalid Airport Code
{
"error": "TIM API Error (400): Invalid IATA code: XXX"
}
Flight Not Found
{
"error": "TIM API Error (404): Flight UA999 not found for the specified date"
}
Invalid Cabin Class
Valid cabin classes for Scope 3: ECONOMY, PREMIUM_ECONOMY, BUSINESS, FIRST
{
"error": "TIM API Error (400): Invalid cabin class: INVALID"
}
Missing API Key
If TRAVEL_IMPACT_MODEL_API_KEY is not set, the server will fail to start:
ValueError: TRAVEL_IMPACT_MODEL_API_KEY environment variable not set.
Rate Limiting
The Google Travel Impact Model API may rate limit requests. Handle accordingly:
{
"error": "TIM API Error (429): Rate limit exceeded"
}
Security Considerations
API Key Storage
- Never commit API keys to version control
- Store the API key in environment variables
- For production, use a secrets manager (AWS Secrets Manager, HashiCorp Vault, etc.)
- The API key is passed as a URL query parameter to Google's API (Google's required pattern)
Network Security
- By default, the server binds to
0.0.0.0- restrict this in production - Use HTTPS in production (configure via reverse proxy like nginx)
- CORS is configured to allow localhost origins by default
- Set
ALLOWED_ORIGINSenvironment variable for production:export ALLOWED_ORIGINS="https://yourdomain.com"
Access Control
- This server does not implement authentication
- Deploy behind an API gateway or reverse proxy for access control
- Consider rate limiting at the infrastructure level
Testing
Install test dependencies and run tests:
uv pip install -e .[test]
pytest
Run with verbose output:
pytest -v
Development
Releasing
To create a new release:
- Ensure you are on the
mainbranch and have no uncommitted changes. - Run the release helper script:
./scripts/release.sh
- Follow the prompts to enter the new version number.
The script will:
- Update the version in
pyproject.toml - Create a git commit and tag
- Push to GitHub
- Trigger the CI/CD pipeline which builds the Docker image and publishes it to GitHub Container Registry (GHCR) and creates a GitHub Release.
Running Without Docker
uv venv
source .venv/bin/activate
uv pip install -e .
# Set API key (see Installation section for .env file method)
export TRAVEL_IMPACT_MODEL_API_KEY="your_api_key_here"
# Run the server
uvicorn mcp_tim_wrapper.main:app --host 127.0.0.1 --port 8080
Linting and Formatting
uv pip install -e .[dev]
ruff check .
black .
Contributing
Contributions are welcome! Here's how you can help:
- Report bugs - Open an issue describing the problem
- Suggest features - Share ideas for improvements
- Submit PRs - Fix bugs or add features
Development Setup
# Clone and install
git clone https://github.com/yourusername/timcp.git
cd timcp
uv venv
source .venv/bin/activate
uv pip install -e .[dev,test]
# Run tests
pytest
# Run linting
ruff check .
black --check .
# Format code
black .
Running Tests
# Run all tests
pytest
# Run with coverage
pytest --cov=mcp_tim_wrapper
# Run specific test file
pytest tests/test_tools.py -v
License
Apache License 2.0
Acknowledgments
- Built with the Model Context Protocol SDK
- Uses Google's Travel Impact Model API
- Powered by FastAPI and httpx
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_tim_wrapper-1.1.0.tar.gz.
File metadata
- Download URL: mcp_tim_wrapper-1.1.0.tar.gz
- Upload date:
- Size: 22.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
90da87fb1ccf51f7b3f5883d3228d3ceb04fd8a309f65603bac656cda4fd48b5
|
|
| MD5 |
a971efb2e80edb88698b6df66ba890b7
|
|
| BLAKE2b-256 |
064dc636e588abc4c886d4b84f4737df7fc49311d5194ff5c46610eab6dc156e
|
Provenance
The following attestation bundles were made for mcp_tim_wrapper-1.1.0.tar.gz:
Publisher:
release.yml on abahgat/timcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_tim_wrapper-1.1.0.tar.gz -
Subject digest:
90da87fb1ccf51f7b3f5883d3228d3ceb04fd8a309f65603bac656cda4fd48b5 - Sigstore transparency entry: 898156053
- Sigstore integration time:
-
Permalink:
abahgat/timcp@db0235d109f9e8ccf0d16f687fd9381a40b214c4 -
Branch / Tag:
refs/tags/v1.1.0 - Owner: https://github.com/abahgat
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@db0235d109f9e8ccf0d16f687fd9381a40b214c4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file mcp_tim_wrapper-1.1.0-py3-none-any.whl.
File metadata
- Download URL: mcp_tim_wrapper-1.1.0-py3-none-any.whl
- Upload date:
- Size: 16.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9723d5b22ee8b10f38ed98bc47df1a26a34e5cda1acf317e06cec9eaa1057f98
|
|
| MD5 |
af0acfbc46d3438f0b85fca5979a72ac
|
|
| BLAKE2b-256 |
2be269253354343b7d0dd5bbec922119bb23f50c048d090d4dbf2a3e86d64006
|
Provenance
The following attestation bundles were made for mcp_tim_wrapper-1.1.0-py3-none-any.whl:
Publisher:
release.yml on abahgat/timcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_tim_wrapper-1.1.0-py3-none-any.whl -
Subject digest:
9723d5b22ee8b10f38ed98bc47df1a26a34e5cda1acf317e06cec9eaa1057f98 - Sigstore transparency entry: 898156078
- Sigstore integration time:
-
Permalink:
abahgat/timcp@db0235d109f9e8ccf0d16f687fd9381a40b214c4 -
Branch / Tag:
refs/tags/v1.1.0 - Owner: https://github.com/abahgat
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@db0235d109f9e8ccf0d16f687fd9381a40b214c4 -
Trigger Event:
push
-
Statement type: