You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: DEVELOPMENT.md
+58Lines changed: 58 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -129,6 +129,64 @@ Example in `config.toml`:
129
129
jwt_exposed_claims = ["user_id", "roles"]
130
130
```
131
131
132
+
### Roles and Scopes for Tool Authorization
133
+
134
+
This project implements a basic role-based access control (RBAC) system using OAuth scopes to restrict tool execution. Scopes are issued by the identity provider (e.g., Keycloak, Auth0, or other OAuth providers) and validated in tools at runtime.
135
+
136
+
#### Defining Your Own Scopes and Roles
137
+
138
+
You can define custom scopes and roles based on your application's needs. Scopes control access to specific tools or features, while roles group permissions.
139
+
140
+
**Example Scopes** (define in your OAuth provider's API/client configuration):
141
+
-`tool:read`: Access to read-only tools.
142
+
-`tool:write`: Access to tools that modify data.
143
+
-`tool:admin`: Administrative access to sensitive tools.
144
+
145
+
**Example Roles** (define in your OAuth provider's user/role management):
146
+
-`user`: Basic user role; grants `tool:read` scope.
147
+
-`editor`: Editor role; grants `tool:read` and `tool:write` scopes.
148
+
-`admin`: Admin role; grants all scopes.
149
+
150
+
Scopes and roles are included in JWT claims (`scope` and `roles`) via your OAuth provider's rules/actions/policies. Configure your provider to map roles to scopes and include them in tokens.
151
+
152
+
#### Checking Scopes in Tools
153
+
154
+
To restrict a tool based on scopes, add authorization checks inside the tool function. Use `get_jwt_payload()` from `mcp_app.context` to access claims.
155
+
156
+
Example for a tool requiring `tool:user` scope:
157
+
158
+
```python
159
+
from mcp_app.context import get_jwt_payload
160
+
161
+
defmy_tool(param: str) -> str:
162
+
"""My tool description. Requires tool:user scope.
163
+
164
+
Args:
165
+
param: Parameter description.
166
+
167
+
Returns:
168
+
Result description.
169
+
170
+
Raises:
171
+
PermissionError: If user lacks required scope.
172
+
"""
173
+
payload = get_jwt_payload()
174
+
if payload: # Only check in HTTP mode (with JWT)
175
+
scope = payload.get("scope", "")
176
+
scopes = scope.split() ifisinstance(scope, str) else scope or []
A comprehensive, production-ready MCP (Model Context Protocol) server template built with Python, featuring OAuth 2.0 authentication, JWT validation, and seamless deployment options for developers building AI-powered applications.
12
+
A comprehensive, production-ready MCP (Model Context Protocol) server template built with Python. This is a Python port of the original MCP Forge Go project, featuring OAuth 2.0 authentication, JWT validation, and seamless deployment options for developers building AI-powered applications.
13
13
14
14
## Key Features of MCP Forge Python
15
15
@@ -26,27 +26,43 @@ A comprehensive, production-ready MCP (Model Context Protocol) server template b
- Auth settings for OAuth flows (client credentials, redirect URIs)
56
+
- JWT claims exposure configuration
57
+
58
+
## Additional Endpoints
59
+
60
+
Beyond MCP protocol endpoints, the server provides:
61
+
62
+
-**GET /**: Server information
63
+
-**GET /health**: Health check endpoint
64
+
-**GET /login**: Initiates OAuth authorization code flow (redirects to Auth0/Keycloak)
65
+
-**GET /callback**: Handles OAuth callback and exchanges code for token
50
66
51
67
## Production-Ready Deployment
52
68
@@ -58,7 +74,7 @@ A comprehensive, production-ready MCP (Model Context Protocol) server template b
58
74
59
75
### External Dependencies
60
76
61
-
-**Python**: >= 3.10
77
+
-**Python**: >= 3.11
62
78
-**uv**: Dependency and virtual environment manager (install from [astral.sh/uv](https://astral.sh/uv))
63
79
-**just** (optional): Simplified command runner (install from [just.systems](https://just.systems/install.sh))
64
80
-**Docker** (optional): For image building
@@ -81,12 +97,25 @@ A comprehensive, production-ready MCP (Model Context Protocol) server template b
81
97
-`PyJWT`: JWT handling
82
98
-`requests`: Synchronous HTTP client
83
99
100
+
-**Production dependencies**:
101
+
-`fastapi`: ASGI web framework
102
+
-`uvicorn[standard]`: ASGI server with SSE support
103
+
-`pydantic`: Data validation
104
+
-`pydantic-settings`: Configuration from files
105
+
-`tomli`: TOML parser for Python < 3.11 (uses `tomllib` for Python 3.11+)
106
+
-`mcp[cli]`: MCP Python SDK
107
+
-`httpx`: Asynchronous HTTP client
108
+
-`PyJWT`: JWT handling
109
+
-`requests`: Synchronous HTTP client
110
+
-`cryptography`: Cryptographic operations
111
+
84
112
-**Development dependencies**:
85
113
-`ruff`: Linting and formatting
86
114
-`pyright`: Type checking
87
115
-`pytest`: Testing framework
88
116
-`pytest-asyncio`: Async support for pytest
89
117
-`coverage`: Code coverage
118
+
-`pytest-benchmark`: Performance benchmarking
90
119
91
120
## Installation & Setup
92
121
@@ -95,10 +124,13 @@ A comprehensive, production-ready MCP (Model Context Protocol) server template b
95
124
uv sync
96
125
97
126
# Install package (enables direct commands)
98
-
uv pip install .
127
+
uv pip install -e .
99
128
100
129
# Run HTTP server with SSE
101
130
uv run http
131
+
132
+
# Alternative: Run stdio server for local AI clients
133
+
uv run stdio
102
134
```
103
135
104
136
## Development Commands
@@ -107,24 +139,23 @@ uv run http
107
139
# Testing & Quality
108
140
just test# Run all tests
109
141
just cov # Run tests with coverage report
142
+
just bench # Run benchmarks
110
143
just lint # Lint and format code
111
144
just typing # Type checking
112
145
just check-all # Run all quality checks
113
146
114
147
# Lifecycle
115
148
just install # Install/update dependencies
149
+
just update # Update dependencies to latest versions
116
150
just clean # Remove all temporary files (.venv, caches, dist)
117
151
just clean-cache # Clean caches only (keep .venv)
118
152
just fresh # Clean + fresh install
119
153
120
154
# Running
121
155
just run # Run HTTP server
122
156
just run-stdio # Run stdio mode
123
-
124
-
# Run stdio server
125
-
126
-
uv run stdio
127
-
157
+
just dev-http # Run HTTP server with MCP Inspector
158
+
just dev-stdio # Run stdio server with MCP Inspector
128
159
```
129
160
130
161
> **Note**: For development, use `uv pip install -e .` for editable installation.
@@ -143,6 +174,7 @@ The JWT middleware supports two validation strategies:
143
174
- Validates JWTs directly in the MCP server.
144
175
- Downloads public keys from a JWKS endpoint (configured in `jwks_uri`).
145
176
- Supports configurable cache and CEL conditions for advanced permissions.
177
+
- MCP tools check for required scopes (e.g., `tool:user` for hello_world).
146
178
-**Requirement**: OAuth server with JWKS endpoint (e.g. Keycloak).
147
179
148
180
### "external" Strategy
@@ -158,23 +190,61 @@ Example in `config.toml`.
158
190
159
191
See `config.toml` for configuration example.
160
192
161
-
**Security Note**: By default, the server runs on `127.0.0.1` to avoid unwanted exposures. Change to `0.0.0.0` only if necessary and with appropriate security measures.
Note: `roles` and `scope` claims are always exposed for authorization purposes.
229
+
230
+
**Security Note**: By default, the server runs on `127.0.0.1` to avoid unwanted exposures. Configure the host and port in `config.toml` under `[server.transport.http]`. Change to `0.0.0.0` only if necessary and with appropriate security measures.
162
231
163
232
## Security Considerations
164
233
165
234
This template implements several security measures to protect against common vulnerabilities. As a template, it's designed to be configurable for different deployment scenarios.
166
235
167
236
### JWT Claims Exposure
168
237
169
-
To minimize data exposure, configure which JWT claims are accessible in the context:
238
+
To minimize data exposure, configure which JWT claims are accessible to MCP tools:
170
239
171
240
```toml
172
-
[context]
173
241
jwt_exposed_claims = ["user_id", "roles"] # Only expose specific claims
174
242
# or
175
243
jwt_exposed_claims = "all"# Expose all claims (not recommended for production)
176
244
```
177
245
246
+
Note: `roles` and `scope` claims are always exposed for authorization purposes, regardless of this configuration.
247
+
178
248
### Access Logging
179
249
180
250
Sensitive headers are automatically redacted in logs:
@@ -212,6 +282,27 @@ Dependencies are regularly updated to address known vulnerabilities. Run `uv loc
212
282
-[Development Guide](DEVELOPMENT.md) - How to use this as a template.
213
283
-[Contributing](CONTRIBUTING.md) - Guidelines for contributors.
214
284
285
+
## Project Architecture
286
+
287
+
```
288
+
src/mcp_app/
289
+
├── main.py # Application entry point and FastAPI setup
290
+
├── config.py # Pydantic configuration models
291
+
├── context.py # JWT context management for secure claim sharing
-**main.py**: Initializes FastMCP server, FastAPI app, middlewares, and OAuth endpoints
300
+
-**config.py**: TOML-based configuration with Pydantic models
301
+
-**context.py**: Async-safe JWT context sharing between middlewares and tools
302
+
-**handlers/**: OAuth authorization server and protected resource metadata endpoints
303
+
-**middlewares/**: JWT validation, access logging, and CORS handling
304
+
-**tools/**: MCP tool implementations and registration system
305
+
215
306
## Development
216
307
217
308
For detailed development instructions, including how to use this project as a template for your own MCP servers, see [DEVELOPMENT.md](DEVELOPMENT.md).
@@ -230,4 +321,4 @@ This project is licensed under the Unlicense - see the [LICENSE](LICENSE) file f
230
321
231
322
## Credits
232
323
233
-
Complete translation to Python of the [MCP Forge](https://github.com/achetronic/mcp-forge) project (Go), maintaining all functionalities and security level of the original.
324
+
This is a Python port of the [MCP Forge](https://github.com/achetronic/mcp-forge) project (Go), extended with additional OAuth flow endpoints and Python-specific implementations while maintaining security standards.
0 commit comments