Skip to main content
Glama
sanjay1110

Ticket Queue MCP Server

by sanjay1110
README.md
# Ticket Queue MCP Server & Client

A production-style Model Context Protocol (MCP) solution built for the
"Build a Production MCP Server & Client" lab: a server that exposes an
internal support ticket queue as MCP tools, resources, and prompts, and a
client that discovers and invokes them, over Streamable HTTP with OAuth 2.1
authorization.

## What's here

```
server/           MCP server (FastMCP): tools, resources, prompts, OAuth AS+RS, error handling
  data_store.py   In-memory mock ticket DB + KB articles (stands in for a real ticketing system)
  auth.py         OAuth 2.1 Authorization Server configuration (scopes, DCR)
  app.py          The FastMCP server itself -- entry point

client/           MCP client
  oauth_flow.py   Scripted OAuth 2.1 + PKCE flow (headless-friendly demo client)
  client_demo.py  Connects, discovers, and invokes everything -- entry point

docs/
  ARCHITECTURE.md   Diagram + component/transport write-up
  CAPABILITIES.md   Full reference for every tool/resource/prompt
  SECURITY.md       Security design summary (Requirement #7)

demo/
  run_demo.sh     Starts the server, runs the client, captures output
  demo_log.txt    A captured successful run (discovery -> invocation -> elicitation -> errors)
```

## Quickstart

```bash
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

bash demo/run_demo.sh
```

This starts the server on `http://127.0.0.1:8000`, runs the client through
the full OAuth handshake, discovery, and invocation flow, and writes the
transcript to `demo/demo_log.txt`.

To run the pieces separately:

```bash
# terminal 1
python3 -m server.app

# terminal 2
python3 -m client.client_demo
```

## What the demo actually shows

`client/client_demo.py` runs, in order:

1. Two OAuth 2.1 + PKCE token acquisitions -- one client requesting only
   `tickets:read`, one requesting `tickets:read tickets:write`.
2. Full discovery: `tools/list`, `resources/list`,
   `resources/templates/list`, `prompts/list`.
3. A tool call (`search_tickets`, `get_ticket`), a resource read (a KB
   article, the queue summary), and a prompt fetch (`triage_ticket`).
4. A write action (`add_comment`).
5. The high-impact `close_ticket` action, once with the elicitation
   **confirmed** and once **declined**, showing both outcomes.
6. The read-only client attempting a write tool, demonstrating
   least-privilege scope enforcement.
7. Both required error-handling failure modes: an invalid ticket ID, and a
   simulated unreachable backing data source, both surfaced as clean,
   non-leaky messages.

See `demo/demo_log.txt` for the full captured transcript, and
`docs/SECURITY.md` for the reasoning behind each of these design choices.

## Requirements coverage

| Lab requirement | Where |
|---|---|
| 1. >=3 tools | 5 tools in `server/app.py` |
| 2. >=2 resources | 3 resources in `server/app.py` |
| 3. >=1 reusable prompt | 2 prompts in `server/app.py` |
| 4. Client discovers & invokes | `client/client_demo.py`, Steps 1-8 |
| 5. Transport choice + justification | `docs/ARCHITECTURE.md` |
| 6. Client-side safety feature | Elicitation on `close_ticket`, `client/client_demo.py` Steps 8-9 |
| 7. Security design summary | `docs/SECURITY.md` |
| 8. Realistic error handling | `server/app.py` + `docs/CAPABILITIES.md` "Error Handling"; demo Steps 11-12 |

## Built with

[Model Context Protocol](https://modelcontextprotocol.io) /
[FastMCP](https://gofastmcp.com) (Python).