@contextstream/mcp-server 0.3.40 → 0.3.41

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 +6 -3
  2. package/dist/index.js +261 -5
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -48,9 +48,10 @@ npx -y @contextstream/mcp-server setup
48
48
 
49
49
  Notes:
50
50
  - Uses browser/device login by default and creates an API key for you.
51
+ - Prompts for **toolset selection**: `core` (default, ~17 essential tools) or `full` (~86 tools including workspaces, projects, search, memory, graph, AI, and integrations).
51
52
  - To avoid re-auth prompts on subsequent runs, the wizard saves that API key to `~/.contextstream/credentials.json` (and also writes it into the MCP config files it generates). Delete that file to force a fresh login.
52
53
  - Codex CLI MCP config is global-only (`~/.codex/config.toml`), so the wizard will always write Codex config globally when selected.
53
- - Some tools still require UI/CLI-based MCP setup (the wizard will tell you when it cant write a config).
54
+ - Some tools still require UI/CLI-based MCP setup (the wizard will tell you when it can't write a config).
54
55
  - Preview changes without writing files: `npx -y @contextstream/mcp-server setup --dry-run`
55
56
 
56
57
  ### Run the server
@@ -74,7 +75,9 @@ contextstream-mcp
74
75
 
75
76
  If you ran the [setup wizard](#setup-wizard-recommended), you can usually skip this section.
76
77
 
77
- If you prefer to configure things by hand (or your tool cant be auto-configured), add the ContextStream MCP server to your client using one of the examples below.
78
+ If you prefer to configure things by hand (or your tool can't be auto-configured), add the ContextStream MCP server to your client using one of the examples below.
79
+
80
+ **Toolset**: By default, the server exposes `core` tools (~17 essential session/context tools). To expose all ~86 tools (workspaces, projects, search, memory, graph, AI, integrations), add `"CONTEXTSTREAM_TOOLSET": "full"` to the `env` block. See the [full tool catalog](https://contextstream.io/docs/mcp/tools).
78
81
 
79
82
  ### Cursor / Windsurf / Claude Desktop (JSON)
80
83
 
@@ -204,7 +207,7 @@ You can authenticate using either:
204
207
  | `CONTEXTSTREAM_WORKSPACE_ID` | No | Default workspace ID fallback |
205
208
  | `CONTEXTSTREAM_PROJECT_ID` | No | Default project ID fallback |
206
209
  | `CONTEXTSTREAM_USER_AGENT` | No | Custom user agent string |
207
- | `CONTEXTSTREAM_TOOLSET` | No | Tool bundle to expose (`core` default, or `full`) |
210
+ | `CONTEXTSTREAM_TOOLSET` | No | Tool bundle to expose: `core` (default, ~17 tools) or `full` (~86 tools). Claude Code/Desktop may warn about large tool contexts with `full`. |
208
211
  | `CONTEXTSTREAM_TOOL_ALLOWLIST` | No | Comma-separated tool names to expose (overrides toolset) |
209
212
  | `CONTEXTSTREAM_PRO_TOOLS` | No | Comma-separated tool names treated as PRO (default: `ai_context,ai_enhanced_context,ai_context_budget,ai_embeddings,ai_plan,ai_tasks`) |
210
213
  | `CONTEXTSTREAM_UPGRADE_URL` | No | Upgrade link shown when Free users call PRO tools (default: `https://contextstream.io/pricing`) |
package/dist/index.js CHANGED
@@ -6885,6 +6885,44 @@ W:${wsHint}
6885
6885
  if (params?.limit) query.set("limit", String(params.limit));
6886
6886
  return request(this.config, `/workspaces/${withDefaults.workspace_id}/github/search?${query.toString()}`, { method: "GET" });
6887
6887
  }
6888
+ /**
6889
+ * Get knowledge extracted from GitHub (decisions, lessons, insights)
6890
+ */
6891
+ async githubKnowledge(params) {
6892
+ const withDefaults = this.withDefaults(params || {});
6893
+ if (!withDefaults.workspace_id) {
6894
+ throw new Error("workspace_id is required for GitHub knowledge");
6895
+ }
6896
+ const query = new URLSearchParams();
6897
+ if (params?.limit) query.set("limit", String(params.limit));
6898
+ if (params?.node_type) query.set("node_type", params.node_type);
6899
+ const suffix = query.toString() ? `?${query.toString()}` : "";
6900
+ return request(this.config, `/workspaces/${withDefaults.workspace_id}/github/knowledge${suffix}`, { method: "GET" });
6901
+ }
6902
+ /**
6903
+ * Get knowledge extracted from Slack (decisions, lessons, insights)
6904
+ */
6905
+ async slackKnowledge(params) {
6906
+ const withDefaults = this.withDefaults(params || {});
6907
+ if (!withDefaults.workspace_id) {
6908
+ throw new Error("workspace_id is required for Slack knowledge");
6909
+ }
6910
+ const query = new URLSearchParams();
6911
+ if (params?.limit) query.set("limit", String(params.limit));
6912
+ if (params?.node_type) query.set("node_type", params.node_type);
6913
+ const suffix = query.toString() ? `?${query.toString()}` : "";
6914
+ return request(this.config, `/workspaces/${withDefaults.workspace_id}/slack/knowledge${suffix}`, { method: "GET" });
6915
+ }
6916
+ /**
6917
+ * Get integration status for all providers in a workspace
6918
+ */
6919
+ async integrationsStatus(params) {
6920
+ const withDefaults = this.withDefaults(params || {});
6921
+ if (!withDefaults.workspace_id) {
6922
+ throw new Error("workspace_id is required for integrations status");
6923
+ }
6924
+ return request(this.config, `/workspaces/${withDefaults.workspace_id}/integrations/status`, { method: "GET" });
6925
+ }
6888
6926
  };
6889
6927
 
6890
6928
  // src/tools.ts
@@ -6894,6 +6932,7 @@ import * as path4 from "node:path";
6894
6932
  // src/rules-templates.ts
6895
6933
  var DEFAULT_CLAUDE_MCP_SERVER_NAME = "contextstream";
6896
6934
  var CONTEXTSTREAM_TOOL_NAMES = [
6935
+ // Session/Context (core)
6897
6936
  "session_init",
6898
6937
  "context_smart",
6899
6938
  "session_summary",
@@ -6906,9 +6945,90 @@ var CONTEXTSTREAM_TOOL_NAMES = [
6906
6945
  "session_smart_search",
6907
6946
  "session_compress",
6908
6947
  "session_delta",
6948
+ // Editor Rules
6909
6949
  "generate_editor_rules",
6950
+ // Workspaces
6910
6951
  "workspace_associate",
6911
- "workspace_bootstrap"
6952
+ "workspace_bootstrap",
6953
+ "workspaces_list",
6954
+ "workspaces_create",
6955
+ "workspaces_update",
6956
+ "workspaces_delete",
6957
+ "workspaces_get",
6958
+ "workspaces_overview",
6959
+ "workspaces_analytics",
6960
+ "workspaces_content",
6961
+ // Projects
6962
+ "projects_list",
6963
+ "projects_create",
6964
+ "projects_update",
6965
+ "projects_delete",
6966
+ "projects_get",
6967
+ "projects_overview",
6968
+ "projects_statistics",
6969
+ "projects_files",
6970
+ "projects_index",
6971
+ "projects_index_status",
6972
+ "projects_ingest_local",
6973
+ // Search
6974
+ "search_semantic",
6975
+ "search_hybrid",
6976
+ "search_keyword",
6977
+ "search_pattern",
6978
+ "search_suggestions",
6979
+ // Memory
6980
+ "memory_create_event",
6981
+ "memory_bulk_ingest",
6982
+ "memory_list_events",
6983
+ "memory_create_node",
6984
+ "memory_list_nodes",
6985
+ "memory_search",
6986
+ "memory_decisions",
6987
+ "memory_get_event",
6988
+ "memory_update_event",
6989
+ "memory_delete_event",
6990
+ "memory_distill_event",
6991
+ "memory_get_node",
6992
+ "memory_update_node",
6993
+ "memory_delete_node",
6994
+ "memory_supersede_node",
6995
+ "memory_timeline",
6996
+ "memory_summary",
6997
+ // Graph
6998
+ "graph_related",
6999
+ "graph_path",
7000
+ "graph_decisions",
7001
+ "graph_dependencies",
7002
+ "graph_call_path",
7003
+ "graph_impact",
7004
+ "graph_circular_dependencies",
7005
+ "graph_unused_code",
7006
+ "graph_contradictions",
7007
+ // AI (PRO)
7008
+ "ai_context",
7009
+ "ai_enhanced_context",
7010
+ "ai_context_budget",
7011
+ "ai_embeddings",
7012
+ "ai_plan",
7013
+ "ai_tasks",
7014
+ // GitHub Integration (PRO)
7015
+ "github_stats",
7016
+ "github_repos",
7017
+ "github_contributors",
7018
+ "github_activity",
7019
+ "github_issues",
7020
+ "github_search",
7021
+ // Slack Integration (PRO)
7022
+ "slack_stats",
7023
+ "slack_channels",
7024
+ "slack_contributors",
7025
+ "slack_activity",
7026
+ "slack_discussions",
7027
+ "slack_search",
7028
+ "slack_sync_users",
7029
+ // Auth/Meta
7030
+ "auth_me",
7031
+ "mcp_server_version"
6912
7032
  ];
6913
7033
  function applyMcpToolPrefix(markdown, toolPrefix) {
6914
7034
  const toolPattern = CONTEXTSTREAM_TOOL_NAMES.join("|");
@@ -7069,6 +7189,41 @@ session_capture(event_type="decision", title="Auth Implementation Complete", con
7069
7189
  # Check past decisions
7070
7190
  session_recall(query="what did we decide about caching?")
7071
7191
  \`\`\`
7192
+
7193
+ ---
7194
+
7195
+ ### Full Tool Catalog
7196
+
7197
+ The following tools are available when \`CONTEXTSTREAM_TOOLSET=full\` (default is \`core\`, which includes only the essential session/context tools above):
7198
+
7199
+ **Session/Context** (included in core):
7200
+ \`session_init\`, \`context_smart\`, \`session_summary\`, \`session_capture\`, \`session_capture_lesson\`, \`session_get_lessons\`, \`session_recall\`, \`session_remember\`, \`session_get_user_context\`, \`session_smart_search\`, \`session_compress\`, \`session_delta\`, \`generate_editor_rules\`, \`workspace_associate\`, \`workspace_bootstrap\`
7201
+
7202
+ **Workspaces**:
7203
+ \`workspaces_list\`, \`workspaces_create\`, \`workspaces_update\`, \`workspaces_delete\`, \`workspaces_get\`, \`workspaces_overview\`, \`workspaces_analytics\`, \`workspaces_content\`
7204
+
7205
+ **Projects**:
7206
+ \`projects_list\`, \`projects_create\`, \`projects_update\`, \`projects_delete\`, \`projects_get\`, \`projects_overview\`, \`projects_statistics\`, \`projects_files\`, \`projects_index\`, \`projects_index_status\`, \`projects_ingest_local\`
7207
+
7208
+ **Search**:
7209
+ \`search_semantic\`, \`search_hybrid\`, \`search_keyword\`, \`search_pattern\`, \`search_suggestions\`
7210
+
7211
+ **Memory**:
7212
+ \`memory_create_event\`, \`memory_bulk_ingest\`, \`memory_list_events\`, \`memory_create_node\`, \`memory_list_nodes\`, \`memory_search\`, \`memory_decisions\`, \`memory_get_event\`, \`memory_update_event\`, \`memory_delete_event\`, \`memory_distill_event\`, \`memory_get_node\`, \`memory_update_node\`, \`memory_delete_node\`, \`memory_supersede_node\`, \`memory_timeline\`, \`memory_summary\`
7213
+
7214
+ **Graph** (code analysis):
7215
+ \`graph_related\`, \`graph_path\`, \`graph_decisions\`, \`graph_dependencies\`, \`graph_call_path\`, \`graph_impact\`, \`graph_circular_dependencies\`, \`graph_unused_code\`, \`graph_contradictions\`
7216
+
7217
+ **AI** (PRO):
7218
+ \`ai_context\`, \`ai_enhanced_context\`, \`ai_context_budget\`, \`ai_embeddings\`, \`ai_plan\`, \`ai_tasks\`
7219
+
7220
+ **GitHub Integration** (PRO):
7221
+ \`github_stats\`, \`github_repos\`, \`github_contributors\`, \`github_activity\`, \`github_issues\`, \`github_search\`
7222
+
7223
+ **Slack Integration** (PRO):
7224
+ \`slack_stats\`, \`slack_channels\`, \`slack_contributors\`, \`slack_activity\`, \`slack_discussions\`, \`slack_search\`, \`slack_sync_users\`
7225
+
7226
+ See full documentation: https://contextstream.io/docs/mcp/tools
7072
7227
  `.trim();
7073
7228
  var CONTEXTSTREAM_RULES_MINIMAL = `
7074
7229
  ## ContextStream (Minimal)
@@ -7080,6 +7235,7 @@ var CONTEXTSTREAM_RULES_MINIMAL = `
7080
7235
  - For code/file discovery, use \`session_smart_search\` before raw repo scans (\`rg\`, \`ls\`, \`find\`); fall back only if needed.
7081
7236
  - After meaningful work/decisions/preferences: \`session_capture(event_type=decision|preference|task|insight, title="\u2026", content="\u2026")\`.
7082
7237
  - On frustration/corrections/tool mistakes: \`session_capture_lesson(...)\`.
7238
+ - Full tool catalog (workspaces, projects, search, memory, graph, AI, integrations): see https://contextstream.io/docs/mcp/tools
7083
7239
  `.trim();
7084
7240
  var TEMPLATES = {
7085
7241
  codex: {
@@ -9668,6 +9824,95 @@ Use this to find specific issues, PRs, or discussions.`,
9668
9824
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
9669
9825
  }
9670
9826
  );
9827
+ registerTool(
9828
+ "github_knowledge",
9829
+ {
9830
+ title: "GitHub extracted knowledge",
9831
+ description: `Get knowledge extracted from GitHub issues and PRs.
9832
+ Returns: decisions, lessons, and insights automatically distilled from GitHub conversations.
9833
+ This surfaces key decisions and learnings from your repository discussions.
9834
+
9835
+ Example queries:
9836
+ - "What decisions were made about authentication?"
9837
+ - "What lessons learned from production incidents?"
9838
+ - "Show recent architectural decisions"`,
9839
+ inputSchema: external_exports.object({
9840
+ workspace_id: external_exports.string().uuid().optional(),
9841
+ limit: external_exports.number().optional().describe("Maximum items to return (default: 20)"),
9842
+ node_type: external_exports.enum(["decision", "lesson", "fact", "insight"]).optional().describe("Filter by knowledge type")
9843
+ })
9844
+ },
9845
+ async (input) => {
9846
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
9847
+ if (!workspaceId) {
9848
+ return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
9849
+ }
9850
+ const result = await client.githubKnowledge({ workspace_id: workspaceId, limit: input.limit, node_type: input.node_type });
9851
+ if (result.length === 0) {
9852
+ return { content: [{ type: "text", text: "No knowledge extracted from GitHub yet. Knowledge is distilled from issues/PRs after sync." }] };
9853
+ }
9854
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
9855
+ }
9856
+ );
9857
+ registerTool(
9858
+ "slack_knowledge",
9859
+ {
9860
+ title: "Slack extracted knowledge",
9861
+ description: `Get knowledge extracted from Slack conversations.
9862
+ Returns: decisions, lessons, and insights automatically distilled from Slack discussions.
9863
+ This surfaces key decisions and learnings from your team conversations.
9864
+
9865
+ Example queries:
9866
+ - "What decisions were made in #engineering this week?"
9867
+ - "Show lessons learned from outages"
9868
+ - "What architectural insights came from Slack?"`,
9869
+ inputSchema: external_exports.object({
9870
+ workspace_id: external_exports.string().uuid().optional(),
9871
+ limit: external_exports.number().optional().describe("Maximum items to return (default: 20)"),
9872
+ node_type: external_exports.enum(["decision", "lesson", "fact", "insight"]).optional().describe("Filter by knowledge type")
9873
+ })
9874
+ },
9875
+ async (input) => {
9876
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
9877
+ if (!workspaceId) {
9878
+ return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
9879
+ }
9880
+ const result = await client.slackKnowledge({ workspace_id: workspaceId, limit: input.limit, node_type: input.node_type });
9881
+ if (result.length === 0) {
9882
+ return { content: [{ type: "text", text: "No knowledge extracted from Slack yet. Knowledge is distilled from high-engagement threads after sync." }] };
9883
+ }
9884
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
9885
+ }
9886
+ );
9887
+ registerTool(
9888
+ "integrations_status",
9889
+ {
9890
+ title: "Integration health status",
9891
+ description: `Check the status of all integrations (GitHub, Slack, etc.) for a workspace.
9892
+ Returns: connection status, last sync time, next sync time, and any errors.
9893
+ Use this to verify integrations are healthy and syncing properly.`,
9894
+ inputSchema: external_exports.object({
9895
+ workspace_id: external_exports.string().uuid().optional()
9896
+ })
9897
+ },
9898
+ async (input) => {
9899
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
9900
+ if (!workspaceId) {
9901
+ return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
9902
+ }
9903
+ const result = await client.integrationsStatus({ workspace_id: workspaceId });
9904
+ if (result.length === 0) {
9905
+ return { content: [{ type: "text", text: "No integrations configured for this workspace." }] };
9906
+ }
9907
+ const formatted = result.map((i) => {
9908
+ const status = i.status === "connected" ? "\u2705" : i.status === "error" ? "\u274C" : "\u23F3";
9909
+ const lastSync = i.last_sync_at ? new Date(i.last_sync_at).toLocaleString() : "Never";
9910
+ const error = i.error_message ? ` (Error: ${i.error_message})` : "";
9911
+ return `${status} ${i.provider}: ${i.status} | Last sync: ${lastSync} | Resources: ${i.resources_synced}${error}`;
9912
+ }).join("\n");
9913
+ return { content: [{ type: "text", text: formatted }], structuredContent: toStructured(result) };
9914
+ }
9915
+ );
9671
9916
  }
9672
9917
 
9673
9918
  // src/resources.ts
@@ -10535,6 +10780,12 @@ Created API key: ${maskApiKey(apiKey)}
10535
10780
  console.log(" 2) Extended \u2014 more guidance + examples (higher token overhead)");
10536
10781
  const modeChoice = normalizeInput(await rl.question("Choose [1/2] (default 1): ")) || "1";
10537
10782
  const mode = modeChoice === "2" ? "full" : "minimal";
10783
+ console.log("\nMCP toolset (which tools to expose to the AI):");
10784
+ console.log(" 1) Core (recommended) \u2014 essential session/context tools (~17 tools, lower token overhead)");
10785
+ console.log(" 2) Full \u2014 all tools including workspaces, projects, search, memory, graph, AI, integrations (~86 tools)");
10786
+ console.log(" Note: Claude Code/Desktop may warn about large tool lists when using full toolset.");
10787
+ const toolsetChoice = normalizeInput(await rl.question("Choose [1/2] (default 1): ")) || "1";
10788
+ const toolset = toolsetChoice === "2" ? "full" : "core";
10538
10789
  const editors = ["codex", "claude", "cursor", "windsurf", "cline", "kilo", "roo", "aider"];
10539
10790
  console.log('\nSelect editors to configure (comma-separated numbers, or "all"):');
10540
10791
  editors.forEach((e, i) => console.log(` ${i + 1}) ${EDITOR_LABELS[e]}`));
@@ -10565,9 +10816,9 @@ Created API key: ${maskApiKey(apiKey)}
10565
10816
  const mcpChoiceDefault = hasCodex && !hasProjectMcpEditors ? "1" : "3";
10566
10817
  const mcpChoice = normalizeInput(await rl.question(`Choose [${hasCodex && !hasProjectMcpEditors ? "1/2" : "1/2/3/4"}] (default ${mcpChoiceDefault}): `)) || mcpChoiceDefault;
10567
10818
  const mcpScope = mcpChoice === "2" && hasCodex && !hasProjectMcpEditors ? "skip" : mcpChoice === "4" ? "skip" : mcpChoice === "1" ? "global" : mcpChoice === "2" ? "project" : "both";
10568
- const mcpServer = buildContextStreamMcpServer({ apiUrl, apiKey });
10569
- const mcpServerClaude = buildContextStreamMcpServer({ apiUrl, apiKey, toolset: "core" });
10570
- const vsCodeServer = buildContextStreamVsCodeServer({ apiUrl, apiKey });
10819
+ const mcpServer = toolset === "full" ? buildContextStreamMcpServer({ apiUrl, apiKey, toolset: "full" }) : buildContextStreamMcpServer({ apiUrl, apiKey });
10820
+ const mcpServerClaude = buildContextStreamMcpServer({ apiUrl, apiKey, toolset });
10821
+ const vsCodeServer = toolset === "full" ? buildContextStreamVsCodeServer({ apiUrl, apiKey, toolset: "full" }) : buildContextStreamVsCodeServer({ apiUrl, apiKey });
10571
10822
  const needsGlobalMcpConfig = mcpScope === "global" || mcpScope === "both" || mcpScope === "project" && hasCodex;
10572
10823
  if (needsGlobalMcpConfig) {
10573
10824
  console.log("\nInstalling global MCP config...");
@@ -10614,7 +10865,7 @@ Created API key: ${maskApiKey(apiKey)}
10614
10865
  }
10615
10866
  }
10616
10867
  console.log("- Claude Code: global MCP config is best done via `claude mcp add --transport stdio ...` (see docs).");
10617
- console.log(" macOS/Linux: claude mcp add --transport stdio contextstream --scope user --env CONTEXTSTREAM_API_URL=... --env CONTEXTSTREAM_API_KEY=... --env CONTEXTSTREAM_TOOLSET=core -- npx -y @contextstream/mcp-server");
10868
+ console.log(` macOS/Linux: claude mcp add --transport stdio contextstream --scope user --env CONTEXTSTREAM_API_URL=... --env CONTEXTSTREAM_API_KEY=... --env CONTEXTSTREAM_TOOLSET=${toolset} -- npx -y @contextstream/mcp-server`);
10618
10869
  console.log(" Windows (native): use `cmd /c npx -y @contextstream/mcp-server` after `--` if `npx` is not found.");
10619
10870
  continue;
10620
10871
  }
@@ -10817,10 +11068,15 @@ Applying to ${projects.length} project(s)...`);
10817
11068
  const skipped = writeActions.filter((a) => a.status === "skipped").length;
10818
11069
  const dry = writeActions.filter((a) => a.status === "dry-run").length;
10819
11070
  console.log(`Summary: ${created} created, ${updated} updated, ${appended} appended, ${skipped} skipped, ${dry} dry-run.`);
11071
+ console.log(`Toolset: ${toolset} (${toolset === "full" ? "~86 tools" : "~17 core tools"})`);
10820
11072
  }
10821
11073
  console.log("\nNext steps:");
10822
11074
  console.log("- Restart your editor/CLI after changing MCP config or rules.");
11075
+ console.log("- Prefer ContextStream search first: use session_smart_search (or mcp__contextstream__session_smart_search) before raw repo scans (rg/ls/find).");
10823
11076
  console.log("- If any tools require UI-based MCP setup (e.g. Cline/Kilo/Roo global), follow https://contextstream.io/docs/mcp.");
11077
+ if (toolset === "full") {
11078
+ console.log("- Note: Claude Code/Desktop may warn about large tool contexts. This is expected with the full toolset.");
11079
+ }
10824
11080
  } finally {
10825
11081
  rl.close();
10826
11082
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contextstream/mcp-server",
3
- "version": "0.3.40",
3
+ "version": "0.3.41",
4
4
  "description": "MCP server exposing ContextStream public API - code context, memory, search, and AI tools for developers",
5
5
  "type": "module",
6
6
  "license": "MIT",