@nestpilot/mcp-app 1.0.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.
- package/README.md +350 -0
- package/dist/cli/doctor.d.ts +1 -0
- package/dist/cli/doctor.js +214 -0
- package/dist/cli/export-import.d.ts +6 -0
- package/dist/cli/export-import.js +132 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +168 -0
- package/dist/cli/init.d.ts +1 -0
- package/dist/cli/init.js +171 -0
- package/dist/host-configs/cowork.json +11 -0
- package/dist/host-configs/goose.yaml +22 -0
- package/dist/host-configs/openclaw-manifest.json +16 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +128 -0
- package/dist/mcp-app.html +155 -0
- package/dist/nestpilot-client.d.ts +44 -0
- package/dist/nestpilot-client.js +160 -0
- package/dist/planner.html +222 -0
- package/dist/server.d.ts +19 -0
- package/dist/server.js +245 -0
- package/dist/skills/SKILL.md +162 -0
- package/dist/skills/manifest.json +51 -0
- package/dist/skills/tools/activate_plan.md +36 -0
- package/dist/skills/tools/coach.md +59 -0
- package/dist/skills/tools/comprehensive_plan.md +65 -0
- package/dist/skills/tools/create_plan.md +59 -0
- package/dist/skills/tools/create_saved_plan.md +49 -0
- package/dist/skills/tools/delete_plan.md +42 -0
- package/dist/skills/tools/delete_scenario.md +38 -0
- package/dist/skills/tools/generate_proposal.md +63 -0
- package/dist/skills/tools/generate_retirement_report.md +50 -0
- package/dist/skills/tools/get_active_plan.md +44 -0
- package/dist/skills/tools/get_baseline_forecast.md +47 -0
- package/dist/skills/tools/get_plan.md +44 -0
- package/dist/skills/tools/get_plan_components.md +50 -0
- package/dist/skills/tools/get_scenario.md +46 -0
- package/dist/skills/tools/list_plans.md +44 -0
- package/dist/skills/tools/list_scenarios.md +42 -0
- package/dist/skills/tools/medicare-guardian.md +59 -0
- package/dist/skills/tools/nestpilot_run_plan.md +61 -0
- package/dist/skills/tools/optimize_roth_conversion.md +107 -0
- package/dist/skills/tools/optimize_ss_claiming.md +30 -0
- package/dist/skills/tools/rename_plan.md +34 -0
- package/dist/skills/tools/retirement-planner.md +55 -0
- package/dist/skills/tools/run_forecast.md +65 -0
- package/dist/skills/tools/run_saved_forecast.md +52 -0
- package/dist/skills/tools/run_scenario.md +66 -0
- package/dist/skills/tools/save_plan.md +48 -0
- package/dist/skills/tools/save_scenario.md +50 -0
- package/dist/skills/tools/verify_forecast.md +43 -0
- package/dist/src/config.d.ts +20 -0
- package/dist/src/config.js +44 -0
- package/dist/src/contracts/provenance.d.ts +37 -0
- package/dist/src/contracts/provenance.js +71 -0
- package/dist/src/contracts/tool-contract-registry.d.ts +43 -0
- package/dist/src/contracts/tool-contract-registry.js +282 -0
- package/dist/src/local/cloud-compute-client.d.ts +55 -0
- package/dist/src/local/cloud-compute-client.js +135 -0
- package/dist/src/local/encryption.d.ts +24 -0
- package/dist/src/local/encryption.js +105 -0
- package/dist/src/local/keychain.d.ts +41 -0
- package/dist/src/local/keychain.js +236 -0
- package/dist/src/local/local-config.d.ts +34 -0
- package/dist/src/local/local-config.js +61 -0
- package/dist/src/local/local-data-layer.d.ts +20 -0
- package/dist/src/local/local-data-layer.js +15 -0
- package/dist/src/local/local-plan-store.d.ts +66 -0
- package/dist/src/local/local-plan-store.js +195 -0
- package/dist/src/local/pii-scrubber.d.ts +26 -0
- package/dist/src/local/pii-scrubber.js +219 -0
- package/dist/src/policy/policy-engine.d.ts +44 -0
- package/dist/src/policy/policy-engine.js +119 -0
- package/dist/src/rate-limit.d.ts +17 -0
- package/dist/src/rate-limit.js +41 -0
- package/dist/src/security.d.ts +19 -0
- package/dist/src/security.js +118 -0
- package/dist/src/skills/index.d.ts +12 -0
- package/dist/src/skills/index.js +16 -0
- package/dist/src/skills/retirement-pack-v1.d.ts +28 -0
- package/dist/src/skills/retirement-pack-v1.js +295 -0
- package/dist/src/skills/skill-executor.d.ts +65 -0
- package/dist/src/skills/skill-executor.js +174 -0
- package/dist/src/skills/skill-manifest-schema.d.ts +337 -0
- package/dist/src/skills/skill-manifest-schema.js +94 -0
- package/dist/src/skills/skill-registry.d.ts +71 -0
- package/dist/src/skills/skill-registry.js +116 -0
- package/dist/src/telemetry.d.ts +12 -0
- package/dist/src/telemetry.js +59 -0
- package/dist/src/types.d.ts +46 -0
- package/dist/src/types.js +4 -0
- package/dist/tools/agent-tools.d.ts +12 -0
- package/dist/tools/agent-tools.js +141 -0
- package/dist/tools/forecast-management-tools.d.ts +9 -0
- package/dist/tools/forecast-management-tools.js +133 -0
- package/dist/tools/local-plan-tools.d.ts +8 -0
- package/dist/tools/local-plan-tools.js +357 -0
- package/dist/tools/mcp-helpers.d.ts +52 -0
- package/dist/tools/mcp-helpers.js +177 -0
- package/dist/tools/medicare-tools.d.ts +3 -0
- package/dist/tools/medicare-tools.js +162 -0
- package/dist/tools/optimize-roth-tools-test.d.ts +2 -0
- package/dist/tools/optimize-roth-tools-test.js +36 -0
- package/dist/tools/optimize-roth-tools.d.ts +3 -0
- package/dist/tools/optimize-roth-tools.js +818 -0
- package/dist/tools/plan-management-tools.d.ts +3 -0
- package/dist/tools/plan-management-tools.js +196 -0
- package/dist/tools/planning-tools.d.ts +3 -0
- package/dist/tools/planning-tools.js +290 -0
- package/dist/tools/proposal-tools.d.ts +3 -0
- package/dist/tools/proposal-tools.js +428 -0
- package/dist/tools/report-tools.d.ts +3 -0
- package/dist/tools/report-tools.js +245 -0
- package/dist/tools/scenario-management-tools.d.ts +3 -0
- package/dist/tools/scenario-management-tools.js +136 -0
- package/dist/views/verification-packet.html +211 -0
- package/host-configs/cowork.json +11 -0
- package/host-configs/goose.yaml +22 -0
- package/host-configs/openclaw-manifest.json +16 -0
- package/package.json +66 -0
- package/skills/SKILL.md +162 -0
- package/skills/manifest.json +51 -0
- package/skills/tools/activate_plan.md +36 -0
- package/skills/tools/coach.md +59 -0
- package/skills/tools/comprehensive_plan.md +65 -0
- package/skills/tools/create_plan.md +59 -0
- package/skills/tools/create_saved_plan.md +49 -0
- package/skills/tools/delete_plan.md +42 -0
- package/skills/tools/delete_scenario.md +38 -0
- package/skills/tools/generate_proposal.md +63 -0
- package/skills/tools/generate_retirement_report.md +50 -0
- package/skills/tools/get_active_plan.md +44 -0
- package/skills/tools/get_baseline_forecast.md +47 -0
- package/skills/tools/get_plan.md +44 -0
- package/skills/tools/get_plan_components.md +50 -0
- package/skills/tools/get_scenario.md +46 -0
- package/skills/tools/list_plans.md +44 -0
- package/skills/tools/list_scenarios.md +42 -0
- package/skills/tools/medicare-guardian.md +59 -0
- package/skills/tools/nestpilot_run_plan.md +61 -0
- package/skills/tools/optimize_roth_conversion.md +107 -0
- package/skills/tools/optimize_ss_claiming.md +30 -0
- package/skills/tools/rename_plan.md +34 -0
- package/skills/tools/retirement-planner.md +55 -0
- package/skills/tools/run_forecast.md +65 -0
- package/skills/tools/run_saved_forecast.md +52 -0
- package/skills/tools/run_scenario.md +66 -0
- package/skills/tools/save_plan.md +48 -0
- package/skills/tools/save_scenario.md +50 -0
- package/skills/tools/verify_forecast.md +43 -0
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { AuthContext } from "./tools/mcp-helpers.js";
|
|
3
|
+
export type { AuthContext } from "./tools/mcp-helpers.js";
|
|
4
|
+
/**
|
|
5
|
+
* Auto-derive skill tool names from manifest.json (auto-registration convention).
|
|
6
|
+
* Adding a new tool only requires updating manifest.json — no server.ts edits needed.
|
|
7
|
+
* Exported for test access.
|
|
8
|
+
*/
|
|
9
|
+
export declare function loadSkillToolNames(skillsDir?: string): string[];
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new MCP server instance with all NestPilot tools and resources.
|
|
12
|
+
* When `authCtx` is provided (HTTP transport), it is threaded through to all
|
|
13
|
+
* tool registrations so backend calls carry the user's JWT.
|
|
14
|
+
*
|
|
15
|
+
* Mode detection (FEAT-0087):
|
|
16
|
+
* - NESTPILOT_MODE=cloud (default) → proxy all tools to Spring Boot API
|
|
17
|
+
* - NESTPILOT_MODE=local → local data layer + cloud compute for PII-free payloads
|
|
18
|
+
*/
|
|
19
|
+
export declare function createServer(authCtx?: AuthContext): McpServer;
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NestPilot MCP Server — Orchestrator
|
|
3
|
+
*
|
|
4
|
+
* Creates the MCP server and registers tool groups by domain:
|
|
5
|
+
* - Medicare tools (medicare-guardian, medicare-analyze, email-subscribe)
|
|
6
|
+
* - Planning tools (create_plan, run_forecast, run_scenario, verify_forecast, coach)
|
|
7
|
+
* - Roth tools (optimize_roth_conversion) — FEAT-0066
|
|
8
|
+
* - Report tools (generate_retirement_report)
|
|
9
|
+
* - Agent Runtime tools (list_skills, run_skill, run_plan)
|
|
10
|
+
* - Views (retirement-planner, verification-packet, medicare-guardian)
|
|
11
|
+
*
|
|
12
|
+
* Unified MCP gateway — consolidates apps/mcp-edge into apps/mcp-app (FEAT-0053).
|
|
13
|
+
* Production features: security, rate-limit, telemetry.
|
|
14
|
+
*/
|
|
15
|
+
import { registerAppResource, registerAppTool, RESOURCE_MIME_TYPE, } from "@modelcontextprotocol/ext-apps/server";
|
|
16
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
17
|
+
import fsSync from "node:fs";
|
|
18
|
+
import fs from "node:fs/promises";
|
|
19
|
+
import path from "node:path";
|
|
20
|
+
import { z } from "zod";
|
|
21
|
+
import { registerAgentTools } from "./tools/agent-tools.js";
|
|
22
|
+
import { registerForecastManagementTools } from "./tools/forecast-management-tools.js";
|
|
23
|
+
import { registerLocalPlanTools } from "./tools/local-plan-tools.js";
|
|
24
|
+
import { registerMedicareTools } from "./tools/medicare-tools.js";
|
|
25
|
+
import { registerRothTools } from "./tools/optimize-roth-tools.js";
|
|
26
|
+
import { registerPlanManagementTools } from "./tools/plan-management-tools.js";
|
|
27
|
+
import { registerPlanningTools } from "./tools/planning-tools.js";
|
|
28
|
+
import { registerProposalTools } from "./tools/proposal-tools.js";
|
|
29
|
+
import { registerReportTools } from "./tools/report-tools.js";
|
|
30
|
+
import { registerScenarioManagementTools } from "./tools/scenario-management-tools.js";
|
|
31
|
+
import { loadLocalConfig, EncryptionService, LocalPlanStore, CloudComputeClient, createKeychainProvider, } from "./src/local/local-data-layer.js";
|
|
32
|
+
// ── Skill resource constants (MCP Appliance — FEAT-0065 Phase 1) ────────
|
|
33
|
+
const SKILLS_DIR = path.join(import.meta.dirname, "skills");
|
|
34
|
+
const SKILL_MANIFEST_URI = "resource://skill/manifest.json";
|
|
35
|
+
const SKILL_MAIN_URI = "resource://skill/SKILL.md";
|
|
36
|
+
/**
|
|
37
|
+
* Auto-derive skill tool names from manifest.json (auto-registration convention).
|
|
38
|
+
* Adding a new tool only requires updating manifest.json — no server.ts edits needed.
|
|
39
|
+
* Exported for test access.
|
|
40
|
+
*/
|
|
41
|
+
export function loadSkillToolNames(skillsDir = SKILLS_DIR) {
|
|
42
|
+
try {
|
|
43
|
+
const manifestPath = path.join(skillsDir, "manifest.json");
|
|
44
|
+
const raw = fsSync.readFileSync(manifestPath, "utf-8");
|
|
45
|
+
const manifest = JSON.parse(raw);
|
|
46
|
+
return Object.keys(manifest.skill.tool_skills);
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
console.warn("[server] Failed to load skill tool names from manifest.json:", e.message);
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const SKILL_TOOL_NAMES = loadSkillToolNames();
|
|
54
|
+
// Works both from source (*.ts) and compiled (dist/)
|
|
55
|
+
const DIST_DIR = import.meta.filename.endsWith(".ts")
|
|
56
|
+
? path.join(import.meta.dirname, "dist")
|
|
57
|
+
: path.join(import.meta.dirname);
|
|
58
|
+
/**
|
|
59
|
+
* Creates a new MCP server instance with all NestPilot tools and resources.
|
|
60
|
+
* When `authCtx` is provided (HTTP transport), it is threaded through to all
|
|
61
|
+
* tool registrations so backend calls carry the user's JWT.
|
|
62
|
+
*
|
|
63
|
+
* Mode detection (FEAT-0087):
|
|
64
|
+
* - NESTPILOT_MODE=cloud (default) → proxy all tools to Spring Boot API
|
|
65
|
+
* - NESTPILOT_MODE=local → local data layer + cloud compute for PII-free payloads
|
|
66
|
+
*/
|
|
67
|
+
export function createServer(authCtx) {
|
|
68
|
+
const localConfig = loadLocalConfig();
|
|
69
|
+
const server = new McpServer({
|
|
70
|
+
name: "NestPilot",
|
|
71
|
+
version: "1.0.0",
|
|
72
|
+
});
|
|
73
|
+
if (localConfig.mode === "local") {
|
|
74
|
+
// ── Local mode (FEAT-0087) ────────────────────────────────────────
|
|
75
|
+
console.log("[server] Starting in LOCAL mode — data stays on this machine");
|
|
76
|
+
const keychain = createKeychainProvider(localConfig.dataDir);
|
|
77
|
+
const encryption = new EncryptionService(keychain);
|
|
78
|
+
const store = new LocalPlanStore(localConfig.dataDir, encryption);
|
|
79
|
+
const computeClient = new CloudComputeClient(localConfig.cloudApiUrl, localConfig.apiKey ?? "");
|
|
80
|
+
console.log("Registering Local Plan tools...");
|
|
81
|
+
registerLocalPlanTools(server, store, computeClient);
|
|
82
|
+
// Cloud-backed tools that use PII-free payloads
|
|
83
|
+
console.log("Registering Medicare tools (cloud)...");
|
|
84
|
+
registerMedicareTools(server, authCtx);
|
|
85
|
+
console.log("Registering Roth tools (cloud)...");
|
|
86
|
+
registerRothTools(server, authCtx);
|
|
87
|
+
console.log("Registering Report tools (cloud)...");
|
|
88
|
+
registerReportTools(server, authCtx);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// ── Cloud mode (default — existing behavior) ──────────────────────
|
|
92
|
+
console.log("[server] Starting in CLOUD mode — proxy to Spring Boot API");
|
|
93
|
+
console.log("Registering Medicare tools...");
|
|
94
|
+
registerMedicareTools(server, authCtx);
|
|
95
|
+
console.log("Registering Planning tools...");
|
|
96
|
+
registerPlanningTools(server, authCtx);
|
|
97
|
+
console.log("Registering Roth tools...");
|
|
98
|
+
registerRothTools(server, authCtx);
|
|
99
|
+
console.log("Registering Agent tools...");
|
|
100
|
+
registerAgentTools(server, authCtx);
|
|
101
|
+
console.log("Registering Plan Management tools...");
|
|
102
|
+
registerPlanManagementTools(server, authCtx);
|
|
103
|
+
console.log("Registering Forecast Management tools...");
|
|
104
|
+
registerForecastManagementTools(server, authCtx);
|
|
105
|
+
console.log("Registering Scenario Management tools...");
|
|
106
|
+
registerScenarioManagementTools(server, authCtx);
|
|
107
|
+
console.log("Registering Proposal tools...");
|
|
108
|
+
registerProposalTools(server, authCtx);
|
|
109
|
+
console.log("Registering Report tools...");
|
|
110
|
+
registerReportTools(server, authCtx);
|
|
111
|
+
}
|
|
112
|
+
// ── Shared registrations (both modes) ─────────────────────────────────
|
|
113
|
+
console.log("Registering views...");
|
|
114
|
+
registerPlannerView(server);
|
|
115
|
+
registerVerificationPacketView(server);
|
|
116
|
+
registerSkillResources(server);
|
|
117
|
+
console.log("Server registration complete");
|
|
118
|
+
return server;
|
|
119
|
+
}
|
|
120
|
+
// ── Retirement Planner view ─────────────────────────────────────────────
|
|
121
|
+
function registerPlannerView(server) {
|
|
122
|
+
// Keep stable URI for host compatibility and support the old cache-busting alias.
|
|
123
|
+
const resourceUri = "ui://retirement-planner/planner.html";
|
|
124
|
+
const resourceUriAlias = "ui://retirement-planner/planner-v2.html";
|
|
125
|
+
// Tool that launches the interactive planner view
|
|
126
|
+
registerAppTool(server, "retirement-planner", {
|
|
127
|
+
title: "Retirement Planner",
|
|
128
|
+
description: `Opens an interactive retirement planner with plan creation form, forecast charts, and scenario comparison.
|
|
129
|
+
|
|
130
|
+
USE THIS TOOL WHEN THE USER:
|
|
131
|
+
- Wants to create or edit a retirement plan interactively
|
|
132
|
+
- Asks to see their retirement forecast as charts
|
|
133
|
+
- Wants a visual retirement planning experience
|
|
134
|
+
- Says "show me my retirement plan" or "open the planner"
|
|
135
|
+
|
|
136
|
+
The view supports three modes:
|
|
137
|
+
- editor (default): Input form for quick plan creation
|
|
138
|
+
- forecast: Displays forecast charts for an existing plan
|
|
139
|
+
- scenario: Shows baseline vs candidate scenario comparison`,
|
|
140
|
+
inputSchema: {
|
|
141
|
+
mode: z
|
|
142
|
+
.enum(["editor", "forecast", "scenario"])
|
|
143
|
+
.default("editor")
|
|
144
|
+
.describe("View mode: 'editor' (plan form), 'forecast' (charts), or 'scenario' (comparison)"),
|
|
145
|
+
},
|
|
146
|
+
_meta: {
|
|
147
|
+
ui: {
|
|
148
|
+
resourceUri,
|
|
149
|
+
visibility: ["model", "app"],
|
|
150
|
+
},
|
|
151
|
+
// Host compatibility fallback for clients that still read OpenAI-style keys.
|
|
152
|
+
"openai/outputTemplate": resourceUri,
|
|
153
|
+
"openai/widgetAccessible": true,
|
|
154
|
+
},
|
|
155
|
+
}, async (args) => {
|
|
156
|
+
const { mode = "editor" } = args;
|
|
157
|
+
return {
|
|
158
|
+
content: [
|
|
159
|
+
{
|
|
160
|
+
type: "text",
|
|
161
|
+
text: JSON.stringify({
|
|
162
|
+
mode,
|
|
163
|
+
message: `Retirement planner opened in ${mode} mode`,
|
|
164
|
+
}),
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
type: "resource_link",
|
|
168
|
+
uri: resourceUri,
|
|
169
|
+
name: "NestPilot Retirement Planner",
|
|
170
|
+
title: "Open Retirement Planner",
|
|
171
|
+
description: `Interactive planner view (${mode} mode)`,
|
|
172
|
+
mimeType: RESOURCE_MIME_TYPE,
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
_meta: {
|
|
176
|
+
"openai/outputTemplate": resourceUri,
|
|
177
|
+
"openai/widgetDescription": "Interactive retirement planner with editor, forecast chart, and scenario comparison.",
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
});
|
|
181
|
+
// UI resource: serves the bundled single-file HTML for the planner view
|
|
182
|
+
registerAppResource(server, resourceUri, resourceUri, { mimeType: RESOURCE_MIME_TYPE }, async () => {
|
|
183
|
+
const html = await fs.readFile(path.join(DIST_DIR, "planner.html"), "utf-8");
|
|
184
|
+
return {
|
|
185
|
+
contents: [
|
|
186
|
+
{ uri: resourceUri, mimeType: RESOURCE_MIME_TYPE, text: html },
|
|
187
|
+
],
|
|
188
|
+
};
|
|
189
|
+
});
|
|
190
|
+
// Alias registration for hosts that still reference the previous URI.
|
|
191
|
+
registerAppResource(server, resourceUriAlias, resourceUriAlias, { mimeType: RESOURCE_MIME_TYPE }, async () => {
|
|
192
|
+
const html = await fs.readFile(path.join(DIST_DIR, "planner.html"), "utf-8");
|
|
193
|
+
return {
|
|
194
|
+
contents: [
|
|
195
|
+
{ uri: resourceUriAlias, mimeType: RESOURCE_MIME_TYPE, text: html },
|
|
196
|
+
],
|
|
197
|
+
};
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
// ── Verification Packet view ─────────────────────────────────────────────
|
|
201
|
+
function registerVerificationPacketView(server) {
|
|
202
|
+
const resourceUri = "ui://verification-packet/verification-packet.html";
|
|
203
|
+
registerAppResource(server, resourceUri, resourceUri, { mimeType: RESOURCE_MIME_TYPE }, async () => {
|
|
204
|
+
const html = await fs.readFile(path.join(DIST_DIR, "views", "verification-packet.html"), "utf-8");
|
|
205
|
+
return {
|
|
206
|
+
contents: [
|
|
207
|
+
{ uri: resourceUri, mimeType: RESOURCE_MIME_TYPE, text: html },
|
|
208
|
+
],
|
|
209
|
+
};
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
// ── Skill resources (MCP Appliance — FEAT-0065 Phase 1) ─────────────────
|
|
213
|
+
//
|
|
214
|
+
// Registers well-known skill URIs so any MCP host can discover and load
|
|
215
|
+
// NestPilot's operational skills via the resource://skill/ convention.
|
|
216
|
+
// All files are read lazily (on resource/read request) so createServer()
|
|
217
|
+
// stays synchronous and fast.
|
|
218
|
+
function registerSkillResources(server) {
|
|
219
|
+
// Tier 0: manifest — AI host discovers skill capabilities
|
|
220
|
+
server.resource("skill-manifest", SKILL_MANIFEST_URI, { mimeType: "application/json" }, async () => {
|
|
221
|
+
const text = await fs.readFile(path.join(SKILLS_DIR, "manifest.json"), "utf-8");
|
|
222
|
+
return {
|
|
223
|
+
contents: [
|
|
224
|
+
{ uri: SKILL_MANIFEST_URI, mimeType: "application/json", text },
|
|
225
|
+
],
|
|
226
|
+
};
|
|
227
|
+
});
|
|
228
|
+
// Tier 2: main skill document — workflow overview and boundaries
|
|
229
|
+
server.resource("skill-main", SKILL_MAIN_URI, { mimeType: "text/markdown" }, async () => {
|
|
230
|
+
const text = await fs.readFile(path.join(SKILLS_DIR, "SKILL.md"), "utf-8");
|
|
231
|
+
return {
|
|
232
|
+
contents: [{ uri: SKILL_MAIN_URI, mimeType: "text/markdown", text }],
|
|
233
|
+
};
|
|
234
|
+
});
|
|
235
|
+
// Tier 2: per-tool skill documents — tool-specific guidance loaded on demand
|
|
236
|
+
for (const toolName of SKILL_TOOL_NAMES) {
|
|
237
|
+
const uri = `resource://skill/tools/${toolName}.md`;
|
|
238
|
+
server.resource(`skill-tool-${toolName}`, uri, { mimeType: "text/markdown" }, async () => {
|
|
239
|
+
const text = await fs.readFile(path.join(SKILLS_DIR, "tools", `${toolName}.md`), "utf-8");
|
|
240
|
+
return {
|
|
241
|
+
contents: [{ uri, mimeType: "text/markdown", text }],
|
|
242
|
+
};
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nestpilot-retirement
|
|
3
|
+
version: "1.0.0"
|
|
4
|
+
description: "Retirement planning, forecasting, scenario analysis, Medicare enrollment, and AI coaching"
|
|
5
|
+
tools:
|
|
6
|
+
- medicare-guardian
|
|
7
|
+
- create_plan
|
|
8
|
+
- run_forecast
|
|
9
|
+
- verify_forecast
|
|
10
|
+
- run_scenario
|
|
11
|
+
- retirement-planner
|
|
12
|
+
- nestpilot_run_plan
|
|
13
|
+
- coach
|
|
14
|
+
- optimize_roth_conversion
|
|
15
|
+
- optimize_ss_claiming
|
|
16
|
+
- generate_proposal
|
|
17
|
+
references:
|
|
18
|
+
- tools/medicare-guardian.md
|
|
19
|
+
- tools/create_plan.md
|
|
20
|
+
- tools/run_forecast.md
|
|
21
|
+
- tools/verify_forecast.md
|
|
22
|
+
- tools/run_scenario.md
|
|
23
|
+
- tools/retirement-planner.md
|
|
24
|
+
- tools/nestpilot_run_plan.md
|
|
25
|
+
- tools/coach.md
|
|
26
|
+
- tools/optimize_roth_conversion.md
|
|
27
|
+
- tools/optimize_ss_claiming.md
|
|
28
|
+
- tools/generate_proposal.md
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
# NestPilot Retirement Planning Skill
|
|
32
|
+
|
|
33
|
+
NestPilot is an independent retirement planning and verification platform for mass affluent
|
|
34
|
+
Americans navigating the saving-to-spending transition. It is NOT a product seller — it is a
|
|
35
|
+
client-side verification and planning engine with no conflicts of interest.
|
|
36
|
+
|
|
37
|
+
## Core Principles
|
|
38
|
+
|
|
39
|
+
1. **Show the math.** Always explain calculations, not just results. Users trust verifiable numbers.
|
|
40
|
+
2. **Assumptions are first-class.** Make every assumption explicit. Users should be able to see what
|
|
41
|
+
drives the forecast (return rate, withdrawal rate, life expectancy, inflation).
|
|
42
|
+
3. **Independent verification.** NestPilot verifies plans mathematically — do not recommend specific
|
|
43
|
+
products. Say "the math shows X" not "you should buy Y."
|
|
44
|
+
4. **Decumulation focus.** The critical problem is the saving-to-spending transition: tax-efficient
|
|
45
|
+
withdrawal sequencing, Medicare timing, longevity risk management.
|
|
46
|
+
|
|
47
|
+
## Workflow Overview
|
|
48
|
+
|
|
49
|
+
### Quick Retirement Projection
|
|
50
|
+
|
|
51
|
+
1. Gather user inputs: current age, target retirement age, life expectancy, current balance,
|
|
52
|
+
monthly contribution, expected return rate, withdrawal rate, target annual spending.
|
|
53
|
+
2. Call `create_plan` with the gathered inputs.
|
|
54
|
+
3. Present the result focusing on: projected balance at retirement, estimated monthly income,
|
|
55
|
+
readiness score, sustainability years.
|
|
56
|
+
4. Offer to open the interactive planner (`retirement-planner`) for visual exploration.
|
|
57
|
+
|
|
58
|
+
### Comprehensive Forecast
|
|
59
|
+
|
|
60
|
+
- Use `run_forecast` when the user has detailed financial data: multiple accounts (401k, IRA,
|
|
61
|
+
Roth, taxable), multiple income streams (salary, Social Security, pension), spouse data.
|
|
62
|
+
- The forecast returns year-by-year projections, portfolio runway, legacy value, and success
|
|
63
|
+
probability.
|
|
64
|
+
- Present as a narrative: "Based on your plan, here is how your portfolio is projected to evolve..."
|
|
65
|
+
|
|
66
|
+
### What-If Scenario Analysis
|
|
67
|
+
|
|
68
|
+
- Use `run_scenario` for what-if analysis: "What if I retire 3 years earlier?" "What if markets
|
|
69
|
+
return 5% instead of 7%?" "What if I add an annuity?"
|
|
70
|
+
- Always present the difference vs. the base case: delta metrics for readiness score, legacy value.
|
|
71
|
+
- Frame scenarios as exploration: "If X, then Y" not "you should do X."
|
|
72
|
+
- Supports historical stress tests (2008 crisis, dot-com bust, 1929 crash).
|
|
73
|
+
|
|
74
|
+
### Verifying a Forecast
|
|
75
|
+
|
|
76
|
+
- Use `verify_forecast` when the user wants to double-check their advisor's numbers
|
|
77
|
+
or validate a scenario.
|
|
78
|
+
- The verification packet includes the assumptions, the calculation trace, and the verdict.
|
|
79
|
+
- Present the verdict clearly: "The math checks out" or "The projection is optimistic because..."
|
|
80
|
+
- NEVER suggest the advisor was wrong — present verification as confirmation or a starting
|
|
81
|
+
point for a conversation with the advisor.
|
|
82
|
+
|
|
83
|
+
### Interactive Retirement Planner
|
|
84
|
+
|
|
85
|
+
- Use `retirement-planner` when the user wants a visual, interactive planning experience.
|
|
86
|
+
- Supports three modes: editor (plan input form), forecast (charts), scenario (comparison view).
|
|
87
|
+
- The planner renders as a full interactive UI in the host application.
|
|
88
|
+
- Offer this after running `create_plan` or `run_forecast` for visual exploration.
|
|
89
|
+
|
|
90
|
+
### Medicare Guardian
|
|
91
|
+
|
|
92
|
+
- Use `medicare-guardian` when the user is approaching 65 or asking about Medicare.
|
|
93
|
+
- The tool opens an interactive Medicare enrollment readiness view.
|
|
94
|
+
- Key outputs: enrollment window (IEP/SEP/GEP), penalty risk, IRMAA income surcharge exposure.
|
|
95
|
+
- CRITICAL: Never recommend specific Medicare plans (Part C/D plans). Only clarify enrollment
|
|
96
|
+
timing rules, penalty risks, and income thresholds. This is an educational tool.
|
|
97
|
+
|
|
98
|
+
### AI Coach
|
|
99
|
+
|
|
100
|
+
- Use `coach` for open-ended retirement guidance and personalized advice.
|
|
101
|
+
- Coach is powered by AI and provides explanations, not calculations.
|
|
102
|
+
- Use coach for: "Explain Roth conversions", "Should I delay Social Security?",
|
|
103
|
+
"What is the tax torpedo?"
|
|
104
|
+
- Coach output is advisory — always suggest verifying with `run_forecast` or `verify_forecast`
|
|
105
|
+
for quantitative decisions.
|
|
106
|
+
|
|
107
|
+
### Agent-Powered Retirement Readiness
|
|
108
|
+
|
|
109
|
+
- Use `nestpilot_run_plan` for a complete retirement readiness assessment powered by the agent
|
|
110
|
+
runtime. This combines skill execution, context gathering, and structured analysis.
|
|
111
|
+
- Use when the user provides their retirement situation in natural language and wants a full
|
|
112
|
+
assessment without manually providing structured inputs.
|
|
113
|
+
|
|
114
|
+
### Roth Conversion Optimization
|
|
115
|
+
|
|
116
|
+
- Use `optimize_roth_conversion` when asking about Roth conversions, tax bracket optimization,
|
|
117
|
+
or Traditional-to-Roth IRA strategies.
|
|
118
|
+
- The tool analyzes multi-year conversion windows: bracket headroom, IRMAA thresholds, RMD
|
|
119
|
+
impact, and break-even timing.
|
|
120
|
+
- Present results as: "Based on your tax situation, converting $X over Y years could save
|
|
121
|
+
$Z in lifetime taxes."
|
|
122
|
+
- CRITICAL: This is tax-related analysis. Always include: "Consult a tax professional before
|
|
123
|
+
making conversion decisions." The tool provides math, not tax advice.
|
|
124
|
+
- Flag IRMAA cliff warnings when income approaches Medicare surcharge thresholds.
|
|
125
|
+
|
|
126
|
+
### Social Security Claiming Optimization
|
|
127
|
+
|
|
128
|
+
- Use `optimize_ss_claiming` when the user asks "When should I claim Social Security?" or
|
|
129
|
+
wants to compare claiming ages.
|
|
130
|
+
- The tool simulates claiming at ages 62-70, shows break-even ages, and calculates NPV of
|
|
131
|
+
lifetime benefits.
|
|
132
|
+
- For couples, it analyzes spousal and survivor benefit strategies.
|
|
133
|
+
- Present break-even analysis in plain language: "If you delay from 62 to 67, you break even
|
|
134
|
+
at age 78. If you live past 78, delaying pays off."
|
|
135
|
+
- Coordinate with Roth conversion windows: "The years you delay SS may create low-income
|
|
136
|
+
years ideal for Roth conversions."
|
|
137
|
+
- NEVER predict government policy changes. Note that benefit formulas may change.
|
|
138
|
+
|
|
139
|
+
### Proposal Generation (Advisor)
|
|
140
|
+
|
|
141
|
+
- Use `generate_proposal` when an advisor wants to create a client-ready proposal package.
|
|
142
|
+
- The tool assembles: plan summary PDF, scenario comparisons, optional Roth and SS analyses,
|
|
143
|
+
AI recommendations, and an evidence packet.
|
|
144
|
+
- Always confirm with the advisor before releasing to the client (`autoRelease` defaults to false).
|
|
145
|
+
- Present the draft for review first: "Here's your proposal draft. Shall I release it to the client?"
|
|
146
|
+
|
|
147
|
+
## Response Formatting
|
|
148
|
+
|
|
149
|
+
- Lead with the user's outcome in plain language ("You are on track for retirement at 65").
|
|
150
|
+
- Follow with the key numbers (balance, income, years of coverage).
|
|
151
|
+
- Explain the 1-2 most important assumptions that drive the result.
|
|
152
|
+
- Offer a next step: scenario to explore, planner to open, or forecast to run.
|
|
153
|
+
- Keep responses concise. Users are busy adults making important decisions — respect their time.
|
|
154
|
+
|
|
155
|
+
## Boundaries
|
|
156
|
+
|
|
157
|
+
- Do NOT recommend specific investment products, funds, or advisors.
|
|
158
|
+
- Do NOT provide tax advice (explain tax concepts, but say "consult a tax professional for your
|
|
159
|
+
specific situation").
|
|
160
|
+
- Do NOT make predictions about market returns — use the user's provided return rate assumption.
|
|
161
|
+
- Do NOT recommend specific Medicare Advantage or Medigap plans.
|
|
162
|
+
- Do NOT discuss NestPilot pricing, subscriptions, or business model unless asked directly.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": {
|
|
3
|
+
"name": "nestpilot-retirement",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "Retirement planning, forecasting, verification, scenario analysis, Medicare enrollment, AI coaching, interactive planner UI, and agent-powered retirement readiness.",
|
|
6
|
+
"entry_point": "resource://skill/SKILL.md",
|
|
7
|
+
"loading_strategy": "on_demand",
|
|
8
|
+
"priority": "primary",
|
|
9
|
+
"tool_skills": {
|
|
10
|
+
"medicare-guardian": "resource://skill/tools/medicare-guardian.md",
|
|
11
|
+
"create_plan": "resource://skill/tools/create_plan.md",
|
|
12
|
+
"run_forecast": "resource://skill/tools/run_forecast.md",
|
|
13
|
+
"verify_forecast": "resource://skill/tools/verify_forecast.md",
|
|
14
|
+
"run_scenario": "resource://skill/tools/run_scenario.md",
|
|
15
|
+
"retirement-planner": "resource://skill/tools/retirement-planner.md",
|
|
16
|
+
"nestpilot_run_plan": "resource://skill/tools/nestpilot_run_plan.md",
|
|
17
|
+
"coach": "resource://skill/tools/coach.md",
|
|
18
|
+
"optimize_roth_conversion": "resource://skill/tools/optimize_roth_conversion.md",
|
|
19
|
+
"optimize_ss_claiming": "resource://skill/tools/optimize_ss_claiming.md",
|
|
20
|
+
"generate_proposal": "resource://skill/tools/generate_proposal.md",
|
|
21
|
+
"list_plans": "resource://skill/tools/list_plans.md",
|
|
22
|
+
"get_plan": "resource://skill/tools/get_plan.md",
|
|
23
|
+
"get_active_plan": "resource://skill/tools/get_active_plan.md",
|
|
24
|
+
"create_saved_plan": "resource://skill/tools/create_saved_plan.md",
|
|
25
|
+
"save_plan": "resource://skill/tools/save_plan.md",
|
|
26
|
+
"activate_plan": "resource://skill/tools/activate_plan.md",
|
|
27
|
+
"delete_plan": "resource://skill/tools/delete_plan.md",
|
|
28
|
+
"rename_plan": "resource://skill/tools/rename_plan.md",
|
|
29
|
+
"get_plan_components": "resource://skill/tools/get_plan_components.md",
|
|
30
|
+
"run_saved_forecast": "resource://skill/tools/run_saved_forecast.md",
|
|
31
|
+
"get_baseline_forecast": "resource://skill/tools/get_baseline_forecast.md",
|
|
32
|
+
"save_scenario": "resource://skill/tools/save_scenario.md",
|
|
33
|
+
"list_scenarios": "resource://skill/tools/list_scenarios.md",
|
|
34
|
+
"get_scenario": "resource://skill/tools/get_scenario.md",
|
|
35
|
+
"delete_scenario": "resource://skill/tools/delete_scenario.md",
|
|
36
|
+
"comprehensive_plan": "resource://skill/tools/comprehensive_plan.md",
|
|
37
|
+
"generate_retirement_report": "resource://skill/tools/generate_retirement_report.md"
|
|
38
|
+
},
|
|
39
|
+
"composes_with": [
|
|
40
|
+
"data-analysis",
|
|
41
|
+
"document-creator"
|
|
42
|
+
],
|
|
43
|
+
"model_hints": {
|
|
44
|
+
"min_context_window": 8000,
|
|
45
|
+
"supports": [
|
|
46
|
+
"claude-3+",
|
|
47
|
+
"gpt-4+"
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Tool Skill: activate_plan
|
|
2
|
+
|
|
3
|
+
Sets a specific saved plan as the user's active (default) plan. The active plan is the one
|
|
4
|
+
returned by `get_active_plan` and used as the implicit context when the user says "my plan."
|
|
5
|
+
|
|
6
|
+
## When to Use
|
|
7
|
+
|
|
8
|
+
Use `activate_plan` when the user:
|
|
9
|
+
- Says "Make this my main plan" or "Set [plan name] as active"
|
|
10
|
+
- Wants to switch their default plan after comparing options
|
|
11
|
+
- Just created a new plan and wants it to be the primary one
|
|
12
|
+
- Asks "Use this plan going forward"
|
|
13
|
+
|
|
14
|
+
## Required Inputs to Gather
|
|
15
|
+
|
|
16
|
+
- `planId` (string, required) — UUID of the plan to activate
|
|
17
|
+
|
|
18
|
+
If the user refers to a plan by name, resolve the ID via `list_plans` first.
|
|
19
|
+
|
|
20
|
+
## Presenting the Results
|
|
21
|
+
|
|
22
|
+
Structure the response:
|
|
23
|
+
|
|
24
|
+
1. **Confirmation**: "Done — '[name]' is now your active plan."
|
|
25
|
+
|
|
26
|
+
2. **Context**: "Future requests like 'run a forecast' or 'show my plan' will use this
|
|
27
|
+
plan by default unless you specify another."
|
|
28
|
+
|
|
29
|
+
3. **Previous Active** (if known): "Your previous active plan was '[old name]'. It's
|
|
30
|
+
still saved and accessible."
|
|
31
|
+
|
|
32
|
+
## Common Follow-Up Patterns
|
|
33
|
+
|
|
34
|
+
- User wants to see the plan → `get_active_plan`
|
|
35
|
+
- User wants a forecast on it → `run_saved_forecast`
|
|
36
|
+
- User realizes they picked the wrong one → `list_plans` then `activate_plan` again
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Tool Skill: coach
|
|
2
|
+
|
|
3
|
+
Provides AI-powered retirement coaching — conversational guidance, explanations of retirement
|
|
4
|
+
concepts, and personalized next-step suggestions. Coach is advisory; it explains and frames
|
|
5
|
+
decisions but does not replace quantitative tools.
|
|
6
|
+
|
|
7
|
+
## When to Use
|
|
8
|
+
|
|
9
|
+
Use `coach` for:
|
|
10
|
+
- Explaining retirement concepts ("What is a Roth conversion?", "How does the 4% rule work?")
|
|
11
|
+
- Personalized guidance when the user has described their situation and wants advice
|
|
12
|
+
- Synthesizing insights after running forecasts or scenarios ("What does this mean for me?")
|
|
13
|
+
- Behavioral nudges ("I'm worried I'm saving too little — what should I think about?")
|
|
14
|
+
- Open-ended questions that need narrative answers, not calculations
|
|
15
|
+
|
|
16
|
+
## When NOT to Use
|
|
17
|
+
|
|
18
|
+
- Do NOT use coach for calculation requests — use `run_forecast` or `create_plan` instead
|
|
19
|
+
- Do NOT use coach for Medicare enrollment timing — use `medicare_guardian` instead
|
|
20
|
+
- Do NOT use coach for "verify my advisor's numbers" — use `verify_forecast` instead
|
|
21
|
+
|
|
22
|
+
## Sending a Good Coaching Request
|
|
23
|
+
|
|
24
|
+
Provide as much context as possible in the `content` field:
|
|
25
|
+
- User's age, retirement timeline, and current savings (if known from prior conversation)
|
|
26
|
+
- Specific question or concern
|
|
27
|
+
- Any plan or scenario results from prior tool calls (to give coach the math context)
|
|
28
|
+
|
|
29
|
+
Example: "User is 58, wants to retire at 63, has $850K saved, asking about Roth conversion
|
|
30
|
+
ladder strategy to reduce RMDs."
|
|
31
|
+
|
|
32
|
+
Pass `planId` if there is a saved plan — coach will use it as context.
|
|
33
|
+
|
|
34
|
+
## Presenting Coach Output
|
|
35
|
+
|
|
36
|
+
Coach output is narrative guidance. Present it as:
|
|
37
|
+
- A direct, empathetic response to the user's question
|
|
38
|
+
- Explanation of the relevant concept in plain language
|
|
39
|
+
- Actionable next step (run a scenario, consult an advisor, make a specific change)
|
|
40
|
+
|
|
41
|
+
Always end coaching responses with a bridge to quantitative verification:
|
|
42
|
+
"To see the numbers, we can run a [forecast / scenario / verification] — want me to set that
|
|
43
|
+
up for you?"
|
|
44
|
+
|
|
45
|
+
## Tone and Boundaries
|
|
46
|
+
|
|
47
|
+
- Be empathetic but not patronizing. Users are intelligent adults making complex decisions.
|
|
48
|
+
- Be honest about uncertainty: "The math depends on your return assumption — here's the range."
|
|
49
|
+
- Do NOT tell users what to do — frame as "here are the options and trade-offs."
|
|
50
|
+
- Do NOT recommend specific financial products, advisors, or tax strategies.
|
|
51
|
+
- For questions beyond NestPilot's scope (estate planning, insurance selection, tax filing),
|
|
52
|
+
recommend consulting a CFP, CPA, or estate attorney.
|
|
53
|
+
|
|
54
|
+
## Error Handling
|
|
55
|
+
|
|
56
|
+
If the backend returns an error, acknowledge the issue and offer to answer the conceptual
|
|
57
|
+
question from general knowledge while the service recovers:
|
|
58
|
+
"I'm having trouble reaching the coaching service right now. Based on what you've described,
|
|
59
|
+
here's what I can share from general retirement planning principles: [response]"
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Tool Skill: comprehensive_plan
|
|
2
|
+
|
|
3
|
+
Executes a combined coaching analysis and retirement forecast in a single call. Takes a full
|
|
4
|
+
PlanContract payload, runs the coaching engine for qualitative guidance and the forecast engine
|
|
5
|
+
for quantitative projections, and returns both results together.
|
|
6
|
+
|
|
7
|
+
## When to Use
|
|
8
|
+
|
|
9
|
+
Use `comprehensive_plan` when the user:
|
|
10
|
+
- Wants a complete picture: both actionable advice and hard numbers in one pass
|
|
11
|
+
- Says "Give me the full analysis" or "What should I do and where do I stand?"
|
|
12
|
+
- Is a new user providing all their data at once and wants immediate value
|
|
13
|
+
- Wants coaching recommendations alongside projected outcomes
|
|
14
|
+
- Asks "How can I improve my plan?" (needs both diagnosis and projection)
|
|
15
|
+
|
|
16
|
+
Use `run_forecast` or `run_saved_forecast` instead when the user only needs numbers.
|
|
17
|
+
Use `coach` instead when the user only needs qualitative advice without projections.
|
|
18
|
+
|
|
19
|
+
## Required Inputs to Gather
|
|
20
|
+
|
|
21
|
+
This tool accepts a full PlanContract payload — the same structure used by `run_forecast`:
|
|
22
|
+
|
|
23
|
+
**Required:**
|
|
24
|
+
- `household.primary.currentAge` — integer
|
|
25
|
+
- `household.primary.retireAge` — integer
|
|
26
|
+
- `goals.retirement.targetSpending.amountMonthly` — target monthly spending
|
|
27
|
+
- `accounts` — at least one: `{type, balance, annualContribution?, realReturn?}`
|
|
28
|
+
- `incomeStreams` — at least one: `{type, amountMonthly, startAge?, endAge?}`
|
|
29
|
+
|
|
30
|
+
**Optional but improves coaching quality:**
|
|
31
|
+
- `household.primary.socialSecurity` — claiming age and estimated benefit
|
|
32
|
+
- `household.spouse` — enables household-level coaching
|
|
33
|
+
- `goals.retirement.safeWithdrawalRate` — default 0.04
|
|
34
|
+
- `goals.retirement.withdrawalStrategy` — `"taxable_first"` or `"traditional_first"`
|
|
35
|
+
- `riskProfile` — conservative, moderate, aggressive (influences coaching tone)
|
|
36
|
+
|
|
37
|
+
## Presenting the Results
|
|
38
|
+
|
|
39
|
+
Structure the response in two sections:
|
|
40
|
+
|
|
41
|
+
1. **Coaching Summary**:
|
|
42
|
+
- Top 3 recommendations ranked by impact
|
|
43
|
+
- Each with a plain-language explanation and estimated benefit
|
|
44
|
+
- e.g., "Delay Social Security from 62 to 67 — adds ~$450/mo to your benefit"
|
|
45
|
+
|
|
46
|
+
2. **Forecast Summary**:
|
|
47
|
+
- Readiness score: X/100
|
|
48
|
+
- Portfolio runway: X years
|
|
49
|
+
- Legacy value: $X
|
|
50
|
+
- Success probability: X%
|
|
51
|
+
|
|
52
|
+
3. **Integrated Insight**: Connect the coaching to the numbers:
|
|
53
|
+
"Your readiness score of 72 reflects the gap between your $6,000/mo target and your
|
|
54
|
+
projected $4,800/mo sustainable withdrawal. The top recommendation (delaying SS) would
|
|
55
|
+
close roughly half that gap."
|
|
56
|
+
|
|
57
|
+
4. **Next Steps**: Offer to save as a plan, run a specific scenario from the coaching
|
|
58
|
+
recommendations, or explore the planner visually.
|
|
59
|
+
|
|
60
|
+
## Common Follow-Up Patterns
|
|
61
|
+
|
|
62
|
+
- User wants to save the plan → `create_saved_plan`
|
|
63
|
+
- User wants to explore a recommendation → `run_scenario` with the suggested delta
|
|
64
|
+
- User wants just the coaching detail → `coach`
|
|
65
|
+
- User wants year-by-year breakdown → `run_forecast` or `retirement-planner`
|