Overview
FinMCP supports flexible output formatting to optimize data presentation for different use cases. Every tool accepts optional output parameters that control:
Response format : JSON (default) or Markdown tables
Preview limit : Number of rows to display in Markdown tables
Output Options Schema
All FinMCP tools extend a common output options schema defined in src/index.ts:
const responseFormatSchema = z . enum ([ "json" , "markdown" ]). default ( "json" );
const outputOptionsSchema = z . object ({
response_format: responseFormatSchema . optional (),
preview_limit: z . number (). int (). min ( 1 ). max ( 200 ). optional (),
save: saveSchema , // Covered in Data Export guide
});
These options are merged into every tool’s schema:
const historySchema = tickerSchema
. extend ({
period: z . string (). optional (),
interval: z . string (). optional (),
// ... other parameters
})
. merge ( outputOptionsSchema ); // Adds response_format, preview_limit, save
When response_format is "json" or omitted, FinMCP returns structured JSON data.
DataFrame Response
DataFrames are serialized with metadata about structure:
{
"data" : {
"__type__" : "dataframe" ,
"columns" : [ "Open" , "High" , "Low" , "Close" , "Volume" ],
"index" : [ "2024-01-01T00:00:00" , "2024-01-02T00:00:00" ],
"data" : [
[ 150.0 , 152.5 , 149.8 , 151.2 , 50000000 ],
[ 151.5 , 153.0 , 150.5 , 152.8 , 48000000 ]
]
},
"saved_path" : null
}
Series Response
Series (1-dimensional data) include index and values:
{
"data" : {
"__type__" : "series" ,
"name" : "Close" ,
"index" : [ "2024-01-01T00:00:00" , "2024-01-02T00:00:00" ],
"data" : [ 151.2 , 152.8 ]
},
"saved_path" : null
}
Object/Array Response
Non-tabular data is returned as plain JSON:
{
"data" : {
"symbol" : "AAPL" ,
"longName" : "Apple Inc." ,
"marketCap" : 3000000000000
},
"saved_path" : null
}
The saved_path field indicates if data was exported to a file. See Data Export for details.
When response_format is "markdown", tabular data (DataFrames and Series) is formatted as Markdown tables.
Implementation
The toMarkdown function in src/index.ts:176 handles Markdown conversion:
function toMarkdown ( result : unknown , previewLimit : number ) : string {
if ( isDataFrame ( result )) {
const rows = result . data . slice ( 0 , previewLimit );
const header = [ "index" , ... result . columns ];
const separator = header . map (() => "---" );
const body = rows . map (( row , idx ) => [ result . index [ idx ], ... row ]);
const table = [ header , separator , ... body ]
. map (( row ) => row . map (( cell ) => String ( cell ?? "" )). join ( " | " ))
. join ( " \n " );
return table ;
}
if ( isSeries ( result )) {
const rows = result . data . slice ( 0 , previewLimit ). map (( value , idx ) => [ result . index [ idx ], value ]);
const header = [ "index" , result . name ?? "value" ];
const separator = header . map (() => "---" );
const table = [ header , separator , ... rows ]
. map (( row ) => row . map (( cell ) => String ( cell ?? "" )). join ( " | " ))
. join ( " \n " );
return table ;
}
return ` \n\n\`\`\` json \n ${ stringifyJson ( result ) } \n\`\`\`\n ` ;
}
DataFrame Markdown Example
yf_ticker_history(
ticker = "AAPL",
period = "5d",
response_format = "markdown",
preview_limit = 3
)
Series Markdown Example
yf_ticker_dividends(
ticker = "AAPL",
response_format = "markdown",
preview_limit = 5
)
preview_limit Parameter
The preview_limit parameter controls how many rows appear in Markdown tables.
Number of rows to include in Markdown table output. Must be between 1 and 200.
Default Behavior
From src/index.ts:39:
function extractPreviewLimit ( options ?: OutputOptions ) : number {
return options ?. preview_limit ?? 25 ; // Default: 25 rows
}
Usage Example
// Get 1 year of daily data, but only preview first 10 days
yf_ticker_history (
ticker = "MSFT" ,
period = "1y" ,
response_format = "markdown" ,
preview_limit = 10 // Only show 10 rows in table
)
Use preview_limit with save to view a preview while saving the full dataset to a file.
Non-Tabular Data in Markdown
When response_format="markdown" is used with non-tabular data (objects, arrays), the data is returned as a JSON code block:
return ` \n\n\`\`\` json \n ${ stringifyJson ( result ) } \n\`\`\`\n ` ;
Example:
yf_ticker_info(
ticker = "TSLA",
response_format = "markdown"
)
Response Building
The buildResponse function in src/index.ts:201 orchestrates format selection:
async function buildResponse ( toolName : string , result : unknown , options ?: OutputOptions ) {
let savedPath : string | undefined ;
if ( options ?. save ) {
savedPath = await saveResult ( result , options . save , toolName );
}
if (( options ?. response_format ?? "json" ) === "markdown" ) {
const preview = toMarkdown ( result , extractPreviewLimit ( options ));
const savedNote = savedPath ? ` \n\n Saved to ${ savedPath } ` : "" ;
return preview + savedNote ;
}
const payload = {
data: result ,
saved_path: savedPath ?? null ,
};
return stringifyJson ( payload );
}
Best Practices
Use JSON for Processing JSON format preserves full data structure and types, ideal for programmatic analysis
Use Markdown for Display Markdown tables are human-readable and render well in chat interfaces
Combine with Export Use save parameter to persist full data while getting a preview response
Adjust Preview Limit Set preview_limit based on context size constraints and readability needs