start_conversation
Initiate a new conversation with a Microsoft Copilot Studio Agent to interact with custom AI assistants through Direct Line 3.0 API integration.
Instructions
Start a new conversation with the Copilot Studio Agent
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| initialMessage | No | Optional first message to send |
Implementation Reference
- src/server/mcp-server.ts:344-447 (handler)Core handler function that executes the start_conversation tool: validates args, creates conversation via ConversationManager, optionally sends initial message and polls for bot response.private async handleStartConversation( args: Record<string, unknown>, userContext?: UserContext ) { const { initialMessage } = validateToolArgs(StartConversationArgsSchema, args); try { // Create new conversation with user-specific client ID const clientId = userContext ? `user-${userContext.userId}-${Date.now()}` : `mcp-client-${Date.now()}`; const convState = await this.conversationManager.createConversation(clientId); // Associate conversation with user if (userContext) { this.associateConversationWithUser(userContext.userId, convState.conversationId); } let result: { conversationId: string; status: string; response?: string; activityId?: string; } = { conversationId: convState.conversationId, status: 'started', }; // If initial message provided, send it if (initialMessage && typeof initialMessage === 'string') { const activityId = await this.client.sendActivity( { conversationId: convState.conversationId, activity: { type: 'message', from: { id: clientId, name: userContext?.name || 'MCP User' }, text: initialMessage, timestamp: new Date().toISOString(), channelData: userContext ? { userId: userContext.userId, userEmail: userContext.email, tenantId: userContext.tenantId, } : undefined, }, }, convState.token ); // Poll for response (same logic as send_message) 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: convState.conversationId, watermark: convState.watermark, }, convState.token ); if (activitySet.watermark) { this.conversationManager.updateWatermark(convState.conversationId, activitySet.watermark); } const botActivities = activitySet.activities.filter( (a) => a.type === 'message' && a.from?.id !== clientId ); if (botActivities.length > 0) { botActivities.forEach((activity) => { this.conversationManager.addToHistory(convState.conversationId, activity); }); const latestBot = botActivities[botActivities.length - 1]; botResponse = latestBot.text || '[No text response]'; break; } } result.response = botResponse || '[No response received within timeout period]'; result.activityId = activityId; } // Audit log this.logAudit({ timestamp: Date.now(), userId: userContext?.userId, action: 'start_conversation', conversationId: convState.conversationId, }); return createSuccessResponse(result); } catch (error) { throw new Error( `Failed to start conversation: ${error instanceof Error ? error.message : String(error)}` ); } }
- src/server/tool-schemas.ts:20-24 (schema)Zod schema defining input validation for start_conversation tool arguments (optional initialMessage).export const StartConversationArgsSchema = z.object({ initialMessage: z.string().min(1, 'Initial message cannot be empty').optional(), }); export type StartConversationArgs = z.infer<typeof StartConversationArgsSchema>;
- src/server/mcp-server.ts:135-146 (registration)Tool registration in ListToolsRequestHandler for stdio transport, defining name, description, and input schema.name: 'start_conversation', description: 'Start a new conversation with the Copilot Studio Agent', inputSchema: { type: 'object', properties: { initialMessage: { type: 'string', description: 'Optional first message to send', }, }, }, },
- src/server/mcp-server.ts:707-717 (registration)Tool registration in HTTP transport handler for tools/list method.name: 'start_conversation', description: 'Start a new conversation with the Copilot Studio Agent', inputSchema: { type: 'object', properties: { initialMessage: { type: 'string', description: 'Optional first message to send', }, }, },
- Helper method called by handler to create and manage conversation state, delegating actual DirectLine start to client.async createConversation(clientId: string): Promise<ConversationState> { // Get token from token manager const token = await this.tokenManager.getToken(clientId); // Start conversation with Direct Line const conversation = await this.client.startConversation(token); // Create state const state: ConversationState = { conversationId: conversation.conversationId, token: conversation.token, clientId, watermark: undefined, createdAt: Date.now(), lastActivity: Date.now(), messageHistory: [], }; // Store state this.conversations.set(conversation.conversationId, state); // Update metrics this.metrics.totalCreated++; this.metrics.activeCount = this.conversations.size; // Schedule cleanup this.scheduleCleanup(conversation.conversationId); console.error(`[ConversationManager] Created conversation ${conversation.conversationId} for client ${clientId}`); return state; }