@contextstream/mcp-server 0.4.31 → 0.4.33

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 (4) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +131 -318
  3. package/dist/index.js +503 -41
  4. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -7436,7 +7436,7 @@ W:${wsHint}
7436
7436
  const query = new URLSearchParams();
7437
7437
  if (params?.days) query.set("days", String(params.days));
7438
7438
  const suffix = query.toString() ? `?${query.toString()}` : "";
7439
- return request(this.config, `/workspaces/${withDefaults.workspace_id}/slack/stats${suffix}`, {
7439
+ return request(this.config, `/integrations/workspaces/${withDefaults.workspace_id}/slack/stats${suffix}`, {
7440
7440
  method: "GET"
7441
7441
  });
7442
7442
  }
@@ -7452,7 +7452,7 @@ W:${wsHint}
7452
7452
  if (params?.page) query.set("page", String(params.page));
7453
7453
  if (params?.per_page) query.set("per_page", String(params.per_page));
7454
7454
  const suffix = query.toString() ? `?${query.toString()}` : "";
7455
- return request(this.config, `/workspaces/${withDefaults.workspace_id}/slack/users${suffix}`, {
7455
+ return request(this.config, `/integrations/workspaces/${withDefaults.workspace_id}/slack/users${suffix}`, {
7456
7456
  method: "GET"
7457
7457
  });
7458
7458
  }
@@ -7464,7 +7464,7 @@ W:${wsHint}
7464
7464
  if (!withDefaults.workspace_id) {
7465
7465
  throw new Error("workspace_id is required for Slack channels");
7466
7466
  }
7467
- return request(this.config, `/workspaces/${withDefaults.workspace_id}/slack/channels`, {
7467
+ return request(this.config, `/integrations/workspaces/${withDefaults.workspace_id}/slack/channels`, {
7468
7468
  method: "GET"
7469
7469
  });
7470
7470
  }
@@ -7483,7 +7483,7 @@ W:${wsHint}
7483
7483
  const suffix = query.toString() ? `?${query.toString()}` : "";
7484
7484
  return request(
7485
7485
  this.config,
7486
- `/workspaces/${withDefaults.workspace_id}/slack/activity${suffix}`,
7486
+ `/integrations/workspaces/${withDefaults.workspace_id}/slack/activity${suffix}`,
7487
7487
  { method: "GET" }
7488
7488
  );
7489
7489
  }
@@ -7500,7 +7500,7 @@ W:${wsHint}
7500
7500
  const suffix = query.toString() ? `?${query.toString()}` : "";
7501
7501
  return request(
7502
7502
  this.config,
7503
- `/workspaces/${withDefaults.workspace_id}/slack/discussions${suffix}`,
7503
+ `/integrations/workspaces/${withDefaults.workspace_id}/slack/discussions${suffix}`,
7504
7504
  { method: "GET" }
7505
7505
  );
7506
7506
  }
@@ -7517,7 +7517,7 @@ W:${wsHint}
7517
7517
  const suffix = query.toString() ? `?${query.toString()}` : "";
7518
7518
  return request(
7519
7519
  this.config,
7520
- `/workspaces/${withDefaults.workspace_id}/slack/contributors${suffix}`,
7520
+ `/integrations/workspaces/${withDefaults.workspace_id}/slack/contributors${suffix}`,
7521
7521
  { method: "GET" }
7522
7522
  );
7523
7523
  }
@@ -7529,7 +7529,7 @@ W:${wsHint}
7529
7529
  if (!withDefaults.workspace_id) {
7530
7530
  throw new Error("workspace_id is required for syncing Slack users");
7531
7531
  }
7532
- return request(this.config, `/workspaces/${withDefaults.workspace_id}/slack/sync-users`, {
7532
+ return request(this.config, `/integrations/workspaces/${withDefaults.workspace_id}/slack/sync-users`, {
7533
7533
  method: "POST"
7534
7534
  });
7535
7535
  }
@@ -7546,7 +7546,7 @@ W:${wsHint}
7546
7546
  if (params?.limit) query.set("limit", String(params.limit));
7547
7547
  return request(
7548
7548
  this.config,
7549
- `/workspaces/${withDefaults.workspace_id}/slack/search?${query.toString()}`,
7549
+ `/integrations/workspaces/${withDefaults.workspace_id}/slack/search?${query.toString()}`,
7550
7550
  { method: "GET" }
7551
7551
  );
7552
7552
  }
@@ -7561,7 +7561,7 @@ W:${wsHint}
7561
7561
  if (!withDefaults.workspace_id) {
7562
7562
  throw new Error("workspace_id is required for GitHub stats");
7563
7563
  }
7564
- return request(this.config, `/workspaces/${withDefaults.workspace_id}/github/stats`, {
7564
+ return request(this.config, `/integrations/workspaces/${withDefaults.workspace_id}/github/stats`, {
7565
7565
  method: "GET"
7566
7566
  });
7567
7567
  }
@@ -7573,7 +7573,7 @@ W:${wsHint}
7573
7573
  if (!withDefaults.workspace_id) {
7574
7574
  throw new Error("workspace_id is required for GitHub repos");
7575
7575
  }
7576
- return request(this.config, `/workspaces/${withDefaults.workspace_id}/github/repos`, {
7576
+ return request(this.config, `/integrations/workspaces/${withDefaults.workspace_id}/github/repos`, {
7577
7577
  method: "GET"
7578
7578
  });
7579
7579
  }
@@ -7593,7 +7593,7 @@ W:${wsHint}
7593
7593
  const suffix = query.toString() ? `?${query.toString()}` : "";
7594
7594
  return request(
7595
7595
  this.config,
7596
- `/workspaces/${withDefaults.workspace_id}/github/activity${suffix}`,
7596
+ `/integrations/workspaces/${withDefaults.workspace_id}/github/activity${suffix}`,
7597
7597
  { method: "GET" }
7598
7598
  );
7599
7599
  }
@@ -7611,7 +7611,7 @@ W:${wsHint}
7611
7611
  if (params?.state) query.set("state", params.state);
7612
7612
  if (params?.repo) query.set("repo", params.repo);
7613
7613
  const suffix = query.toString() ? `?${query.toString()}` : "";
7614
- return request(this.config, `/workspaces/${withDefaults.workspace_id}/github/issues${suffix}`, {
7614
+ return request(this.config, `/integrations/workspaces/${withDefaults.workspace_id}/github/issues${suffix}`, {
7615
7615
  method: "GET"
7616
7616
  });
7617
7617
  }
@@ -7628,7 +7628,7 @@ W:${wsHint}
7628
7628
  const suffix = query.toString() ? `?${query.toString()}` : "";
7629
7629
  return request(
7630
7630
  this.config,
7631
- `/workspaces/${withDefaults.workspace_id}/github/contributors${suffix}`,
7631
+ `/integrations/workspaces/${withDefaults.workspace_id}/github/contributors${suffix}`,
7632
7632
  { method: "GET" }
7633
7633
  );
7634
7634
  }
@@ -7645,7 +7645,7 @@ W:${wsHint}
7645
7645
  if (params?.limit) query.set("limit", String(params.limit));
7646
7646
  return request(
7647
7647
  this.config,
7648
- `/workspaces/${withDefaults.workspace_id}/github/search?${query.toString()}`,
7648
+ `/integrations/workspaces/${withDefaults.workspace_id}/github/search?${query.toString()}`,
7649
7649
  { method: "GET" }
7650
7650
  );
7651
7651
  }
@@ -7663,7 +7663,7 @@ W:${wsHint}
7663
7663
  const suffix = query.toString() ? `?${query.toString()}` : "";
7664
7664
  return request(
7665
7665
  this.config,
7666
- `/workspaces/${withDefaults.workspace_id}/github/knowledge${suffix}`,
7666
+ `/integrations/workspaces/${withDefaults.workspace_id}/github/knowledge${suffix}`,
7667
7667
  { method: "GET" }
7668
7668
  );
7669
7669
  }
@@ -7681,7 +7681,7 @@ W:${wsHint}
7681
7681
  const suffix = query.toString() ? `?${query.toString()}` : "";
7682
7682
  return request(
7683
7683
  this.config,
7684
- `/workspaces/${withDefaults.workspace_id}/slack/knowledge${suffix}`,
7684
+ `/integrations/workspaces/${withDefaults.workspace_id}/slack/knowledge${suffix}`,
7685
7685
  { method: "GET" }
7686
7686
  );
7687
7687
  }
@@ -7693,9 +7693,10 @@ W:${wsHint}
7693
7693
  if (!withDefaults.workspace_id) {
7694
7694
  throw new Error("workspace_id is required for integrations status");
7695
7695
  }
7696
- return request(this.config, `/workspaces/${withDefaults.workspace_id}/integrations/status`, {
7696
+ const result = await request(this.config, `/integrations/workspaces/${withDefaults.workspace_id}/integrations/status`, {
7697
7697
  method: "GET"
7698
7698
  });
7699
+ return unwrapApiResponse(result);
7699
7700
  }
7700
7701
  /**
7701
7702
  * Get GitHub summary for a workspace
@@ -7784,17 +7785,181 @@ W:${wsHint}
7784
7785
  if (!withDefaults.workspace_id) {
7785
7786
  throw new Error("workspace_id is required for creating Notion pages");
7786
7787
  }
7787
- return request(this.config, `/integrations/notion/pages`, {
7788
+ return request(this.config, `/integrations/notion/pages?workspace_id=${withDefaults.workspace_id}`, {
7788
7789
  method: "POST",
7789
- body: JSON.stringify({
7790
- workspace_id: withDefaults.workspace_id,
7790
+ body: {
7791
7791
  title: params.title,
7792
7792
  content: params.content,
7793
7793
  parent_database_id: params.parent_database_id,
7794
7794
  parent_page_id: params.parent_page_id
7795
- })
7795
+ }
7796
7796
  });
7797
7797
  }
7798
+ /**
7799
+ * Get Notion integration statistics and overview
7800
+ */
7801
+ async notionStats(params) {
7802
+ const withDefaults = this.withDefaults(params || {});
7803
+ if (!withDefaults.workspace_id) {
7804
+ throw new Error("workspace_id is required for Notion stats");
7805
+ }
7806
+ const query = new URLSearchParams();
7807
+ if (params?.days) query.set("days", String(params.days));
7808
+ const suffix = query.toString() ? `?${query.toString()}` : "";
7809
+ return request(
7810
+ this.config,
7811
+ `/integrations/workspaces/${withDefaults.workspace_id}/notion/stats${suffix}`,
7812
+ { method: "GET" }
7813
+ );
7814
+ }
7815
+ /**
7816
+ * Get recent Notion activity feed
7817
+ */
7818
+ async notionActivity(params) {
7819
+ const withDefaults = this.withDefaults(params || {});
7820
+ if (!withDefaults.workspace_id) {
7821
+ throw new Error("workspace_id is required for Notion activity");
7822
+ }
7823
+ const query = new URLSearchParams();
7824
+ if (params?.limit) query.set("limit", String(params.limit));
7825
+ if (params?.database_id) query.set("database_id", params.database_id);
7826
+ const suffix = query.toString() ? `?${query.toString()}` : "";
7827
+ return request(
7828
+ this.config,
7829
+ `/integrations/workspaces/${withDefaults.workspace_id}/notion/activity${suffix}`,
7830
+ { method: "GET" }
7831
+ );
7832
+ }
7833
+ /**
7834
+ * Get knowledge extracted from Notion (decisions, lessons, insights)
7835
+ */
7836
+ async notionKnowledge(params) {
7837
+ const withDefaults = this.withDefaults(params || {});
7838
+ if (!withDefaults.workspace_id) {
7839
+ throw new Error("workspace_id is required for Notion knowledge");
7840
+ }
7841
+ const query = new URLSearchParams();
7842
+ if (params?.limit) query.set("limit", String(params.limit));
7843
+ if (params?.node_type) query.set("node_type", params.node_type);
7844
+ const suffix = query.toString() ? `?${query.toString()}` : "";
7845
+ return request(
7846
+ this.config,
7847
+ `/integrations/workspaces/${withDefaults.workspace_id}/notion/knowledge${suffix}`,
7848
+ { method: "GET" }
7849
+ );
7850
+ }
7851
+ /**
7852
+ * Get Notion summary for a workspace
7853
+ */
7854
+ async notionSummary(params) {
7855
+ const withDefaults = this.withDefaults(params || {});
7856
+ if (!withDefaults.workspace_id) {
7857
+ throw new Error("workspace_id is required for Notion summary");
7858
+ }
7859
+ const query = new URLSearchParams();
7860
+ if (params?.days) query.set("days", String(params.days));
7861
+ if (params?.database_id) query.set("database_id", params.database_id);
7862
+ const suffix = query.toString() ? `?${query.toString()}` : "";
7863
+ return request(
7864
+ this.config,
7865
+ `/integrations/workspaces/${withDefaults.workspace_id}/notion/summary${suffix}`,
7866
+ { method: "GET" }
7867
+ );
7868
+ }
7869
+ /**
7870
+ * List Notion databases available in the workspace
7871
+ */
7872
+ async notionListDatabases(params) {
7873
+ const withDefaults = this.withDefaults(params || {});
7874
+ if (!withDefaults.workspace_id) {
7875
+ throw new Error("workspace_id is required for listing Notion databases");
7876
+ }
7877
+ return request(
7878
+ this.config,
7879
+ `/integrations/workspaces/${withDefaults.workspace_id}/notion/databases`,
7880
+ { method: "GET" }
7881
+ );
7882
+ }
7883
+ /**
7884
+ * Search/list pages in Notion with smart type detection filtering
7885
+ */
7886
+ async notionSearchPages(params) {
7887
+ const withDefaults = this.withDefaults(params || {});
7888
+ if (!withDefaults.workspace_id) {
7889
+ throw new Error("workspace_id is required for searching Notion pages");
7890
+ }
7891
+ const query = new URLSearchParams();
7892
+ if (params?.query) query.set("query", params.query);
7893
+ if (params?.database_id) query.set("database_id", params.database_id);
7894
+ if (params?.limit) query.set("limit", String(params.limit));
7895
+ if (params?.event_type) query.set("event_type", params.event_type);
7896
+ if (params?.status) query.set("status", params.status);
7897
+ if (params?.priority) query.set("priority", params.priority);
7898
+ if (params?.has_due_date !== void 0) query.set("has_due_date", String(params.has_due_date));
7899
+ if (params?.tags) query.set("tags", params.tags);
7900
+ const suffix = query.toString() ? `?${query.toString()}` : "";
7901
+ return request(
7902
+ this.config,
7903
+ `/integrations/workspaces/${withDefaults.workspace_id}/notion/pages${suffix}`,
7904
+ { method: "GET" }
7905
+ );
7906
+ }
7907
+ /**
7908
+ * Get a specific Notion page with its content
7909
+ */
7910
+ async notionGetPage(params) {
7911
+ const withDefaults = this.withDefaults(params || {});
7912
+ if (!withDefaults.workspace_id) {
7913
+ throw new Error("workspace_id is required for getting Notion page");
7914
+ }
7915
+ return request(
7916
+ this.config,
7917
+ `/integrations/workspaces/${withDefaults.workspace_id}/notion/pages/${params.page_id}`,
7918
+ { method: "GET" }
7919
+ );
7920
+ }
7921
+ /**
7922
+ * Query a Notion database (get rows with optional filters)
7923
+ */
7924
+ async notionQueryDatabase(params) {
7925
+ const withDefaults = this.withDefaults(params || {});
7926
+ if (!withDefaults.workspace_id) {
7927
+ throw new Error("workspace_id is required for querying Notion database");
7928
+ }
7929
+ return request(
7930
+ this.config,
7931
+ `/integrations/workspaces/${withDefaults.workspace_id}/notion/databases/${params.database_id}/query`,
7932
+ {
7933
+ method: "POST",
7934
+ body: {
7935
+ filter: params.filter,
7936
+ sorts: params.sorts,
7937
+ page_size: params.limit
7938
+ }
7939
+ }
7940
+ );
7941
+ }
7942
+ /**
7943
+ * Update a Notion page
7944
+ */
7945
+ async notionUpdatePage(params) {
7946
+ const withDefaults = this.withDefaults(params || {});
7947
+ if (!withDefaults.workspace_id) {
7948
+ throw new Error("workspace_id is required for updating Notion page");
7949
+ }
7950
+ return request(
7951
+ this.config,
7952
+ `/integrations/workspaces/${withDefaults.workspace_id}/notion/pages/${params.page_id}`,
7953
+ {
7954
+ method: "PATCH",
7955
+ body: {
7956
+ title: params.title,
7957
+ content: params.content,
7958
+ properties: params.properties
7959
+ }
7960
+ }
7961
+ );
7962
+ }
7798
7963
  // ============================================
7799
7964
  // Reminder Methods
7800
7965
  // ============================================
@@ -8756,7 +8921,16 @@ var TOOL_CATALOG = [
8756
8921
  {
8757
8922
  name: "Notion",
8758
8923
  tools: [
8759
- { name: "create_page", hint: "new-page" }
8924
+ { name: "create_page", hint: "new-page" },
8925
+ { name: "search_pages", hint: "find" },
8926
+ { name: "list_databases", hint: "list-dbs" },
8927
+ { name: "get_page", hint: "get" },
8928
+ { name: "query_database", hint: "query-db" },
8929
+ { name: "update_page", hint: "edit" },
8930
+ { name: "stats", hint: "overview" },
8931
+ { name: "activity", hint: "recent" },
8932
+ { name: "knowledge", hint: "insights" },
8933
+ { name: "summary", hint: "brief" }
8760
8934
  ]
8761
8935
  }
8762
8936
  ];
@@ -9635,7 +9809,16 @@ var GITHUB_TOOLS = /* @__PURE__ */ new Set([
9635
9809
  "github_summary"
9636
9810
  ]);
9637
9811
  var NOTION_TOOLS = /* @__PURE__ */ new Set([
9638
- "notion_create_page"
9812
+ "notion_create_page",
9813
+ "notion_list_databases",
9814
+ "notion_search_pages",
9815
+ "notion_get_page",
9816
+ "notion_query_database",
9817
+ "notion_update_page",
9818
+ "notion_stats",
9819
+ "notion_activity",
9820
+ "notion_knowledge",
9821
+ "notion_summary"
9639
9822
  ]);
9640
9823
  var CROSS_INTEGRATION_TOOLS = /* @__PURE__ */ new Set([
9641
9824
  "integrations_status",
@@ -9849,6 +10032,15 @@ var TOOL_BUNDLES = {
9849
10032
  "github_knowledge",
9850
10033
  "github_summary",
9851
10034
  "notion_create_page",
10035
+ "notion_list_databases",
10036
+ "notion_search_pages",
10037
+ "notion_get_page",
10038
+ "notion_query_database",
10039
+ "notion_update_page",
10040
+ "notion_stats",
10041
+ "notion_activity",
10042
+ "notion_knowledge",
10043
+ "notion_summary",
9852
10044
  "integrations_status",
9853
10045
  "integrations_search",
9854
10046
  "integrations_summary",
@@ -10000,7 +10192,7 @@ var CONSOLIDATED_TOOLS = /* @__PURE__ */ new Set([
10000
10192
  "reminder",
10001
10193
  // Consolidates reminders_list, reminders_create, etc.
10002
10194
  "integration",
10003
- // Consolidates slack_*, github_*, integrations_*
10195
+ // Consolidates slack_*, github_*, notion_*, integrations_*
10004
10196
  "help"
10005
10197
  // Consolidates session_tools, auth_me, mcp_server_version, etc.
10006
10198
  ]);
@@ -10328,7 +10520,16 @@ function registerTools(server, client, sessionManager) {
10328
10520
  "github_issues",
10329
10521
  "github_search",
10330
10522
  // Notion integration tools
10331
- "notion_create_page"
10523
+ "notion_create_page",
10524
+ "notion_list_databases",
10525
+ "notion_search_pages",
10526
+ "notion_get_page",
10527
+ "notion_query_database",
10528
+ "notion_update_page",
10529
+ "notion_stats",
10530
+ "notion_activity",
10531
+ "notion_knowledge",
10532
+ "notion_summary"
10332
10533
  ]);
10333
10534
  const proTools = (() => {
10334
10535
  const raw = process.env.CONTEXTSTREAM_PRO_TOOLS;
@@ -10383,14 +10584,14 @@ function registerTools(server, client, sessionManager) {
10383
10584
  ].join("\n")
10384
10585
  );
10385
10586
  }
10386
- let integrationStatus = { checked: false, slack: false, github: false };
10587
+ let integrationStatus = { checked: false, slack: false, github: false, notion: false };
10387
10588
  let toolsListChangedNotified = false;
10388
10589
  async function checkIntegrationStatus(workspaceId) {
10389
10590
  if (integrationStatus.checked && integrationStatus.workspaceId === workspaceId) {
10390
- return { slack: integrationStatus.slack, github: integrationStatus.github };
10591
+ return { slack: integrationStatus.slack, github: integrationStatus.github, notion: integrationStatus.notion };
10391
10592
  }
10392
10593
  if (!workspaceId) {
10393
- return { slack: false, github: false };
10594
+ return { slack: false, github: false, notion: false };
10394
10595
  }
10395
10596
  try {
10396
10597
  const status = await client.integrationsStatus({ workspace_id: workspaceId });
@@ -10400,32 +10601,38 @@ function registerTools(server, client, sessionManager) {
10400
10601
  const githubConnected = status?.some(
10401
10602
  (s) => s.provider === "github" && s.status === "connected"
10402
10603
  ) ?? false;
10604
+ const notionConnected = status?.some(
10605
+ (s) => s.provider === "notion" && s.status === "connected"
10606
+ ) ?? false;
10403
10607
  integrationStatus = {
10404
10608
  checked: true,
10405
10609
  slack: slackConnected,
10406
10610
  github: githubConnected,
10611
+ notion: notionConnected,
10407
10612
  workspaceId
10408
10613
  };
10409
10614
  console.error(
10410
- `[ContextStream] Integration status: Slack=${slackConnected}, GitHub=${githubConnected}`
10615
+ `[ContextStream] Integration status: Slack=${slackConnected}, GitHub=${githubConnected}, Notion=${notionConnected}`
10411
10616
  );
10412
- return { slack: slackConnected, github: githubConnected };
10617
+ return { slack: slackConnected, github: githubConnected, notion: notionConnected };
10413
10618
  } catch (error) {
10414
10619
  console.error("[ContextStream] Failed to check integration status:", error);
10415
- return { slack: false, github: false };
10620
+ return { slack: false, github: false, notion: false };
10416
10621
  }
10417
10622
  }
10418
10623
  function updateIntegrationStatus(status, workspaceId) {
10419
10624
  const hadSlack = integrationStatus.slack;
10420
10625
  const hadGithub = integrationStatus.github;
10626
+ const hadNotion = integrationStatus.notion;
10421
10627
  integrationStatus = {
10422
10628
  checked: true,
10423
10629
  slack: status.slack,
10424
10630
  github: status.github,
10631
+ notion: status.notion,
10425
10632
  workspaceId
10426
10633
  };
10427
10634
  if (AUTO_HIDE_INTEGRATIONS && !toolsListChangedNotified) {
10428
- const newlyConnected = !hadSlack && status.slack || !hadGithub && status.github;
10635
+ const newlyConnected = !hadSlack && status.slack || !hadGithub && status.github || !hadNotion && status.notion;
10429
10636
  if (newlyConnected) {
10430
10637
  try {
10431
10638
  server.server?.sendToolsListChanged?.();
@@ -10443,8 +10650,9 @@ function registerTools(server, client, sessionManager) {
10443
10650
  if (!AUTO_HIDE_INTEGRATIONS) return null;
10444
10651
  const requiresSlack = SLACK_TOOLS.has(toolName);
10445
10652
  const requiresGithub = GITHUB_TOOLS.has(toolName);
10653
+ const requiresNotion = NOTION_TOOLS.has(toolName);
10446
10654
  const requiresCrossIntegration = CROSS_INTEGRATION_TOOLS.has(toolName);
10447
- if (!requiresSlack && !requiresGithub && !requiresCrossIntegration) {
10655
+ if (!requiresSlack && !requiresGithub && !requiresNotion && !requiresCrossIntegration) {
10448
10656
  return null;
10449
10657
  }
10450
10658
  const workspaceId = sessionManager?.getContext()?.workspace_id;
@@ -10479,6 +10687,18 @@ function registerTools(server, client, sessionManager) {
10479
10687
  ].join("\n")
10480
10688
  );
10481
10689
  }
10690
+ if (requiresNotion && !status.notion) {
10691
+ return errorResult(
10692
+ [
10693
+ `Integration not connected: \`${toolName}\` requires Notion integration.`,
10694
+ "",
10695
+ "To use Notion tools:",
10696
+ "1. Go to https://contextstream.io/settings/integrations",
10697
+ "2. Connect your Notion workspace",
10698
+ "3. Try this command again"
10699
+ ].join("\n")
10700
+ );
10701
+ }
10482
10702
  if (requiresCrossIntegration && !status.slack && !status.github) {
10483
10703
  return errorResult(
10484
10704
  [
@@ -10504,6 +10724,9 @@ function registerTools(server, client, sessionManager) {
10504
10724
  if (GITHUB_TOOLS.has(toolName)) {
10505
10725
  return integrationStatus.github;
10506
10726
  }
10727
+ if (NOTION_TOOLS.has(toolName)) {
10728
+ return integrationStatus.notion;
10729
+ }
10507
10730
  if (CROSS_INTEGRATION_TOOLS.has(toolName)) {
10508
10731
  return integrationStatus.slack || integrationStatus.github;
10509
10732
  }
@@ -14504,7 +14727,10 @@ Use this to verify integrations are healthy and syncing properly.`,
14504
14727
  const githubConnected = result?.some(
14505
14728
  (s) => s.provider === "github" && s.status === "connected"
14506
14729
  ) ?? false;
14507
- updateIntegrationStatus({ slack: slackConnected, github: githubConnected }, workspaceId);
14730
+ const notionConnected = result?.some(
14731
+ (s) => s.provider === "notion" && s.status === "connected"
14732
+ ) ?? false;
14733
+ updateIntegrationStatus({ slack: slackConnected, github: githubConnected, notion: notionConnected }, workspaceId);
14508
14734
  }
14509
14735
  if (result.length === 0) {
14510
14736
  return {
@@ -16187,9 +16413,9 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
16187
16413
  "integration",
16188
16414
  {
16189
16415
  title: "Integration",
16190
- description: `Integration operations for Slack and GitHub. Provider: slack, github, all. Actions: status, search, stats, activity, contributors, knowledge, summary, channels (slack), discussions (slack), repos (github), issues (github).`,
16416
+ description: `Integration operations for Slack, GitHub, and Notion. Provider: slack, github, notion, all. Actions: status, search, stats, activity, contributors, knowledge, summary, channels (slack), discussions (slack), repos (github), issues (github), create_page (notion), list_databases (notion), search_pages (notion with smart type detection - filter by event_type, status, priority, has_due_date, tags), get_page (notion), query_database (notion), update_page (notion).`,
16191
16417
  inputSchema: external_exports.object({
16192
- provider: external_exports.enum(["slack", "github", "all"]).describe("Integration provider"),
16418
+ provider: external_exports.enum(["slack", "github", "notion", "all"]).describe("Integration provider"),
16193
16419
  action: external_exports.enum([
16194
16420
  "status",
16195
16421
  "search",
@@ -16202,21 +16428,49 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
16202
16428
  "discussions",
16203
16429
  "sync_users",
16204
16430
  "repos",
16205
- "issues"
16431
+ "issues",
16432
+ // Notion-specific actions
16433
+ "create_page",
16434
+ "list_databases",
16435
+ "search_pages",
16436
+ "get_page",
16437
+ "query_database",
16438
+ "update_page"
16206
16439
  ]).describe("Action to perform"),
16207
16440
  workspace_id: external_exports.string().uuid().optional(),
16208
16441
  project_id: external_exports.string().uuid().optional(),
16209
16442
  query: external_exports.string().optional(),
16210
16443
  limit: external_exports.number().optional(),
16211
16444
  since: external_exports.string().optional(),
16212
- until: external_exports.string().optional()
16445
+ until: external_exports.string().optional(),
16446
+ // Notion-specific parameters
16447
+ title: external_exports.string().optional().describe("Page title (for Notion create_page/update_page)"),
16448
+ content: external_exports.string().optional().describe("Page content in Markdown (for Notion create_page/update_page)"),
16449
+ parent_database_id: external_exports.string().optional().describe("Parent database ID (for Notion create_page)"),
16450
+ parent_page_id: external_exports.string().optional().describe("Parent page ID (for Notion create_page)"),
16451
+ page_id: external_exports.string().optional().describe("Page ID (for Notion get_page/update_page)"),
16452
+ database_id: external_exports.string().optional().describe("Database ID (for Notion query_database/search_pages/activity)"),
16453
+ days: external_exports.number().optional().describe("Number of days for stats/summary (default: 7)"),
16454
+ node_type: external_exports.string().optional().describe("Filter knowledge by type (for Notion knowledge)"),
16455
+ filter: external_exports.record(external_exports.unknown()).optional().describe("Query filter (for Notion query_database)"),
16456
+ sorts: external_exports.array(external_exports.object({
16457
+ property: external_exports.string(),
16458
+ direction: external_exports.enum(["ascending", "descending"])
16459
+ })).optional().describe("Sort order (for Notion query_database)"),
16460
+ properties: external_exports.record(external_exports.unknown()).optional().describe("Page properties (for Notion update_page)"),
16461
+ // Smart type detection filters (for Notion search_pages)
16462
+ event_type: external_exports.enum(["NotionTask", "NotionMeeting", "NotionWiki", "NotionBugReport", "NotionFeature", "NotionJournal", "NotionPage"]).optional().describe("Filter by detected content type (for Notion search_pages)"),
16463
+ status: external_exports.string().optional().describe("Filter by status property, e.g. 'Done', 'In Progress' (for Notion search_pages)"),
16464
+ priority: external_exports.string().optional().describe("Filter by priority property, e.g. 'High', 'Medium', 'Low' (for Notion search_pages)"),
16465
+ has_due_date: external_exports.boolean().optional().describe("Filter to pages with or without due dates (for Notion search_pages)"),
16466
+ tags: external_exports.string().optional().describe("Filter by tags, comma-separated (for Notion search_pages)")
16213
16467
  })
16214
16468
  },
16215
16469
  async (input) => {
16216
16470
  const workspaceId = resolveWorkspaceId(input.workspace_id);
16217
16471
  const projectId = resolveProjectId(input.project_id);
16218
16472
  const integrationGated = await gateIfIntegrationTool(
16219
- input.provider === "slack" ? "slack_search" : input.provider === "github" ? "github_search" : "integrations_status"
16473
+ input.provider === "slack" ? "slack_search" : input.provider === "github" ? "github_search" : input.provider === "notion" ? "notion_create_page" : "integrations_status"
16220
16474
  );
16221
16475
  if (integrationGated) return integrationGated;
16222
16476
  const params = {
@@ -16284,8 +16538,17 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
16284
16538
  content: [{ type: "text", text: formatContent(result) }],
16285
16539
  structuredContent: toStructured(result)
16286
16540
  };
16541
+ } else if (input.provider === "notion") {
16542
+ const result = await client.notionStats({
16543
+ workspace_id: workspaceId,
16544
+ days: input.days
16545
+ });
16546
+ return {
16547
+ content: [{ type: "text", text: formatContent(result) }],
16548
+ structuredContent: toStructured(result)
16549
+ };
16287
16550
  }
16288
- return errorResult("stats requires provider: slack or github");
16551
+ return errorResult("stats requires provider: slack, github, or notion");
16289
16552
  }
16290
16553
  case "activity": {
16291
16554
  if (input.provider === "slack") {
@@ -16300,8 +16563,18 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
16300
16563
  content: [{ type: "text", text: formatContent(result) }],
16301
16564
  structuredContent: toStructured(result)
16302
16565
  };
16566
+ } else if (input.provider === "notion") {
16567
+ const result = await client.notionActivity({
16568
+ workspace_id: workspaceId,
16569
+ limit: input.limit,
16570
+ database_id: input.database_id
16571
+ });
16572
+ return {
16573
+ content: [{ type: "text", text: formatContent(result) }],
16574
+ structuredContent: toStructured(result)
16575
+ };
16303
16576
  }
16304
- return errorResult("activity requires provider: slack or github");
16577
+ return errorResult("activity requires provider: slack, github, or notion");
16305
16578
  }
16306
16579
  case "contributors": {
16307
16580
  if (input.provider === "slack") {
@@ -16332,6 +16605,16 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
16332
16605
  content: [{ type: "text", text: formatContent(result) }],
16333
16606
  structuredContent: toStructured(result)
16334
16607
  };
16608
+ } else if (input.provider === "notion") {
16609
+ const result = await client.notionKnowledge({
16610
+ workspace_id: workspaceId,
16611
+ limit: input.limit,
16612
+ node_type: input.node_type
16613
+ });
16614
+ return {
16615
+ content: [{ type: "text", text: formatContent(result) }],
16616
+ structuredContent: toStructured(result)
16617
+ };
16335
16618
  } else {
16336
16619
  const result = await client.integrationsKnowledge(params);
16337
16620
  return {
@@ -16353,6 +16636,16 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
16353
16636
  content: [{ type: "text", text: formatContent(result) }],
16354
16637
  structuredContent: toStructured(result)
16355
16638
  };
16639
+ } else if (input.provider === "notion") {
16640
+ const result = await client.notionSummary({
16641
+ workspace_id: workspaceId,
16642
+ days: input.days,
16643
+ database_id: input.database_id
16644
+ });
16645
+ return {
16646
+ content: [{ type: "text", text: formatContent(result) }],
16647
+ structuredContent: toStructured(result)
16648
+ };
16356
16649
  } else {
16357
16650
  const result = await client.integrationsSummary(params);
16358
16651
  return {
@@ -16411,6 +16704,175 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
16411
16704
  structuredContent: toStructured(result)
16412
16705
  };
16413
16706
  }
16707
+ case "create_page": {
16708
+ if (input.provider !== "notion") {
16709
+ return errorResult("create_page is only available for notion provider");
16710
+ }
16711
+ if (!input.title) {
16712
+ return errorResult("title is required for create_page action");
16713
+ }
16714
+ if (!workspaceId) {
16715
+ return errorResult(
16716
+ "Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly."
16717
+ );
16718
+ }
16719
+ const result = await client.createNotionPage({
16720
+ workspace_id: workspaceId,
16721
+ title: input.title,
16722
+ content: input.content,
16723
+ parent_database_id: input.parent_database_id,
16724
+ parent_page_id: input.parent_page_id
16725
+ });
16726
+ return {
16727
+ content: [
16728
+ {
16729
+ type: "text",
16730
+ text: `Page created successfully!
16731
+
16732
+ Title: ${result.title}
16733
+ URL: ${result.url}
16734
+ ID: ${result.id}
16735
+ Created: ${result.created_time}`
16736
+ }
16737
+ ],
16738
+ structuredContent: toStructured(result)
16739
+ };
16740
+ }
16741
+ case "list_databases": {
16742
+ if (input.provider !== "notion") {
16743
+ return errorResult("list_databases is only available for notion provider");
16744
+ }
16745
+ if (!workspaceId) {
16746
+ return errorResult(
16747
+ "Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly."
16748
+ );
16749
+ }
16750
+ const databases = await client.notionListDatabases({
16751
+ workspace_id: workspaceId
16752
+ });
16753
+ return {
16754
+ content: [{ type: "text", text: formatContent(databases) }],
16755
+ structuredContent: toStructured(databases)
16756
+ };
16757
+ }
16758
+ case "search_pages": {
16759
+ if (input.provider !== "notion") {
16760
+ return errorResult("search_pages is only available for notion provider");
16761
+ }
16762
+ if (!workspaceId) {
16763
+ return errorResult(
16764
+ "Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly."
16765
+ );
16766
+ }
16767
+ const pages = await client.notionSearchPages({
16768
+ workspace_id: workspaceId,
16769
+ query: input.query,
16770
+ database_id: input.database_id,
16771
+ limit: input.limit,
16772
+ event_type: input.event_type,
16773
+ status: input.status,
16774
+ priority: input.priority,
16775
+ has_due_date: input.has_due_date,
16776
+ tags: input.tags
16777
+ });
16778
+ return {
16779
+ content: [{ type: "text", text: formatContent(pages) }],
16780
+ structuredContent: toStructured(pages)
16781
+ };
16782
+ }
16783
+ case "get_page": {
16784
+ if (input.provider !== "notion") {
16785
+ return errorResult("get_page is only available for notion provider");
16786
+ }
16787
+ if (!input.page_id) {
16788
+ return errorResult("page_id is required for get_page action");
16789
+ }
16790
+ if (!workspaceId) {
16791
+ return errorResult(
16792
+ "Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly."
16793
+ );
16794
+ }
16795
+ const page = await client.notionGetPage({
16796
+ workspace_id: workspaceId,
16797
+ page_id: input.page_id
16798
+ });
16799
+ return {
16800
+ content: [
16801
+ {
16802
+ type: "text",
16803
+ text: `# ${page.title}
16804
+
16805
+ ID: ${page.id}
16806
+ URL: ${page.url}
16807
+ Created: ${page.created_time}
16808
+ Last edited: ${page.last_edited_time}
16809
+
16810
+ ---
16811
+
16812
+ ${page.content}`
16813
+ }
16814
+ ],
16815
+ structuredContent: toStructured(page)
16816
+ };
16817
+ }
16818
+ case "query_database": {
16819
+ if (input.provider !== "notion") {
16820
+ return errorResult("query_database is only available for notion provider");
16821
+ }
16822
+ if (!input.database_id) {
16823
+ return errorResult("database_id is required for query_database action");
16824
+ }
16825
+ if (!workspaceId) {
16826
+ return errorResult(
16827
+ "Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly."
16828
+ );
16829
+ }
16830
+ const queryResult = await client.notionQueryDatabase({
16831
+ workspace_id: workspaceId,
16832
+ database_id: input.database_id,
16833
+ filter: input.filter,
16834
+ sorts: input.sorts,
16835
+ limit: input.limit
16836
+ });
16837
+ return {
16838
+ content: [{ type: "text", text: formatContent(queryResult) }],
16839
+ structuredContent: toStructured(queryResult)
16840
+ };
16841
+ }
16842
+ case "update_page": {
16843
+ if (input.provider !== "notion") {
16844
+ return errorResult("update_page is only available for notion provider");
16845
+ }
16846
+ if (!input.page_id) {
16847
+ return errorResult("page_id is required for update_page action");
16848
+ }
16849
+ if (!workspaceId) {
16850
+ return errorResult(
16851
+ "Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly."
16852
+ );
16853
+ }
16854
+ const updatedPage = await client.notionUpdatePage({
16855
+ workspace_id: workspaceId,
16856
+ page_id: input.page_id,
16857
+ title: input.title,
16858
+ content: input.content,
16859
+ properties: input.properties
16860
+ });
16861
+ return {
16862
+ content: [
16863
+ {
16864
+ type: "text",
16865
+ text: `Page updated successfully!
16866
+
16867
+ Title: ${updatedPage.title}
16868
+ URL: ${updatedPage.url}
16869
+ ID: ${updatedPage.id}
16870
+ Last edited: ${updatedPage.last_edited_time}`
16871
+ }
16872
+ ],
16873
+ structuredContent: toStructured(updatedPage)
16874
+ };
16875
+ }
16414
16876
  default:
16415
16877
  return errorResult(`Unknown action: ${input.action}`);
16416
16878
  }