Skip to main content
Glama
groveale

approval-mcpapp

by groveale

Access Request & Approval Workflow — MCP App

An MCP (Model Context Protocol) server that implements a multi-stage employee access request and approval workflow. Employees request system access, and managers and IT admins review and approve or reject requests — all from within an MCP-compatible host like VS Code Copilot Chat.

MCP Node.js TypeScript


Features

  • Multi-stage approval pipeline — Requested → Manager Review → IT Review → Granted/Rejected

  • Interactive UI panels — Rich React-based forms and dashboards served as MCP app resources

  • 6 supported systems — GitHub, SAP, Production Database, Azure DevOps, Salesforce, Jira

  • Persistent storage — Azure Table Storage (Azurite emulator for local dev)


Related MCP server: hr-assist

Architecture

┌──────────────────────────────────────────────────┐
│  MCP Host (e.g. VS Code Copilot Chat)            │
│                                                  │
│  ┌─────────────┐ ┌──────────────┐                │
│  │ Request Form │ │ Approval     │                │
│  │   (React)    │ │ Panel (React)│                │
│  └──────┬───────┘ └──────┬───────┘                │
│         │                │                        │
│         └────────┬───────┘                        │
│                  │ callServerTool                  │
└──────────────────┼────────────────────────────────┘
                   ▼
         ┌─────────────────────────────────┐
         │     MCP Server (Express)        │
         │     POST /mcp                   │
         │                                 │
         │  Tools: submit-request          │
         │         submit-decision         │
         │         get-request             │
         └──────────────┬──────────────────┘
                        │
                        ▼
              ┌───────────────────┐
              │  Azure Table      │
              │  Storage          │
              │  (Azurite local)  │
              └───────────────────┘

Prerequisites

  • Node.js 22 or later

  • npm 10 or later


Getting Started

1. Install dependencies

npm install

2. Start the Azurite storage emulator

In a separate terminal:

npm run start:azurite

This starts the Azure Table Storage emulator on http://127.0.0.1:10002. Data is stored in the .azurite/ directory.

3. Seed sample data (optional)

npm run seed

Loads three sample requests (REQ-001 through REQ-003) from fixtures/ so you can explore the app immediately.

4. Build and run

npm start

The MCP server starts at http://localhost:3001/mcp.


Development

Start the dev server with hot reload for both UI and backend:

npm run dev

This runs concurrently:

  • UI watcher — Rebuilds HTML bundles on file changes in ui/ and src/

  • Server watcher — Restarts the MCP server on backend file changes


Available Scripts

Command

Description

npm start

Full build + start the server

npm run build

Type-check, build UI bundles, compile server TypeScript

npm run serve

Run the already-built server

npm run dev

Watch mode with hot reload

npm run start:azurite

Start Azurite Table Storage emulator

npm run seed

Seed sample data into Azurite


MCP Tools

Frontend Tools (return interactive UI)

request-access

Opens the access request form for employees.

Parameter

Type

Required

Description

employeeName

string

No

Pre-fill the employee name

employeeEmail

string

No

Pre-fill the employee email

Example prompt: "I need to request access to GitHub"

approve-access

Opens the approval panel for managers and IT admins to review pending requests.

Parameter

Type

Required

Description

requestId

string

No

View a specific request, or leave blank to see all pending

Example prompt: "Show me pending access requests to approve"

Backend Tools (called by UI widgets)

Tool

Parameters

Description

submit-request

employeeName, employeeEmail, system, role, justification

Creates a new access request

submit-decision

requestId, decision (approve/reject), reviewer, comment

Records an approval or rejection

get-request

requestId

Fetches a single request by ID


Workflow Stages

Each access request progresses through these stages:

┌───────────┐    ┌────────────────┐    ┌────────────┐    ┌─────────┐
│ Requested │───▶│ Manager Review │───▶│ IT Review  │───▶│ Granted │
└───────────┘    └───────┬────────┘    └─────┬──────┘    └─────────┘
                         │                   │
                         ▼                   ▼
                    ┌──────────┐        ┌──────────┐
                    │ Rejected │        │ Rejected │
                    └──────────┘        └──────────┘
  1. Requested — Employee submits the form

  2. Manager Review — Direct manager approves or rejects

  3. IT Review — IT admin performs final review

  4. Granted — Access is provisioned

  5. Rejected — Request denied (can happen at either review stage)


Supported Systems and Roles

System

Available Roles

GitHub

Read, Write, Admin

SAP

Finance Viewer, Finance Editor, Admin

Production Database

Read-Only, Read-Write, DBA

Azure DevOps

Reader, Contributor, Project Admin

Salesforce

Viewer, Editor, Admin

Jira

Viewer, Developer, Project Lead


Data Model

Access Request

{
  "id": "REQ-001",
  "employeeName": "Alice Johnson",
  "employeeEmail": "alice@contoso.com",
  "system": "GitHub",
  "role": "Write",
  "justification": "Need write access for the frontend repo",
  "status": "Manager Review",
  "createdAt": "2026-03-31T10:00:00.000Z",
  "updatedAt": "2026-03-31T10:00:00.000Z",
  "timeline": [
    {
      "stage": "Requested",
      "status": "completed",
      "actor": "Alice Johnson",
      "timestamp": "2026-03-31T10:00:00.000Z"
    },
    {
      "stage": "Manager Review",
      "status": "current",
      "timestamp": "2026-03-31T10:00:00.000Z"
    }
  ]
}

Environment Variables

Variable

Description

Default

PORT

HTTP server port

3001

AZURE_STORAGE_CONNECTION_STRING

Azure Table Storage connection string

Azurite local default

NODE_ENV

Set to development for watch mode


Project Structure

├── main.ts                  # Express app entry point, /mcp endpoint
├── server.ts                # MCP server definition, tool/resource registration
├── mock-data/
│   └── requests.ts          # Data access layer (Azure Table Storage)
├── src/
│   ├── global.css           # Shared styles
│   ├── request-form/
│   │   └── App.tsx          # Employee request form UI
│   └── approval-panel/
│       └── App.tsx          # Manager/admin approval panel UI
├── ui/
│   ├── request-form.html    # Entry HTML for request form
│   └── approval-panel.html  # Entry HTML for approval panel
├── fixtures/
│   ├── access-requests.json # Sample request data for seeding
│   └── counters.json        # Counter seed data
├── scripts/
│   └── seed-data.ts         # Seed script for loading fixtures
├── vite.config.ts           # Vite configuration
├── tsconfig.json            # TypeScript config (type-checking)
├── tsconfig.server.json     # TypeScript config (server compilation)
└── package.json

Tech Stack

Layer

Technology

MCP Framework

@modelcontextprotocol/sdk, @modelcontextprotocol/ext-apps

Server

Express 5, TypeScript

UI

React 19, Fluent UI React v9

Storage

Azure Table Storage (@azure/data-tables)

Local Emulator

Azurite

Build

Vite, vite-plugin-singlefile

Validation

Zod

Related MCP Connectors

Related MCP Servers