Skip to main content
Glama
NaveedUrRehman787

Real MCP System

README.md
# Real MCP System (mcp-use + OpenAI + dynamic Web UI)

Prepared by Muhammad Khalil — 21 August 2026.

End-to-end university/demo deliverable:

1. **MCP Server** (`server.py`) — live tools over streamable-HTTP  
2. **OpenAI Agent** (`agent_core.py` / `agent.py`) — discovers tools and calls them  
3. **Web UI** (`web.py` + `static/`) — chat + tool result cards  

## Live demo

- **Web UI:** https://real-mcp-system.vercel.app  
- **GitHub (public):** https://github.com/NaveedUrRehman787/real-mcp-system  

## Tools

| Tool | Source |
|------|--------|
| `get_weather` | Live Open-Meteo geocoding + forecast |
| `convert_currency` | Live currency-api FX (USD/EUR/PKR/…) |
| `calculate` | Local safe math |
| `roll_dice` | Local random |

## Setup (local)

```bash
python3 -m venv .venv
source .venv/bin/activate
cp .env.example .env   # set OPENAI_API_KEY
pip install -r requirements.txt
```

> Pin `mcp>=1.28,<2` — mcp 2.x breaks mcp-use 1.7.0.

## Run locally (2 terminals)

```bash
# Terminal 1 — MCP server
python server.py
# MCP: http://127.0.0.1:8000/mcp
# Inspector: http://127.0.0.1:8000/inspector

# Terminal 2 — Web UI
python web.py
# Chat UI: http://127.0.0.1:3010
```

## CLI agent

```bash
python agent.py --list-tools
python agent.py "Live weather in Tokyo and convert 50 EUR to USD"
```

## Hosted demo (Vercel)

On Vercel the chat UI runs as a single FastAPI app. Because serverless cannot keep a companion MCP process, production uses the same tools **in-process** (`AGENT_BACKEND=direct`). Local two-process MCP mode is unchanged.

Set `OPENAI_API_KEY` in the Vercel project environment variables (already configured for this demo).

## Documentation

- Project documentation (PDF): `docs/Real_MCP_System_Documentation.pdf`
- Student learning guide (PDF): `docs/Student_Learning_Guide.pdf`

## Architecture

```text
Browser chat
  → FastAPI (/api/chat)
  → OpenAI (gpt-4o-mini)
  → tools via MCP (local) or in-process (Vercel)
  → live APIs / local tools
  → reply + dynamic widgets
```

## A note on "widgets" (this is not an MCP App)

The `widgets` key in the `/api/chat` response and `renderWidget()` in `static/index.html`
are this project's **own** rendering layer, not the MCP Apps / MCP-UI protocol extension.
The distinction matters if you plan to extend this project:

| MCP Apps (the spec) | This project |
|---|---|
| Tool declares `view: { name }` at registration | No view registration; the frontend switches on tool name |
| Handler returns `widget({ props, message })` | Handler returns a plain `dict` |
| View is a React component compiled to a bundled HTML resource | Card markup is a template literal in `static/index.html` |
| Host renders it in a sandboxed iframe over a `postMessage` bridge | Markup is injected into the parent page via `innerHTML` |
| Portable — renders in ChatGPT, Claude, any compatible host | Only renders in this repo's own UI |

MCP Apps is currently a **TypeScript** `mcp-use` feature (`mcp-use/server`, `mcp-use/react`,
`views/<name>/view.tsx`). The Python `mcp-use==1.7.0` pinned here exposes no `widget()`
helper, no `view=` argument on `@server.tool()`, and no view bundling — so real MCP Apps
support would mean porting the server to the TypeScript SDK, not a local change.

Because the cards render in the parent page rather than in the spec's sandboxed iframe,
this project does its own escaping: every value interpolated by `renderWidget()` goes
through `esc()`. Keep that up if you add a card.