config.go

 1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
 2//
 3// SPDX-License-Identifier: LicenseRef-MutuaL-1.2
 4
 5// Package config holds configuration for the SilverBullet MCP server,
 6// loaded from environment variables and command-line flags.
 7package config
 8
 9import (
10	"fmt"
11	"net/url"
12	"os"
13	"strconv"
14)
15
16// Config holds all configuration for the sb-mcp server.
17type Config struct {
18	// SBURL is the base URL of the SilverBullet instance (required).
19	SBURL string
20	// SBUser and SBPass are Basic Auth credentials (optional).
21	SBUser string
22	SBPass string
23	// SBToken is a Bearer token for authentication (optional).
24	SBToken string
25	// HTTPAddr is the address for streamable HTTP transport.
26	// Empty string means stdio transport.
27	HTTPAddr string
28	// DefaultTimeout is the default Lua execution timeout in seconds.
29	DefaultTimeout int
30}
31
32// Load reads configuration from environment variables.
33// SB_URL (required), SB_USER, SB_PASS, SB_TOKEN (optional).
34func Load() (*Config, error) {
35	sbURL := os.Getenv("SB_URL")
36	if sbURL == "" {
37		return nil, fmt.Errorf("SB_URL environment variable is required")
38	}
39
40	u, err := url.Parse(sbURL)
41	if err != nil || (u.Scheme != "http" && u.Scheme != "https") {
42		return nil, fmt.Errorf("SB_URL must be a valid HTTP(S) URL, got: %s", sbURL)
43	}
44
45	cfg := &Config{
46		SBURL:          sbURL,
47		SBUser:         os.Getenv("SB_USER"),
48		SBPass:         os.Getenv("SB_PASS"),
49		SBToken:        os.Getenv("SB_TOKEN"),
50		DefaultTimeout: parseDefaultTimeout(),
51	}
52
53	return cfg, nil
54}
55
56// HasBasicAuth returns true if both SB_USER and SB_PASS are set.
57func (c *Config) HasBasicAuth() bool {
58	return c.SBUser != "" && c.SBPass != ""
59}
60
61// HasBearerToken returns true if SB_TOKEN is set.
62func (c *Config) HasBearerToken() bool {
63	return c.SBToken != ""
64}
65
66// parseDefaultTimeout reads the default Lua execution timeout from
67// the SB_TIMEOUT environment variable (in seconds), defaulting to 120.
68func parseDefaultTimeout() int {
69	s := os.Getenv("SB_TIMEOUT")
70	if s == "" {
71		return 120
72	}
73	n, err := strconv.Atoi(s)
74	if err != nil || n < 1 {
75		return 120
76	}
77	return n
78}