feat: implement server publishing endpoint with Bearer token authentication and update documentation
This commit is contained in:
parent
e0a4883465
commit
9c6eebbed0
4 changed files with 190 additions and 48 deletions
|
|
@ -5,23 +5,13 @@ import (
|
|||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/modelcontextprotocol/registry/internal/auth"
|
||||
"github.com/modelcontextprotocol/registry/internal/model"
|
||||
"github.com/modelcontextprotocol/registry/internal/service"
|
||||
)
|
||||
|
||||
// httpError represents an HTTP error with a message and status code
|
||||
type httpError struct {
|
||||
msg string
|
||||
status int
|
||||
}
|
||||
|
||||
// Error returns the error message
|
||||
func (e *httpError) Error() string {
|
||||
return e.msg
|
||||
}
|
||||
|
||||
// PublishHandler handles requests to publish new server details to the registry
|
||||
func PublishHandler(registry service.RegistryService, authService auth.Service) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
@ -62,23 +52,39 @@ func PublishHandler(registry service.RegistryService, authService auth.Service)
|
|||
return
|
||||
}
|
||||
|
||||
// Validate authentication credentials
|
||||
if authService != nil {
|
||||
publishReq.Authentication.RepoRef = serverDetail.Name
|
||||
valid, err := authService.ValidateAuth(r.Context(), publishReq.Authentication)
|
||||
if err != nil {
|
||||
if err == auth.ErrAuthRequired {
|
||||
http.Error(w, "Authentication is required for publishing", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
http.Error(w, "Authentication failed: "+err.Error(), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
// Get auth token from Authorization header
|
||||
authHeader := r.Header.Get("Authorization")
|
||||
if authHeader == "" {
|
||||
http.Error(w, "Authorization header is required", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
if !valid {
|
||||
http.Error(w, "Invalid authentication credentials", http.StatusUnauthorized)
|
||||
// Handle bearer token format (e.g., "Bearer xyz123")
|
||||
token := authHeader
|
||||
if len(authHeader) > 7 && strings.ToUpper(authHeader[:7]) == "BEARER " {
|
||||
token = authHeader[7:]
|
||||
}
|
||||
|
||||
// Setup authentication info
|
||||
a := model.Authentication{
|
||||
Method: model.AuthMethodGitHub,
|
||||
Token: token,
|
||||
RepoRef: serverDetail.Name,
|
||||
}
|
||||
|
||||
valid, err := authService.ValidateAuth(r.Context(), a)
|
||||
if err != nil {
|
||||
if err == auth.ErrAuthRequired {
|
||||
http.Error(w, "Authentication is required for publishing", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
http.Error(w, "Authentication failed: "+err.Error(), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
if !valid {
|
||||
http.Error(w, "Invalid authentication credentials", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
// Call the publish method on the registry service
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
summary: Publish a server to the registry
|
||||
description: Adds a new server to the MCP registry with authentication
|
||||
operationId: publishServer
|
||||
security:
|
||||
- bearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
|
|
@ -14,11 +16,9 @@
|
|||
properties:
|
||||
server_detail:
|
||||
$ref: '#/components/schemas/ServerDetail'
|
||||
authentication:
|
||||
$ref: '#/components/schemas/Authentication'
|
||||
auth_status_token:
|
||||
repo_ref:
|
||||
type: string
|
||||
description: Optional status token from a device authorization flow
|
||||
description: Repository reference used for authentication (defaults to server name if not provided)
|
||||
responses:
|
||||
'201':
|
||||
description: Server published successfully
|
||||
|
|
|
|||
|
|
@ -101,6 +101,74 @@ paths:
|
|||
'405':
|
||||
description: Method not allowed
|
||||
|
||||
/v0/publish:
|
||||
post:
|
||||
tags:
|
||||
- servers
|
||||
summary: Publish a server to the registry
|
||||
description: Adds a new server to the MCP registry with authentication
|
||||
operationId: publishServer
|
||||
security:
|
||||
- bearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
server_detail:
|
||||
$ref: '#/components/schemas/ServerDetail'
|
||||
repo_ref:
|
||||
type: string
|
||||
description: Repository reference used for authentication (defaults to server name if not provided)
|
||||
responses:
|
||||
'201':
|
||||
description: Server published successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
example: Server publication successful
|
||||
id:
|
||||
type: string
|
||||
example: 1234567890abcdef12345678
|
||||
'400':
|
||||
description: Invalid request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
example: Name is required
|
||||
'401':
|
||||
description: Authentication failed
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
example: Authentication is required for publishing
|
||||
'405':
|
||||
description: Method not allowed
|
||||
'500':
|
||||
description: Server error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
example: Failed to publish server details
|
||||
|
||||
/v0/servers/{id}:
|
||||
get:
|
||||
tags:
|
||||
|
|
@ -131,6 +199,13 @@ paths:
|
|||
description: Method not allowed
|
||||
|
||||
components:
|
||||
securitySchemes:
|
||||
bearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: JWT
|
||||
description: "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\""
|
||||
|
||||
schemas:
|
||||
Server:
|
||||
type: object
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ type Authentication struct {
|
|||
// PublishRequest represents a request to publish a server to the registry
|
||||
type PublishRequest struct {
|
||||
ServerDetail ServerDetail `json:"server_detail"`
|
||||
Authentication Authentication `json:"authentication,omitempty"`
|
||||
Authentication Authentication `json:"-"` // Now provided via Authorization header
|
||||
AuthStatusToken string `json:"-"` // Used internally for device flows
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue