agent-planner-mcp 1.5.4 → 1.5.5

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-planner-mcp",
3
- "version": "1.5.4",
3
+ "version": "1.5.5",
4
4
  "description": "MCP server for AgentPlanner — AI agent orchestration with planning, dependencies, knowledge graphs, and human oversight",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -26,6 +26,24 @@ function safeArray(value) {
26
26
  return Array.isArray(value) ? value : [];
27
27
  }
28
28
 
29
+ /**
30
+ * The web app origin (where /app/plans/:id lives), for building shareable plan
31
+ * links agents can post (e.g. to Slack). Derived from API_URL — the web app
32
+ * shares the origin and the API sits under /api behind nginx — with an explicit
33
+ * AGENTPLANNER_WEB_URL override for local/self-hosted setups where the UI is on
34
+ * a different host/port.
35
+ */
36
+ function webOrigin() {
37
+ if (process.env.AGENTPLANNER_WEB_URL) return process.env.AGENTPLANNER_WEB_URL.replace(/\/+$/, '');
38
+ const api = process.env.API_URL || 'https://agentplanner.io/api';
39
+ return api.replace(/\/+$/, '').replace(/\/api$/, '') || 'https://agentplanner.io';
40
+ }
41
+
42
+ /** Shareable web link to a plan (set the plan's visibility to unlisted/public for a rich unfurl). */
43
+ function planUrl(planId) {
44
+ return planId ? `${webOrigin()}/app/plans/${planId}` : null;
45
+ }
46
+
29
47
  /**
30
48
  * True when an error means the backend has no /v1 surface (pre-consolidation
31
49
  * self-hosted API). Express returns a default 404 with no structured body for
@@ -38,4 +56,4 @@ function isV1Unavailable(err) {
38
56
  return !(body && typeof body === 'object' && body.error);
39
57
  }
40
58
 
41
- module.exports = { asOf, formatResponse, errorResponse, safeArray, isV1Unavailable };
59
+ module.exports = { asOf, formatResponse, errorResponse, safeArray, isV1Unavailable, webOrigin, planUrl };
@@ -5,7 +5,7 @@
5
5
  * plan_analysis. Each answers one whole agentic question and returns `as_of`.
6
6
  */
7
7
 
8
- const { asOf, formatResponse, errorResponse, safeArray, isV1Unavailable } = require('./_shared');
8
+ const { asOf, formatResponse, errorResponse, safeArray, isV1Unavailable, planUrl } = require('./_shared');
9
9
 
10
10
  // ─────────────────────────────────────────────────────────────────────────
11
11
  // briefing — bundled mission control state. Replaces 4 round trips.
@@ -486,6 +486,7 @@ async function listPlansHandler(args, apiClient) {
486
486
  summary,
487
487
  plans: page.map((p) => ({
488
488
  id: p.id,
489
+ url: planUrl(p.id),
489
490
  title: p.title,
490
491
  status: p.status,
491
492
  visibility: p.visibility,
@@ -13,7 +13,7 @@
13
13
  * See ../../../docs/MCP_v1.0_FULL_SURFACE.md for design rationale.
14
14
  */
15
15
 
16
- const { asOf, formatResponse, errorResponse, isV1Unavailable } = require('./_shared');
16
+ const { asOf, formatResponse, errorResponse, isV1Unavailable, planUrl } = require('./_shared');
17
17
  const { version: PKG_VERSION } = require('../../../package.json');
18
18
 
19
19
  // Provenance tag stamped onto every plan this server creates, so a plan stays
@@ -854,16 +854,18 @@ async function formIntentionHandler(args, apiClient) {
854
854
  tree,
855
855
  client_version: CLIENT_TAG,
856
856
  });
857
+ const facadePlanId = result.plan?.id || result.plan_id;
857
858
  return formatResponse({
858
859
  ...result,
859
- plan_id: result.plan?.id || result.plan_id,
860
+ plan_id: facadePlanId,
861
+ url: planUrl(facadePlanId),
860
862
  goal_id,
861
863
  status: result.plan?.status || status,
862
864
  is_draft: (result.plan?.status || status) === 'draft',
863
865
  nodes_created: Array.isArray(result.tree) ? result.tree.length : undefined,
864
866
  next_step: (result.plan?.status || status) === 'draft'
865
867
  ? "Plan created as draft. Will surface in dashboard pending for human review. Auto-promotes to active when first task moves to in_progress."
866
- : "Plan active. Claim a task with claim_next_task({plan_id}) to begin work.",
868
+ : `Plan active. Claim a task with claim_next_task({plan_id}) to begin work. Shareable link: ${planUrl(facadePlanId)} (set visibility:'unlisted' for a rich Slack/social preview).`,
867
869
  });
868
870
  } catch {
869
871
  // Fall through to the legacy multi-call path for older/self-hosted APIs.
@@ -966,6 +968,7 @@ async function formIntentionHandler(args, apiClient) {
966
968
  const response = {
967
969
  as_of: asOf(),
968
970
  plan_id: plan.id,
971
+ url: planUrl(plan.id),
969
972
  goal_id,
970
973
  status: plan.status,
971
974
  is_draft: plan.status === 'draft',
@@ -975,7 +978,7 @@ async function formIntentionHandler(args, apiClient) {
975
978
  structure,
976
979
  next_step: plan.status === 'draft'
977
980
  ? "Plan created as draft. Will surface in dashboard pending for human review. Auto-promotes to active when first task moves to in_progress."
978
- : "Plan active. Claim a task with claim_next_task({plan_id}) to begin work.",
981
+ : `Plan active. Claim a task with claim_next_task({plan_id}) to begin work. Shareable link: ${planUrl(plan.id)} (set visibility:'unlisted' for a rich Slack/social preview).`,
979
982
  };
980
983
  if (createdWithoutDependencies) {
981
984
  response.warning =
@@ -1153,6 +1156,7 @@ async function proposeResearchChainHandler(args, apiClient) {
1153
1156
  return formatResponse({
1154
1157
  as_of: asOf(),
1155
1158
  plan_id,
1159
+ url: planUrl(plan_id),
1156
1160
  parent_id,
1157
1161
  rationale,
1158
1162
  research: { id: created.research.id, title: created.research.title },