@pipeworx/mcp-edgar 0.3.1 → 0.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipeworx/mcp-edgar",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "EDGAR MCP — SEC EDGAR public APIs (free, no auth)",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
package/server.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "io.github.pipeworx-io/edgar",
4
4
  "title": "Edgar",
5
5
  "description": "EDGAR MCP — SEC EDGAR public APIs (free, no auth)",
6
- "version": "0.3.1",
6
+ "version": "0.3.2",
7
7
  "websiteUrl": "https://pipeworx.io/packs/edgar",
8
8
  "repository": {
9
9
  "url": "https://github.com/pipeworx-io/mcp-edgar",
package/src/index.ts CHANGED
@@ -315,28 +315,32 @@ const tools: McpToolExport['tools'] = [
315
315
  {
316
316
  name: 'edgar_filing_documents',
317
317
  description:
318
- 'AUTHORITATIVE list of the SEC filing documents inside ONE specific filing, by accession number. Retrieve a filing / its contents / attachments: pass the accession (e.g. "0000320193-25-000079", with or without dashes) plus the filer\'s ticker ("AAPL") or CIK ("320193"). Returns every document in the filing folder — the primary document (10-K / 10-Q / 8-K body), all exhibits, and XBRL files — each with name, type, size, and a direct https URL, plus the filing\'s form type, filing date, and human -index.html page. Set include_primary_text:true to also pull the primary document\'s text (HTML stripped to plaintext, ~40k chars). Use to list a 10-K / 10-Q / 8-K\'s exhibits by accession number, retrieve filing contents/attachments, or fetch the text of a known filing. Get accession numbers from edgar_company_filings or edgar_search_filings. Example: edgar_filing_documents({accession: "0000320193-25-000079", ticker: "AAPL"}).',
318
+ 'AUTHORITATIVE list of the SEC filing documents inside ONE specific filing, by accession number. Retrieve a filing / its contents / attachments: pass the accession (e.g. "0000320193-25-000079", with or without dashes) plus the filer\'s ticker ("AAPL") or CIK ("320193"). Returns every document in the filing folder — the primary document (10-K / 10-Q / 8-K body), all exhibits, and XBRL files — each with name, type, size, and a direct https URL, plus the filing\'s form type, filing date, and human -index.html page. Set include_primary_text:true to also pull the primary document\'s text (HTML stripped to plaintext, ~40k chars). Use to list a 10-K / 10-Q / 8-K\'s exhibits, retrieve filing contents/attachments, or fetch the text of a filing. You can pass an exact accession, OR just a ticker + form_type to auto-resolve the latest matching filing (no accession lookup needed). Examples: edgar_filing_documents({ticker: "NVDA", form_type: "10-K"}) for the documents in NVIDIA\'s latest annual report; edgar_filing_documents({accession: "0000320193-25-000079", ticker: "AAPL", include_primary_text: true}) for a specific filing\'s text.',
319
319
  inputSchema: {
320
320
  type: 'object' as const,
321
321
  properties: {
322
322
  accession: {
323
323
  type: 'string',
324
- description: 'SEC accession number of the filing, with or without dashes (e.g. "0000320193-25-000079" or "000032019325000079"). 18 digits shaped 10-2-6.',
324
+ description: 'Optional SEC accession number of a specific filing, with or without dashes (e.g. "0000320193-25-000079"). Omit it to auto-resolve the latest filing — pass form_type instead.',
325
325
  },
326
326
  ticker: {
327
327
  type: 'string',
328
- description: 'The filer\'s ticker (e.g. "AAPL") or company name. Provide this OR cik — needed to build the filing archive path. Tickers are auto-resolved to CIKs.',
328
+ description: 'The filer\'s ticker (e.g. "AAPL", "NVDA") or company name. Provide this OR cik. Tickers are auto-resolved to CIKs.',
329
329
  },
330
330
  cik: {
331
331
  type: 'string',
332
332
  description: 'The filer\'s CIK number (e.g. "320193"). Provide this OR ticker.',
333
333
  },
334
+ form_type: {
335
+ type: 'string',
336
+ description: 'When accession is omitted, the form type of the latest filing to fetch, e.g. "10-K", "10-Q", "8-K", "DEF 14A". Omit both accession and form_type to get the single most recent filing of any type.',
337
+ },
334
338
  include_primary_text: {
335
339
  type: 'boolean',
336
340
  description: 'When true, also fetch the primary document and return its text (HTML stripped to plaintext, truncated to ~40,000 chars). Default false.',
337
341
  },
338
342
  },
339
- required: ['accession'],
343
+ required: [],
340
344
  },
341
345
  },
342
346
  ];
@@ -525,23 +529,44 @@ function htmlToText(html: string): string {
525
529
  }
526
530
 
527
531
  async function filingDocuments(
528
- accession: string,
532
+ accession: string | undefined,
529
533
  tickerOrCik: string,
530
534
  includePrimaryText?: boolean,
535
+ wantFormTypeArg?: string,
531
536
  ) {
532
- const acc = normalizeAccession(accession);
533
- if (!acc) {
537
+ if (typeof tickerOrCik !== 'string' || !tickerOrCik.trim()) {
534
538
  throw new Error(
535
- `Invalid accession "${accession}". A SEC accession number is 18 digits shaped 10-2-6 (e.g. "0000320193-25-000079" or "000032019325000079", with or without dashes). Get accession numbers from edgar_company_filings or edgar_search_filings.`,
539
+ 'A ticker or CIK is required. Pass ticker ("AAPL") or cik ("320193"), plus either an accession or a form_type (e.g. edgar_filing_documents({ticker: "NVDA", form_type: "10-K"}) for the latest 10-K).',
536
540
  );
537
541
  }
538
- if (typeof tickerOrCik !== 'string' || !tickerOrCik.trim()) {
542
+ const cik = await resolveCik(tickerOrCik);
543
+ // Accession is optional: when omitted, resolve the latest filing matching
544
+ // form_type (or the single most recent filing of any type) so one-shot
545
+ // questions like "documents in NVIDIA's latest 10-K" work without the caller
546
+ // first having to look up an accession number.
547
+ let acc = accession ? normalizeAccession(accession) : null;
548
+ if (accession && !acc) {
539
549
  throw new Error(
540
- 'A ticker or CIK is required to build the filing archive path. Pass ticker ("AAPL") or cik ("320193"), e.g. edgar_filing_documents({accession: "' +
541
- acc.dashed + '", ticker: "AAPL"}).',
550
+ `Invalid accession "${accession}". A SEC accession number is 18 digits shaped 10-2-6 (e.g. "0000320193-25-000079", with or without dashes). Get accession numbers from edgar_company_filings, or omit accession and pass form_type to auto-resolve the latest.`,
542
551
  );
543
552
  }
544
- const cik = await resolveCik(tickerOrCik);
553
+ if (!acc) {
554
+ const wantForm = wantFormTypeArg?.trim().toUpperCase();
555
+ const subRes = await fetch(`${DATA_BASE}/submissions/CIK${padCik(cik)}.json`, { headers: SEC_HEADERS });
556
+ if (!subRes.ok) throw new Error(`SEC submissions lookup failed (HTTP ${subRes.status}) resolving the latest filing for ${tickerOrCik}.`);
557
+ const sub = (await subRes.json()) as { filings?: { recent?: { accessionNumber?: string[]; form?: string[] } } };
558
+ const r = sub.filings?.recent;
559
+ const forms = r?.form ?? [];
560
+ const accs = r?.accessionNumber ?? [];
561
+ const idx = wantForm ? forms.findIndex((f) => f.toUpperCase() === wantForm) : 0;
562
+ if (idx < 0 || !accs[idx]) {
563
+ throw new Error(
564
+ `No ${wantForm ?? 'recent'} filing found for ${tickerOrCik} in the recent index. Use edgar_company_filings({ticker:"${tickerOrCik}"${wantForm ? `, form_type:"${wantForm}"` : ''}}) to list available filings, then pass an accession.`,
565
+ );
566
+ }
567
+ acc = normalizeAccession(accs[idx]);
568
+ if (!acc) throw new Error('Failed to resolve a valid accession from the submissions index.');
569
+ }
545
570
  const cikNoZeros = String(Number(cik.replace(/\D/g, ''))); // archive path uses CIK with no leading zeros
546
571
  const paddedCik = padCik(cik);
547
572
 
@@ -1360,9 +1385,10 @@ async function callTool(name: string, args: Record<string, unknown>): Promise<un
1360
1385
  return companyConcept((args.cik ?? args.ticker_or_cik) as string, args.concept as string);
1361
1386
  case 'edgar_filing_documents':
1362
1387
  return filingDocuments(
1363
- args.accession as string,
1388
+ args.accession as string | undefined,
1364
1389
  (args.cik ?? args.ticker ?? args.ticker_or_cik) as string,
1365
1390
  args.include_primary_text as boolean | undefined,
1391
+ args.form_type as string | undefined,
1366
1392
  );
1367
1393
  case 'edgar_ticker_to_cik':
1368
1394
  return tickerToCik(args.ticker as string);