Feature Discussion: gateway compatibility for Power Platform / Copilot Studio #126
Replies: 3 comments 3 replies
-
|
hi @zlucas-netapp thanks for the great discussion!
|
Beta Was this translation helpful? Give feedback.
-
|
This was spot on. Thanks @cgrinds! I removed the middleware layer and updated the go.mod and the connector checked out! I will raise an issue on number 1 and is there a timeline on when that pre-release will be in ONTAP MCP? Want to make sure I have this documentation for correct for the customer I am working with. |
Beta Was this translation helpful? Give feedback.
-
|
For this connector path, I would document the security and operability assumptions very explicitly because the architecture crosses several trust zones. The flow is effectively: Copilot Studio -> Power Platform cloud -> on-premises data gateway -> ONTAP MCP server -> storage management APIs A few controls seem worth making first-class in the guidance:
An The integration also seems like a good candidate for a minimal "safe profile" example: read/list tools first, then a separate expanded profile for controlled write/admin tools. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Deploying ONTAP MCP behind Power Platform On-Premises Data Gateway for Copilot Studio
Preface
This is in relation to issue #119 where the stateless mode did help but did not solve the full integration issue with CoPilot Studio. I ended up recreating the environment locally in our lab, forking the current repo and working through this problem with GitHub Copilot - by no means am I an experienced developer and unsure if the proposed fixes our to invasive on the larger codebase. However, this does work and allowed me to give an agent in CoPilot Studio access to my on-prem MCP. I would like guidance around potentially implementing this and raising an issue for the correct integration to make this a reality for all users. All discussion and feedback is welcome. Below is CoPilots summary of the issues and what was done to resolve.
Scenario
I'm connecting ONTAP MCP to Microsoft Copilot Studio via the Power Platform on-premises data gateway. The goal is to let a Copilot Studio agent use ONTAP MCP tools natively through a custom connector, without exposing the MCP server to the internet.
Architecture:
The custom connector is created from a Swagger 2.0 spec with
x-ms-agentic-protocol: mcp-streamable-1.0— this tells Copilot Studio to treat the endpoint as a native MCP server and handle tool discovery/invocation automatically.Custom Connector Swagger Spec
This is the full spec imported into Power Platform as a custom connector:
Key points:
x-ms-agentic-protocol: mcp-streamable-1.0is what makes Copilot Studio treat this as an MCP endpointx-ms-visibility: internalhides the header params from the agent — they're sent automaticallyErrors Encountered
Error 1: Generic gateway failure (SSE incompatibility)
With the stock ONTAP MCP server, every request from Copilot Studio returned:
No logs appeared on the MCP server at all — the gateway rejected the response before forwarding it. The root cause: ONTAP MCP responds with
Content-Type: text/event-streamandTransfer-Encoding: chunked. The on-premises data gateway does not support relaying SSE/chunked streams. It expects a complete response body withContent-Type: application/json.Error 2: HTTP 415 — Content-Type validation failure
After enabling
--json-response(which makes the server return JSON instead of SSE), requests started reaching the server but were rejected with:The
--inspect-trafficflag confirmed the JSON-RPC body arrived intact, but the Go MCP SDK rejected the request at this validation point instreamable.go:baseMediaType()uses Go'smime.ParseMediaType(). The gateway sends something that string-compares as"application/json"but failsmime.ParseMediaType()— likely a BOM, trailing whitespace, or non-standard charset parameter. The body is fine; only the header is broken.Code Changes That Fixed It
Change 1:
--json-responseCLI flagWires the existing
StreamableHTTPOptions.JSONResponseSDK field to a CLI flag so the server returnsapplication/jsonresponses instead oftext/event-stream. This is already MCP spec-compliant per §2.1.5.cmd/cmds.go — added field to
StartCmd:server/server.go — added to
Optionsstruct and wired toStreamableHTTPOptions:This fixed Error 1 — the gateway could now relay the complete JSON response body.
Change 2: Header normalization middleware
Added to the existing
wrappedHandlerinserver/server.go, positioned before the SDK handler receives the request:This unconditionally overwrites both headers on every POST before the SDK validates them. The body is untouched — only the metadata is normalized.
This fixed Error 2 — the SDK no longer rejects gateway requests.
Final Deployment
--statelessMcp-Session-Idheaders between requests.--json-response--read-onlyResult
Copilot Studio agent successfully:
initialize→tools/listlist_registered_clusters,ontap_get,search_ontap_endpoints, etc.)Questions for the Team
Would a PR adding the
--json-responseflag be welcome? It's a minimal change (wires an existing SDK field) and enables any deployment behind a non-SSE-compatible proxy.Header normalization approach: My implementation is unconditional (always rewrites). A cleaner upstream version might be a
--gateway-compatflag that opts into lenient header handling. Thoughts on the right pattern?Tool count filtering: Copilot Studio caps at 70 tools. ONTAP MCP registers ~72 with catalog tools. Would a
--tagsor--include-toolsflag for selective tool registration be useful?Beta Was this translation helpful? Give feedback.
All reactions