agenthub-multiagent-mcp 1.26.2 → 1.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -239,6 +239,14 @@ export function registerTools() {
239
239
  properties: {},
240
240
  },
241
241
  },
242
+ {
243
+ name: "brain_flush_session",
244
+ description: "Flush this session's accumulated activity into the local searchable brain (.mv2) and the server brain_sessions table WITHOUT disconnecting the agent. Call this at session close (e.g. from /close-session) so the brain is current even where the on-process-exit flush is unreliable (notably Windows, where SIGTERM never fires). Idempotent and best-effort.",
245
+ inputSchema: {
246
+ type: "object",
247
+ properties: {},
248
+ },
249
+ },
242
250
  // Time orientation (add-time-aware-agents §1.3)
243
251
  {
244
252
  name: "now",
@@ -1977,6 +1985,110 @@ export function registerTools() {
1977
1985
  required: ["project_id", "tour_id"],
1978
1986
  },
1979
1987
  },
1988
+ // ── Product Roadmap (add-product-roadmap §1.5) ──
1989
+ {
1990
+ name: "roadmap_get",
1991
+ description: "Read the per-project Product Roadmap. Returns the live view (or the latest snapshot when audience+full is requested via the dashboard share path). Defaults: audience=full (org-member only), format=json. Set format='markdown' for a CommonMark render suitable for emails, brain notes, A2A replies.",
1992
+ inputSchema: {
1993
+ type: "object",
1994
+ properties: {
1995
+ project_id: { type: "string", description: "Project ID" },
1996
+ audience: {
1997
+ type: "string",
1998
+ enum: ["investor", "leadership", "customer", "product"],
1999
+ description: "Audience filter. Omit for the full (unfiltered) view. Phase 1 returns the full view regardless; Phase 3 enforces filtering.",
2000
+ },
2001
+ format: {
2002
+ type: "string",
2003
+ enum: ["json", "markdown"],
2004
+ description: "Output format (default json)",
2005
+ },
2006
+ },
2007
+ required: ["project_id"],
2008
+ },
2009
+ },
2010
+ {
2011
+ name: "roadmap_set_field",
2012
+ description: "Upsert one Product Roadmap field with source='manual'. value is JSON-encoded by the caller (e.g. \"\\\"4.2L\\\"\", \"9\", '{\"caption\":\"Payments\"}'). Sensitive sections (snapshot.finance.*, snapshot.partners.*) require the roadmap_admin role.",
2013
+ inputSchema: {
2014
+ type: "object",
2015
+ properties: {
2016
+ project_id: { type: "string", description: "Project ID" },
2017
+ section: {
2018
+ type: "string",
2019
+ description: "Section id, e.g. 'snapshot.finance', 'shipped', 'timeline', 'commentary.highlights'",
2020
+ },
2021
+ key: {
2022
+ type: "string",
2023
+ description: "Field key within the section (e.g. 'mrr', 'runway_months', an openspec change id, a partner slug). May be empty for singleton sections.",
2024
+ },
2025
+ value: {
2026
+ type: "string",
2027
+ description: "JSON-encoded value. Strings: '\"...\"'. Numbers: '42'. Objects: '{\"k\":\"v\"}'.",
2028
+ },
2029
+ sensitive: {
2030
+ type: "boolean",
2031
+ description: "Mark this entry as sensitive (stripped from customer/public renderers in Phase 3).",
2032
+ },
2033
+ },
2034
+ required: ["project_id", "section", "value"],
2035
+ },
2036
+ },
2037
+ {
2038
+ name: "roadmap_publish_snapshot",
2039
+ description: "Freeze the current roadmap into an immutable snapshot. Returns { id, slug, project_id, audience, created_at }. Phase 3 publishes one snapshot per audience under the same per-day slug; Phase 1 publishes one (audience-agnostic) snapshot per call.",
2040
+ inputSchema: {
2041
+ type: "object",
2042
+ properties: {
2043
+ project_id: { type: "string", description: "Project ID" },
2044
+ audience: {
2045
+ type: "string",
2046
+ enum: ["investor", "leadership", "customer", "product"],
2047
+ description: "Audience to stamp on the snapshot. Omit for full view.",
2048
+ },
2049
+ },
2050
+ required: ["project_id"],
2051
+ },
2052
+ },
2053
+ {
2054
+ name: "roadmap_add_evidence",
2055
+ description: "Attach an evidence row to a roadmap entry (drill-down surface). kind is one of openspec | pr | brain | task | pdf | sheet | url | note. (entry_id, kind, ref) is idempotent — duplicates return the existing row.",
2056
+ inputSchema: {
2057
+ type: "object",
2058
+ properties: {
2059
+ project_id: { type: "string", description: "Project ID" },
2060
+ entry_id: { type: "string", description: "Roadmap entry id (from roadmap_get)" },
2061
+ kind: {
2062
+ type: "string",
2063
+ enum: ["openspec", "pr", "brain", "task", "pdf", "sheet", "url", "note"],
2064
+ },
2065
+ ref: { type: "string", description: "Reference (URL, openspec id, brain knowledge id, etc.)" },
2066
+ label: { type: "string", description: "Optional human label" },
2067
+ sort_order: { type: "number", description: "Optional sort hint" },
2068
+ },
2069
+ required: ["project_id", "entry_id", "kind", "ref"],
2070
+ },
2071
+ },
2072
+ {
2073
+ name: "roadmap_share_to_slack",
2074
+ description: "One-click share: publish a snapshot, mint a public share token, render Slack Block Kit, post to the channel. Returns { snapshot_id, slug, share_token, permalink, delivered }.",
2075
+ inputSchema: {
2076
+ type: "object",
2077
+ properties: {
2078
+ project_id: { type: "string", description: "Project ID" },
2079
+ channel: {
2080
+ type: "string",
2081
+ description: "Slack channel (e.g. #leadership). Empty = notifier default.",
2082
+ },
2083
+ audience: {
2084
+ type: "string",
2085
+ enum: ["investor", "leadership", "customer", "product"],
2086
+ description: "Audience filter applied before render.",
2087
+ },
2088
+ },
2089
+ required: ["project_id"],
2090
+ },
2091
+ },
1980
2092
  // ── Secrets Vault ──
1981
2093
  {
1982
2094
  name: "secret_set",
@@ -2478,6 +2590,19 @@ export async function handleToolCall(name, args, client, context) {
2478
2590
  } : null,
2479
2591
  };
2480
2592
  }
2593
+ case "brain_flush_session": {
2594
+ // Flush the current session to the local .mv2 + server WITHOUT
2595
+ // disconnecting. Mirrors gracefulShutdown's agent-id resolution so it
2596
+ // works even if agent_register was never called this process. The agent
2597
+ // stays registered for the next reconnect.
2598
+ const workingDir = context.getWorkingDir();
2599
+ const flushAgentId = agentId || (workingDir ? state.readHookAgentId(workingDir) : null);
2600
+ if (!flushAgentId) {
2601
+ return { flushed: false, reason: "no agent id resolved" };
2602
+ }
2603
+ const { mv2Written } = await brainCapture.flushSessionToBrain(client, flushAgentId);
2604
+ return { flushed: true, agent_id: flushAgentId, mv2_written: mv2Written };
2605
+ }
2481
2606
  case "now": {
2482
2607
  // No wrapping — server_time would otherwise overshadow the explicit
2483
2608
  // tool result. Force-refresh past the cache so the agent gets a fresh
@@ -3787,6 +3912,72 @@ export async function handleToolCall(name, args, client, context) {
3787
3912
  const projectId = args.project_id;
3788
3913
  return client.del(`/projects/${projectId}/features/tours/${args.tour_id}`);
3789
3914
  }
3915
+ // ── Product Roadmap (add-product-roadmap §1.5) ──
3916
+ case "roadmap_get": {
3917
+ const projectId = args.project_id;
3918
+ if (!projectId)
3919
+ throw new Error("project_id is required");
3920
+ const audience = args.audience || "";
3921
+ const format = (args.format || "json").toLowerCase();
3922
+ const query = new URLSearchParams();
3923
+ if (format)
3924
+ query.set("format", format);
3925
+ if (audience)
3926
+ query.set("audience", audience);
3927
+ const suffix = query.toString() ? `?${query.toString()}` : "";
3928
+ return client.get(`/projects/${projectId}/roadmap${suffix}`);
3929
+ }
3930
+ case "roadmap_set_field": {
3931
+ const projectId = args.project_id;
3932
+ if (!projectId)
3933
+ throw new Error("project_id is required");
3934
+ const section = args.section;
3935
+ if (!section)
3936
+ throw new Error("section is required");
3937
+ const body = {
3938
+ section,
3939
+ key: args.key || "",
3940
+ value: args.value ?? "",
3941
+ };
3942
+ if (args.sensitive !== undefined)
3943
+ body.sensitive = !!args.sensitive;
3944
+ return client.put(`/projects/${projectId}/roadmap/entries`, body);
3945
+ }
3946
+ case "roadmap_publish_snapshot": {
3947
+ const projectId = args.project_id;
3948
+ if (!projectId)
3949
+ throw new Error("project_id is required");
3950
+ const body = {};
3951
+ if (args.audience)
3952
+ body.audience = args.audience;
3953
+ return client.post(`/projects/${projectId}/roadmap/snapshots`, body);
3954
+ }
3955
+ case "roadmap_add_evidence": {
3956
+ const projectId = args.project_id;
3957
+ const entryId = args.entry_id;
3958
+ if (!projectId || !entryId)
3959
+ throw new Error("project_id and entry_id are required");
3960
+ const body = {
3961
+ kind: args.kind,
3962
+ ref: args.ref,
3963
+ };
3964
+ if (args.label !== undefined)
3965
+ body.label = args.label;
3966
+ if (args.sort_order !== undefined)
3967
+ body.sort_order = args.sort_order;
3968
+ return client.post(`/projects/${projectId}/roadmap/entries/${entryId}/evidence`, body);
3969
+ }
3970
+ case "roadmap_share_to_slack": {
3971
+ const projectId = args.project_id;
3972
+ if (!projectId)
3973
+ throw new Error("project_id is required");
3974
+ const body = {};
3975
+ if (args.channel !== undefined)
3976
+ body.channel = args.channel;
3977
+ if (args.audience !== undefined)
3978
+ body.audience = args.audience;
3979
+ return client.post(`/projects/${projectId}/roadmap/share/slack`, body);
3980
+ }
3790
3981
  // ── Capabilities (add-agent-capabilities Phase 2 §2.3) ──
3791
3982
  case "capability_list": {
3792
3983
  if (!agentId) {