mcp-framework/docs/secrets.md

3.3 KiB

Secrets

Le package secretstore supporte plusieurs politiques de backend :

  • auto : comportement par défaut, utilise un backend keyring disponible et peut retomber sur l'environnement si LookupEnv est fourni
  • kwallet-only : impose KWallet et retourne une erreur explicite si KWallet n'est pas disponible
  • keyring-any : impose l'utilisation d'un backend keyring disponible
  • env-only : lecture seule depuis les variables d'environnement
  • bitwarden-cli : utilise le CLI Bitwarden (bw) comme backend de vault

Backends keyring typiques :

  • macOS : Keychain
  • Linux : Secret Service ou KWallet selon l'environnement
  • Windows : Credential Manager

Ouverture recommandée depuis la policy du manifeste runtime (mcp.toml résolu près de l'exécutable) :

store, err := secretstore.OpenFromManifest(secretstore.OpenFromManifestOptions{
	ServiceName: "my-mcp",
	LookupEnv:   os.LookupEnv,
})
if err != nil {
	return err
}

Exemple bas niveau :

store, err := secretstore.Open(secretstore.Options{
	ServiceName:   "my-mcp",
	BackendPolicy: secretstore.BackendAuto,
})
if err != nil {
	return err
}

if err := store.SetSecret("api-token", "My MCP API token", token); err != nil {
	return err
}

token, err = store.GetSecret("api-token")
switch {
case err == nil:
	// secret found
case errors.Is(err, secretstore.ErrNotFound):
	// first run
default:
	return err
}

Pour imposer KWallet sur Linux :

store, err := secretstore.Open(secretstore.Options{
	ServiceName:   "email-mcp",
	BackendPolicy: secretstore.BackendKWalletOnly,
})

Pour imposer Bitwarden via son CLI :

store, err := secretstore.Open(secretstore.Options{
	ServiceName:   "email-mcp",
	BackendPolicy: secretstore.BackendBitwardenCLI,
	// Optionnel si `bw` n'est pas dans le PATH :
	// BitwardenCommand: "/usr/local/bin/bw",
})

Pour vérifier explicitement que Bitwarden est prêt (login + unlock + BW_SESSION) :

if err := secretstore.EnsureBitwardenReady(secretstore.Options{
	BitwardenCommand: "bw",
	LookupEnv:        os.LookupEnv,
}); err != nil {
	switch {
	case errors.Is(err, secretstore.ErrBWNotLoggedIn):
		// guider vers `bw login`
	case errors.Is(err, secretstore.ErrBWLocked):
		// guider vers `bw unlock --raw` puis export BW_SESSION
	default:
		// indisponibilité CLI/réseau
	}
	return err
}

Pour stocker un secret structuré en JSON :

type Credentials struct {
	Host     string `json:"host"`
	Username string `json:"username"`
	Password string `json:"password"`
}

err = secretstore.SetJSON(store, "imap-credentials", "IMAP credentials", Credentials{
	Host:     "imap.example.com",
	Username: "alice",
	Password: token,
})
if err != nil {
	return err
}

creds, err := secretstore.GetJSON[Credentials](store, "imap-credentials")
if err != nil {
	return err
}
_ = creds

Pour écrire puis confirmer immédiatement une relecture :

if err := secretstore.SetSecretVerified(store, "api-token", "My MCP API token", token); err != nil {
	return err
}

Pour connaître le backend effectif utilisé :

effective := secretstore.EffectiveBackendPolicy(store)
fmt.Println("backend effectif:", effective) // bitwarden-cli, env-only, keyring-any...

En mode env-only, GetSecret("API_TOKEN") lit la variable d'environnement API_TOKEN. Les opérations d'écriture et de suppression retournent secretstore.ErrReadOnly.