@@ -4,15 +4,14 @@ import (
44 "context"
55 "encoding/json"
66 "errors"
7- "flag"
87 "fmt"
98 "os"
109 "path/filepath"
11- "strings"
1210
1311 "github.com/modelcontextprotocol/registry/cmd/publisher/auth"
1412 "github.com/modelcontextprotocol/registry/cmd/publisher/auth/azurekeyvault"
1513 "github.com/modelcontextprotocol/registry/cmd/publisher/auth/googlekms"
14+ "github.com/spf13/cobra"
1615)
1716
1817const (
@@ -27,6 +26,8 @@ const (
2726
2827type CryptoAlgorithm auth.CryptoAlgorithm
2928
29+ type Token string
30+
3031type SignerType string
3132
3233type LoginFlags struct {
@@ -36,10 +37,9 @@ type LoginFlags struct {
3637 KvVault string
3738 KvKeyName string
3839 KmsResource string
39- Token Token
40+ Token string
4041 CryptoAlgorithm CryptoAlgorithm
4142 SignerType SignerType
42- ArgOffset int
4343}
4444
4545const (
@@ -62,54 +62,81 @@ func (c *CryptoAlgorithm) Set(v string) error {
6262 return fmt .Errorf ("invalid algorithm: %q (allowed: ed25519, ecdsap384)" , v )
6363}
6464
65- type Token string
66-
67- func parseLoginFlags (method string , args []string ) (LoginFlags , error ) {
68- var flags LoginFlags
69- loginFlags := flag .NewFlagSet ("login" , flag .ExitOnError )
70- flags .CryptoAlgorithm = CryptoAlgorithm (auth .AlgorithmEd25519 )
71- flags .SignerType = NoSignerType
72- flags .ArgOffset = 1
73- loginFlags .StringVar (& flags .RegistryURL , "registry" , DefaultRegistryURL , "Registry URL" )
65+ func (c * CryptoAlgorithm ) Type () string {
66+ return "cryptoAlgorithm"
67+ }
7468
75- // Add --token flag for GitHub authentication
76- var token string
77- if method == MethodGitHub {
78- loginFlags .StringVar (& token , "token" , "" , "GitHub Personal Access Token" )
79- }
69+ var flags LoginFlags
70+
71+ func init () {
72+ mcpPublisherCmd .AddCommand (loginCmd )
73+ loginCmd .Flags ().StringVar (& flags .RegistryURL , "registry" , DefaultRegistryURL , "Registry URL" )
74+ loginCmd .Flags ().StringVarP (& flags .Token , "token" , "t" , "" , "GitHub Personal Access Token" )
75+ loginCmd .Flags ().StringVarP (& flags .Domain , "domain" , "d" , "" , "Domain name" )
76+ loginCmd .Flags ().StringVarP (& flags .KvVault , "vault" , "v" , "" , "The name of the Azure Key Vault resource" )
77+ loginCmd .Flags ().StringVarP (& flags .KvKeyName , "key" , "k" , "" , "Name of the signing key in the Azure Key Vault" )
78+ loginCmd .Flags ().StringVarP (& flags .KmsResource , "resource" , "r" , "" , "Google Cloud KMS resource name (e.g. projects/lotr/locations/global/keyRings/fellowship/cryptoKeys/frodo/cryptoKeyVersions/1)" )
79+ loginCmd .Flags ().StringVarP (& flags .PrivateKey , "private-key" , "p" , "" , "Private key (hex)" )
80+ loginCmd .Flags ().VarP (& flags .CryptoAlgorithm , "algorithm" , "a" , "Cryptographic algorithm (ed25519, ecdsap384)" )
81+ }
8082
81- if method == "dns" || method == "http" {
82- loginFlags .StringVar (& flags .Domain , "domain" , "" , "Domain name" )
83- if len (args ) > 1 {
84- switch args [1 ] {
85- case string (AzureKeyVaultSignerType ):
86- flags .SignerType = AzureKeyVaultSignerType
87- loginFlags .StringVar (& flags .KvVault , "vault" , "" , "The name of the Azure Key Vault resource" )
88- loginFlags .StringVar (& flags .KvKeyName , "key" , "" , "Name of the signing key in the Azure Key Vault" )
89- flags .ArgOffset = 2
90- case string (GoogleKMSSignerType ):
91- flags .SignerType = GoogleKMSSignerType
92- loginFlags .StringVar (& flags .KmsResource , "resource" , "" , "Google Cloud KMS resource name (e.g. projects/lotr/locations/global/keyRings/fellowship/cryptoKeys/frodo/cryptoKeyVersions/1)" )
93- flags .ArgOffset = 2
94- }
83+ var loginCmd = & cobra.Command {
84+ Use : "login <method> [options]" ,
85+ Short : "Authenticate with the registry" ,
86+ Long : `Methods:
87+ github Interactive GitHub authentication
88+ github-oidc GitHub Actions OIDC authentication
89+ dns DNS-based authentication (requires --domain)
90+ http HTTP-based authentication (requires --domain)
91+ none Anonymous authentication (for testing)` ,
92+ Args : func (_ * cobra.Command , args []string ) error {
93+ if len (args ) < 1 {
94+ return errors .New (`authentication method required
95+
96+ Usage: mcp-publisher login <method> [<signing provider>]
97+
98+ Methods:
99+ github Interactive GitHub authentication
100+ github-oidc GitHub Actions OIDC authentication
101+ dns DNS-based authentication (requires --domain)
102+ http HTTP-based authentication (requires --domain)
103+ none Anonymous authentication (for testing)
104+
105+ Signing providers:
106+ azure-key-vault Sign using Azure Key Vault
107+ google-kms Sign using Google Cloud KMS
108+
109+ The dns and http methods require a --private-key for in-process signing. For
110+ out-of-process signing, use one of the supported signing providers. Signing is
111+ needed for an authentication challenge with the registry.
112+
113+ The github and github-oidc methods do not support signing providers and
114+ authenticate using the GitHub as an identity provider.
115+
116+ Examples:
117+ # Interactive GitHub login, using device code flow
118+ mcp-publisher login github
119+
120+ # Sign in using a specific Ed25519 private key for DNS authentication
121+ mcp-publisher login dns -algorithm ed25519 -domain example.com -private-key <64 hex chars>
122+
123+ # Sign in using a specific ECDSA P-384 private key for DNS authentication
124+ mcp-publisher login dns -algorithm ecdsap384 -domain example.com -private-key <96 hex chars>
125+
126+ # Sign in with gcloud CLI, use Google Cloud KMS for signing in DNS authentication
127+ gcloud auth application-default login
128+ mcp-publisher login dns google-kms -domain example.com -resource projects/lotr/locations/global/keyRings/fellowship/cryptoKeys/frodo/cryptoKeyVersions/1
129+
130+ # Sign in with az CLI, use Azure Key Vault for signing in HTTP authentication
131+ az login
132+ mcp-publisher login http azure-key-vault -domain example.com -vault myvault -key mysigningkey` )
95133 }
96- if flags .SignerType == NoSignerType {
97- flags .SignerType = InProcessSignerType
98- loginFlags .StringVar (& flags .PrivateKey , "private-key" , "" , "Private key (hex)" )
99- loginFlags .Var (& flags .CryptoAlgorithm , "algorithm" , "Cryptographic algorithm (ed25519, ecdsap384)" )
100- }
101- }
102- err := loginFlags .Parse (args [flags .ArgOffset :])
103- if err == nil {
104- flags .RegistryURL = strings .TrimRight (flags .RegistryURL , "/" )
105- }
106-
107- // Store the token in flags if it was provided
108- if method == MethodGitHub {
109- flags .Token = Token (token )
110- }
111-
112- return flags , err
134+ return nil
135+ },
136+ Example : `
137+ mcp-publisher login github
138+ mcp-publisher login dns --domain example.com --private-key <key>` ,
139+ RunE : runLoginCommand ,
113140}
114141
115142func createSigner (flags LoginFlags ) (auth.Signer , error ) {
@@ -127,10 +154,10 @@ func createSigner(flags LoginFlags) (auth.Signer, error) {
127154 }
128155}
129156
130- func createAuthProvider (method , registryURL , domain string , token Token , signer auth.Signer ) (auth.Provider , error ) {
157+ func createAuthProvider (method , registryURL , domain string , token string , signer auth.Signer ) (auth.Provider , error ) {
131158 switch method {
132159 case MethodGitHub :
133- return auth .NewGitHubATProvider (true , registryURL , string ( token ) ), nil
160+ return auth .NewGitHubATProvider (true , registryURL , token ), nil
134161 case MethodGitHubOIDC :
135162 return auth .NewGitHubOIDCProvider (registryURL ), nil
136163 case MethodDNS :
@@ -150,59 +177,26 @@ func createAuthProvider(method, registryURL, domain string, token Token, signer
150177 }
151178}
152179
153- func LoginCommand (args []string ) error {
154- if len (args ) < 1 {
155- return errors .New (`authentication method required
156-
157- Usage: mcp-publisher login <method> [<signing provider>]
158-
159- Methods:
160- github Interactive GitHub authentication
161- github-oidc GitHub Actions OIDC authentication
162- dns DNS-based authentication (requires --domain)
163- http HTTP-based authentication (requires --domain)
164- none Anonymous authentication (for testing)
165-
166- Signing providers:
167- azure-key-vault Sign using Azure Key Vault
168- google-kms Sign using Google Cloud KMS
169-
170- The dns and http methods require a --private-key for in-process signing. For
171- out-of-process signing, use one of the supported signing providers. Signing is
172- needed for an authentication challenge with the registry.
173-
174- The github and github-oidc methods do not support signing providers and
175- authenticate using the GitHub as an identity provider.
176-
177- Examples:
178-
179- # Interactive GitHub login, using device code flow
180- mcp-publisher login github
181-
182- # Sign in using a specific Ed25519 private key for DNS authentication
183- mcp-publisher login dns -algorithm ed25519 -domain example.com -private-key <64 hex chars>
184-
185- # Sign in using a specific ECDSA P-384 private key for DNS authentication
186- mcp-publisher login dns -algorithm ecdsap384 -domain example.com -private-key <96 hex chars>
187-
188- # Sign in with gcloud CLI, use Google Cloud KMS for signing in DNS authentication
189- gcloud auth application-default login
190- mcp-publisher login dns google-kms -domain example.com -resource projects/lotr/locations/global/keyRings/fellowship/cryptoKeys/frodo/cryptoKeyVersions/1
191-
192- # Sign in with az CLI, use Azure Key Vault for signing in HTTP authentication
193- az login
194- mcp-publisher login http azure-key-vault -domain example.com -vault myvault -key mysigningkey
195-
196- ` )
197- }
198-
180+ var runLoginCommand = func (_ * cobra.Command , args []string ) error {
181+ var (
182+ signer auth.Signer
183+ err error
184+ )
199185 method := args [0 ]
200- flags , err := parseLoginFlags (method , args )
201- if err != nil {
202- return err
186+ flags .SignerType = NoSignerType
187+ if method == "http" || method == "dns" {
188+ if len (args ) > 1 {
189+ switch args [1 ] {
190+ case string (AzureKeyVaultSignerType ):
191+ flags .SignerType = AzureKeyVaultSignerType
192+ case string (GoogleKMSSignerType ):
193+ flags .SignerType = GoogleKMSSignerType
194+ }
195+ } else {
196+ flags .SignerType = InProcessSignerType
197+ }
203198 }
204199
205- var signer auth.Signer
206200 if flags .SignerType != NoSignerType {
207201 signer , err = createSigner (flags )
208202 if err != nil {
0 commit comments