feat(core-agent): add mcp and serve commands

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-03-31 11:10:27 +00:00
parent 85f3a02361
commit 759bb9bcb7
4 changed files with 124 additions and 1 deletions

View file

@ -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
}

View file

@ -11,7 +11,7 @@ func Example_registerApplicationCommands() {
registerApplicationCommands(c)
core.Println(len(c.Commands()))
// Output: 3
// Output: 5
}
func Example_applyLogLevel() {

View file

@ -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")

View file

@ -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")