added mcp docs

This commit is contained in:
Oliver Kieselbach
2026-03-30 18:05:35 +02:00
parent 705555369f
commit eccb8cf945
9 changed files with 518 additions and 19 deletions
@@ -1 +1 @@
723
724
@@ -1,7 +1,9 @@
"use client";
import { useMemo } from "react";
import { usePageSections } from "../../hooks/usePageSections";
import { PageSectionItem } from "../../contexts/SidebarContext";
import { useAuth } from "../../contexts/AuthContext";
import { NAV_SECTIONS } from "./docsNavSections";
import {
KeyIcon,
@@ -15,6 +17,7 @@ import {
SparklesIcon,
CodeBracketIcon,
QuestionMarkCircleIcon,
CommandLineIcon,
} from "../../lib/sidebarIcons";
const SECTION_ICONS: Record<string, React.ReactNode> = {
@@ -29,16 +32,25 @@ const SECTION_ICONS: Record<string, React.ReactNode> = {
"analyze-rules": <SparklesIcon />,
"ime-log-patterns": <CodeBracketIcon />,
"faq": <QuestionMarkCircleIcon />,
"mcp-integration": <CommandLineIcon />,
};
const docsItems: PageSectionItem[] = NAV_SECTIONS.map((s) => ({
id: s.id,
label: s.label,
icon: SECTION_ICONS[s.id],
href: `/docs/${s.id}`,
}));
export function DocsSidebar({ children }: { children: React.ReactNode }) {
const { user } = useAuth();
const docsItems: PageSectionItem[] = useMemo(
() =>
NAV_SECTIONS
.filter((s) => !s.requiresMcpAccess || user?.hasMcpAccess)
.map((s) => ({
id: s.id,
label: s.label,
icon: SECTION_ICONS[s.id],
href: `/docs/${s.id}`,
})),
[user?.hasMcpAccess],
);
usePageSections(docsItems, "Contents", "route");
return (
@@ -0,0 +1,39 @@
"use client";
import dynamic from "next/dynamic";
import type { ComponentType } from "react";
import { useAuth } from "../../contexts/AuthContext";
const MCP_SECTIONS: Record<string, ComponentType> = {
"mcp-integration": dynamic(() => import("./sections/SectionMcpIntegration").then((m) => ({ default: m.SectionMcpIntegration }))),
};
/**
* Client-side gate for MCP-only docs sections.
* Only loads the section content via dynamic import AFTER verifying auth + MCP access.
* Returns null (renders nothing) for unauthenticated or non-MCP users —
* the server-side page.tsx calls notFound() for unknown sections,
* and this component handles the "known but unauthorized" case.
*/
export function McpDocsGate({ sectionId }: { sectionId: string }) {
const { user, isLoading, isAuthenticated } = useAuth();
if (isLoading) {
return (
<div className="flex justify-center py-16">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" />
</div>
);
}
if (!isAuthenticated || !user?.hasMcpAccess) {
// Return empty — indistinguishable from a non-existent page.
// The sidebar already hides this section for unauthorized users.
return null;
}
const Section = MCP_SECTIONS[sectionId];
if (!Section) return null;
return <Section />;
}
@@ -1,6 +1,7 @@
import { notFound } from "next/navigation";
import type { Metadata } from "next";
import { NAV_SECTIONS, type SectionId } from "../docsNavSections";
import { McpDocsGate } from "../McpDocsGate";
import { SectionPrivatePreview } from "../sections/SectionPrivatePreview";
import { SectionGeneral } from "../sections/SectionGeneral";
import { SectionOverview } from "../sections/SectionOverview";
@@ -13,7 +14,7 @@ import { SectionAnalyzeRules } from "../sections/SectionAnalyzeRules";
import { SectionImeLogPatterns } from "../sections/SectionImeLogPatterns";
import { SectionFaq } from "../sections/SectionFaq";
const SECTION_COMPONENTS: Record<SectionId, React.ComponentType> = {
const SECTION_COMPONENTS: Record<string, React.ComponentType> = {
"private-preview": SectionPrivatePreview,
"general": SectionGeneral,
"overview": SectionOverview,
@@ -27,6 +28,10 @@ const SECTION_COMPONENTS: Record<SectionId, React.ComponentType> = {
"faq": SectionFaq,
};
function isMcpSection(id: string): boolean {
return NAV_SECTIONS.some((s) => s.id === id && s.requiresMcpAccess);
}
export function generateStaticParams() {
return NAV_SECTIONS.map((s) => ({ section: s.id }));
}
@@ -58,19 +63,23 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
export default async function DocsSectionPage({ params }: Props) {
const { section } = await params;
const SectionContent = SECTION_COMPONENTS[section as SectionId];
if (!SectionContent) notFound();
const nav = NAV_SECTIONS.find((s) => s.id === section);
if (!nav) notFound();
// MCP-only sections are rendered entirely client-side via McpDocsGate
// (dynamic import — no HTML shipped until auth check passes).
const isMcp = isMcpSection(section);
if (!isMcp && !SECTION_COMPONENTS[section]) notFound();
const SectionContent = isMcp ? null : SECTION_COMPONENTS[section]!;
const breadcrumbJsonLd = {
"@context": "https://schema.org",
"@type": "BreadcrumbList",
itemListElement: [
{ "@type": "ListItem", position: 1, name: "Home", item: "https://www.autopilotmonitor.com" },
{ "@type": "ListItem", position: 2, name: "Docs", item: "https://www.autopilotmonitor.com/docs" },
...(nav
? [{ "@type": "ListItem", position: 3, name: nav.label, item: `https://www.autopilotmonitor.com/docs/${section}` }]
: []),
{ "@type": "ListItem", position: 3, name: nav.label, item: `https://www.autopilotmonitor.com/docs/${section}` },
],
};
@@ -80,7 +89,7 @@ export default async function DocsSectionPage({ params }: Props) {
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbJsonLd) }}
/>
<SectionContent />
{isMcp ? <McpDocsGate sectionId={section} /> : SectionContent && <SectionContent />}
</>
);
}
@@ -1,4 +1,11 @@
export const NAV_SECTIONS = [
interface NavSection {
readonly id: string;
readonly label: string;
readonly description: string;
readonly requiresMcpAccess?: true;
}
export const NAV_SECTIONS: readonly NavSection[] = [
{ id: "private-preview", label: "Private Preview", description: "Join the Autopilot Monitor private preview for early access. Learn about onboarding steps, requirements, and how to start monitoring Windows Autopilot enrollments." },
{ id: "overview", label: "Overview", description: "Explore the Autopilot Monitor architecture and core components. Learn how the agent, backend, and web dashboard work together to monitor Windows Autopilot enrollments." },
{ id: "general", label: "General", description: "Learn general Autopilot Monitor concepts including Admin Mode, session lifecycle statuses, user roles, and how enrollment data flows through the platform." },
@@ -10,6 +17,7 @@ export const NAV_SECTIONS = [
{ id: "analyze-rules", label: "Analyze Rules", description: "Set up analyze rules to automatically evaluate Windows Autopilot enrollments. Define conditions, severity levels, and custom logic to detect issues in real time." },
{ id: "ime-log-patterns", label: "IME Log Patterns", description: "Define regex patterns for parsing the Intune Management Extension (IME) log into structured events. Customize how Autopilot Monitor extracts log entries." },
{ id: "faq", label: "FAQ", description: "Frequently asked questions about Autopilot Monitor — covering setup, agent behavior, troubleshooting common issues, and tips for getting the most out of the platform." },
{ id: "mcp-integration", label: "MCP Integration", description: "Connect AI assistants to Autopilot Monitor via Model Context Protocol. Configure MCP clients, explore available tools, and learn how to query enrollment data with natural language.", requiresMcpAccess: true },
] as const;
export type SectionId = (typeof NAV_SECTIONS)[number]["id"];
export type SectionId = NavSection["id"];
@@ -0,0 +1,417 @@
"use client";
export function SectionMcpIntegration() {
return (
<section className="space-y-10">
{/* Header */}
<div className="bg-white rounded-lg shadow-md p-8">
<div className="flex items-center space-x-3 mb-4">
<svg className="w-8 h-8 text-blue-600 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="m6.75 7.5 3 2.25-3 2.25m4.5 0h3m-9 8.25h13.5A2.25 2.25 0 0 0 21 18V6a2.25 2.25 0 0 0-2.25-2.25H5.25A2.25 2.25 0 0 0 3 6v12a2.25 2.25 0 0 0 2.25 2.25Z" />
</svg>
<h2 className="text-2xl font-bold text-gray-900">MCP Integration</h2>
</div>
<p className="text-gray-700 leading-relaxed mb-6">
Autopilot Monitor exposes a <strong>Model Context Protocol (MCP)</strong> server that lets AI assistants
query enrollment data, analyze sessions, and search across your fleet using natural language.
Connect your preferred MCP client &mdash; such as Claude Desktop, VS Code with Claude, or any
MCP-compatible tool &mdash; and interact with your enrollment data conversationally.
</p>
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
<div className="bg-blue-50 rounded-lg p-4">
<p className="font-semibold text-blue-900 mb-1">Natural Language Queries</p>
<p className="text-sm text-blue-800">Ask questions about enrollments, failures, and device health in plain language.</p>
</div>
<div className="bg-indigo-50 rounded-lg p-4">
<p className="font-semibold text-indigo-900 mb-1">22 Specialized Tools</p>
<p className="text-sm text-indigo-800">Search sessions, analyze failures, query metrics, and explore device properties.</p>
</div>
<div className="bg-violet-50 rounded-lg p-4">
<p className="font-semibold text-violet-900 mb-1">Secure &amp; Scoped</p>
<p className="text-sm text-violet-800">Uses your existing auth token &mdash; data access is scoped to your tenant.</p>
</div>
</div>
</div>
{/* Architecture */}
<div className="bg-white rounded-lg shadow-md p-8">
<h3 className="text-xl font-semibold text-gray-900 mb-4">How It Works</h3>
<p className="text-gray-700 leading-relaxed mb-4">
The MCP server acts as a bridge between your AI assistant and the Autopilot Monitor backend.
Your existing authentication token is passed through &mdash; the MCP server never stores credentials.
</p>
<div className="bg-gray-50 rounded-lg p-6 font-mono text-sm text-gray-700">
<div className="flex items-center justify-center gap-3 flex-wrap">
<span className="bg-blue-100 text-blue-800 px-3 py-1.5 rounded-md">AI Client</span>
<span className="text-gray-400">&rarr;</span>
<span className="bg-indigo-100 text-indigo-800 px-3 py-1.5 rounded-md">MCP Server</span>
<span className="text-gray-400">&rarr;</span>
<span className="bg-violet-100 text-violet-800 px-3 py-1.5 rounded-md">Backend API</span>
<span className="text-gray-400">&rarr;</span>
<span className="bg-gray-200 text-gray-800 px-3 py-1.5 rounded-md">Your Data</span>
</div>
<p className="text-center text-xs text-gray-500 mt-3">Bearer token is forwarded with every request &mdash; no separate service credentials needed</p>
</div>
</div>
{/* Prerequisites */}
<div className="bg-white rounded-lg shadow-md p-8">
<h3 className="text-xl font-semibold text-gray-900 mb-4">Prerequisites</h3>
<ul className="space-y-3">
<li className="flex items-start gap-3">
<span className="mt-0.5 flex-shrink-0 w-6 h-6 bg-blue-100 text-blue-700 rounded-full flex items-center justify-center text-sm font-medium">1</span>
<div>
<p className="font-medium text-gray-900">Autopilot Monitor account with MCP access</p>
<p className="text-sm text-gray-600">Your administrator must enable MCP for your account. MCP access is managed under Settings &rarr; MCP Users.</p>
</div>
</li>
<li className="flex items-start gap-3">
<span className="mt-0.5 flex-shrink-0 w-6 h-6 bg-blue-100 text-blue-700 rounded-full flex items-center justify-center text-sm font-medium">2</span>
<div>
<p className="font-medium text-gray-900">An MCP-compatible AI client</p>
<p className="text-sm text-gray-600">Claude Desktop, VS Code with Claude extension, or any client supporting Streamable HTTP transport.</p>
</div>
</li>
</ul>
</div>
{/* Client Configuration */}
<div className="bg-white rounded-lg shadow-md p-8">
<h3 className="text-xl font-semibold text-gray-900 mb-4">Client Configuration</h3>
<p className="text-gray-700 leading-relaxed mb-4">
The MCP server uses <strong>Streamable HTTP</strong> transport with OAuth Bearer token authentication.
Add the following configuration to your MCP client:
</p>
<div className="space-y-6">
{/* Server URL */}
<div>
<h4 className="text-sm font-semibold text-gray-700 mb-2">Server URL</h4>
<div className="bg-gray-900 rounded-lg p-4 font-mono text-sm text-green-400 overflow-x-auto">
https://autopilotmonitor-mcp.azurewebsites.net/mcp
</div>
</div>
{/* Claude Desktop */}
<div>
<h4 className="text-sm font-semibold text-gray-700 mb-2">Claude Desktop</h4>
<p className="text-sm text-gray-600 mb-2">
In Claude Desktop, go to <strong>Settings &rarr; MCP Servers &rarr; Add</strong> and enter the server URL above.
OAuth authentication will be handled automatically via the browser.
</p>
</div>
{/* VS Code */}
<div>
<h4 className="text-sm font-semibold text-gray-700 mb-2">VS Code with Claude Extension</h4>
<p className="text-sm text-gray-600 mb-2">
Add the server to your <code className="bg-gray-100 px-1.5 py-0.5 rounded text-xs">.vscode/mcp.json</code> or user settings:
</p>
<div className="bg-gray-900 rounded-lg p-4 font-mono text-sm text-green-400 overflow-x-auto whitespace-pre">
{`{
"servers": {
"autopilot-monitor": {
"type": "http",
"url": "https://autopilotmonitor-mcp.azurewebsites.net/mcp"
}
}
}`}
</div>
</div>
{/* Verification */}
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
<p className="text-sm font-medium text-blue-900 mb-1">Verify your connection</p>
<p className="text-sm text-blue-800">
After configuring the server, ask your AI assistant: <em>&quot;List all available tools from Autopilot Monitor&quot;</em>.
You should see 16+ tools listed. If authentication fails, ensure your MCP access has been enabled by an administrator.
</p>
</div>
</div>
</div>
{/* Available Tools */}
<div className="bg-white rounded-lg shadow-md p-8">
<h3 className="text-xl font-semibold text-gray-900 mb-6">Available Tools</h3>
{/* Search & Discovery */}
<div className="mb-8">
<h4 className="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span className="w-2 h-2 rounded-full bg-blue-500" />
Search &amp; Discovery
</h4>
<div className="overflow-x-auto">
<table className="min-w-full text-sm">
<thead>
<tr className="border-b border-gray-200">
<th className="text-left py-2 pr-4 font-medium text-gray-700 w-1/3">Tool</th>
<th className="text-left py-2 font-medium text-gray-700">Description</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-100">
<tr>
<td className="py-2 pr-4 font-mono text-xs text-blue-700">search_sessions</td>
<td className="py-2 text-gray-600">Search enrollment sessions by status, device properties, serial number, manufacturer, model, OS build, geo location, and more. Supports dynamic device property filters with dot notation.</td>
</tr>
<tr>
<td className="py-2 pr-4 font-mono text-xs text-blue-700">search_sessions_by_event</td>
<td className="py-2 text-gray-600">Find sessions containing a specific event type (e.g. app install failure, phase transition, error). Use the <code className="bg-gray-100 px-1 rounded text-xs">event_types</code> resource for valid values.</td>
</tr>
<tr>
<td className="py-2 pr-4 font-mono text-xs text-blue-700">search_sessions_by_cve</td>
<td className="py-2 text-gray-600">Find devices affected by a specific CVE. Returns sessions where the vulnerability was detected during enrollment.</td>
</tr>
<tr>
<td className="py-2 pr-4 font-mono text-xs text-blue-700">search_events_semantic</td>
<td className="py-2 text-gray-600">Fuzzy/semantic search across event messages. Useful when you don&apos;t know the exact event type but can describe what happened.</td>
</tr>
<tr>
<td className="py-2 pr-4 font-mono text-xs text-blue-700">search_knowledge</td>
<td className="py-2 text-gray-600">Semantic search over analysis rules, gather rules, and IME log patterns. Helps the AI understand your configured rules and diagnostics.</td>
</tr>
</tbody>
</table>
</div>
</div>
{/* Session Analysis */}
<div className="mb-8">
<h4 className="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span className="w-2 h-2 rounded-full bg-indigo-500" />
Session Analysis
</h4>
<div className="overflow-x-auto">
<table className="min-w-full text-sm">
<thead>
<tr className="border-b border-gray-200">
<th className="text-left py-2 pr-4 font-medium text-gray-700 w-1/3">Tool</th>
<th className="text-left py-2 font-medium text-gray-700">Description</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-100">
<tr>
<td className="py-2 pr-4 font-mono text-xs text-indigo-700">get_session</td>
<td className="py-2 text-gray-600">Full session details with all device metadata. Optionally includes AI rule analysis with failure explanations and remediation suggestions.</td>
</tr>
<tr>
<td className="py-2 pr-4 font-mono text-xs text-indigo-700">get_session_events</td>
<td className="py-2 text-gray-600">Event timeline for a session. Filter by event type, severity, or source (app name) for focused root cause analysis.</td>
</tr>
<tr>
<td className="py-2 pr-4 font-mono text-xs text-indigo-700">get_session_summary</td>
<td className="py-2 text-gray-600">Concise structured summary: overview, key events (noise filtered), rule analysis, and aggregate stats. Best starting point for session investigation.</td>
</tr>
</tbody>
</table>
</div>
</div>
{/* Metrics & Observability */}
<div className="mb-8">
<h4 className="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span className="w-2 h-2 rounded-full bg-emerald-500" />
Metrics &amp; Observability
</h4>
<div className="overflow-x-auto">
<table className="min-w-full text-sm">
<thead>
<tr className="border-b border-gray-200">
<th className="text-left py-2 pr-4 font-medium text-gray-700 w-1/3">Tool</th>
<th className="text-left py-2 font-medium text-gray-700">Description</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-100">
<tr>
<td className="py-2 pr-4 font-mono text-xs text-emerald-700">get_metrics</td>
<td className="py-2 text-gray-600">Aggregated enrollment metrics: failure rates, slowest/most-failing apps, session counts. Supports 7, 30, or 90 day windows.</td>
</tr>
<tr>
<td className="py-2 pr-4 font-mono text-xs text-emerald-700">get_geographic_metrics</td>
<td className="py-2 text-gray-600">Geographic distribution of enrollments with performance comparisons across locations.</td>
</tr>
<tr>
<td className="py-2 pr-4 font-mono text-xs text-emerald-700">get_geographic_sessions</td>
<td className="py-2 text-gray-600">Drill into a specific location by country, region, or city to see enrollment details.</td>
</tr>
<tr>
<td className="py-2 pr-4 font-mono text-xs text-emerald-700">get_usage_metrics</td>
<td className="py-2 text-gray-600">Platform usage statistics: active tenants, feature adoption, and usage trends.</td>
</tr>
<tr>
<td className="py-2 pr-4 font-mono text-xs text-emerald-700">get_api_usage</td>
<td className="py-2 text-gray-600">Your MCP/API usage per endpoint per day. Monitor your own consumption and rate limits.</td>
</tr>
</tbody>
</table>
</div>
</div>
{/* Device Management & Admin */}
<div className="mb-8">
<h4 className="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span className="w-2 h-2 rounded-full bg-amber-500" />
Device Management &amp; Administration
</h4>
<div className="overflow-x-auto">
<table className="min-w-full text-sm">
<thead>
<tr className="border-b border-gray-200">
<th className="text-left py-2 pr-4 font-medium text-gray-700 w-1/3">Tool</th>
<th className="text-left py-2 font-medium text-gray-700">Description</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-100">
<tr>
<td className="py-2 pr-4 font-mono text-xs text-amber-700">list_blocked_devices</td>
<td className="py-2 text-gray-600">List devices currently blocked from enrolling in your tenant.</td>
</tr>
<tr>
<td className="py-2 pr-4 font-mono text-xs text-amber-700">get_audit_logs</td>
<td className="py-2 text-gray-600">Audit trail of configuration changes, device blocks, and user management actions. Returns up to 100 most recent entries.</td>
</tr>
</tbody>
</table>
</div>
</div>
{/* Raw Data */}
<div>
<h4 className="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span className="w-2 h-2 rounded-full bg-gray-500" />
Raw Data Queries
</h4>
<div className="overflow-x-auto">
<table className="min-w-full text-sm">
<thead>
<tr className="border-b border-gray-200">
<th className="text-left py-2 pr-4 font-medium text-gray-700 w-1/3">Tool</th>
<th className="text-left py-2 font-medium text-gray-700">Description</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-100">
<tr>
<td className="py-2 pr-4 font-mono text-xs text-gray-700">query_raw_events</td>
<td className="py-2 text-gray-600">Query raw event data with flexible filters. Requires your tenant ID. Useful for custom analysis beyond the high-level tools.</td>
</tr>
<tr>
<td className="py-2 pr-4 font-mono text-xs text-gray-700">query_raw_sessions</td>
<td className="py-2 text-gray-600">Query raw session data with field projection. Select specific fields to reduce response size for bulk analysis.</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
{/* Resources */}
<div className="bg-white rounded-lg shadow-md p-8">
<h3 className="text-xl font-semibold text-gray-900 mb-4">Resources</h3>
<p className="text-gray-700 leading-relaxed mb-4">
The MCP server exposes two discovery resources that help the AI assistant understand available data:
</p>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="border border-gray-200 rounded-lg p-4">
<p className="font-mono text-sm text-blue-700 mb-1">event_types</p>
<p className="text-sm text-gray-600">
Catalog of all enrollment event type strings, organized by category (phase events, app events,
network events, device info, errors, vulnerabilities). The AI consults this before searching by event type.
</p>
</div>
<div className="border border-gray-200 rounded-lg p-4">
<p className="font-mono text-sm text-blue-700 mb-1">device_properties</p>
<p className="text-sm text-gray-600">
Searchable device property keys using dot notation (e.g.{" "}
<code className="bg-gray-100 px-1 rounded text-xs">tpm_status.specVersion</code>,{" "}
<code className="bg-gray-100 px-1 rounded text-xs">hardware_spec.ramTotalGB</code>).
Covers TPM, Secure Boot, BitLocker, Autopilot profile, hardware specs, network, and AAD join status.
</p>
</div>
</div>
</div>
{/* Example Workflows */}
<div className="bg-white rounded-lg shadow-md p-8">
<h3 className="text-xl font-semibold text-gray-900 mb-4">Example Workflows</h3>
<p className="text-gray-700 leading-relaxed mb-6">
Here are some examples of what you can ask your AI assistant once connected. The AI will automatically
select the right tools and chain multiple queries together to answer your question.
</p>
<div className="space-y-4">
<ExampleWorkflow
prompt="Show me all failed enrollments from the last 24 hours"
description="Uses search_sessions with status=Failed and startedAfter filter. Returns device names, failure reasons, and session IDs for further investigation."
tools={["search_sessions"]}
/>
<ExampleWorkflow
prompt="Which devices are affected by CVE-2024-30078?"
description="Uses search_sessions_by_cve to find sessions where the vulnerability was detected. Shows affected device details and enrollment status."
tools={["search_sessions_by_cve"]}
/>
<ExampleWorkflow
prompt="Summarize session abc-123 and suggest fixes"
description="Uses get_session_summary for a concise overview with filtered key events, then includes rule analysis results with probable causes and remediation steps."
tools={["get_session_summary"]}
/>
<ExampleWorkflow
prompt="Compare enrollment performance between Germany and the US"
description="Uses get_geographic_metrics to retrieve per-country stats, then compares failure rates, average durations, and session counts across locations."
tools={["get_geographic_metrics"]}
/>
<ExampleWorkflow
prompt="Which apps cause the most timeouts during enrollment?"
description="Uses get_metrics to retrieve the slowest and most-failing apps, ranked by failure count and average install duration."
tools={["get_metrics"]}
/>
<ExampleWorkflow
prompt="Show me the event timeline for device DESKTOP-ABC123"
description="First uses search_sessions to find the session by device name, then get_session_events to retrieve the full event timeline with severity filtering."
tools={["search_sessions", "get_session_events"]}
/>
<ExampleWorkflow
prompt="Find enrollments with BitLocker issues"
description="Uses search_events_semantic with a natural language query to find sessions mentioning BitLocker errors, or search_sessions with deviceProperties filter on bitlocker_status."
tools={["search_events_semantic", "search_sessions"]}
/>
<ExampleWorkflow
prompt="How has the failure rate changed this week?"
description="Uses get_metrics with a 7-day window to show current failure rates, then compares with 30-day metrics to identify trends."
tools={["get_metrics"]}
/>
</div>
</div>
{/* Rate Limits */}
<div className="bg-white rounded-lg shadow-md p-8">
<h3 className="text-xl font-semibold text-gray-900 mb-4">Rate Limits</h3>
<p className="text-gray-700 leading-relaxed mb-4">
MCP requests are rate-limited per user to ensure fair usage. The default limit is <strong>60 requests per minute</strong>.
Your administrator may adjust this via usage plans. You can check your current usage with the{" "}
<code className="bg-gray-100 px-1.5 py-0.5 rounded text-xs">get_api_usage</code> tool.
</p>
<div className="bg-amber-50 border border-amber-200 rounded-lg p-4">
<p className="text-sm text-amber-800">
If you hit the rate limit, the server returns HTTP 429. Your AI client will typically retry automatically
after the cooldown period.
</p>
</div>
</div>
</section>
);
}
function ExampleWorkflow({ prompt, description, tools }: { prompt: string; description: string; tools: string[] }) {
return (
<div className="border border-gray-200 rounded-lg p-4 hover:border-blue-200 transition-colors">
<p className="font-medium text-gray-900 mb-1">&quot;{prompt}&quot;</p>
<p className="text-sm text-gray-600 mb-2">{description}</p>
<div className="flex flex-wrap gap-1.5">
{tools.map((tool) => (
<span key={tool} className="inline-flex items-center px-2 py-0.5 rounded text-xs font-mono bg-blue-50 text-blue-700 border border-blue-100">
{tool}
</span>
))}
</div>
</div>
);
}
@@ -270,3 +270,11 @@ export function KeyIcon({ className = "w-5 h-5" }: IconProps) {
</svg>
);
}
export function CommandLineIcon({ className = "w-5 h-5" }: IconProps) {
return (
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
<path strokeLinecap="round" strokeLinejoin="round" d="m6.75 7.5 3 2.25-3 2.25m4.5 0h3m-9 8.25h13.5A2.25 2.25 0 0 0 21 18V6a2.25 2.25 0 0 0-2.25-2.25H5.25A2.25 2.25 0 0 0 3 6v12a2.25 2.25 0 0 0 2.25 2.25Z" />
</svg>
);
}
File diff suppressed because one or more lines are too long
+6
View File
@@ -13,3 +13,9 @@
## Testing
## Common Mistakes
### PowerShell scripts deployed via Intune MUST be pure ASCII (2026-03-30)
**What went wrong:** Em-dash characters `—` (U+2014) and Unicode symbols (✓, →, ✗) in Bootstrap .ps1 scripts caused cascading PowerShell parse errors in production. The IME (Intune Management Extension) uses PowerShell 5.1 which reads scripts without BOM as ANSI — multi-byte UTF-8 chars get corrupted.
**Rule:** ALL `.ps1` files under `scripts/Bootstrap/` (and any other scripts deployed via Intune) MUST contain only ASCII characters (0x00-0x7F). No em-dashes, no Unicode symbols, no special quotes. Use `-` instead of `—`, `[OK]` instead of `✓`, etc.
**How to check:** `LC_ALL=en_US.UTF-8 grep -Pn '[^\x00-\x7F]' <file>` — must return no matches.
**Severity:** PRODUCTION BREAKING — agent installation fails completely on all devices.