Skip to main content
Glama

send_message_to_session

Send a message to an active Devin session and optionally post it to a linked Slack thread or channel. Maintains context between Devin and Slack for streamlined communication and task management.

Instructions

Send a message to an existing Devin session and optionally to the associated Slack thread

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
messageYesMessage to send to Devin
session_idYesThe ID of the Devin session
slack_channelNoOptional Slack channel ID to post to
slack_thread_tsNoOptional Slack thread timestamp to reply to

Implementation Reference

  • The handler case for 'send_message_to_session' that validates inputs, sends the message to the Devin API endpoint `/session/{normalized_session_id}/message`, optionally forwards to Slack, and returns success/error responses.
    case "send_message_to_session": {
      const session_id = String(request.params.arguments?.session_id);
      const message = String(request.params.arguments?.message);
      const slack_channel = request.params.arguments?.slack_channel as string | undefined;
      const slack_thread_ts = request.params.arguments?.slack_thread_ts as string | undefined;
    
      if (!session_id) {
        return {
          content: [{
            type: "text",
            text: "Error: session_id is required"
          }],
          isError: true
        };
      }
    
      if (!message) {
        return {
          content: [{
            type: "text",
            text: "Error: message is required"
          }],
          isError: true
        };
      }
    
      try {
        // Send message to Devin API
        // Devin APIへメッセージ送信
        const response = await axios.post(
          `${BASE_URL}/session/${normalizeSessionId(session_id)}/message`,
          { message },
          { headers: getHeaders() }
        );
        
        // APIレスポンスの詳細なチェック
        // HTTP 200系のステータスが返ってきたら基本的に成功とみなす
        // 空のオブジェクトが返る場合も成功と判断する
        const isSuccess = response.status >= 200 && response.status < 300;
        
        let slackResponse = null;
        // Slackスレッド情報が提供されていれば、Slackにも送信
        if (isSuccess && slack_channel && slack_thread_ts) {
          slackResponse = await sendSlackMessage(slack_channel, message, slack_thread_ts);
        }
    
        if (isSuccess) {
          return {
            content: [{
              type: "text",
              text: JSON.stringify({
                status: "Message sent successfully",
                success: true,
                response_data: response.data || {},
                slack_response: slackResponse ? {
                  channel: slack_channel,
                  thread_ts: slack_thread_ts,
                  message_ts: slackResponse.ts
                } : null
              }, null, 2)
            }]
          };
        } else {
          // APIレスポンスが成功しなかった場合
          return {
            content: [{
              type: "text",
              text: JSON.stringify({
                status: "Message sending failed",
                success: false,
                http_status: response.status,
                response_data: response.data || {}
              }, null, 2)
            }],
            isError: true
          };
        }
      } catch (error) {
        if (axios.isAxiosError(error)) {
          return {
            content: [{
              type: "text",
              text: `Error sending message: ${error.response?.status} - ${JSON.stringify(error.response?.data)}`
            }],
            isError: true
          };
        }
        
        return {
          content: [{
            type: "text",
            text: `Unexpected error: ${error}`
          }],
          isError: true
        };
      }
    }
  • Input schema defining the parameters for the send_message_to_session tool.
    inputSchema: {
      type: "object",
      properties: {
        session_id: {
          type: "string",
          description: "The ID of the Devin session"
        },
        message: {
          type: "string",
          description: "Message to send to Devin"
        },
        slack_channel: {
          type: "string",
          description: "Optional Slack channel ID to post to"
        },
        slack_thread_ts: {
          type: "string",
          description: "Optional Slack thread timestamp to reply to"
        }
      },
      required: ["session_id", "message"]
    }
  • src/index.ts:189-214 (registration)
    Tool registration in the ListToolsRequestSchema handler, including name, description, and input schema.
    {
      name: "send_message_to_session",
      description: "Send a message to an existing Devin session and optionally to the associated Slack thread",
      inputSchema: {
        type: "object",
        properties: {
          session_id: {
            type: "string",
            description: "The ID of the Devin session"
          },
          message: {
            type: "string",
            description: "Message to send to Devin"
          },
          slack_channel: {
            type: "string",
            description: "Optional Slack channel ID to post to"
          },
          slack_thread_ts: {
            type: "string",
            description: "Optional Slack thread timestamp to reply to"
          }
        },
        required: ["session_id", "message"]
      }
    },
  • Helper function to resolve Slack channel name or ID to channel ID, used indirectly via sendSlackMessage.
    async function getChannelId(channelNameOrId: string): Promise<string> {
      // すでにIDの場合 (C12345 形式)
      if (/^[C][A-Z0-9]{8,}$/.test(channelNameOrId)) {
        return channelNameOrId;
      }
      
      try {
        // チャンネル名の場合、一覧を取得して検索
        const result = await slackClient.conversations.list();
        if (result.channels && Array.isArray(result.channels)) {
          // チャンネル名で検索 (#は省略可能)
          const normalizedName = channelNameOrId.startsWith('#') ? 
            channelNameOrId.substring(1) : channelNameOrId;
          
          const channel = result.channels.find(
            (ch) => ch.name === normalizedName
          );
          
          if (channel && channel.id) {
            return channel.id;
          }
        }
        
        // 見つからない場合はエラー
        throw new Error(`Channel not found: ${channelNameOrId}`);
      } catch (error) {
        console.error(`Error resolving channel name to ID: ${error}`);
        throw error;
      }
    }
  • Helper function to send a message to a Slack channel/thread, called from the handler when Slack parameters are provided.
    async function sendSlackMessage(channel: string, text: string, threadTs?: string) {
      try {
        // チャンネルIDを解決
        const channelId = await getChannelId(channel);
        
        const messageOptions = {
          channel: channelId,
          text,
          thread_ts: threadTs,
          as_user: true
        };
    
        const response = await slackClient.chat.postMessage(messageOptions);
        return response;
      } catch (error) {
        console.error('Error sending message to Slack:', error);
        throw error;
      }
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions the action 'send a message' but doesn't describe what happens after sending (e.g., does Devin respond, is it async, are there rate limits, what permissions are needed). For a communication tool with zero annotation coverage, this leaves significant gaps in understanding the tool's behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that front-loads the core purpose and includes the optional Slack functionality. Every word earns its place with no redundancy or unnecessary elaboration.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no annotations and no output schema, the description adequately covers the basic action but lacks details on behavioral outcomes, error conditions, or response format. For a tool that sends messages (potentially involving async interactions or notifications), more context on what to expect after invocation would be helpful.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all 4 parameters thoroughly. The description adds no additional meaning beyond what's in the schema (e.g., it doesn't explain the relationship between slack_channel and slack_thread_ts or provide usage examples). Baseline 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'send' and the resource 'message to an existing Devin session', with additional optional functionality 'to the associated Slack thread'. It distinguishes from siblings like create_devin_session (creation vs. communication) and get/list sessions (retrieval vs. action).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage when you have an existing session (vs. create_devin_session for new sessions) and want to communicate with it, but doesn't explicitly state when to use this tool versus alternatives like whether it's for real-time interaction or notifications. No explicit exclusions or detailed context are provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kazuph/mcp-devin'

If you have feedback or need assistance with the MCP directory API, please join our Discord server