Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
47669fa
Add Maven project structure for Java Auth MCP Server (#2)
Mar 17, 2026
19d34d2
Add server configuration file for Java Auth MCP Server (#2)
Mar 17, 2026
cc2f376
Add AuthServerConfig class with INI parsing (#2)
Mar 17, 2026
d249192
Add config buildFromMap and validation methods (#2)
Mar 17, 2026
38053de
Add AuthContext model for JWT token data (#2)
Mar 17, 2026
6f0f844
Add JSON-RPC 2.0 model classes (#2)
Mar 17, 2026
2816905
Add MCP tool model classes (#2)
Mar 17, 2026
8864b43
Add CORS filter with MCP headers (#2)
Mar 17, 2026
81f76d3
Update gopher-orch submodule to br_release branch (#2)
Mar 17, 2026
3e380a4
Add health check endpoint handler (#2)
Mar 17, 2026
6fbb14e
Add OAuthEndpoints with protected resource metadata (#2)
Mar 17, 2026
45a8d1d
Add authorization server metadata endpoint (#2)
Mar 17, 2026
68bcad8
Add OpenID configuration and OAuth endpoints (#2)
Mar 17, 2026
76f5733
Add OAuthAuthMiddleware with token extraction (#2)
Mar 17, 2026
9309d39
Add path-based authentication rules (#2)
Mar 17, 2026
40ff446
Add unauthorized response with WWW-Authenticate header (#2)
Mar 17, 2026
5b2403f
Add middleware handle method with token validation (#2)
Mar 17, 2026
8d50bf3
Add MCP handler with JSON-RPC routing (#2)
Mar 17, 2026
1053561
Add WeatherTools with scope-based access control (#2)
Mar 17, 2026
cb8bc1a
Add Application main class with server startup (#2)
Mar 17, 2026
16baec5
Move auth client interfaces to library package (#2)
Mar 17, 2026
aa12378
Move AuthContext to library auth package (#2)
Mar 17, 2026
63a67d4
Add auth example to build.sh (#2)
Mar 17, 2026
16e1d89
Resolve OAuth discovery endpoints to match JS/Rust implementations (#2)
Mar 17, 2026
a9876e3
Improve OAuth authorize and register endpoints (#2)
Mar 17, 2026
3b05432
Always rebuild auth example before running (#2)
Mar 17, 2026
3e72d2d
Update authorization_endpoint to point to MCP server (#2)
Mar 17, 2026
791e914
Require auth on protected paths even without auth client (#2)
Mar 17, 2026
12b7d78
Improve auth status message and null client handling (#2)
Mar 17, 2026
e163925
Resolve OAuth loop by trusting tokens when client unavailable (#2)
Mar 17, 2026
eb22ac1
Format code
Mar 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[submodule "third_party/gopher-orch"]
path = third_party/gopher-orch
url = https://github.com/GopherSecurity/gopher-orch.git
branch = br_release
33 changes: 29 additions & 4 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,34 @@ echo ""
echo -e "${YELLOW}Step 5: Running tests...${NC}"
mvn test -q 2>/dev/null && echo -e "${GREEN}✓ Tests passed${NC}" || echo -e "${YELLOW}⚠ Some tests may have failed (native library required)${NC}"

# Package JAR
echo -e "${YELLOW}Step 6: Packaging JAR...${NC}"
mvn package -q -DskipTests
echo -e "${GREEN}✓ JAR packaged successfully${NC}"
# Step 6: Package and install JAR to local Maven repo
echo -e "${YELLOW}Step 6: Packaging and installing JAR...${NC}"
mvn install -q -DskipTests -Dmaven.javadoc.skip=true
echo -e "${GREEN}✓ JAR packaged and installed to local Maven repo${NC}"
echo ""

# Step 7: Build and test auth example
echo -e "${YELLOW}Step 7: Building and testing auth example...${NC}"
AUTH_EXAMPLE_DIR="${SCRIPT_DIR}/examples/auth"

if [ -d "${AUTH_EXAMPLE_DIR}" ]; then
cd "${AUTH_EXAMPLE_DIR}"

echo -e "${YELLOW} Compiling auth example...${NC}"
mvn compile -q
echo -e "${GREEN} ✓ Auth example compiled${NC}"

echo -e "${YELLOW} Running auth example tests...${NC}"
mvn test -q 2>/dev/null && echo -e "${GREEN} ✓ Auth example tests passed${NC}" || echo -e "${YELLOW} ⚠ Some auth example tests may have failed${NC}"

echo -e "${YELLOW} Packaging auth example...${NC}"
mvn package -q -DskipTests
echo -e "${GREEN} ✓ Auth example packaged${NC}"

cd "${SCRIPT_DIR}"
else
echo -e "${YELLOW}⚠ Auth example not found at ${AUTH_EXAMPLE_DIR}${NC}"
fi

echo ""
echo -e "${GREEN}======================================${NC}"
Expand All @@ -182,3 +206,4 @@ echo -e "Native headers: ${YELLOW}${NATIVE_INCLUDE_DIR}${NC}"
echo -e "Run tests: ${YELLOW}mvn test${NC}"
echo -e "Run example: ${YELLOW}mvn exec:java${NC}"
echo -e "Package JAR: ${YELLOW}mvn package${NC}"
echo -e "Run auth example: ${YELLOW}cd examples/auth && ./run_example.sh --no-auth${NC}"
180 changes: 180 additions & 0 deletions examples/auth/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
# Java Auth MCP Server

An OAuth-protected MCP (Model Context Protocol) server demonstrating JWT token validation and scope-based access control.

## Prerequisites

- Java 17 or later
- Maven 3.8 or later

## Building

```bash
mvn package
```

## Running

### Development Mode (No Auth)

```bash
./run_example.sh --no-auth
```

### With Configuration File

```bash
./run_example.sh --config server.config
```

### Direct Java Execution

```bash
java -jar target/auth-mcp-server-1.0.0.jar server.config
```

## Configuration

Create a `server.config` file with the following options:

```ini
# Server settings
host=0.0.0.0
port=3001

# OAuth/IDP settings
client_id=my-client
client_secret=my-secret
auth_server_url=https://keycloak.example.com/realms/mcp

# Scopes
allowed_scopes=openid profile email mcp:read mcp:admin

# Cache settings
jwks_cache_duration=3600
jwks_auto_refresh=true
request_timeout=30

# Auth bypass mode (for development)
auth_disabled=true
```

## Endpoints

### Health Check

```bash
curl http://localhost:3001/health
```

### OAuth Discovery

```bash
# Protected Resource Metadata (RFC 9728)
curl http://localhost:3001/.well-known/oauth-protected-resource

# Authorization Server Metadata (RFC 8414)
curl http://localhost:3001/.well-known/oauth-authorization-server

# OpenID Configuration
curl http://localhost:3001/.well-known/openid-configuration
```

### MCP Endpoints

#### Initialize

```bash
curl -X POST http://localhost:3001/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize"}'
```

#### List Tools

```bash
curl -X POST http://localhost:3001/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
```

#### Call Tool (get-weather)

```bash
curl -X POST http://localhost:3001/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc":"2.0",
"id":3,
"method":"tools/call",
"params":{
"name":"get-weather",
"arguments":{"city":"London"}
}
}'
```

#### Call Tool (get-forecast) - Requires mcp:read scope

```bash
curl -X POST http://localhost:3001/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"jsonrpc":"2.0",
"id":4,
"method":"tools/call",
"params":{
"name":"get-forecast",
"arguments":{"city":"Tokyo"}
}
}'
```

#### Call Tool (get-weather-alerts) - Requires mcp:admin scope

```bash
curl -X POST http://localhost:3001/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"jsonrpc":"2.0",
"id":5,
"method":"tools/call",
"params":{
"name":"get-weather-alerts",
"arguments":{"region":"California"}
}
}'
```

## Available Tools

| Tool | Description | Required Scope |
|------|-------------|----------------|
| get-weather | Get current weather for a city | None |
| get-forecast | Get 5-day weather forecast | mcp:read |
| get-weather-alerts | Get weather alerts for a region | mcp:admin |

## Authentication

When authentication is enabled, protected endpoints require a valid JWT bearer token:

```bash
curl -X POST http://localhost:3001/mcp \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9..." \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

The token can also be passed as a query parameter:

```bash
curl -X POST "http://localhost:3001/mcp?access_token=eyJhbGciOiJSUzI1NiJ9..." \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

## License

MIT License
131 changes: 131 additions & 0 deletions examples/auth/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.gophersecurity</groupId>
<artifactId>auth-mcp-server</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>

<name>Java Auth MCP Server</name>
<description>OAuth-protected MCP server example with JWT validation and scope-based access control</description>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<javalin.version>6.1.3</javalin.version>
<jackson.version>2.16.1</jackson.version>
<slf4j.version>2.0.12</slf4j.version>
<junit.version>5.10.2</junit.version>
</properties>

<dependencies>
<!-- Gopher Orch library -->
<dependency>
<groupId>com.gophersecurity</groupId>
<artifactId>gopher-orch</artifactId>
<version>0.1.2</version>
</dependency>

<!-- Web framework -->
<dependency>
<groupId>io.javalin</groupId>
<artifactId>javalin</artifactId>
<version>${javalin.version}</version>
</dependency>

<!-- JSON processing -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>

<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>

<!-- Testing -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<mainClass>com.gophersecurity.mcp.auth.Application</mainClass>
</manifest>
</archive>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.gophersecurity.mcp.auth.Application</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.5</version>
</plugin>
</plugins>
</build>
</project>
Loading