Skip to content

Commit e01683a

Browse files
authored
Merge pull request #79 from agentic-community/pr-77
JWT Token Vending Service + React Frontend Migration + GitHub Icon
2 parents 68436f9 + fdf08d2 commit e01683a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+33994
-694
lines changed

.gitignore

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ celerybeat.pid
131131
*.sage.py
132132

133133
# Environments
134-
.env
134+
.env*
135+
135136
.env.user
136137
.env*
137138
.env.docker
@@ -197,3 +198,50 @@ agents/test_results/
197198
agents/.env.user
198199
ssl_data/
199200
agents/.env.agent
201+
202+
# Frontend / Node.js / React / TypeScript
203+
frontend/node_modules/
204+
frontend/build/
205+
frontend/dist/
206+
frontend/.env
207+
frontend/.env.local
208+
frontend/.env.development.local
209+
frontend/.env.test.local
210+
frontend/.env.production.local
211+
frontend/npm-debug.log*
212+
frontend/yarn-debug.log*
213+
frontend/yarn-error.log*
214+
frontend/.pnpm-debug.log*
215+
frontend/lerna-debug.log*
216+
frontend/.DS_Store
217+
frontend/.vscode/
218+
frontend/.idea/
219+
frontend/*.tsbuildinfo
220+
frontend/.nyc_output
221+
frontend/coverage/
222+
frontend/.cache/
223+
frontend/.parcel-cache/
224+
frontend/.next/
225+
frontend/out/
226+
frontend/.nuxt/
227+
frontend/.vuepress/dist
228+
frontend/.serverless/
229+
frontend/.fusebox/
230+
frontend/.dynamodb/
231+
frontend/.tern-port
232+
frontend/storybook-static/
233+
234+
# Node.js (global patterns)
235+
node_modules/
236+
*.log
237+
npm-debug.log*
238+
yarn-debug.log*
239+
yarn-error.log*
240+
.pnpm-debug.log*
241+
lerna-debug.log*
242+
.DS_Store
243+
*.tsbuildinfo
244+
.nyc_output
245+
coverage/
246+
.cache/
247+
.parcel-cache/

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ You can deploy the gateway and registry on Amazon EC2 or Amazon EKS for producti
5757

5858
## What's New
5959

60+
* **JWT Token Vending Service:** Generate personal access tokens for programmatic access to MCP servers through a user-friendly web interface. Features include scope validation, rate limiting, and secure HMAC-SHA256 token generation. Perfect for automation, scripting, and agent access. [Learn more →](docs/jwt-token-vending.md)
61+
* **Modern React Frontend:** Complete UI overhaul with React 18 + TypeScript, featuring responsive design, dark/light themes, real-time updates, and integrated token management interface.
6062
* **IdP Integration with Amazon Cognito:** Complete identity provider integration supporting both user identity and agent identity modes. See [detailed Cognito setup guide](docs/cognito.md) for configuration instructions.
6163
* **Fine-Grained Access Control (FGAC) for MCP servers and tools:** Granular permissions system allowing precise control over which agents can access specific servers and tools. See [detailed FGAC documentation](docs/scopes.md) for scope configuration and access control setup.
6264
* **Integration with [Strands Agents](https://github.com/strands-agents/sdk-python):** Enhanced agent capabilities with the Strands SDK
@@ -200,6 +202,12 @@ These authentication patterns are discussed in detail in [`docs/auth.md`](docs/a
200202

201203
* **MCP Tool Discovery:** Enables automatic tool discovery by AI Agents and Agent developers. Fetches and displays the list of tools (name, description, schema) based on natural language queries (e.g. _do I have tools to get stock information?_).
202204
* **Unified access to a governed list of MCP servers:** Access multiple MCP servers through a common MCP gateway, enabling AI Agents to dynamically discover and execute MCP tools.
205+
* **JWT Token Vending Service:** Generate personal access tokens for programmatic access to MCP servers. Users can create scoped JWT tokens through the web interface for automation, scripting, and agent access. Features include rate limiting, scope validation, and secure token generation. See [detailed documentation →](docs/jwt-token-vending.md)
206+
* **Modern React Frontend:** Built with React 18 + TypeScript, featuring:
207+
* **Responsive Design:** Modern UI with Tailwind CSS and dark/light theme support
208+
* **Real-time Updates:** WebSocket integration for live status updates
209+
* **Enhanced UX:** Compact server cards, improved navigation, and accessibility features
210+
* **Token Management:** Integrated JWT token generation interface
203211
* **Service Registration:** Register MCP services via JSON files or the web UI/API.
204212
* **Web UI:** Manage services, view status, and monitor health through a web interface.
205213
* **Authentication:** Secure login system for the web UI and API access.
@@ -219,6 +227,9 @@ These authentication patterns are discussed in detail in [`docs/auth.md`](docs/a
219227

220228
## Prerequisites
221229

230+
* **Node.js 16+**: Required for building the React frontend. Install from [nodejs.org](https://nodejs.org/)
231+
* **npm**: Package manager for frontend dependencies (usually comes with Node.js)
232+
222233
* **Amazon EC2 Instance:** An Amazon EC2 machine (`ml.t3.2xlarge`) with a standard Ubuntu AMI for running this solution.
223234

224235
* **SSL Certificate Options:**
@@ -517,6 +528,7 @@ For comprehensive information about using the MCP Gateway & Registry, see our de
517528
- **[Frequently Asked Questions (FAQ)](docs/FAQ.md)** - Common questions and answers for developers and platform engineers
518529
- **[Authentication Guide](docs/auth.md)** - Detailed authentication and authorization patterns
519530
- **[Cognito Setup Guide](docs/cognito.md)** - Step-by-step Amazon Cognito configuration
531+
- **[JWT Token Vending Service](docs/jwt-token-vending.md)** - Generate personal access tokens for programmatic access to MCP servers
520532
- **[Fine-Grained Access Control](docs/scopes.md)** - Scope configuration and access control setup
521533
- **[Dynamic Tool Discovery](docs/dynamic-tool-discovery.md)** - AI agent autonomous tool discovery capabilities
522534

README_REACT_SETUP.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# MCP Gateway Registry - React Frontend
2+
3+
This project has been refactored to use a modern React frontend with TypeScript and Tailwind CSS.
4+
5+
## Architecture
6+
7+
- **Backend**: FastAPI (Python) - serves API endpoints and static React build
8+
- **Frontend**: React + TypeScript + Tailwind CSS
9+
- **Deployment**: Docker with automatic frontend build
10+
11+
## Development
12+
13+
### Running with Docker (Production-like)
14+
```bash
15+
# Build and run the complete stack
16+
docker build -f docker/Dockerfile.registry -t mcp-gateway-registry .
17+
docker run -p 7860:7860 -e ADMIN_PASSWORD=your_secure_password mcp-gateway-registry
18+
```
19+
20+
### Local Development
21+
For faster development, you can run the frontend and backend separately:
22+
23+
#### Backend (FastAPI)
24+
```bash
25+
cd registry
26+
uvicorn main:app --host 0.0.0.0 --port 7860 --reload
27+
```
28+
29+
#### Frontend (React)
30+
```bash
31+
cd frontend
32+
npm install
33+
npm start # Runs on http://localhost:3000
34+
```
35+
36+
The React dev server will proxy API requests to the FastAPI backend on port 7860.
37+
38+
## Features
39+
40+
### Modern UI Components
41+
- ✅ User dropdown with "Generate Token" option
42+
- ✅ Clean sidebar with filters and statistics
43+
- ✅ Modern card-based server grid
44+
- ✅ Dark/light theme toggle
45+
- ✅ Responsive mobile design
46+
- ✅ Loading states and error handling
47+
48+
### Architecture Benefits
49+
- ✅ Component-based and maintainable code
50+
- ✅ TypeScript for type safety
51+
- ✅ Tailwind CSS for consistent styling
52+
- ✅ React Router for client-side navigation
53+
- ✅ Context providers for global state
54+
- ✅ Proper separation of concerns
55+
56+
## API Integration
57+
58+
The React frontend communicates with the FastAPI backend via REST APIs:
59+
60+
- `GET /api/auth/me` - Get current user info
61+
- `GET /api/servers` - Get server list
62+
- `POST /api/servers/{path}/toggle` - Toggle server enabled/disabled
63+
- `POST /api/auth/generate-token` - Generate JWT tokens
64+
- `GET /api/servers/stats` - Get server statistics
65+
66+
## File Structure
67+
68+
```
69+
frontend/
70+
├── src/
71+
│ ├── components/ # Reusable UI components
72+
│ ├── contexts/ # React contexts (Auth, Theme)
73+
│ ├── hooks/ # Custom React hooks
74+
│ ├── pages/ # Page components
75+
│ └── App.tsx # Main app component
76+
├── public/ # Static assets
77+
└── package.json # Dependencies and scripts
78+
```
79+
80+
## Docker Build Process
81+
82+
The Docker build process:
83+
1. Installs Node.js 20
84+
2. Builds the React frontend (`npm run build`)
85+
3. Sets up Python environment
86+
4. Configures FastAPI to serve the built React app
87+
5. Sets up Nginx reverse proxy
88+
89+
## Migration Notes
90+
91+
The old template-based UI has been completely replaced with:
92+
- Modern React components instead of 2700+ line HTML files
93+
- Component-based architecture instead of monolithic templates
94+
- TypeScript for better developer experience
95+
- Tailwind CSS for consistent, maintainable styling
96+
- Client-side routing instead of server-side redirects
97+
98+
This makes the codebase much more maintainable and provides a better user experience.

agents/agent.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,8 @@ def parse_arguments() -> argparse.Namespace:
241241
help='Use session cookie authentication instead of M2M')
242242
parser.add_argument('--session-cookie-file', type=str, default='~/.mcp/session_cookie',
243243
help='Path to session cookie file (default: ~/.mcp/session_cookie)')
244+
parser.add_argument('--jwt-token', type=str,
245+
help='Use a pre-generated JWT token instead of generating M2M token')
244246

245247
# Environment file configuration arguments
246248
parser.add_argument('--user-env-file', type=str, default=user_env_file,
@@ -271,6 +273,14 @@ def parse_arguments() -> argparse.Namespace:
271273
if not os.path.exists(cookie_path):
272274
parser.error(f"Session cookie file not found: {cookie_path}\n"
273275
f"Run 'python agents/cli_user_auth.py' to authenticate first")
276+
elif args.jwt_token:
277+
# For pre-generated JWT token, we only need the token and basic headers
278+
if not args.user_pool_id:
279+
args.user_pool_id = 'us-east-1_EXAMPLE' # Default fallback
280+
if not args.client_id:
281+
args.client_id = 'user-generated' # Default for user-generated tokens
282+
if not args.region:
283+
args.region = 'us-east-1' # Default region
274284
else:
275285
# For M2M auth, validate Cognito parameters
276286
missing_params = []
@@ -555,14 +565,24 @@ async def main():
555565
logger.info(f"Connecting to MCP server: {server_url}")
556566
logger.info(f"Using model: {args.model}")
557567
logger.info(f"Message: {args.message}")
558-
logger.info(f"Authentication method: {'Session Cookie' if args.use_session_cookie else 'M2M Token'}")
568+
if args.jwt_token:
569+
auth_display = 'Pre-generated JWT Token'
570+
elif args.use_session_cookie:
571+
auth_display = 'Session Cookie'
572+
else:
573+
auth_display = 'M2M Token'
574+
logger.info(f"Authentication method: {auth_display}")
559575

560576
# Initialize authentication variables
561577
access_token = None
562578
session_cookie = None
563579
auth_method = "session_cookie" if args.use_session_cookie else "m2m"
564580

565-
if args.use_session_cookie:
581+
if args.jwt_token:
582+
# Use pre-generated JWT token
583+
access_token = args.jwt_token
584+
logger.info("Using pre-generated JWT token")
585+
elif args.use_session_cookie:
566586
# Load session cookie from file
567587
try:
568588
cookie_path = os.path.expanduser(args.session_cookie_file)
@@ -610,6 +630,7 @@ async def main():
610630
'X-Region': args.region or 'us-east-1'
611631
}
612632
else:
633+
# For both M2M and pre-generated JWT tokens
613634
auth_headers = {
614635
'Authorization': f'Bearer {access_token}',
615636
'X-User-Pool-Id': args.user_pool_id,
@@ -671,6 +692,7 @@ async def main():
671692
session_cookie=session_cookie
672693
)
673694
else:
695+
# For both M2M and pre-generated JWT tokens
674696
system_prompt = system_prompt_template.format(
675697
current_utc_time=current_utc_time,
676698
mcp_registry_url=args.mcp_registry_url,
@@ -679,7 +701,7 @@ async def main():
679701
client_id=args.client_id,
680702
region=args.region,
681703
auth_method=auth_method,
682-
session_cookie='' # Not used for M2M auth
704+
session_cookie='' # Not used for JWT auth
683705
)
684706

685707
# Format the message with system message first

agents/cli_user_auth.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,15 @@
5959
USE_DIRECT_CALLBACK = os.environ.get('USE_DIRECT_CALLBACK', 'true').lower() == 'true'
6060

6161
if USE_DIRECT_CALLBACK:
62+
logger.info("Using direct callback")
6263
# Direct callback to local server (original behavior)
63-
COGNITO_REDIRECT_URI = "http://localhost:8080/callback"
64-
CALLBACK_PORT = 8080
64+
COGNITO_REDIRECT_URI = "http://localhost:9090/callback"
65+
CALLBACK_PORT = 9090
6566
CALLBACK_PATH = "/callback"
6667
else:
6768
# Use nginx proxy callback (for Docker environments)
6869
COGNITO_REDIRECT_URI = f"{REGISTRY_URL}/oauth2/callback/cognito"
69-
CALLBACK_PORT = 8081 # Different port to avoid conflicts
70+
CALLBACK_PORT = 8080 # Different port to avoid conflicts
7071
CALLBACK_PATH = "/auth_complete"
7172

7273
AWS_REGION = os.environ.get('AWS_REGION', 'us-east-1')

0 commit comments

Comments
 (0)