feat(plugins): Microsoft Workflows Pack v0 (Graph, Win+Mac universal) - #23
Merged
Conversation
First external pack built on the AgentMarkPlugin contract from PR #22. Universal Outlook + OneDrive surface that runs identically on Windows and macOS because every tool hits Microsoft Graph rather than native COM/AppleScript bindings. Office app drivers (Excel-COM on Windows, AppleScript on macOS) ship in a follow-up. Tools (10): - agentmark_microsoft_login / logout / whoami - agentmark_outlook_send_email / search / get_message / reply - agentmark_onedrive_list / upload / download Auth: OAuth 2.0 device-code flow (RFC 8628). Tokens are persisted to ~/.thinkfleet/agentmark/microsoft-tokens.json with 0600 permissions. Refresh tokens rotate automatically on access-token expiry; expired refresh tokens surface NotAuthenticatedError pointing the user back to agentmark_microsoft_login. Client ID is read from the AGENTMARK_MS_CLIENT_ID environment variable or the `clientId` config option. Register an Azure AD app with these delegated permissions: Mail.Send, Mail.ReadWrite, Files.ReadWrite, offline_access, User.Read. The "Allow public client flows" toggle must be enabled for device-code to work. Opt-in pack: not part of the default plugin set. Use it explicitly: import { createMcpServer, createWebPlugin, createPdfPlugin, createDesktopPlugin, createMetaPlugin, createMicrosoftPlugin } from '@thinkfleet/agentmark' const web = createWebPlugin() const pdf = createPdfPlugin() const desktop = createDesktopPlugin() const microsoft = createMicrosoftPlugin({ clientId: '...' }) const meta = createMetaPlugin([web, pdf, desktop, microsoft]) createMcpServer({ plugins: [web, pdf, desktop, microsoft, meta] }) Tests: 12 new (auth state machine + plugin registration + Outlook handler shape). Total 338 pass, 10 skip. Build clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
AgentMarkPlugincontract — cross-platform Outlook + OneDrive via Microsoft Graph.Tools shipped (10)
agentmark_microsoft_login,..._logout,..._whoamiagentmark_outlook_send_email,..._search,..._get_message,..._replyagentmark_onedrive_list,..._upload,..._downloadWhy
First validation of the plugin contract by a real external pack. Establishes the auth pattern (device-code + persistent cache) and the Graph HTTP client that the rest of the Microsoft surface (Teams, Calendar, SharePoint) will reuse. Cross-platform identical because every call hits Graph rather than COM/AppleScript.
Setup (one-time)
Mail.Send,Mail.ReadWrite,Files.ReadWrite,offline_access,User.ReadAGENTMARK_MS_CLIENT_ID=<your-client-id>or passclientIdtocreateMicrosoftPlugin().Opt-in usage
Pack is not part of the default plugin set — explicitly include it:
```ts
import {
createMcpServer,
createWebPlugin, createPdfPlugin, createDesktopPlugin, createMetaPlugin,
createMicrosoftPlugin,
} from '@thinkfleet/agentmark'
const web = createWebPlugin()
const pdf = createPdfPlugin()
const desktop = createDesktopPlugin()
const microsoft = createMicrosoftPlugin() // reads AGENTMARK_MS_CLIENT_ID
const meta = createMetaPlugin([web, pdf, desktop, microsoft])
createMcpServer({ plugins: [web, pdf, desktop, microsoft, meta] })
```
Test plan
pnpm buildcleanpnpm test— 338 pass / 10 skip (12 new tests for auth + handlers via mockedfetch)agentmark_microsoft_login, send a test email🤖 Generated with Claude Code