HERE Location Reasoning integration examples
Beta availability
HERE Location Reasoning is currently available to beta participants. For information about joining the beta, visit HERE Location Reasoning.
These examples show how you can connect an application or agent to HERE Location Reasoning, discover available tools, and make location-tool requests.
Before you begin
- Complete Connect to and authenticate with HERE Location Reasoning to create a HERE bearer token.
- Choose a Python or TypeScript example.
- Set the environment variables required by that example.
- Change to the matching example directory and install its dependencies by using the command shown with the example.
Set environment variables
Set the following environment variables to connect to HERE Location Reasoning. Agent examples also require AWS Bedrock credentials and a model ID.
| Variable | Required | Description |
|---|---|---|
HLR_SERVER_URL | Yes | https://hlr.here.ai/mcp |
HERE_JWT_TOKEN | Yes (tool calls) | HERE Bearer token |
AWS_ACCESS_KEY_ID | Yes (agent examples) | AWS credentials for Bedrock LLM access |
AWS_SECRET_ACCESS_KEY | Yes (agent examples) | AWS credentials for Bedrock LLM access |
AWS_DEFAULT_REGION | Yes (agent examples) | AWS region, e.g. us-east-1 |
BEDROCK_MODEL_ID | Yes (agent examples) | Bedrock model ID |
Authentication requires a HERE bearer token. See Connect to and authenticate with HERE Location Reasoning to create one.
The agent examples use AWS Bedrock. HERE Location Reasoning supports any large language model provider that supports tool calling.
Agent examples retrieve a server-provided usage policy and guardrail prompt, then add both to the agent system prompt. Keep this pattern when you adapt an example so that the agent receives the server guidance.
Python
Python MCP SDK (Direct)
Demonstrates how to discover available tools and resources, run a geocoding request, and access server-provided guidance without using an LLM.
mcp-sdk.py
"""Direct MCP server connection using the official Python SDK — no LLM, no framework."""
import asyncio
import os
from dotenv import load_dotenv
import httpx
from mcp import ClientSession
from mcp.client.streamable_http import streamable_http_client
load_dotenv()
def require_environment_variable(name: str) -> str:
value = os.getenv(name)
if not value:
raise RuntimeError(f"Set {name} before running this example.")
return value
SERVER_URL = require_environment_variable("HLR_SERVER_URL")
JWT_TOKEN = require_environment_variable("HERE_JWT_TOKEN")
async def main():
# Auth header with JWT Bearer token, required for tool calls
client = httpx.AsyncClient(headers={"Authorization": f"Bearer {JWT_TOKEN}"})
async with streamable_http_client(url=SERVER_URL, http_client=client) as (
read_stream,
write_stream,
_,
):
async with ClientSession(read_stream, write_stream) as session:
await session.initialize()
# Discover available tools
tools = await session.list_tools()
print(f"Available tools: {[tool.name for tool in tools.tools]}", "\n")
# Call a tool directly
geocode_result = await session.call_tool(
"hlr___geocode", {"q": "Alexanderplatz, Berlin"}
)
print(geocode_result.structuredContent, "\n")
# List resources
resources = await session.list_resources()
print(
f"Available resources: {[(resource.name, resource.uri) for resource in resources.resources]}",
"\n",
)
# Read guardrails resource
policy = await session.read_resource(
uri="guardrails://location-reasoning-usage-policy"
)
print(policy)
await client.aclose()
if __name__ == "__main__":
asyncio.run(main())
Use the MCP SDK directly when you need programmatic access to location tools without an agent framework, or when you want to explore available tools and resources.
cd examples/python
uv sync
uv run mcp-sdk.pyA successful run prints available tool names, the geocoding result for Alexanderplatz, available resources, and the usage-policy resource.
Python LangChain
Demonstrates how a LangChain agent uses HERE Location Reasoning tools to interpret a routing request, retrieve location data, calculate a route, and generate a natural-language response.
langchain-example.py
"""LangChain agent with MCP tools — full agentic loop with tool execution."""
import asyncio
import os
from textwrap import dedent
from dotenv import load_dotenv
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain_mcp_adapters.prompts import load_mcp_prompt
from langchain_mcp_adapters.resources import load_mcp_resources
from langchain_mcp_adapters.tools import load_mcp_tools
load_dotenv()
def require_environment_variable(name: str) -> str:
value = os.getenv(name)
if not value:
raise RuntimeError(f"Set {name} before running this example.")
return value
SERVER_URL = require_environment_variable("HLR_SERVER_URL")
JWT_TOKEN = require_environment_variable("HERE_JWT_TOKEN")
MODEL_ID = require_environment_variable("BEDROCK_MODEL_ID")
async def main():
client = MultiServerMCPClient(
{
"hlr": {
"transport": "http",
"url": SERVER_URL,
# Auth header with JWT Bearer token, required for tool calls
"headers": {"Authorization": f"Bearer {JWT_TOKEN}"},
}
}
)
async with client.session("hlr") as session:
tools = await load_mcp_tools(session)
blobs = await load_mcp_resources(
session, uris=["guardrails://location-reasoning-usage-policy"]
)
guardrail_instruction = await load_mcp_prompt(
session=session, name="hlr___secure_location_reasoning"
)
# Build system prompt with guardrails resource and prompt
sys_prompt_template = dedent(
"""
<about>
You are a precise and accurate assistant.
</about>
<instructions>
{instructions}
</instructions>
<usage_policy>
{policy}
</usage_policy>
"""
).strip()
sys_prompt = sys_prompt_template.format(
instructions=guardrail_instruction[0].content, policy=blobs[0].data
)
model = init_chat_model(
model=MODEL_ID,
model_provider="bedrock_converse",
)
agent = create_agent(model=model, tools=tools, system_prompt=sys_prompt)
# Invoke agent with your prompt
response = await agent.ainvoke(
{
"messages": [
{
"role": "user",
"content": "Plan a route from Paris to Berlin.",
}
]
}
)
print(response["messages"][-1].content)
if __name__ == "__main__":
asyncio.run(main())
Use this example when you build with LangChain and want to add HERE Location Reasoning capabilities to an existing agent through AWS Bedrock.
cd examples/python
uv sync
uv run langchain-example.pyA successful run prints the agent's response to the route request from Paris to Berlin.
Python Strands Agents
Runs the same routing scenario as the LangChain example. The agent determines which tools to call, executes them through MCP, and synthesizes a response.
strands-example.py
"""Strands Agents (AWS-native) with MCP tools — full agentic loop with tool execution."""
import asyncio
import os
from textwrap import dedent
from dotenv import load_dotenv
from mcp.client.streamable_http import streamablehttp_client
from strands import Agent
from strands.models.bedrock import BedrockModel
from strands.tools.mcp import MCPClient
load_dotenv()
def require_environment_variable(name: str) -> str:
value = os.getenv(name)
if not value:
raise RuntimeError(f"Set {name} before running this example.")
return value
SERVER_URL = require_environment_variable("HLR_SERVER_URL")
JWT_TOKEN = require_environment_variable("HERE_JWT_TOKEN")
MODEL_ID = require_environment_variable("BEDROCK_MODEL_ID")
hlr_client = MCPClient(
lambda: streamablehttp_client(
url=SERVER_URL,
# Auth header with JWT Bearer token, required for tool calls
headers={"Authorization": f"Bearer {JWT_TOKEN}"},
)
)
async def main():
with hlr_client:
tools = hlr_client.list_tools_sync()
blob = hlr_client.read_resource_sync(
uri="guardrails://location-reasoning-usage-policy"
)
guardrail_instruction = hlr_client.get_prompt_sync(
prompt_id="hlr___secure_location_reasoning", args={}
)
# Build system prompt with guardrails resource and prompt
sys_prompt_template = dedent(
"""
<about>
You are a precise and accurate assistant.
</about>
<instructions>
{instructions}
</instructions>
<usage_policy>
{policy}
</usage_policy>
"""
).strip()
sys_prompt = sys_prompt_template.format(
instructions=guardrail_instruction.messages[0].content.text,
policy=blob.contents[0].text,
)
# streaming=False because ConverseStream requires additional IAM permissions that may not be provisioned
model = BedrockModel(model_id=MODEL_ID, streaming=False)
agent = Agent(
model=model, tools=tools, system_prompt=sys_prompt, callback_handler=None
)
response = agent(prompt="Plan a route from Paris to Berlin.")
print(response)
agent.cleanup()
if __name__ == "__main__":
asyncio.run(main())
Use this example when you build AWS-native applications with the Strands Agents framework and AWS Bedrock.
cd examples/python
uv sync
uv run strands-example.pyA successful run prints the agent's response to the route request from Paris to Berlin.
Python PydanticAI
Demonstrates type-safe tool calling with PydanticAI by using HERE Location Reasoning tools to process a routing request and return a response.
pydantic_ai-example.py
"""PydanticAI agent with MCP tools — full agentic loop with tool execution."""
import asyncio
import os
from textwrap import dedent
from dotenv import load_dotenv
from fastmcp import Client
from fastmcp.client.auth import BearerAuth
from pydantic_ai import Agent
from pydantic_ai.mcp import MCPToolset
load_dotenv()
def require_environment_variable(name: str) -> str:
value = os.getenv(name)
if not value:
raise RuntimeError(f"Set {name} before running this example.")
return value
SERVER_URL = require_environment_variable("HLR_SERVER_URL")
JWT_TOKEN = require_environment_variable("HERE_JWT_TOKEN")
MODEL_ID = require_environment_variable("BEDROCK_MODEL_ID")
async def main():
hlr_client = Client(
SERVER_URL,
# Auth with JWT Bearer token, required for tool calls
auth=BearerAuth(JWT_TOKEN),
)
hlr_toolset = MCPToolset(hlr_client)
async with hlr_client:
guardrail_blob = await hlr_client.read_resource(
uri="guardrails://location-reasoning-usage-policy"
)
guardrail_instruction = await hlr_client.get_prompt(
name="hlr___secure_location_reasoning"
)
# Build system prompt with guardrails resource and prompt
sys_prompt_template = dedent(
"""
<about>
You are a precise and accurate assistant.
</about>
<instructions>
{instructions}
</instructions>
<usage_policy>
{policy}
</usage_policy>
"""
).strip()
sys_prompt = sys_prompt_template.format(
instructions=guardrail_instruction.messages[0].content.text,
policy=guardrail_blob[0].text,
)
agent = Agent(
f"bedrock:{MODEL_ID}",
toolsets=[hlr_toolset],
system_prompt=sys_prompt,
)
result = await agent.run("Plan a route from Paris to Berlin.")
print(result.output)
if __name__ == "__main__":
asyncio.run(main())
Use this example for type-safe agent interactions with HERE Location Reasoning through AWS Bedrock.
cd examples/python
uv sync
uv run pydantic_ai-example.pyA successful run prints the agent's response to the route request from Paris to Berlin.
TypeScript
TypeScript MCP SDK (Direct)
Demonstrates how to discover and invoke HERE Location Reasoning tools from a Node.js application and work with the returned structured data.
mcp-sdk.ts
/**
* Direct MCP SDK client example — no LLM, no agent framework.
*
* Shows:
* - Low-level MCP client setup with streamable HTTP transport
* - Auth header configuration
* - Listing available tools
* - Calling a tool directly (geocode)
*/
import 'dotenv/config'
import { Client } from '@modelcontextprotocol/sdk/client'
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp'
function requireEnvironmentVariable(name: string): string {
const value = process.env[name]
if (!value) {
throw new Error(`Set ${name} before running this example.`)
}
return value
}
const SERVER_URL = requireEnvironmentVariable('HLR_SERVER_URL')
const JWT_TOKEN = requireEnvironmentVariable('HERE_JWT_TOKEN')
async function main(): Promise<void> {
let transport: StreamableHTTPClientTransport | null = null
try {
const client = new Client(
{ name: 'hlr-client', version: '1.0.0' },
{ capabilities: {} }
)
// Client with JWT bearer token auth header
transport = new StreamableHTTPClientTransport(
new URL(SERVER_URL),
{
requestInit: {
headers: { 'Authorization': `Bearer ${JWT_TOKEN}` }
}
}
)
await client.connect(transport)
const tools = await client.listTools()
console.log('Available tools:', tools.tools.map(t => t.name))
// Call geocode tool directly
const geocodeResult = await client.callTool({
name: 'hlr___geocode',
arguments: { q: 'Alexanderplatz, Berlin' }
})
console.log('\nGeocode result:')
console.log(geocodeResult.content)
} finally {
if (transport) await transport.close()
}
}
await main()Use the MCP SDK directly for programmatic access to HERE Location Reasoning tools from Node.js without an agent framework.
cd examples/ts
npm install
npm run mcp-sdkA successful run prints available tool names and the geocoding result for Alexanderplatz.
TypeScript Strands Agents
Demonstrates how a TypeScript-based Strands agent uses HERE Location Reasoning tools to fulfill a routing request and generate a route description.
strands.ts
/**
* Strands Agent example — connect to HERE Location Reasoning MCP.
*
* Shows:
* - MCP client setup with auth headers
* - Loading server-provided resource (usage policy) and prompt (guardrails)
* - Composing both into the system prompt
* - Bedrock model configuration
* - Agent invocation with MCP tools
*/
import 'dotenv/config'
import { Agent, BedrockModel, McpClient } from '@strands-agents/sdk'
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp'
function requireEnvironmentVariable(name: string): string {
const value = process.env[name]
if (!value) {
throw new Error(`Set ${name} before running this example.`)
}
return value
}
const SERVER_URL = requireEnvironmentVariable('HLR_SERVER_URL')
const JWT_TOKEN = requireEnvironmentVariable('HERE_JWT_TOKEN')
const MODEL_ID = requireEnvironmentVariable('BEDROCK_MODEL_ID')
const client = new McpClient({
transport: new StreamableHTTPClientTransport(
new URL(SERVER_URL),
{
requestInit: {
headers: {
'Authorization': `Bearer ${JWT_TOKEN}`,
},
},
}
),
})
await client.connect()
// Load the server's usage policy (resource) and application instructions (prompt).
// These are server-provided guardrails instructions.
const guardrailPolicy = await client.client.readResource({
uri: 'guardrails://location-reasoning-usage-policy',
})
const guardrailPrompt = await client.client.getPrompt({
name: 'hlr___secure_location_reasoning',
})
// Extract text from the resource and prompt content
const policyText = guardrailPolicy.contents[0] && 'text' in guardrailPolicy.contents[0] ? guardrailPolicy.contents[0].text : ''
const instructionsContent = guardrailPrompt.messages[0] && 'content' in guardrailPrompt.messages[0] ? guardrailPrompt.messages[0].content : ''
const instructionsText = instructionsContent && 'text' in instructionsContent ? instructionsContent.text : ''
// Build system prompt with guardrails resource and prompt
const systemPrompt = `
<about>
You are a precise and accurate assistant.
</about>
<instructions>
${instructionsText}
</instructions>
<usage_policy>
${policyText}
</usage_policy>
`.trim()
const bedrockModel = new BedrockModel({
modelId: MODEL_ID,
stream: false,
})
const agent = new Agent({
model: bedrockModel,
tools: [client],
systemPrompt,
printer: false
})
try {
const result = await agent.invoke('Plan a route from Paris to Berlin.')
console.log(result.toString())
} finally {
await client.disconnect()
}Use this example for TypeScript and Node.js applications that use Strands Agents and AWS Bedrock.
cd examples/ts
npm install
npm run strandsA successful run prints the agent's response to the route request from Paris to Berlin.
Next steps
- HERE Location Reasoning tools reference — Complete list of available location tools with descriptions.
Updated last month