dhl-ops-tools
by az-cod
README.md
# DHL Ops Copilot - MCP + ADK Edition
A re-architected version of [DHL Ops Copilot](https://github.com/az-cod/DHL_OPS_COPILOT), migrating the original custom function-calling tool layer to the **Model Context Protocol (FastMCP)** and rebuilding multi-agent orchestration on Google's **Agent Development Kit (ADK)**.
---
## What Changed From The Original
| Component | Original Version | MCP + ADK Edition | Why It Matters |
|---|---|---|---|
| **Tool Layer** | Custom dict-based JSON schemas & manual dispatch function | Standardized Model Context Protocol (`FastMCP 4.0`) | Decouples tools from any single LLM or client; standard MCP clients (Claude Desktop, ADK, Cursor) can inspect & consume tools without custom code. |
| **Agent Orchestration** | Manual while-loop and chat completion message passing | Google ADK (`LlmAgent` + `SequentialAgent`) | Native pipeline orchestration with structured state passing and pipeline inspection. |
| **LLM Provider & Model** | Groq (`llama-3.3-70b-versatile`) | Google Gemini (`gemini-3.6-flash`) | Leverages Google AI Studio free-tier quotas and structured tool calling. |
| **Transport Protocol** | In-process Python imports | Dual-mode: Local `stdio` & Remote `streamable-http` | Runs locally via stdio with zero network overhead, and deploys to cloud hosting via Streamable HTTP. |
---
## What Stayed The Same (Core Provenance)
1. **Deterministic ID-Pattern Fallback**:
- `SHP-xxxx`: Normalizes numeric inputs (e.g. `2044` -> `SHP-2044`) and matches shipment tracking records with hub status and ETA.
- `SO-xxxxx`: Normalizes SAP order numbers (e.g. `88213` -> `SO-88213`) and reports sync status and errors (`MATERIAL_MASTER_NOT_FOUND`, `DUPLICATE_ORDER_REFERENCE`).
- `INCxxxx`: Normalizes ServiceNow ticket IDs (e.g. `43` -> `INC0043`) or performs substring matching across issue descriptions.
- Malformed/garbage IDs gracefully trigger deterministic fallback dictionaries without throwing unhandled exceptions.
2. **SQLite Audit Trail**:
- Every tool execution logs an immutable record to `mcp_server/audit.db` (`id`, `ts`, `tool`, `query`, `result_status`).
- Note on Render free tier: The free tier filesystem is ephemeral, meaning `audit.db` resets on container redeploy. For persistent enterprise audit logs, configure a managed SQLite/PostgreSQL mount.
3. **Investigator / Synthesis Hallucination-Constraint Pattern**:
- **Investigator Agent**: Prohibited from answering the user directly; strictly tasked with calling tools and outputting evidence into `{evidence}`.
- **Synthesizer Agent**: Strictly constrained to `{evidence}`, requiring inline citations and refusing ungrounded claims.
---
## MCP Tools Description and Details
The FastMCP server (`mcp_server/server.py`) standardizes operational data access across three core enterprise systems plus internal procedural runbooks.
### 1. Shipment Tracking Tool: `get_shipment_status`
Look up live shipment tracking details by tracking identifier.
- **Signature**: `get_shipment_status(tracking_id: str) -> Dict[str, Any]`
- **Input Parameters**:
- `tracking_id` (string, required): Tracking code formatted as `SHP-xxxx` (e.g. `SHP-2044`, `SHP-3311`) or numeric digits (e.g. `2044`).
- **Return Shape**:
```json
{
"shipment_id": "SHP-2044",
"found": true,
"status": "In transit",
"current_hub": "Frankfurt Hub",
"eta": "2026-09-13",
"note": "On schedule.",
"source": "simulated shipment tracking system"
}
```
- **Fallback Behavior**: Malformed IDs or missing records return `{"shipment_id": "...", "found": false, "status": "not_found", "fallback_applied": true}` without raising exceptions.
- **Audit Trace**: Logs tool name, tracking ID query, and status to `mcp_server/audit.db`.
---
### 2. SAP Order Backend Tool: `get_sap_order`
Retrieve enterprise sales order sync status and backend error codes from SAP.
- **Signature**: `get_sap_order(order_id: str) -> Dict[str, Any]`
- **Input Parameters**:
- `order_id` (string, required): SAP order code formatted as `SO-xxxxx` (e.g. `SO-88213`, `SO-90144`) or numeric digits (e.g. `88213`).
- **Return Shape**:
```json
{
"order_id": "SO-88213",
"found": true,
"status": "Sync failed",
"error_code": "MATERIAL_MASTER_NOT_FOUND",
"order_value_usd": 4210.00,
"note": "SKU replication pending.",
"source": "simulated SAP backend"
}
```
- **Fallback Behavior**: Malformed IDs return `{"order_id": "...", "found": false, "status": "not_found", "fallback_applied": true}`.
- **Audit Trace**: Logs tool name, order ID query, and status to `mcp_server/audit.db`.
---
### 3. ServiceNow Ticket Tool: `get_servicenow_ticket`
Look up IT support incident tickets by exact identifier or search by issue keyword.
- **Signature**: `get_servicenow_ticket(ticket_id: str) -> Dict[str, Any]`
- **Input Parameters**:
- `ticket_id` (string, required): Ticket identifier (e.g. `INC0043`, `43`) or search query (e.g. `VPN`, `sync`).
- **Return Shape (Exact Match)**:
```json
{
"ticket_id": "INC0043",
"found": true,
"priority": "P2",
"status": "In Progress",
"description": "SAP order sync failures reported by 6 regional support agents, multiple orders showing MATERIAL_MASTER_NOT_FOUND.",
"source": "simulated ServiceNow instance"
}
```
- **Return Shape (Keyword Match)**:
```json
{
"query": "VPN",
"found": true,
"status": "matches_found",
"matches": [
{
"ticket_id": "INC0091",
"priority": "P3",
"status": "Open",
"description": "Single user unable to connect to VPN, certificate appears expired."
}
],
"source": "simulated ServiceNow instance"
}
```
- **Audit Trace**: Logs tool name, ticket ID or query string, and status to `mcp_server/audit.db`.
---
### 4. Standard Operating Procedures Tool: `retrieve_sop`
Search internal knowledge base runbooks, escalation policies, and procedures.
- **Signature**: `retrieve_sop(query: str) -> Dict[str, Any]`
- **Input Parameters**:
- `query` (string, required): Natural language search terms (e.g. `VPN expired certificate`, `SAP sync error`, `customs hold`).
- **Return Shape**:
```json
{
"query": "VPN expired certificate",
"found": true,
"status": "found",
"results": [
{
"id": "SOP-VPN-01",
"title": "VPN Access Troubleshooting",
"text": "If user cannot connect to VPN: 1. Confirm AD account active. 2. Check VPN cert validity..."
}
],
"source": "internal knowledge base"
}
```
- **Audit Trace**: Logs tool name, search query, and status to `mcp_server/audit.db`.
---
## How To Use In The Frontend
### Option A: Google ADK Web UI (Built-In Browser Interface)
The primary frontend interface is powered by Google ADK Web, providing a full chat window with real-time tool execution tracking.
#### Step 1: Start the Web UI Server
```bash
adk web agent --port 8085
```
#### Step 2: Open In Browser
Navigate to:
```
http://127.0.0.1:8085
```
#### Step 3: Select Agent & Start Session
1. On the left navigation pane, select **`agent`** (or the loaded application).
2. Click **New Session** to open a fresh chat workspace.
#### Step 4: Interact With Operational Queries
Type natural-language requests into the chat input:
- **Single System Query**:
`What is the current status and location of shipment SHP-2044?`
The `investigator` agent automatically calls `get_shipment_status("SHP-2044")`, and the `synthesizer` outputs the grounded status with inline citation `[get_shipment_status]`.
- **Multi-System Correlation**:
`Check SAP order SO-88213 and ServiceNow ticket INC0043.`
The pipeline executes parallel lookups for both systems, detects the `MATERIAL_MASTER_NOT_FOUND` error, automatically retrieves runbook `SOP-SAPSYNC-04`, and presents a structured incident brief.
- **Keyword Search**:
`Are there any active tickets regarding VPN access issues?`
The pipeline calls `get_servicenow_ticket("VPN")` and returns matching open incidents.
- **Runbook Procedures**:
`What is our policy for shipments delayed on customs hold?`
The pipeline queries `retrieve_sop("customs hold")` and summarizes `SOP-CUSTOMSHOLD-06`.
- **Malformed ID Handling**:
`Look up shipment SHP-INVALID-999.`
The pipeline gracefully reports that no records were found without crashing.
#### Step 5: Inspect Evidence & Tool Traces
In the ADK Web UI:
- Click on the intermediate execution steps to view raw JSON outputs returned by FastMCP tools.
- Expand the `{evidence}` dictionary to inspect the exact payload passed from the `investigator` to the `synthesizer`.
---
### Option B: Claude Desktop / Cursor (Standard MCP Client)
Because the tool layer uses standard FastMCP, any MCP-compliant frontend can connect to `mcp_server/server.py`.
#### Stdio Connection (Local)
Add to `claude_desktop_config.json`:
```json
{
"mcpServers": {
"dhl-ops-tools": {
"command": "python",
"args": ["/absolute/path/to/dhl-ops-mcp/mcp_server/server.py"]
}
}
}
```
#### Streamable HTTP Connection (Remote / Render)
When hosted on Render:
```json
{
"mcpServers": {
"dhl-ops-tools": {
"url": "https://dhl-ops-mcp-server.onrender.com/mcp"
}
}
}
```
---
## Repository Structure
```
dhl-ops-mcp/
|-- mcp_server/
| |-- __init__.py
| |-- server.py
| |-- audit.py
| |-- fallback.py
| \-- audit.db
|-- agent/
| |-- __init__.py
| |-- agent.py
| |-- .env.example
| \-- .env
|-- tests/
| |-- __init__.py
| |-- test_mcp_server.py
| \-- test_e2e.py
|-- .env.example
|-- pyproject.toml
|-- requirements.txt
|-- render.yaml
\-- README.md
```
---
## Setup & Local Development
### 1. Installation
```bash
git clone https://github.com/az-cod/DHL_OPS_COPILOT.git dhl-ops-mcp
cd dhl-ops-mcp
git checkout mcp-adk-migration
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
```
### 2. Configure Environment
Create `agent/.env` (from `agent/.env.example`):
```ini
GOOGLE_API_KEY=your_gemini_api_key_from_ai_studio
GOOGLE_GENAI_USE_VERTEXAI=FALSE
ADK_DEFAULT_MODEL=gemini-3.6-flash
```
### 3. Test MCP Server in Isolation
Run the test suite or launch FastMCP inspector:
```bash
pytest tests/ -v
fastmcp dev mcp_server/server.py
```
### 4. Run ADK Agent Locally
Launch the ADK web chat interface:
```bash
adk web agent --port 8085
```
---
## Deployment (Render Free Tier)
Deploying as two independent microservices on Render:
1. **`dhl-ops-mcp-server`**:
- Runtime: Python
- Build command: `pip install -r requirements.txt`
- Start command: `python mcp_server/server.py`
- Env vars:
- `PORT`: `8080`
- `MCP_TRANSPORT`: `streamable-http`
2. **`dhl-ops-adk-agent`**:
- Runtime: Python
- Build command: `pip install -r requirements.txt`
- Start command: `adk web agent --host 0.0.0.0 --port 10000`
- Env vars:
- `GOOGLE_API_KEY`: *(Set securely in Render Dashboard)*
- `MCP_SERVER_URL`: `https://dhl-ops-mcp-server.onrender.com/mcp`
Both services are pre-configured in [`render.yaml`](render.yaml) for one-click deployment via Render Blueprints.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues