feat(core-agent): add mcp and serve commands
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
85f3a02361
commit
759bb9bcb7
4 changed files with 124 additions and 1 deletions
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"dappco.re/go/agent/pkg/agentic"
|
||||
"dappco.re/go/core"
|
||||
coremcp "forge.lthn.ai/core/mcp/pkg/mcp"
|
||||
)
|
||||
|
||||
type applicationCommandSet struct {
|
||||
|
|
@ -83,6 +84,16 @@ func registerApplicationCommands(c *core.Core) {
|
|||
Description: "Show all core.Env() keys and values",
|
||||
Action: commands.env,
|
||||
})
|
||||
|
||||
c.Command("mcp", core.Command{
|
||||
Description: "Start the MCP server on stdio",
|
||||
Action: commands.mcp,
|
||||
})
|
||||
|
||||
c.Command("serve", core.Command{
|
||||
Description: "Start the MCP server over HTTP",
|
||||
Action: commands.serve,
|
||||
})
|
||||
}
|
||||
|
||||
func (commands applicationCommandSet) version(_ core.Options) core.Result {
|
||||
|
|
@ -133,3 +144,57 @@ func (commands applicationCommandSet) env(_ core.Options) core.Result {
|
|||
}
|
||||
return core.Result{OK: true}
|
||||
}
|
||||
|
||||
func (commands applicationCommandSet) mcp(_ core.Options) core.Result {
|
||||
service, err := commands.mcpService()
|
||||
if err != nil {
|
||||
return core.Result{Value: err, OK: false}
|
||||
}
|
||||
if err := service.ServeStdio(commands.coreApp.Context()); err != nil {
|
||||
return core.Result{Value: core.E("main.mcp", "serve mcp stdio", err), OK: false}
|
||||
}
|
||||
return core.Result{OK: true}
|
||||
}
|
||||
|
||||
func (commands applicationCommandSet) serve(options core.Options) core.Result {
|
||||
service, err := commands.mcpService()
|
||||
if err != nil {
|
||||
return core.Result{Value: err, OK: false}
|
||||
}
|
||||
if err := service.ServeHTTP(commands.coreApp.Context(), commands.serveAddress(options)); err != nil {
|
||||
return core.Result{Value: core.E("main.serve", "serve mcp http", err), OK: false}
|
||||
}
|
||||
return core.Result{OK: true}
|
||||
}
|
||||
|
||||
func (commands applicationCommandSet) mcpService() (*coremcp.Service, error) {
|
||||
if commands.coreApp == nil {
|
||||
return nil, core.E("main.mcpService", "core is required", nil)
|
||||
}
|
||||
|
||||
result := commands.coreApp.Service("mcp")
|
||||
if !result.OK {
|
||||
return nil, core.E("main.mcpService", "mcp service not registered", nil)
|
||||
}
|
||||
|
||||
service, ok := result.Value.(*coremcp.Service)
|
||||
if !ok || service == nil {
|
||||
return nil, core.E("main.mcpService", "mcp service has invalid type", nil)
|
||||
}
|
||||
|
||||
return service, nil
|
||||
}
|
||||
|
||||
func (commands applicationCommandSet) serveAddress(options core.Options) string {
|
||||
address := options.String("addr")
|
||||
if address == "" {
|
||||
address = options.String("_arg")
|
||||
}
|
||||
if address == "" {
|
||||
address = core.Env("CORE_AGENT_HTTP_ADDR")
|
||||
}
|
||||
if address == "" {
|
||||
address = coremcp.DefaultHTTPAddr
|
||||
}
|
||||
return address
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ func Example_registerApplicationCommands() {
|
|||
registerApplicationCommands(c)
|
||||
|
||||
core.Println(len(c.Commands()))
|
||||
// Output: 3
|
||||
// Output: 5
|
||||
}
|
||||
|
||||
func Example_applyLogLevel() {
|
||||
|
|
|
|||
|
|
@ -113,6 +113,8 @@ func TestCommands_RegisterApplicationCommands_Good(t *testing.T) {
|
|||
assert.Contains(t, cmds, "version")
|
||||
assert.Contains(t, cmds, "check")
|
||||
assert.Contains(t, cmds, "env")
|
||||
assert.Contains(t, cmds, "mcp")
|
||||
assert.Contains(t, cmds, "serve")
|
||||
}
|
||||
|
||||
func TestCommands_Version_Good(t *testing.T) {
|
||||
|
|
@ -169,6 +171,60 @@ func TestCommands_Env_Good(t *testing.T) {
|
|||
assert.True(t, r.OK)
|
||||
}
|
||||
|
||||
func TestCommands_MCPService_Good(t *testing.T) {
|
||||
c := core.New(
|
||||
core.WithOption("name", "core-agent"),
|
||||
core.WithService(registerMCPService),
|
||||
)
|
||||
registerApplicationCommands(c)
|
||||
|
||||
service, err := (applicationCommandSet{coreApp: c}).mcpService()
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, service)
|
||||
}
|
||||
|
||||
func TestCommands_MCPService_Bad(t *testing.T) {
|
||||
_, err := (applicationCommandSet{coreApp: newTestCore(t)}).mcpService()
|
||||
assert.EqualError(t, err, "main.mcpService: mcp service not registered")
|
||||
}
|
||||
|
||||
func TestCommands_MCPService_Ugly(t *testing.T) {
|
||||
c := core.New(core.WithOption("name", "core-agent"))
|
||||
assert.True(t, c.RegisterService("mcp", "invalid").OK)
|
||||
|
||||
_, err := (applicationCommandSet{coreApp: c}).mcpService()
|
||||
assert.EqualError(t, err, "main.mcpService: mcp service has invalid type")
|
||||
}
|
||||
|
||||
func TestCommands_ServeAddress_Good(t *testing.T) {
|
||||
c := newTestCore(t)
|
||||
|
||||
addr := (applicationCommandSet{coreApp: c}).serveAddress(core.NewOptions(
|
||||
core.Option{Key: "addr", Value: "0.0.0.0:9201"},
|
||||
))
|
||||
|
||||
assert.Equal(t, "0.0.0.0:9201", addr)
|
||||
}
|
||||
|
||||
func TestCommands_ServeAddress_Bad(t *testing.T) {
|
||||
c := newTestCore(t)
|
||||
t.Setenv("CORE_AGENT_HTTP_ADDR", "")
|
||||
|
||||
addr := (applicationCommandSet{coreApp: c}).serveAddress(core.NewOptions())
|
||||
|
||||
assert.Equal(t, "127.0.0.1:9101", addr)
|
||||
}
|
||||
|
||||
func TestCommands_ServeAddress_Ugly(t *testing.T) {
|
||||
c := newTestCore(t)
|
||||
|
||||
addr := (applicationCommandSet{coreApp: c}).serveAddress(core.NewOptions(
|
||||
core.Option{Key: "_arg", Value: "127.0.0.1:9911"},
|
||||
))
|
||||
|
||||
assert.Equal(t, "127.0.0.1:9911", addr)
|
||||
}
|
||||
|
||||
func TestCommands_CliUnknown_Bad(t *testing.T) {
|
||||
c := newTestCore(t)
|
||||
r := c.Cli().Run("nonexistent")
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ func TestMain_NewCoreAgent_Good(t *testing.T) {
|
|||
assert.Contains(t, c.Commands(), "version")
|
||||
assert.Contains(t, c.Commands(), "check")
|
||||
assert.Contains(t, c.Commands(), "env")
|
||||
assert.Contains(t, c.Commands(), "mcp")
|
||||
assert.Contains(t, c.Commands(), "serve")
|
||||
assert.Contains(t, c.Actions(), "process.run")
|
||||
|
||||
service := c.Service("agentic")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue