@@ -64,6 +64,13 @@ const GetScenarioDataInputSchema = z.object({
6464 ) ,
6565} ) ;
6666
67+ const GetScenarioDataOutputSchema = z . object ( {
68+ templates : z . array ( ScenarioTemplateSchema ) ,
69+ defaultInputs : ScenarioInputsSchema ,
70+ customProjections : z . array ( MonthlyProjectionSchema ) . optional ( ) ,
71+ customSummary : ScenarioSummarySchema . optional ( ) ,
72+ } ) ;
73+
6774// Types derived from schemas
6875type ScenarioInputs = z . infer < typeof ScenarioInputsSchema > ;
6976type MonthlyProjection = z . infer < typeof MonthlyProjectionSchema > ;
@@ -243,6 +250,37 @@ const DEFAULT_INPUTS: ScenarioInputs = {
243250 fixedCosts : 30000 ,
244251} ;
245252
253+ // ============================================================================
254+ // Formatters for text output
255+ // ============================================================================
256+
257+ function formatCurrency ( value : number ) : string {
258+ const absValue = Math . abs ( value ) ;
259+ const sign = value < 0 ? "-" : "" ;
260+ if ( absValue >= 1_000_000 ) {
261+ return `${ sign } $${ ( absValue / 1_000_000 ) . toFixed ( 2 ) } M` ;
262+ }
263+ if ( absValue >= 1_000 ) {
264+ return `${ sign } $${ ( absValue / 1_000 ) . toFixed ( 1 ) } K` ;
265+ }
266+ return `${ sign } $${ Math . round ( absValue ) } ` ;
267+ }
268+
269+ function formatScenarioSummary (
270+ summary : ScenarioSummary ,
271+ label : string ,
272+ ) : string {
273+ return [
274+ `${ label } :` ,
275+ ` Ending MRR: ${ formatCurrency ( summary . endingMRR ) } ` ,
276+ ` ARR: ${ formatCurrency ( summary . arr ) } ` ,
277+ ` Total Revenue: ${ formatCurrency ( summary . totalRevenue ) } ` ,
278+ ` Total Profit: ${ formatCurrency ( summary . totalProfit ) } ` ,
279+ ` MRR Growth: ${ summary . mrrGrowthPct . toFixed ( 1 ) } %` ,
280+ ` Break-even: ${ summary . breakEvenMonth ? `Month ${ summary . breakEvenMonth } ` : "Not achieved" } ` ,
281+ ] . join ( "\n" ) ;
282+ }
283+
246284// ============================================================================
247285// MCP Server
248286// ============================================================================
@@ -269,6 +307,7 @@ export function createServer(): McpServer {
269307 description :
270308 "Returns SaaS scenario templates and optionally computes custom projections for given inputs" ,
271309 inputSchema : GetScenarioDataInputSchema . shape ,
310+ outputSchema : GetScenarioDataOutputSchema . shape ,
272311 _meta : { [ RESOURCE_URI_META_KEY ] : resourceUri } ,
273312 } ,
274313 async ( args : {
@@ -278,18 +317,28 @@ export function createServer(): McpServer {
278317 ? calculateScenario ( args . customInputs )
279318 : undefined ;
280319
320+ const text = [
321+ "SaaS Scenario Modeler" ,
322+ "=" . repeat ( 40 ) ,
323+ "" ,
324+ "Available Templates:" ,
325+ ...SCENARIO_TEMPLATES . map (
326+ ( t ) => ` ${ t . icon } ${ t . name } : ${ t . description } ` ,
327+ ) ,
328+ "" ,
329+ customScenario
330+ ? formatScenarioSummary ( customScenario . summary , "Custom Scenario" )
331+ : "Use customInputs parameter to compute projections for a specific scenario." ,
332+ ] . join ( "\n" ) ;
333+
281334 return {
282- content : [
283- {
284- type : "text" ,
285- text : JSON . stringify ( {
286- templates : SCENARIO_TEMPLATES ,
287- defaultInputs : DEFAULT_INPUTS ,
288- customProjections : customScenario ?. projections ,
289- customSummary : customScenario ?. summary ,
290- } ) ,
291- } ,
292- ] ,
335+ content : [ { type : "text" , text } ] ,
336+ structuredContent : {
337+ templates : SCENARIO_TEMPLATES ,
338+ defaultInputs : DEFAULT_INPUTS ,
339+ customProjections : customScenario ?. projections ,
340+ customSummary : customScenario ?. summary ,
341+ } ,
293342 } ;
294343 } ,
295344 ) ;
0 commit comments