Get started with HERE Location Reasoning
Beta availability
HERE Location Reasoning is currently available to beta participants. For information about joining the beta, visit HERE Location Reasoning.
Connect to HERE Location Reasoning through the Model Context Protocol (MCP), authenticate with HERE OAuth 2.1 machine-to-machine (M2M) credentials, start a session, discover available tools, and call a tool.
Prerequisites
-
Install Python 3.10 or later.
-
Install the required libraries:
python3 -m pip install httpx "PyJWT[crypto]" -
Verify the installation:
python3 -c "import httpx, jwt; print(httpx.__version__, jwt.__version__)" -
Make sure the
opensslcommand is available to generate your signing key. It is preinstalled on most Linux and macOS systems. On Windows, use Git Bash (included with Git for Windows) or the Windows Subsystem for Linux (WSL).
Step 1: Create and register a signing key
HERE Location Reasoning uses the OAuth 2.1 private_key_jwt flow: you sign a short-lived JWT assertion with a private RSA key, and HERE verifies it against the matching public key you register. The private key never leaves your environment.
-
Generate a private RSA key. Run this in your terminal; it writes
private-key.pemto your current directory:openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out private-key.pemThen derive the matching public key, written as
public-key.pem:openssl pkey -in private-key.pem -pubout -out public-key.pem -
Print the public modulus (
n) and exponent (e) you will register with HERE. Run this in your terminal; it uses thecryptographypackage installed withPyJWT[crypto]:python3 -c " import base64 from cryptography.hazmat.primitives.serialization import load_pem_public_key nums = load_pem_public_key(open('public-key.pem','rb').read()).public_numbers() b64 = lambda v: base64.urlsafe_b64encode(v.to_bytes((v.bit_length()+7)//8,'big')).rstrip(b'=').decode() sep = '-' * 40 print(f'{sep}\nn = {b64(nums.n)}\n\ne = {b64(nums.e)}') " -
Refer to the steps listed in Using OAuth 2.1 in the HERE Platform for creating OAuth 2.1 credentials. When you register the JWK, paste the RSA public modulus (
n) and RSA public exponent (e) generated above.
After registering, you should have the following values:
| Value | Used as |
|---|---|
| APP ID | OAuth client_id |
| KEY ID | JWT header kid |
Step 2: Generate a HERE token
Sign a JWT client assertion with your private key and exchange it for a short-lived access token that you include as a bearer token in MCP requests.
import time
import uuid
import httpx
import jwt
TOKEN_URL = "https://account.api.here.com/oauth2/token"
RESOURCE = "https://hlr.here.ai/mcp"
CLIENT_ID = "<YOUR_APP_ID>" # APP ID from the HERE platform
KEY_ID = "<YOUR_KEY_ID>" # KEY ID of the registered JWK
PRIVATE_KEY_PATH = "private-key.pem" # path to your private key file
CLIENT_ASSERTION_TYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
def get_here_token() -> str:
"""Generate a HERE OAuth 2.1 token using a private_key_jwt client assertion."""
private_key = open(PRIVATE_KEY_PATH, "r").read()
now = int(time.time())
assertion = jwt.encode(
{
"iss": CLIENT_ID,
"sub": CLIENT_ID,
"aud": TOKEN_URL,
"iat": now,
"exp": now + 300,
"jti": str(uuid.uuid4()),
},
private_key,
algorithm="RS256",
headers={"kid": KEY_ID},
)
resp = httpx.post(
TOKEN_URL,
data={
"grant_type": "client_credentials",
"client_id": CLIENT_ID,
"client_assertion_type": CLIENT_ASSERTION_TYPE,
"client_assertion": assertion,
"resource": RESOURCE
},
headers={"Content-Type": "application/x-www-form-urlencoded"},
timeout=30,
)
resp.raise_for_status()
try:
return resp.json()["access_token"]
except KeyError as exc:
raise RuntimeError("The token response did not include an access token.") from exc
token = get_here_token()
print("Access token obtained.")The code signs a five-minute JWT assertion with your private key and exchanges it for a short-lived access token.
Step 3: Initialize the MCP session
Send an initialize request to start an MCP session. The server returns its capabilities and an Mcp-Session-Id header. Include this header in later requests to maintain session context.
HERE_LOCATION_REASONING_URL = "https://hlr.here.ai/mcp"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {token}",
}
resp = httpx.post(HERE_LOCATION_REASONING_URL, json={
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {},
"clientInfo": {"name": "quickstart", "version": "1.0"},
},
}, headers=headers, timeout=30)
resp.raise_for_status()
session_id = resp.headers.get("mcp-session-id")
if not session_id:
raise RuntimeError("The initialize response did not include Mcp-Session-Id.")
headers["Mcp-Session-Id"] = session_id
print("Session established.")A successful request prints Session established.
Step 4: Send initialized notification
Notify the server that your client completed initialization and is ready to use MCP features:
resp = httpx.post(HERE_LOCATION_REASONING_URL, json={
"jsonrpc": "2.0",
"method": "notifications/initialized",
"params": {},
}, headers=headers, timeout=30)
resp.raise_for_status()This is a notification, so it has no id field. It signals that the handshake is complete.
Note
If you skip this notification, some MCP servers may reject later requests or behave unpredictably.
Step 5: Discover available tools
List the tools exposed by the HERE Location Reasoning MCP server. The tools/list response returns each tool's name, description, and schema, so your application can discover tools without hardcoding them.
resp = httpx.post(HERE_LOCATION_REASONING_URL, json={
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {},
}, headers=headers, timeout=30)
resp.raise_for_status()
tools = resp.json()["result"]["tools"]
print(f"Available tools: {[t['name'] for t in tools]}")This returns the full list of tools with their input and output schemas.
Step 6: Call a tool
Call a tool with the tools/call method. Include the tool name and its required arguments.
resp = httpx.post(HERE_LOCATION_REASONING_URL, json={
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "hlr___geocode",
"arguments": {"q": "Alexanderplatz, Berlin"},
},
}, headers=headers, timeout=30)
resp.raise_for_status()
result = resp.json()["result"]
print(result)This calls the hlr___geocode tool and returns structured coordinate and address data. The tool arguments are:
{
"name": "hlr___geocode",
"arguments": {
"q": "Alexanderplatz, Berlin"
}
}A successful call returns a result similar to the following:
{
"title": "Alexanderplatz",
"address": {
"label": "Alexanderplatz, 10178 Berlin, Germany",
"city": "Berlin",
"postalCode": "10178",
"countryName": "Germany",
"countryCode": "DEU"
},
"position": {
"lat": 52.52192,
"lng": 13.41321
}
}Each response value has its own field. For example, use position.lat and position.lng to place the result on a map, or use address.city and address.countryName to filter or store the result.
Troubleshooting
| Issue | Root cause | Solution |
|---|---|---|
invalid_client on token request | The client_id is not the APP ID, or the JWK was registered for another application. | Use the APP ID as client_id and confirm the application is active. |
| Signature or key error on token request | The JWT kid does not match the registered KEY ID, or private-key.pem is not the pair of the registered public key. | Set kid to the registered KEY ID and sign with the matching private key. |
| Session initialization fails | The bearer token is missing, expired, or invalid. | Generate a new token and retry the initialize request. |
| Later requests fail after initialization | The Mcp-Session-Id header is missing. | Include the session ID returned by the initialize response in subsequent requests. |
| The server returns an MCP error | The request is invalid or the tool is unavailable. | Review the error code and message, then verify the request against the schema returned by tools/list. |
| Tool call fails | The tool name or arguments do not match the tool schema. | Call tools/list and verify the tool name and required arguments. |
Next steps
- Connect and authenticate — Comprehensive reference for the auth flow, session management, and error handling.
- HERE Location Reasoning integration examples — Ready-to-run integrations using LangChain, Strands Agents, PydanticAI, and more.
- HERE Location Reasoning tools reference — Complete list of available location tools.
Updated 13 hours ago