Skip to content

Commit a0bd3cd

Browse files
committed
Add support for Composer
1 parent 75f1c16 commit a0bd3cd

File tree

4 files changed

+47
-38
lines changed

4 files changed

+47
-38
lines changed

local/mcp/app.go

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ package mcp
2222
import (
2323
"bytes"
2424
"encoding/json"
25+
"strings"
2526

2627
"github.com/pkg/errors"
2728
"github.com/symfony-cli/symfony-cli/local/php"
@@ -59,27 +60,18 @@ type option struct {
5960
Default interface{} `json:"default"`
6061
}
6162

62-
func NewApp(projectDir string) (*Application, error) {
63-
app, err := parseApplication(projectDir)
64-
if err != nil {
65-
return nil, err
66-
}
67-
68-
return app, nil
69-
}
70-
71-
func parseApplication(projectDir string) (*Application, error) {
63+
func NewApp(projectDir string, args []string) (*Application, error) {
64+
args = append(args, "list", "--format=json")
7265
var buf bytes.Buffer
73-
var bufErr bytes.Buffer
7466
e := &php.Executor{
7567
BinName: "php",
7668
Dir: projectDir,
77-
Args: []string{"php", "bin/console", "list", "--format=json"},
69+
Args: args,
7870
Stdout: &buf,
79-
Stderr: &bufErr,
71+
Stderr: &buf,
8072
}
8173
if ret := e.Execute(false); ret != 0 {
82-
return nil, errors.Errorf("unable to list commands: %s\n%s", bufErr.String(), buf.String())
74+
return nil, errors.Errorf("unable to list commands (%s):\n%s", strings.Join(args, " "), buf.String())
8375
}
8476

8577
// Fix PHP types

local/mcp/server.go

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ import (
3333

3434
type MCP struct {
3535
server *server.MCPServer
36-
app *Application
36+
apps map[string]*Application
37+
appArgs map[string][]string
3738
projectDir string
3839
}
3940

@@ -61,6 +62,7 @@ var excludedOptions = map[string]bool{
6162
func NewServer(projectDir string) (*MCP, error) {
6263
mcp := &MCP{
6364
projectDir: projectDir,
65+
apps: map[string]*Application{},
6466
}
6567

6668
mcp.server = server.NewMCPServer(
@@ -70,21 +72,36 @@ func NewServer(projectDir string) (*MCP, error) {
7072
server.WithResourceCapabilities(true, true),
7173
)
7274

73-
var err error
74-
mcp.app, err = NewApp(projectDir)
75-
if err != nil {
76-
return nil, err
75+
mcp.appArgs = map[string][]string{
76+
"symfony": {"php", "bin/console"},
77+
// "cloud": {"run", "upsun"},
7778
}
78-
for _, command := range mcp.app.Commands {
79-
if _, ok := excludedCommands[command.Name]; ok {
80-
continue
81-
}
82-
if command.Hidden {
83-
continue
84-
}
85-
if err := mcp.addTool(command); err != nil {
79+
80+
e := &php.Executor{
81+
Dir: projectDir,
82+
BinName: "php",
83+
}
84+
if composerPath, err := e.FindComposer(""); err == nil {
85+
mcp.appArgs["composer"] = []string{"php", composerPath}
86+
}
87+
88+
for name, args := range mcp.appArgs {
89+
var err error
90+
mcp.apps[name], err = NewApp(projectDir, args)
91+
if err != nil {
8692
return nil, err
8793
}
94+
for _, command := range mcp.apps[name].Commands {
95+
if _, ok := excludedCommands[command.Name]; ok {
96+
continue
97+
}
98+
if command.Hidden {
99+
continue
100+
}
101+
if err := mcp.addTool(name, command); err != nil {
102+
return nil, err
103+
}
104+
}
88105
}
89106

90107
return mcp, nil
@@ -94,7 +111,7 @@ func (p *MCP) Start() error {
94111
return server.ServeStdio(p.server)
95112
}
96113

97-
func (p *MCP) addTool(cmd command) error {
114+
func (p *MCP) addTool(appName string, cmd command) error {
98115
toolOptions := []mcp.ToolOption{}
99116
toolOptions = append(toolOptions, mcp.WithDescription(cmd.Description+"\n\n"+cmd.Help))
100117
for name, arg := range cmd.Definition.Arguments {
@@ -120,7 +137,7 @@ func (p *MCP) addTool(cmd command) error {
120137
}
121138
}
122139

123-
toolName := strings.ReplaceAll(cmd.Name, ":", "-")
140+
toolName := appName + "--" + strings.ReplaceAll(cmd.Name, ":", "-")
124141
regexp := regexp.MustCompile(`^[a-zA-Z0-9_-]{1,64}$`)
125142
if !regexp.MatchString(toolName) {
126143
return fmt.Errorf("invalid command name: %s", cmd.Name)
@@ -159,14 +176,14 @@ func (p *MCP) addTool(cmd command) error {
159176
}
160177
executorArgs = append(executorArgs, "--no-ansi")
161178
executorArgs = append(executorArgs, "--no-interaction")
162-
e, err := php.SymfonyConsoleExecutor(p.projectDir, executorArgs)
163-
if err != nil {
164-
return nil, err
165-
}
166-
e.Dir = p.projectDir
167179
var buf bytes.Buffer
168-
e.Stdout = &buf
169-
e.Stderr = &buf
180+
e := &php.Executor{
181+
BinName: "php",
182+
Dir: p.projectDir,
183+
Args: append(p.appArgs[appName], executorArgs...),
184+
Stdout: &buf,
185+
Stderr: &buf,
186+
}
170187
if ret := e.Execute(false); ret != 0 {
171188
return mcp.NewToolResultError(fmt.Sprintf("Error running %s (exit code: %d)\n%s", strings.Join(executorArgs, " "), ret, buf.String())), nil
172189
}

local/php/composer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func Composer(dir string, args, env []string, stdout, stderr, logger io.Writer,
7373
if composerVersion() == 2 {
7474
composerBin = "composer2"
7575
}
76-
path, err := e.findComposer(composerBin)
76+
path, err := e.FindComposer(composerBin)
7777
if err != nil || !isPHPScript(path) {
7878
fmt.Fprintln(logger, " WARNING: Unable to find Composer, downloading one. It is recommended to install Composer yourself at https://getcomposer.org/download/")
7979
// we don't store it under bin/ to avoid it being found by findComposer as we want to only use it as a fallback

local/php/executor.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ func cleanupStaleTemporaryDirectories(mainLogger zerolog.Logger, doneCh chan<- b
390390
}
391391

392392
// Find composer depending on the configuration
393-
func (e *Executor) findComposer(extraBin string) (string, error) {
393+
func (e *Executor) FindComposer(extraBin string) (string, error) {
394394
if scriptDir, err := e.DetectScriptDir(); err == nil {
395395
for _, file := range []string{extraBin, "composer.phar", "composer"} {
396396
path := filepath.Join(scriptDir, file)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy