Build a ConnectWise PSA MCP server driven by my API definition JSON and an explicit allow/deny policy. Connect it to Microsoft Foundry and document the setup with real screenshots embedded beside the relevant tutorial steps. My environment: - API definition JSON file: [LOCAL PATH TO CONNECTWISE All.json] - Allowed operation IDs: [EXACT operationId VALUES FROM THAT FILE] - Denied operation IDs: [EXACT operationId VALUES] - Enable write-capable operations: [true OR false] - Denied HTTP methods: [FOR EXAMPLE DELETE] - Azure subscription and dedicated resource group: [SUBSCRIPTION AND GROUP] - Azure region and permitted model processing geography: [VALUES] - Maximum pilot spend: [AMOUNT AND CURRENCY] - ConnectWise credentials: [SECURE LOCAL FILE PATH, NEVER SECRET VALUES] - Synthetic records authorized for testing: [IDS AND PERMITTED ACTIONS] Read the actual API file first. Inventory its version, operation IDs, paths, methods, parameters, request bodies and local schema references. Do not invent endpoints or replace the integration with a hard-coded ticket tool. Register one MCP tool per permitted operation. Let the administrator change the available calls through JSON without adding a Python function for each endpoint. Use a separate policy.json with default deny, exact allow and deny lists, an allowWrites boolean and denyMethods. Deny must win. GET and HEAD may pass the read gate. Other methods require allowWrites=true as well as an explicit allow entry. Missing, malformed or unknown policy entries must fail closed. Check permission at both registration and invocation so calling a hidden tool directly cannot bypass policy. Recheck the local policy for each call. Restart the host and refresh discovery after deployment changes. Keep the API file and policy writable only by administrators. Use Python 3.12 and Azure Functions Flex Consumption with the MCP extension at /runtime/webhooks/mcp. Generate tool properties from the imported parameters. Validate complete input schemas on the server. Preserve JSON request bodies, including ConnectWise JSON Patch arrays. Unsupported allowed operations must produce a clear startup error, not silently disappear. Identify discrepancies in the vendor schema and validate selected operations against PSA before claiming full compatibility. Fix the PSA base URL and credentials in protected server settings. Never let tool arguments choose the host, method, credentials or policy. Use managed identity for Azure storage. Protect the MCP endpoint with the mcp_extension system key sent in x-functions-key. Match the PSA API member's security role to the permitted actions. Explain that this shared connection controls operations, not individual technicians or company rows. Do not claim per-company or field-level restrictions unless implemented and tested. Prepare the exact resource, cost and access changes for review before deployment. After approval, carry out that scope without asking again for the same action. Obtain missing credentials through a secure local file. Keep credentials and customer content out of screenshots, prompts and logs. Keep always-ready instances off for the pilot. Test catalog import, discovery, allowed reads, blocked direct calls, deny precedence, disabled writes, explicitly allowed writes against a mock service, invalid inputs, policy revocation and upstream failures. Never retry an uncertain write automatically. Live write tests require the specified synthetic records and authorized actions. Capture and embed real screenshots of completed Azure steps. Label local, deployed and live-provider evidence separately. Deliver the source, JSON examples, tutorial and remaining prerequisites.