m365-roadmap-mcp 0.2.0__tar.gz → 0.3.0__tar.gz

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.
Files changed (29) hide show
  1. {m365_roadmap_mcp-0.2.0 → m365_roadmap_mcp-0.3.0}/.github/workflows/publish.yml +10 -0
  2. {m365_roadmap_mcp-0.2.0 → m365_roadmap_mcp-0.3.0}/.gitignore +4 -0
  3. {m365_roadmap_mcp-0.2.0 → m365_roadmap_mcp-0.3.0}/PKG-INFO +33 -38
  4. {m365_roadmap_mcp-0.2.0 → m365_roadmap_mcp-0.3.0}/README.md +32 -37
  5. m365_roadmap_mcp-0.3.0/icon.png +0 -0
  6. {m365_roadmap_mcp-0.2.0 → m365_roadmap_mcp-0.3.0}/pyproject.toml +1 -1
  7. m365_roadmap_mcp-0.3.0/server.json +23 -0
  8. {m365_roadmap_mcp-0.2.0 → m365_roadmap_mcp-0.3.0}/src/m365_roadmap_mcp/__init__.py +1 -1
  9. {m365_roadmap_mcp-0.2.0 → m365_roadmap_mcp-0.3.0}/src/m365_roadmap_mcp/feeds/m365_api.py +17 -0
  10. {m365_roadmap_mcp-0.2.0 → m365_roadmap_mcp-0.3.0}/src/m365_roadmap_mcp/models/feature.py +16 -1
  11. {m365_roadmap_mcp-0.2.0 → m365_roadmap_mcp-0.3.0}/src/m365_roadmap_mcp/server.py +9 -2
  12. m365_roadmap_mcp-0.3.0/src/m365_roadmap_mcp/tools/cloud.py +70 -0
  13. m365_roadmap_mcp-0.3.0/src/m365_roadmap_mcp/tools/details.py +35 -0
  14. m365_roadmap_mcp-0.3.0/src/m365_roadmap_mcp/tools/recent.py +50 -0
  15. {m365_roadmap_mcp-0.2.0 → m365_roadmap_mcp-0.3.0}/src/m365_roadmap_mcp/tools/search.py +72 -0
  16. {m365_roadmap_mcp-0.2.0 → m365_roadmap_mcp-0.3.0}/tests/test_feeds.py +26 -0
  17. m365_roadmap_mcp-0.3.0/tests/test_tools.py +589 -0
  18. m365_roadmap_mcp-0.2.0/.claude/agents/mcp-server-architect.md +0 -164
  19. m365_roadmap_mcp-0.2.0/.claude/settings.local.json +0 -67
  20. m365_roadmap_mcp-0.2.0/CLAUDE.md +0 -139
  21. m365_roadmap_mcp-0.2.0/tests/test_tools.py +0 -244
  22. {m365_roadmap_mcp-0.2.0 → m365_roadmap_mcp-0.3.0}/LICENSE +0 -0
  23. {m365_roadmap_mcp-0.2.0 → m365_roadmap_mcp-0.3.0}/src/m365_roadmap_mcp/__main__.py +0 -0
  24. {m365_roadmap_mcp-0.2.0 → m365_roadmap_mcp-0.3.0}/src/m365_roadmap_mcp/feeds/__init__.py +0 -0
  25. {m365_roadmap_mcp-0.2.0 → m365_roadmap_mcp-0.3.0}/src/m365_roadmap_mcp/models/__init__.py +0 -0
  26. {m365_roadmap_mcp-0.2.0 → m365_roadmap_mcp-0.3.0}/src/m365_roadmap_mcp/tools/__init__.py +0 -0
  27. {m365_roadmap_mcp-0.2.0 → m365_roadmap_mcp-0.3.0}/tests/__init__.py +0 -0
  28. {m365_roadmap_mcp-0.2.0 → m365_roadmap_mcp-0.3.0}/tests/api_snapshot.json +0 -0
  29. {m365_roadmap_mcp-0.2.0 → m365_roadmap_mcp-0.3.0}/tests/rss_feed_snapshot.xml +0 -0
@@ -27,3 +27,13 @@ jobs:
27
27
 
28
28
  - name: Publish to PyPI
29
29
  uses: pypa/gh-action-pypi-publish@release/v1
30
+
31
+ - name: Install mcp-publisher
32
+ run: |
33
+ curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_linux_amd64.tar.gz" | tar xz mcp-publisher
34
+
35
+ - name: Authenticate to MCP Registry
36
+ run: ./mcp-publisher login github-oidc
37
+
38
+ - name: Publish to MCP Registry
39
+ run: ./mcp-publisher publish
@@ -201,6 +201,10 @@ cython_debug/
201
201
  .cursorignore
202
202
  .cursorindexingignore
203
203
 
204
+ # Claude Code
205
+ .claude/
206
+ CLAUDE.md
207
+
204
208
  # Marimo
205
209
  marimo/_static/
206
210
  marimo/_lsp/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: m365-roadmap-mcp
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: MCP server for querying the Microsoft 365 Roadmap
5
5
  Project-URL: Homepage, https://github.com/jonnybottles/M365-roadmap-mcp-server
6
6
  Project-URL: Repository, https://github.com/jonnybottles/M365-roadmap-mcp-server
@@ -24,32 +24,19 @@ Requires-Dist: pytest; extra == 'dev'
24
24
  Requires-Dist: pytest-asyncio; extra == 'dev'
25
25
  Description-Content-Type: text/markdown
26
26
 
27
+ ### Disclaimer: This is an independent, self-built project and is not an official Microsoft tool or service.
28
+
27
29
  # M365 Roadmap MCP Server
28
30
 
29
- mcp-name: io.github.jonnybottles.m365-roadmap
31
+ <!-- mcp-name: io.github.jonnybottles/m365-roadmap -->
30
32
 
31
33
  A Python-based MCP (Model Context Protocol) server that enables AI agents to query the Microsoft 365 Roadmap programmatically.
32
34
 
33
- ## Quick Setup
34
-
35
- [![Install in VS Code](https://img.shields.io/badge/Install_in-VS_Code-0078d4?style=flat-square&logo=visualstudiocode)](https://vscode.dev/redirect/mcp/install?name=m365-roadmap-mcp&config=%7B%22type%22%3A%20%22stdio%22%2C%20%22command%22%3A%20%22uvx%22%2C%20%22args%22%3A%20%5B%22m365-roadmap-mcp%22%5D%7D)
36
- [![Install in Cursor](https://img.shields.io/badge/Install_in-Cursor-000000?style=flat-square&logo=cursor)](https://cursor.com/docs/context/mcp)
37
- [![Install in Claude Code](https://img.shields.io/badge/Install_in-Claude_Code-9b6bff?style=flat-square&logo=anthropic)](https://code.claude.com/docs/en/mcp)
38
- [![Install in Copilot CLI](https://img.shields.io/badge/Install_in-Copilot_CLI-28a745?style=flat-square&logo=github)](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/use-copilot-cli)
39
-
40
- > **One-click install:** Click VS Code badge for automatic setup (requires `uv` installed)
41
- > **Manual install:** See instructions below for Cursor, Claude Code, Copilot CLI, or Claude Desktop
42
-
43
- ## Features
35
+ ## Strategic Rationale
44
36
 
45
- Provides a single **`search_roadmap`** tool that handles all M365 roadmap queries. Combine any filters:
37
+ 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.
46
38
 
47
- - **Keyword search** -- Find features by keyword in title/description
48
- - **Product filter** -- Filter by product tag (Teams, SharePoint, etc.)
49
- - **Status filter** -- Filter by status (In development, Rolling out, Launched)
50
- - **Cloud instance filter** -- Filter by cloud instance (GCC, GCC High, DoD)
51
- - **Feature lookup** -- Retrieve full metadata for a specific roadmap ID
52
- - **Recent additions** -- List features added within the last N days
39
+ 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.
53
40
 
54
41
  ## Prompt Examples
55
42
 
@@ -76,6 +63,12 @@ Using `uvx` (requires [uv](https://github.com/astral-sh/uv)):
76
63
  uvx m365-roadmap-mcp
77
64
  ```
78
65
 
66
+ To update to the latest version:
67
+
68
+ ```bash
69
+ uvx m365-roadmap-mcp@latest
70
+ ```
71
+
79
72
  Install uv if you don't have it:
80
73
 
81
74
  ```bash
@@ -90,15 +83,19 @@ Or install with pip (no uv required):
90
83
 
91
84
  ```bash
92
85
  pip install m365-roadmap-mcp
86
+
87
+ # Update to latest
88
+ pip install --upgrade m365-roadmap-mcp
93
89
  ```
90
+ ## Quick Setup
94
91
 
95
- ### From source (for development)
92
+ [![Install in VS Code](https://img.shields.io/badge/Install_in-VS_Code-0078d4?style=flat-square&logo=visualstudiocode)](https://vscode.dev/redirect/mcp/install?name=m365-roadmap-mcp&config=%7B%22type%22%3A%20%22stdio%22%2C%20%22command%22%3A%20%22uvx%22%2C%20%22args%22%3A%20%5B%22m365-roadmap-mcp%22%5D%7D)
93
+ [![Install in Cursor](https://img.shields.io/badge/Install_in-Cursor-000000?style=flat-square&logo=cursor)](https://cursor.com/docs/context/mcp)
94
+ [![Install in Claude Code](https://img.shields.io/badge/Install_in-Claude_Code-9b6bff?style=flat-square&logo=anthropic)](https://code.claude.com/docs/en/mcp)
95
+ [![Install in Copilot CLI](https://img.shields.io/badge/Install_in-Copilot_CLI-28a745?style=flat-square&logo=github)](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/use-copilot-cli)
96
96
 
97
- ```bash
98
- git clone https://github.com/jonnybottles/M365-roadmap-mcp-server.git
99
- cd M365-roadmap-mcp-server
100
- pip install -e ".[dev]"
101
- ```
97
+ > **One-click install:** Click VS Code badge for automatic setup (requires `uv` installed)
98
+ > **Manual install:** See instructions below for Cursor, Claude Code, Copilot CLI, or Claude Desktop
102
99
 
103
100
  ## Client Configuration
104
101
 
@@ -182,6 +179,16 @@ Add to `~/.copilot/mcp-config.json`:
182
179
  }
183
180
  }
184
181
  ```
182
+ ## Features
183
+
184
+ Provides a single **`search_roadmap`** tool that handles all M365 roadmap queries. Combine any filters:
185
+
186
+ - **Keyword search** -- Find features by keyword in title/description
187
+ - **Product filter** -- Filter by product tag (Teams, SharePoint, etc.)
188
+ - **Status filter** -- Filter by status (In development, Rolling out, Launched)
189
+ - **Cloud instance filter** -- Filter by cloud instance (GCC, GCC High, DoD)
190
+ - **Feature lookup** -- Retrieve full metadata for a specific roadmap ID
191
+ - **Recent additions** -- List features added within the last N days
185
192
 
186
193
  ## Data Source
187
194
 
@@ -201,18 +208,6 @@ There is no official Microsoft documentation for this API. It is a public, unaut
201
208
 
202
209
  ---
203
210
 
204
- ## Strategic Rationale
205
-
206
- 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.
207
-
208
- 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.
209
-
210
- ## Development
211
-
212
- ```bash
213
- pytest
214
- ```
215
-
216
211
  ## License
217
212
 
218
213
  MIT
@@ -1,29 +1,16 @@
1
+ ### Disclaimer: This is an independent, self-built project and is not an official Microsoft tool or service.
2
+
1
3
  # M365 Roadmap MCP Server
2
4
 
3
- mcp-name: io.github.jonnybottles.m365-roadmap
5
+ <!-- mcp-name: io.github.jonnybottles/m365-roadmap -->
4
6
 
5
7
  A Python-based MCP (Model Context Protocol) server that enables AI agents to query the Microsoft 365 Roadmap programmatically.
6
8
 
7
- ## Quick Setup
8
-
9
- [![Install in VS Code](https://img.shields.io/badge/Install_in-VS_Code-0078d4?style=flat-square&logo=visualstudiocode)](https://vscode.dev/redirect/mcp/install?name=m365-roadmap-mcp&config=%7B%22type%22%3A%20%22stdio%22%2C%20%22command%22%3A%20%22uvx%22%2C%20%22args%22%3A%20%5B%22m365-roadmap-mcp%22%5D%7D)
10
- [![Install in Cursor](https://img.shields.io/badge/Install_in-Cursor-000000?style=flat-square&logo=cursor)](https://cursor.com/docs/context/mcp)
11
- [![Install in Claude Code](https://img.shields.io/badge/Install_in-Claude_Code-9b6bff?style=flat-square&logo=anthropic)](https://code.claude.com/docs/en/mcp)
12
- [![Install in Copilot CLI](https://img.shields.io/badge/Install_in-Copilot_CLI-28a745?style=flat-square&logo=github)](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/use-copilot-cli)
13
-
14
- > **One-click install:** Click VS Code badge for automatic setup (requires `uv` installed)
15
- > **Manual install:** See instructions below for Cursor, Claude Code, Copilot CLI, or Claude Desktop
16
-
17
- ## Features
9
+ ## Strategic Rationale
18
10
 
19
- Provides a single **`search_roadmap`** tool that handles all M365 roadmap queries. Combine any filters:
11
+ 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.
20
12
 
21
- - **Keyword search** -- Find features by keyword in title/description
22
- - **Product filter** -- Filter by product tag (Teams, SharePoint, etc.)
23
- - **Status filter** -- Filter by status (In development, Rolling out, Launched)
24
- - **Cloud instance filter** -- Filter by cloud instance (GCC, GCC High, DoD)
25
- - **Feature lookup** -- Retrieve full metadata for a specific roadmap ID
26
- - **Recent additions** -- List features added within the last N days
13
+ 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.
27
14
 
28
15
  ## Prompt Examples
29
16
 
@@ -50,6 +37,12 @@ Using `uvx` (requires [uv](https://github.com/astral-sh/uv)):
50
37
  uvx m365-roadmap-mcp
51
38
  ```
52
39
 
40
+ To update to the latest version:
41
+
42
+ ```bash
43
+ uvx m365-roadmap-mcp@latest
44
+ ```
45
+
53
46
  Install uv if you don't have it:
54
47
 
55
48
  ```bash
@@ -64,15 +57,19 @@ Or install with pip (no uv required):
64
57
 
65
58
  ```bash
66
59
  pip install m365-roadmap-mcp
60
+
61
+ # Update to latest
62
+ pip install --upgrade m365-roadmap-mcp
67
63
  ```
64
+ ## Quick Setup
68
65
 
69
- ### From source (for development)
66
+ [![Install in VS Code](https://img.shields.io/badge/Install_in-VS_Code-0078d4?style=flat-square&logo=visualstudiocode)](https://vscode.dev/redirect/mcp/install?name=m365-roadmap-mcp&config=%7B%22type%22%3A%20%22stdio%22%2C%20%22command%22%3A%20%22uvx%22%2C%20%22args%22%3A%20%5B%22m365-roadmap-mcp%22%5D%7D)
67
+ [![Install in Cursor](https://img.shields.io/badge/Install_in-Cursor-000000?style=flat-square&logo=cursor)](https://cursor.com/docs/context/mcp)
68
+ [![Install in Claude Code](https://img.shields.io/badge/Install_in-Claude_Code-9b6bff?style=flat-square&logo=anthropic)](https://code.claude.com/docs/en/mcp)
69
+ [![Install in Copilot CLI](https://img.shields.io/badge/Install_in-Copilot_CLI-28a745?style=flat-square&logo=github)](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/use-copilot-cli)
70
70
 
71
- ```bash
72
- git clone https://github.com/jonnybottles/M365-roadmap-mcp-server.git
73
- cd M365-roadmap-mcp-server
74
- pip install -e ".[dev]"
75
- ```
71
+ > **One-click install:** Click VS Code badge for automatic setup (requires `uv` installed)
72
+ > **Manual install:** See instructions below for Cursor, Claude Code, Copilot CLI, or Claude Desktop
76
73
 
77
74
  ## Client Configuration
78
75
 
@@ -156,6 +153,16 @@ Add to `~/.copilot/mcp-config.json`:
156
153
  }
157
154
  }
158
155
  ```
156
+ ## Features
157
+
158
+ Provides a single **`search_roadmap`** tool that handles all M365 roadmap queries. Combine any filters:
159
+
160
+ - **Keyword search** -- Find features by keyword in title/description
161
+ - **Product filter** -- Filter by product tag (Teams, SharePoint, etc.)
162
+ - **Status filter** -- Filter by status (In development, Rolling out, Launched)
163
+ - **Cloud instance filter** -- Filter by cloud instance (GCC, GCC High, DoD)
164
+ - **Feature lookup** -- Retrieve full metadata for a specific roadmap ID
165
+ - **Recent additions** -- List features added within the last N days
159
166
 
160
167
  ## Data Source
161
168
 
@@ -175,18 +182,6 @@ There is no official Microsoft documentation for this API. It is a public, unaut
175
182
 
176
183
  ---
177
184
 
178
- ## Strategic Rationale
179
-
180
- 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.
181
-
182
- 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.
183
-
184
- ## Development
185
-
186
- ```bash
187
- pytest
188
- ```
189
-
190
185
  ## License
191
186
 
192
187
  MIT
Binary file
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "m365-roadmap-mcp"
7
- version = "0.2.0"
7
+ version = "0.3.0"
8
8
  description = "MCP server for querying the Microsoft 365 Roadmap"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.jonnybottles/m365-roadmap",
4
+ "description": "Query the Microsoft 365 Roadmap from AI agents",
5
+ "title": "M365 Roadmap",
6
+ "repository": {
7
+ "url": "https://github.com/jonnybottles/M365-roadmap-mcp-server",
8
+ "source": "github"
9
+ },
10
+ "version": "0.2.1",
11
+ "packages": [
12
+ {
13
+ "registryType": "pypi",
14
+ "registryBaseUrl": "https://pypi.org",
15
+ "identifier": "m365-roadmap-mcp",
16
+ "version": "0.2.1",
17
+ "runtimeHint": "uvx",
18
+ "transport": {
19
+ "type": "stdio"
20
+ }
21
+ }
22
+ ]
23
+ }
@@ -1,3 +1,3 @@
1
1
  """M365 Roadmap MCP Server - Query the Microsoft 365 Roadmap via MCP."""
2
2
 
3
- __version__ = "0.1.0"
3
+ __version__ = "0.2.1"
@@ -55,6 +55,20 @@ def _parse_item(item: dict) -> RoadmapFeature | None:
55
55
  if "tagName" in c
56
56
  ]
57
57
 
58
+ # Extract release phases from tagsContainer
59
+ release_phases = [
60
+ r["tagName"]
61
+ for r in tags_container.get("releasePhase", [])
62
+ if "tagName" in r
63
+ ]
64
+
65
+ # Extract platforms from tagsContainer
66
+ platforms = [
67
+ p["tagName"]
68
+ for p in tags_container.get("platforms", [])
69
+ if "tagName" in p
70
+ ]
71
+
58
72
  return RoadmapFeature(
59
73
  id=str(item.get("id", "")),
60
74
  title=item.get("title", ""),
@@ -62,7 +76,10 @@ def _parse_item(item: dict) -> RoadmapFeature | None:
62
76
  status=item.get("status"),
63
77
  tags=products,
64
78
  cloud_instances=cloud_instances,
79
+ release_phases=release_phases,
80
+ platforms=platforms,
65
81
  public_disclosure_date=item.get("publicDisclosureAvailabilityDate"),
82
+ public_preview_date=item.get("publicPreviewDate"),
66
83
  created=item.get("created"),
67
84
  modified=item.get("modified"),
68
85
  )
@@ -21,9 +21,21 @@ class RoadmapFeature(BaseModel):
21
21
  default_factory=list,
22
22
  description="Cloud availability (e.g., Worldwide, GCC, GCC High, DoD)",
23
23
  )
24
+ release_phases: list[str] = Field(
25
+ default_factory=list,
26
+ description="Release phases (e.g., General Availability, Preview, Targeted Release)",
27
+ )
28
+ platforms: list[str] = Field(
29
+ default_factory=list,
30
+ description="Target platforms (e.g., Web, Desktop, iOS, Android, Mac)",
31
+ )
24
32
  public_disclosure_date: str | None = Field(
25
33
  default=None,
26
- description="Estimated release date (e.g., August CY2026)",
34
+ description="Estimated rollout start date (e.g., December CY2026)",
35
+ )
36
+ public_preview_date: str | None = Field(
37
+ default=None,
38
+ description="Estimated preview availability date (e.g., July 2026)",
27
39
  )
28
40
  created: str | None = Field(
29
41
  default=None,
@@ -43,7 +55,10 @@ class RoadmapFeature(BaseModel):
43
55
  "status": self.status,
44
56
  "tags": self.tags,
45
57
  "cloud_instances": self.cloud_instances,
58
+ "release_phases": self.release_phases,
59
+ "platforms": self.platforms,
46
60
  "public_disclosure_date": self.public_disclosure_date,
61
+ "public_preview_date": self.public_preview_date,
47
62
  "created": self.created,
48
63
  "modified": self.modified,
49
64
  }
@@ -22,13 +22,20 @@ mcp = FastMCP(
22
22
  "- status: filter by status ('In development', 'Rolling out', 'Launched')\n"
23
23
  "- cloud_instance: filter by cloud instance ('GCC', 'GCC High', 'DoD')\n"
24
24
  "- feature_id: retrieve a single feature by its roadmap ID\n"
25
- "- added_within_days: show only features added within N days\n\n"
25
+ "- added_within_days: show only features added within N days\n"
26
+ "- release_phase: filter by release phase ('General Availability', 'Preview')\n"
27
+ "- platform: filter by platform ('Web', 'Desktop', 'iOS', 'Android', 'Mac')\n"
28
+ "- rollout_date: filter by rollout start date (e.g. 'December 2026')\n"
29
+ "- preview_date: filter by preview availability date (e.g. 'July 2026')\n"
30
+ "- modified_within_days: show only features modified within N days\n\n"
26
31
  "Tips:\n"
27
32
  "- To get feature details, use feature_id with the roadmap ID.\n"
28
33
  "- To check cloud availability, use cloud_instance with a feature_id or "
29
34
  "product filter. The cloud_instances field in each result shows all "
30
35
  "supported instances.\n"
31
- "- To list recent additions, use added_within_days (e.g. 30 for last month)."
36
+ "- To list recent additions, use added_within_days (e.g. 30 for last month).\n"
37
+ "- To filter by release phase or platform, use release_phase or platform filters.\n"
38
+ "- To search by dates, use rollout_date or preview_date with partial date strings."
32
39
  ),
33
40
  )
34
41
 
@@ -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
+ }