This guide provides the implementation order and key files for each component.
- Backend: New Event Types (P1)
- Backend: Multi-Type Filter (P2)
- Web UI: Enable Activity Log Menu (P2)
- Web UI: Multi-Select Filter (P2)
- Web UI: Intent Column & Sorting (P2)
- CLI: Multi-Type Filter (P3)
- Documentation (P3)
- Testing & Validation
File: internal/storage/activity_models.go
const (
// Existing types...
ActivityTypeToolCall ActivityType = "tool_call"
ActivityTypePolicyDecision ActivityType = "policy_decision"
ActivityTypeQuarantineChange ActivityType = "quarantine_change"
ActivityTypeServerChange ActivityType = "server_change"
// NEW: Spec 024
ActivityTypeSystemStart ActivityType = "system_start"
ActivityTypeSystemStop ActivityType = "system_stop"
ActivityTypeInternalToolCall ActivityType = "internal_tool_call"
ActivityTypeConfigChange ActivityType = "config_change"
)File: internal/runtime/events.go
const (
// Existing...
// NEW: Spec 024
EventTypeActivitySystemStart EventType = "activity.system.start"
EventTypeActivitySystemStop EventType = "activity.system.stop"
EventTypeActivityInternalToolCall EventType = "activity.internal_tool_call.completed"
EventTypeActivityConfigChange EventType = "activity.config_change"
)File: internal/server/server.go
In StartServer() method after HTTP listener bind:
s.runtime.EmitActivitySystemStart(version, listenAddr, startupDurationMs, configPath)In Shutdown() method at the beginning:
s.runtime.EmitActivitySystemStop(reason, uptimeSeconds, errorMsg)File: internal/server/mcp.go
In each internal tool handler (handleRetrieveTools, handleCallToolRead, etc.):
p.emitActivityInternalToolCall(toolName, targetServer, targetTool, args, status, durationMs, intent)File: internal/runtime/activity_service.go
Subscribe to EventTypeServersChanged and create config_change activity records.
File: internal/storage/activity_models.go
type ActivityFilter struct {
Types []string // Changed from Type string
Server string
// ... rest unchanged
}Update Matches() method for OR logic.
File: internal/httpapi/activity.go
Parse comma-separated type parameter:
typeParam := r.URL.Query().Get("type")
if typeParam != "" {
filter.Types = strings.Split(typeParam, ",")
}File: frontend/src/components/SidebarNav.vue
Uncomment or add Activity Log menu item:
<router-link to="/activity" class="...">
<span>Activity Log</span>
</router-link>File: frontend/src/views/Activity.vue
Create multi-select dropdown component:
<div class="dropdown">
<label tabindex="0" class="btn btn-sm">
Event Type {{ selectedTypes.length > 0 ? `(${selectedTypes.length})` : '' }}
</label>
<ul class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-52">
<li v-for="type in eventTypes" :key="type">
<label class="label cursor-pointer">
<input type="checkbox" :value="type" v-model="selectedTypes" class="checkbox checkbox-sm" />
<span class="label-text">{{ type }}</span>
</label>
</li>
</ul>
</div>File: frontend/src/views/Activity.vue
Add column to table:
<th>Intent</th>
<!-- In row -->
<td>
<span v-if="activity.metadata?.intent" :title="activity.metadata.intent.reason">
{{ getIntentIcon(activity.metadata.intent.operation_type) }}
{{ truncate(activity.metadata.intent.reason, 30) }}
</span>
<span v-else>-</span>
</td>Add sort state and click handlers:
<th @click="sortBy('timestamp')" class="cursor-pointer">
Time {{ getSortIndicator('timestamp') }}
</th>File: cmd/mcpproxy/activity_cmd.go
Update type flag handling:
typeFlag, _ := cmd.Flags().GetString("type")
if typeFlag != "" {
types := strings.Split(typeFlag, ",")
for _, t := range types {
if !isValidActivityType(t) {
return fmt.Errorf("invalid type: %s. Valid types: %s", t, validTypesString)
}
}
params.Set("type", typeFlag)
}-
docs/features/activity-log.md- Add new event types to table
- Add examples for system_start, system_stop, internal_tool_call, config_change
-
docs/cli/activity-commands.md- Add multi-type filter examples
- Document valid event types
-
docs/web-ui/activity-log.md(create if needed)- Document multi-select filter
- Document Intent column
- Document sortable columns
go test ./internal/storage/... -v -run TestActivity
go test ./internal/runtime/... -v -run TestActivity
go test ./internal/httpapi/... -v -run TestActivity./scripts/test-api-e2e.sh- System Events: Start/stop MCPProxy and check activity log
- Internal Tools: Call retrieve_tools via MCP client
- Config Changes: Add/remove server via CLI
- Multi-Type Filter: Test API with
?type=tool_call,config_change - Web UI: Verify multi-select, Intent column, sorting
| Component | Files |
|---|---|
| Activity Types | internal/storage/activity_models.go |
| Event Types | internal/runtime/events.go |
| Event Emission | internal/server/server.go, internal/server/mcp.go |
| Event Handling | internal/runtime/activity_service.go |
| REST API | internal/httpapi/activity.go |
| CLI | cmd/mcpproxy/activity_cmd.go |
| Web UI | frontend/src/views/Activity.vue, frontend/src/components/SidebarNav.vue |
| Docs | docs/features/activity-log.md, docs/cli/activity-commands.md |