Initial import: SharePoint Embedded MCP Server - #3
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
Initial open-source import of the SharePoint Embedded MCP Server package, including the MCP server runtime, tool implementations for provisioning/container/content workflows, reference-architecture scaffolding, and OSS-compliance/testing infrastructure.
Changes:
- Adds the MCP server core (tools, prompts/resources, CLI bootstrap/auth, Graph/Azure helpers) to support end-to-end SharePoint Embedded workflows.
- Introduces reference-architecture scaffolding backed by committed sample apps (React SPA + Functions; ASP.NET Core on ACA) and supporting infra templates.
- Establishes OSS + repo hygiene (MIT licensing, security/support/contributing docs, third-party notices generation, Vitest/ESLint/TypeScript config, regression tests).
Reviewed changes
Copilot reviewed 123 out of 128 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| vitest.config.ts | Adds Vitest configuration with coverage settings for src/. |
| tsconfig.json | Sets TS build settings for Node16 ESM output to dist/. |
| SUPPORT.md | Adds GitHub Issues-based support policy and security-reporting guidance. |
| src/validation.ts | Introduces shared runtime validation helpers for MCP tool args. |
| src/validation.test.ts | Adds unit tests for validation helpers. |
| src/user-agent.ts | Defines shared User-Agent token for Graph/Azure attribution. |
| src/types.ts | Adds shared MCP/tool and Graph domain type definitions. |
| src/tools/upload-file.ts | Implements content_file_upload tool (text upload). |
| src/tools/status.ts | Implements status_get tool (bootstrap identity + state summary). |
| src/tools/status.test.ts | Unit tests for status_get behavior via mocks. |
| src/tools/seed-sample-data.ts | Implements project_seed_sample_data tool for demo content. |
| src/tools/search-docs.ts | Adds docs_search/docs_fetch tools backed by Learn MCP. |
| src/tools/search-content.ts | Implements content_search tool using Microsoft Search API. |
| src/tools/scaffold.ts | Implements project_scaffold tool to materialize reference architectures. |
| src/tools/register-container-type.ts | Implements container_type_register tool for app grants registration. |
| src/tools/preview-file.ts | Implements content_file_preview tool for preview URLs. |
| src/tools/manage-sharing.ts | Implements content_sharing_manage tool (create/list/revoke links). |
| src/tools/manage-permissions.ts | Implements container_permissions_manage tool with role validation. |
| src/tools/manage-permissions.test.ts | Adds tests ensuring roles are validated and never default silently. |
| src/tools/list-containers.ts | Implements container_list tool for containers under a type. |
| src/tools/list-container-types.ts | Implements container_type_list tool for tenant container types. |
| src/tools/list-azure.ts | Adds Azure CLI listing tools (subscriptions/resource groups). |
| src/tools/list-azure.test.ts | Tests not-signed-in detection for Azure subscriptions listing. |
| src/tools/get-container.ts | Implements container_get tool (details, drive, perms, properties). |
| src/tools/docs.test.ts | Tests docs_search/docs_fetch tools with mocked Learn client. |
| src/tools/delete-container.ts | Implements container_delete tool (soft/permanent/restore). |
| src/tools/create-folder.ts | Implements content_folder_create tool with nested folder creation. |
| src/tools/create-container.ts | Implements container_create with retry/backoff + activation. |
| src/tools/content-access.ts | Adds opt-in content-plane gating + wrapper (withContentAccess). |
| src/tools/content-access.test.ts | Tests gating behavior and wrapper enforcement. |
| src/tools/container-type-tools.test.ts | Tests container-type CRUD + owner-permission tools via mocks. |
| src/tools/container-type-permissions.ts | Adds beta container type owner permission management tools. |
| src/tools/container-type-crud.ts | Adds container_type_get/update/delete tools with safety policy. |
| src/tools/container-type-app-grants.test.ts | Tests container type app-grant tools (registration grants). |
| src/tools/cleanup.ts | Adds project_cleanup teardown tool with conservative deletion policy. |
| src/tools/check-billing.ts | Adds billing_check tool to surface billing/trial info. |
| src/tools/archive-restore.ts | Adds container_archive_restore tool (lock/unlock). |
| src/state.ts | Implements persisted provisioning state (~/.spe-mcp/state.json). |
| src/server-readiness.ts | Adds TCP readiness probe utility for local dev server. |
| src/server-readiness.test.ts | Tests readiness probe using mocked node:net. |
| src/resources.ts | Exposes reference architectures as MCP resources + reader. |
| src/reference-architectures.ts | Catalogs architectures and scaffolds from committed samples/. |
| src/reference-architectures.test.ts | Validates catalog behavior and secure ACA template properties. |
| src/prompts.ts | Adds provision_spe_app MCP prompt for guided end-to-end flow. |
| src/packaging.test.ts | Regression tests for OSS/publish metadata and dependency hygiene. |
| src/elicitation.ts | Provides agent-guided elicitation helper for portable flows. |
| src/docs-client.ts | Implements Learn MCP client wrapper with tool discovery/drift handling. |
| src/container-retry.ts | Adds shared retry classification/backoff for container creation. |
| src/container-retry.test.ts | Tests retry classification and bounded retry-loop behavior. |
| src/constants.ts | Defines shared local dev port/origin constants (single source of truth). |
| src/cli.ts | Adds spe-mcp CLI (start/auth/logout). |
| src/bootstrap.test.ts | Tests Azure CLI bootstrap module behavior with mocked execFile. |
| src/azure-cli.test.ts | Tests Syntex region validation + CA error handling in Azure helpers. |
| src/az-errors.ts | Centralizes Conditional Access / claims-challenge error classification. |
| src/az-errors.test.ts | Tests CA classifier + guidance builder + enrichment behavior. |
| src/auth.test.ts | Tests tenant-safe MSAL token cache partitioning and account selection. |
| src/auth-error-guidance.ts | Adds actionable guidance for SPA redirect URI AADSTS errors. |
| src/auth-error-guidance.test.ts | Tests guidance + drift guard vs React sample embedded helper. |
| SECURITY.md | Adds standard Microsoft security reporting guidance. |
| scripts/generate-third-party-notices.mjs | Adds generator for THIRD-PARTY-NOTICES from production deps. |
| samples/react-spa-functions/vite.config.ts | Vite config for React sample (dev port/build output). |
| samples/react-spa-functions/tsconfig.json | TS config for React sample (bundler resolution/noEmit). |
| samples/react-spa-functions/staticwebapp.config.json | SWA navigation fallback config. |
| samples/react-spa-functions/src/vite-env.d.ts | Declares Vite env vars used by sample. |
| samples/react-spa-functions/src/main.tsx | React sample entrypoint. |
| samples/react-spa-functions/README.md | React sample usage and sign-in note. |
| samples/react-spa-functions/package.json | React sample deps/scripts and overrides. |
| samples/react-spa-functions/infra/web.bicep | SWA infra module for React sample. |
| samples/react-spa-functions/infra/main.parameters.json | azd parameters for React sample infra. |
| samples/react-spa-functions/infra/main.bicep | Subscription-scoped infra entrypoint for React sample. |
| samples/react-spa-functions/index.html | React sample HTML entry. |
| samples/react-spa-functions/azure.yaml | azd descriptor for React sample. |
| samples/react-spa-functions/.gitignore | Sample ignore rules (build/env outputs). |
| samples/csharp-web/spe-sample-csharp-web.csproj | ASP.NET Core sample project file (net8). |
| samples/csharp-web/README.md | C# sample docs and security model overview. |
| samples/csharp-web/Program.cs | Minimal ASP.NET Core endpoints and health check. |
| samples/csharp-web/infra/shared/registry.bicep | ACR module with admin disabled. |
| samples/csharp-web/infra/shared/identity.bicep | User-assigned managed identity module. |
| samples/csharp-web/infra/shared/apps-env.bicep | Container Apps environment module. |
| samples/csharp-web/infra/modules/fetch-container-image.bicep | Helper module to fetch existing container image info. |
| samples/csharp-web/infra/main.parameters.json | azd parameters (incl. substitution tokens). |
| samples/csharp-web/infra/main.bicep | Subscription-scoped infra entrypoint for ACA sample. |
| samples/csharp-web/infra/abbreviations.json | Naming abbreviations for infra templates. |
| samples/csharp-web/Dockerfile | Multi-stage build for containerized deployment. |
| samples/csharp-web/bicepconfig.json | Enables Bicep extensibility feature. |
| samples/csharp-web/azure.yaml | azd descriptor for ACA sample. |
| samples/csharp-web/appsettings.json | App configuration placeholders for SPE settings. |
| samples/csharp-web/.gitignore | Ignore build outputs for sample. |
| samples/csharp-web/.dockerignore | Docker ignore rules for sample build context. |
| package.json | Defines package metadata, deps, scripts, engines, publishConfig, overrides. |
| LICENSE | Adds MIT license file. |
| eslint.config.js | Adds ESLint v9 flat config for TS/JS linting. |
| CONTRIBUTING.md | Adds contribution and local validation guidance. |
| CODE_OF_CONDUCT.md | Adds Microsoft OSS Code of Conduct. |
| CHANGELOG.md | Adds initial changelog scaffold. |
| .vscode/mcp.json | Adds VS Code MCP server launch configuration for the repo. |
| .gitignore | Adds repo ignore rules for dist, node_modules, sample build outputs. |
| .gitattributes | Normalizes EOLs and marks binary file types. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+14
to
+16
| * Keep the version in sync with package.json / SERVER_VERSION on release. | ||
| */ | ||
| export const USER_AGENT = "spe-mcp-server/0.1.0"; |
Comment on lines
+10
to
+13
| import { searchContent } from "../graph-client.js"; | ||
| import { requireContentAccess } from "./content-access.js"; | ||
| import type { McpTool, SearchResponse } from "../types.js"; | ||
|
|
Comment on lines
+34
to
+46
| handler: async (args) => { | ||
| const gate = requireContentAccess(); | ||
| if (gate) return gate; | ||
|
|
||
| const query = args.query as string; | ||
| const maxResults = (args.maxResults as number) ?? 25; | ||
|
|
||
| if (!query) { | ||
| return { | ||
| content: [{ type: "text", text: "Error: query is required" }], | ||
| isError: true, | ||
| }; | ||
| } |
Comment on lines
+10
to
+12
| import { getContainerDrive, uploadSmallFile } from "../graph-client.js"; | ||
| import { requireContentAccess } from "./content-access.js"; | ||
| import type { McpTool } from "../types.js"; |
Comment on lines
+41
to
+55
| handler: async (args) => { | ||
| const gate = requireContentAccess(); | ||
| if (gate) return gate; | ||
|
|
||
| const containerId = args.containerId as string; | ||
| const fileName = args.fileName as string; | ||
| const content = args.content as string; | ||
| const folderPath = (args.folderPath as string) ?? ""; | ||
|
|
||
| if (!containerId || !fileName || content === undefined) { | ||
| return { | ||
| content: [{ type: "text", text: "Error: containerId, fileName, and content are required" }], | ||
| isError: true, | ||
| }; | ||
| } |
Comment on lines
+47
to
+50
| const drive = await getContainerDrive(containerId); | ||
| const segments = folderPath.replace(/^\/+|\/+$/g, "").split("/"); | ||
| let currentParent = "root"; | ||
| const results: Array<{ name: string; id: string; status: string }> = []; |
added 2 commits
June 25, 2026 13:04
…n bootstrap mode container_type_update failed with HTTP 400 'One of the provided arguments is not acceptable' because the beta PATCH omitted the REQUIRED etag (per Graph docs, the 'Update without ETag' example returns 400). graph-client.updateContainerType now reads the current etag via GET and merges it into the body unless the caller supplies one. Adds etag to ContainerType/RawContainerType. In bootstrap mode, read tools that do not call setAuthConfig (container_list, container_get, billing_check, container_type_list, content_*) threw 'Auth not configured' when invoked as the first Graph call. index.ts now primes setAuthConfig from persisted provisioning state at startup. Adds 2 regression tests for the etag in graph-client.test.ts.
Gregory Joseph (gnjoseph)
force-pushed
the
feat/spe-mcp-server
branch
from
June 25, 2026 20:05
8826984 to
d0d8637
Compare
…s); default containerTypeId from state; actionable auth error Rebased onto PR #3; drops changes already landed by the prior fix commit (index.ts auth priming, container_type_update etag). project_run_local always reported "never became ready" on Windows: Vite 6 binds localhost == IPv6 ::1, but server-readiness probed IPv4 127.0.0.1 only, so the TCP probe never connected even though the app was up. waitForServerReady now probes BOTH 127.0.0.1 and ::1 and succeeds if either accepts (verified live: run-local returns the URL and the app serves HTTP 200 over ::1). run-local also now runs `npm install` to completion before starting the dev server, instead of racing a detached install against Vite's dependency optimizer. container_list and billing_check required containerTypeId even when one was in provisioning state; they now default it from state (parity with container_create / register / seed), so "list my containers" / "check my billing" work with no args after provisioning. auth.ts getConfig() now returns an actionable message (run project_provision / start with --client-id) instead of the internal "call setAuthConfig()" string — defense-in-depth for tenants with no persisted state, complementing the PR's startup auth priming. Adds regression tests: dual-stack readiness (IPv6-only and IPv4-only servers), and state-defaulted containerTypeId for container_list / billing_check. 397 tests pass; lint + build clean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…sclaimer placeholder
…issues/new-tool/e2e-prompts
… annotations, central validation, Graph error mapping, zod defineTool (pilot), http seam Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…feat/spe-mcp-server
…at/spe-mcp-server
…onfirmation middleware; read-only/profile policy helpers (SAFE-002/003/004 WIP)
…Confirmation; annotate all tools; migrate tools to defineTool/ok-fail (SAFE-001, TOOL-002/005)
…dpoint policy (SEC-007); tests for pagination, policy (read-only/profiles), and docs endpoint
…E-001..004, TOOL-002/003/005, SEC-007)
…den test (TEST-002); coverage thresholds (TEST-004)
…lden + coverage thresholds (TEST-001/002/004)
…protocol-e2e beforeAll (TEST-001 robustness)
…etch readOnly + container_create plane annotations; sanitize tool-local Graph errors; require https for docs endpoint; correct README token-cache claim
…E (org repos) so Security workflow stays green
…o issued-token tenant (BUG-1) Signing into an SPE resource/test tenant with a corporate identity (guest/B2B) cached an account whose HOME tenant differs from the configured tenant. The home-tenant equality check in getCachedAccount rejected this valid account, so a freshly consented owning app still failed with 'No cached credentials found' (observed in a real session against spemcptesting.onmicrosoft.com). The on-disk cache is already partitioned by (tenant, client), so any account in it was obtained under the configured authority. getCachedAccount now falls back to a partitioned-cache candidate (guest/B2B) for a silent attempt instead of forcing interactive, and the authoritative wrong-tenant protection moves to isWrongTenantToken, which verifies the ISSUED TOKEN's tenant rather than the account's home tenant. This is strictly more correct: it admits valid guests and still refuses a token actually minted for a different tenant.
…issued-token wrong-tenant guard (BUG-1, security-reviewed SHIP)
…interactive sign-in (no terminal/restart)
UX-2: control-plane SPE calls without an owning app now return a typed,
actionable OWNING_APP_REQUIRED error ('run project_app_create first') via the
safe-error envelope, instead of the leaked internal 'call setAuthConfig()'.
status_get proactively states the precondition; new isOwningAppConfigured()
+ OWNING_APP_REQUIRED_MESSAGE.
UX-1/UX-3: interactive sign-in is now enabled by default even over stdio (no
TTY) — a local MCP server opens a browser for consent in-process, so after
project_app_create (which already re-points auth in-process via setAuthConfig)
the next SPE call signs in and caches the token live — no terminal 'spe-mcp auth'
and no server restart. SPE_NON_INTERACTIVE=1 opts out for automation/CI; all
sign-in failure messages are now typed AppErrors with actionable guidance.
create-app success message updated ('no restart needed'); leaked catch now uses
clientSafeMessage. +4 tests; full CI green (447 pass).
…evice-code fast-fail Review (rubber-duck) SHOULD-FIX items: - Device code now only offered when stderr is a TTY (deviceCodeIsVisible); over stdio the browser is attempted and, on failure, we fail fast with an actionable AppError instead of hanging on an invisible 10-min device-code wait. - Interactive sign-in default now also OFF in obvious automation/headless envs (CI=true, Linux without DISPLAY/WAYLAND_DISPLAY) via isLikelyHeadlessEnv(); SPE_INTERACTIVE=1 forces on, SPE_NON_INTERACTIVE=1 forces off. NITs: create-app says 'configured to sign in as this app' (not 'signed in'); isOwningAppConfigured() doc clarifies availability vs readiness; README auth section rewritten for in-process browser auth + automation env vars. Full CI green (447 pass).
…cess sign-in (no terminal/restart) [UX-1/2/3, reviewed]
…restart-after-az-login Addresses PR #3 review comments on the owning-app onboarding flow: - create-app: after the owning app is created (or reused) and its SPE permissions are requested, append a copy-paste tenant-wide admin-consent link (https://login.microsoftonline.com/{tenantId}/adminconsent?client_id={appId}) built from the real signed-in tenant id + the app's public client id. Explains the Global-Admin (grant tenant-wide) vs non-admin (forward the link) paths. Non-blocking/informational: no browser is opened, provisioning is never gated on consent, and the URL carries no secret. - create-app: remove the dangling "full-setup skill 02-app.ps1" reference (no public URL to point at, so removed rather than invented). - index.ts: clarify the config.clientId branch is the bring-your-own-app path (a pre-created owning app supplied via --client-id / SPE_CLIENT_ID) and emit an explicit startup line saying no owning app will be provisioned. - index.ts: extend the bootstrap "not signed in" message to instruct users to RESTART the server after `az login`, since auth/session state is stamped at startup (a restart begins a fresh session and re-primes auth). - New src/onboarding-messages.ts houses the pure message builders with the missing-tenant fallback (organizations) + unit tests; extend create-app tests to assert the URL, admin/non-admin copy, no-secret guarantee, and skill-ref removal. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… unused Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
refactor(types): adopt official beta Graph types for container-type control-plane contracts
feat(onboarding): admin-consent link + bring-your-own-app guidance + restart-after-az-login
…ocument headless/sub-agent sign-in The device-code cancel was hardcoded to 2 min (TTY) / 10 min (headless). The 10-min (600s) headless bound is SHORTER than the ~15-min (900s) Azure AD device-code lifetime, so it prematurely cancelled a sign-in that was still valid. MSAL already stops polling at code expiry, so our client timer only ever needs to be a safety net at that same horizon - never below it. Fix (src/auth.ts): - Replace the fixed, TTY-dependent DEVICE_CODE_TIMEOUT_MS with a bound DERIVED from the device code's real lifetime: DEVICE_CODE_LIFETIME_SECONDS = 900 and a pure deviceCodeCancelDelayMs(expiresIn) helper (seconds -> ms, defaulting to the ~15-min lifetime when expiresIn is unknown). - Set the native DeviceCodeRequest.timeout to the code lifetime; per MSAL "the device code expiration window will always take precedence over this set period", so it caps the wait without cancelling a still-valid code. - Re-arm the JS safety-net timer inside deviceCodeCallback using the STS-reported response.expiresIn, so it can never fire before the code expires. - Keep the existing fail-fast-when-invisible behavior; refresh the stale "hang for up to 10 minutes" comment. Docs (README.md): new "Headless & orchestrator / sub-agent sign-in" section covering interactive defaults + SPE_INTERACTIVE / SPE_NON_INTERACTIVE overrides, why device-code prompts (stderr) are not visible to a calling agent and therefore fail fast instead of hanging, the pre-auth + restart pattern, and the ~15-min device-code timeout. Tests (src/auth.test.ts): assert the cancel horizon is >= the code lifetime and never the old 600s/120s, that expiresIn drives the derivation, and (fake timers) that a still-valid code is not cancelled before it expires. Token/account-selection and guest/B2B logic are untouched. Ref: PR #3 review. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Defense-in-depth from PR #3 review: bound the expiresIn-derived cancel delay to 4x the ~15-min AAD code lifetime so an absurd expiresIn can't exceed Node's max setTimeout delay (~24.85 days) and get clamped to 1ms (near-instant cancel). AAD never issues such values and MSAL's native timeout stays authoritative. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
fix(auth): align device-code timeout to the ~15-min code lifetime + document headless/sub-agent sign-in
…R) + secure-fs hardening Adds a configurable data directory so multiple SPE MCP server instances stop clobbering the single ~/.spe-mcp/state.json + token cache. - New src/paths.ts: lazy/memoized resolve-once seam (resolveDataDir, getDataDir, getStateFile, getCacheDir, getCacheFile, getLegacyCacheFile, setDataDirOverride). Precedence flag > env > default ~/.spe-mcp; default is byte-identical. - Remove module-level STATE_DIR (state.ts) / CACHE_DIR (auth.ts) consts and route state + token cache through the seam. state.json is NOT auto-partitioned (the directory is the isolation boundary). - CLI: --data-dir on start/auth/logout; resolve + set the override, propagate SPE_DATA_DIR, and log the resolved path to stderr (path-only) BEFORE importing state/auth so all entry points resolve the same dir. - Harden secure-fs (fail-closed): refuse symlink / foreign-owned / group-or-other dirs; O_NOFOLLOW + fstat on read/write; chmod the fd, never the path; Windows off-profile owner-only DACL via icacls or refuse; insecure target blocks refresh-token persistence (forces fresh interactive sign-in). - Untrusted-path validation in resolveDataDir: absolute + normalized, reject CWD-relative, expand leading ~. - Tests: paths.test.ts, state.test.ts (isolation + golden default), secure-fs symlink/TOCTOU/perms. Suite: 688 passed / 7 skipped. - Version bump 0.1.0-alpha.1 -> 0.2.0-alpha.1 (additive / back-compat). AB#3141787 AB#3141788 AB#3141789 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- readState: route through readSecureFile (O_NOFOLLOW + owner check) so a symlinked/foreign-owned state.json fails closed, matching writeState. (sec S1) - secure-fs: invoke icacls by absolute %SystemRoot%\System32 path, not bare name, to remove any binary-planting angle. (sec S2) - writeSecureFile: drop O_TRUNC; ftruncate only AFTER the fstat owner/type checks pass (no truncate-before-verify), and use writeFileSync(fd,...) to handle short writes / EINTR. (sec S3 + review C3) - ensureSecureDir: scope the strict group/other-accessible rejection to off-home overrides; keep best-effort for the default ~/.spe-mcp so a mode-ignoring FS (WSL DrvFs, some NFS/CIFS) doesn't hard-fail existing users. Ownership + symlink checks remain universal. (review C1) - secureWindowsDirAclOrThrow: document the known off-profile explicit-ACE / owner-verify limitation (follow-up under AB#3116729). (review C2) - README: Configuration row + Token Storage + "Running multiple instances" with .vscode/mcp.json snippets and the absolute-path rule. (review C4) - tests: add sanitizeForFilename coverage. Suite 689 passed / 7 skipped; npm run ci + lint green. AB#3141787 AB#3141788 AB#3141789 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ardening Compliance C1 (Keep-a-Changelog repo convention). Non-code; no ci impact. AB#3141787 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The scaffolded React reference app was functional but visually bare (single blue button, gray config box, raw <ul> lists, byte counts). This gives it a polished, Fluent-inspired look without adding any dependency. - New src/styles.css design system: CSS-variable theming with light + dark (prefers-color-scheme), sticky app bar with product mark + account chip, hero sign-in state, container cards in a responsive grid with status pills, a files panel with folder/file glyphs + humanized sizes, empty/loading states, spinner, focus-visible rings, and a collapsible "Connection details" panel that de-emphasizes the raw config. - App.tsx: replace all inline styles with semantic classNames; add formatSize (humanized bytes) and initials (avatar) helpers. All MSAL auth logic, Graph calls, and the byte-for-byte interpretAuthError/explainAuthError guidance (and its four error-message prefixes) are unchanged — the auth-error drift guard still passes. - main.tsx imports the stylesheet; index.html gets an inline SVG favicon + theme-color. Verified: sample pm run build (tsc -b + vite build) green; server pm run ci + pm run lint green (717 passed / 3 skipped) incl. the sample drift-guard and reference-architecture scaffolder tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… error classification, guest remap scope, RG existence check) Four LOW-severity follow-ups from the PR #3 review, each small and surgical: 1. provision.ts - stamp the session confirmed as soon as the owning app is settled, BEFORE the billing-model / sub-RG elicitations can return an agent-guided ask and be re-invoked. Prevents the always-ask app gate from re-firing if the agent drops appSelection while answering a later billing prompt. The ownerScope gate is relaxed to key on resolved intent only (not session confirmation) so the earlier stamp does not suppress its ask. The confirmBilling financial-safety gate ordering is unchanged. 2. Control-plane mutation tools (create/register container type, app-grant add/remove, owner grant/revoke) - move resolveContextGate() INSIDE each handler's try so a stamp-write failure on contextChoice=confirm (writeState/writeSecureFile EACCES/EIO) is classified by the tool's own error handling instead of the generic dispatch catch. Early-return-on-gate behavior is unchanged. 3. container-type-permissions.ts - scope the guest-owner-rejection remap to the self-target (signed-in user) path only. An explicit member userId grant that fails for an unrelated reason mentioning "guest" now surfaces its raw reason instead of misdirected guest guidance. The proactive userType==="Guest" self-target check is preserved. 4. standard-billing-target.ts / azure-cli.ts - verify a user-entered NEW resource-group name (0-RG path) via a non-throwing resourceGroupExists probe (az group show). A non-existent RG now fails COST-FREE with actionable guidance before any container type / billing account is created, instead of only failing later at createSyntexAccount. An indeterminate probe (az missing / auth / transient) degrades to the prior behavior. The auto-select-singleton and multi-RG elicit paths are unchanged. Tests: gate-error-classification.test.ts (Nit 2) and standard-billing-target.test.ts (Nit 4) added; container-type-tools.test.ts (Nit 3), orchestration.test.ts (Nit 1), and provision-guided-billing.test.ts (Nit 4 integration) extended. Full suite: 731 passed | 3 skipped. lint / typecheck / build all clean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
fix: address code-review follow-up nits (confirm-stamp ordering, gate error classification, guest remap scope, RG existence check)
fix(samples): map SWA-unsupported deploy regions so azd up doesn't fail on region
feat(data-dir): per-instance data directory (--data-dir / SPE_DATA_DIR) + secure-fs hardening
feat(sample): modern visual refresh for the React SPA reference app
pemtaira-msft
requested changes
Jul 10, 2026
| matrix: | ||
| node-version: | ||
| - 18.x | ||
| - 20.x |
Collaborator
There was a problem hiding this comment.
These node versions are all almost end-of-life. We should be using at least Node 22 (LTS)
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: 20.x |
Collaborator
There was a problem hiding this comment.
Should be at least node 22, but better if we go higher (like latest stable)
Close the CELA MCP-release notice gaps for Matter-0000001599: - Replace the pending MCP-disclaimer placeholder in README with an "Important notices" section (preview/no-warranty, autonomous-operation warning + SAFE-002/003/004, cost/billing, data & telemetry, data residency/EUDB, and a Product Terms pointer). - Add PRIVACY.md reconciling the no-telemetry posture with the static product User-Agent and local-only logging. - Add docs/DATA-FLOW.md enumerating outbound endpoints, boundary, and EUDB. - Fix README label that called the User-Agent a "Telemetry" string. - Add a top-of-README preview/cost/agent callout. Exact MCP disclaimer wording pending frontline-CELA confirmation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Renames the published npm package id @microsoft/spe-mcp-server -> @microsoft/spe-mcp across package.json, package-lock.json, server.json (npm identifier), README, THIRD-PARTY-NOTICES, generate-third-party-notices.mjs, resources.ts and types.ts. Runtime identity (server name / User-Agent 'spe-mcp-server'), the MCP registry reverse-DNS name, the GitHub repo URL, and the 'spe-mcp' bin are intentionally unchanged; package version 0.2.0-alpha.1 is untouched. Also adds a Documentation section to the README cross-linking the Microsoft Learn getting-started article (sp-dev-docs) and the in-repo security-controls / troubleshooting docs, completing the bidirectional documentation links. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Rename npm package to @microsoft/spe-mcp; add README docs cross-link
…/cela-mcp-notices # Conflicts: # README.md
docs: CELA MCP notices, PRIVACY, and data-flow (Matter-0000001599)
Drop Node 18/20 from documented and CI-supported runtimes, and align workflows and package engines with active Node lines. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
pemtaira-msft
approved these changes
Jul 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Initial import of the SharePoint Embedded MCP Server (
@microsoft/spe-mcp-server), prepared for open-source release.Contents
src/): ~40 tools spanning the SharePoint Embedded workflow — provisioning (app → container type → billing → container), container & content management, scaffold/run/deploy, and docs search — backed by a two-token auth model (app-only Microsoft Graph token + delegated MSAL token).samples/): a Vite + React SPA and an ASP.NET Core C# web app.LICENSE,THIRD-PARTY-NOTICES,SECURITY.md,CONTRIBUTING.md,CODE_OF_CONDUCT.md,SUPPORT.md, and per-file MIT headers.Validation
npm install(public npm) clean ·npm run lint✅ ·npm run typecheck✅npm test✅ 390/390 ·npm audit0 vulnerabilitiesVersion
0.1.0-alpha.1(first prerelease).