@etsquare/mcp-server-sec 0.5.2 → 0.6.2
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/dist/etsquare-client.d.ts +9 -0
- package/dist/etsquare-client.js +18 -0
- package/dist/index.js +161 -16
- package/package.json +1 -1
|
@@ -53,6 +53,14 @@ interface KpiExtractionsApiInput {
|
|
|
53
53
|
fiscal_year?: number;
|
|
54
54
|
limit?: number;
|
|
55
55
|
}
|
|
56
|
+
/** Company research packet request. */
|
|
57
|
+
interface CompanyResearchApiInput {
|
|
58
|
+
ticker: string;
|
|
59
|
+
sections?: Array<'snapshot' | 'financials' | 'earnings' | 'narrative' | 'ownership' | 'kpis'>;
|
|
60
|
+
detail_level?: 'summary' | 'standard' | 'full';
|
|
61
|
+
peers?: string[];
|
|
62
|
+
n_periods?: number;
|
|
63
|
+
}
|
|
56
64
|
/** Server-side KPI query with metric filtering. */
|
|
57
65
|
interface QueryKpisApiInput {
|
|
58
66
|
select?: string[];
|
|
@@ -96,6 +104,7 @@ export declare class ETSquareClient {
|
|
|
96
104
|
getInsiderTransactions(input: InsiderTransactionsApiInput): Promise<Record<string, unknown>>;
|
|
97
105
|
getEarningsActuals(input: EarningsActualsApiInput): Promise<Record<string, unknown>>;
|
|
98
106
|
getKpiExtractions(input: KpiExtractionsApiInput): Promise<Record<string, unknown>>;
|
|
107
|
+
getCompanyResearch(input: CompanyResearchApiInput): Promise<Record<string, unknown>>;
|
|
99
108
|
queryKpis(input: QueryKpisApiInput): Promise<Record<string, unknown>>;
|
|
100
109
|
discoverMetrics(input: DiscoverMetricsApiInput): Promise<Record<string, unknown>>;
|
|
101
110
|
getChunk(input: GetChunkInput): Promise<Record<string, unknown>>;
|
package/dist/etsquare-client.js
CHANGED
|
@@ -158,6 +158,24 @@ export class ETSquareClient {
|
|
|
158
158
|
body: JSON.stringify(body),
|
|
159
159
|
});
|
|
160
160
|
}
|
|
161
|
+
async getCompanyResearch(input) {
|
|
162
|
+
const body = {
|
|
163
|
+
ticker: input.ticker,
|
|
164
|
+
};
|
|
165
|
+
if (input.sections && input.sections.length > 0)
|
|
166
|
+
body.sections = input.sections;
|
|
167
|
+
if (input.detail_level)
|
|
168
|
+
body.detail_level = input.detail_level;
|
|
169
|
+
if (input.peers && input.peers.length > 0)
|
|
170
|
+
body.peers = input.peers;
|
|
171
|
+
if (input.n_periods !== undefined)
|
|
172
|
+
body.n_periods = input.n_periods;
|
|
173
|
+
return this.request('/api/v1/company/research', {
|
|
174
|
+
method: 'POST',
|
|
175
|
+
headers: this.headers,
|
|
176
|
+
body: JSON.stringify(body),
|
|
177
|
+
});
|
|
178
|
+
}
|
|
161
179
|
async queryKpis(input) {
|
|
162
180
|
const body = {
|
|
163
181
|
limit: input.limit || 50,
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* @etsquare/mcp-server-sec v0.
|
|
3
|
+
* @etsquare/mcp-server-sec v0.6.0
|
|
4
4
|
* MCP server for SEC Intelligence: search SEC filings,
|
|
5
5
|
* resolve company tickers, execute financial metrics templates,
|
|
6
6
|
* compare companies, and access weekly briefs.
|
|
@@ -57,7 +57,7 @@ if (!apiKey) {
|
|
|
57
57
|
process.exit(1);
|
|
58
58
|
}
|
|
59
59
|
const client = new ETSquareClient({ baseUrl, apiKey });
|
|
60
|
-
log('info', `ETSquare MCP Server v0.
|
|
60
|
+
log('info', `ETSquare MCP Server v0.6.0 starting with backend: ${baseUrl}`);
|
|
61
61
|
// ─── Item Code Labels ───────────────────────────────────────────────────────
|
|
62
62
|
const ITEM_CODE_LABELS = {
|
|
63
63
|
// 10-K
|
|
@@ -358,7 +358,16 @@ function buildMarkdownTable(colNames, rows, maxRows = 20) {
|
|
|
358
358
|
// ─── MCP Server ─────────────────────────────────────────────────────────────
|
|
359
359
|
const server = new McpServer({
|
|
360
360
|
name: 'etsquare-mcp-sec',
|
|
361
|
-
version: '0.
|
|
361
|
+
version: '0.6.0',
|
|
362
|
+
});
|
|
363
|
+
const CITATION_POLICY = 'Citation policy (required): When `cite: true` appears in the response, you MUST include ' +
|
|
364
|
+
'the sec_url for every filing referenced in the answer. Cite each URL inline with its claim.';
|
|
365
|
+
const baseRegisterTool = server.registerTool.bind(server);
|
|
366
|
+
server.registerTool = ((name, config, handler) => {
|
|
367
|
+
const description = typeof config?.description === 'string' && config.description.trim().length > 0
|
|
368
|
+
? `${config.description}\n\n${CITATION_POLICY}`
|
|
369
|
+
: CITATION_POLICY;
|
|
370
|
+
return baseRegisterTool(name, { ...config, description }, handler);
|
|
362
371
|
});
|
|
363
372
|
// ─── Tool 1: Company Lookup ─────────────────────────────────────────────────
|
|
364
373
|
server.registerTool('etsquare_lookup_company', {
|
|
@@ -406,7 +415,7 @@ server.registerTool('etsquare_lookup_company', {
|
|
|
406
415
|
// ─── Tool 2: SEC Filing Search ──────────────────────────────────────────────
|
|
407
416
|
server.registerTool('etsquare_search', {
|
|
408
417
|
title: 'Search SEC Filings',
|
|
409
|
-
description: 'Search
|
|
418
|
+
description: 'Search 4.0M+ SEC filing sections (10-K, 10-Q, 8-K) with hybrid retrieval. ' +
|
|
410
419
|
'Returns verbatim filing text with citations — best for qualitative research.\n\n' +
|
|
411
420
|
'Execution contract (required):\n' +
|
|
412
421
|
'- mode_lock: NARRATIVE (recommended) | HYBRID\n' +
|
|
@@ -496,6 +505,7 @@ server.registerTool('etsquare_search', {
|
|
|
496
505
|
? buildColumnMeta(result.xbrl_output_schema?.columns || [], xbrlMetrics)
|
|
497
506
|
: null;
|
|
498
507
|
const structured = {
|
|
508
|
+
cite: true,
|
|
499
509
|
search_context: buildSearchContext(result, input.query),
|
|
500
510
|
results: searchResults
|
|
501
511
|
.slice(0, input.top_k || 5)
|
|
@@ -678,6 +688,13 @@ server.registerTool('etsquare_financial_statements', {
|
|
|
678
688
|
table += `| **${labelDisplay(dk)}** | ${values.join(' | ')} |\n`;
|
|
679
689
|
}
|
|
680
690
|
}
|
|
691
|
+
// Filing source URLs per period
|
|
692
|
+
const periodUrls = periods
|
|
693
|
+
.filter((p) => p.sec_url)
|
|
694
|
+
.map((p) => `- FY${p.fiscal_year}${p.fiscal_period !== 'FY' ? ' ' + p.fiscal_period : ''}: ${p.sec_url}`);
|
|
695
|
+
if (periodUrls.length > 0) {
|
|
696
|
+
table += `\n**Filing Sources:**\n${periodUrls.join('\n')}\n`;
|
|
697
|
+
}
|
|
681
698
|
// Provenance note
|
|
682
699
|
const firstPeriod = periods[0];
|
|
683
700
|
const sampleLine = firstPeriod?.lines?.[labels[0]];
|
|
@@ -752,14 +769,15 @@ server.registerTool('etsquare_insider_trades', {
|
|
|
752
769
|
text += `\n\n`;
|
|
753
770
|
// Transaction table — show top 20
|
|
754
771
|
const shown = transactions.slice(0, 20);
|
|
755
|
-
text += `| Date | Insider | Title | Type | Shares | Price | Value |\n`;
|
|
756
|
-
text +=
|
|
772
|
+
text += `| Date | Insider | Title | Type | Shares | Price | Value | Filing |\n`;
|
|
773
|
+
text += `|------|---------|-------|------|-------:|------:|------:|:------:|\n`;
|
|
757
774
|
for (const t of shown) {
|
|
758
775
|
const shares = t.shares != null ? t.shares.toLocaleString() : '—';
|
|
759
776
|
const price = t.price_per_share != null ? `$${t.price_per_share.toFixed(2)}` : '—';
|
|
760
777
|
const value = t.total_value != null ? fmtVal(t.total_value) : '—';
|
|
761
778
|
const typeLabel = t.is_derivative ? `${t.transaction_type} *` : t.transaction_type;
|
|
762
|
-
|
|
779
|
+
const filing = t.sec_url ? `[SEC](${t.sec_url})` : '—';
|
|
780
|
+
text += `| ${t.transaction_date} | ${t.owner_name} | ${t.officer_title || '—'} | ${typeLabel} | ${shares} | ${price} | ${value} | ${filing} |\n`;
|
|
763
781
|
}
|
|
764
782
|
if (transactions.length > 20) {
|
|
765
783
|
text += `\n*Showing 20 of ${transactions.length} transactions.*\n`;
|
|
@@ -845,6 +863,19 @@ server.registerTool('etsquare_institutional_holdings', {
|
|
|
845
863
|
if (holders.length > 20) {
|
|
846
864
|
text += `\n*Showing 20 of ${holders.length} tracked holders.*\n`;
|
|
847
865
|
}
|
|
866
|
+
// Filing source URLs for this quarter (deduplicated by manager)
|
|
867
|
+
const seenMgrs = new Set();
|
|
868
|
+
const quarterLinks = [];
|
|
869
|
+
for (const h of holders) {
|
|
870
|
+
const key = h.manager_cik || h.manager_name;
|
|
871
|
+
if (h.sec_url && key && !seenMgrs.has(key)) {
|
|
872
|
+
seenMgrs.add(key);
|
|
873
|
+
quarterLinks.push(`- ${h.manager_name || 'Unknown'}: [13F Filing](${h.sec_url})`);
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
if (quarterLinks.length > 0) {
|
|
877
|
+
text += `\n**13F Filing Sources (${q}):**\n${quarterLinks.slice(0, 10).join('\n')}\n`;
|
|
878
|
+
}
|
|
848
879
|
text += '\n';
|
|
849
880
|
}
|
|
850
881
|
text += `*Source: SEC 13F-HR filings via EDGAR. Tracked managers only — not full institutional ownership.*`;
|
|
@@ -928,6 +959,18 @@ server.registerTool('etsquare_earnings_actuals', {
|
|
|
928
959
|
const conf = a.confidence != null ? `${(a.confidence * 100).toFixed(0)}%` : '—';
|
|
929
960
|
text += `| ${a.filing_date || '—'} | ${a.metric_name} | ${val} | ${gaap} | ${fy} | ${fq} | ${conf} |\n`;
|
|
930
961
|
}
|
|
962
|
+
// Filing source URLs (deduplicated by accession)
|
|
963
|
+
const seenAccessions = new Set();
|
|
964
|
+
const filingLinks = [];
|
|
965
|
+
for (const a of actuals) {
|
|
966
|
+
if (a.sec_url && a.accession_number && !seenAccessions.has(a.accession_number)) {
|
|
967
|
+
seenAccessions.add(a.accession_number);
|
|
968
|
+
filingLinks.push(`- ${a.filing_date || '—'}: ${a.sec_url}`);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
if (filingLinks.length > 0) {
|
|
972
|
+
text += `\n**Filing Sources:**\n${filingLinks.join('\n')}\n`;
|
|
973
|
+
}
|
|
931
974
|
text += '\n';
|
|
932
975
|
}
|
|
933
976
|
if (guidance.length > 0) {
|
|
@@ -943,6 +986,18 @@ server.registerTool('etsquare_earnings_actuals', {
|
|
|
943
986
|
const fq = g.fiscal_quarter ?? '—';
|
|
944
987
|
text += `| ${g.filing_date || '—'} | ${g.metric_name} | ${low} | ${high} | ${mid} | ${gaap} | ${fy} | ${fq} |\n`;
|
|
945
988
|
}
|
|
989
|
+
// Filing source URLs for guidance (deduplicated)
|
|
990
|
+
const seenGuidanceAcc = new Set();
|
|
991
|
+
const guidanceLinks = [];
|
|
992
|
+
for (const g of guidance) {
|
|
993
|
+
if (g.sec_url && g.accession_number && !seenGuidanceAcc.has(g.accession_number)) {
|
|
994
|
+
seenGuidanceAcc.add(g.accession_number);
|
|
995
|
+
guidanceLinks.push(`- ${g.filing_date || '—'}: ${g.sec_url}`);
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
if (guidanceLinks.length > 0) {
|
|
999
|
+
text += `\n**Guidance Filing Sources:**\n${guidanceLinks.join('\n')}\n`;
|
|
1000
|
+
}
|
|
946
1001
|
text += '\n';
|
|
947
1002
|
}
|
|
948
1003
|
text += `*Source: SEC 8-K Item 2.02 press releases — deterministic extraction from issuer filings.*`;
|
|
@@ -1001,6 +1056,7 @@ server.registerTool('etsquare_kpi_extractions', {
|
|
|
1001
1056
|
content: [{
|
|
1002
1057
|
type: 'text',
|
|
1003
1058
|
text: JSON.stringify({
|
|
1059
|
+
cite: true,
|
|
1004
1060
|
count,
|
|
1005
1061
|
filters,
|
|
1006
1062
|
extractions,
|
|
@@ -1055,6 +1111,9 @@ server.registerTool('etsquare_kpi_extractions', {
|
|
|
1055
1111
|
text += `${entries.join('\n')}\n`;
|
|
1056
1112
|
}
|
|
1057
1113
|
}
|
|
1114
|
+
if (extraction.sec_url) {
|
|
1115
|
+
text += `SEC Filing: ${extraction.sec_url}\n`;
|
|
1116
|
+
}
|
|
1058
1117
|
if (extraction.notes) {
|
|
1059
1118
|
text += `Notes: ${extraction.notes}\n`;
|
|
1060
1119
|
}
|
|
@@ -1196,12 +1255,13 @@ server.registerTool('etsquare_query_kpis', {
|
|
|
1196
1255
|
return {
|
|
1197
1256
|
content: [{
|
|
1198
1257
|
type: 'text',
|
|
1199
|
-
text: JSON.stringify({ count, data }, null, 2),
|
|
1258
|
+
text: JSON.stringify({ cite: true, count, data }, null, 2),
|
|
1200
1259
|
}],
|
|
1201
1260
|
};
|
|
1202
1261
|
}
|
|
1203
|
-
// Build markdown table
|
|
1204
|
-
const
|
|
1262
|
+
// Build markdown table — exclude sec_url from columns (too wide for table)
|
|
1263
|
+
const excludeFromTable = new Set(['sec_url']);
|
|
1264
|
+
const columns = Object.keys(data[0]).filter(c => !excludeFromTable.has(c));
|
|
1205
1265
|
let text = `Found ${count} results.\n\n`;
|
|
1206
1266
|
text += '| ' + columns.join(' | ') + ' |\n';
|
|
1207
1267
|
text += '| ' + columns.map(() => '---').join(' | ') + ' |\n';
|
|
@@ -1219,6 +1279,18 @@ server.registerTool('etsquare_query_kpis', {
|
|
|
1219
1279
|
if (count > data.length) {
|
|
1220
1280
|
text += `\nShowing ${data.length} of ${count} results.`;
|
|
1221
1281
|
}
|
|
1282
|
+
// Filing source URLs (deduplicated by ticker)
|
|
1283
|
+
const seenTickers = new Set();
|
|
1284
|
+
const filingLinks = [];
|
|
1285
|
+
for (const row of data) {
|
|
1286
|
+
if (row.sec_url && row.ticker && !seenTickers.has(row.ticker)) {
|
|
1287
|
+
seenTickers.add(row.ticker);
|
|
1288
|
+
filingLinks.push(`- ${row.ticker}: ${row.sec_url}`);
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
if (filingLinks.length > 0) {
|
|
1292
|
+
text += `\n\n**Filing Sources:**\n${filingLinks.join('\n')}`;
|
|
1293
|
+
}
|
|
1222
1294
|
// Append summary stats if available
|
|
1223
1295
|
const summary = result.summary;
|
|
1224
1296
|
if (summary && typeof summary === 'object' && Object.keys(summary).length > 0) {
|
|
@@ -1231,7 +1303,7 @@ server.registerTool('etsquare_query_kpis', {
|
|
|
1231
1303
|
}
|
|
1232
1304
|
}
|
|
1233
1305
|
// Provenance hint
|
|
1234
|
-
text += '\n*Each row includes extraction_id
|
|
1306
|
+
text += '\n*Each row includes extraction_id. Filing source URLs are listed above. Use response_format="structured" for per-row sec_url in JSON.*';
|
|
1235
1307
|
return { content: [{ type: 'text', text }] };
|
|
1236
1308
|
}
|
|
1237
1309
|
catch (error) {
|
|
@@ -1341,6 +1413,7 @@ server.registerTool('etsquare_execute_metrics', {
|
|
|
1341
1413
|
const autoHint = deriveMetricsVizHint(rows, { columns: columnMeta });
|
|
1342
1414
|
const colNames = columnMeta.map((c) => c.name);
|
|
1343
1415
|
const structured = {
|
|
1416
|
+
cite: true,
|
|
1344
1417
|
template_id: input.template_id,
|
|
1345
1418
|
columns: columnMeta,
|
|
1346
1419
|
rows,
|
|
@@ -1353,18 +1426,35 @@ server.registerTool('etsquare_execute_metrics', {
|
|
|
1353
1426
|
return { content: [{ type: 'text', text: JSON.stringify(structured, null, 2) }] };
|
|
1354
1427
|
}
|
|
1355
1428
|
// ── Text response path (existing behavior) ──
|
|
1356
|
-
const
|
|
1429
|
+
const allColNames = columns.length > 0
|
|
1357
1430
|
? columns.map((c) => c.name)
|
|
1358
1431
|
: Object.keys(rows[0] || {});
|
|
1432
|
+
// Exclude sec_url from table columns (too wide for markdown)
|
|
1433
|
+
const colNames = allColNames.filter((c) => c !== 'sec_url');
|
|
1359
1434
|
const table = buildMarkdownTable(colNames, rows);
|
|
1360
1435
|
const suffix = truncated || rows.length > 20
|
|
1361
1436
|
? `\n\n(Showing ${Math.min(rows.length, 20)} of ${rowCount} rows${truncated ? ', results truncated' : ''})`
|
|
1362
1437
|
: '';
|
|
1438
|
+
// Filing source URLs (deduplicated)
|
|
1439
|
+
let filingSources = '';
|
|
1440
|
+
const seenUrls = new Set();
|
|
1441
|
+
const urlLinks = [];
|
|
1442
|
+
for (const row of rows) {
|
|
1443
|
+
if (row.sec_url && !seenUrls.has(row.sec_url)) {
|
|
1444
|
+
seenUrls.add(row.sec_url);
|
|
1445
|
+
const label = row.ticker || row.TICKER || '';
|
|
1446
|
+
const year = row.fiscal_year || row.FISCAL_YEAR || row.year || '';
|
|
1447
|
+
urlLinks.push(`- ${label} ${year}: ${row.sec_url}`);
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
if (urlLinks.length > 0) {
|
|
1451
|
+
filingSources = `\n\n**Filing Sources:**\n${urlLinks.slice(0, 20).join('\n')}`;
|
|
1452
|
+
}
|
|
1363
1453
|
log('info', `Metrics query returned ${rowCount} rows`);
|
|
1364
1454
|
return {
|
|
1365
1455
|
content: [{
|
|
1366
1456
|
type: 'text',
|
|
1367
|
-
text: `Metrics data (${rowCount} rows):\n\n${table}${suffix}`,
|
|
1457
|
+
text: `Metrics data (${rowCount} rows):\n\n${table}${suffix}${filingSources}`,
|
|
1368
1458
|
}],
|
|
1369
1459
|
};
|
|
1370
1460
|
}
|
|
@@ -1513,10 +1603,14 @@ server.registerTool('etsquare_get_chunk', {
|
|
|
1513
1603
|
? result.chunk_text
|
|
1514
1604
|
: '';
|
|
1515
1605
|
const chunkLength = result.chunk_text_length;
|
|
1606
|
+
const secUrl = result.sec_url;
|
|
1607
|
+
let header = `Chunk ${input.chunk_id}${typeof chunkLength === 'number' ? ` (${chunkLength} chars)` : ''}`;
|
|
1608
|
+
if (secUrl)
|
|
1609
|
+
header += `\nSEC Filing: ${secUrl}`;
|
|
1516
1610
|
return {
|
|
1517
1611
|
content: [{
|
|
1518
1612
|
type: 'text',
|
|
1519
|
-
text:
|
|
1613
|
+
text: `${header}\n\n${chunkText}`,
|
|
1520
1614
|
}],
|
|
1521
1615
|
};
|
|
1522
1616
|
}
|
|
@@ -1735,7 +1829,7 @@ server.registerTool('etsquare_weekly_brief', {
|
|
|
1735
1829
|
// ── Structured response path ──
|
|
1736
1830
|
if (input.response_format === 'structured') {
|
|
1737
1831
|
log('info', `Weekly brief returned: ${(brief.notable || []).length} notable, ${(brief.edge_signals || []).length} edge signals`);
|
|
1738
|
-
return { content: [{ type: 'text', text: JSON.stringify(output, null, 2) }] };
|
|
1832
|
+
return { content: [{ type: 'text', text: JSON.stringify({ cite: true, ...output }, null, 2) }] };
|
|
1739
1833
|
}
|
|
1740
1834
|
// ── Text response path ──
|
|
1741
1835
|
const lines = [];
|
|
@@ -1782,7 +1876,58 @@ server.registerTool('etsquare_weekly_brief', {
|
|
|
1782
1876
|
};
|
|
1783
1877
|
}
|
|
1784
1878
|
});
|
|
1879
|
+
// ─── Tool 9: Company Research ──────────────────────────────────────────────
|
|
1880
|
+
server.registerTool('etsquare_company_research', {
|
|
1881
|
+
title: 'Company Research Packet',
|
|
1882
|
+
description: 'Returns a citation-grounded research packet for one company in a single call. ' +
|
|
1883
|
+
'Server-side orchestration assembles financials, earnings, narrative, ownership, and KPIs with SEC provenance.',
|
|
1884
|
+
inputSchema: {
|
|
1885
|
+
ticker: z.string().min(1).max(10)
|
|
1886
|
+
.describe('Company ticker (e.g., "AAPL", "NVDA"). Resolve names first with etsquare_lookup_company.'),
|
|
1887
|
+
sections: z.array(z.enum(['snapshot', 'financials', 'earnings', 'narrative', 'ownership', 'kpis']))
|
|
1888
|
+
.optional()
|
|
1889
|
+
.describe('Sections to include. Returns all if omitted.'),
|
|
1890
|
+
detail_level: z.enum(['summary', 'standard', 'full']).default('standard')
|
|
1891
|
+
.describe('Controls response size: summary (~4K tokens), standard (~8K), full (~15K).'),
|
|
1892
|
+
peers: z.array(z.string().min(1).max(10)).max(3).optional()
|
|
1893
|
+
.describe('Peer tickers for comparison (financial spine + earnings only). Max 3.'),
|
|
1894
|
+
n_periods: z.number().min(1).max(8).default(4)
|
|
1895
|
+
.describe('Financial statement periods (default: 4).'),
|
|
1896
|
+
},
|
|
1897
|
+
}, async (input) => {
|
|
1898
|
+
if (containsGuardrailBypass(input))
|
|
1899
|
+
return guardrailViolationResponse();
|
|
1900
|
+
const ticker = input.ticker.trim().toUpperCase();
|
|
1901
|
+
try {
|
|
1902
|
+
log('info', `Company research: ${ticker}`, {
|
|
1903
|
+
sections: input.sections,
|
|
1904
|
+
detail_level: input.detail_level,
|
|
1905
|
+
peers: input.peers,
|
|
1906
|
+
n_periods: input.n_periods,
|
|
1907
|
+
});
|
|
1908
|
+
const packet = await client.getCompanyResearch({
|
|
1909
|
+
ticker,
|
|
1910
|
+
sections: input.sections,
|
|
1911
|
+
detail_level: input.detail_level,
|
|
1912
|
+
peers: input.peers?.map((peer) => peer.trim().toUpperCase()),
|
|
1913
|
+
n_periods: input.n_periods,
|
|
1914
|
+
});
|
|
1915
|
+
log('info', `Company research: ${ticker} complete`, {
|
|
1916
|
+
elapsed_ms: packet?.meta?.elapsed_ms,
|
|
1917
|
+
sections_returned: packet?.meta?.sections_returned,
|
|
1918
|
+
sections_failed: packet?.meta?.sections_failed,
|
|
1919
|
+
});
|
|
1920
|
+
return { content: [{ type: 'text', text: JSON.stringify(packet, null, 2) }] };
|
|
1921
|
+
}
|
|
1922
|
+
catch (error) {
|
|
1923
|
+
log('error', `Company research failed: ${ticker}`, { error: error instanceof Error ? error.message : error });
|
|
1924
|
+
return {
|
|
1925
|
+
content: [{ type: 'text', text: `Company research failed for ${ticker}: ${error instanceof Error ? error.message : 'Unknown error'}` }],
|
|
1926
|
+
isError: true,
|
|
1927
|
+
};
|
|
1928
|
+
}
|
|
1929
|
+
});
|
|
1785
1930
|
// ─── Start Server ───────────────────────────────────────────────────────────
|
|
1786
1931
|
const transport = new StdioServerTransport();
|
|
1787
1932
|
await server.connect(transport);
|
|
1788
|
-
log('info', 'ETSquare MCP Server v0.
|
|
1933
|
+
log('info', 'ETSquare MCP Server v0.6.0 ready and listening on stdio (15 tools)');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsquare/mcp-server-sec",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "MCP server for Claude Desktop: search SEC filing sections, financial statements, insider trades, institutional ownership, earnings actuals, XBRL metrics, and company lookup.",
|
|
6
6
|
"main": "dist/index.js",
|