@etsquare/mcp-server-sec 0.7.0 → 0.7.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.
@@ -61,6 +61,21 @@ interface CompanyResearchApiInput {
61
61
  peers?: string[];
62
62
  n_periods?: number;
63
63
  }
64
+ /** Ticker cohort resolver request. */
65
+ interface ResolveTickerCohortApiInput {
66
+ question: string;
67
+ profile_code?: string;
68
+ boost_anchor_terms?: string[];
69
+ boost_topic_terms?: string[];
70
+ boost_negative_terms?: string[];
71
+ boost_positive_seeds?: string[];
72
+ boost_negative_seeds?: string[];
73
+ output_limit?: number;
74
+ semantic_mode?: 'auto' | 'off' | 'on';
75
+ grounding_context?: Record<string, unknown>;
76
+ ticker_cohort_candidate?: Record<string, unknown>;
77
+ response_mode?: 'full' | 'compact';
78
+ }
64
79
  /** Server-side KPI query with metric filtering. */
65
80
  interface QueryKpisApiInput {
66
81
  select?: string[];
@@ -105,6 +120,7 @@ export declare class ETSquareClient {
105
120
  getEarningsActuals(input: EarningsActualsApiInput): Promise<Record<string, unknown>>;
106
121
  getKpiExtractions(input: KpiExtractionsApiInput): Promise<Record<string, unknown>>;
107
122
  getCompanyResearch(input: CompanyResearchApiInput): Promise<Record<string, unknown>>;
123
+ resolveTickerCohort(input: ResolveTickerCohortApiInput): Promise<Record<string, unknown>>;
108
124
  queryKpis(input: QueryKpisApiInput): Promise<Record<string, unknown>>;
109
125
  discoverMetrics(input: DiscoverMetricsApiInput): Promise<Record<string, unknown>>;
110
126
  getChunk(input: GetChunkInput): Promise<Record<string, unknown>>;
@@ -176,6 +176,37 @@ export class ETSquareClient {
176
176
  body: JSON.stringify(body),
177
177
  });
178
178
  }
179
+ async resolveTickerCohort(input) {
180
+ const body = {
181
+ question: input.question,
182
+ semantic_mode: input.semantic_mode || 'auto',
183
+ };
184
+ if (input.profile_code)
185
+ body.profile_code = input.profile_code;
186
+ if (input.boost_anchor_terms && input.boost_anchor_terms.length > 0)
187
+ body.boost_anchor_terms = input.boost_anchor_terms;
188
+ if (input.boost_topic_terms && input.boost_topic_terms.length > 0)
189
+ body.boost_topic_terms = input.boost_topic_terms;
190
+ if (input.boost_negative_terms && input.boost_negative_terms.length > 0)
191
+ body.boost_negative_terms = input.boost_negative_terms;
192
+ if (input.boost_positive_seeds && input.boost_positive_seeds.length > 0)
193
+ body.boost_positive_seeds = input.boost_positive_seeds;
194
+ if (input.boost_negative_seeds && input.boost_negative_seeds.length > 0)
195
+ body.boost_negative_seeds = input.boost_negative_seeds;
196
+ if (input.output_limit !== undefined)
197
+ body.output_limit = input.output_limit;
198
+ if (input.grounding_context)
199
+ body.grounding_context = input.grounding_context;
200
+ if (input.ticker_cohort_candidate)
201
+ body.ticker_cohort_candidate = input.ticker_cohort_candidate;
202
+ if (input.response_mode)
203
+ body.response_mode = input.response_mode;
204
+ return this.request('/api/v1/cohort/resolve', {
205
+ method: 'POST',
206
+ headers: this.headers,
207
+ body: JSON.stringify(body),
208
+ });
209
+ }
179
210
  async queryKpis(input) {
180
211
  const body = {
181
212
  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.6.0
3
+ * @etsquare/mcp-server-sec v0.7.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.6.0 starting with backend: ${baseUrl}`);
60
+ log('info', `ETSquare MCP Server v0.7.0 starting with backend: ${baseUrl}`);
61
61
  // ─── Item Code Labels ───────────────────────────────────────────────────────
62
62
  const ITEM_CODE_LABELS = {
63
63
  // 10-K
@@ -358,7 +358,7 @@ 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.6.0',
361
+ version: '0.7.0',
362
362
  });
363
363
  const CITATION_POLICY = 'Citation policy (required): When `cite: true` appears in the response, you MUST include ' +
364
364
  'the sec_url for every filing referenced in the answer. Cite each URL inline with its claim.';
@@ -410,11 +410,82 @@ server.registerTool('etsquare_lookup_company', {
410
410
  };
411
411
  }
412
412
  });
413
- // ─── Tool 2: SEC Filing Search ──────────────────────────────────────────────
413
+ // ─── Tool 2: Resolve Ticker Cohort ──────────────────────────────────────────
414
+ server.registerTool('etsquare_resolve_ticker_cohort', {
415
+ title: 'Resolve Ticker Cohort',
416
+ description: 'Resolve a natural-language question into a ranked ticker cohort using corpus-grounded terms. ' +
417
+ 'Use this before precision search for INDUSTRY/MACRO workflows, then pass selected tickers to etsquare_search with scope_lock=COMPANY.',
418
+ inputSchema: {
419
+ question: z.string().min(3).max(500)
420
+ .describe('Natural-language cohort question (e.g., "public SaaS companies discussing AI pricing power").'),
421
+ profile_code: z.string().min(2).max(80).optional()
422
+ .describe('Optional curated profile code override.'),
423
+ boost_anchor_terms: z.array(z.string()).max(5).optional()
424
+ .describe('WHO anchor terms (industry/exposure/entity class).'),
425
+ boost_topic_terms: z.array(z.string()).max(5).optional()
426
+ .describe('WHAT topic terms (KPI/theme/impact).'),
427
+ boost_negative_terms: z.array(z.string()).max(5).optional()
428
+ .describe('Negative terms to suppress confusable cohorts.'),
429
+ boost_positive_seeds: z.array(z.string().min(1).max(10)).max(5).optional()
430
+ .describe('Manual positive seed tickers (MCP/manual only).'),
431
+ boost_negative_seeds: z.array(z.string().min(1).max(10)).max(5).optional()
432
+ .describe('Manual negative seed tickers (MCP/manual only).'),
433
+ output_limit: z.number().int().min(1).max(50).optional()
434
+ .describe('Output ticker count override.'),
435
+ semantic_mode: z.enum(['auto', 'off', 'on']).default('auto')
436
+ .describe('Semantic embedding mode for resolver matching.'),
437
+ response_mode: z.enum(['full', 'compact']).default('full')
438
+ .describe('Response verbosity. Use "compact" for a consumer-focused payload and "full" for trace-rich output.'),
439
+ grounding_context: z.record(z.unknown()).optional()
440
+ .describe('Optional pre-computed grounding context from upstream workflow.'),
441
+ ticker_cohort_candidate: z.record(z.unknown()).optional()
442
+ .describe('Workflow candidate payload translated into resolver fields before resolution.'),
443
+ },
444
+ }, async (input) => {
445
+ if (containsGuardrailBypass(input))
446
+ return guardrailViolationResponse();
447
+ try {
448
+ log('debug', 'Resolving ticker cohort', {
449
+ question: input.question,
450
+ profile_code: input.profile_code,
451
+ output_limit: input.output_limit,
452
+ semantic_mode: input.semantic_mode,
453
+ });
454
+ const result = await client.resolveTickerCohort({
455
+ question: input.question,
456
+ profile_code: input.profile_code,
457
+ boost_anchor_terms: input.boost_anchor_terms,
458
+ boost_topic_terms: input.boost_topic_terms,
459
+ boost_negative_terms: input.boost_negative_terms,
460
+ boost_positive_seeds: input.boost_positive_seeds?.map((t) => t.trim().toUpperCase()),
461
+ boost_negative_seeds: input.boost_negative_seeds?.map((t) => t.trim().toUpperCase()),
462
+ output_limit: input.output_limit,
463
+ semantic_mode: input.semantic_mode,
464
+ response_mode: input.response_mode,
465
+ grounding_context: input.grounding_context,
466
+ ticker_cohort_candidate: input.ticker_cohort_candidate,
467
+ });
468
+ log('info', 'Ticker cohort resolved', {
469
+ cohort_code: result?.cohort_code,
470
+ profile_match_mode: result?.profile_match_mode,
471
+ ticker_count: Array.isArray(result?.tickers) ? result.tickers.length : 0,
472
+ });
473
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
474
+ }
475
+ catch (error) {
476
+ log('error', 'Ticker cohort resolve failed', { error: error instanceof Error ? error.message : error });
477
+ return {
478
+ content: [{ type: 'text', text: `Ticker cohort resolution failed: ${error instanceof Error ? error.message : 'Unknown error'}` }],
479
+ isError: true,
480
+ };
481
+ }
482
+ });
483
+ // ─── Tool 3: SEC Filing Search ──────────────────────────────────────────────
414
484
  server.registerTool('etsquare_search', {
415
485
  title: 'Search SEC Filings',
416
486
  description: 'Search SEC filing text (10-K, 10-Q, 8-K). Returns verbatim excerpts with SEC URL citations.\n\n' +
417
487
  'COMPANY + tickers = precision. INDUSTRY + sector = breadth. When precision matters, supply tickers.\n\n' +
488
+ 'Predict literal filing text: draft queries using exact MD&A and Risk Factors disclosure phraseology ("revenue attributable to," "material adverse effect on," "growth driven by adoption of"), never casual topic labels or conceptual summaries.\n\n' +
418
489
  'For financial statements use etsquare_financial_statements. For metrics use etsquare_discover_metrics.',
419
490
  inputSchema: {
420
491
  query: z.string().min(3).describe('What to search for in SEC filings (e.g., "customer concentration risk", "Show NVDA revenue trend")'),
@@ -1865,4 +1936,4 @@ server.registerTool('etsquare_company_research', {
1865
1936
  // ─── Start Server ───────────────────────────────────────────────────────────
1866
1937
  const transport = new StdioServerTransport();
1867
1938
  await server.connect(transport);
1868
- log('info', 'ETSquare MCP Server v0.6.0 ready and listening on stdio (15 tools)');
1939
+ log('info', 'ETSquare MCP Server v0.7.0 ready and listening on stdio (16 tools)');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsquare/mcp-server-sec",
3
- "version": "0.7.0",
3
+ "version": "0.7.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",