m365-roadmap-mcp 0.2.1__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.
@@ -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,22 @@ 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"
31
+ "- include_facets: include taxonomy facets with counts (default: False)\n\n"
26
32
  "Tips:\n"
27
33
  "- To get feature details, use feature_id with the roadmap ID.\n"
28
34
  "- To check cloud availability, use cloud_instance with a feature_id or "
29
35
  "product filter. The cloud_instances field in each result shows all "
30
36
  "supported instances.\n"
31
- "- To list recent additions, use added_within_days (e.g. 30 for last month)."
37
+ "- To list recent additions, use added_within_days (e.g. 30 for last month).\n"
38
+ "- To filter by release phase or platform, use release_phase or platform filters.\n"
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)."
32
41
  ),
33
42
  )
34
43
 
@@ -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
+ }
@@ -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(
@@ -12,6 +59,12 @@ async def search_roadmap(
12
59
  cloud_instance: str | None = None,
13
60
  feature_id: str | None = None,
14
61
  added_within_days: int | None = None,
62
+ release_phase: str | None = None,
63
+ platform: str | None = None,
64
+ rollout_date: str | None = None,
65
+ preview_date: str | None = None,
66
+ modified_within_days: int | None = None,
67
+ include_facets: bool = False,
15
68
  limit: int = 10,
16
69
  ) -> dict:
17
70
  """Search the Microsoft 365 Roadmap for features matching keywords and filters.
@@ -29,6 +82,11 @@ async def search_roadmap(
29
82
  - Filter by cloud instance (cloud_instance="GCC High", "DoD", "GCC")
30
83
  - Retrieve a specific feature by ID (feature_id="534606")
31
84
  - List recently added features (added_within_days=30)
85
+ - Filter by release phase (release_phase="General Availability", "Preview")
86
+ - Filter by platform (platform="Web", "iOS", "Android")
87
+ - Filter by rollout date (rollout_date="December 2026")
88
+ - Filter by preview date (preview_date="July 2026")
89
+ - List recently modified features (modified_within_days=7)
32
90
  - Combine any of the above (query="Copilot" + product="Teams" + cloud_instance="GCC")
33
91
 
34
92
  Args:
@@ -43,6 +101,18 @@ async def search_roadmap(
43
101
  added_within_days: Optional number of days to look back for recently added
44
102
  features (clamped to 1–365). Only features with a created date within
45
103
  this window are returned.
104
+ release_phase: Optional release phase filter (case-insensitive partial match).
105
+ platform: Optional platform filter (case-insensitive partial match).
106
+ rollout_date: Optional rollout start date filter (partial string match against
107
+ publicDisclosureAvailabilityDate, e.g. "December 2026").
108
+ preview_date: Optional preview availability date filter (partial string match
109
+ against publicPreviewDate, e.g. "July 2026").
110
+ modified_within_days: Optional number of days to look back for recently modified
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.
46
116
  limit: Maximum number of results to return (default: 10, max: 100).
47
117
  Ignored when feature_id is provided.
48
118
 
@@ -51,6 +121,7 @@ async def search_roadmap(
51
121
  - total_found: Number of features matching the filters (before applying limit)
52
122
  - features: List of matching feature objects (up to limit)
53
123
  - filters_applied: Summary of which filters were used
124
+ - facets: (Optional) Dictionary with facet categories and counts when include_facets=True
54
125
  """
55
126
  features = await fetch_features()
56
127
 
@@ -69,8 +140,9 @@ async def search_roadmap(
69
140
  "filters_applied": {"feature_id": feature_id},
70
141
  }
71
142
 
72
- # Clamp limit to reasonable bounds
73
- 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))
74
146
 
75
147
  # Compute recency cutoff if requested
76
148
  cutoff = None
@@ -78,11 +150,21 @@ async def search_roadmap(
78
150
  added_within_days = max(1, min(added_within_days, 365))
79
151
  cutoff = datetime.now(timezone.utc) - timedelta(days=added_within_days)
80
152
 
153
+ # Compute modified cutoff if requested
154
+ modified_cutoff = None
155
+ if modified_within_days is not None:
156
+ modified_within_days = max(1, min(modified_within_days, 365))
157
+ modified_cutoff = datetime.now(timezone.utc) - timedelta(days=modified_within_days)
158
+
81
159
  # Prepare lowercase values for case-insensitive matching
82
160
  query_lower = query.lower() if query else None
83
161
  product_lower = product.lower() if product else None
84
162
  status_lower = status.lower() if status else None
85
163
  cloud_lower = cloud_instance.lower() if cloud_instance else None
164
+ release_phase_lower = release_phase.lower() if release_phase else None
165
+ platform_lower = platform.lower() if platform else None
166
+ rollout_date_lower = rollout_date.lower() if rollout_date else None
167
+ preview_date_lower = preview_date.lower() if preview_date else None
86
168
 
87
169
  # Apply all filters
88
170
  matched = []
@@ -102,6 +184,38 @@ async def search_roadmap(
102
184
  if not any(cloud_lower in ci.lower() for ci in feature.cloud_instances):
103
185
  continue
104
186
 
187
+ # Release phase filter (partial match)
188
+ if release_phase_lower:
189
+ if not any(release_phase_lower in rp.lower() for rp in feature.release_phases):
190
+ continue
191
+
192
+ # Platform filter (partial match)
193
+ if platform_lower:
194
+ if not any(platform_lower in p.lower() for p in feature.platforms):
195
+ continue
196
+
197
+ # Rollout date filter (partial match against publicDisclosureAvailabilityDate)
198
+ # API uses "CY" prefix (e.g., "December CY2026") but users typically omit it
199
+ if rollout_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:
206
+ continue
207
+
208
+ # Preview date filter (partial match against publicPreviewDate)
209
+ # API uses "CY" prefix (e.g., "July CY2026") but users typically omit it
210
+ if 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:
217
+ continue
218
+
105
219
  # Keyword search (title + description)
106
220
  if query_lower:
107
221
  if (
@@ -123,6 +237,19 @@ async def search_roadmap(
123
237
  except (ValueError, TypeError):
124
238
  continue
125
239
 
240
+ # Recency filter (modified_within_days)
241
+ if modified_cutoff is not None:
242
+ if not feature.modified:
243
+ continue
244
+ try:
245
+ modified_dt = datetime.fromisoformat(feature.modified)
246
+ if modified_dt.tzinfo is None:
247
+ modified_dt = modified_dt.replace(tzinfo=timezone.utc)
248
+ if modified_dt < modified_cutoff:
249
+ continue
250
+ except (ValueError, TypeError):
251
+ continue
252
+
126
253
  matched.append(feature)
127
254
 
128
255
  # Build filters summary
@@ -138,11 +265,29 @@ async def search_roadmap(
138
265
  if added_within_days is not None:
139
266
  filters_applied["added_within_days"] = added_within_days
140
267
  filters_applied["cutoff_date"] = cutoff.isoformat()
268
+ if modified_within_days is not None:
269
+ filters_applied["modified_within_days"] = modified_within_days
270
+ filters_applied["modified_cutoff_date"] = modified_cutoff.isoformat()
271
+ if release_phase:
272
+ filters_applied["release_phase"] = release_phase
273
+ if platform:
274
+ filters_applied["platform"] = platform
275
+ if rollout_date:
276
+ filters_applied["rollout_date"] = rollout_date
277
+ if preview_date:
278
+ filters_applied["preview_date"] = preview_date
141
279
  if not filters_applied:
142
280
  filters_applied["note"] = "No filters applied, returning most recent features"
143
281
 
144
- return {
282
+ # Build response
283
+ result = {
145
284
  "total_found": len(matched),
146
285
  "features": [f.to_dict() for f in matched[:limit]],
147
286
  "filters_applied": filters_applied,
148
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.2.1
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
@@ -24,6 +24,8 @@ 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
31
  <!-- mcp-name: io.github.jonnybottles/m365-roadmap -->
@@ -187,6 +189,11 @@ Provides a single **`search_roadmap`** tool that handles all M365 roadmap querie
187
189
  - **Cloud instance filter** -- Filter by cloud instance (GCC, GCC High, DoD)
188
190
  - **Feature lookup** -- Retrieve full metadata for a specific roadmap ID
189
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
190
197
 
191
198
  ## Data Source
192
199
 
@@ -0,0 +1,17 @@
1
+ m365_roadmap_mcp/__init__.py,sha256=ydNG2ztexAZvnKchX4y1FnQ_atvfc1WGa4E8Y45lPjk,96
2
+ m365_roadmap_mcp/__main__.py,sha256=D9mYXV4TlB361LHfDDwvxsybz0_7EUsseJ3pZkS9AOo,84
3
+ m365_roadmap_mcp/server.py,sha256=bRqk4b51sRdfrv1r5g-s4Qc-opVTurHryLLHKjn3RLI,2970
4
+ m365_roadmap_mcp/feeds/__init__.py,sha256=mVerRhM3n8iwoiupqp4rhqOGOpR2WbtA6MErj5pLG3g,38
5
+ m365_roadmap_mcp/feeds/m365_api.py,sha256=Elkx_4N42H8v-b93Y9jbt5y2zq6jB8gbWZAjQ3dwWVA,2594
6
+ m365_roadmap_mcp/models/__init__.py,sha256=Ml_sDvBRyK40Pq4Of0pDExGEBTjyh0QWB4VLu_zKkks,112
7
+ m365_roadmap_mcp/models/feature.py,sha256=XZlFbwR5s3Unq4JylOQ9YbJv6KLRxldFyDwZGjytK_M,2302
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=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,,
@@ -1,14 +0,0 @@
1
- m365_roadmap_mcp/__init__.py,sha256=ydNG2ztexAZvnKchX4y1FnQ_atvfc1WGa4E8Y45lPjk,96
2
- m365_roadmap_mcp/__main__.py,sha256=D9mYXV4TlB361LHfDDwvxsybz0_7EUsseJ3pZkS9AOo,84
3
- m365_roadmap_mcp/server.py,sha256=U-vSRQjxmQVpySifzbPFM_eHdZn0cmYygZnoZWeDW0E,2181
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/search.py,sha256=yKfWtQ1LzPJSa96OlM8PQBkbDzuW6SPVjmCLAWtFa9U,5817
10
- m365_roadmap_mcp-0.2.1.dist-info/METADATA,sha256=p_WX6PvRNjlvleOWhDRViZI1NNZcUXjdPdenICCqT54,7392
11
- m365_roadmap_mcp-0.2.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
12
- m365_roadmap_mcp-0.2.1.dist-info/entry_points.txt,sha256=GNzyIHa06s1_7BMZzkI4Dsury7aBgUmOYiSXFGNgE6M,66
13
- m365_roadmap_mcp-0.2.1.dist-info/licenses/LICENSE,sha256=NNt5lEWzqGxqVCVmj-VEeWFxXhtbgCNwFhYcCUffWDI,1071
14
- m365_roadmap_mcp-0.2.1.dist-info/RECORD,,