m365-roadmap-mcp 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ """M365 Roadmap MCP Server - Query the Microsoft 365 Roadmap via MCP."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,5 @@
1
+ """Entry point for python -m m365_roadmap_mcp."""
2
+
3
+ from .server import main
4
+
5
+ main()
@@ -0,0 +1 @@
1
+ """M365 Roadmap API feed handling."""
@@ -0,0 +1,70 @@
1
+ """M365 Roadmap API fetching and parsing."""
2
+
3
+ import httpx
4
+
5
+ from ..models.feature import RoadmapFeature
6
+
7
+ M365_ROADMAP_API_URL = "https://www.microsoft.com/releasecommunications/api/v1/m365"
8
+
9
+
10
+ async def fetch_features() -> list[RoadmapFeature]:
11
+ """Fetch and parse features from the M365 Roadmap API.
12
+
13
+ Returns:
14
+ List of RoadmapFeature objects sorted by created date (newest first).
15
+ """
16
+ async with httpx.AsyncClient() as client:
17
+ response = await client.get(M365_ROADMAP_API_URL, timeout=30.0)
18
+ response.raise_for_status()
19
+
20
+ items = response.json()
21
+ features = []
22
+
23
+ for item in items:
24
+ feature = _parse_item(item)
25
+ if feature:
26
+ features.append(feature)
27
+
28
+ # Sort by created date, newest first
29
+ features.sort(key=lambda f: f.created or "", reverse=True)
30
+ return features
31
+
32
+
33
+ def _parse_item(item: dict) -> RoadmapFeature | None:
34
+ """Parse a single API item into a RoadmapFeature.
35
+
36
+ Args:
37
+ item: A dictionary from the API JSON array.
38
+
39
+ Returns:
40
+ RoadmapFeature object or None if parsing fails.
41
+ """
42
+ try:
43
+ # Extract product tags from tagsContainer
44
+ tags_container = item.get("tagsContainer") or {}
45
+ products = [
46
+ p["tagName"]
47
+ for p in tags_container.get("products", [])
48
+ if "tagName" in p
49
+ ]
50
+
51
+ # Extract cloud instances from tagsContainer
52
+ cloud_instances = [
53
+ c["tagName"]
54
+ for c in tags_container.get("cloudInstances", [])
55
+ if "tagName" in c
56
+ ]
57
+
58
+ return RoadmapFeature(
59
+ id=str(item.get("id", "")),
60
+ title=item.get("title", ""),
61
+ description=item.get("description", ""),
62
+ status=item.get("status"),
63
+ tags=products,
64
+ cloud_instances=cloud_instances,
65
+ public_disclosure_date=item.get("publicDisclosureAvailabilityDate"),
66
+ created=item.get("created"),
67
+ modified=item.get("modified"),
68
+ )
69
+ except Exception:
70
+ return None
@@ -0,0 +1,5 @@
1
+ """Data models for M365 Roadmap features."""
2
+
3
+ from .feature import RoadmapFeature
4
+
5
+ __all__ = ["RoadmapFeature"]
@@ -0,0 +1,49 @@
1
+ """Pydantic models for M365 Roadmap features."""
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+
6
+ class RoadmapFeature(BaseModel):
7
+ """Represents a single feature from the M365 Roadmap API."""
8
+
9
+ id: str = Field(description="Unique Roadmap ID")
10
+ title: str = Field(description="Feature title")
11
+ description: str = Field(description="Feature description (HTML/text)")
12
+ status: str | None = Field(
13
+ default=None,
14
+ description="Feature status: In development, Rolling out, or Launched",
15
+ )
16
+ tags: list[str] = Field(
17
+ default_factory=list,
18
+ description="Product tags (e.g., Microsoft Teams, SharePoint)",
19
+ )
20
+ cloud_instances: list[str] = Field(
21
+ default_factory=list,
22
+ description="Cloud availability (e.g., Worldwide, GCC, GCC High, DoD)",
23
+ )
24
+ public_disclosure_date: str | None = Field(
25
+ default=None,
26
+ description="Estimated release date (e.g., August CY2026)",
27
+ )
28
+ created: str | None = Field(
29
+ default=None,
30
+ description="Date the feature was added to the roadmap",
31
+ )
32
+ modified: str | None = Field(
33
+ default=None,
34
+ description="Date the feature was last modified",
35
+ )
36
+
37
+ def to_dict(self) -> dict:
38
+ """Convert to dictionary for tool output."""
39
+ return {
40
+ "id": self.id,
41
+ "title": self.title,
42
+ "description": self.description,
43
+ "status": self.status,
44
+ "tags": self.tags,
45
+ "cloud_instances": self.cloud_instances,
46
+ "public_disclosure_date": self.public_disclosure_date,
47
+ "created": self.created,
48
+ "modified": self.modified,
49
+ }
@@ -0,0 +1,61 @@
1
+ """M365 Roadmap MCP Server - FastMCP server with stdio/HTTP transport."""
2
+
3
+ import logging
4
+ import os
5
+
6
+ from fastmcp import FastMCP
7
+
8
+ # Suppress FastMCP's INFO logs to reduce console noise
9
+ logging.getLogger("fastmcp").setLevel(logging.WARNING)
10
+
11
+ from .tools.cloud import check_cloud_availability
12
+ from .tools.details import get_feature_details
13
+ from .tools.recent import list_recent_additions
14
+ from .tools.search import search_roadmap
15
+
16
+ # Create the MCP server
17
+ mcp = FastMCP(
18
+ "M365 Roadmap MCP",
19
+ instructions=(
20
+ "Query and search the Microsoft 365 Roadmap for upcoming features, "
21
+ "release dates, and cloud instance availability.\n\n"
22
+ "Available tools:\n"
23
+ "- search_roadmap: Find and filter roadmap features by keyword, product, "
24
+ "status, cloud instance (GCC, GCC High, DoD), or feature ID.\n"
25
+ "- get_feature_details: Retrieve full metadata for a specific roadmap "
26
+ "feature by its ID.\n"
27
+ "- check_cloud_availability: Verify whether a feature is available for a "
28
+ "specific cloud instance (critical for government/defense clients).\n"
29
+ "- list_recent_additions: List features recently added to the roadmap "
30
+ "within a given number of days."
31
+ ),
32
+ )
33
+
34
+ # Register tools
35
+ mcp.tool(search_roadmap)
36
+ mcp.tool(get_feature_details)
37
+ mcp.tool(check_cloud_availability)
38
+ mcp.tool(list_recent_additions)
39
+
40
+
41
+ def main():
42
+ """Run the MCP server.
43
+
44
+ Uses stdio transport by default (for MCP client auto-start).
45
+ Set MCP_TRANSPORT=http to run as an HTTP server for remote access.
46
+ """
47
+ transport = os.getenv("MCP_TRANSPORT", "stdio")
48
+
49
+ if transport == "http":
50
+ host = os.getenv("MCP_HOST", "0.0.0.0")
51
+ port = int(os.getenv("MCP_PORT", "8000"))
52
+ print(f"Starting M365 Roadmap MCP server on {host}:{port}")
53
+ print(f"MCP endpoint: http://{host}:{port}/mcp")
54
+ mcp.run(transport="http", host=host, port=port, show_banner=False)
55
+ else:
56
+ # stdio transport (default for MCP client auto-start)
57
+ mcp.run(transport="stdio", show_banner=False)
58
+
59
+
60
+ if __name__ == "__main__":
61
+ main()
@@ -0,0 +1 @@
1
+ """MCP tools for M365 Roadmap."""
@@ -0,0 +1,70 @@
1
+ """Tool for checking cloud instance availability of M365 Roadmap features."""
2
+
3
+ from ..feeds.m365_api import fetch_features
4
+
5
+
6
+ async def check_cloud_availability(feature_id: str, instance: str) -> dict:
7
+ """Check whether a Microsoft 365 Roadmap feature is available for a specific cloud instance.
8
+
9
+ Critical for government and defense clients who need to verify feature availability
10
+ on GCC, GCC High, or DoD cloud instances before planning deployments.
11
+
12
+ Args:
13
+ feature_id: The unique Roadmap ID (e.g., "534606").
14
+ instance: The cloud instance to check (e.g., "GCC", "GCC High", "DoD",
15
+ "Worldwide"). Case-insensitive partial match is used, so "gcc" matches
16
+ "GCC" and "GCC High".
17
+
18
+ Returns:
19
+ Dictionary with:
20
+ - feature_id: The queried feature ID
21
+ - instance_queried: The cloud instance that was checked
22
+ - found: Whether the feature was found in the roadmap
23
+ - available: Whether the feature is available for the queried instance
24
+ - matched_instances: List of cloud instances that matched the query
25
+ - all_instances: All cloud instances the feature supports
26
+ - status: Feature status (if found)
27
+ - public_disclosure_date: Estimated release date (if found)
28
+ - title: Feature title (if found)
29
+ - error: Error message (if feature not found)
30
+ """
31
+ features = await fetch_features()
32
+
33
+ # Find the feature by ID
34
+ target = None
35
+ for feature in features:
36
+ if feature.id == feature_id:
37
+ target = feature
38
+ break
39
+
40
+ if target is None:
41
+ return {
42
+ "feature_id": feature_id,
43
+ "instance_queried": instance,
44
+ "found": False,
45
+ "available": False,
46
+ "matched_instances": [],
47
+ "all_instances": [],
48
+ "status": None,
49
+ "public_disclosure_date": None,
50
+ "title": None,
51
+ "error": f"No feature found with ID '{feature_id}'",
52
+ }
53
+
54
+ # Case-insensitive partial match on cloud instances
55
+ instance_lower = instance.lower()
56
+ matched = [
57
+ ci for ci in target.cloud_instances if instance_lower in ci.lower()
58
+ ]
59
+
60
+ return {
61
+ "feature_id": feature_id,
62
+ "instance_queried": instance,
63
+ "found": True,
64
+ "available": len(matched) > 0,
65
+ "matched_instances": matched,
66
+ "all_instances": target.cloud_instances,
67
+ "status": target.status,
68
+ "public_disclosure_date": target.public_disclosure_date,
69
+ "title": target.title,
70
+ }
@@ -0,0 +1,35 @@
1
+ """Tool for retrieving full details of a single M365 Roadmap feature."""
2
+
3
+ from ..feeds.m365_api import fetch_features
4
+
5
+
6
+ async def get_feature_details(feature_id: str) -> dict:
7
+ """Retrieve full metadata for a specific Microsoft 365 Roadmap feature by its ID.
8
+
9
+ Use this tool when you need complete details about a known roadmap feature,
10
+ including its description, status, product tags, cloud instance availability,
11
+ and release date.
12
+
13
+ Args:
14
+ feature_id: The unique Roadmap ID (e.g., "534606").
15
+
16
+ Returns:
17
+ Dictionary with:
18
+ - found: Whether the feature was found
19
+ - feature: Full feature object if found, None otherwise
20
+ - error: Error message if not found
21
+ """
22
+ features = await fetch_features()
23
+
24
+ for feature in features:
25
+ if feature.id == feature_id:
26
+ return {
27
+ "found": True,
28
+ "feature": feature.to_dict(),
29
+ }
30
+
31
+ return {
32
+ "found": False,
33
+ "feature": None,
34
+ "error": f"No feature found with ID '{feature_id}'",
35
+ }
@@ -0,0 +1,50 @@
1
+ """Tool for listing recently added M365 Roadmap features."""
2
+
3
+ from datetime import datetime, timedelta, timezone
4
+
5
+ from ..feeds.m365_api import fetch_features
6
+
7
+
8
+ async def list_recent_additions(days: int = 7) -> dict:
9
+ """List features recently added to the Microsoft 365 Roadmap.
10
+
11
+ Use this tool to monitor what new features have appeared on the roadmap
12
+ within a given time window. Useful for staying current on Microsoft's
13
+ latest plans and announcements.
14
+
15
+ Args:
16
+ days: Number of days to look back (default: 7, clamped to 1–365).
17
+
18
+ Returns:
19
+ Dictionary with:
20
+ - total_found: Number of features added within the time window
21
+ - features: List of recently added feature objects
22
+ - days_queried: The actual number of days used (after clamping)
23
+ - cutoff_date: The earliest date included in the results (ISO format)
24
+ """
25
+ # Clamp days to reasonable bounds
26
+ days = max(1, min(days, 365))
27
+
28
+ cutoff = datetime.now(timezone.utc) - timedelta(days=days)
29
+ features = await fetch_features()
30
+
31
+ recent = []
32
+ for feature in features:
33
+ if not feature.created:
34
+ continue
35
+ try:
36
+ created_dt = datetime.fromisoformat(feature.created)
37
+ # Ensure timezone-aware comparison
38
+ if created_dt.tzinfo is None:
39
+ created_dt = created_dt.replace(tzinfo=timezone.utc)
40
+ if created_dt >= cutoff:
41
+ recent.append(feature)
42
+ except (ValueError, TypeError):
43
+ continue
44
+
45
+ return {
46
+ "total_found": len(recent),
47
+ "features": [f.to_dict() for f in recent],
48
+ "days_queried": days,
49
+ "cutoff_date": cutoff.isoformat(),
50
+ }
@@ -0,0 +1,118 @@
1
+ """Search tool for querying and filtering M365 Roadmap features."""
2
+
3
+ from ..feeds.m365_api import fetch_features
4
+
5
+
6
+ async def search_roadmap(
7
+ query: str | None = None,
8
+ product: str | None = None,
9
+ status: str | None = None,
10
+ cloud_instance: str | None = None,
11
+ feature_id: str | None = None,
12
+ limit: int = 10,
13
+ ) -> dict:
14
+ """Search the Microsoft 365 Roadmap for features matching keywords and filters.
15
+
16
+ Combines keyword search, product filtering, status filtering, and cloud instance
17
+ filtering into a single flexible tool. All filter parameters are optional and
18
+ can be combined. When no filters are provided, returns the most recent features.
19
+
20
+ Use this tool to:
21
+ - Browse recent roadmap features (no filters)
22
+ - Search for features by keyword (query="Copilot")
23
+ - Filter by product (product="Microsoft Teams")
24
+ - Find features by status (status="In development", "Rolling out", "Launched")
25
+ - Filter by cloud instance (cloud_instance="GCC High", "DoD", "GCC")
26
+ - Retrieve a specific feature by ID (feature_id="534606")
27
+ - Combine any of the above (query="Copilot" + product="Teams" + cloud_instance="GCC")
28
+
29
+ Args:
30
+ query: Optional keyword to match against title and description (case-insensitive).
31
+ product: Optional product tag to filter by (case-insensitive partial match,
32
+ e.g. "Teams" matches "Microsoft Teams").
33
+ status: Optional status filter. Valid values: In development, Rolling out, Launched.
34
+ cloud_instance: Optional cloud instance filter (case-insensitive partial match,
35
+ e.g. "GCC" matches "GCC", "GCC High" matches "GCC High").
36
+ feature_id: Optional roadmap ID to retrieve a single specific feature.
37
+ When provided, all other filters are ignored.
38
+ limit: Maximum number of results to return (default: 10, max: 100).
39
+ Ignored when feature_id is provided.
40
+
41
+ Returns:
42
+ Dictionary with:
43
+ - total_found: Number of features matching the filters (before applying limit)
44
+ - features: List of matching feature objects (up to limit)
45
+ - filters_applied: Summary of which filters were used
46
+ """
47
+ features = await fetch_features()
48
+
49
+ # Feature ID lookup is a fast path that ignores all other filters
50
+ if feature_id:
51
+ for feature in features:
52
+ if feature.id == feature_id:
53
+ return {
54
+ "total_found": 1,
55
+ "features": [feature.to_dict()],
56
+ "filters_applied": {"feature_id": feature_id},
57
+ }
58
+ return {
59
+ "total_found": 0,
60
+ "features": [],
61
+ "filters_applied": {"feature_id": feature_id},
62
+ }
63
+
64
+ # Clamp limit to reasonable bounds
65
+ limit = max(1, min(limit, 100))
66
+
67
+ # Prepare lowercase values for case-insensitive matching
68
+ query_lower = query.lower() if query else None
69
+ product_lower = product.lower() if product else None
70
+ status_lower = status.lower() if status else None
71
+ cloud_lower = cloud_instance.lower() if cloud_instance else None
72
+
73
+ # Apply all filters
74
+ matched = []
75
+ for feature in features:
76
+ # Status filter
77
+ if status_lower:
78
+ if not feature.status or feature.status.lower() != status_lower:
79
+ continue
80
+
81
+ # Product filter (partial match)
82
+ if product_lower:
83
+ if not any(product_lower in tag.lower() for tag in feature.tags):
84
+ continue
85
+
86
+ # Cloud instance filter (partial match)
87
+ if cloud_lower:
88
+ if not any(cloud_lower in ci.lower() for ci in feature.cloud_instances):
89
+ continue
90
+
91
+ # Keyword search (title + description)
92
+ if query_lower:
93
+ if (
94
+ query_lower not in feature.title.lower()
95
+ and query_lower not in feature.description.lower()
96
+ ):
97
+ continue
98
+
99
+ matched.append(feature)
100
+
101
+ # Build filters summary
102
+ filters_applied: dict = {}
103
+ if query:
104
+ filters_applied["query"] = query
105
+ if product:
106
+ filters_applied["product"] = product
107
+ if status:
108
+ filters_applied["status"] = status
109
+ if cloud_instance:
110
+ filters_applied["cloud_instance"] = cloud_instance
111
+ if not filters_applied:
112
+ filters_applied["note"] = "No filters applied, returning most recent features"
113
+
114
+ return {
115
+ "total_found": len(matched),
116
+ "features": [f.to_dict() for f in matched[:limit]],
117
+ "filters_applied": filters_applied,
118
+ }
@@ -0,0 +1,140 @@
1
+ Metadata-Version: 2.4
2
+ Name: m365-roadmap-mcp
3
+ Version: 0.1.0
4
+ Summary: MCP server for querying the Microsoft 365 Roadmap
5
+ Project-URL: Homepage, https://github.com/jonnybottles/M365-roadmap-mcp-server
6
+ Project-URL: Repository, https://github.com/jonnybottles/M365-roadmap-mcp-server
7
+ Project-URL: Issues, https://github.com/jonnybottles/M365-roadmap-mcp-server/issues
8
+ Author: Justin Buttler
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: ai-agent,gcc,mcp,microsoft-365,roadmap
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Requires-Python: >=3.11
19
+ Requires-Dist: fastmcp
20
+ Requires-Dist: httpx
21
+ Requires-Dist: pydantic
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest; extra == 'dev'
24
+ Requires-Dist: pytest-asyncio; extra == 'dev'
25
+ Description-Content-Type: text/markdown
26
+
27
+ # M365-roadmap-mcp-server
28
+
29
+ A Model Context Protocol (MCP) server that enables AI agents to query the Microsoft 365 Roadmap programmatically.
30
+
31
+ ## Strategic Rationale
32
+
33
+ For organizations relying on Microsoft 365, Teams, or SharePoint, the "Roadmap" is the single source of truth for upcoming changes. However, navigating the roadmap website manually is cumbersome and disconnected from technical planning workflows. "When is Copilot coming to GCC High?" is a question that affects multi-million dollar contracts and deployment schedules.
34
+
35
+ Existing research indicates that while RSS feeds exist, there is no tool that allows an AI agent to structurally query this data to answer complex filtering questions. A "Roadmap Scout" MCP server empowers the Agent to act as a release manager, proactively identifying features that enable new capabilities or threaten existing customizations.
36
+
37
+ ## example MCP server
38
+
39
+ ** NOTE THE EXAMPLE MCP SERVER IS THE WAY WE SHOULD MODEL OUR MCP SERVER FOR THIS PROJECT
40
+
41
+ ## Data Source
42
+
43
+ This MCP server pulls data from Microsoft's public roadmap API:
44
+
45
+ - **API Endpoint:** `https://www.microsoft.com/releasecommunications/api/v1/m365`
46
+ - **Authentication:** None required (public endpoint)
47
+ - **RSS Mirror:** `https://www.microsoft.com/microsoft-365/RoadmapFeatureRSS` (same data, RSS format)
48
+
49
+ This is the same data that powers the [Microsoft 365 Roadmap website](https://www.microsoft.com/en-us/microsoft-365/roadmap). The legacy endpoint (`roadmap-api.azurewebsites.net`) was retired in March 2025.
50
+
51
+ ### Coverage and Limitations
52
+
53
+ The API returns approximately **1,900 active features** -- those currently In Development, Rolling Out, or recently Launched. This is a hard cap; older or retired features age out of the API and are no longer returned. The roadmap website may display historical features that are no longer present in the API.
54
+
55
+ There is no official Microsoft documentation for this API. It is a public, unauthenticated endpoint that the community has reverse-engineered. Microsoft Graph does not expose the public M365 roadmap (Graph's Service Communications API covers tenant-specific Message Center posts and Service Health, which is different data).
56
+
57
+ ### Schema
58
+
59
+ The API returns a JSON array where each item represents a feature:
60
+
61
+ | Field | Description |
62
+ |-------|-------------|
63
+ | `id` | Unique Roadmap ID (e.g., "93182") |
64
+ | `title` | Feature title |
65
+ | `description` | HTML/Text description |
66
+ | `status` | Enumerated values like "In development", "Rolling out", "Launched" |
67
+ | `tags` | Product associations (e.g., "Microsoft Teams", "SharePoint") |
68
+ | `publicDisclosureAvailabilityDate` | The estimated release target |
69
+ | `cloudInstances` | Critical for government/defense clients. Values include "Worldwide (Standard Multi-Tenant)", "DoD", "GCC" |
70
+
71
+ ## Proposed Tool Definitions
72
+
73
+ | Tool Name | Description | Arguments (JSON Schema) | Expected Output |
74
+ |-----------|-------------|------------------------|-----------------|
75
+ | `search_roadmap` | Searches the M365 roadmap for features matching keywords and filters | `{ "query": "string", "product": "string", "status": "string" }` | List of feature summaries with IDs and dates |
76
+ | `get_feature_details` | Retrieves the full metadata for a specific roadmap ID | `{ "feature_id": "string" }` | Detailed JSON object including description and instance tags |
77
+ | `check_cloud_availability` | Verifies if a feature is scheduled for a specific cloud instance | `{ "feature_id": "string", "instance": "string (e.g., GCC)" }` | Boolean availability and specific release date for that instance |
78
+ | `list_recent_additions` | Lists features added to the roadmap in the last X days | `{ "days": "integer" }` | List of new features to monitor |
79
+
80
+ ## Example Prompts
81
+
82
+ Here are 10 prompts you can use with an AI agent connected to this MCP server:
83
+
84
+ 1. **"What Microsoft Teams features are currently rolling out?"**
85
+ Uses `search_roadmap` with product and status filters to find Teams features in active rollout.
86
+
87
+ 2. **"Is Copilot available for GCC High yet?"**
88
+ Uses `search_roadmap` to find Copilot features, then `check_cloud_availability` to verify GCC High support for each result.
89
+
90
+ 3. **"Show me everything added to the M365 roadmap in the last 30 days."**
91
+ Uses `list_recent_additions(days=30)` to surface newly announced features.
92
+
93
+ 4. **"Tell me more about that Microsoft Lists agent feature you just found."**
94
+ After a prior search, the agent uses `get_feature_details` with the ID from the earlier result to retrieve the full description, cloud instances, and release date.
95
+
96
+ 5. **"Which SharePoint features are in development and available for DoD?"**
97
+ Uses `search_roadmap` with `product="SharePoint"`, `status="In development"`, and `cloud_instance="DoD"` to combine all three filters.
98
+
99
+ 6. **"Compare GCC and GCC High availability for feature 412718."**
100
+ Uses `check_cloud_availability` twice -- once with `instance="GCC"` and once with `instance="GCC High"` -- to compare cloud parity for a single feature.
101
+
102
+ 7. **"What new features were added to the roadmap this week?"**
103
+ Uses `list_recent_additions(days=7)` to get a concise list of the latest additions for a weekly briefing.
104
+
105
+ 8. **"Find all roadmap features related to data loss prevention."**
106
+ Uses `search_roadmap(query="data loss prevention")` to keyword-search across titles and descriptions.
107
+
108
+ 9. **"My agency is on GCC High. Which OneDrive features can we expect?"**
109
+ Uses `search_roadmap` with `product="OneDrive"` and `cloud_instance="GCC High"` to find features available for that government cloud.
110
+
111
+ 10. **"List all launched Viva features and check which ones support GCC."**
112
+ Uses `search_roadmap(product="Viva", status="Launched")` to get candidates, then `check_cloud_availability` on each to filter for GCC support.
113
+
114
+ ## Usage Narrative: Government Compliance Checking
115
+
116
+ ### Scenario
117
+
118
+ An IT Director for a federal agency (using the GCC High cloud) asks about the availability of a new "Microsoft Lists" feature they saw in a demo.
119
+
120
+ **User Query:** "My agency is on GCC High. When will we get the new 'Microsoft Lists' agent capabilities?"
121
+
122
+ ### Agent Action
123
+
124
+ 1. **Analysis:** The Agent parses the intent: Product="Microsoft Lists", Feature="agent capabilities", Constraint="GCC High"
125
+
126
+ 2. **Tool Call:** `search_roadmap(query="Lists agent", product="Microsoft Lists")`
127
+
128
+ 3. **Data Retrieval:** The server queries the API. It finds Roadmap ID 534606: "Enables effortless list creation for Copilot users..."
129
+
130
+ 4. **Tool Call:** `check_cloud_availability(feature_id="534606", instance="GCC High")`
131
+
132
+ 5. **Logic:** The server inspects the `cloudInstances` array of the feature object. It looks for "GCC High"
133
+
134
+ 6. **Result:** The array contains "Worldwide (Standard Multi-Tenant)". It does not contain "GCC High"
135
+
136
+ 7. **Synthesis:** The Agent formulates a precise answer
137
+
138
+ ### Response
139
+
140
+ > "Currently, Roadmap ID 534606 is listed for 'Worldwide (Standard Multi-Tenant)' with a status of 'Rolling Out'. It has not yet been scheduled for the GCC High environment. Based on typical parity delays, this feature is likely 6-12 months away for your tenant."
@@ -0,0 +1,17 @@
1
+ m365_roadmap_mcp/__init__.py,sha256=qz6B-DQCFRM2X6JTnpV_csufVZFBugE6D29ieAJUAWw,96
2
+ m365_roadmap_mcp/__main__.py,sha256=D9mYXV4TlB361LHfDDwvxsybz0_7EUsseJ3pZkS9AOo,84
3
+ m365_roadmap_mcp/server.py,sha256=GXKAyCWojGATKInS6vtVW3PKzizSTe2OhHP2kPVR_0g,2107
4
+ m365_roadmap_mcp/feeds/__init__.py,sha256=mVerRhM3n8iwoiupqp4rhqOGOpR2WbtA6MErj5pLG3g,38
5
+ m365_roadmap_mcp/feeds/m365_api.py,sha256=MXvPGxRaE1EIyGYQCF6F94CGarz4qvGoIS6b_yD5t0Y,2058
6
+ m365_roadmap_mcp/models/__init__.py,sha256=Ml_sDvBRyK40Pq4Of0pDExGEBTjyh0QWB4VLu_zKkks,112
7
+ m365_roadmap_mcp/models/feature.py,sha256=NDKZpq4xcWBaujSaI3H7npXTO03Bh4y2BCY5vc4ZUH0,1672
8
+ m365_roadmap_mcp/tools/__init__.py,sha256=nsNOC46HR1ElncjDck0CjOyeCkh1ZugH8YOiaCg_4dE,34
9
+ m365_roadmap_mcp/tools/cloud.py,sha256=NuvztbKyMLc9pKZYD98kih23e09dAKnAeaEXZig2ky0,2562
10
+ m365_roadmap_mcp/tools/details.py,sha256=jgIpi1BhraHPuMT9tQi3d8ikvLF0EZR7p_D7spNlWL0,1067
11
+ m365_roadmap_mcp/tools/recent.py,sha256=Y9I5SS0I2MsV0i98QKtzXrL14AF5yfEyC3f6RiAxj-g,1709
12
+ m365_roadmap_mcp/tools/search.py,sha256=kmFGam_uJsvTvDUcKjoREVSxUBghkDlrS4JevJLePtQ,4550
13
+ m365_roadmap_mcp-0.1.0.dist-info/METADATA,sha256=mHnm1DnW4CEJv1lOVs1CQx77kB82W4fjI6SdsLG_1zc,8120
14
+ m365_roadmap_mcp-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
15
+ m365_roadmap_mcp-0.1.0.dist-info/entry_points.txt,sha256=GNzyIHa06s1_7BMZzkI4Dsury7aBgUmOYiSXFGNgE6M,66
16
+ m365_roadmap_mcp-0.1.0.dist-info/licenses/LICENSE,sha256=NNt5lEWzqGxqVCVmj-VEeWFxXhtbgCNwFhYcCUffWDI,1071
17
+ m365_roadmap_mcp-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ m365-roadmap-mcp = m365_roadmap_mcp.server:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Justin Buttler
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.