@inkeep/agents-work-apps 0.58.1 → 0.58.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/env.d.ts CHANGED
@@ -14,11 +14,11 @@ declare const envSchema: z.ZodObject<{
14
14
  pentest: "pentest";
15
15
  }>>;
16
16
  LOG_LEVEL: z.ZodDefault<z.ZodEnum<{
17
- error: "error";
18
17
  trace: "trace";
19
18
  debug: "debug";
20
19
  info: "info";
21
20
  warn: "warn";
21
+ error: "error";
22
22
  }>>;
23
23
  INKEEP_AGENTS_RUN_DATABASE_URL: z.ZodOptional<z.ZodString>;
24
24
  INKEEP_AGENTS_MANAGE_UI_URL: z.ZodOptional<z.ZodString>;
@@ -28,6 +28,7 @@ declare const envSchema: z.ZodObject<{
28
28
  GITHUB_STATE_SIGNING_SECRET: z.ZodOptional<z.ZodString>;
29
29
  GITHUB_APP_NAME: z.ZodOptional<z.ZodString>;
30
30
  GITHUB_MCP_API_KEY: z.ZodOptional<z.ZodString>;
31
+ SLACK_MCP_API_KEY: z.ZodOptional<z.ZodString>;
31
32
  SLACK_CLIENT_ID: z.ZodOptional<z.ZodString>;
32
33
  SLACK_CLIENT_SECRET: z.ZodOptional<z.ZodString>;
33
34
  SLACK_SIGNING_SECRET: z.ZodOptional<z.ZodString>;
@@ -44,7 +45,7 @@ declare const envSchema: z.ZodObject<{
44
45
  declare const env: {
45
46
  NODE_ENV: "development" | "production" | "test";
46
47
  ENVIRONMENT: "development" | "production" | "test" | "pentest";
47
- LOG_LEVEL: "error" | "trace" | "debug" | "info" | "warn";
48
+ LOG_LEVEL: "trace" | "debug" | "info" | "warn" | "error";
48
49
  INKEEP_AGENTS_RUN_DATABASE_URL?: string | undefined;
49
50
  INKEEP_AGENTS_MANAGE_UI_URL?: string | undefined;
50
51
  GITHUB_APP_ID?: string | undefined;
@@ -53,6 +54,7 @@ declare const env: {
53
54
  GITHUB_STATE_SIGNING_SECRET?: string | undefined;
54
55
  GITHUB_APP_NAME?: string | undefined;
55
56
  GITHUB_MCP_API_KEY?: string | undefined;
57
+ SLACK_MCP_API_KEY?: string | undefined;
56
58
  SLACK_CLIENT_ID?: string | undefined;
57
59
  SLACK_CLIENT_SECRET?: string | undefined;
58
60
  SLACK_SIGNING_SECRET?: string | undefined;
package/dist/env.js CHANGED
@@ -30,6 +30,7 @@ const envSchema = z.object({
30
30
  GITHUB_STATE_SIGNING_SECRET: z.string().min(32, "GITHUB_STATE_SIGNING_SECRET must be at least 32 characters").optional().describe("Secret for signing GitHub OAuth state (minimum 32 characters)"),
31
31
  GITHUB_APP_NAME: z.string().optional().describe("Name of the GitHub App"),
32
32
  GITHUB_MCP_API_KEY: z.string().optional().describe("API key for the GitHub MCP"),
33
+ SLACK_MCP_API_KEY: z.string().optional().describe("API key for the Slack MCP"),
33
34
  SLACK_CLIENT_ID: z.string().optional().describe("Slack App Client ID"),
34
35
  SLACK_CLIENT_SECRET: z.string().optional().describe("Slack App Client Secret"),
35
36
  SLACK_SIGNING_SECRET: z.string().optional().describe("Slack App Signing Secret"),
@@ -4,10 +4,10 @@ import "./routes/setup.js";
4
4
  import "./routes/tokenExchange.js";
5
5
  import { WebhookVerificationResult, verifyWebhookSignature } from "./routes/webhooks.js";
6
6
  import { Hono } from "hono";
7
- import * as hono_types5 from "hono/types";
7
+ import * as hono_types0 from "hono/types";
8
8
 
9
9
  //#region src/github/index.d.ts
10
- declare function createGithubRoutes(): Hono<hono_types5.BlankEnv, hono_types5.BlankSchema, "/">;
11
- declare const githubRoutes: Hono<hono_types5.BlankEnv, hono_types5.BlankSchema, "/">;
10
+ declare function createGithubRoutes(): Hono<hono_types0.BlankEnv, hono_types0.BlankSchema, "/">;
11
+ declare const githubRoutes: Hono<hono_types0.BlankEnv, hono_types0.BlankSchema, "/">;
12
12
  //#endregion
13
13
  export { GenerateInstallationAccessTokenResult, GenerateTokenError, GenerateTokenResult, GitHubAppConfig, InstallationAccessToken, InstallationInfo, LookupInstallationError, LookupInstallationForRepoResult, LookupInstallationResult, WebhookVerificationResult, clearConfigCache, createAppJwt, createGithubRoutes, determineStatus, fetchInstallationDetails, fetchInstallationRepositories, generateInstallationAccessToken, getGitHubAppConfig, getGitHubAppName, getStateSigningSecret, getWebhookSecret, githubRoutes, isGitHubAppConfigured, isGitHubAppNameConfigured, isStateSigningConfigured, isWebhookConfigured, lookupInstallationForRepo, validateGitHubAppConfigOnStartup, validateGitHubInstallFlowConfigOnStartup, validateGitHubWebhookConfigOnStartup, verifyWebhookSignature };
@@ -1,7 +1,7 @@
1
- import * as hono1 from "hono";
1
+ import * as hono0 from "hono";
2
2
 
3
3
  //#region src/github/mcp/auth.d.ts
4
- declare const githubMcpAuth: () => hono1.MiddlewareHandler<{
4
+ declare const githubMcpAuth: () => hono0.MiddlewareHandler<{
5
5
  Variables: {
6
6
  toolId: string;
7
7
  };
@@ -1,11 +1,11 @@
1
1
  import { Hono } from "hono";
2
- import * as hono_types9 from "hono/types";
2
+ import * as hono_types3 from "hono/types";
3
3
 
4
4
  //#region src/github/mcp/index.d.ts
5
5
  declare const app: Hono<{
6
6
  Variables: {
7
7
  toolId: string;
8
8
  };
9
- }, hono_types9.BlankSchema, "/">;
9
+ }, hono_types3.BlankSchema, "/">;
10
10
  //#endregion
11
11
  export { app as default };
@@ -76,8 +76,8 @@ declare const ChangedFileSchema: z.ZodObject<{
76
76
  path: z.ZodString;
77
77
  status: z.ZodEnum<{
78
78
  added: "added";
79
- removed: "removed";
80
79
  modified: "modified";
80
+ removed: "removed";
81
81
  renamed: "renamed";
82
82
  copied: "copied";
83
83
  changed: "changed";
@@ -1,7 +1,7 @@
1
1
  import { Hono } from "hono";
2
- import * as hono_types3 from "hono/types";
2
+ import * as hono_types4 from "hono/types";
3
3
 
4
4
  //#region src/github/routes/setup.d.ts
5
- declare const app: Hono<hono_types3.BlankEnv, hono_types3.BlankSchema, "/">;
5
+ declare const app: Hono<hono_types4.BlankEnv, hono_types4.BlankSchema, "/">;
6
6
  //#endregion
7
7
  export { app as default };
@@ -1,7 +1,7 @@
1
1
  import { Hono } from "hono";
2
- import * as hono_types0 from "hono/types";
2
+ import * as hono_types6 from "hono/types";
3
3
 
4
4
  //#region src/github/routes/tokenExchange.d.ts
5
- declare const app: Hono<hono_types0.BlankEnv, hono_types0.BlankSchema, "/">;
5
+ declare const app: Hono<hono_types6.BlankEnv, hono_types6.BlankSchema, "/">;
6
6
  //#endregion
7
7
  export { app as default };
@@ -1,5 +1,5 @@
1
1
  import { Hono } from "hono";
2
- import * as hono_types1 from "hono/types";
2
+ import * as hono_types9 from "hono/types";
3
3
 
4
4
  //#region src/github/routes/webhooks.d.ts
5
5
  interface WebhookVerificationResult {
@@ -7,6 +7,6 @@ interface WebhookVerificationResult {
7
7
  error?: string;
8
8
  }
9
9
  declare function verifyWebhookSignature(payload: string, signature: string | undefined, secret: string): WebhookVerificationResult;
10
- declare const app: Hono<hono_types1.BlankEnv, hono_types1.BlankSchema, "/">;
10
+ declare const app: Hono<hono_types9.BlankEnv, hono_types9.BlankSchema, "/">;
11
11
  //#endregion
12
12
  export { WebhookVerificationResult, app as default, verifyWebhookSignature };
@@ -1,5 +1,7 @@
1
1
  import { DispatchOptions, SlackEventDispatchResult, dispatchSlackEvent } from "./dispatcher.js";
2
2
  import { ManageAppVariables, WorkAppsVariables } from "./types.js";
3
+ import { resolveWorkspaceToken } from "./mcp/utils.js";
4
+ import { getSlackClient, validateBotChannelMembership } from "./services/client.js";
3
5
  import { DefaultAgentConfig, SlackWorkspaceConnection, WorkspaceInstallData, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createConnectSession, deleteWorkspaceInstallation, findWorkspaceConnectionByTeamId, getConnectionAccessToken, getSlackIntegrationId, getSlackNango, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, listWorkspaceInstallations, setWorkspaceDefaultAgent, storeWorkspaceInstallation, updateConnectionMetadata } from "./services/nango.js";
4
6
  import { getChannelAgentConfig } from "./services/events/utils.js";
5
7
  import "./services/events/index.js";
@@ -9,7 +11,6 @@ import { startSocketMode } from "./socket-mode.js";
9
11
  import { OpenAPIHono } from "@hono/zod-openapi";
10
12
 
11
13
  //#region src/slack/index.d.ts
12
-
13
14
  declare function createSlackRoutes(): OpenAPIHono<{
14
15
  Variables: WorkAppsVariables;
15
16
  }, {}, "/">;
@@ -17,4 +18,4 @@ declare const slackRoutes: OpenAPIHono<{
17
18
  Variables: WorkAppsVariables;
18
19
  }, {}, "/">;
19
20
  //#endregion
20
- export { DefaultAgentConfig, type DispatchOptions, ManageAppVariables, type SlackEventDispatchResult, SlackWorkspaceConnection, WorkAppsVariables, WorkspaceInstallData, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createConnectSession, createSlackRoutes, deleteWorkspaceInstallation, dispatchSlackEvent, findWorkspaceConnectionByTeamId, getBotTokenForTeam, getChannelAgentConfig, getConnectionAccessToken, getSlackIntegrationId, getSlackNango, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, listWorkspaceInstallations, setBotTokenForTeam, setWorkspaceDefaultAgent, slackRoutes, startSocketMode, storeWorkspaceInstallation, updateConnectionMetadata };
21
+ export { DefaultAgentConfig, type DispatchOptions, ManageAppVariables, type SlackEventDispatchResult, SlackWorkspaceConnection, WorkAppsVariables, WorkspaceInstallData, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createConnectSession, createSlackRoutes, deleteWorkspaceInstallation, dispatchSlackEvent, findWorkspaceConnectionByTeamId, getBotTokenForTeam, getChannelAgentConfig, getConnectionAccessToken, getSlackClient, getSlackIntegrationId, getSlackNango, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, listWorkspaceInstallations, resolveWorkspaceToken, setBotTokenForTeam, setWorkspaceDefaultAgent, slackRoutes, startSocketMode, storeWorkspaceInstallation, updateConnectionMetadata, validateBotChannelMembership };
@@ -1,8 +1,11 @@
1
1
  import { clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createConnectSession, deleteWorkspaceInstallation, findWorkspaceConnectionByTeamId, getConnectionAccessToken, getSlackIntegrationId, getSlackNango, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, listWorkspaceInstallations, setWorkspaceDefaultAgent, storeWorkspaceInstallation, updateConnectionMetadata } from "./services/nango.js";
2
2
  import { getChannelAgentConfig } from "./services/events/utils.js";
3
+ import { getSlackClient, validateBotChannelMembership } from "./services/client.js";
3
4
  import "./services/events/index.js";
4
5
  import { getBotTokenForTeam, setBotTokenForTeam } from "./services/workspace-tokens.js";
5
6
  import { dispatchSlackEvent } from "./dispatcher.js";
7
+ import { resolveWorkspaceToken } from "./mcp/utils.js";
8
+ import mcp_default from "./mcp/index.js";
6
9
  import "./routes/oauth.js";
7
10
  import routes_default from "./routes/index.js";
8
11
  import { startSocketMode } from "./socket-mode.js";
@@ -22,9 +25,10 @@ import { OpenAPIHono } from "@hono/zod-openapi";
22
25
  function createSlackRoutes() {
23
26
  const app = new OpenAPIHono();
24
27
  app.route("/", routes_default);
28
+ app.route("/mcp", mcp_default);
25
29
  return app;
26
30
  }
27
31
  const slackRoutes = createSlackRoutes();
28
32
 
29
33
  //#endregion
30
- export { clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createConnectSession, createSlackRoutes, deleteWorkspaceInstallation, dispatchSlackEvent, findWorkspaceConnectionByTeamId, getBotTokenForTeam, getChannelAgentConfig, getConnectionAccessToken, getSlackIntegrationId, getSlackNango, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, listWorkspaceInstallations, setBotTokenForTeam, setWorkspaceDefaultAgent, slackRoutes, startSocketMode, storeWorkspaceInstallation, updateConnectionMetadata };
34
+ export { clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createConnectSession, createSlackRoutes, deleteWorkspaceInstallation, dispatchSlackEvent, findWorkspaceConnectionByTeamId, getBotTokenForTeam, getChannelAgentConfig, getConnectionAccessToken, getSlackClient, getSlackIntegrationId, getSlackNango, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, listWorkspaceInstallations, resolveWorkspaceToken, setBotTokenForTeam, setWorkspaceDefaultAgent, slackRoutes, startSocketMode, storeWorkspaceInstallation, updateConnectionMetadata, validateBotChannelMembership };
@@ -0,0 +1,12 @@
1
+ import * as hono0 from "hono";
2
+
3
+ //#region src/slack/mcp/auth.d.ts
4
+ declare const slackMcpAuth: () => hono0.MiddlewareHandler<{
5
+ Variables: {
6
+ toolId: string;
7
+ tenantId: string;
8
+ projectId: string;
9
+ };
10
+ }, string, {}, Response>;
11
+ //#endregion
12
+ export { slackMcpAuth };
@@ -0,0 +1,70 @@
1
+ import { env } from "../../env.js";
2
+ import { createApiError } from "@inkeep/agents-core";
3
+ import { createMiddleware } from "hono/factory";
4
+ import { timingSafeEqual } from "node:crypto";
5
+
6
+ //#region src/slack/mcp/auth.ts
7
+ const slackMcpAuth = () => createMiddleware(async (c, next) => {
8
+ const toolId = c.req.header("x-inkeep-tool-id");
9
+ if (!toolId) throw createApiError({
10
+ code: "unauthorized",
11
+ message: "Missing required header: x-inkeep-tool-id",
12
+ extensions: { parameter: {
13
+ in: "header",
14
+ name: "x-inkeep-tool-id"
15
+ } }
16
+ });
17
+ const tenantId = c.req.header("x-inkeep-tenant-id");
18
+ if (!tenantId) throw createApiError({
19
+ code: "unauthorized",
20
+ message: "Missing required header: x-inkeep-tenant-id",
21
+ extensions: { parameter: {
22
+ in: "header",
23
+ name: "x-inkeep-tenant-id"
24
+ } }
25
+ });
26
+ const projectId = c.req.header("x-inkeep-project-id");
27
+ if (!projectId) throw createApiError({
28
+ code: "unauthorized",
29
+ message: "Missing required header: x-inkeep-project-id",
30
+ extensions: { parameter: {
31
+ in: "header",
32
+ name: "x-inkeep-project-id"
33
+ } }
34
+ });
35
+ const authHeader = c.req.header("Authorization");
36
+ if (!authHeader) throw createApiError({
37
+ code: "unauthorized",
38
+ message: "Missing required header: Authorization",
39
+ extensions: { parameter: {
40
+ in: "header",
41
+ name: "Authorization"
42
+ } }
43
+ });
44
+ const apiKey = authHeader.startsWith("Bearer ") ? authHeader.substring(7) : void 0;
45
+ if (!apiKey) throw createApiError({
46
+ code: "unauthorized",
47
+ message: "Invalid Authorization header format. Expected: Bearer <token>",
48
+ extensions: { parameter: {
49
+ in: "header",
50
+ name: "Authorization"
51
+ } }
52
+ });
53
+ if (!env.SLACK_MCP_API_KEY) throw createApiError({
54
+ code: "internal_server_error",
55
+ message: "Slack MCP API key not configured"
56
+ });
57
+ const expectedKey = Buffer.from(env.SLACK_MCP_API_KEY);
58
+ const providedKey = Buffer.from(apiKey);
59
+ if (expectedKey.length !== providedKey.length || !timingSafeEqual(expectedKey, providedKey)) throw createApiError({
60
+ code: "unauthorized",
61
+ message: "Invalid API key"
62
+ });
63
+ c.set("toolId", toolId);
64
+ c.set("tenantId", tenantId);
65
+ c.set("projectId", projectId);
66
+ await next();
67
+ });
68
+
69
+ //#endregion
70
+ export { slackMcpAuth };
@@ -0,0 +1,23 @@
1
+ import { Hono } from "hono";
2
+ import * as hono_types8 from "hono/types";
3
+
4
+ //#region src/slack/mcp/index.d.ts
5
+ interface ChannelInfo {
6
+ id: string;
7
+ name: string;
8
+ }
9
+ type ToolScope = {
10
+ tenantId: string;
11
+ projectId: string;
12
+ toolId: string;
13
+ };
14
+ declare function pruneStaleChannelIds(scope: ToolScope, availableChannels: ChannelInfo[], currentChannelIds: string[]): string[];
15
+ declare const app: Hono<{
16
+ Variables: {
17
+ toolId: string;
18
+ tenantId: string;
19
+ projectId: string;
20
+ };
21
+ }, hono_types8.BlankSchema, "/">;
22
+ //#endregion
23
+ export { ChannelInfo, app as default, pruneStaleChannelIds };
@@ -0,0 +1,220 @@
1
+ import { getLogger } from "../../logger.js";
2
+ import runDbClient_default from "../../db/runDbClient.js";
3
+ import { getBotMemberChannels, getSlackClient, openDmConversation, postMessage, postMessageInThread } from "../services/client.js";
4
+ import { slackMcpAuth } from "./auth.js";
5
+ import { resolveChannelId, resolveWorkspaceToken, validateChannelAccess } from "./utils.js";
6
+ import { z } from "@hono/zod-openapi";
7
+ import { getSlackMcpToolAccessConfig, updateSlackMcpToolAccessChannelIds } from "@inkeep/agents-core";
8
+ import { Hono } from "hono";
9
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
10
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
11
+ import { toFetchResponse, toReqRes } from "fetch-to-node";
12
+
13
+ //#region src/slack/mcp/index.ts
14
+ const logger = getLogger("slack-mcp");
15
+ async function getAvailableChannels(client, config) {
16
+ try {
17
+ const botChannels = await getBotMemberChannels(client);
18
+ if (config.channelAccessMode === "all") return botChannels.filter((ch) => !!ch.id && !!ch.name).map((ch) => ({
19
+ id: ch.id,
20
+ name: ch.name
21
+ }));
22
+ const allowedIds = new Set(config.channelIds);
23
+ return botChannels.filter((ch) => !!ch.id && !!ch.name && allowedIds.has(ch.id)).map((ch) => ({
24
+ id: ch.id,
25
+ name: ch.name
26
+ }));
27
+ } catch (error) {
28
+ logger.warn({ error }, "Failed to fetch available channels for tool description");
29
+ return [];
30
+ }
31
+ }
32
+ function getAvailableChannelsString(channels) {
33
+ if (channels.length === 0) return "No channels available";
34
+ return `Available channels: ${channels.map((ch) => `#${ch.name} (${ch.id})`).join(", ")}`;
35
+ }
36
+ function pruneStaleChannelIds(scope, availableChannels, currentChannelIds) {
37
+ const availableIds = new Set(availableChannels.map((ch) => ch.id));
38
+ const staleIds = currentChannelIds.filter((id) => !availableIds.has(id));
39
+ if (staleIds.length > 0) {
40
+ const prunedIds = currentChannelIds.filter((id) => availableIds.has(id));
41
+ logger.info({
42
+ toolId: scope.toolId,
43
+ staleIds,
44
+ prunedIds
45
+ }, "Pruning stale channel IDs from MCP access config");
46
+ updateSlackMcpToolAccessChannelIds(runDbClient_default)(scope, prunedIds).catch((error) => {
47
+ logger.warn({
48
+ error,
49
+ toolId: scope.toolId
50
+ }, "Failed to prune stale channel IDs");
51
+ });
52
+ }
53
+ return currentChannelIds;
54
+ }
55
+ const getServer = async (scope) => {
56
+ const botToken = await resolveWorkspaceToken(scope.tenantId);
57
+ const config = await getSlackMcpToolAccessConfig(runDbClient_default)(scope);
58
+ const client = getSlackClient(botToken);
59
+ const availableChannels = await getAvailableChannels(client, config);
60
+ if (config.channelAccessMode === "selected") pruneStaleChannelIds(scope, availableChannels, config.channelIds);
61
+ const server = new McpServer({
62
+ name: "inkeep-slack-mcp-server",
63
+ version: "1.0.0",
64
+ description: "A Slack MCP server for posting messages to channels" + (config.dmEnabled ? " and sending direct messages to users" : "") + ".\n" + availableChannels.map((ch) => `• #${ch.name} (${ch.id})`).join("\n")
65
+ }, { capabilities: { logging: {} } });
66
+ server.tool("post-channel-message", `Post a message to a Slack channel. Supports mrkdwn formatting and thread replies. ${getAvailableChannelsString(availableChannels)}`, {
67
+ channel: z.string().describe("Channel ID (e.g., C1234567890) or channel name prefixed with # (e.g., #general)."),
68
+ text: z.string().describe("Message text. Supports Slack mrkdwn formatting."),
69
+ thread_ts: z.string().optional().describe("Thread timestamp to reply in a thread. If omitted, posts as a new message.")
70
+ }, async ({ channel, text, thread_ts }) => {
71
+ try {
72
+ const channelId = await resolveChannelId(client, channel);
73
+ const accessCheck = validateChannelAccess(channelId, config);
74
+ if (!accessCheck.allowed) return {
75
+ content: [{
76
+ type: "text",
77
+ text: `Error: ${accessCheck.reason}`
78
+ }],
79
+ isError: true
80
+ };
81
+ const result = thread_ts ? await postMessageInThread(client, channelId, thread_ts, text) : await postMessage(client, channelId, text);
82
+ return { content: [{
83
+ type: "text",
84
+ text: JSON.stringify({
85
+ ok: result.ok,
86
+ ts: result.ts,
87
+ channel: result.channel
88
+ })
89
+ }] };
90
+ } catch (error) {
91
+ const message = error instanceof Error ? error.message : "Unknown error";
92
+ logger.error({
93
+ error,
94
+ toolId: scope.toolId,
95
+ channel
96
+ }, "Failed to post Slack message via MCP");
97
+ return {
98
+ content: [{
99
+ type: "text",
100
+ text: `Error posting message: ${message}`
101
+ }],
102
+ isError: true
103
+ };
104
+ }
105
+ });
106
+ if (config.dmEnabled) server.tool("post-direct-message", "Send a direct message to a Slack user. Opens or continues an existing DM conversation with the user.", {
107
+ user_id: z.string().describe("The Slack user ID to DM (e.g., U1234567890)."),
108
+ text: z.string().describe("Message text. Supports Slack mrkdwn formatting."),
109
+ thread_ts: z.string().optional().describe("Thread timestamp to reply in a thread. If omitted, posts as a new message.")
110
+ }, async ({ user_id, text, thread_ts }) => {
111
+ try {
112
+ const dmChannelId = await openDmConversation(client, user_id);
113
+ const result = thread_ts ? await postMessageInThread(client, dmChannelId, thread_ts, text) : await postMessage(client, dmChannelId, text);
114
+ return { content: [{
115
+ type: "text",
116
+ text: JSON.stringify({
117
+ ok: result.ok,
118
+ ts: result.ts,
119
+ channel: result.channel,
120
+ user_id
121
+ })
122
+ }] };
123
+ } catch (error) {
124
+ const message = error instanceof Error ? error.message : "Unknown error";
125
+ logger.error({
126
+ error,
127
+ toolId: scope.toolId,
128
+ user_id
129
+ }, "Failed to send Slack DM via MCP");
130
+ return {
131
+ content: [{
132
+ type: "text",
133
+ text: `Error sending DM: ${message}`
134
+ }],
135
+ isError: true
136
+ };
137
+ }
138
+ });
139
+ return server;
140
+ };
141
+ const app = new Hono();
142
+ app.onError((err, c) => {
143
+ const message = err.message || "Internal server error";
144
+ logger.error({ error: err }, "Slack MCP error");
145
+ return c.json({
146
+ jsonrpc: "2.0",
147
+ error: {
148
+ code: -32603,
149
+ message
150
+ },
151
+ id: null
152
+ }, 500);
153
+ });
154
+ app.use("/", slackMcpAuth());
155
+ app.post("/", async (c) => {
156
+ const toolId = c.get("toolId");
157
+ const tenantId = c.get("tenantId");
158
+ const projectId = c.get("projectId");
159
+ let server;
160
+ try {
161
+ const body = await c.req.json();
162
+ server = await getServer({
163
+ tenantId,
164
+ projectId,
165
+ toolId
166
+ });
167
+ const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: void 0 });
168
+ await server.connect(transport);
169
+ const { req, res } = toReqRes(c.req.raw);
170
+ await transport.handleRequest(req, res, body);
171
+ return toFetchResponse(res);
172
+ } catch (error) {
173
+ const message = error instanceof Error ? error.message : "Unknown error";
174
+ logger.error({
175
+ error,
176
+ toolId
177
+ }, "MCP request failed");
178
+ return c.json({
179
+ jsonrpc: "2.0",
180
+ error: {
181
+ code: -32603,
182
+ message
183
+ },
184
+ id: null
185
+ }, 500);
186
+ } finally {
187
+ if (server) await server.close().catch((e) => logger.warn({ error: e }, "Failed to close MCP server"));
188
+ }
189
+ });
190
+ app.delete("/", async (c) => {
191
+ return c.json({
192
+ jsonrpc: "2.0",
193
+ error: {
194
+ code: -32001,
195
+ message: "Method Not Allowed"
196
+ },
197
+ id: null
198
+ }, { status: 405 });
199
+ });
200
+ app.get("/", async (c) => {
201
+ return c.json({
202
+ jsonrpc: "2.0",
203
+ error: {
204
+ code: -32e3,
205
+ message: "Method not allowed."
206
+ },
207
+ id: null
208
+ }, { status: 405 });
209
+ });
210
+ app.get("/health", async (c) => {
211
+ return c.json({
212
+ status: "healthy",
213
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
214
+ service: "Slack MCP Server"
215
+ });
216
+ });
217
+ var mcp_default = app;
218
+
219
+ //#endregion
220
+ export { mcp_default as default, pruneStaleChannelIds };
@@ -0,0 +1,12 @@
1
+ import { SlackMcpToolAccessConfig } from "@inkeep/agents-core";
2
+ import { WebClient } from "@slack/web-api";
3
+
4
+ //#region src/slack/mcp/utils.d.ts
5
+ declare function resolveChannelId(client: WebClient, channelInput: string): Promise<string>;
6
+ declare function resolveWorkspaceToken(tenantId: string): Promise<string>;
7
+ declare function validateChannelAccess(channelId: string, config: SlackMcpToolAccessConfig): {
8
+ allowed: boolean;
9
+ reason?: string;
10
+ };
11
+ //#endregion
12
+ export { resolveChannelId, resolveWorkspaceToken, validateChannelAccess };
@@ -0,0 +1,58 @@
1
+ import runDbClient_default from "../../db/runDbClient.js";
2
+ import { isSlackDevMode, loadSlackDevConfig } from "../services/dev-config.js";
3
+ import { getConnectionAccessToken } from "../services/nango.js";
4
+ import { listWorkAppSlackWorkspacesByTenant } from "@inkeep/agents-core";
5
+
6
+ //#region src/slack/mcp/utils.ts
7
+ const MAX_PAGES = 10;
8
+ async function resolveChannelId(client, channelInput) {
9
+ if (!channelInput.startsWith("#")) return channelInput;
10
+ const channelName = channelInput.slice(1);
11
+ let cursor;
12
+ let pageCount = 0;
13
+ do {
14
+ if (pageCount >= MAX_PAGES) throw new Error(`Channel not found within first ${MAX_PAGES * 200} channels: ${channelInput}`);
15
+ const result = await client.conversations.list({
16
+ types: "public_channel,private_channel",
17
+ exclude_archived: true,
18
+ limit: 200,
19
+ cursor
20
+ });
21
+ const match = result.channels?.find((ch) => ch.name === channelName);
22
+ if (match?.id) return match.id;
23
+ cursor = result.response_metadata?.next_cursor || void 0;
24
+ pageCount++;
25
+ } while (cursor);
26
+ throw new Error(`Channel not found: ${channelInput}`);
27
+ }
28
+ async function resolveWorkspaceToken(tenantId) {
29
+ if (isSlackDevMode()) {
30
+ const devConfig = loadSlackDevConfig();
31
+ if (devConfig?.botToken) return devConfig.botToken;
32
+ throw new Error("Slack dev mode enabled but no botToken found in .slack-dev.json");
33
+ }
34
+ const workspaces = await listWorkAppSlackWorkspacesByTenant(runDbClient_default)(tenantId);
35
+ if (workspaces.length === 0) throw new Error(`No Slack workspace installed for tenant ${tenantId}`);
36
+ const workspace = workspaces[0];
37
+ const botToken = await getConnectionAccessToken(workspace.nangoConnectionId);
38
+ if (!botToken) throw new Error(`Failed to retrieve bot token for workspace ${workspace.slackTeamId}`);
39
+ return botToken;
40
+ }
41
+ function validateChannelAccess(channelId, config) {
42
+ if (channelId.startsWith("D")) {
43
+ if (!config.dmEnabled) return {
44
+ allowed: false,
45
+ reason: "DM access is not enabled for this tool"
46
+ };
47
+ return { allowed: true };
48
+ }
49
+ if (config.channelAccessMode === "all") return { allowed: true };
50
+ if (config.channelIds.includes(channelId)) return { allowed: true };
51
+ return {
52
+ allowed: false,
53
+ reason: "Channel not in allowed list"
54
+ };
55
+ }
56
+
57
+ //#endregion
58
+ export { resolveChannelId, resolveWorkspaceToken, validateChannelAccess };
@@ -1,5 +1,5 @@
1
1
  import { ManageAppVariables } from "../types.js";
2
- import * as hono0 from "hono";
2
+ import * as hono1 from "hono";
3
3
 
4
4
  //#region src/slack/middleware/permissions.d.ts
5
5
  /**
@@ -14,7 +14,7 @@ declare const requireWorkspaceAdmin: <Env extends {
14
14
  Variables: ManageAppVariables;
15
15
  } = {
16
16
  Variables: ManageAppVariables;
17
- }>() => hono0.MiddlewareHandler<Env, string, {}, Response>;
17
+ }>() => hono1.MiddlewareHandler<Env, string, {}, Response>;
18
18
  /**
19
19
  * Middleware that requires either:
20
20
  * 1. Org admin/owner role (can modify any channel), OR
@@ -26,6 +26,6 @@ declare const requireChannelMemberOrAdmin: <Env extends {
26
26
  Variables: ManageAppVariables;
27
27
  } = {
28
28
  Variables: ManageAppVariables;
29
- }>() => hono0.MiddlewareHandler<Env, string, {}, Response>;
29
+ }>() => hono1.MiddlewareHandler<Env, string, {}, Response>;
30
30
  //#endregion
31
31
  export { isOrgAdmin, requireChannelMemberOrAdmin, requireWorkspaceAdmin };
@@ -6,7 +6,7 @@ import { getBotMemberChannels, getSlackChannels, getSlackClient, revokeSlackToke
6
6
  import "../services/index.js";
7
7
  import { requireChannelMemberOrAdmin, requireWorkspaceAdmin } from "../middleware/permissions.js";
8
8
  import { OpenAPIHono, z } from "@hono/zod-openapi";
9
- import { WorkAppSlackAgentConfigRequestSchema, deleteAllWorkAppSlackChannelAgentConfigsByTeam, deleteAllWorkAppSlackUserMappingsByTeam, deleteWorkAppSlackChannelAgentConfig, deleteWorkAppSlackWorkspaceByNangoConnectionId, findWorkAppSlackChannelAgentConfig, findWorkAppSlackWorkspaceByTeamId, listWorkAppSlackChannelAgentConfigsByTeam, listWorkAppSlackUserMappingsByTeam, updateWorkAppSlackWorkspace, upsertWorkAppSlackChannelAgentConfig } from "@inkeep/agents-core";
9
+ import { WorkAppSlackAgentConfigRequestSchema, deleteAllSlackMcpToolAccessConfigsByTenant, deleteAllWorkAppSlackChannelAgentConfigsByTeam, deleteAllWorkAppSlackUserMappingsByTeam, deleteWorkAppSlackChannelAgentConfig, deleteWorkAppSlackWorkspaceByNangoConnectionId, findWorkAppSlackChannelAgentConfig, findWorkAppSlackWorkspaceByTeamId, listWorkAppSlackChannelAgentConfigsByTeam, listWorkAppSlackUserMappingsByTeam, updateWorkAppSlackWorkspace, upsertWorkAppSlackChannelAgentConfig } from "@inkeep/agents-core";
10
10
  import { createProtectedRoute, inheritedWorkAppsAuth } from "@inkeep/agents-core/middleware";
11
11
 
12
12
  //#region src/slack/routes/workspaces.ts
@@ -376,6 +376,11 @@ app.openapi(createProtectedRoute({
376
376
  teamId,
377
377
  deletedMappings
378
378
  }, "Deleted user mappings for uninstalled workspace");
379
+ const deletedMcpConfigs = await deleteAllSlackMcpToolAccessConfigsByTenant(runDbClient_default)(tenantId);
380
+ if (deletedMcpConfigs > 0) logger.info({
381
+ teamId,
382
+ deletedMcpConfigs
383
+ }, "Deleted MCP tool access configs for uninstalled workspace");
379
384
  if (await deleteWorkAppSlackWorkspaceByNangoConnectionId(runDbClient_default)(connectionId)) logger.info({ connectionId }, "Deleted workspace from database");
380
385
  if (!await deleteWorkspaceInstallation(connectionId)) logger.error({ connectionId }, "deleteWorkspaceInstallation returned false (DB already cleaned up)");
381
386
  clearWorkspaceConnectionCache(teamId);
@@ -132,6 +132,25 @@ declare function postMessageInThread(client: WebClient, channel: string, threadT
132
132
  * @returns true if user is a member, false otherwise
133
133
  */
134
134
  declare function checkUserIsChannelMember(client: WebClient, channelId: string, userId: string): Promise<boolean>;
135
+ /**
136
+ * Open (or resume) a direct message conversation with a Slack user.
137
+ *
138
+ * @param client - Authenticated Slack WebClient
139
+ * @param userId - Slack user ID to DM (e.g., U0ABC123)
140
+ * @returns The DM channel ID
141
+ */
142
+ declare function openDmConversation(client: WebClient, userId: string): Promise<string>;
143
+ /**
144
+ * Validate that the bot is a member of the given channels.
145
+ *
146
+ * @param client - Authenticated Slack WebClient
147
+ * @param channelIds - Channel IDs to validate
148
+ * @returns Object with valid and invalid channel ID arrays
149
+ */
150
+ declare function validateBotChannelMembership(client: WebClient, channelIds: string[]): Promise<{
151
+ valid: string[];
152
+ invalid: string[];
153
+ }>;
135
154
  /**
136
155
  * Revoke a Slack bot token.
137
156
  *
@@ -143,4 +162,4 @@ declare function checkUserIsChannelMember(client: WebClient, channelId: string,
143
162
  */
144
163
  declare function revokeSlackToken(token: string): Promise<boolean>;
145
164
  //#endregion
146
- export { checkUserIsChannelMember, getBotMemberChannels, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackTeamInfo, getSlackUserInfo, postMessage, postMessageInThread, revokeSlackToken };
165
+ export { checkUserIsChannelMember, getBotMemberChannels, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackTeamInfo, getSlackUserInfo, openDmConversation, postMessage, postMessageInThread, revokeSlackToken, validateBotChannelMembership };
@@ -272,6 +272,37 @@ async function checkUserIsChannelMember(client, channelId, userId) {
272
272
  })).includes(userId);
273
273
  }
274
274
  /**
275
+ * Open (or resume) a direct message conversation with a Slack user.
276
+ *
277
+ * @param client - Authenticated Slack WebClient
278
+ * @param userId - Slack user ID to DM (e.g., U0ABC123)
279
+ * @returns The DM channel ID
280
+ */
281
+ async function openDmConversation(client, userId) {
282
+ const channelId = (await client.conversations.open({ users: userId })).channel?.id;
283
+ if (!channelId) throw new Error(`Failed to open DM conversation with user ${userId}`);
284
+ return channelId;
285
+ }
286
+ /**
287
+ * Validate that the bot is a member of the given channels.
288
+ *
289
+ * @param client - Authenticated Slack WebClient
290
+ * @param channelIds - Channel IDs to validate
291
+ * @returns Object with valid and invalid channel ID arrays
292
+ */
293
+ async function validateBotChannelMembership(client, channelIds) {
294
+ const botChannels = await getBotMemberChannels(client);
295
+ const memberChannelIds = new Set(botChannels.filter((ch) => !!ch.id).map((ch) => ch.id));
296
+ const valid = [];
297
+ const invalid = [];
298
+ for (const id of channelIds) if (memberChannelIds.has(id)) valid.push(id);
299
+ else invalid.push(id);
300
+ return {
301
+ valid,
302
+ invalid
303
+ };
304
+ }
305
+ /**
275
306
  * Revoke a Slack bot token.
276
307
  *
277
308
  * This should be called when uninstalling a workspace to ensure
@@ -301,4 +332,4 @@ async function revokeSlackToken(token) {
301
332
  }
302
333
 
303
334
  //#endregion
304
- export { checkUserIsChannelMember, getBotMemberChannels, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackTeamInfo, getSlackUserInfo, postMessage, postMessageInThread, revokeSlackToken };
335
+ export { checkUserIsChannelMember, getBotMemberChannels, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackTeamInfo, getSlackUserInfo, openDmConversation, postMessage, postMessageInThread, revokeSlackToken, validateBotChannelMembership };
@@ -74,7 +74,7 @@ function saveSlackDevConfig(config) {
74
74
  const configPath = getDevConfigPath();
75
75
  if (!configPath) return false;
76
76
  try {
77
- writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
77
+ writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`, "utf-8");
78
78
  cachedConfig = config;
79
79
  cacheExpiresAt = Date.now() + CACHE_TTL_MS;
80
80
  return true;
@@ -9,12 +9,12 @@ import { AgentOption } from "../modals.js";
9
9
  * Called on every @mention and /inkeep command — caching avoids redundant DB queries.
10
10
  */
11
11
  declare function findCachedUserMapping(tenantId: string, slackUserId: string, teamId: string, clientId?: string): Promise<{
12
- slackUserId: string;
13
12
  id: string;
14
13
  createdAt: string;
15
14
  updatedAt: string;
16
15
  tenantId: string;
17
16
  clientId: string;
17
+ slackUserId: string;
18
18
  slackTeamId: string;
19
19
  slackEnterpriseId: string | null;
20
20
  inkeepUserId: string;
@@ -1,6 +1,6 @@
1
1
  import { AgentResolutionParams, ResolvedAgentConfig, getAgentConfigSources, lookupAgentName, lookupProjectName, resolveEffectiveAgent } from "./agent-resolution.js";
2
2
  import { AgentConfigSources, ContextBlockParams, ToolApprovalButtonValue, ToolApprovalButtonValueSchema, buildCitationsBlock, buildDataArtifactBlocks, buildDataComponentBlocks, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, createAlreadyLinkedMessage, createContextBlock, createContextBlockFromText, createCreateInkeepAccountMessage, createErrorMessage, createNotLinkedMessage, createSmartLinkMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage } from "./blocks/index.js";
3
- import { checkUserIsChannelMember, getBotMemberChannels, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackTeamInfo, getSlackUserInfo, postMessage, postMessageInThread, revokeSlackToken } from "./client.js";
3
+ import { checkUserIsChannelMember, getBotMemberChannels, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackTeamInfo, getSlackUserInfo, openDmConversation, postMessage, postMessageInThread, revokeSlackToken, validateBotChannelMembership } from "./client.js";
4
4
  import { DefaultAgentConfig, SlackWorkspaceConnection, WorkspaceInstallData, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createConnectSession, deleteWorkspaceInstallation, findWorkspaceConnectionByTeamId, getConnectionAccessToken, getSlackIntegrationId, getSlackNango, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, listWorkspaceInstallations, setWorkspaceDefaultAgent, storeWorkspaceInstallation, updateConnectionMetadata } from "./nango.js";
5
5
  import { SlackCommandPayload, SlackCommandResponse } from "./types.js";
6
6
  import { handleAgentPickerCommand, handleCommand, handleHelpCommand, handleLinkCommand, handleQuestionCommand, handleStatusCommand, handleUnlinkCommand } from "./commands/index.js";
@@ -15,4 +15,4 @@ import { handleModalSubmission } from "./events/modal-submission.js";
15
15
  import "./events/index.js";
16
16
  import { parseSlackCommandBody, parseSlackEventBody, verifySlackRequest } from "./security.js";
17
17
  import { getBotTokenForTeam, setBotTokenForTeam } from "./workspace-tokens.js";
18
- export { AgentConfigSources, AgentOption, AgentResolutionParams, BuildAgentSelectorModalParams, BuildMessageShortcutModalParams, ContextBlockParams, DefaultAgentConfig, InlineSelectorMetadata, ModalMetadata, PublicExecutionParams, ResolvedAgentConfig, SlackCommandPayload, SlackCommandResponse, SlackErrorType, SlackWorkspaceConnection, StreamResult, ToolApprovalButtonValue, ToolApprovalButtonValueSchema, WorkspaceInstallData, buildAgentSelectorModal, buildCitationsBlock, buildDataArtifactBlocks, buildDataComponentBlocks, buildMessageShortcutModal, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, checkIfBotThread, checkUserIsChannelMember, classifyError, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createAlreadyLinkedMessage, createConnectSession, createContextBlock, createContextBlockFromText, createCreateInkeepAccountMessage, createErrorMessage, createNotLinkedMessage, createSmartLinkMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage, deleteWorkspaceInstallation, executeAgentPublicly, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, findWorkspaceConnectionByTeamId, generateSlackConversationId, getAgentConfigSources, getBotMemberChannels, getBotTokenForTeam, getChannelAgentConfig, getConnectionAccessToken, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackIntegrationId, getSlackNango, getSlackTeamInfo, getSlackUserInfo, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, handleAgentPickerCommand, handleAppMention, handleCommand, handleDirectMessage, handleHelpCommand, handleLinkCommand, handleMessageShortcut, handleModalSubmission, handleOpenAgentSelectorModal, handleQuestionCommand, handleStatusCommand, handleToolApproval, handleUnlinkCommand, listWorkspaceInstallations, lookupAgentName, lookupProjectName, markdownToMrkdwn, parseSlackCommandBody, parseSlackEventBody, postMessage, postMessageInThread, resolveEffectiveAgent, revokeSlackToken, sendResponseUrlMessage, setBotTokenForTeam, setWorkspaceDefaultAgent, storeWorkspaceInstallation, streamAgentResponse, updateConnectionMetadata, verifySlackRequest };
18
+ export { AgentConfigSources, AgentOption, AgentResolutionParams, BuildAgentSelectorModalParams, BuildMessageShortcutModalParams, ContextBlockParams, DefaultAgentConfig, InlineSelectorMetadata, ModalMetadata, PublicExecutionParams, ResolvedAgentConfig, SlackCommandPayload, SlackCommandResponse, SlackErrorType, SlackWorkspaceConnection, StreamResult, ToolApprovalButtonValue, ToolApprovalButtonValueSchema, WorkspaceInstallData, buildAgentSelectorModal, buildCitationsBlock, buildDataArtifactBlocks, buildDataComponentBlocks, buildMessageShortcutModal, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, checkIfBotThread, checkUserIsChannelMember, classifyError, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createAlreadyLinkedMessage, createConnectSession, createContextBlock, createContextBlockFromText, createCreateInkeepAccountMessage, createErrorMessage, createNotLinkedMessage, createSmartLinkMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage, deleteWorkspaceInstallation, executeAgentPublicly, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, findWorkspaceConnectionByTeamId, generateSlackConversationId, getAgentConfigSources, getBotMemberChannels, getBotTokenForTeam, getChannelAgentConfig, getConnectionAccessToken, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackIntegrationId, getSlackNango, getSlackTeamInfo, getSlackUserInfo, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, handleAgentPickerCommand, handleAppMention, handleCommand, handleDirectMessage, handleHelpCommand, handleLinkCommand, handleMessageShortcut, handleModalSubmission, handleOpenAgentSelectorModal, handleQuestionCommand, handleStatusCommand, handleToolApproval, handleUnlinkCommand, listWorkspaceInstallations, lookupAgentName, lookupProjectName, markdownToMrkdwn, openDmConversation, parseSlackCommandBody, parseSlackEventBody, postMessage, postMessageInThread, resolveEffectiveAgent, revokeSlackToken, sendResponseUrlMessage, setBotTokenForTeam, setWorkspaceDefaultAgent, storeWorkspaceInstallation, streamAgentResponse, updateConnectionMetadata, validateBotChannelMembership, verifySlackRequest };
@@ -2,7 +2,7 @@ import { clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createConn
2
2
  import { SlackErrorType, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, markdownToMrkdwn, sendResponseUrlMessage } from "./events/utils.js";
3
3
  import { getAgentConfigSources, lookupAgentName, lookupProjectName, resolveEffectiveAgent } from "./agent-resolution.js";
4
4
  import { ToolApprovalButtonValueSchema, buildCitationsBlock, buildDataArtifactBlocks, buildDataComponentBlocks, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, createAlreadyLinkedMessage, createContextBlock, createContextBlockFromText, createCreateInkeepAccountMessage, createErrorMessage, createNotLinkedMessage, createSmartLinkMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage } from "./blocks/index.js";
5
- import { checkUserIsChannelMember, getBotMemberChannels, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackTeamInfo, getSlackUserInfo, postMessage, postMessageInThread, revokeSlackToken } from "./client.js";
5
+ import { checkUserIsChannelMember, getBotMemberChannels, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackTeamInfo, getSlackUserInfo, openDmConversation, postMessage, postMessageInThread, revokeSlackToken, validateBotChannelMembership } from "./client.js";
6
6
  import { streamAgentResponse } from "./events/streaming.js";
7
7
  import { executeAgentPublicly } from "./events/execution.js";
8
8
  import { buildAgentSelectorModal, buildMessageShortcutModal } from "./modals.js";
@@ -15,4 +15,4 @@ import "./events/index.js";
15
15
  import { parseSlackCommandBody, parseSlackEventBody, verifySlackRequest } from "./security.js";
16
16
  import { getBotTokenForTeam, setBotTokenForTeam } from "./workspace-tokens.js";
17
17
 
18
- export { SlackErrorType, ToolApprovalButtonValueSchema, buildAgentSelectorModal, buildCitationsBlock, buildDataArtifactBlocks, buildDataComponentBlocks, buildMessageShortcutModal, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, checkIfBotThread, checkUserIsChannelMember, classifyError, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createAlreadyLinkedMessage, createConnectSession, createContextBlock, createContextBlockFromText, createCreateInkeepAccountMessage, createErrorMessage, createNotLinkedMessage, createSmartLinkMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage, deleteWorkspaceInstallation, executeAgentPublicly, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, findWorkspaceConnectionByTeamId, generateSlackConversationId, getAgentConfigSources, getBotMemberChannels, getBotTokenForTeam, getChannelAgentConfig, getConnectionAccessToken, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackIntegrationId, getSlackNango, getSlackTeamInfo, getSlackUserInfo, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, handleAgentPickerCommand, handleAppMention, handleCommand, handleDirectMessage, handleHelpCommand, handleLinkCommand, handleMessageShortcut, handleModalSubmission, handleOpenAgentSelectorModal, handleQuestionCommand, handleStatusCommand, handleToolApproval, handleUnlinkCommand, listWorkspaceInstallations, lookupAgentName, lookupProjectName, markdownToMrkdwn, parseSlackCommandBody, parseSlackEventBody, postMessage, postMessageInThread, resolveEffectiveAgent, revokeSlackToken, sendResponseUrlMessage, setBotTokenForTeam, setWorkspaceDefaultAgent, storeWorkspaceInstallation, streamAgentResponse, updateConnectionMetadata, verifySlackRequest };
18
+ export { SlackErrorType, ToolApprovalButtonValueSchema, buildAgentSelectorModal, buildCitationsBlock, buildDataArtifactBlocks, buildDataComponentBlocks, buildMessageShortcutModal, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, checkIfBotThread, checkUserIsChannelMember, classifyError, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createAlreadyLinkedMessage, createConnectSession, createContextBlock, createContextBlockFromText, createCreateInkeepAccountMessage, createErrorMessage, createNotLinkedMessage, createSmartLinkMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage, deleteWorkspaceInstallation, executeAgentPublicly, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, findWorkspaceConnectionByTeamId, generateSlackConversationId, getAgentConfigSources, getBotMemberChannels, getBotTokenForTeam, getChannelAgentConfig, getConnectionAccessToken, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackIntegrationId, getSlackNango, getSlackTeamInfo, getSlackUserInfo, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, handleAgentPickerCommand, handleAppMention, handleCommand, handleDirectMessage, handleHelpCommand, handleLinkCommand, handleMessageShortcut, handleModalSubmission, handleOpenAgentSelectorModal, handleQuestionCommand, handleStatusCommand, handleToolApproval, handleUnlinkCommand, listWorkspaceInstallations, lookupAgentName, lookupProjectName, markdownToMrkdwn, openDmConversation, parseSlackCommandBody, parseSlackEventBody, postMessage, postMessageInThread, resolveEffectiveAgent, revokeSlackToken, sendResponseUrlMessage, setBotTokenForTeam, setWorkspaceDefaultAgent, storeWorkspaceInstallation, streamAgentResponse, updateConnectionMetadata, validateBotChannelMembership, verifySlackRequest };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inkeep/agents-work-apps",
3
- "version": "0.58.1",
3
+ "version": "0.58.3",
4
4
  "description": "First party integrations for Inkeep Agents",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -33,7 +33,7 @@
33
33
  "jose": "^6.1.0",
34
34
  "minimatch": "^10.2.1",
35
35
  "slack-block-builder": "^2.8.0",
36
- "@inkeep/agents-core": "0.58.1"
36
+ "@inkeep/agents-core": "0.58.3"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@hono/zod-openapi": "^1.1.5",