mcp-framework/docs/config.md

1.7 KiB

Config JSON

Le package config stocke une structure générique par profil dans un JSON privé pour l'utilisateur courant.

Exemple :

type Profile struct {
	BaseURL string `json:"base_url"`
	APIKey  string `json:"api_key"`
}

store := config.NewStore[Profile]("my-mcp")

cfg, path, err := store.LoadDefault()
if err != nil {
	return err
}

profileName := cli.ResolveProfileName(flagProfile, os.Getenv("MY_MCP_PROFILE"), cfg.CurrentProfile)
profile := cfg.Profiles[profileName]

profile.BaseURL = "https://api.example.com"
cfg.CurrentProfile = profileName
cfg.Profiles[profileName] = profile

_, err = store.SaveDefault(cfg)
if err != nil {
	return err
}

fmt.Printf("config saved to %s\n", path)

Notes :

  • le fichier est créé avec des permissions 0600
  • le répertoire parent est forcé en 0700
  • l'écriture est atomique via un fichier temporaire puis rename
  • si le fichier n'existe pas, Load et LoadDefault retournent une config vide par défaut
  • NewStoreWithOptions permet de définir une version cible, des migrations JSON (from -> to) et une validation explicite après chargement
  • une config plus récente que la version supportée, ou sans chemin de migration complet, retourne une erreur explicite

Exemple de store versionné :

store := config.NewStoreWithOptions[Profile]("my-mcp", config.Options[Profile]{
	Version: 2,
	Migrations: map[int]config.Migration{
		1: func(doc map[string]json.RawMessage) error {
			return nil
		},
	},
	Validator: func(cfg config.FileConfig[Profile]) []config.ValidationIssue {
		if cfg.CurrentProfile == "" {
			return []config.ValidationIssue{{
				Path:    "current_profile",
				Message: "must not be empty",
			}}
		}
		return nil
	},
})