teams-mcp-server
Version:
Microsoft Teams MCP server with direct messaging support
136 lines (135 loc) • 4.88 kB
JavaScript
import { Client } from '@microsoft/microsoft-graph-client';
import { RateLimiter } from './rateLimiter.js';
export class TeamsClientStateless {
rateLimiter;
constructor() {
this.rateLimiter = new RateLimiter();
}
createClient(accessToken) {
return Client.init({
authProvider: async (done) => {
done(null, accessToken);
}
});
}
async getUserProfile(accessToken) {
return this.rateLimiter.execute(async () => {
const client = this.createClient(accessToken);
try {
return await client.api('/me').get();
}
catch (error) {
throw this.handleError(error);
}
});
}
async listChats(accessToken, limit = 50, filter) {
return this.rateLimiter.execute(async () => {
const client = this.createClient(accessToken);
const chats = [];
try {
let request = client.api('/chats')
.select('id,topic,chatType,createdDateTime,lastUpdatedDateTime,webUrl,tenantId')
.top(limit);
if (filter) {
request = request.filter(filter);
}
const response = await request.get();
if (response.value) {
chats.push(...response.value);
}
return chats;
}
catch (error) {
throw this.handleError(error);
}
});
}
async createChat(accessToken, request) {
return this.rateLimiter.execute(async () => {
const client = this.createClient(accessToken);
const members = await Promise.all(request.members.map(async (member) => {
const userResponse = await client
.api(`/users/${member.email}`)
.select('id')
.get();
return {
'@odata.type': '#microsoft.graph.aadUserConversationMember',
roles: [member.role || 'owner'],
'user@odata.bind': `https://graph.microsoft.com/v1.0/users('${userResponse.id}')`
};
}));
const chatData = {
chatType: request.chatType,
members
};
if (request.topic && request.chatType === 'group') {
chatData.topic = request.topic;
}
try {
return await client.api('/chats').post(chatData);
}
catch (error) {
throw this.handleError(error);
}
});
}
async sendMessage(accessToken, chatId, request) {
return this.rateLimiter.execute(async () => {
const client = this.createClient(accessToken);
const messageData = {
body: {
contentType: request.contentType || 'text',
content: request.content
}
};
try {
return await client.api(`/chats/${chatId}/messages`).post(messageData);
}
catch (error) {
throw this.handleError(error);
}
});
}
async getMessages(accessToken, chatId, limit = 50, orderBy = 'createdDateTime desc') {
return this.rateLimiter.execute(async () => {
const client = this.createClient(accessToken);
const messages = [];
try {
const response = await client
.api(`/chats/${chatId}/messages`)
.top(limit)
.orderby(orderBy)
.get();
if (response.value) {
messages.push(...response.value);
}
return messages;
}
catch (error) {
throw this.handleError(error);
}
});
}
getRateLimitStats() {
return this.rateLimiter.getStats();
}
handleError(error) {
if (error.statusCode === 401) {
return new Error('Authentication failed. Token may be expired or invalid.');
}
if (error.statusCode === 403) {
return new Error('Insufficient permissions. Make sure the app has the required permissions.');
}
if (error.statusCode === 404) {
return new Error('Resource not found. Check that the chat or user exists.');
}
if (error.statusCode === 429) {
return new Error('Rate limit exceeded. Please wait before making more requests.');
}
if (error.message) {
return new Error(`Teams API error: ${error.message}`);
}
return new Error('Unknown Teams API error');
}
}