Skip to main content

Microsoft 365

Connect your agents to Microsoft 365 for Outlook, OneDrive, Teams, Excel, and more.

Available Tools

Outlook (Email)

ToolDescription
outlook_searchSearch emails
outlook_readRead email content
outlook_sendSend email
outlook_replyReply to email
outlook_forwardForward email
outlook_moveMove to folder
outlook_deleteDelete email

OneDrive

ToolDescription
onedrive_listList files and folders
onedrive_searchSearch files
onedrive_readRead file content
onedrive_uploadUpload file
onedrive_shareShare file
onedrive_deleteDelete file

Microsoft Teams

ToolDescription
teams_list_channelsList team channels
teams_sendSend message to channel
teams_replyReply to message
teams_list_membersList team members

Excel

ToolDescription
excel_readRead spreadsheet data
excel_writeWrite to cells
excel_appendAppend rows
excel_create_tableCreate table

SharePoint

ToolDescription
sharepoint_list_sitesList sites
sharepoint_list_itemsList items in a list
sharepoint_searchSearch SharePoint

Connecting

Required Permissions

Microsoft uses Graph API permissions:

// Read-only access
permissions: [
'Mail.Read',
'Files.Read.All',
'Calendars.Read'
]

// Full access
permissions: [
'Mail.ReadWrite',
'Mail.Send',
'Files.ReadWrite.All',
'Calendars.ReadWrite',
'ChannelMessage.Send'
]

OAuth Setup

const connection = await client.integrations.connect({
integrationId: 'microsoft-365',
permissions: ['Mail.ReadWrite', 'Mail.Send', 'Files.ReadWrite.All'],
redirectUrl: 'https://your-app.com/oauth/callback'
});

// Redirect user
window.location.href = connection.authUrl;

App-Only Auth (Admin)

For admin operations without user context:

await client.integrations.connectAppOnly({
integrationId: 'microsoft-365-admin',
tenantId: 'your-tenant-id',
clientId: 'your-app-client-id',
clientSecret: process.env.MS_CLIENT_SECRET,
permissions: [
'User.ReadWrite.All',
'Group.ReadWrite.All',
'Directory.ReadWrite.All'
]
});

Tool Examples

const emails = await tools.outlook_search({
query: 'from:support@company.com isread:false',
top: 10,
orderBy: 'receivedDateTime desc'
});

// Returns
{
messages: [
{
id: 'msg-123',
conversationId: 'conv-456',
from: {
emailAddress: {
name: 'Support',
address: 'support@company.com'
}
},
toRecipients: [...],
subject: 'Your ticket #1234',
bodyPreview: 'We have received your request...',
receivedDateTime: '2024-01-15T10:30:00Z',
isRead: false,
hasAttachments: true
}
],
nextLink: 'https://graph.microsoft.com/...'
}

Outlook Send

const result = await tools.outlook_send({
to: ['customer@example.com'],
cc: ['team@company.com'],
subject: 'Re: Your inquiry',
body: 'Thank you for reaching out...',
bodyType: 'text', // or 'html'
importance: 'normal'
});

// Returns
{
success: true,
messageId: 'msg-789'
}

OneDrive List

const files = await tools.onedrive_list({
path: '/Documents/Projects',
top: 20
});

// Returns
{
items: [
{
id: 'item-123',
name: 'Q4 Report.docx',
size: 245678,
createdDateTime: '2024-01-01T00:00:00Z',
lastModifiedDateTime: '2024-01-15T10:00:00Z',
webUrl: 'https://company.sharepoint.com/...',
file: {
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
},
createdBy: {
user: { displayName: 'Alice', email: 'alice@company.com' }
}
}
]
}
const files = await tools.onedrive_search({
query: 'budget 2024 filetype:xlsx',
top: 10
});

Teams Send

const message = await tools.teams_send({
teamId: 'team-123',
channelId: 'channel-456',
content: 'Hello team! Here is the update...',
contentType: 'text' // or 'html'
});

// Returns
{
id: 'msg-789',
webUrl: 'https://teams.microsoft.com/...',
createdDateTime: '2024-01-15T10:00:00Z'
}

Excel Read

const data = await tools.excel_read({
fileId: 'file-123',
worksheet: 'Sheet1',
range: 'A1:D10'
});

// Returns
{
values: [
['Name', 'Email', 'Department', 'Start Date'],
['Alice', 'alice@company.com', 'Engineering', '2023-01-15'],
['Bob', 'bob@company.com', 'Sales', '2023-03-01']
],
metadata: {
address: 'Sheet1!A1:D10',
rowCount: 3,
columnCount: 4
}
}

Excel Write

await tools.excel_write({
fileId: 'file-123',
worksheet: 'Sheet1',
range: 'A11',
values: [
['Charlie', 'charlie@company.com', 'Marketing', '2024-01-15']
]
});

Microsoft Admin

For IT administration (requires admin consent):

Admin Tools

ToolDescription
ms_admin_create_userCreate new user
ms_admin_list_usersList directory users
ms_admin_update_userUpdate user
ms_admin_delete_userDelete user
ms_admin_create_groupCreate group
ms_admin_add_to_groupAdd member to group
ms_admin_list_licensesList available licenses
ms_admin_assign_licenseAssign license
ms_admin_revoke_licenseRemove license
ms_admin_get_user_licensesGet user's licenses

Create User

const user = await tools.ms_admin_create_user({
displayName: 'New User',
mailNickname: 'newuser',
userPrincipalName: 'newuser@company.onmicrosoft.com',
password: 'temporary-password',
forceChangePasswordNextSignIn: true,
department: 'Engineering',
jobTitle: 'Software Engineer'
});

// Returns
{
id: 'user-123',
displayName: 'New User',
userPrincipalName: 'newuser@company.onmicrosoft.com',
mail: 'newuser@company.com',
createdDateTime: '2024-01-15T10:00:00Z'
}

List Users

const users = await tools.ms_admin_list_users({
filter: "department eq 'Engineering'",
top: 50,
select: ['displayName', 'mail', 'department', 'jobTitle']
});

Assign License

await tools.ms_admin_assign_license({
userId: 'user-123',
skuId: 'c7df2760-2c81-4ef7-b578-5b5392b571df' // Microsoft 365 E3
});

Get User Licenses

const licenses = await tools.ms_admin_get_user_licenses({
userId: 'user-123'
});

// Returns
{
licenses: [
{
skuId: 'c7df2760-2c81-4ef7-b578-5b5392b571df',
skuPartNumber: 'ENTERPRISEPACK',
displayName: 'Microsoft 365 E3',
assignedDateTime: '2024-01-01T00:00:00Z'
}
]
}

Best Practices

1. Use Least Privilege

// ✅ Good - specific permissions
permissions: ['Mail.Read', 'Calendars.Read']

// ❌ Bad - overly broad
permissions: ['Mail.ReadWrite.All', 'Sites.FullControl.All']

2. Handle Pagination

let nextLink = null;
const allItems = [];

do {
const result = await tools.onedrive_list({
path: '/Documents',
nextLink
});
allItems.push(...result.items);
nextLink = result.nextLink;
} while (nextLink);

3. Use Batch Requests

For multiple operations, use batching:

const results = await tools.ms_batch({
requests: [
{ id: '1', method: 'GET', url: '/me/messages?$top=5' },
{ id: '2', method: 'GET', url: '/me/calendar/events?$top=5' }
]
});

4. Cache Directory Data

User and group info changes infrequently:

// Cache user lookup results
const user = await getCachedUser(email) || await tools.ms_admin_list_users({
filter: `mail eq '${email}'`
});

Troubleshooting

"Insufficient Privileges"

  1. Check API permissions in Azure AD app registration
  2. Ensure admin consent was granted for admin permissions
  3. Verify user has appropriate Microsoft 365 license

"Request Throttled"

Microsoft Graph has service-specific limits:

ServiceLimit
Outlook10,000 requests/10 minutes
OneDrive10,000 requests/10 minutes
Teams2,000 requests/minute

"Token Expired"

// Refresh connection
await client.integrations.refreshConnection('connection-123');

"User Not Found"

Ensure user exists and is licensed:

const user = await tools.ms_admin_list_users({
filter: `userPrincipalName eq 'user@company.com'`
});

if (user.value.length === 0) {
console.log('User not found in directory');
}

Next: Explore Security Features for authentication and compliance.