Skip to content

Commit ce2171d

Browse files
authored
fix: detect server subfolder in init (#566)
<!-- Provide a brief summary of your changes --> ## Motivation and Context Discussion from this issue: #538 We want to make it clearer that repo name & server name do not HAVE to be the same, especially in monorepos. @tadasant this seems like a minor thing that doesn't have to be documented specifically, lmk if you disagree :) ## How Has This Been Tested? Tested the init flow locally, running the built `init` command from a subfolder and the repo root. ## Breaking Changes No ## Types of changes <!-- What types of changes does your code introduce? Put an `x` in all the boxes that apply: --> - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist <!-- Go over all the following points, and put an `x` in all the boxes that apply. --> - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed ## Additional context <!-- Add any other context, implementation notes, or design decisions -->
1 parent 73d2174 commit ce2171d

File tree

1 file changed

+87
-19
lines changed

1 file changed

+87
-19
lines changed

cmd/publisher/commands/init.go

Lines changed: 87 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@ func InitCommand() error {
2121
return errors.New("server.json already exists")
2222
}
2323

24+
// Detect if we're in a subdirectory of the git repository
25+
subfolder := detectSubfolder()
26+
2427
// Try to detect values from environment
25-
name := detectServerName()
28+
name := detectServerName(subfolder)
2629
description := detectDescription()
2730
version := "1.0.0"
2831
repoURL := detectRepoURL()
@@ -55,7 +58,7 @@ func InitCommand() error {
5558

5659
// Create the server structure
5760
server := createServerJSON(
58-
name, description, version, repoURL, repoSource,
61+
name, description, version, repoURL, repoSource, subfolder,
5962
packageType, packageIdentifier, version, envVars,
6063
)
6164

@@ -82,6 +85,50 @@ func InitCommand() error {
8285
return nil
8386
}
8487

88+
func detectSubfolder() string {
89+
// Get current working directory
90+
cwd, err := os.Getwd()
91+
if err != nil {
92+
return ""
93+
}
94+
95+
// Find git repository root
96+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
97+
defer cancel()
98+
cmd := exec.CommandContext(ctx, "git", "rev-parse", "--show-toplevel")
99+
cmd.Dir = cwd
100+
output, err := cmd.Output()
101+
if err != nil {
102+
// Not in a git repository
103+
return ""
104+
}
105+
106+
gitRoot := strings.TrimSpace(string(output))
107+
108+
// Clean the paths to ensure proper comparison
109+
gitRoot = filepath.Clean(gitRoot)
110+
cwd = filepath.Clean(cwd)
111+
112+
// If we're in the root, no subfolder
113+
if gitRoot == cwd {
114+
return ""
115+
}
116+
117+
// Check if cwd is actually within gitRoot
118+
if !strings.HasPrefix(cwd, gitRoot) {
119+
return ""
120+
}
121+
122+
// Calculate relative path from git root to current directory
123+
relPath, err := filepath.Rel(gitRoot, cwd)
124+
if err != nil {
125+
return ""
126+
}
127+
128+
// Convert to forward slashes for consistency (important for cross-platform)
129+
return filepath.ToSlash(relPath)
130+
}
131+
85132
func getNameFromPackageJSON() string {
86133
data, err := os.ReadFile("package.json")
87134
if err != nil {
@@ -109,18 +156,13 @@ func getNameFromPackageJSON() string {
109156
return fmt.Sprintf("io.github.<your-username>/%s", name)
110157
}
111158

112-
func detectServerName() string {
159+
func detectServerName(subfolder string) string {
113160
// Try to get from git remote
114161
repoURL := detectRepoURL()
115-
if repoURL != "" {
116-
// Extract owner/repo from GitHub URL
117-
if strings.Contains(repoURL, "github.com") {
118-
parts := strings.Split(repoURL, "/")
119-
if len(parts) >= 5 {
120-
owner := parts[3]
121-
repo := strings.TrimSuffix(parts[4], ".git")
122-
return fmt.Sprintf("io.github.%s/%s", owner, repo)
123-
}
162+
if repoURL != "" && strings.Contains(repoURL, "github.com") {
163+
name := buildGitHubServerName(repoURL, subfolder)
164+
if name != "" {
165+
return name
124166
}
125167
}
126168

@@ -138,6 +180,24 @@ func detectServerName() string {
138180
return "com.example/my-mcp-server"
139181
}
140182

183+
func buildGitHubServerName(repoURL, subfolder string) string {
184+
parts := strings.Split(repoURL, "/")
185+
if len(parts) < 5 {
186+
return ""
187+
}
188+
189+
owner := parts[3]
190+
repo := strings.TrimSuffix(parts[4], ".git")
191+
192+
// If we're in a subdirectory, use the current folder name
193+
if subfolder != "" {
194+
folderName := filepath.Base(subfolder)
195+
return fmt.Sprintf("io.github.%s/%s", owner, folderName)
196+
}
197+
198+
return fmt.Sprintf("io.github.%s/%s", owner, repo)
199+
}
200+
141201
func detectDescription() string {
142202
// Try to get from package.json
143203
if data, err := os.ReadFile("package.json"); err == nil {
@@ -263,7 +323,7 @@ func detectPackageIdentifier(serverName string, packageType string) string {
263323
}
264324

265325
func createServerJSON(
266-
name, description, version, repoURL, repoSource,
326+
name, description, version, repoURL, repoSource, subfolder,
267327
packageType, packageIdentifier, packageVersion string,
268328
envVars []model.KeyValueInput,
269329
) apiv0.ServerJSON {
@@ -326,16 +386,24 @@ func createServerJSON(
326386
}
327387
}
328388

389+
// Create repository with optional subfolder
390+
repo := model.Repository{
391+
URL: repoURL,
392+
Source: repoSource,
393+
}
394+
395+
// Only set subfolder if we're actually in a subdirectory
396+
if subfolder != "" {
397+
repo.Subfolder = subfolder
398+
}
399+
329400
// Create server structure
330401
return apiv0.ServerJSON{
331402
Schema: model.CurrentSchemaURL,
332403
Name: name,
333404
Description: description,
334-
Repository: model.Repository{
335-
URL: repoURL,
336-
Source: repoSource,
337-
},
338-
Version: version,
339-
Packages: []model.Package{pkg},
405+
Repository: repo,
406+
Version: version,
407+
Packages: []model.Package{pkg},
340408
}
341409
}

0 commit comments

Comments
 (0)