Skip to main content
Glama
nilansh-07

JouleOps MCP Server

by nilansh-07
README.md
# JouleOps @ NorthWind Manufacturing

> **Agentic AI Enterprise Assistant using SAP Joule, SAP HANA Cloud,
> Python FastAPI, and Model Context Protocol (MCP).**

JouleOps is a scenario-based enterprise assistant for NorthWind
Manufacturing. It provides a governed natural-language interface for
retrieving operational data from SAP HANA Cloud and performing
controlled business actions through Python FastAPI services and a custom
MCP server.

------------------------------------------------------------------------

## Table of Contents

-   [Project Overview](#project-overview)
-   [Problem Statement](#problem-statement)
-   [Key Features](#key-features)
-   [Architecture](#architecture)
-   [Technology Stack](#technology-stack)
-   [Project Structure](#project-structure)
-   [Business Capabilities](#business-capabilities)
-   [Database](#database)
-   [REST API](#rest-api)
-   [MCP Server](#mcp-server)
-   [Environment Configuration](#environment-configuration)
-   [Local Setup](#local-setup)
-   [Running the Project](#running-the-project)
-   [Testing](#testing)
-   [SAP BTP and Joule Integration](#sap-btp-and-joule-integration)
-   [Security and Guardrails](#security-and-guardrails)
-   [Demo Scenarios](#demo-scenarios)
-   [Troubleshooting](#troubleshooting)
-   [Reproducibility Checklist](#reproducibility-checklist)
-   [Future Improvements](#future-improvements)
-   [License](#license)

------------------------------------------------------------------------

## Project Overview

NorthWind Manufacturing stores its operational data in SAP HANA Cloud.
JouleOps provides a single agentic interface for common plant, sales,
and finance operations.

The intended end-to-end flow is:

``` text
User
  ↓
SAP Joule / Joule Studio Agent
  ↓
Joule Skill OR MCP Tool
  ↓
Python FastAPI / MCP Server
  ↓
SAP HANA Cloud
  ↓
JSON Result
  ↓
Joule Agent
  ↓
Grounded Response
```

The project combines REST-based Joule Skills with MCP-based tool
exposure so the same backend capabilities can be consumed through
governed integration paths.

------------------------------------------------------------------------

## Problem Statement

The project addresses common operational tasks at NorthWind
Manufacturing:

-   Check material stock and safety stock at a plant.
-   Retrieve open sales orders for a region and date range.
-   Review customer exposure and overdue invoices.
-   Summarize overdue invoices and support collection decisions.
-   Create maintenance tickets when operational action is required.

Instead of manually querying several systems, users can express these
requirements in natural language through SAP Joule.

------------------------------------------------------------------------

## Key Features

### Operational Data

-   Material details by material and plant.
-   Open sales orders by region and date range.
-   Customer summaries.
-   Overdue invoice summaries.

### Business Action

-   Create maintenance tickets.
-   Verify material/plant combinations before creating tickets.
-   Write audit records for business actions.

### MCP

-   Custom Python MCP server using FastMCP.
-   Streamable HTTP transport.
-   MCP tool discovery and execution through MCP Inspector.
-   Reuse of backend business logic.

### Guardrails

-   HANA credentials remain in the backend.
-   Pydantic validation.
-   Parameterized SQL.
-   Audit logging.
-   Role-aware write operations.
-   No guessing of missing required business parameters.

------------------------------------------------------------------------

## Architecture

``` text
                    ┌──────────────────────┐
                    │      User / Joule    │
                    └──────────┬───────────┘
                               │
                               ▼
                    ┌──────────────────────┐
                    │  SAP Joule Studio    │
                    │       Agent          │
                    └──────────┬───────────┘
                               │
                    ┌──────────┴───────────┐
                    │                      │
                    ▼                      ▼
             ┌──────────────┐      ┌──────────────┐
             │ Joule Skill  │      │ MCP Server   │
             │ REST Action  │      │  FastMCP     │
             └──────┬───────┘      └──────┬───────┘
                    │                     │
                    └──────────┬──────────┘
                               ▼
                    ┌──────────────────────┐
                    │ Python Backend       │
                    │ FastAPI + Services   │
                    └──────────┬───────────┘
                               │
                               ▼
                    ┌──────────────────────┐
                    │   SAP HANA Cloud     │
                    │      NORTHWIND       │
                    └──────────────────────┘
```

### Responsibilities

  Component            Responsibility
  -------------------- ----------------------------------------------
  SAP Joule            Natural-language interaction
  Joule Studio Agent   Intent routing, planning, and tool selection
  Joule Skills         REST-based actions
  MCP Server           MCP tool exposure
  FastAPI              Backend action/API layer
  Services             Business logic and HANA queries
  HANA Cloud           Data persistence
  AUDIT_LOG            Write-operation auditing

------------------------------------------------------------------------

## Technology Stack

  Technology                 Purpose
  -------------------------- ------------------------
  Python 3.11+               Backend and MCP
  FastAPI                    REST API
  Pydantic                   Validation and schemas
  Uvicorn                    ASGI server
  `hdbcli`                   SAP HANA connectivity
  SAP HANA Cloud             Database
  FastMCP / `mcp`            MCP server
  SAP Joule / Joule Studio   Agentic AI
  SAP Build                  SAP-native integration
  MCP Inspector              MCP testing
  Git / GitHub               Version control

------------------------------------------------------------------------

## Project Structure

``` text
jouleops/
│
├── app/
│   ├── api/
│   │   └── routes.py
│   │
│   ├── db/
│   │   └── db.py
│   │
│   ├── models/
│   │   └── models.py
│   │
│   ├── services/
│   │   ├── customers.py
│   │   ├── invoices.py
│   │   ├── materials.py
│   │   ├── sales_orders.py
│   │   └── tickets.py
│   │
│   └── main.py
│
├── mcp/
│   └── server.py
│
├── sql/
│   ├── 01_schema.sql
│   ├── 02_seed.sql
│   └── generate_seed.py
│
├── tests/
│
├── .env
├── .gitignore
├── requirements.txt
└── README.md
```

The application separates HTTP routing, database connectivity, business
services, data models, and MCP integration.

------------------------------------------------------------------------

## Business Capabilities

### 1. Material Details

``` text
GET /materials/{material_id}/{plant_code}
```

Example:

``` text
GET /materials/MAT-1023/PLT-PUN
```

Retrieves material information for a specific plant.

### 2. Open Sales Orders

``` text
GET /sales-orders/open
```

Required parameters:

``` text
region
date_from
date_to
```

The service retrieves open orders and groups the returned orders by
customer.

### 3. Customer Summary

``` text
GET /customers/{customer_id}/summary
```

Example:

``` text
GET /customers/C-501/summary
```

Combines customer and invoice information for customer exposure
analysis.

### 4. Overdue Invoice Summary

``` text
GET /customers/{customer_id}/overdue-invoices
```

Example:

``` text
GET /customers/C-501/overdue-invoices
```

Provides overdue invoice information used by the agent for collection
recommendations.

### 5. Create Maintenance Ticket

``` text
POST /tickets
```

The service:

1.  Validates the request.
2.  Verifies the material exists at the requested plant.
3.  Creates a ticket ID.
4.  Inserts the ticket into HANA.
5.  Inserts an audit record.
6.  Commits the transaction.
7.  Returns the created ticket.

------------------------------------------------------------------------

## Database

The application uses the `NORTHWIND` schema in SAP HANA Cloud.

### Tables

``` text
NORTHWIND.MATERIALS
NORTHWIND.SALES_ORDERS
NORTHWIND.CUSTOMERS
NORTHWIND.INVOICES
NORTHWIND.TICKETS
NORTHWIND.AUDIT_LOG
```

### MATERIALS

Stores material ID, description, category, unit price, stock quantity,
safety stock, and plant code.

### SALES_ORDERS

Stores order ID, customer ID, material ID, quantity, status, creation
date, and region.

### CUSTOMERS

Stores customer ID, name, region, credit limit, and outstanding amount.

### INVOICES

Stores invoice ID, customer ID, amount, due date, status, and days
overdue.

### TICKETS

Stores maintenance tickets created through JouleOps.

### AUDIT_LOG

Stores timestamp, user role, tool name, masked parameters, and outcome
for audited operations.

### Database Scripts

``` text
sql/01_schema.sql
```

Creates the database objects.

``` text
sql/02_seed.sql
```

Loads synthetic NorthWind data.

``` text
sql/generate_seed.py
```

Generates seed data when required.

------------------------------------------------------------------------

## REST API

Start the API from the project root:

``` powershell
uvicorn app.main:app --reload
```

Default local address:

``` text
http://127.0.0.1:8000
```

Swagger UI:

``` text
http://127.0.0.1:8000/docs
```

OpenAPI specification:

``` text
http://127.0.0.1:8000/openapi.json
```

The generated OpenAPI document can be used when registering the REST
actions in SAP Build.

------------------------------------------------------------------------

## MCP Server

The project exposes selected backend capabilities through a custom
FastMCP server.

Local MCP endpoint:

``` text
http://127.0.0.1:8001/mcp
```

Transport:

``` text
Streamable HTTP
```

The MCP server exposes tools for operations such as:

``` text
get_customer_summary_tool
get_material_details
get_open_sales_orders_tool
summarize_overdue_invoices
create_maintenance_ticket
```

The MCP tool signature must match the underlying business operation. For
example, open sales orders requires:

``` text
region
date_from
date_to
```

rather than a single `customer_id`.

------------------------------------------------------------------------

## Environment Configuration

Create a `.env` file in the project root:

``` env
HANA_HOST=your-hana-host
HANA_PORT=443
HANA_USER=your-hana-user
HANA_PASSWORD=your-hana-password
```

Do not commit `.env`.

Recommended `.gitignore` entries:

``` gitignore
.env
.venv/
__pycache__/
*.pyc
```

HANA credentials must remain server-side and must never be included in
Joule prompts, MCP descriptions, LLM context, or API responses.

------------------------------------------------------------------------

## Local Setup

### 1. Clone the repository

``` powershell
git clone <repository-url>
cd jouleops
```

### 2. Create a virtual environment

``` powershell
py -m venv .venv
```

Activate it:

``` powershell
.\.venv\Scripts\Activate.ps1
```

### 3. Install dependencies

``` powershell
pip install -r requirements.txt
```

### 4. Configure HANA

Create `.env` and provide the SAP HANA Cloud connection information.

### 5. Create the database

Execute:

``` text
sql/01_schema.sql
```

against the target HANA Cloud schema.

### 6. Load seed data

Execute:

``` text
sql/02_seed.sql
```

or generate the required data using:

``` text
sql/generate_seed.py
```

------------------------------------------------------------------------

## Running the Project

### FastAPI

``` powershell
uvicorn app.main:app --reload
```

Verify:

``` text
http://127.0.0.1:8000/docs
```

### MCP Server

Run the MCP server using the ASGI/application entry point defined in
`mcp/server.py`.

For an ASGI application exposed as `app`, the command is:

``` powershell
uvicorn mcp.server:app --host 127.0.0.1 --port 8001
```

The final command should match the object exported by the project's
`mcp/server.py`.

------------------------------------------------------------------------

## Testing

### REST API

Use Swagger UI:

``` text
http://127.0.0.1:8000/docs
```

Recommended checks:

``` text
GET  /materials/MAT-1023/PLT-PUN
GET  /customers/C-501/summary
GET  /customers/C-501/overdue-invoices
GET  /sales-orders/open
POST /tickets
```

For the ticket operation, verify both:

``` text
NORTHWIND.TICKETS
NORTHWIND.AUDIT_LOG
```

after a successful write.

### MCP Inspector

Use [MCP Inspector](https://github.com/modelcontextprotocol/inspector)
to inspect and execute the MCP server.

Configure:

``` text
Server ID: jouleops-mcp
Transport: Streamable HTTP
URL: http://127.0.0.1:8001/mcp
```

After connecting:

1.  Open **Tools**.
2.  Select a JouleOps tool.
3.  Enter all required parameters.
4.  Execute the tool.
5.  Verify the JSON response.
6.  Verify HANA data where appropriate.
7.  For write operations, verify `AUDIT_LOG`.

------------------------------------------------------------------------

## SAP BTP and Joule Integration

The intended enterprise flow is:

``` text
SAP Joule
   ↓
Joule Studio Agent
   ↓
BTP Destination
   ↓
FastAPI / MCP
   ↓
SAP HANA Cloud
```

### FastAPI Action Destination

The REST API is exposed through a BTP Destination for Joule Studio
actions.

The destination should contain:

``` text
sap-joule-studio-action = true
```

### MCP Destination

The MCP server is exposed through an HTTP destination configured for
Joule Studio MCP discovery.

The destination should contain:

``` text
sap-joule-studio-mcp-server = true
```

For local demonstrations, a tunnel such as ngrok can expose the local
service.

HANA itself should never be exposed directly to Joule.

------------------------------------------------------------------------

## Security and Guardrails

### No HANA Credentials to the LLM

Only FastAPI/MCP holds HANA credentials.

``` text
Joule
  ↓
Tool parameters
  ↓
FastAPI / MCP
  ↓
HANA credentials
  ↓
SAP HANA Cloud
```

### Parameterized SQL

Queries use parameter binding:

``` python
cursor.execute(
    """
    SELECT ...
    WHERE MATERIAL_ID = ?
      AND PLANT_CODE = ?
    """,
    (material_id, plant_code),
)
```

rather than string concatenation.

### Audit Logging

Write operations should record:

``` text
user role
tool name
masked parameters
outcome
timestamp
```

in `NORTHWIND.AUDIT_LOG`.

### Input Validation

FastAPI/Pydantic models validate structured inputs before business logic
executes.

### Role-Based Access

The intended roles are:

``` text
PLANT_SUPERVISOR
SALES_MANAGER
FINANCE
VIEWER
```

A `VIEWER` must not be allowed to create maintenance tickets.

### No Guessing

If a required parameter is missing, the agent should request the missing
information instead of guessing or sending null values to a write
operation.

------------------------------------------------------------------------

## Demo Scenarios

### Scenario 1 --- Stock Check + Auto Ticket

``` text
Is steel coil MAT-1023 below safety stock in Pune?
If yes, raise a HIGH-priority ticket for the Mechanical team.
```

Expected flow:

``` text
get_material_details
        ↓
Compare stock with safety stock
        ↓
create_ticket
        ↓
AUDIT_LOG
        ↓
Confirmation
```

### Scenario 2 --- Open Sales Orders

``` text
Show me last week's open sales orders for the South region,
grouped by customer, with totals.
```

Expected tool:

``` text
get_open_sales_orders
```

Expected parameters:

``` text
region
date_from
date_to
```

### Scenario 3 --- Customer Exposure

``` text
Summarize C-501's overdue invoices and tell me what to do next.
```

Expected tools:

``` text
get_customer_summary
summarize_overdue_invoices
```

### Scenario 4 --- MCP Architecture Demonstration

``` text
Give me an inventory snapshot for the Chennai plant.
```

This scenario is intended to demonstrate an equivalent business
capability through an MCP tool.

### Scenario 5 --- Escalation / Missing Parameters

``` text
Create a ticket.
```

The agent should request the required information instead of guessing.

For a `VIEWER`, the write operation must be rejected.

------------------------------------------------------------------------

## Troubleshooting

### `500 Internal Server Error`

Check:

1.  `.env` values.
2.  HANA host and port.
3.  HANA Cloud network accessibility.
4.  Schema/table names.
5.  SQL parameters.
6.  Uvicorn logs.

### HANA Table Not Found

Verify the schema and tables:

``` sql
SELECT SCHEMA_NAME, TABLE_NAME
FROM SYS.TABLES
ORDER BY SCHEMA_NAME, TABLE_NAME;
```

The project expects the NorthWind tables under:

``` text
NORTHWIND
```

### MCP Inspector Cannot Connect

Verify:

``` text
MCP server is running
Port = 8001
Path = /mcp
Transport = Streamable HTTP
```

Expected endpoint:

``` text
http://127.0.0.1:8001/mcp
```

### MCP Tool Reports Missing Arguments

Check that the MCP wrapper signature matches the service function.

For example:

``` python
def get_open_sales_orders(
    region: str,
    date_from: date,
    date_to: date,
):
    ...
```

The MCP tool must expose all three parameters.

### SAP Build Action Returns `404 Not Found`

The SAP Build Action endpoint must exactly match the FastAPI route.

For example:

``` text
GET /customers/{customer_id}/overdue-invoices
```

must not be configured as:

``` text
/invoices/{customer_id}/overdue-summary
```

Use the current FastAPI OpenAPI specification:

``` text
http://127.0.0.1:8000/openapi.json
```

### Invalid OpenAPI File

Use the OpenAPI document generated by the current FastAPI application
rather than an outdated specification.

------------------------------------------------------------------------

## Reproducibility Checklist

### Backend

-   [ ] Python environment created.
-   [ ] Dependencies installed.
-   [ ] `.env` configured.
-   [ ] FastAPI starts successfully.
-   [ ] Swagger UI loads.
-   [ ] OpenAPI specification loads.
-   [ ] All core REST operations work.

### HANA

-   [ ] HANA Cloud instance available.
-   [ ] `NORTHWIND` schema exists.
-   [ ] Required tables exist.
-   [ ] Seed data loaded.
-   [ ] Ticket creation persists.
-   [ ] Audit records are created.

### MCP

-   [ ] MCP server starts.
-   [ ] Streamable HTTP endpoint is reachable.
-   [ ] MCP Inspector connects.
-   [ ] Tools are discovered.
-   [ ] All required parameters are exposed.
-   [ ] Read tools return valid results.
-   [ ] Write tools create audit records.

### Joule / SAP Build

-   [ ] JouleOps agent configured.
-   [ ] REST actions registered.
-   [ ] MCP server connected.
-   [ ] BTP Destinations configured.
-   [ ] Required destination properties configured.
-   [ ] Correct tools selected for representative prompts.
-   [ ] Missing parameters handled correctly.
-   [ ] RBAC behavior verified.
-   [ ] Source transparency verified.

### Demo

-   [ ] Stock + ticket scenario tested.
-   [ ] Open sales order scenario tested.
-   [ ] Customer/invoice scenario tested.
-   [ ] MCP scenario tested.
-   [ ] Escalation/RBAC scenario tested.
-   [ ] Tool traces captured.
-   [ ] HANA results verified.

------------------------------------------------------------------------

## Future Improvements

Potential extensions include:

-   Deploy FastAPI and MCP to SAP BTP Cloud Foundry or Kyma.
-   Add CI/CD using GitHub Actions.
-   Add comprehensive automated tests.
-   Build a Fiori/SAPUI5 audit dashboard.
-   Add HANA Vector Engine capabilities.
-   Add semantic search over historical tickets.
-   Add document grounding for credit/collection policies.
-   Add multi-agent orchestration.
-   Add bilingual interaction.
-   Add production-grade authentication and authorization.
-   Add structured observability and performance monitoring.

------------------------------------------------------------------------

## License

This project was developed as an educational/capstone implementation
demonstrating SAP Joule, SAP HANA Cloud, Python FastAPI, and Model
Context Protocol integration.

Unless a separate license is added to the repository, the project should
be treated as project-specific educational work.

------------------------------------------------------------------------

## Acknowledgements

Built using:

-   SAP Joule / Joule Studio
-   SAP Build
-   SAP HANA Cloud
-   Python
-   FastAPI
-   Pydantic
-   FastMCP / Model Context Protocol
-   MCP Inspector
-   Git / GitHub

Maintenance

ActivityMaintained
ResponsivenessNo issues