Skip to main content
Glama
bradcstevens

Copilot Studio Agent Direct Line MCP Server

by bradcstevens

send_message

Send messages to Microsoft Copilot Studio Agents via Direct Line API to interact with custom conversational agents directly from development environments.

Instructions

Send a message to the Copilot Studio Agent

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
messageYesThe message text to send
conversationIdNoOptional conversation ID to continue existing conversation

Implementation Reference

  • The core handler function that executes the send_message tool logic: validates input using SendMessageArgsSchema, manages or creates conversations, sends the message via DirectLineClient, polls for the bot's response, logs audit, and returns conversationId, response, and activityId.
    private async handleSendMessage(args: Record<string, unknown>, userContext?: UserContext) { const { message, conversationId } = validateToolArgs(SendMessageArgsSchema, args); // Validate permissions if user context exists if (userContext && conversationId) { this.validateUserConversationAccess(userContext.userId, conversationId); } try { let convId = conversationId; let convState; // Get or create conversation if (convId) { convState = this.conversationManager.getConversation(convId); if (!convState) { throw new Error(`Conversation ${convId} not found or expired`); } } else { // Create new conversation with user-specific client ID const clientId = userContext ? `user-${userContext.userId}-${Date.now()}` : `mcp-client-${Date.now()}`; convState = await this.conversationManager.createConversation(clientId); convId = convState.conversationId; // Associate conversation with user if (userContext) { this.associateConversationWithUser(userContext.userId, convId); } } // Send message to Direct Line with user metadata const activityId = await this.client.sendActivity( { conversationId: convId, activity: { type: 'message', from: { id: convState.clientId, name: userContext?.name || 'MCP User', }, text: message, timestamp: new Date().toISOString(), // Add user metadata to activity channelData: userContext ? { userId: userContext.userId, userEmail: userContext.email, tenantId: userContext.tenantId, } : undefined, }, }, convState.token ); // Poll for response const startTime = Date.now(); const timeout = 30000; let botResponse = ''; while (Date.now() - startTime < timeout) { await new Promise((resolve) => setTimeout(resolve, 1000)); const activitySet = await this.client.getActivities( { conversationId: convId, watermark: convState.watermark, }, convState.token ); if (activitySet.watermark) { this.conversationManager.updateWatermark(convId, activitySet.watermark); } const botActivities = activitySet.activities.filter( (a) => a.type === 'message' && a.from?.id !== convState.clientId ); if (botActivities.length > 0) { botActivities.forEach((activity) => { this.conversationManager.addToHistory(convId!, activity); }); const latestBot = botActivities[botActivities.length - 1]; botResponse = latestBot.text || '[No text response]'; break; } } if (!botResponse) { botResponse = '[No response received within timeout period]'; } // Audit log this.logAudit({ timestamp: Date.now(), userId: userContext?.userId, action: 'send_message', conversationId: convId, details: { activityId }, }); return createSuccessResponse({ conversationId: convId, response: botResponse, activityId, }); } catch (error) { throw new Error( `Failed to send message: ${error instanceof Error ? error.message : String(error)}` ); } }
  • Zod schema for validating send_message tool arguments: requires 'message' string (non-empty), optional 'conversationId' string. Used in handleSendMessage via validateToolArgs.
    * Schema for send_message tool arguments */ export const SendMessageArgsSchema = z.object({ message: z.string().min(1, 'Message cannot be empty'), conversationId: z.string().optional(), }); export type SendMessageArgs = z.infer<typeof SendMessageArgsSchema>;
  • Tool registration in the MCP server's ListToolsRequestSchema handler, defining name, description, and inputSchema for send_message.
    { name: 'send_message', description: 'Send a message to the Copilot Studio Agent', inputSchema: { type: 'object', properties: { message: { type: 'string', description: 'The message text to send', }, conversationId: { type: 'string', description: 'Optional conversation ID to continue existing conversation', }, }, required: ['message'], }, },
  • Dispatch/registration in CallToolRequestSchema handler: routes 'send_message' calls to handleSendMessage function.
    switch (name) { case 'send_message': return await this.handleSendMessage(args || {}, userContext);
  • Duplicate tool registration for HTTP transport mode in handleHttpMessage 'tools/list' case.
    name: 'send_message', description: 'Send a message to the Copilot Studio Agent', inputSchema: { type: 'object', properties: { message: { type: 'string', description: 'The message text to send', }, conversationId: { type: 'string', description: 'Optional conversation ID to continue existing conversation', }, }, required: ['message'], },

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/bradcstevens/copilot-studio-agent-direct-line-mcp'

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