Skip to content

Commit 4b83e33

Browse files
committed
feat: Implement database integration and event handling for MCP servers
- Added SQLite database support for managing MCP servers and tools. - Introduced event bus for handling server addition, removal, and tool updates. - Created backend service for CRUD operations on MCP servers. - Implemented updater service for periodic polling of MCP servers and fetching tools. - Added API handlers for managing MCP servers and exporting configuration. - Included tests for backend service and database interactions. This commit establishes the foundational architecture for the agent-browser application, enabling dynamic management of MCP servers and their associated tools.
1 parent 59246b9 commit 4b83e33

File tree

19 files changed

+2726
-23
lines changed

19 files changed

+2726
-23
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*.dll
55
*.so
66
*.dylib
7-
agent-browser
7+
*.db
88

99
# Test binary, built with `go test -c`
1010
*.test

cmd/agent-browser/main.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"github.com/co-browser/agent-browser/internal/log"
66
"go.uber.org/fx"
77
"go.uber.org/fx/fxevent"
8-
// No longer need context, errors, net/http, or log imports directly here
98
)
109

1110
func main() {
@@ -14,12 +13,11 @@ func main() {
1413
fxApp := fx.New(
1514
app.CoreModules,
1615

17-
// Configure Fx to use our custom zerolog logger
16+
// Configure Fx to use our custom log.Logger via the adapter
1817
fx.WithLogger(func(logger log.Logger) fxevent.Logger {
1918
// Use the adapter we created
2019
return log.NewFxZerologAdapter(logger)
2120
}),
22-
// Remove old comment: // Add fx.NopLogger() here for quiet startup, or fx.WithLogger(...) for custom fx logging
2321
)
2422

2523
// Run the application.

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ require (
1111
require (
1212
github.com/mattn/go-colorable v0.1.13 // indirect
1313
github.com/mattn/go-isatty v0.0.20 // indirect
14+
github.com/mattn/go-sqlite3 v1.14.27 // indirect
1415
go.uber.org/dig v1.18.0 // indirect
1516
go.uber.org/multierr v1.10.0 // indirect
1617
go.uber.org/zap v1.26.0 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
1212
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
1313
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
1414
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
15+
github.com/mattn/go-sqlite3 v1.14.27 h1:drZCnuvf37yPfs95E5jd9s3XhdVWLal+6BOK6qrv6IU=
16+
github.com/mattn/go-sqlite3 v1.14.27/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
1517
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
1618
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
1719
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=

internal/app/app.go

Lines changed: 87 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,70 +2,138 @@
22
package app
33

44
import (
5+
"context"
6+
"net/http"
7+
"time"
8+
9+
"github.com/co-browser/agent-browser/internal/backend"
10+
"github.com/co-browser/agent-browser/internal/backend/database"
11+
"github.com/co-browser/agent-browser/internal/config"
12+
"github.com/co-browser/agent-browser/internal/events"
513
"github.com/co-browser/agent-browser/internal/log"
14+
"github.com/co-browser/agent-browser/internal/mcp/client"
15+
"github.com/co-browser/agent-browser/internal/updater"
616
"github.com/co-browser/agent-browser/internal/web"
717
"github.com/co-browser/agent-browser/internal/web/handlers"
18+
819
"go.uber.org/fx"
920
)
1021

1122
// CoreModules bundles the main application components for fx.
1223
var CoreModules = fx.Options(
13-
CommonModule,
24+
LogModule,
25+
DatabaseModule,
1426
ConfigModule,
27+
EventsModule,
1528
BackendModule,
16-
MCPModule,
29+
MCPClientModule,
1730
UpdaterModule,
1831
WebModule,
19-
// Add other core modules like SyncModule if needed
32+
// TODO: Add MCP Server Frontend module
33+
// TODO: Add Sync Daemon module
2034
)
2135

22-
// CommonModule provides common dependencies like logging.
23-
var CommonModule = fx.Module("common",
36+
// LogModule provides common dependencies like logging.
37+
var LogModule = fx.Module("logger",
2438
fx.Provide(
2539
log.NewLogger,
2640
),
2741
)
2842

43+
// DatabaseModule provides the database dependency.
44+
var DatabaseModule = fx.Module("database",
45+
fx.Provide(
46+
func(lc fx.Lifecycle, logger log.Logger) (database.DBInterface, error) {
47+
dbPath := "agent-browser.db"
48+
db, err := database.New(dbPath)
49+
if err != nil {
50+
logger.Error().Err(err).Str("dbPath", dbPath).Msg("Failed to initialize database")
51+
return nil, err
52+
}
53+
54+
lc.Append(fx.Hook{
55+
OnStop: func(ctx context.Context) error {
56+
logger.Info().Msg("Closing database connection...")
57+
return db.Close()
58+
},
59+
})
60+
logger.Info().Str("dbPath", dbPath).Msg("Database initialized")
61+
return db, nil
62+
},
63+
),
64+
)
65+
2966
// ConfigModule provides configuration loading services.
3067
var ConfigModule = fx.Module("config",
3168
fx.Provide(
32-
// config.NewConfigLoader, // Example placeholder
69+
config.NewExporter,
3370
),
3471
)
3572

36-
// BackendModule provides the backend service and its dependencies (like DB).
73+
// EventsModule provides the event bus.
74+
var EventsModule = fx.Module("events",
75+
fx.Provide(events.NewBus),
76+
)
77+
78+
// BackendModule provides the backend service.
3779
var BackendModule = fx.Module("backend",
3880
fx.Provide(
39-
// backend.NewDB, // Example placeholder
40-
// backend.NewService, // Example placeholder
81+
func(db database.DBInterface, bus events.Bus, logger log.Logger) backend.Service {
82+
return backend.NewService(db, bus, logger)
83+
},
4184
),
4285
)
4386

44-
// MCPModule provides the MCP server frontend and its dependencies.
45-
var MCPModule = fx.Module("mcp",
87+
// MCPClientModule provides the MCP client (distinct from server frontend).
88+
var MCPClientModule = fx.Module("mcp_client",
4689
fx.Provide(
47-
// mcp.NewClient, // Example placeholder
48-
// mcp.NewServer, // Example placeholder
90+
client.NewHTTPClient,
4991
),
5092
)
5193

5294
// UpdaterModule provides the tool and server updater service.
5395
var UpdaterModule = fx.Module("updater",
5496
fx.Provide(
55-
// updater.NewService, // Example placeholder
97+
func(bs backend.Service, mc client.Client, bus events.Bus, logger log.Logger) updater.Service {
98+
pollInterval := 5 * time.Minute
99+
logger.Info().Dur("pollInterval", pollInterval).Msg("Creating Updater Service")
100+
return updater.NewService(bs, mc, bus, logger, pollInterval)
101+
},
56102
),
103+
fx.Invoke(func(lc fx.Lifecycle, us updater.Service, logger log.Logger) {
104+
lc.Append(fx.Hook{
105+
OnStart: func(ctx context.Context) error {
106+
logger.Info().Msg("Registering Updater Service start hook")
107+
us.Start(ctx)
108+
return nil
109+
},
110+
OnStop: func(ctx context.Context) error {
111+
logger.Info().Msg("Registering Updater Service stop hook")
112+
us.Stop()
113+
return nil
114+
},
115+
})
116+
}),
57117
)
58118

59-
// WebModule provides the web server, UI handlers, and API handlers.
119+
// WebModule provides the web server components
60120
var WebModule = fx.Module("web",
61121
fx.Provide(
122+
// Provide UI handler
62123
handlers.NewUIHandler,
63-
// handlers.NewAPIHandler,
124+
// Provide API handlers
125+
func(bs backend.Service, us updater.Service, ce *config.Exporter, logger log.Logger) *handlers.APIHandlers {
126+
return handlers.NewAPIHandlers(bs, us, ce, logger)
127+
},
128+
// Provide HTTP mux using web package
64129
web.NewMux,
130+
// Provide HTTP server using web package
65131
web.NewServer,
66132
),
133+
// Register API handlers with the router
134+
fx.Invoke(func(router *http.ServeMux, apiHandlers *handlers.APIHandlers) {
135+
apiHandlers.RegisterRoutes(router)
136+
}),
137+
// Register web server lifecycle hooks
67138
fx.Invoke(web.RegisterWebServerHooks),
68139
)
69-
70-
// --- Placeholders for other modules like Sync ---
71-
// var SyncModule = fx.Module("sync", ...)

0 commit comments

Comments
 (0)