feat(UI plugins): Kanban MCP task-boards …#2054
Open
dimetron wants to merge 2 commits into
Open
Conversation
48ab832 to
5b6503d
Compare
…kagent-dev#2048) Add go/plugins/kanban-mcp: a self-contained MCP server exposing task/board/ subtask/attachment tools for agents, with dual SQLite/Postgres support, embedded migrations, an embedded board SPA, a real-time task-progress MCP app, and SSE live updates. Add contrib/plugins/kanban-mcp Helm chart that deploys it and registers its web UI as a kagent plugin via RemoteMCPServer.spec.ui. Depends conceptually on kagent-dev#2047 (plugin registration) and kagent-dev#2046 (chat MCP UI widget); this PR is self-contained and builds independently. Includes design/EP-2048-kanban-mcp-plugin.md. Signed-off-by: Dmytro Rashko <dmitriy.rashko@amdocs.com>
5b6503d to
e72e4d7
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR introduces a new self-contained Kanban MCP server plugin (go/plugins/kanban-mcp) that provides task/board/subtask/attachment tooling for agents, plus an embedded board UI (served from the same binary) and an in-chat MCP App “task progress” widget. It also adds deployment artifacts (Docker + Helm) and design/spec documentation to ship it as a kagent UI plugin via RemoteMCPServer.spec.ui.
Changes:
- Add kanban-mcp server wiring for MCP over Streamable HTTP (
/mcp), SSE updates (/events), REST API (/api/*), and embedded SPA UI (/). - Add Postgres-backed persistence with embedded migrations, sqlc-generated query layer, and service logic (boards, subtasks, attachments/attributes, progress computation).
- Add deployment and docs: Dockerfile + compose, Helm chart, EP/design doc, and MCP App contract documentation.
Reviewed changes
Copilot reviewed 62 out of 69 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| go/plugins/kanban-mcp/server.go | HTTP mux wiring for MCP/SSE/REST/UI |
| go/plugins/kanban-mcp/server_test.go | End-to-end HTTP wiring tests |
| go/plugins/kanban-mcp/main.go | Binary entrypoint (stdio + HTTP modes) |
| go/plugins/kanban-mcp/internal/ui/task_progress.html | Embedded MCP App widget (task progress) |
| go/plugins/kanban-mcp/internal/ui/embed.go | go:embed UI assets + readonly rewrite |
| go/plugins/kanban-mcp/internal/ui/embed_test.go | UI embed + readonly rewrite tests |
| go/plugins/kanban-mcp/internal/sse/hub.go | SSE hub + subscription/broadcast logic |
| go/plugins/kanban-mcp/internal/sse/hub_test.go | SSE hub unit tests |
| go/plugins/kanban-mcp/internal/service/progress.go | Progress computation for widget output |
| go/plugins/kanban-mcp/internal/service/progress_test.go | Progress computation tests |
| go/plugins/kanban-mcp/internal/service/board_service.go | Board CRUD + normalization |
| go/plugins/kanban-mcp/internal/service/board_service_test.go | Board behavior tests |
| go/plugins/kanban-mcp/internal/service/attachment_service_test.go | Attachment + attribute behavior tests |
| go/plugins/kanban-mcp/internal/seed/seed.go | Board seeding from inline/file JSON |
| go/plugins/kanban-mcp/internal/seed/seed_test.go | Seed parsing/apply tests |
| go/plugins/kanban-mcp/internal/migrations/sql/000007_board_subtasks.up.sql | Add per-board subtask template column |
| go/plugins/kanban-mcp/internal/migrations/sql/000007_board_subtasks.down.sql | Drop per-board subtask template column |
| go/plugins/kanban-mcp/internal/migrations/sql/000006_drop_due_date.up.sql | Drop dedicated due_date column |
| go/plugins/kanban-mcp/internal/migrations/sql/000006_drop_due_date.down.sql | Restore dedicated due_date column |
| go/plugins/kanban-mcp/internal/migrations/sql/000005_kind.up.sql | Add task kind (feature/task) + backfill |
| go/plugins/kanban-mcp/internal/migrations/sql/000005_kind.down.sql | Drop task kind column |
| go/plugins/kanban-mcp/internal/migrations/sql/000004_due_date.up.sql | Add due_date column (historical) |
| go/plugins/kanban-mcp/internal/migrations/sql/000004_due_date.down.sql | Drop due_date column (historical) |
| go/plugins/kanban-mcp/internal/migrations/sql/000003_subtasks.up.sql | Create checklist subtask table |
| go/plugins/kanban-mcp/internal/migrations/sql/000003_subtasks.down.sql | Drop checklist subtask table |
| go/plugins/kanban-mcp/internal/migrations/sql/000002_boards.up.sql | Create boards + backfill tasks to default |
| go/plugins/kanban-mcp/internal/migrations/sql/000002_boards.down.sql | Drop boards + remove board_id |
| go/plugins/kanban-mcp/internal/migrations/sql/000001_initial.up.sql | Initial kanban schema (task/attachment) |
| go/plugins/kanban-mcp/internal/migrations/sql/000001_initial.down.sql | Drop initial kanban schema |
| go/plugins/kanban-mcp/internal/migrations/migrations.go | Embedded migrations runner |
| go/plugins/kanban-mcp/internal/migrations/migrations_test.go | Migrations integration tests |
| go/plugins/kanban-mcp/internal/integration/integration_test.go | Full Postgres integration test suite |
| go/plugins/kanban-mcp/internal/db/status.go | Status/scope/kind/attachment type helpers |
| go/plugins/kanban-mcp/internal/db/status_test.go | Status/type helper tests |
| go/plugins/kanban-mcp/internal/db/sqlc.yaml | sqlc configuration |
| go/plugins/kanban-mcp/internal/db/queries/tasks.sql | Task queries (sqlc) |
| go/plugins/kanban-mcp/internal/db/queries/subtasks.sql | Subtask queries (sqlc) |
| go/plugins/kanban-mcp/internal/db/queries/boards.sql | Board queries (sqlc) |
| go/plugins/kanban-mcp/internal/db/queries/attachments.sql | Attachment/attribute queries (sqlc) |
| go/plugins/kanban-mcp/internal/db/gen/tasks.sql.go | Generated task query code |
| go/plugins/kanban-mcp/internal/db/gen/subtasks.sql.go | Generated subtask query code |
| go/plugins/kanban-mcp/internal/db/gen/querier.go | Generated Querier interface |
| go/plugins/kanban-mcp/internal/db/gen/models.go | Generated DB models |
| go/plugins/kanban-mcp/internal/db/gen/db.go | sqlc-style DB wrapper (hand-pinned) |
| go/plugins/kanban-mcp/internal/db/gen/boards.sql.go | Generated board query code |
| go/plugins/kanban-mcp/internal/db/gen/attachments.sql.go | Generated attachment query code |
| go/plugins/kanban-mcp/internal/db/connect.go | DB URL resolution + pool connect w/ backoff |
| go/plugins/kanban-mcp/internal/config/config.go | Flag/env configuration loader |
| go/plugins/kanban-mcp/internal/config/config_test.go | Config resolution tests |
| go/plugins/kanban-mcp/internal/api/handlers_test.go | REST handler integration tests |
| go/plugins/kanban-mcp/docs/mcp-app-task-progress.md | MCP App contract documentation |
| go/plugins/kanban-mcp/Dockerfile | Container build for kanban-mcp |
| go/plugins/kanban-mcp/docker-compose.yml | Local Postgres + server compose |
| design/EP-2048-kanban-mcp-plugin.md | EP/design doc for the plugin |
| contrib/plugins/kanban-mcp/values.yaml | Helm chart values |
| contrib/plugins/kanban-mcp/templates/service.yaml | Helm Service manifest |
| contrib/plugins/kanban-mcp/templates/secret.yaml | Helm DB URL Secret template |
| contrib/plugins/kanban-mcp/templates/remotemcpserver.yaml | Helm RemoteMCPServer registration |
| contrib/plugins/kanban-mcp/templates/deployment.yaml | Helm Deployment manifest |
| contrib/plugins/kanban-mcp/templates/configmap-boards.yaml | Helm seeded-boards ConfigMap |
| contrib/plugins/kanban-mcp/templates/agent.yaml | Helm Agent manifest (declarative) |
| contrib/plugins/kanban-mcp/templates/_helpers.tpl | Helm helpers (names/urls/labels) |
| contrib/plugins/kanban-mcp/Chart.yaml | Helm chart metadata |
Files not reviewed (7)
- go/plugins/kanban-mcp/internal/db/gen/attachments.sql.go: Generated file
- go/plugins/kanban-mcp/internal/db/gen/boards.sql.go: Generated file
- go/plugins/kanban-mcp/internal/db/gen/db.go: Generated file
- go/plugins/kanban-mcp/internal/db/gen/models.go: Generated file
- go/plugins/kanban-mcp/internal/db/gen/querier.go: Generated file
- go/plugins/kanban-mcp/internal/db/gen/subtasks.sql.go: Generated file
- go/plugins/kanban-mcp/internal/db/gen/tasks.sql.go: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+6
to
+8
| // - /api/* REST API. Stubbed with 501 Not Implemented until Step 9, except | ||
| // the GET /api/tasks/{id} not-found path which returns 404 so clients and | ||
| // the UI behave correctly before the full handlers land. |
Comment on lines
+3
to
+5
| // In stdio mode it runs the MCP server over stdin/stdout so kagent can register | ||
| // it as an MCP server. HTTP transport (REST + SSE + MCP over HTTP) is wired in a | ||
| // later step. |
Comment on lines
+130
to
+170
| w.Header().Set("Content-Type", "text/event-stream") | ||
| w.Header().Set("Cache-Control", "no-cache") | ||
| w.Header().Set("Connection", "keep-alive") | ||
| w.Header().Set("X-Accel-Buffering", "no") | ||
|
|
||
| ch := h.Subscribe(board) | ||
| defer h.Unsubscribe(ch) | ||
|
|
||
| // Flush the response headers immediately so the client's request returns and | ||
| // the stream is established before any event is sent. Without this an HTTP | ||
| // client blocks in Do() until the first byte is written. | ||
| w.WriteHeader(http.StatusOK) | ||
| flusher.Flush() | ||
|
|
||
| // Initial snapshot so a freshly connected client renders immediately and so a | ||
| // reconnecting client recovers state without a separate fetch. | ||
| if h.snapshot != nil { | ||
| if data, err := json.Marshal(h.snapshot(board)); err == nil { | ||
| fmt.Fprintf(w, "event: snapshot\ndata: %s\n\n", data) | ||
| flusher.Flush() | ||
| } | ||
| } | ||
|
|
||
| ctx := r.Context() | ||
| for { | ||
| select { | ||
| case <-ctx.Done(): | ||
| return | ||
| case event, ok := <-ch: | ||
| if !ok { | ||
| // Hub unsubscribed/closed this channel. | ||
| return | ||
| } | ||
| data, err := json.Marshal(event.Data) | ||
| if err != nil { | ||
| continue | ||
| } | ||
| fmt.Fprintf(w, "event: %s\ndata: %s\n\n", event.Type, data) | ||
| flusher.Flush() | ||
| } | ||
| } |
Comment on lines
+241
to
+243
| window.addEventListener("message", function (event) { | ||
| var data = event.data; | ||
| if (!data || typeof data !== "object" || data.jsonrpc !== "2.0") return; |
Comment on lines
+93
to
+98
| Every call returns: | ||
|
|
||
| - `content[0].text` — a one-line human summary (the **required** text fallback), | ||
| e.g. `Feature "Checkout v2" is 60% complete — 3 of 5 child tasks done (in "Done").` | ||
| - `structuredContent` — the `TaskProgress` object the View renders: | ||
|
|
Comment on lines
+108
to
+110
| "children": [ { "id": 3, "title": "...", "status": "Done", "percent": 100, "done": true }, ... ], // feature | ||
| "subtasks": [ { "id": 7, "title": "...", "percent": 0, "done": false }, ... ], // task | ||
| "updated_at": "2026-..." |
Comment on lines
+33
to
+35
| - A standalone Go MCP server (`go/plugins/kanban-mcp`) with: | ||
| - SQLite **and** Postgres support (via a shared query layer). | ||
| - Schema migrations and optional board seeding. |
Comment on lines
+66
to
+68
| - **Dual database support:** queries are authored once (`internal/db/queries/*.sql`), | ||
| generated with sqlc (`internal/db/gen`), and run against SQLite or Postgres | ||
| selected at runtime from the configured DB URL. |
Comment on lines
+178
to
+180
| // TestHTTPServer_CORS verifies the /mcp endpoint negotiates an MCP session, | ||
| // returning the expected Mcp-Session-Id header on initialize. | ||
| func TestHTTPServer_CORS(t *testing.T) { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Kanban MCP plugin (#2048):
Depends on #2053
Add go/plugins/kanban-mcp: a self-contained MCP server exposing task/board/ subtask/attachment tools for agents, with dual SQLite/Postgres support, embedded migrations, an embedded board SPA, a real-time task-progress MCP app, and SSE live updates. Add contrib/plugins/kanban-mcp Helm chart that deploys it and registers its web UI as a kagent plugin via RemoteMCPServer.spec.ui.
Depends conceptually on #2047 (plugin registration) and #2046 (chat MCP UI widget); this PR is self-contained and builds independently.
Includes design/EP-2048-kanban-mcp-plugin.md and specs/mcp-kanban-server.