m365-roadmap-mcp 0.3.0__py3-none-any.whl → 0.3.1__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.
@@ -27,7 +27,8 @@ mcp = FastMCP(
27
27
  "- platform: filter by platform ('Web', 'Desktop', 'iOS', 'Android', 'Mac')\n"
28
28
  "- rollout_date: filter by rollout start date (e.g. 'December 2026')\n"
29
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"
30
+ "- modified_within_days: show only features modified within N days\n"
31
+ "- include_facets: include taxonomy facets with counts (default: False)\n\n"
31
32
  "Tips:\n"
32
33
  "- To get feature details, use feature_id with the roadmap ID.\n"
33
34
  "- To check cloud availability, use cloud_instance with a feature_id or "
@@ -35,7 +36,8 @@ mcp = FastMCP(
35
36
  "supported instances.\n"
36
37
  "- To list recent additions, use added_within_days (e.g. 30 for last month).\n"
37
38
  "- 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."
39
+ "- To search by dates, use rollout_date or preview_date with partial date strings.\n"
40
+ "- To discover available filter values, use include_facets=True (optionally with limit=0)."
39
41
  ),
40
42
  )
41
43
 
@@ -1,8 +1,55 @@
1
1
  """Search tool for querying and filtering M365 Roadmap features."""
2
2
 
3
+ from collections import Counter
3
4
  from datetime import datetime, timedelta, timezone
4
5
 
5
6
  from ..feeds.m365_api import fetch_features
7
+ from ..models.feature import RoadmapFeature
8
+
9
+
10
+ def compute_facets(features: list[RoadmapFeature]) -> dict:
11
+ """Compute facet counts from a list of features.
12
+
13
+ Args:
14
+ features: List of RoadmapFeature objects to analyze
15
+
16
+ Returns:
17
+ Dictionary with facet categories and counts
18
+ """
19
+ products = Counter()
20
+ statuses = Counter()
21
+ release_phases = Counter()
22
+ platforms = Counter()
23
+ cloud_instances = Counter()
24
+
25
+ for feature in features:
26
+ # Products (from tags)
27
+ for tag in feature.tags:
28
+ products[tag] += 1
29
+
30
+ # Status
31
+ if feature.status:
32
+ statuses[feature.status] += 1
33
+
34
+ # Release phases
35
+ for rp in feature.release_phases:
36
+ release_phases[rp] += 1
37
+
38
+ # Platforms
39
+ for p in feature.platforms:
40
+ platforms[p] += 1
41
+
42
+ # Cloud instances
43
+ for ci in feature.cloud_instances:
44
+ cloud_instances[ci] += 1
45
+
46
+ return {
47
+ "products": [{"name": k, "count": v} for k, v in products.most_common()],
48
+ "statuses": [{"name": k, "count": v} for k, v in statuses.most_common()],
49
+ "release_phases": [{"name": k, "count": v} for k, v in release_phases.most_common()],
50
+ "platforms": [{"name": k, "count": v} for k, v in platforms.most_common()],
51
+ "cloud_instances": [{"name": k, "count": v} for k, v in cloud_instances.most_common()],
52
+ }
6
53
 
7
54
 
8
55
  async def search_roadmap(
@@ -17,6 +64,7 @@ async def search_roadmap(
17
64
  rollout_date: str | None = None,
18
65
  preview_date: str | None = None,
19
66
  modified_within_days: int | None = None,
67
+ include_facets: bool = False,
20
68
  limit: int = 10,
21
69
  ) -> dict:
22
70
  """Search the Microsoft 365 Roadmap for features matching keywords and filters.
@@ -61,6 +109,10 @@ async def search_roadmap(
61
109
  against publicPreviewDate, e.g. "July 2026").
62
110
  modified_within_days: Optional number of days to look back for recently modified
63
111
  features (clamped to 1-365).
112
+ include_facets: When True, includes taxonomy facets (products, statuses,
113
+ release_phases, platforms, cloud_instances) with occurrence counts in
114
+ the response. Use with limit=0 to get only facets without features.
115
+ Facets are computed from matched results after filters are applied.
64
116
  limit: Maximum number of results to return (default: 10, max: 100).
65
117
  Ignored when feature_id is provided.
66
118
 
@@ -69,6 +121,7 @@ async def search_roadmap(
69
121
  - total_found: Number of features matching the filters (before applying limit)
70
122
  - features: List of matching feature objects (up to limit)
71
123
  - filters_applied: Summary of which filters were used
124
+ - facets: (Optional) Dictionary with facet categories and counts when include_facets=True
72
125
  """
73
126
  features = await fetch_features()
74
127
 
@@ -87,8 +140,9 @@ async def search_roadmap(
87
140
  "filters_applied": {"feature_id": feature_id},
88
141
  }
89
142
 
90
- # Clamp limit to reasonable bounds
91
- limit = max(1, min(limit, 100))
143
+ # Clamp limit to reasonable bounds (allow 0 when only requesting facets)
144
+ min_limit = 0 if include_facets else 1
145
+ limit = max(min_limit, min(limit, 100))
92
146
 
93
147
  # Compute recency cutoff if requested
94
148
  cutoff = None
@@ -141,13 +195,25 @@ async def search_roadmap(
141
195
  continue
142
196
 
143
197
  # Rollout date filter (partial match against publicDisclosureAvailabilityDate)
198
+ # API uses "CY" prefix (e.g., "December CY2026") but users typically omit it
144
199
  if rollout_date_lower:
145
- if not feature.public_disclosure_date or rollout_date_lower not in feature.public_disclosure_date.lower():
200
+ if not feature.public_disclosure_date:
201
+ continue
202
+ # Normalize by removing "cy" prefix for comparison
203
+ normalized_date = feature.public_disclosure_date.lower().replace(" cy", " ")
204
+ normalized_query = rollout_date_lower.replace(" cy", " ")
205
+ if normalized_query not in normalized_date:
146
206
  continue
147
207
 
148
208
  # Preview date filter (partial match against publicPreviewDate)
209
+ # API uses "CY" prefix (e.g., "July CY2026") but users typically omit it
149
210
  if preview_date_lower:
150
- if not feature.public_preview_date or preview_date_lower not in feature.public_preview_date.lower():
211
+ if not feature.public_preview_date:
212
+ continue
213
+ # Normalize by removing "cy" prefix for comparison
214
+ normalized_date = feature.public_preview_date.lower().replace(" cy", " ")
215
+ normalized_query = preview_date_lower.replace(" cy", " ")
216
+ if normalized_query not in normalized_date:
151
217
  continue
152
218
 
153
219
  # Keyword search (title + description)
@@ -213,8 +279,15 @@ async def search_roadmap(
213
279
  if not filters_applied:
214
280
  filters_applied["note"] = "No filters applied, returning most recent features"
215
281
 
216
- return {
282
+ # Build response
283
+ result = {
217
284
  "total_found": len(matched),
218
285
  "features": [f.to_dict() for f in matched[:limit]],
219
286
  "filters_applied": filters_applied,
220
287
  }
288
+
289
+ # Add facets if requested (computed from matched results)
290
+ if include_facets:
291
+ result["facets"] = compute_facets(matched)
292
+
293
+ return result
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: m365-roadmap-mcp
3
- Version: 0.3.0
3
+ Version: 0.3.1
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
@@ -189,6 +189,11 @@ Provides a single **`search_roadmap`** tool that handles all M365 roadmap querie
189
189
  - **Cloud instance filter** -- Filter by cloud instance (GCC, GCC High, DoD)
190
190
  - **Feature lookup** -- Retrieve full metadata for a specific roadmap ID
191
191
  - **Recent additions** -- List features added within the last N days
192
+ - **Release phase filter** -- Filter by release phase (General Availability, Preview, Targeted Release)
193
+ - **Platform filter** -- Filter by platform (Web, Desktop, iOS, Android, Mac)
194
+ - **Rollout date filter** -- Filter by rollout start date (e.g., "December 2026", "2026")
195
+ - **Preview date filter** -- Filter by preview availability date (e.g., "July 2026")
196
+ - **Recently modified** -- List features modified within the last N days
192
197
 
193
198
  ## Data Source
194
199
 
@@ -1,6 +1,6 @@
1
1
  m365_roadmap_mcp/__init__.py,sha256=ydNG2ztexAZvnKchX4y1FnQ_atvfc1WGa4E8Y45lPjk,96
2
2
  m365_roadmap_mcp/__main__.py,sha256=D9mYXV4TlB361LHfDDwvxsybz0_7EUsseJ3pZkS9AOo,84
3
- m365_roadmap_mcp/server.py,sha256=jO47eBfPs8SOYySjs9WUR2u4NXChW_I4iCOOQdEjg9A,2785
3
+ m365_roadmap_mcp/server.py,sha256=bRqk4b51sRdfrv1r5g-s4Qc-opVTurHryLLHKjn3RLI,2970
4
4
  m365_roadmap_mcp/feeds/__init__.py,sha256=mVerRhM3n8iwoiupqp4rhqOGOpR2WbtA6MErj5pLG3g,38
5
5
  m365_roadmap_mcp/feeds/m365_api.py,sha256=Elkx_4N42H8v-b93Y9jbt5y2zq6jB8gbWZAjQ3dwWVA,2594
6
6
  m365_roadmap_mcp/models/__init__.py,sha256=Ml_sDvBRyK40Pq4Of0pDExGEBTjyh0QWB4VLu_zKkks,112
@@ -9,9 +9,9 @@ m365_roadmap_mcp/tools/__init__.py,sha256=nsNOC46HR1ElncjDck0CjOyeCkh1ZugH8YOiaC
9
9
  m365_roadmap_mcp/tools/cloud.py,sha256=NuvztbKyMLc9pKZYD98kih23e09dAKnAeaEXZig2ky0,2562
10
10
  m365_roadmap_mcp/tools/details.py,sha256=jgIpi1BhraHPuMT9tQi3d8ikvLF0EZR7p_D7spNlWL0,1067
11
11
  m365_roadmap_mcp/tools/recent.py,sha256=Y9I5SS0I2MsV0i98QKtzXrL14AF5yfEyC3f6RiAxj-g,1709
12
- m365_roadmap_mcp/tools/search.py,sha256=Baoh9Gc7XsBlrsTXIoN_KVPYmEnW6ExMva9Wqad6kg8,9344
13
- m365_roadmap_mcp-0.3.0.dist-info/METADATA,sha256=ZRUqG71qDlw4uZTAwwIwfYZtamgYBSuUnnT04vCJJFs,7502
14
- m365_roadmap_mcp-0.3.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
15
- m365_roadmap_mcp-0.3.0.dist-info/entry_points.txt,sha256=GNzyIHa06s1_7BMZzkI4Dsury7aBgUmOYiSXFGNgE6M,66
16
- m365_roadmap_mcp-0.3.0.dist-info/licenses/LICENSE,sha256=NNt5lEWzqGxqVCVmj-VEeWFxXhtbgCNwFhYcCUffWDI,1071
17
- m365_roadmap_mcp-0.3.0.dist-info/RECORD,,
12
+ m365_roadmap_mcp/tools/search.py,sha256=IaRRHfWF3FixF709oiVgxxtYE4lXHuIWl0HMshFqnNA,12146
13
+ m365_roadmap_mcp-0.3.1.dist-info/METADATA,sha256=kh3J7VH6yEyt6tOFf39rW1mXFG0qH45pRZ9b7y0KU3A,7932
14
+ m365_roadmap_mcp-0.3.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
15
+ m365_roadmap_mcp-0.3.1.dist-info/entry_points.txt,sha256=GNzyIHa06s1_7BMZzkI4Dsury7aBgUmOYiSXFGNgE6M,66
16
+ m365_roadmap_mcp-0.3.1.dist-info/licenses/LICENSE,sha256=NNt5lEWzqGxqVCVmj-VEeWFxXhtbgCNwFhYcCUffWDI,1071
17
+ m365_roadmap_mcp-0.3.1.dist-info/RECORD,,