@secapi/cli 0.4.0 → 0.5.0

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.
Files changed (3) hide show
  1. package/README.md +17 -0
  2. package/dist/index.js +143 -1
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -8,6 +8,23 @@ Command-line interface for SEC API factor data, SEC filings, financial statement
8
8
  npm install -g @secapi/cli
9
9
  ```
10
10
 
11
+ ## Connect an agent
12
+
13
+ Wire the hosted MCP server into your agent client in one command:
14
+
15
+ ```bash
16
+ secapi init --client claude-code # prints the `claude mcp add` command
17
+ secapi init --client cursor # writes .cursor/mcp.json
18
+ secapi init --client claude-desktop # writes the Claude Desktop config
19
+ secapi init --client windsurf # writes ~/.codeium/windsurf/mcp_config.json
20
+ secapi init --client project # writes ./.mcp.json
21
+ secapi init --client cursor --print # dry-run: print the config, write nothing
22
+ ```
23
+
24
+ `secapi init` reads your key from `SECAPI_API_KEY` (or `--api-key-stdin`) and never
25
+ accepts it as an argv flag. `secapi agent-context` prints a machine-readable JSON
26
+ description of the whole CLI surface so an agent can learn the tool in one call.
27
+
11
28
  ## Configuration
12
29
 
13
30
  ```bash
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { readFileSync } from "node:fs";
4
+ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
5
+ import { homedir } from "node:os";
6
+ import { dirname, join } from "node:path";
5
7
 
6
8
  // src/generated-contracts/agent-prompts.ts
7
9
  var AGENT_PROMPT_PERSONAS = [
@@ -25558,6 +25560,140 @@ async function main() {
25558
25560
  }));
25559
25561
  return;
25560
25562
  }
25563
+ if (group === "init" || group === "agents" && command === "setup") {
25564
+ const mcpUrl = `${baseUrl.replace(/\/+$/, "")}/mcp`;
25565
+ const initKeySource = hasFlag(STDIN_FLAG_NAME) ? credentials.apiKey : envCredential("SECAPI_API_KEY");
25566
+ const literalKey = initKeySource ?? "YOUR_API_KEY";
25567
+ const hasRealKey = Boolean(initKeySource);
25568
+ const dryRun = hasFlag("--print") || hasFlag("--dry-run");
25569
+ const positional = group === "init" && command && !command.startsWith("-") ? command : undefined;
25570
+ const clientFlag = getFlag("--client");
25571
+ const requested = clientFlag && !clientFlag.startsWith("-") ? clientFlag : positional;
25572
+ const claudeDesktopPath = () => {
25573
+ const home = homedir();
25574
+ if (process.platform === "darwin")
25575
+ return join(home, "Library", "Application Support", "Claude", "claude_desktop_config.json");
25576
+ if (process.platform === "win32")
25577
+ return join(process.env.APPDATA ?? join(home, "AppData", "Roaming"), "Claude", "claude_desktop_config.json");
25578
+ return join(home, ".config", "Claude", "claude_desktop_config.json");
25579
+ };
25580
+ const clients = {
25581
+ "claude-code": { kind: "command" },
25582
+ "claude-desktop": { kind: "file", urlKey: "url", httpType: true, keyValue: literalKey, committable: false, path: claudeDesktopPath },
25583
+ cursor: { kind: "file", urlKey: "url", httpType: false, keyValue: "${SECAPI_API_KEY}", committable: true, path: () => join(process.cwd(), ".cursor", "mcp.json") },
25584
+ windsurf: { kind: "file", urlKey: "serverUrl", httpType: false, keyValue: "${env:SECAPI_API_KEY}", committable: false, path: () => join(homedir(), ".codeium", "windsurf", "mcp_config.json") },
25585
+ project: { kind: "file", urlKey: "url", httpType: true, keyValue: "${SECAPI_API_KEY}", committable: true, path: () => join(process.cwd(), ".mcp.json") }
25586
+ };
25587
+ const names = Object.keys(clients).join(", ");
25588
+ if (!requested) {
25589
+ process.stdout.write(`Usage: secapi init --client <${names}> [--print]
25590
+
25591
+ Writes the SEC API hosted-MCP config (${mcpUrl}, x-api-key) for your agent client.
25592
+ Provide your API key via SECAPI_API_KEY (or ${STDIN_FLAG_NAME}); it is never read from an argv flag.
25593
+ `);
25594
+ return;
25595
+ }
25596
+ const spec = clients[requested];
25597
+ if (!spec)
25598
+ throw new Error(`Unknown client '${requested}'. Supported: ${names}`);
25599
+ if (spec.kind === "command") {
25600
+ process.stdout.write(`Add SEC API to Claude Code:
25601
+
25602
+ claude mcp add --transport http secapi ${mcpUrl} --header "x-api-key: $SECAPI_API_KEY"
25603
+ `);
25604
+ if (!hasRealKey)
25605
+ process.stdout.write(`
25606
+ Set SECAPI_API_KEY in your environment first.
25607
+ `);
25608
+ return;
25609
+ }
25610
+ const filePath = spec.path();
25611
+ let config2 = {};
25612
+ if (existsSync(filePath)) {
25613
+ let parsed;
25614
+ try {
25615
+ parsed = JSON.parse(readFileSync(filePath, "utf8"));
25616
+ } catch {
25617
+ throw new Error(`Existing config at ${filePath} is not valid JSON; fix or move it before running init.`);
25618
+ }
25619
+ if (Array.isArray(parsed) || typeof parsed !== "object" || parsed === null) {
25620
+ throw new Error(`Existing config at ${filePath} is not a JSON object; fix or move it before running init.`);
25621
+ }
25622
+ config2 = parsed;
25623
+ }
25624
+ const existingServers = config2.mcpServers;
25625
+ if (existingServers !== undefined && (typeof existingServers !== "object" || existingServers === null || Array.isArray(existingServers))) {
25626
+ throw new Error(`Existing "mcpServers" in ${filePath} is not an object; fix or move it before running init.`);
25627
+ }
25628
+ const servers = existingServers ? existingServers : {};
25629
+ servers.secapi = {
25630
+ ...spec.httpType ? { type: "http" } : {},
25631
+ [spec.urlKey]: mcpUrl,
25632
+ headers: { "x-api-key": spec.keyValue }
25633
+ };
25634
+ config2.mcpServers = servers;
25635
+ const rendered = `${JSON.stringify(config2, null, 2)}
25636
+ `;
25637
+ if (dryRun) {
25638
+ process.stdout.write(`# ${filePath}
25639
+ ${rendered}`);
25640
+ return;
25641
+ }
25642
+ mkdirSync(dirname(filePath), { recursive: true });
25643
+ writeFileSync(filePath, rendered, { mode: 384 });
25644
+ chmodSync(filePath, 384);
25645
+ process.stdout.write(`Wrote SEC API MCP config for ${requested} to ${filePath}
25646
+ `);
25647
+ if (spec.keyValue.startsWith("$")) {
25648
+ process.stdout.write(`Set SECAPI_API_KEY in your environment so ${requested} can resolve the key.
25649
+ `);
25650
+ } else if (!hasRealKey) {
25651
+ process.stdout.write(`Replace YOUR_API_KEY in that file with your key (or set SECAPI_API_KEY and re-run).
25652
+ `);
25653
+ }
25654
+ if (spec.committable) {
25655
+ process.stdout.write(`Note: ${filePath} can be committed — it uses an env-var reference, not your literal key.
25656
+ `);
25657
+ }
25658
+ process.stdout.write(`Restart ${requested} to load the server.
25659
+ `);
25660
+ return;
25661
+ }
25662
+ if (group === "agent-context" || group === "agents" && command === "context") {
25663
+ print({
25664
+ object: "agent_context",
25665
+ cli: { binaries: ["secapi", "omni-sec"], version: cliVersion() },
25666
+ baseUrl,
25667
+ mcpUrl: `${baseUrl.replace(/\/+$/, "")}/mcp`,
25668
+ docs: "https://docs.secapi.ai",
25669
+ agentsPage: "https://secapi.ai/agents",
25670
+ auth: {
25671
+ header: "x-api-key",
25672
+ note: "Authenticate with the x-api-key header. Never send the API key as Authorization: Bearer.",
25673
+ envVars: ["SECAPI_API_KEY", "SECAPI_OPERATOR_API_KEY", "SECAPI_BEARER_TOKEN (WorkOS bearer, not an API key)"],
25674
+ stdin: [STDIN_FLAG_NAME, STDIN_BEARER_FLAG_NAME]
25675
+ },
25676
+ install: {
25677
+ mcp: `secapi init --client <claude-code|claude-desktop|cursor|windsurf|project>`,
25678
+ skills: "npx skills add secapi-ai/secapi-skills --global"
25679
+ },
25680
+ commandGroups: [
25681
+ { group: "account", commands: ["health", "me", "org show", "billing show", "usage show", "limits show", "api-keys list", "api-keys create --label <l> --scopes <s>"] },
25682
+ { group: "agent", commands: ["agent bootstrap-token --label <l> --scopes <s> --ttl-seconds <n>", "agent bootstrap --token <agbt_...>"] },
25683
+ { group: "agents", commands: ["agents personas", "agents prompts list [--persona <p>] [--include-v2] [--json]", "agents prompts read <id>", "agents prompts copy <id>", "agents setup --client <name>", "agents context"] },
25684
+ { group: "entities", commands: ["entities resolve --ticker <t> | --name <n> | --cik <c>"] },
25685
+ { group: "filings", commands: ["filings search --ticker <t> --form <f>", "filings latest --ticker <t> --form <f>", "sections get --ticker <t> --form 10-K --section item_1a"] },
25686
+ { group: "factors", commands: ["factors exposures --symbols <list>", "factors decomposition --symbol <t>", "factors screen --keys <list>", "factors valuations --keys <list>"] },
25687
+ { group: "setup", commands: ["init --client <claude-code|claude-desktop|cursor|windsurf|project> [--print]", "agent-context"] }
25688
+ ],
25689
+ conventions: {
25690
+ output: "JSON to stdout by default; human-readable when stdout is a TTY for agents/personas commands.",
25691
+ correlation: "Request-Id header on every response.",
25692
+ guardrails: "Check GET /v1/billing and POST /v1/billing/quote before expensive or repeated workflows."
25693
+ }
25694
+ });
25695
+ return;
25696
+ }
25561
25697
  const commandHelpLines = [
25562
25698
  "SEC API CLI",
25563
25699
  "Preferred binary: secapi",
@@ -25576,6 +25712,12 @@ async function main() {
25576
25712
  " secapi agent bootstrap-token --label ci --scopes read:sec --ttl-seconds 900",
25577
25713
  " secapi agent bootstrap --token agbt_... --label first-agent-key",
25578
25714
  "",
25715
+ " # Connect an agent (one-command MCP install)",
25716
+ " secapi init --client claude-code # prints the `claude mcp add` command",
25717
+ " secapi init --client cursor # writes .cursor/mcp.json",
25718
+ " secapi init --client claude-desktop --print # dry-run the config",
25719
+ " secapi agent-context # machine-readable CLI surface for agents",
25720
+ "",
25579
25721
  " # Agent prompt library",
25580
25722
  " secapi agents personas",
25581
25723
  " secapi agents prompts list",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@secapi/cli",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "SEC API CLI for SEC data shaped for investors and agents",
5
5
  "type": "module",
6
6
  "bin": {