Skip to content

Initial import: SharePoint Embedded MCP Server - #3

Merged
Gregory Joseph (gnjoseph) merged 125 commits into
mainfrom
feat/spe-mcp-server
Jul 10, 2026
Merged

Initial import: SharePoint Embedded MCP Server#3
Gregory Joseph (gnjoseph) merged 125 commits into
mainfrom
feat/spe-mcp-server

Conversation

@gnjoseph

Copy link
Copy Markdown
Collaborator

Initial import of the SharePoint Embedded MCP Server (@microsoft/spe-mcp-server), prepared for open-source release.

Contents

  • MCP server (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).
  • Reference-architecture samples (samples/): a Vite + React SPA and an ASP.NET Core C# web app.
  • Tests (vitest), ESLint flat config, TypeScript build.
  • OSS compliance: MIT 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 audit 0 vulnerabilities

Version 0.1.0-alpha.1 (first prerelease).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 thread src/user-agent.ts Outdated
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 thread src/tools/search-content.ts Outdated
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 thread src/tools/upload-file.ts Outdated
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 thread src/tools/upload-file.ts Outdated
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 }> = [];
Greg Joseph 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.
Greg Joseph and others added 23 commits June 25, 2026 13:29
…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>
… annotations, central validation, Graph error mapping, zod defineTool (pilot), http seam

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…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
…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>
Gregory Joseph (gnjoseph) and others added 4 commits July 9, 2026 08:33
… 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>
Gregory Joseph (gnjoseph) and others added 7 commits July 9, 2026 08:59
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
Comment thread .github/workflows/ci.yml Outdated
matrix:
node-version:
- 18.x
- 20.x

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These node versions are all almost end-of-life. We should be using at least Node 22 (LTS)

Comment thread .github/workflows/security.yml Outdated
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20.x

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be at least node 22, but better if we go higher (like latest stable)

Greg Joseph and others added 6 commits July 10, 2026 12:52
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>
@gnjoseph
Gregory Joseph (gnjoseph) merged commit 3e2afea into main Jul 10, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants