Microsoft 365
Connect your agents to Microsoft 365 for Outlook, OneDrive, Teams, Excel, and more.
Available Tools
Outlook (Email)
| Tool | Description |
|---|---|
outlook_search | Search emails |
outlook_read | Read email content |
outlook_send | Send email |
outlook_reply | Reply to email |
outlook_forward | Forward email |
outlook_move | Move to folder |
outlook_delete | Delete email |
OneDrive
| Tool | Description |
|---|---|
onedrive_list | List files and folders |
onedrive_search | Search files |
onedrive_read | Read file content |
onedrive_upload | Upload file |
onedrive_share | Share file |
onedrive_delete | Delete file |
Microsoft Teams
| Tool | Description |
|---|---|
teams_list_channels | List team channels |
teams_send | Send message to channel |
teams_reply | Reply to message |
teams_list_members | List team members |
Excel
| Tool | Description |
|---|---|
excel_read | Read spreadsheet data |
excel_write | Write to cells |
excel_append | Append rows |
excel_create_table | Create table |
SharePoint
| Tool | Description |
|---|---|
sharepoint_list_sites | List sites |
sharepoint_list_items | List items in a list |
sharepoint_search | Search 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
Outlook Search
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' }
}
}
]
}
OneDrive Search
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
| Tool | Description |
|---|---|
ms_admin_create_user | Create new user |
ms_admin_list_users | List directory users |
ms_admin_update_user | Update user |
ms_admin_delete_user | Delete user |
ms_admin_create_group | Create group |
ms_admin_add_to_group | Add member to group |
ms_admin_list_licenses | List available licenses |
ms_admin_assign_license | Assign license |
ms_admin_revoke_license | Remove license |
ms_admin_get_user_licenses | Get 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"
- Check API permissions in Azure AD app registration
- Ensure admin consent was granted for admin permissions
- Verify user has appropriate Microsoft 365 license
"Request Throttled"
Microsoft Graph has service-specific limits:
| Service | Limit |
|---|---|
| Outlook | 10,000 requests/10 minutes |
| OneDrive | 10,000 requests/10 minutes |
| Teams | 2,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.