@contextstream/mcp-server 0.3.27 → 0.3.28

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 +1 -1
  2. package/dist/index.js +499 -1
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -20,7 +20,7 @@ No special syntax. No commands to learn. Just ask.
20
20
 
21
21
  > **Tip:** For best results, add the [recommended editor rules](https://contextstream.io/docs/quickstart) so your AI consistently calls `session_init` / `context_smart` automatically.
22
22
 
23
- ![ContextStream in action](mcp.gif.gif)
23
+ ![ContextStream in action](compare1.gif)
24
24
 
25
25
  ## Features
26
26
 
package/dist/index.js CHANGED
@@ -6282,6 +6282,191 @@ W:${wsHint}
6282
6282
  }
6283
6283
  return matches / keywords.length;
6284
6284
  }
6285
+ // ============================================
6286
+ // Slack Integration Methods
6287
+ // ============================================
6288
+ /**
6289
+ * Get Slack integration statistics and overview
6290
+ */
6291
+ async slackStats(params) {
6292
+ const withDefaults = this.withDefaults(params || {});
6293
+ if (!withDefaults.workspace_id) {
6294
+ throw new Error("workspace_id is required for Slack stats");
6295
+ }
6296
+ const query = new URLSearchParams();
6297
+ if (params?.days) query.set("days", String(params.days));
6298
+ const suffix = query.toString() ? `?${query.toString()}` : "";
6299
+ return request(this.config, `/workspaces/${withDefaults.workspace_id}/slack/stats${suffix}`, { method: "GET" });
6300
+ }
6301
+ /**
6302
+ * Get Slack users for a workspace
6303
+ */
6304
+ async slackUsers(params) {
6305
+ const withDefaults = this.withDefaults(params || {});
6306
+ if (!withDefaults.workspace_id) {
6307
+ throw new Error("workspace_id is required for Slack users");
6308
+ }
6309
+ const query = new URLSearchParams();
6310
+ if (params?.page) query.set("page", String(params.page));
6311
+ if (params?.per_page) query.set("per_page", String(params.per_page));
6312
+ const suffix = query.toString() ? `?${query.toString()}` : "";
6313
+ return request(this.config, `/workspaces/${withDefaults.workspace_id}/slack/users${suffix}`, { method: "GET" });
6314
+ }
6315
+ /**
6316
+ * Get Slack channels with stats
6317
+ */
6318
+ async slackChannels(params) {
6319
+ const withDefaults = this.withDefaults(params || {});
6320
+ if (!withDefaults.workspace_id) {
6321
+ throw new Error("workspace_id is required for Slack channels");
6322
+ }
6323
+ return request(this.config, `/workspaces/${withDefaults.workspace_id}/slack/channels`, { method: "GET" });
6324
+ }
6325
+ /**
6326
+ * Get recent Slack activity feed
6327
+ */
6328
+ async slackActivity(params) {
6329
+ const withDefaults = this.withDefaults(params || {});
6330
+ if (!withDefaults.workspace_id) {
6331
+ throw new Error("workspace_id is required for Slack activity");
6332
+ }
6333
+ const query = new URLSearchParams();
6334
+ if (params?.limit) query.set("limit", String(params.limit));
6335
+ if (params?.offset) query.set("offset", String(params.offset));
6336
+ if (params?.channel_id) query.set("channel_id", params.channel_id);
6337
+ const suffix = query.toString() ? `?${query.toString()}` : "";
6338
+ return request(this.config, `/workspaces/${withDefaults.workspace_id}/slack/activity${suffix}`, { method: "GET" });
6339
+ }
6340
+ /**
6341
+ * Get high-engagement Slack discussions
6342
+ */
6343
+ async slackDiscussions(params) {
6344
+ const withDefaults = this.withDefaults(params || {});
6345
+ if (!withDefaults.workspace_id) {
6346
+ throw new Error("workspace_id is required for Slack discussions");
6347
+ }
6348
+ const query = new URLSearchParams();
6349
+ if (params?.limit) query.set("limit", String(params.limit));
6350
+ const suffix = query.toString() ? `?${query.toString()}` : "";
6351
+ return request(this.config, `/workspaces/${withDefaults.workspace_id}/slack/discussions${suffix}`, { method: "GET" });
6352
+ }
6353
+ /**
6354
+ * Get top Slack contributors
6355
+ */
6356
+ async slackContributors(params) {
6357
+ const withDefaults = this.withDefaults(params || {});
6358
+ if (!withDefaults.workspace_id) {
6359
+ throw new Error("workspace_id is required for Slack contributors");
6360
+ }
6361
+ const query = new URLSearchParams();
6362
+ if (params?.limit) query.set("limit", String(params.limit));
6363
+ const suffix = query.toString() ? `?${query.toString()}` : "";
6364
+ return request(this.config, `/workspaces/${withDefaults.workspace_id}/slack/contributors${suffix}`, { method: "GET" });
6365
+ }
6366
+ /**
6367
+ * Trigger a sync of Slack user profiles
6368
+ */
6369
+ async slackSyncUsers(params) {
6370
+ const withDefaults = this.withDefaults(params || {});
6371
+ if (!withDefaults.workspace_id) {
6372
+ throw new Error("workspace_id is required for syncing Slack users");
6373
+ }
6374
+ return request(this.config, `/workspaces/${withDefaults.workspace_id}/slack/sync-users`, { method: "POST" });
6375
+ }
6376
+ /**
6377
+ * Search Slack messages
6378
+ */
6379
+ async slackSearch(params) {
6380
+ const withDefaults = this.withDefaults(params || {});
6381
+ if (!withDefaults.workspace_id) {
6382
+ throw new Error("workspace_id is required for Slack search");
6383
+ }
6384
+ const query = new URLSearchParams();
6385
+ query.set("q", params.q);
6386
+ if (params?.limit) query.set("limit", String(params.limit));
6387
+ return request(this.config, `/workspaces/${withDefaults.workspace_id}/slack/search?${query.toString()}`, { method: "GET" });
6388
+ }
6389
+ // ============================================
6390
+ // GitHub Integration Methods
6391
+ // ============================================
6392
+ /**
6393
+ * Get GitHub integration statistics and overview
6394
+ */
6395
+ async githubStats(params) {
6396
+ const withDefaults = this.withDefaults(params || {});
6397
+ if (!withDefaults.workspace_id) {
6398
+ throw new Error("workspace_id is required for GitHub stats");
6399
+ }
6400
+ return request(this.config, `/workspaces/${withDefaults.workspace_id}/github/stats`, { method: "GET" });
6401
+ }
6402
+ /**
6403
+ * Get GitHub repository stats
6404
+ */
6405
+ async githubRepos(params) {
6406
+ const withDefaults = this.withDefaults(params || {});
6407
+ if (!withDefaults.workspace_id) {
6408
+ throw new Error("workspace_id is required for GitHub repos");
6409
+ }
6410
+ return request(this.config, `/workspaces/${withDefaults.workspace_id}/github/repos`, { method: "GET" });
6411
+ }
6412
+ /**
6413
+ * Get recent GitHub activity feed
6414
+ */
6415
+ async githubActivity(params) {
6416
+ const withDefaults = this.withDefaults(params || {});
6417
+ if (!withDefaults.workspace_id) {
6418
+ throw new Error("workspace_id is required for GitHub activity");
6419
+ }
6420
+ const query = new URLSearchParams();
6421
+ if (params?.limit) query.set("limit", String(params.limit));
6422
+ if (params?.offset) query.set("offset", String(params.offset));
6423
+ if (params?.repo) query.set("repo", params.repo);
6424
+ if (params?.type) query.set("type", params.type);
6425
+ const suffix = query.toString() ? `?${query.toString()}` : "";
6426
+ return request(this.config, `/workspaces/${withDefaults.workspace_id}/github/activity${suffix}`, { method: "GET" });
6427
+ }
6428
+ /**
6429
+ * Get GitHub issues and PRs
6430
+ */
6431
+ async githubIssues(params) {
6432
+ const withDefaults = this.withDefaults(params || {});
6433
+ if (!withDefaults.workspace_id) {
6434
+ throw new Error("workspace_id is required for GitHub issues");
6435
+ }
6436
+ const query = new URLSearchParams();
6437
+ if (params?.limit) query.set("limit", String(params.limit));
6438
+ if (params?.offset) query.set("offset", String(params.offset));
6439
+ if (params?.state) query.set("state", params.state);
6440
+ if (params?.repo) query.set("repo", params.repo);
6441
+ const suffix = query.toString() ? `?${query.toString()}` : "";
6442
+ return request(this.config, `/workspaces/${withDefaults.workspace_id}/github/issues${suffix}`, { method: "GET" });
6443
+ }
6444
+ /**
6445
+ * Get top GitHub contributors
6446
+ */
6447
+ async githubContributors(params) {
6448
+ const withDefaults = this.withDefaults(params || {});
6449
+ if (!withDefaults.workspace_id) {
6450
+ throw new Error("workspace_id is required for GitHub contributors");
6451
+ }
6452
+ const query = new URLSearchParams();
6453
+ if (params?.limit) query.set("limit", String(params.limit));
6454
+ const suffix = query.toString() ? `?${query.toString()}` : "";
6455
+ return request(this.config, `/workspaces/${withDefaults.workspace_id}/github/contributors${suffix}`, { method: "GET" });
6456
+ }
6457
+ /**
6458
+ * Search GitHub content
6459
+ */
6460
+ async githubSearch(params) {
6461
+ const withDefaults = this.withDefaults(params || {});
6462
+ if (!withDefaults.workspace_id) {
6463
+ throw new Error("workspace_id is required for GitHub search");
6464
+ }
6465
+ const query = new URLSearchParams();
6466
+ query.set("q", params.q);
6467
+ if (params?.limit) query.set("limit", String(params.limit));
6468
+ return request(this.config, `/workspaces/${withDefaults.workspace_id}/github/search?${query.toString()}`, { method: "GET" });
6469
+ }
6285
6470
  };
6286
6471
 
6287
6472
  // src/rules-templates.ts
@@ -6537,7 +6722,22 @@ function registerTools(server, client, sessionManager) {
6537
6722
  "ai_context_budget",
6538
6723
  "ai_embeddings",
6539
6724
  "ai_plan",
6540
- "ai_tasks"
6725
+ "ai_tasks",
6726
+ // Slack integration tools
6727
+ "slack_stats",
6728
+ "slack_channels",
6729
+ "slack_contributors",
6730
+ "slack_activity",
6731
+ "slack_discussions",
6732
+ "slack_search",
6733
+ "slack_sync_users",
6734
+ // GitHub integration tools
6735
+ "github_stats",
6736
+ "github_repos",
6737
+ "github_contributors",
6738
+ "github_activity",
6739
+ "github_issues",
6740
+ "github_search"
6541
6741
  ]);
6542
6742
  const proTools = (() => {
6543
6743
  const raw = process.env.CONTEXTSTREAM_PRO_TOOLS;
@@ -8510,6 +8710,304 @@ This saves ~80% tokens compared to including full chat history.`,
8510
8710
  };
8511
8711
  }
8512
8712
  );
8713
+ registerTool(
8714
+ "slack_stats",
8715
+ {
8716
+ title: "Slack overview stats",
8717
+ description: `Get Slack integration statistics and overview for a workspace.
8718
+ Returns: total messages, threads, active users, channel stats, activity trends, and sync status.
8719
+ Use this to understand Slack activity and engagement patterns.`,
8720
+ inputSchema: external_exports.object({
8721
+ workspace_id: external_exports.string().uuid().optional(),
8722
+ days: external_exports.number().optional().describe("Number of days to include in stats (default: 30)")
8723
+ })
8724
+ },
8725
+ async (input) => {
8726
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
8727
+ if (!workspaceId) {
8728
+ return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
8729
+ }
8730
+ const result = await client.slackStats({ workspace_id: workspaceId, days: input.days });
8731
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
8732
+ }
8733
+ );
8734
+ registerTool(
8735
+ "slack_channels",
8736
+ {
8737
+ title: "List Slack channels",
8738
+ description: `Get synced Slack channels with statistics for a workspace.
8739
+ Returns: channel names, message counts, thread counts, and last activity timestamps.`,
8740
+ inputSchema: external_exports.object({
8741
+ workspace_id: external_exports.string().uuid().optional()
8742
+ })
8743
+ },
8744
+ async (input) => {
8745
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
8746
+ if (!workspaceId) {
8747
+ return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
8748
+ }
8749
+ const result = await client.slackChannels({ workspace_id: workspaceId });
8750
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
8751
+ }
8752
+ );
8753
+ registerTool(
8754
+ "slack_contributors",
8755
+ {
8756
+ title: "Slack top contributors",
8757
+ description: `Get top Slack contributors for a workspace.
8758
+ Returns: user profiles with message counts, sorted by activity level.`,
8759
+ inputSchema: external_exports.object({
8760
+ workspace_id: external_exports.string().uuid().optional(),
8761
+ limit: external_exports.number().optional().describe("Maximum contributors to return (default: 20)")
8762
+ })
8763
+ },
8764
+ async (input) => {
8765
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
8766
+ if (!workspaceId) {
8767
+ return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
8768
+ }
8769
+ const result = await client.slackContributors({ workspace_id: workspaceId, limit: input.limit });
8770
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
8771
+ }
8772
+ );
8773
+ registerTool(
8774
+ "slack_activity",
8775
+ {
8776
+ title: "Slack activity feed",
8777
+ description: `Get recent Slack activity feed for a workspace.
8778
+ Returns: messages with user info, reactions, replies, and timestamps.
8779
+ Can filter by channel.`,
8780
+ inputSchema: external_exports.object({
8781
+ workspace_id: external_exports.string().uuid().optional(),
8782
+ limit: external_exports.number().optional().describe("Maximum messages to return (default: 50)"),
8783
+ offset: external_exports.number().optional().describe("Pagination offset"),
8784
+ channel_id: external_exports.string().optional().describe("Filter by specific channel ID")
8785
+ })
8786
+ },
8787
+ async (input) => {
8788
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
8789
+ if (!workspaceId) {
8790
+ return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
8791
+ }
8792
+ const result = await client.slackActivity({
8793
+ workspace_id: workspaceId,
8794
+ limit: input.limit,
8795
+ offset: input.offset,
8796
+ channel_id: input.channel_id
8797
+ });
8798
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
8799
+ }
8800
+ );
8801
+ registerTool(
8802
+ "slack_discussions",
8803
+ {
8804
+ title: "Slack key discussions",
8805
+ description: `Get high-engagement Slack discussions/threads for a workspace.
8806
+ Returns: threads with high reply/reaction counts, sorted by engagement.
8807
+ Useful for finding important conversations and decisions.`,
8808
+ inputSchema: external_exports.object({
8809
+ workspace_id: external_exports.string().uuid().optional(),
8810
+ limit: external_exports.number().optional().describe("Maximum discussions to return (default: 20)")
8811
+ })
8812
+ },
8813
+ async (input) => {
8814
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
8815
+ if (!workspaceId) {
8816
+ return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
8817
+ }
8818
+ const result = await client.slackDiscussions({ workspace_id: workspaceId, limit: input.limit });
8819
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
8820
+ }
8821
+ );
8822
+ registerTool(
8823
+ "slack_search",
8824
+ {
8825
+ title: "Search Slack messages",
8826
+ description: `Search Slack messages for a workspace.
8827
+ Returns: matching messages with channel, user, and engagement info.
8828
+ Use this to find specific conversations or topics.`,
8829
+ inputSchema: external_exports.object({
8830
+ workspace_id: external_exports.string().uuid().optional(),
8831
+ q: external_exports.string().describe("Search query"),
8832
+ limit: external_exports.number().optional().describe("Maximum results (default: 50)")
8833
+ })
8834
+ },
8835
+ async (input) => {
8836
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
8837
+ if (!workspaceId) {
8838
+ return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
8839
+ }
8840
+ const result = await client.slackSearch({ workspace_id: workspaceId, q: input.q, limit: input.limit });
8841
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
8842
+ }
8843
+ );
8844
+ registerTool(
8845
+ "slack_sync_users",
8846
+ {
8847
+ title: "Sync Slack users",
8848
+ description: `Trigger a sync of Slack user profiles for a workspace.
8849
+ This fetches the latest user info from Slack and updates local profiles.
8850
+ Also auto-maps Slack users to ContextStream users by email.`,
8851
+ inputSchema: external_exports.object({
8852
+ workspace_id: external_exports.string().uuid().optional()
8853
+ })
8854
+ },
8855
+ async (input) => {
8856
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
8857
+ if (!workspaceId) {
8858
+ return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
8859
+ }
8860
+ const result = await client.slackSyncUsers({ workspace_id: workspaceId });
8861
+ return {
8862
+ content: [{
8863
+ type: "text",
8864
+ text: `\u2705 Synced ${result.synced_users} Slack users, auto-mapped ${result.auto_mapped} by email.`
8865
+ }],
8866
+ structuredContent: toStructured(result)
8867
+ };
8868
+ }
8869
+ );
8870
+ registerTool(
8871
+ "github_stats",
8872
+ {
8873
+ title: "GitHub overview stats",
8874
+ description: `Get GitHub integration statistics and overview for a workspace.
8875
+ Returns: total issues, PRs, releases, comments, repository stats, activity trends, and sync status.
8876
+ Use this to understand GitHub activity and engagement patterns across synced repositories.`,
8877
+ inputSchema: external_exports.object({
8878
+ workspace_id: external_exports.string().uuid().optional()
8879
+ })
8880
+ },
8881
+ async (input) => {
8882
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
8883
+ if (!workspaceId) {
8884
+ return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
8885
+ }
8886
+ const result = await client.githubStats({ workspace_id: workspaceId });
8887
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
8888
+ }
8889
+ );
8890
+ registerTool(
8891
+ "github_repos",
8892
+ {
8893
+ title: "List GitHub repositories",
8894
+ description: `Get synced GitHub repositories with statistics for a workspace.
8895
+ Returns: repository names with issue, PR, release, and comment counts, plus last activity timestamps.`,
8896
+ inputSchema: external_exports.object({
8897
+ workspace_id: external_exports.string().uuid().optional()
8898
+ })
8899
+ },
8900
+ async (input) => {
8901
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
8902
+ if (!workspaceId) {
8903
+ return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
8904
+ }
8905
+ const result = await client.githubRepos({ workspace_id: workspaceId });
8906
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
8907
+ }
8908
+ );
8909
+ registerTool(
8910
+ "github_contributors",
8911
+ {
8912
+ title: "GitHub top contributors",
8913
+ description: `Get top GitHub contributors for a workspace.
8914
+ Returns: usernames with contribution counts, sorted by activity level.`,
8915
+ inputSchema: external_exports.object({
8916
+ workspace_id: external_exports.string().uuid().optional(),
8917
+ limit: external_exports.number().optional().describe("Maximum contributors to return (default: 20)")
8918
+ })
8919
+ },
8920
+ async (input) => {
8921
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
8922
+ if (!workspaceId) {
8923
+ return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
8924
+ }
8925
+ const result = await client.githubContributors({ workspace_id: workspaceId, limit: input.limit });
8926
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
8927
+ }
8928
+ );
8929
+ registerTool(
8930
+ "github_activity",
8931
+ {
8932
+ title: "GitHub activity feed",
8933
+ description: `Get recent GitHub activity feed for a workspace.
8934
+ Returns: issues, PRs, releases, and comments with details like state, author, labels.
8935
+ Can filter by repository or type (issue, pull_request, release, comment).`,
8936
+ inputSchema: external_exports.object({
8937
+ workspace_id: external_exports.string().uuid().optional(),
8938
+ limit: external_exports.number().optional().describe("Maximum items to return (default: 50)"),
8939
+ offset: external_exports.number().optional().describe("Pagination offset"),
8940
+ repo: external_exports.string().optional().describe("Filter by repository name"),
8941
+ type: external_exports.enum(["issue", "pull_request", "release", "comment"]).optional().describe("Filter by item type")
8942
+ })
8943
+ },
8944
+ async (input) => {
8945
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
8946
+ if (!workspaceId) {
8947
+ return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
8948
+ }
8949
+ const result = await client.githubActivity({
8950
+ workspace_id: workspaceId,
8951
+ limit: input.limit,
8952
+ offset: input.offset,
8953
+ repo: input.repo,
8954
+ type: input.type
8955
+ });
8956
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
8957
+ }
8958
+ );
8959
+ registerTool(
8960
+ "github_issues",
8961
+ {
8962
+ title: "GitHub issues and PRs",
8963
+ description: `Get GitHub issues and pull requests for a workspace.
8964
+ Returns: issues/PRs with title, state, author, labels, comment count.
8965
+ Can filter by state (open/closed) or repository.`,
8966
+ inputSchema: external_exports.object({
8967
+ workspace_id: external_exports.string().uuid().optional(),
8968
+ limit: external_exports.number().optional().describe("Maximum items to return (default: 50)"),
8969
+ offset: external_exports.number().optional().describe("Pagination offset"),
8970
+ state: external_exports.enum(["open", "closed"]).optional().describe("Filter by state"),
8971
+ repo: external_exports.string().optional().describe("Filter by repository name")
8972
+ })
8973
+ },
8974
+ async (input) => {
8975
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
8976
+ if (!workspaceId) {
8977
+ return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
8978
+ }
8979
+ const result = await client.githubIssues({
8980
+ workspace_id: workspaceId,
8981
+ limit: input.limit,
8982
+ offset: input.offset,
8983
+ state: input.state,
8984
+ repo: input.repo
8985
+ });
8986
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
8987
+ }
8988
+ );
8989
+ registerTool(
8990
+ "github_search",
8991
+ {
8992
+ title: "Search GitHub content",
8993
+ description: `Search GitHub issues, PRs, and comments for a workspace.
8994
+ Returns: matching items with repository, title, state, and content preview.
8995
+ Use this to find specific issues, PRs, or discussions.`,
8996
+ inputSchema: external_exports.object({
8997
+ workspace_id: external_exports.string().uuid().optional(),
8998
+ q: external_exports.string().describe("Search query"),
8999
+ limit: external_exports.number().optional().describe("Maximum results (default: 50)")
9000
+ })
9001
+ },
9002
+ async (input) => {
9003
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
9004
+ if (!workspaceId) {
9005
+ return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
9006
+ }
9007
+ const result = await client.githubSearch({ workspace_id: workspaceId, q: input.q, limit: input.limit });
9008
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
9009
+ }
9010
+ );
8513
9011
  }
8514
9012
 
8515
9013
  // src/resources.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contextstream/mcp-server",
3
- "version": "0.3.27",
3
+ "version": "0.3.28",
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",