We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/safedep/vet'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
package aitool
import (
"context"
"path/filepath"
"strings"
"github.com/safedep/vet/pkg/common/logger"
"github.com/safedep/vet/pkg/models"
"github.com/safedep/vet/pkg/readers"
)
// ideNameFromPath extracts the IDE name from an extensions.json path.
// e.g. "/home/user/.vscode/extensions/extensions.json" → "VS Code"
var ideDirNames = map[string]string{
".vscode": "VS Code",
".vscode-oss": "VSCodium",
".cursor": "Cursor",
".windsurf": "Windsurf",
}
const (
ideExtensionsApp = "ide_extensions"
ideExtensionsAppDisplay = "IDE Extensions"
)
type aiExtensionDiscoverer struct {
config DiscoveryConfig
}
// NewAIExtensionDiscoverer creates a discoverer that bridges the VSIX extension reader
// to find AI-specific IDE extensions.
func NewAIExtensionDiscoverer(config DiscoveryConfig) (AIToolReader, error) {
return &aiExtensionDiscoverer{config: config}, nil
}
func (d *aiExtensionDiscoverer) Name() string { return "AI IDE Extensions" }
func (d *aiExtensionDiscoverer) App() string { return ideExtensionsApp }
func (d *aiExtensionDiscoverer) EnumTools(_ context.Context, handler AIToolHandlerFn) error {
// IDE extensions are system-scoped; skip when system scope is not enabled
if !d.config.ScopeEnabled(AIToolScopeSystem) {
return nil
}
vsixReader, err := readers.NewVSIXExtReaderFromDefaultDistributions()
if err != nil {
logger.Debugf("No IDE extensions found: %v", err)
return nil
}
return vsixReader.EnumManifests(func(manifest *models.PackageManifest, pr readers.PackageReader) error {
return pr.EnumPackages(func(pkg *models.Package) error {
info, ok := knownAIExtensions[strings.ToLower(pkg.Name)]
if !ok {
return nil
}
tool := &AITool{
Name: info.DisplayName,
Type: AIToolTypeAIExtension,
Scope: AIToolScopeSystem,
App: ideExtensionsApp,
AppDisplay: ideExtensionsAppDisplay,
ConfigPath: manifest.GetPath(),
}
tool.ID = generateID(tool.App, string(tool.Type), string(tool.Scope), pkg.Name, tool.ConfigPath)
tool.SourceID = generateSourceID(tool.App, tool.ConfigPath)
tool.SetMeta("extension.id", pkg.Name)
tool.SetMeta("extension.version", pkg.Version)
tool.SetMeta("extension.ecosystem", manifest.Ecosystem)
if ide := ideNameFromPath(manifest.GetPath()); ide != "" {
tool.SetMeta("extension.ide", ide)
tool.AppDisplay = ide
}
return handler(tool)
})
})
}
func ideNameFromPath(configPath string) string {
// Walk up from extensions.json to find the IDE directory.
// Path pattern: ~/.vscode/extensions/extensions.json
dir := filepath.Dir(configPath) // .../extensions
dir = filepath.Dir(dir) // .../.vscode
base := filepath.Base(dir)
if name, ok := ideDirNames[base]; ok {
return name
}
return ""
}