Compare commits

...
Sign in to create a new pull request.

10 commits

Author SHA1 Message Date
8e80e2956c
add uvx
Some checks failed
Go CI / Test (push) Failing after 19s
Go CI / Build (push) Successful in 38s
Build and Push container / build_concierge_backend (push) Successful in 1m24s
2025-06-02 03:55:14 +02:00
c3e2abd2bc
change cmd
Some checks failed
Go CI / Test (push) Failing after 21s
Go CI / Build (push) Successful in 55s
Build and Push container / build_concierge_backend (push) Successful in 1m21s
2025-06-02 03:41:06 +02:00
e0beca18cf
adjust configuration to kvant 2025-05-19 10:25:27 +02:00
Pavindu Lakshan
ad5185ad72
Merge pull request #28 from pavinduLakshan/update_pr_template 2025-05-03 01:08:19 +05:30
Pavindu Lakshan
0bbc20ca5a Remove unnecessary fields from PR template 2025-05-03 01:06:41 +05:30
Pavindu Lakshan
4a5cf4e1cc
Update README.md 2025-04-27 17:23:13 +05:30
Pavindu Lakshan
87a1cbe21a
Update release.yml 2025-04-26 20:02:45 +05:30
Pavindu Lakshan
9ce9509cce
Fix issues in makefile (#26) 2025-04-21 15:29:48 +05:30
Pavindu Lakshan
5261a69f7a
Improve ordering in README (#24) 2025-04-18 21:40:36 +05:30
Pavindu Lakshan
23c282dcfc
Add badges to README (#25) 2025-04-18 21:40:12 +05:30
9 changed files with 218 additions and 126 deletions

View file

@ -19,7 +19,7 @@ GIT_TOKEN=$1
WORK_DIR=$2
VERSION_TYPE=$3 # possible values: major, minor, patch
Check if GIT_TOKEN is empty
# Check if GIT_TOKEN is empty
if [ -z "$GIT_TOKEN" ]; then
echo "❌ Error: GIT_TOKEN is not set."
exit 1

71
.github/workflows/ci.yaml vendored Normal file
View file

@ -0,0 +1,71 @@
name: Build and Push container
run-name: Build and Push container
on:
workflow_dispatch:
#schedule:
# - cron: "0 10 * * *"
push:
branches:
- 'main'
- 'master'
tags:
- 'v*'
pull_request:
branches:
- 'main'
- 'master'
env:
IMAGE: git.kvant.cloud/${{github.repository}}
jobs:
build_concierge_backend:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set current time
uses: https://github.com/gerred/actions/current-time@master
id: current_time
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to git.kvant.cloud registry
uses: docker/login-action@v3
with:
registry: git.kvant.cloud
username: ${{ vars.ORG_PACKAGE_WRITER_USERNAME }}
password: ${{ secrets.ORG_PACKAGE_WRITER_TOKEN }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
# list of Docker images to use as base name for tags
images: |
${{env.IMAGE}}
# generate Docker tags based on the following events/attributes
tags: |
type=schedule
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
- name: Build and push to gitea registry
uses: docker/build-push-action@v6
with:
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
context: .
provenance: mode=max
sbom: true
build-args: |
BUILD_DATE=${{ steps.current_time.outputs.time }}
cache-from: |
type=registry,ref=${{ env.IMAGE }}:buildcache
type=registry,ref=${{ env.IMAGE }}:${{ github.ref_name }}
type=registry,ref=${{ env.IMAGE }}:main
cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max,image-manifest=true

View file

@ -32,7 +32,7 @@ jobs:
with:
ref: 'main'
fetch-depth: 0
token: ${{ secrets.GIT_BOT_PAT }}
token: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@v2
- name: Set up Go 1.x
@ -60,5 +60,5 @@ jobs:
- name: Update artifact version, package, commit, and create release.
env:
GITHUB_TOKEN: ${{ secrets.GIT_BOT_PAT }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: bash ./.github/scripts/release.sh $GITHUB_TOKEN ${{ github.workspace }} ${{ github.event.inputs.version_type }}

48
Dockerfile Normal file
View file

@ -0,0 +1,48 @@
FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.24@sha256:d9db32125db0c3a680cfb7a1afcaefb89c898a075ec148fdc2f0f646cc2ed509 AS build
ARG TARGETPLATFORM
ARG BUILDPLATFORM
ARG TARGETOS
ARG TARGETARCH
WORKDIR /workspace
RUN apt update -qq && apt install -qq -y git bash curl g++
# Download libraries
ADD go.* .
RUN go mod download
# Build
ADD cmd cmd
ADD internal internal
RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o webhook -ldflags '-w -extldflags "-static"' -o openmcpauthproxy ./cmd/proxy
#Test
RUN CGO_ENABLED=1 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go test -v -race ./...
# Build production container
FROM --platform=${BUILDPLATFORM:-linux/amd64} ubuntu:24.04
RUN apt-get update \
&& apt-get install --no-install-recommends -y \
python3-pip \
python-is-python3 \
npm \
&& apt-get autoremove \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN pip install uvenv --break-system-packages
WORKDIR /app
COPY --from=build /workspace/openmcpauthproxy /app/
ADD config.yaml /app
ENTRYPOINT ["/app/openmcpauthproxy"]
ARG IMAGE_SOURCE
LABEL org.opencontainers.image.source=$IMAGE_SOURCE

View file

@ -30,19 +30,19 @@ build: clean test build-linux build-linux-arm build-darwin
build-linux:
mkdir -p $(BUILD_DIR)/linux
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -x -ldflags "-X main.version=$(BUILD_VERSION) \
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -x -ldflags "-X main.version=$(BUILD_VERSION)" \
-o $(BUILD_DIR)/linux/openmcpauthproxy $(PROJECT_ROOT)/cmd/proxy
cp config.yaml $(BUILD_DIR)/linux
build-linux-arm:
mkdir -p $(BUILD_DIR)/linux-arm
GOOS=linux GOARCH=arm CGO_ENABLED=0 go build -x -ldflags "-X main.version=$(BUILD_VERSION) \
GOOS=linux GOARCH=arm CGO_ENABLED=0 go build -x -ldflags "-X main.version=$(BUILD_VERSION)" \
-o $(BUILD_DIR)/linux-arm/openmcpauthproxy $(PROJECT_ROOT)/cmd/proxy
cp config.yaml $(BUILD_DIR)/linux-arm
build-darwin:
mkdir -p $(BUILD_DIR)/darwin
GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -x -ldflags "-X main.version=$(BUILD_VERSION) \
GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -x -ldflags "-X main.version=$(BUILD_VERSION)" \
-o $(BUILD_DIR)/darwin/openmcpauthproxy $(PROJECT_ROOT)/cmd/proxy
cp config.yaml $(BUILD_DIR)/darwin

106
README.md
View file

@ -1,6 +1,12 @@
# Open MCP Auth Proxy
A lightweight authorization proxy for Model Context Protocol (MCP) servers that enforces authorization according to the [MCP authorization specification](https://spec.modelcontextprotocol.io/specification/2025-03-26/basic/authorization/).
A lightweight authorization proxy for Model Context Protocol (MCP) servers that enforces authorization according to the [MCP authorization specification](https://spec.modelcontextprotocol.io/specification/2025-03-26/basic/authorization/)
<a href="">[![🚀 Release](https://github.com/wso2/open-mcp-auth-proxy/actions/workflows/release.yml/badge.svg)](https://github.com/wso2/open-mcp-auth-proxy/actions/workflows/release.yml)</a>
<a href="">[![💬 Stackoverflow](https://img.shields.io/badge/Ask%20for%20help%20on-Stackoverflow-orange)](https://stackoverflow.com/questions/tagged/wso2is)</a>
<a href="">[![💬 Discord](https://img.shields.io/badge/Join%20us%20on-Discord-%23e01563.svg)](https://discord.gg/wso2)</a>
<a href="">[![🐦 Twitter](https://img.shields.io/twitter/follow/wso2.svg?style=social&label=Follow)](https://twitter.com/intent/follow?screen_name=wso2)</a>
<a href="">[![📝 License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/wso2/product-is/blob/master/LICENSE)</a>
![Architecture Diagram](https://github.com/user-attachments/assets/41cf6723-c488-4860-8640-8fec45006f92)
@ -19,28 +25,29 @@ Open MCP Auth Proxy sits between MCP clients and your MCP server to:
* Go 1.20 or higher
* A running MCP server
> If you don't have an MCP server, you can use the included example:
>
> 1. Navigate to the `resources` directory
> 2. Set up a Python environment:
>
> ```bash
> python3 -m venv .venv
> source .venv/bin/activate
> pip3 install -r requirements.txt
> ```
>
> 3. Start the example server:
>
> ```bash
> python3 echo_server.py
> ```
* An MCP client that supports MCP authorization
### Installation
```bash
git clone https://github.com/wso2/open-mcp-auth-proxy
cd open-mcp-auth-proxy
go get github.com/golang-jwt/jwt/v4 gopkg.in/yaml.v2
go build -o openmcpauthproxy ./cmd/proxy
```
### Basic Usage
1. The repository comes with a default `config.yaml` file that contains the basic configuration:
```yaml
listen_port: 8080
base_url: "http://localhost:8000" # Your MCP server URL
paths:
sse: "/sse"
messages: "/messages/"
```
1. Download the latest release from [Github releases](https://github.com/wso2/open-mcp-auth-proxy/releases/latest).
2. Start the proxy in demo mode (uses pre-configured authentication with Asgardeo sandbox):
@ -48,31 +55,30 @@ paths:
./openmcpauthproxy --demo
```
> The repository comes with a default `config.yaml` file that contains the basic configuration:
>
> ```yaml
> listen_port: 8080
> base_url: "http://localhost:8000" # Your MCP server URL
> paths:
> sse: "/sse"
> messages: "/messages/"
> ```
3. Connect using an MCP client like [MCP Inspector](https://github.com/shashimalcse/inspector)(This is a temporary fork with fixes for authentication [issues](https://github.com/modelcontextprotocol/typescript-sdk/issues/257) in the original implementation)
## Identity Provider Integration
## Connect an Identity Provider
### Demo Mode
### Asgardeo
For quick testing, use the `--demo` flag which includes pre-configured authentication and authorization with an Asgardeo sandbox.
```bash
./openmcpauthproxy --demo
```
### Asgardeo Integration
To enable authorization through your own Asgardeo organization:
To enable authorization through your Asgardeo organization:
1. [Register](https://asgardeo.io/signup) and create an organization in Asgardeo
2. Create an [M2M application](https://wso2.com/asgardeo/docs/guides/applications/register-machine-to-machine-app/)
1. [Authorize this application](https://wso2.com/asgardeo/docs/guides/applications/register-machine-to-machine-app/#authorize-the-api-resources-for-the-app) to invoke "Application Management API" with the `internal_application_mgt_create` scope
![image](https://github.com/user-attachments/assets/0bd57cac-1904-48cc-b7aa-0530224bc41a)
2. Update the existing `config.yaml` with your Asgardeo details:
#### Configure the Auth Proxy
Create a configuration file config.yaml with the following parameters:
3. Update `config.yaml` with the following parameters.
```yaml
base_url: "http://localhost:8000" # URL of your MCP server
@ -84,7 +90,7 @@ asgardeo:
client_secret: "<client_secret>" # Client secret of the M2M app
```
3. Start the proxy with Asgardeo integration:
4. Start the proxy with Asgardeo integration:
```bash
./openmcpauthproxy --asgardeo
@ -95,25 +101,6 @@ asgardeo:
- [Auth0](docs/integrations/Auth0.md)
- [Keycloak](docs/integrations/keycloak.md)
## Testing with an Example MCP Server
If you don't have an MCP server, you can use the included example:
1. Navigate to the `resources` directory
2. Set up a Python environment:
```bash
python3 -m venv .venv
source .venv/bin/activate
pip3 install -r requirements.txt
```
3. Start the example server:
```bash
python3 echo_server.py
```
# Advanced Configuration
### Transport Modes
@ -228,3 +215,12 @@ asgardeo:
client_id: "<client_id>"
client_secret: "<client_secret>"
```
### Build from source
```bash
git clone https://github.com/wso2/open-mcp-auth-proxy
cd open-mcp-auth-proxy
go get github.com/golang-jwt/jwt/v4 gopkg.in/yaml.v2
go build -o openmcpauthproxy ./cmd/proxy
```

View file

@ -12,7 +12,7 @@ import (
"github.com/wso2/open-mcp-auth-proxy/internal/authz"
"github.com/wso2/open-mcp-auth-proxy/internal/config"
"github.com/wso2/open-mcp-auth-proxy/internal/constants"
"github.com/wso2/open-mcp-auth-proxy/internal/logging"
logger "github.com/wso2/open-mcp-auth-proxy/internal/logging"
"github.com/wso2/open-mcp-auth-proxy/internal/proxy"
"github.com/wso2/open-mcp-auth-proxy/internal/subprocess"
"github.com/wso2/open-mcp-auth-proxy/internal/util"
@ -58,7 +58,7 @@ func main() {
logger.Warn("%v", err)
logger.Warn("Subprocess may fail to start due to missing dependencies")
}
procManager = subprocess.NewManager()
if err := procManager.Start(cfg); err != nil {
logger.Warn("Failed to start subprocess: %v", err)
@ -95,7 +95,7 @@ func main() {
// 5. Build the main router
mux := proxy.NewRouter(cfg, provider)
listen_address := fmt.Sprintf(":%d", cfg.ListenPort)
listen_address := fmt.Sprintf("0.0.0.0:%d", cfg.ListenPort)
// 6. Start the server
srv := &http.Server{

View file

@ -6,29 +6,23 @@ base_url: "http://localhost:8000" # Base URL for the MCP server
port: 8000 # Port for the MCP server
timeout_seconds: 10
# Path configuration
paths:
sse: "/sse" # SSE endpoint path
messages: "/messages/" # Messages endpoint path
# Transport mode configuration
transport_mode: "sse" # Options: "sse" or "stdio"
transport_mode: "stdio" # Options: "sse" or "stdio"
# stdio-specific configuration (used only when transport_mode is "stdio")
stdio:
enabled: true
user_command: "npx -y @modelcontextprotocol/server-github"
user_command: uvx mcp-server-time --local-timezone=Europe/Zurich
#user_command: "npx -y @modelcontextprotocol/server-github"
work_dir: "" # Working directory (optional)
# env: # Environment variables (optional)
# - "NODE_ENV=development"
# Path mapping (optional)
path_mapping:
# CORS configuration
# CORS settings
cors:
allowed_origins:
- "http://localhost:5173"
- "http://localhost:6274" # Origin of your frontend/client app
allowed_methods:
- "GET"
- "POST"
@ -40,8 +34,32 @@ cors:
- "mcp-protocol-version"
allow_credentials: true
# Demo configuration for Asgardeo
demo:
org_name: "openmcpauthdemo"
client_id: "N0U9e_NNGr9mP_0fPnPfPI0a6twa"
client_secret: "qFHfiBp5gNGAO9zV4YPnDofBzzfInatfUbHyPZvM0jka"
# Keycloak endpoint path mappings
path_mapping:
sse: "/sse" # SSE endpoint path
messages: "/messages/" # Messages endpoint path
/token: /realms/master/protocol/openid-connect/token
/register: /realms/master/clients-registrations/openid-connect
# Keycloak configuration block
default:
base_url: "https://iam.phoenix-systems.ch"
jwks_url: "https://iam.phoenix-systems.ch/realms/kvant/protocol/openid-connect/certs"
path:
/.well-known/oauth-authorization-server:
response:
issuer: "https://iam.phoenix-systems.ch/realms/kvant"
jwks_uri: "https://iam.phoenix-systems.ch/realms/kvant/protocol/openid-connect/certs"
authorization_endpoint: "https://iam.phoenix-systems.ch/realms/kvant/protocol/openid-connect/auth"
response_types_supported:
- "code"
grant_types_supported:
- "authorization_code"
- "refresh_token"
code_challenge_methods_supported:
- "S256"
- "plain"
/token:
addBodyParams:
- name: "audience"
value: "mcp_proxy"

View file

@ -1,52 +1,11 @@
## Purpose
> Describe the problems, issues, or needs driving this feature/fix and include links to related issues in the following format: Resolves issue1, issue2, etc.
<!-- Describe the problems, issues, or needs driving this feature/fix and include links to related issues in the following format: Resolves issue1, issue2, etc. -->
## Goals
> Describe the solutions that this feature/fix will introduce to resolve the problems described above
## Approach
> Describe how you are implementing the solutions. Include an animated GIF or screenshot if the change affects the UI (email documentation@wso2.com to review all UI text). Include a link to a Markdown file or Google doc if the feature write-up is too long to paste here.
## User stories
> Summary of user stories addressed by this change>
## Release note
> Brief description of the new feature or bug fix as it will appear in the release notes
## Documentation
> Link(s) to product documentation that addresses the changes of this PR. If no doc impact, enter “N/A” plus brief explanation of why theres no doc impact
## Training
> Link to the PR for changes to the training content in https://github.com/wso2/WSO2-Training, if applicable
## Certification
> Type “Sent” when you have provided new/updated certification questions, plus four answers for each question (correct answer highlighted in bold), based on this change. Certification questions/answers should be sent to certification@wso2.com and NOT pasted in this PR. If there is no impact on certification exams, type “N/A” and explain why.
## Marketing
> Link to drafts of marketing content that will describe and promote this feature, including product page changes, technical articles, blog posts, videos, etc., if applicable
## Automation tests
- Unit tests
> Code coverage information
- Integration tests
> Details about the test cases and coverage
## Security checks
- Followed secure coding standards in http://wso2.com/technical-reports/wso2-secure-engineering-guidelines? yes/no
- Ran FindSecurityBugs plugin and verified report? yes/no
- Confirmed that this PR doesn't commit any keys, passwords, tokens, usernames, or other secrets? yes/no
## Samples
> Provide high-level details about the samples related to this feature
## Related Issues
<!-- List any related issues -->
## Related PRs
> List any other related PRs
<!-- List any other related PRs -->
## Migrations (if applicable)
> Describe migration steps and platforms on which migration has been tested
## Test environment
> List all JDK versions, operating systems, databases, and browser/versions on which this feature/fix was tested
## Learning
> Describe the research phase and any blog posts, patterns, libraries, or add-ons you used to solve the problem.
<!-- Describe migration steps and platforms on which migration has been tested -->