diff --git a/cmd/mcpproxy/status_cmd.go b/cmd/mcpproxy/status_cmd.go
index 9cde5374..8448d283 100644
--- a/cmd/mcpproxy/status_cmd.go
+++ b/cmd/mcpproxy/status_cmd.go
@@ -21,16 +21,24 @@ import (
// StatusInfo holds the collected status data for display.
type StatusInfo struct {
- State string `json:"state"`
- ListenAddr string `json:"listen_addr"`
- Uptime string `json:"uptime,omitempty"`
- UptimeSeconds float64 `json:"uptime_seconds,omitempty"`
- APIKey string `json:"api_key"`
- WebUIURL string `json:"web_ui_url"`
- Servers *ServerCounts `json:"servers,omitempty"`
- SocketPath string `json:"socket_path,omitempty"`
- ConfigPath string `json:"config_path,omitempty"`
- Version string `json:"version,omitempty"`
+ State string `json:"state"`
+ Edition string `json:"edition"`
+ ListenAddr string `json:"listen_addr"`
+ Uptime string `json:"uptime,omitempty"`
+ UptimeSeconds float64 `json:"uptime_seconds,omitempty"`
+ APIKey string `json:"api_key"`
+ WebUIURL string `json:"web_ui_url"`
+ Servers *ServerCounts `json:"servers,omitempty"`
+ SocketPath string `json:"socket_path,omitempty"`
+ ConfigPath string `json:"config_path,omitempty"`
+ Version string `json:"version,omitempty"`
+ TeamsInfo *TeamsStatusInfo `json:"teams,omitempty"`
+}
+
+// TeamsStatusInfo holds teams-specific status information.
+type TeamsStatusInfo struct {
+ OAuthProvider string `json:"oauth_provider"`
+ AdminEmails []string `json:"admin_emails"`
}
// ServerCounts holds upstream server statistics.
@@ -151,11 +159,15 @@ func collectStatusFromDaemon(cfg *config.Config, socketPath, configPath string)
info := &StatusInfo{
State: "Running",
+ Edition: Edition,
APIKey: cfg.APIKey,
SocketPath: socketPath,
ConfigPath: configPath,
}
+ // Add teams info if available
+ info.TeamsInfo = collectTeamsInfo(cfg)
+
// Get status data (running, listen_addr, upstream_stats)
statusData, err := client.GetStatus(ctx)
if err != nil {
@@ -208,13 +220,18 @@ func collectStatusFromConfig(cfg *config.Config, socketPath, configPath string)
listenAddr = "127.0.0.1:8080"
}
- return &StatusInfo{
+ info := &StatusInfo{
State: "Not running",
+ Edition: Edition,
ListenAddr: listenAddr + " (configured)",
APIKey: cfg.APIKey,
WebUIURL: statusBuildWebUIURL(listenAddr, cfg.APIKey),
ConfigPath: configPath,
}
+
+ info.TeamsInfo = collectTeamsInfo(cfg)
+
+ return info
}
func extractServerCounts(stats map[string]interface{}) *ServerCounts {
@@ -321,6 +338,7 @@ func printStatusTable(info *StatusInfo) {
fmt.Println("MCPProxy Status")
fmt.Printf(" %-12s %s\n", "State:", info.State)
+ fmt.Printf(" %-12s %s\n", "Edition:", info.Edition)
if info.Version != "" {
fmt.Printf(" %-12s %s\n", "Version:", info.Version)
@@ -346,6 +364,13 @@ func printStatusTable(info *StatusInfo) {
if info.ConfigPath != "" {
fmt.Printf(" %-12s %s\n", "Config:", info.ConfigPath)
}
+
+ if info.TeamsInfo != nil {
+ fmt.Println()
+ fmt.Println("Teams")
+ fmt.Printf(" %-12s %s\n", "OAuth:", info.TeamsInfo.OAuthProvider)
+ fmt.Printf(" %-12s %s\n", "Admins:", strings.Join(info.TeamsInfo.AdminEmails, ", "))
+ }
}
func loadStatusConfig() (*config.Config, error) {
diff --git a/cmd/mcpproxy/status_teams.go b/cmd/mcpproxy/status_teams.go
new file mode 100644
index 00000000..f77755ce
--- /dev/null
+++ b/cmd/mcpproxy/status_teams.go
@@ -0,0 +1,18 @@
+//go:build teams
+
+package main
+
+import "github.com/smart-mcp-proxy/mcpproxy-go/internal/config"
+
+func collectTeamsInfo(cfg *config.Config) *TeamsStatusInfo {
+ if cfg.Teams == nil || !cfg.Teams.Enabled {
+ return nil
+ }
+ info := &TeamsStatusInfo{
+ AdminEmails: cfg.Teams.AdminEmails,
+ }
+ if cfg.Teams.OAuth != nil {
+ info.OAuthProvider = cfg.Teams.OAuth.Provider
+ }
+ return info
+}
diff --git a/cmd/mcpproxy/status_teams_stub.go b/cmd/mcpproxy/status_teams_stub.go
new file mode 100644
index 00000000..327de7e7
--- /dev/null
+++ b/cmd/mcpproxy/status_teams_stub.go
@@ -0,0 +1,9 @@
+//go:build !teams
+
+package main
+
+import "github.com/smart-mcp-proxy/mcpproxy-go/internal/config"
+
+func collectTeamsInfo(_ *config.Config) *TeamsStatusInfo {
+ return nil
+}
diff --git a/cmd/mcpproxy/teams_register.go b/cmd/mcpproxy/teams_register.go
index b464b418..d2647b0d 100644
--- a/cmd/mcpproxy/teams_register.go
+++ b/cmd/mcpproxy/teams_register.go
@@ -2,17 +2,10 @@
package main
-import (
- "log"
-
- "github.com/smart-mcp-proxy/mcpproxy-go/internal/teams"
-)
-
-func init() {
- // Initialize all registered teams features.
- // Individual feature packages (auth, workspace, etc.) register
- // themselves via their own init() functions.
- if err := teams.SetupAll(teams.Dependencies{}); err != nil {
- log.Fatalf("failed to initialize teams features: %v", err)
- }
-}
+// Teams features are registered via init() functions in their respective
+// packages. The actual setup happens when the server calls teams.SetupAll()
+// during HTTP server initialization (see internal/server/teams_wire.go).
+//
+// This file imports the teams package for its init() side effects,
+// which register feature modules in the teams registry.
+import _ "github.com/smart-mcp-proxy/mcpproxy-go/internal/teams"
diff --git a/frontend/src/App.vue b/frontend/src/App.vue
index 7b3e907a..babaa029 100644
--- a/frontend/src/App.vue
+++ b/frontend/src/App.vue
@@ -47,10 +47,12 @@ import ConnectionStatus from '@/components/ConnectionStatus.vue'
import AuthErrorModal from '@/components/AuthErrorModal.vue'
import { useSystemStore } from '@/stores/system'
import { useServersStore } from '@/stores/servers'
+import { useAuthStore } from '@/stores/auth'
import api, { type APIAuthEvent } from '@/services/api'
const systemStore = useSystemStore()
const serversStore = useServersStore()
+const authStore = useAuthStore()
// Authentication modal state
const authModal = reactive({
@@ -93,7 +95,10 @@ function handleAuthError(event: APIAuthEvent) {
authModal.show = true
}
-onMounted(() => {
+onMounted(async () => {
+ // Initialize auth state (needed for teams edition role-based nav)
+ await authStore.checkAuth()
+
// Set up API error listener
removeAPIListener = api.addEventListener(handleAuthError)
@@ -133,4 +138,4 @@ onUnmounted(() => {
opacity: 0;
transform: translateX(-10px);
}
-
\ No newline at end of file
+
diff --git a/frontend/src/components/SidebarNav.vue b/frontend/src/components/SidebarNav.vue
index bf899c4d..ddc6db76 100644
--- a/frontend/src/components/SidebarNav.vue
+++ b/frontend/src/components/SidebarNav.vue
@@ -6,25 +6,90 @@
- MCPProxy
+
+ MCPProxy
+ Teams
+
-