Skip to content

MCP Track B Phase B0-B2: design inbound MCP architecture, auth, PRM, and governance #1017

Open

Description

@Bionic711

Summary

Implement the inbound SimpleChat MCP foundation from #1013: architecture decision, dedicated auth guard, Protected Resource Metadata (PRM), governance, roles, client allowlists, and explicit tool policy.

Scope

  • Choose first production hosting model for inbound MCP.
  • Prefer a first-class SimpleChat component/service layer initially, with optional later sidecar/container deployment.
  • Keep MCP tool business logic behind reusable authorization-aware service functions.
  • Start with streamable HTTP.
  • Add a dedicated inbound MCP auth guard without broadening accesstoken_required.
  • Validate token issuer, tenant, expiration, and audience.
  • Require a dedicated inbound MCP role/scope or deliberately reused ExternalApi role.
  • Add approved caller app ID allowlist.
  • Separate app-only and delegated user access.
  • Reject app-only tokens for user-data tools unless a future admin-only operation is explicitly designed.
  • Add .well-known/oauth-protected-resource metadata.
  • Add governance settings for global enablement, per-client enablement, per-tool allowlists, per-scope allowlists, and optional rate limits.
  • Build an explicit inbound MCP tool registry with required identity type, workspace scope, feature flags, governance keys, rate-limit category, and audit event type.

Acceptance Criteria

  • Inbound MCP has a documented architecture choice and deployment boundary.
  • Auth failures are distinct from governance denials.
  • Token validation includes issuer, audience, expiration, tenant, role/scope, and caller app ID checks.
  • App-only tokens cannot access personal user data tools.
  • PRM metadata is available and does not expose secrets, internal endpoints, or raw settings.
  • Governance denies by default when client, tool, or scope is not configured.
  • Tests cover missing token, malformed token, expired token, invalid issuer, invalid audience, missing role/scope, disallowed app ID, app-only rejection for user data, delegated token acceptance, disabled global setting, disabled client, disabled tool, and disabled scope.

Notes

Parent: #1013
Prototype/reference PR: #722 should inform intent only; do not copy its implementation directly.
Planning doc: docs/explanation/features/MCP_PLUGIN_ROBUSTNESS_PLAN.md
Priority: P1
Size: XL

Activity

  1. self-assigned this
    on Jul 9, 2026
  2. Bionic711 commented on Jul 9, 2026

    @Bionic711
    CollaboratorAuthor

    MCP planning checkpoint update:

    • Track B Phase B0/B1 planning is complete and documented in docs\explanation\features\INBOUND_MCP_SERVER_ARCHITECTURE.md.
    • The master plan now carries the inbound architecture/auth foundation forward in docs\explanation\features\MCP_PLUGIN_ROBUSTNESS_PLAN.md.
    • Added explicit future requirements for fine-grained inbound tool/resource exposure governance:
      • per tool/resource family/operation,
      • per caller user/group segment,
      • per specific group or wildcard group target,
      • explicit deny wins, missing policy denies,
      • governance does not bypass existing workspace authorization.
    • Added source allowlisting requirements for inbound MCP clients:
      • allow * for identity-only deployments,
      • treat token/client identity as primary,
      • treat origin/user-agent/custom headers as supplemental unless injected or signed by trusted infrastructure.
    • Next executable Track B slice remains a disabled inbound MCP shell with PRM, health, auth guard, and governance skeletons before exposing any tools.
  3. Bionic711 commented on Jul 9, 2026

    @Bionic711
    CollaboratorAuthor

    Implementation checkpoint: disabled inbound MCP shell is now in place.

    What changed:

    • Added disabled-by-default inbound MCP config in application/single_app/config.py and bumped the app version to 0.250.063.
    • Added a dedicated inbound MCP bearer-token guard in functions_mcp_server_auth.py with client allowlist, tenant checks, required role/scope checks, and source allowlist scaffolding.
    • Added deny-by-default governance and no-enabled-tools registry skeletons in functions_mcp_server_governance.py and functions_mcp_server_registry.py.
    • Added route_inbound_mcp.py with:
      • public PRM metadata route,
      • authenticated /api/mcp/health shell route,
      • authenticated /api/mcp shell endpoint that returns no tools.
    • Registered the inbound_mcp Blueprint with a dedicated auth policy and updated route policy tests.
    • Updated the inbound MCP architecture/master plan docs and release notes for v0.250.063.

    Validation:

    • python -m py_compile ... for changed Python files and route tests passed.
    • python functional_tests/test_inbound_mcp_server_shell.py passed.
    • python functional_tests/route_tests/test_route_blueprint_policy_inventory.py passed.
    • python functional_tests/route_tests/test_route_unauthenticated_policy_contract.py passed.
    • python functional_tests/route_tests/test_route_policy_test_coverage.py passed.
    • git diff --check passed.

    Important behavior:

    • No inbound MCP tools are exposed yet.
    • ENABLE_INBOUND_MCP_SERVER=false remains the default.
    • The shell establishes route/auth/governance/registry foundations before any read tools are added.

    Next candidate slice:

    • Track B Phase B2/B3: durable inbound MCP governance evaluation plus the first read-only personal tool behind delegated identity, client/source allowlisting, SimpleChat governance allow, existing object authorization, audit logging, and negative tests for disabled group/public/all scopes.
  4. Bionic711 commented on Jul 15, 2026

    @Bionic711
    CollaboratorAuthor

    Implemented the first governed inbound MCP tool slice for Track B.

    What changed:

    • Added explicit deny-by-default inbound MCP item-policy evaluation for client, source, tool, scope, resource operation, and target scope.
    • Added explicit-deny precedence when matching policies specify effect=deny.
    • Extended the inbound MCP registry with input schemas, implementation flags, rate-limit categories, and audit event metadata.
    • Added minimal streamable HTTP JSON-RPC handling for initialize, notifications/initialized, tools/list, and tools/call.
    • Implemented the first delegated-user personal tool: list_personal_tags.
    • Kept execute_workflow and the remaining planned personal tools disabled until their service-layer authorization and guardrails are implemented.
    • Bumped app version to 0.250.070 and updated inbound MCP docs/release notes.

    Validation:

    • python -m py_compile application\single_app\functions_mcp_server_governance.py application\single_app\functions_mcp_server_registry.py application\single_app\functions_mcp_server_tools.py application\single_app\route_inbound_mcp.py application\single_app\config.py functional_tests\test_inbound_mcp_server_shell.py functional_tests\test_inbound_mcp_governance_and_tools.py functional_tests\route_tests\test_route_blueprint_policy_inventory.py functional_tests\route_tests\test_route_unauthenticated_policy_contract.py functional_tests\route_tests\test_route_policy_test_coverage.py
    • python functional_tests\test_inbound_mcp_server_shell.py
    • python functional_tests\test_inbound_mcp_governance_and_tools.py
    • python functional_tests\route_tests\test_route_blueprint_policy_inventory.py
    • python functional_tests\route_tests\test_route_unauthenticated_policy_contract.py
    • python functional_tests\route_tests\test_route_policy_test_coverage.py
    • python -m pytest functional_tests\test_inbound_mcp_server_shell.py functional_tests\test_inbound_mcp_governance_and_tools.py -v
    • git -c core.whitespace=blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol diff --check

    Follow-ups:

    • Add admin UX or documented operator workflow for creating inbound MCP policies.
    • Implement another low-risk personal read tool next.
    • Keep execute_workflow deferred until workflow ownership, distributed run locks, rate limits, and execution audit guardrails are wired.
  5. Bionic711 commented on Jul 15, 2026

    @Bionic711
    CollaboratorAuthor

    Implemented the inbound MCP app-settings + minimal admin UI slice in v0.250.071.

    Summary:

    • Moved mutable inbound MCP runtime config out of static OS env constants and into Cosmos-backed app_settings defaults/normalization.
    • Added functions_mcp_server_config.py for runtime config normalization and the OS-only MCP UI gate.
    • Updated inbound MCP auth/PRM/health handling to resolve runtime config per request.
    • Added a minimal Admin Settings > Agents and Actions panel for server enablement, required Entra role/scope, client/tenant/source allowlists, and source-header configuration.
    • Added a gated left-nav Inbound MCP entry under Agents and Actions.
    • Kept ENABLE_MCP_UI environment-only; it is not persisted in app_settings or exposed as an editable UI setting.
    • Kept MCP endpoint paths fixed/read-only for this slice.
    • Updated docs, release notes, and source-level regression coverage.

    Validation passed:

    • python -m py_compile on changed Python files and inbound MCP tests
    • python functional_tests\test_inbound_mcp_server_shell.py
    • python functional_tests\test_inbound_mcp_governance_and_tools.py
    • python functional_tests\test_inbound_mcp_admin_ui.py
    • Route policy tests:
      • test_route_blueprint_policy_inventory.py
      • test_route_unauthenticated_policy_contract.py
      • test_route_policy_test_coverage.py
    • python -m pytest functional_tests\test_inbound_mcp_server_shell.py functional_tests\test_inbound_mcp_governance_and_tools.py functional_tests\test_inbound_mcp_admin_ui.py -v (14 passed)
    • git diff --check

    Remaining follow-ups:

    • Governance-policy authoring UI for inbound MCP is still future work.
    • Additional personal tools, including list_personal_documents and execute_workflow, remain planned but unimplemented pending their service-layer authorization, bounds, locking/rate-limit, and audit guardrails.
  6. Bionic711 commented on Jul 17, 2026

    @Bionic711
    CollaboratorAuthor

    Implemented the inbound MCP Easy Auth enablement guard for the Admin Settings UI.

    What changed:

    • Added required Easy Auth excluded-path constants for the PRM, MCP JSON-RPC, and MCP health endpoints.
    • Added a server-side unauthenticated probe that treats SimpleChat JSON responses as success and sign-in redirects/sign-in HTML as failure.
    • Added admin-only endpoint POST /api/admin/settings/inbound-mcp/easy-auth-check.
    • Added server-side Admin Settings save enforcement so inbound MCP cannot be enabled from disabled unless the Easy Auth exclusion probe succeeds.
    • Added the Bootstrap confirmation modal under Admin Settings > Agents and Actions with Cloud Shell-friendly PowerShell/az CLI setup guidance.
    • Updated admin JS so the MCP enable toggle opens the modal, verifies endpoints, keeps the toggle off on failure, and allows normal save after success.
    • Updated docs, master MCP robustness plan, release notes, and app version to 0.250.072.

    Validation:

    • python -m py_compile application\single_app\functions_mcp_server_config.py application\single_app\route_frontend_admin_settings.py application\single_app\config.py functional_tests\test_inbound_mcp_admin_ui.py functional_tests\test_inbound_mcp_server_shell.py functional_tests\test_inbound_mcp_governance_and_tools.py ui_tests\test_admin_inbound_mcp_easy_auth_modal.py
    • node --check application\single_app\static\js\admin\admin_settings.js
    • python functional_tests\test_inbound_mcp_admin_ui.py
    • Route policy tests all passed.
    • python -m pytest functional_tests\test_inbound_mcp_server_shell.py functional_tests\test_inbound_mcp_governance_and_tools.py functional_tests\test_inbound_mcp_admin_ui.py ui_tests\test_admin_inbound_mcp_easy_auth_modal.py -v -> 15 passed, 1 skipped (UI test skipped because UI env/storage state is not configured).
    • git -c core.whitespace=blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol diff --check

    Follow-up:

    • Next inbound slice can continue with the next low-risk personal read tool after list_personal_tags, reusing the app-settings config, governance checks, and now the Easy Auth exclusion enablement guard.
  7. Bionic711 commented on Jul 17, 2026

    @Bionic711
    CollaboratorAuthor

    Implemented the cloud-aware inbound MCP Easy Auth setup script update.

    What changed:

    • The Admin Settings inbound MCP modal now generates its PowerShell/az CLI script from SimpleChat/App Service deployment hints instead of assuming public Azure.
    • Script values are derived from TENANT_ID, AZURE_ENVIRONMENT, the configured Resource Manager endpoint, WEBSITE_SITE_NAME, WEBSITE_RESOURCE_GROUP, and a best-effort subscription GUID from App Service/Azure env metadata.
    • The generated script sets the Azure CLI cloud before login, maps public and US Government directly, and matches custom/MAG/Secret clouds by registered Azure CLI Resource Manager endpoint.
    • The script runs az login --tenant, optionally selects the derived subscription, validates the active Resource Manager endpoint, and then reads authsettingsV2.
    • Before applying changes, the script writes a timestamped simplechat-authsettingsV2-backup-*.json backup.
    • Existing excluded paths are preserved and the three inbound MCP paths are merged in.
    • The modal now shows derived deployment values, missing-value warnings, custom-cloud guidance, and backup behavior.
    • Updated version to 0.250.073, plus docs and release notes.

    Validation:

    • python -m py_compile application\single_app\route_frontend_admin_settings.py application\single_app\config.py functional_tests\test_inbound_mcp_admin_ui.py functional_tests\test_inbound_mcp_server_shell.py functional_tests\test_inbound_mcp_governance_and_tools.py ui_tests\test_admin_inbound_mcp_easy_auth_modal.py
    • node --check application\single_app\static\js\admin\admin_settings.js
    • python functional_tests\test_inbound_mcp_admin_ui.py
    • Route policy tests all passed.
    • python -m pytest functional_tests\test_inbound_mcp_server_shell.py functional_tests\test_inbound_mcp_governance_and_tools.py functional_tests\test_inbound_mcp_admin_ui.py ui_tests\test_admin_inbound_mcp_easy_auth_modal.py -v -> 15 passed, 1 skipped (UI test skipped because UI env/storage state is not configured).
    • git -c core.whitespace=blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol diff --check
  8. Bionic711 commented on Jul 17, 2026

    @Bionic711
    CollaboratorAuthor

    Implemented a follow-up fix for the inbound MCP Easy Auth modal/script.

    What changed:

    • Added a compact copy-to-clipboard icon button for the generated PowerShell script in the inbound MCP Easy Auth modal.
    • Added clipboard handling with navigator.clipboard.writeText, a safe textarea fallback, and Bootstrap toast feedback.
    • Fixed the generated script to read current App Service Authentication settings with GET .../config/authsettingsV2?api-version=2023-12-01 instead of POSTing to /list.
    • Moved JSON parsing after the successful az rest --method get call so backups are only created from successful reads.
    • Updated the standalone scripts\Disable-InboundMCPEasyAuth.ps1 copy with the same GET/read-before-backup fix.
    • Updated version to 0.250.074, plus docs and release notes.

    Validation:

    • python -m py_compile application\single_app\route_frontend_admin_settings.py application\single_app\config.py functional_tests\test_inbound_mcp_admin_ui.py functional_tests\test_inbound_mcp_server_shell.py functional_tests\test_inbound_mcp_governance_and_tools.py ui_tests\test_admin_inbound_mcp_easy_auth_modal.py
    • node --check application\single_app\static\js\admin\admin_settings.js
    • python functional_tests\test_inbound_mcp_admin_ui.py
    • Route policy tests all passed.
    • python -m pytest functional_tests\test_inbound_mcp_server_shell.py functional_tests\test_inbound_mcp_governance_and_tools.py functional_tests\test_inbound_mcp_admin_ui.py ui_tests\test_admin_inbound_mcp_easy_auth_modal.py -v -> 15 passed, 1 skipped (UI test skipped because UI env/storage state is not configured).
    • git -c core.whitespace=blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol diff --check
  9. Bionic711 commented on Jul 17, 2026

    @Bionic711
    CollaboratorAuthor

    Implemented the inbound MCP delegated-scope update for the v0.250.075 slice.

    What changed:

    • Changed the default inbound MCP delegated scope to DelegatedMcpServerAccess while keeping the app role default as McpServerAccess.
    • Clarified in Admin Settings that delegated user tokens are the default path for personal MCP tools, while app-role/app-only access is reserved for future non-personal service/admin tools.
    • Extended the Easy Auth PowerShell setup script to show the SimpleChat API client ID and required delegated scope.
    • Added a best-effort az ad app show preflight in the generated script to verify the API app registration exposes the enabled delegated scope before changing Easy Auth excluded paths.
    • Added a UI warning when SimpleChat cannot derive every value needed for that delegated-scope preflight.
    • Updated docs, functional/UI tests, release notes, and the standalone scripts\Disable-InboundMCPEasyAuth.ps1 helper.

    Validation:

    • python -m py_compile application\single_app\functions_mcp_server_config.py application\single_app\route_frontend_admin_settings.py application\single_app\config.py functional_tests\test_inbound_mcp_admin_ui.py functional_tests\test_inbound_mcp_server_shell.py functional_tests\test_inbound_mcp_governance_and_tools.py ui_tests\test_admin_inbound_mcp_easy_auth_modal.py
    • python functional_tests\test_inbound_mcp_admin_ui.py
    • python functional_tests\test_inbound_mcp_server_shell.py
    • python functional_tests\test_inbound_mcp_governance_and_tools.py
    • python functional_tests\route_tests\test_route_blueprint_policy_inventory.py
    • python functional_tests\route_tests\test_route_unauthenticated_policy_contract.py
    • python functional_tests\route_tests\test_route_policy_test_coverage.py
    • node --check application\single_app\static\js\admin\admin_settings.js
    • python -m pytest functional_tests\test_inbound_mcp_server_shell.py functional_tests\test_inbound_mcp_governance_and_tools.py functional_tests\test_inbound_mcp_admin_ui.py ui_tests\test_admin_inbound_mcp_easy_auth_modal.py -v (15 passed, 1 skipped because UI env/storage state is not configured)
    • git -c core.whitespace=blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol diff --check

    Follow-up note:

    • Existing deployments that already persisted inbound_mcp_required_scope may need to update that setting in Admin Settings to DelegatedMcpServerAccess if it still says McpServerAccess.
  10. Bionic711 commented on Jul 17, 2026

    @Bionic711
    CollaboratorAuthor

    Inbound MCP governance UI checkpoint completed locally.

    What changed:

    • Added Admin Settings > Governance controls for the six inbound MCP delegated item-policy dimensions required by governed tools: inbound_mcp_client, inbound_mcp_source, inbound_mcp_tool, inbound_mcp_scope, inbound_mcp_resource_operation, and inbound_mcp_target.
    • Added quick-create buttons for the initial list_personal_tags policy set, including *, list_personal_tags, personal, personal:tags:list, and personal:* defaults.
    • Extended the delegated item-policy editor to use custom item IDs for inbound MCP policy entities.
    • Added functional and Playwright UI regression coverage.
    • Bumped app version to 0.250.077 and updated inbound MCP docs/release notes.

    Validation:

    • python -m py_compile application\single_app\config.py functional_tests\test_inbound_mcp_admin_ui.py functional_tests\test_inbound_mcp_server_shell.py functional_tests\test_inbound_mcp_governance_and_tools.py ui_tests\test_admin_inbound_mcp_easy_auth_modal.py ui_tests\test_admin_inbound_mcp_governance_ui.py
    • node --check application\single_app\static\js\admin\admin_governance.js
    • node --check application\single_app\static\js\admin\admin_settings.js
    • python functional_tests\test_inbound_mcp_admin_ui.py
    • python functional_tests\test_inbound_mcp_server_shell.py
    • python functional_tests\test_inbound_mcp_governance_and_tools.py
    • python functional_tests\route_tests\test_route_blueprint_policy_inventory.py
    • python functional_tests\route_tests\test_route_unauthenticated_policy_contract.py
    • python functional_tests\route_tests\test_route_policy_test_coverage.py
    • python -m pytest functional_tests\test_inbound_mcp_server_shell.py functional_tests\test_inbound_mcp_governance_and_tools.py functional_tests\test_inbound_mcp_admin_ui.py ui_tests\test_admin_inbound_mcp_easy_auth_modal.py ui_tests\test_admin_inbound_mcp_governance_ui.py -v => 16 passed, 2 skipped because the UI environment/storage state is not configured.
    • git -c core.whitespace=blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol diff --check

    Follow-up:

    • After deploying and creating the inbound MCP policies, retry the live SimpleChatDemoMCP call. If it still denies, use the returned governance dimension/error to add the missing item policy.
  11. Bionic711 commented on Jul 19, 2026

    @Bionic711
    CollaboratorAuthor

    Implemented the v0.250.079 MCP governance policy help modal update.

    Summary:

    • Added reusable modal-backed info/help buttons next to outbound MCP destination and inbound MCP governance quick-create buttons.
    • Added policy-specific guidance describing purpose, safe usage, and example configuration values using fake fedorg.gov examples.
    • Kept the implementation in local SimpleChat static JavaScript with text-only modal content.
    • Updated Admin Settings source/UI coverage, inbound MCP docs, the master MCP robustness plan, and release notes.

    Validation:

    • Python compile passed for config, inbound MCP functional tests, and related UI tests.
    • JS syntax checks passed for admin_governance.js and admin_settings.js.
    • Inbound MCP functional/source tests passed.
    • Route policy tests passed.
    • Targeted pytest suite: 16 passed, 2 skipped because UI environment/storage state is not configured.
    • git diff --check passed.
  12. Bionic711 commented on Jul 20, 2026

    @Bionic711
    CollaboratorAuthor

    Implemented the v0.250.080 inbound MCP governance simplification.

    Summary:

    • Simplified current inbound MCP governance from six required policy dimensions to two production-facing policy types:
      • inbound_mcp_access with delegated item personal
      • inbound_mcp_source with delegated item * or a resolved source value
    • Kept tenant/client trust in Inbound MCP runtime configuration instead of duplicating client allowlisting as governance.
    • Removed Admin Settings quick-create buttons for legacy client, tool, scope, resource-operation, and target policy types.
    • Preserved backend compatibility fallback for legacy inbound_mcp_scope/personal and inbound_mcp_target/personal:* or personal:<delegated-user-id> policies.
    • Updated Admin Settings guidance so allow-all/users/groups are the user authorization controls and item IDs no longer encode user wildcards.
    • Updated functional/UI tests, inbound MCP architecture docs, the master MCP robustness plan, release notes, and bumped app version to v0.250.080.

    Validation:

    • Python compile passed for changed inbound MCP/governance files and related tests.
    • JS syntax checks passed for admin_governance.js and admin_settings.js.
    • Inbound MCP functional/source tests passed.
    • Route policy tests passed.
    • Targeted pytest suite: 16 passed, 2 skipped because UI environment/storage state is not configured.
    • git diff --check passed.
  13. Bionic711 commented on Jul 21, 2026

    @Bionic711
    CollaboratorAuthor

    Implemented final inbound MCP governance simplification for the current phase.

    Summary:

    • Collapsed current inbound MCP governance to one broad inbound_mcp_access policy using delegated item inbound_mcp.
    • Removed source as a required user-bound governance policy; source trust remains in Inbound MCP runtime configuration via inbound_mcp_allowed_source_ids and the configured source signal/header.
    • Updated Admin Settings > Governance to quick-create only the new inbound MCP access policy and moved source policy to legacy compatibility surfaces.
    • Preserved backend compatibility fallback for legacy scope/target policies and kept inbound_mcp_source recognizable as a legacy policy type.
    • Updated inbound MCP docs, master MCP plan, release notes, functional tests, UI tests, and version markers to 0.250.081.

    Validation:

    • python -m py_compile for changed Python files and tests: passed.
    • node --check for admin_governance.js and admin_settings.js: passed.
    • Inbound MCP functional source-contract tests: 16/16 passed.
    • Route policy tests: 12/12 passed.
    • Targeted functional pytest: 19 passed, 3 existing return-value warnings.
    • Targeted UI pytest: 3 skipped because local Playwright/storage-state environment is not configured.
    • git diff --check: passed.

    Live MCP retest without Azure CLI:

    • Used the VS Code public client via MSAL device-code flow, not Azure CLI.
    • Token contained tenant 228db43d-371a-49d8-864e-fa202d181ea5, client aebc6443-996d-45c2-90f0-388ff96faa56, scope DelegatedMcpServerAccess, and role InboundMCPUserAccess.
    • /api/mcp initialize: HTTP 200, server version 0.250.081.
    • tools/list: HTTP 200, included list_personal_tags.
    • tools/call list_personal_tags: HTTP 200, returned 5 personal tags.

    Follow-up note:

    • The first non-CLI retest correctly failed with mcp_client_not_allowed until the VS Code public client ID was added to the Inbound MCP runtime allowed client application IDs. After that was saved, the non-CLI retest succeeded.
  14. Bionic711 commented on Jul 21, 2026

    @Bionic711
    CollaboratorAuthor

    Implemented the next Track B Phase B3 inbound MCP slice for version 0.250.082.

    What changed:

    • Added delegated-user-scoped inbound MCP conversation read tools:
      • list_conversations
      • get_conversation_messages
    • Kept tool execution bound to the authenticated delegated user; no caller-supplied user_id is accepted.
    • Reused existing SimpleChat personal conversation and personal-collaboration authorization boundaries.
    • Added bounded pagination and message content truncation for predictable MCP responses.
    • Added JSON-RPC error mapping for invalid parameters, object-level authorization denial, and missing resources.
    • Updated inbound MCP docs, master MCP robustness plan, tests, and release notes.

    Validation completed:

    • Python syntax compilation for changed MCP source/test files: passed.
    • functional_tests/test_inbound_mcp_governance_and_tools.py: 5/5 passed.
    • functional_tests/test_inbound_mcp_server_shell.py: 6/6 passed.
    • Route policy tests: passed.
    • Latest Features tests: passed.
    • Targeted pytest: 20 passed; UI Playwright tests skipped where local UI env/storage state is not configured.
    • git diff --check: passed.

    Notes:

    • This is implemented locally on the feature branch and still needs deployment before live MCP endpoint retesting can cover the new conversation tools.
    • The likely next Phase B3 tools are list_personal_documents and list_personal_prompts before moving toward search or workflow execution.
  15. Bionic711 commented on Jul 21, 2026

    @Bionic711
    CollaboratorAuthor

    Implemented the next Track B Phase B3 inbound MCP slice for version 0.250.083.

    What changed:

    • Added delegated-user-scoped inbound MCP metadata listing tools:
      • list_personal_documents
      • list_personal_prompts
    • Kept tool execution bound to the authenticated delegated user; no caller-supplied user_id is accepted.
    • Document listings reuse SimpleChat's existing personal document visibility boundary, current-revision selection, and sorting.
    • Document responses are metadata-only and include owned/shared relationship plus shared approval status.
    • Prompt listings return bounded prompt metadata only; prompt content is not returned by the list tool.
    • Added bounded limit/offset schemas and a single safe document tag filter.
    • Updated inbound MCP docs, master MCP robustness plan, tests, version markers, and release notes.

    Validation completed:

    • Python syntax compilation for changed MCP source/test files: passed.
    • functional_tests/test_inbound_mcp_governance_and_tools.py: 6/6 passed.
    • functional_tests/test_inbound_mcp_server_shell.py: 6/6 passed.
    • functional_tests/test_inbound_mcp_admin_ui.py: 6/6 passed.
    • Latest Features functional tests: passed.
    • Route policy tests: passed.
    • Targeted functional pytest: 21 passed with the existing bool-return warnings.
    • Targeted UI pytest: 3 skipped because the local UI environment/storage state is not configured.
    • git diff --check: passed.

    Notes:

    • A combined pytest invocation across functional and UI latest-feature nav tests hits the existing duplicate module basename collection issue; running the functional and UI groups separately passes/skips as expected.
    • This is implemented locally on the feature branch and still needs deployment before live MCP endpoint retesting can cover the new document and prompt listing tools.
    • The likely next Phase B3 candidate is search_personal_documents; execute_workflow should remain later because it is execution/write-like and needs separate guardrails.
  16. Bionic711 commented on Jul 21, 2026

    @Bionic711
    CollaboratorAuthor

    Implemented an inbound MCP OAuth discovery compatibility fix locally in v0.250.085.

    Root cause / behavior:

    • VS Code was still redirecting to the SimpleChat host /authorize even when oauth.clientId was configured.
    • Direct probes showed Microsoft Entra exposes OIDC metadata at /v2.0/.well-known/openid-configuration, but does not expose RFC8414 oauth-authorization-server metadata at the generic OAuth discovery paths VS Code appears to require.
    • When that discovery fails, VS Code falls back to assuming the SimpleChat origin is the authorization server and tries /authorize, which SimpleChat does not implement.

    Fix:

    • Added a SimpleChat-hosted OAuth Authorization Server Metadata bridge at /.well-known/oauth-authorization-server.
    • Updated inbound MCP Protected Resource Metadata to advertise the SimpleChat public host as the authorization server issuer for RFC8414 discovery.
    • The bridge returns Entra authorization_endpoint, token_endpoint, and jwks_uri values derived from the configured AUTHORITY.
    • Qualified the delegated scope for OAuth client requests as api://<CLIENT_ID>/<scope> while retaining SimpleChat token validation against the bare scp claim value.
    • Added the new metadata bridge path to inbound MCP guard bypass, App Service Authentication exclusion checks, setup script guidance, Admin Settings modal copy, route policy coverage, docs, and tests.

    Validation:

    • Syntax compile passed for changed app/test files.
    • Direct functional contract tests passed:
      • test_inbound_mcp_server_shell.py: 6/6
      • test_inbound_mcp_admin_ui.py: 6/6
      • test_inbound_mcp_governance_and_tools.py: 7/7
      • latest-features functional tests: passed
    • Route policy tests passed: 6/6, 4/4, 2/2.
    • Targeted functional pytest passed: 22 passed, with 3 existing bool-return warnings in latest-features tests.
    • Targeted UI pytest skipped as expected because local UI environment/storage state is not configured: 3 skipped.
    • git diff --check passed.

    Deployment/retest note:

    • The live App Service needs v0.250.085 deployed and must include the additional Easy Auth excluded path /.well-known/oauth-authorization-server before VS Code MCP auth should be retested.
    • If VS Code gets past discovery, the next thing to watch is whether the VS Code MCP client app registration accepts the dynamic loopback redirect URI.
  17. Bionic711 commented on Jul 21, 2026

    @Bionic711
    CollaboratorAuthor

    0.250.086 follow-up for inbound MCP OAuth discovery is implemented locally.

    What changed:

    • Normalized inbound MCP public metadata/challenge URLs so non-local hosted deployments advertise https:// even when App Service forwards to Flask over internal HTTP.
    • Reused the same public-base-url helper for PRM, OAuth authorization-server metadata, and WWW-Authenticate resource_metadata challenges.
    • Preserved HTTP for localhost/loopback development.
    • Added release notes for v0.250.086.

    Validation:

    • python -m py_compile on the changed inbound MCP app/test files passed.
    • python functional_tests/test_inbound_mcp_server_shell.py passed (6/6).
    • python functional_tests/test_inbound_mcp_admin_ui.py passed (6/6).
    • python functional_tests/test_inbound_mcp_governance_and_tools.py passed (7/7).
    • Latest Features functional tests passed.
    • Route policy tests passed: blueprint inventory, unauthenticated contract, and policy coverage.
    • Targeted functional pytest passed: 22 passed with the existing bool-return warnings.
    • Targeted UI pytest skipped as expected because the local UI environment/storage state is not configured.
    • git diff --check passed.

    Follow-up after deployment:

    • Re-probe /.well-known/oauth-protected-resource/mcp, /.well-known/oauth-authorization-server, and unauthenticated POST /api/mcp on the live App Service.
    • Confirm PRM authorization_servers, OAuth metadata issuer, and the 401 WWW-Authenticate resource_metadata URL all use https://simplechatdemo-....
    • Then retry VS Code MCP auth. If it still opens /authorize, next investigation should focus on VS Code discovery/cache behavior or loopback redirect URI handling in the MCP client app registration.
  18. Bionic711 commented on Jul 21, 2026

    @Bionic711
    CollaboratorAuthor

    Inbound MCP PRM alias compatibility update is complete locally for v0.250.087.

    What changed:

    • Added root, resource-path, and legacy protected-resource metadata aliases for MCP OAuth discovery:
      • /.well-known/oauth-protected-resource
      • /.well-known/oauth-protected-resource/api/mcp
      • /.well-known/oauth-protected-resource/mcp
    • Updated the primary WWW-Authenticate resource_metadata challenge to point at the /api/mcp-derived PRM alias.
    • Updated Easy Auth exclusion checks, generated setup script guidance, Admin Settings modal text, route policy coverage, and inbound MCP source-contract tests for all aliases.
    • Documented the live environment naming distinction:
      • App Service target: simplechatdemo in RG-Demos
      • API/auth app/SP: SimpleChatApp / 81dce308-4d9d-4fd9-953e-2844ad0578e4
      • legacy App Service simplechatapp is not the MCP validation target.

    Validation:

    • python -m py_compile on changed inbound MCP app, route, functional test, route test, and UI test Python files.
    • python functional_tests\test_inbound_mcp_server_shell.py - 6/6 passed.
    • python functional_tests\test_inbound_mcp_admin_ui.py - 6/6 passed.
    • python functional_tests\test_inbound_mcp_governance_and_tools.py - 7/7 passed.
    • Route policy tests passed.
    • Latest Features functional tests passed.
    • Targeted functional pytest passed: 22 passed, with 3 existing bool-return warnings.
    • Targeted UI pytest skipped because the local UI environment/storage state is not configured.
    • git diff --check passed.

    Next live check after v0.250.087 deploy:

    • All three PRM aliases should return 200 JSON.
    • /.well-known/oauth-authorization-server should return 200 JSON.
    • Unauthenticated /api/mcp should challenge with https://<host>/.well-known/oauth-protected-resource/api/mcp.
  19. Bionic711 commented on Jul 23, 2026

    @Bionic711
    CollaboratorAuthor

    Implemented the inbound MCP settings/governance UI hardening for v0.250.091.

    Summary:

    • Converted inbound MCP delegated/app role settings to single-value fields while preserving derived legacy lists for runtime compatibility.
    • Converted allowed client apps, tenant IDs, and source IDs to { value, description } entry lists with add/edit/remove modal behavior.
    • Added tenant/source toggles: tenants default to the SimpleChat tenant only; sources default to allow-all.
    • Added a locked system-managed inbound_mcp_source:* policy that is created/removed from the source allow-all toggle and cleans up stale wildcard source policies.
    • Updated runtime governance so inbound MCP now requires both inbound_mcp_access and inbound_mcp_source allow policies.
    • Updated Governance UI source policy creation to use a dropdown populated from configured source IDs, with system-managed wildcard policies locked from edit/delete.
    • Added an Admin Settings “About MCP & Tools” modal backed by the MCP tool registry.

    Validation:

    • Python syntax compile on changed app/test files passed.
    • node --check passed for admin_settings.js and admin_governance.js.
    • Targeted functional pytest passed: 23 passed, with 3 existing bool-return warnings.
    • Route policy tests passed: 6/6, 4/4, and 2/2.
    • Targeted UI pytest skipped as expected because local Playwright/storage state is not configured.
    • git diff --check passed.

    Follow-ups:

    • Deploy v0.250.091 before live MCP retesting.
    • When validating live, confirm Admin Settings save creates the locked wildcard source policy only while inbound MCP and allow-all source IDs are enabled.
  20. Bionic711 commented on Jul 23, 2026

    @Bionic711
    CollaboratorAuthor

    Implemented source-only inbound MCP governance in v0.250.092.

    Summary:

    • Active inbound MCP governance now uses only inbound_mcp_source policies.
    • inbound_mcp_source:* allows selected users/groups to use any runtime-accepted source; specific source IDs restrict users/groups to that source.
    • Removed inbound_mcp_access from runtime evaluation and Admin Settings/Governance quick-create/filter/help UI.
    • Removed save-time auto-create/delete of the locked system-managed wildcard source policy.
    • Runtime ignores stale system-allow-all-sources rows so old auto-created wildcard policies do not silently grant access.
    • Governance UI now offers * as an admin-managed source option and shows configured source IDs when source filtering is controlled.
    • Updated docs, release notes, functional tests, UI tests, latest-feature markers, and bumped application\single_app\config.py to 0.250.092.

    Validation:

    • Python syntax compile passed for changed app/test files.
    • node --check passed for application\single_app\static\js\admin\admin_governance.js and application\single_app\static\js\admin\admin_settings.js.
    • Standalone source-contract tests passed: inbound MCP admin UI (6/6), governance/tools (8/8), server shell (6/6), latest-feature checks (3/3).
    • Targeted functional pytest passed: 23 passed, with the existing bool-return warnings.
    • Targeted UI pytest skipped because local UI environment/storage state is not configured.
    • Route policy tests passed.
    • git diff --check passed.

    Follow-up:

    • If a stale locked system-allow-all-sources row exists in a live environment, it is ignored by runtime after this change but may still need manual cleanup if admins want it removed from the policy list.
  21. Bionic711 commented on Jul 23, 2026

    @Bionic711
    CollaboratorAuthor

    Follow-up implemented in v0.250.093 for inbound MCP source-governance admin guidance.

    Summary:

    • Removed stale Admin Settings text that still said the source allow-all toggle creates a locked system-managed wildcard policy.
    • Added source-governance callouts in the Inbound MCP Server source settings card explaining that tools require an inbound_mcp_source governance policy before they are returned.
    • Added a Create Wildcard Source Policy button when all sources are accepted at the runtime allowlist layer; it opens the Governance source policy editor for inbound_mcp_source:*.
    • Added a Create Source Policy button when source IDs are controlled; it opens the Governance source policy editor so admins can choose * or a configured source ID.
    • Buttons switch admins to the Governance tab and open the policy editor in restricted user/group mode by default.
    • Updated docs, release notes, UI tests, source-contract tests, and bumped application\single_app\config.py to 0.250.093.

    Validation:

    • Python syntax compile passed for changed app/test files.
    • node --check passed for admin_settings.js and admin_governance.js.
    • Standalone source-contract checks passed.
    • Targeted functional pytest passed: 23 passed, with the existing bool-return warnings.
    • Targeted UI pytest skipped because local UI environment/storage state is not configured.
    • git diff --check passed.
  22. Bionic711 commented on Jul 23, 2026

    @Bionic711
    CollaboratorAuthor

    Implemented v0.250.094 follow-up for inbound MCP workflow execution clarity.

    What changed:

    • Added delegated-user-scoped list_personal_workflows so MCP clients can discover generated workflow IDs before calling execute_workflow.
    • Clarified execute_workflow schema/description and not-found messaging: workflow_id is the generated workflow document ID, not the display name.
    • Updated JSON-RPC tool errors to preserve a successful HTTP transport response and include the intended HTTP status in error data, reducing client-side "Canceled" masking.
    • Marked failed execute_workflow results with MCP isError: true when the workflow runner returns success: false.
    • Updated inbound MCP architecture/robustness docs and release notes.

    Validation:

    • python -m py_compile passed for changed Python modules and MCP tests.
    • python functional_tests\test_inbound_mcp_governance_and_tools.py passed: 9/9.
    • python functional_tests\test_inbound_mcp_server_shell.py passed: 6/6.
    • Route policy tests passed: 6/6, 4/4, and 2/2.
    • git diff --check passed.

    Live retest:

    • Retesting execute_workflow with generated workflow ID 5c8c6443-5a2e-4e73-bcb9-463c973a93c3 reached the workflow runner, confirming the prior display-name lookup/404 issue was bypassed.
    • The workflow itself failed because no recent documents were found in the last 10 minutes, which is a workflow business-rule failure rather than an MCP ID-resolution failure.
  23. Bionic711 commented on Jul 27, 2026

    @Bionic711
    CollaboratorAuthor

    Implemented v0.250.095 outbound MCP discovery logging hardening.

    What changed:

    • Added per-discovery mcp_operation_id correlation IDs to outbound MCP discovery.
    • Added structured discovery lifecycle telemetry for start/completed/failed states with duration, HTTP status, category, and failure stage.
    • Added safe destination logging context: host, path, port, preconfiguration id, server profile, and short endpoint hash without raw endpoint query strings or secret-bearing values.
    • Threaded the operation id through destination policy checks and connector creation.
    • Added factory-level retry/failure telemetry for outbound MCP operations.
    • Removed raw endpoint debug logging from MCP remote connector creation.
    • Added functional_tests/test_mcp_outbound_logging.py.
    • Updated MCP robustness plan and release notes.

    Validation:

    • Python compile passed for changed outbound MCP/logging modules and tests.
    • python functional_tests\test_mcp_outbound_logging.py passed.
    • python functional_tests\test_mcp_phase2_probe_metadata.py passed.
    • python functional_tests\test_mcp_destination_governance_and_preconfigurations.py passed.
    • python functional_tests\test_unified_logging_entrypoint.py passed with PYTHONUTF8=1.
    • Route policy tests passed: 6/6, 4/4, and 2/2.
    • git diff --check passed.

    Next planned MCP work:

    • Resume Track B Phase B6 enterprise readiness hardening. The plan labels this as Phase B6, not 6B.
  24. Bionic711 commented on Jul 27, 2026

    @Bionic711
    CollaboratorAuthor

    Track B Phase B6 inbound MCP enterprise-readiness hardening is implemented in v0.250.096.

    Summary:

    • Added shared inbound MCP enterprise helpers for request correlation, safe telemetry context, and Cosmos-backed per-tool rate-limit counters.
    • Added app-settings-backed controls for request size and read/search/write throttle limits.
    • Enhanced /api/mcp with mcp_request_id, X-Correlation-ID response headers, request-size checks, request lifecycle telemetry, and safer JSON-RPC error correlation.
    • Enhanced tool execution telemetry so governance denials, object authorization denials, validation errors, conflicts, not-found errors, workflow business-rule failures, rate-limit denials, and rate-limit store failures are distinguishable in Application Insights.
    • Enhanced auth-guard telemetry so auth/runtime-source failures remain distinct from SimpleChat governance denials.
    • Kept throttles multi-instance safe with Cosmos optimistic concurrency and safe hashed caller/category counters instead of process-local memory.

    Validation:

    • Python compile passed for changed inbound MCP app/test modules.
    • python functional_tests\test_inbound_mcp_server_shell.py passed: 7/7.
    • python functional_tests\test_inbound_mcp_governance_and_tools.py passed: 9/9.
    • python functional_tests\test_inbound_mcp_admin_ui.py passed: 6/6.
    • Latest Features functional checks passed.
    • Route policy tests passed: 6/6, 4/4, and 2/2.
    • python functional_tests\test_mcp_outbound_logging.py passed.
    • Targeted functional pytest passed: 25 passed, with the existing bool-return warnings.
    • Targeted UI pytest collected and skipped 3 tests because local UI storage state is not configured.
    • git diff --check passed.

    Follow-ups to consider:

    • Add Admin Settings UI controls for inbound MCP request-size and throttle limits.
    • Add App Insights dashboards/workbooks or saved KQL for request/tool/auth/governance/rate-limit telemetry.
    • Add per-client/per-source override limits if operations need more granular throttling than the current category defaults.
  25. Bionic711 commented on Jul 27, 2026

    @Bionic711
    CollaboratorAuthor

    MCP hygiene status: recommended close-on-merge for the upcoming MCP PR.

    Track B Phase B0-B2 inbound MCP architecture/auth/PRM/governance work is implemented in the working branch. The inbound server foundation now uses the SimpleChat-hosted streamable HTTP JSON-RPC route, PRM/OAuth metadata discovery, Easy Auth setup/verification guidance, runtime config, and source-first governance controls.

    PR prep note for the later PR body: include Closes #1017 so this issue closes when the PR lands on main, currently targeted for Aug 7.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestsecurity_improvementThis issue results in an improvement to security

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions