Skip to content

Commit 307fdb1

Browse files
Publish Auth Interface (#112)
This pull request introduces significant updates to the authentication system for the MCP Registry Publisher Tool. The changes focus on transitioning to an interface-based authentication system, implementing GitHub OAuth device flow as the default authentication method, and restructuring the codebase for better modularity and extensibility. Adding an interface to the publishing CLI, so that it'll be easier to add more auth methods as they become available.
1 parent a15d525 commit 307fdb1

File tree

5 files changed

+465
-266
lines changed

5 files changed

+465
-266
lines changed

tools/publisher/README.md

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# MCP Registry Publisher Tool
22

3-
The MCP Registry Publisher Tool is designed to publish Model Context Protocol (MCP) server details to an MCP registry. This tool currently only handles GitHub authentication via device flow and manages the publishing process.
3+
The MCP Registry Publisher Tool is designed to publish Model Context Protocol (MCP) server details to an MCP registry. This tool uses GitHub OAuth device flow authentication to securely manage the publishing process.
44

55
## Building the Tool
66

@@ -20,29 +20,30 @@ The compiled binary will be placed in the `bin` directory.
2020

2121
```bash
2222
# Basic usage
23-
./bin/mcp-publisher --registry-url <REGISTRY_URL> --mcp-file <PATH_TO_MCP_FILE>
23+
./bin/mcp-publisher -registry-url <REGISTRY_URL> -mcp-file <PATH_TO_MCP_FILE>
2424

2525
# Force a new login even if a token exists
26-
./bin/mcp-publisher --registry-url <REGISTRY_URL> --mcp-file <PATH_TO_MCP_FILE> --login
26+
./bin/mcp-publisher -registry-url <REGISTRY_URL> -mcp-file <PATH_TO_MCP_FILE> -login
2727
```
2828

2929
### Command-line Arguments
3030

31-
- `--registry-url`: URL of the MCP registry (required)
32-
- `--mcp-file`: Path to the MCP configuration file (required)
33-
- `--login`: Force a new GitHub authentication even if a token already exists (overwrites existing token file)
34-
- `--token`: Use the provided token instead of GitHub authentication (bypasses the device flow)
31+
- `-registry-url`: URL of the MCP registry (required)
32+
- `-mcp-file`: Path to the MCP configuration file (required)
33+
- `-login`: Force a new GitHub authentication even if a token already exists (overwrites existing token file)
34+
- `-auth-method`: Authentication method to use (default: github-oauth)
3535

3636
## Authentication
3737

38-
The tool uses GitHub device flow authentication:
39-
1. The tool automatically retrieves the GitHub Client ID from the registry's health endpoint
40-
2. When first run (or with `--login` flag), the tool will initiate the GitHub device flow
41-
3. You'll be provided with a URL and a code to enter
42-
4. After successful authentication, the tool saves the token locally for future use
43-
5. The token is sent in the HTTP Authorization header with the Bearer scheme
38+
The tool has been simplified to use **GitHub OAuth device flow authentication exclusively**. Previous versions supported multiple authentication methods, but this version focuses solely on GitHub OAuth for better security and user experience.
4439

45-
_NOTE_ : Authentication is made on behalf of a OAuth App which you must authorize for respective resources (e.g `org`)
40+
1. **Automatic Setup**: The tool automatically retrieves the GitHub Client ID from the registry's health endpoint
41+
2. **First Run Authentication**: When first run (or with the `--login` flag), the tool initiates the GitHub device flow
42+
3. **User Authorization**: You'll be provided with a URL and a verification code to enter on GitHub
43+
4. **Token Storage**: After successful authentication, the tool saves the access token locally in `.mcpregistry_token` for future use
44+
5. **Secure Communication**: The token is sent in the HTTP Authorization header with the Bearer scheme for all registry API calls
45+
46+
**Note**: Authentication is performed via GitHub OAuth App, which you must authorize for the respective resources (e.g., organization access if publishing organization repositories).
4647

4748
## Example
4849

@@ -98,7 +99,9 @@ _NOTE_ : Authentication is made on behalf of a OAuth App which you must authoriz
9899

99100
## Important Notes
100101

101-
- The GitHub Client ID is automatically retrieved from the registry's health endpoint
102-
- The authentication token is saved in a file named `.mcpregistry_token` in the current directory
103-
- The tool requires an active internet connection to authenticate with GitHub and communicate with the registry
104-
- Make sure the repository and package mentioned in your `mcp.json` file exist and are accessible
102+
- **GitHub Authentication Only**: The tool exclusively uses GitHub OAuth device flow for authentication
103+
- **Automatic Client ID**: The GitHub Client ID is automatically retrieved from the registry's health endpoint
104+
- **Token Storage**: The authentication token is saved in `.mcpregistry_token` in the current directory
105+
- **Internet Required**: Active internet connection needed for GitHub authentication and registry communication
106+
- **Repository Access**: Ensure the repository and package mentioned in your `mcp.json` file exist and are accessible
107+
- **OAuth Permissions**: You may need to grant the OAuth app access to your GitHub organizations if publishing org repositories

tools/publisher/auth/README.md

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# Authentication System
2+
3+
The publisher tool now uses an interface-based authentication system that allows for multiple authentication mechanisms.
4+
5+
## Architecture
6+
7+
### Provider Interface
8+
9+
The `Provider` interface is defined in `auth/interface.go` and provides the following methods:
10+
11+
- `GetToken(ctx context.Context) (string, error)` - Retrieves or generates an authentication token
12+
- `NeedsLogin() bool` - Checks if a new login flow is required
13+
- `Login(ctx context.Context) error` - Performs the authentication flow
14+
- `Name() string` - Returns the name of the authentication provider
15+
16+
### Available Authentication Providers
17+
18+
#### 1. GitHub OAuth Provider
19+
- **Location**: `auth/github/oauth.go`
20+
- **Usage**: Uses GitHub's device flow for authentication
21+
- **Example**: `github.NewOAuthProvider(forceLogin, registryURL)`
22+
23+
24+
## How to Add New Authentication Providers
25+
26+
1. Create a new package under `auth/` directory (e.g., `auth/custom/`)
27+
2. Implement the `Provider` interface
28+
3. Add any necessary configuration or initialization functions
29+
4. Update the main application to use the new provider
30+
31+
### Example Implementation
32+
33+
```go
34+
package custom
35+
36+
import (
37+
"context"
38+
"fmt"
39+
)
40+
41+
type CustomProvider struct {
42+
// your custom fields
43+
}
44+
45+
func NewCustomProvider(config string) *CustomProvider {
46+
return &CustomProvider{
47+
// initialize your provider
48+
}
49+
}
50+
51+
func (cp *CustomProvider) GetToken(ctx context.Context) (string, error) {
52+
// implement token retrieval logic
53+
return "custom-token", nil
54+
}
55+
56+
func (cp *CustomProvider) NeedsLogin() bool {
57+
// implement login check logic
58+
return false
59+
}
60+
61+
func (cp *CustomProvider) Login(ctx context.Context) error {
62+
// implement authentication flow
63+
return nil
64+
}
65+
66+
func (cp *CustomProvider) Name() string {
67+
return "custom-auth"
68+
}
69+
```
70+
71+
## Usage in Main Application
72+
73+
The main application automatically selects the appropriate authentication provider:
74+
75+
1. Uses `GitHub OAuth Provider` by default
76+
2. Future providers can be added by extending the provider selection logic
77+
78+
```go
79+
// Create the appropriate auth provider based on configuration
80+
var authProvider auth.Provider
81+
switch authMethod {
82+
case "github-oauth":
83+
log.Println("Using GitHub OAuth for authentication")
84+
authProvider = github.NewOAuthProvider(forceLogin, registryURL)
85+
default:
86+
log.Printf("Unsupported authentication method: %s\n", authMethod)
87+
return
88+
}
89+
90+
// Check if login is needed and perform authentication
91+
ctx := context.Background()
92+
if authProvider.NeedsLogin() {
93+
err := authProvider.Login(ctx)
94+
if err != nil {
95+
log.Printf("Failed to authenticate with %s: %s\n", authProvider.Name(), err.Error())
96+
return
97+
}
98+
}
99+
100+
// Get the token
101+
token, err := authProvider.GetToken(ctx)
102+
```
103+
104+
This design allows for easy extension and testing of different authentication mechanisms while maintaining a clean separation of concerns.

0 commit comments

Comments
 (0)