Summary
The MCP 2026-07-28 ("MCP 2.0") specification replaces the initialize handshake with a
stateless, per-request protocol model. This issue tracks making ISHRemoteMcpServer a
dual-era server: serving modern requests at 2026-07-28 while still answering the
legacy initialize handshake for existing clients.
Companion issue: #243 — fixes the stdin-EOF infinite loop that this work also depends on.
Why this is a good investment
MCP 2.0 is not just a different protocol version — it is a measurably better platform for
agentic automation of Tridion Docs Content Manager. The table below maps each spec change
to a concrete improvement for ISHRemote users and their LLM clients.
| MCP 2.0 change |
What is better today vs. before |
| Stateless per-request protocol |
A crashed or restarted MCP server process loses no session state; clients retry in-flight requests against the fresh process without re-initializing. Today a dead server leaves the LLM stuck waiting for a handshake that will never arrive. |
server/discover (mandatory) |
AI tools (VS Code, Claude Desktop, Cursor, GitHub Copilot) can enumerate the server's capabilities, supported versions, and instructions in a single call before invoking any tool. No separate probe-then-initialize round trip; faster startup and better IDE integration. |
resultType: "complete" / "input_required" |
The client knows structurally whether a result is final or whether the server needs more information (Multi Round-Trip Requests). Today every result looks the same to the client regardless of whether the tool succeeded or is mid-flight. |
isError: true in tools/call results |
Tool execution errors (invalid field names, session not found, Tridion Docs API failures) are surfaced to the LLM as actionable feedback. The LLM can self-correct and retry with adjusted parameters. Today errors are swallowed into the log (Invoke-IshRemoteMcpHandleRequest.ps1:53-66) and the LLM receives no signal that anything went wrong, producing silent wrong answers. |
Protocol error -32602 for unknown tool |
A misconfigured or hallucinated tool name returns a clear JSON-RPC error the client can surface to the user. Today the server silently returns an empty result. |
structuredContent + outputSchema |
Tools can return typed JSON objects alongside the human-readable text. LLMs and downstream scripts can parse and validate results reliably instead of extracting data from free-form Out-String output. Enables richer agentic pipelines. |
Caching hints (ttlMs, cacheScope) on tools/list |
The large ISHRemote tool list (100+ cmdlets) can be cached by the client, cutting token usage and latency on every conversation that needs it. Also improves LLM prompt-cache hit rates when the tool list is included in the system prompt. |
Version negotiation (-32022) |
Server and client can independently upgrade to future MCP versions. If a client speaks a version the server does not support, it gets a structured error with the supported list and retries — no silent breakage. |
title on tool definitions |
IDE and chat UIs display a clean human-readable label (e.g. Get ISH Folder) separate from the programmatic cmdlet name (Get-IshFolder), improving discoverability for end users. |
| EOF exit (companion #243) |
Server process exits cleanly when the client closes stdin, eliminating orphaned hidden pwsh processes that accumulate across sessions. |
Current state
Invoke-IshRemoteMcpHandleRequest.ps1 is pure legacy-era 2024-11-05:
- Line 17 —
initialize returns hardcoded "protocolVersion":"2024-11-05" and placeholder
serverInfo "PowerShell MCP Server (Template)" / "0.2.0".
- No
server/discover; modern clients receive -32601 and fall back to initialize, so
nothing breaks today — but the server is pinned to 2024-11-05 semantics and gains none of
the improvements above.
- Lines 53-66 —
tools/call swallows all execution errors and always returns isError:false.
- Unknown tool returns an empty result rather than a protocol error.
Proposed change — dual-era server
Keep the legacy initialize branch intact for existing clients; add modern handling alongside it.
- Era detection — request carries
_meta["io.modelcontextprotocol/protocolVersion"]
→ modern path; method == "initialize" → legacy path.
server/discover → DiscoverResult with supportedVersions (e.g. ["2026-07-28"]),
capabilities, resultType: "complete", ttlMs, cacheScope, instructions (reuse
Register-IshRemoteMcpInstructions), _meta serverInfo.
resultType: "complete" on all modern ping, tools/list, and tools/call results;
add required ttlMs / cacheScope to tools/list.
- Version gate — unsupported
_meta version → -32022
UnsupportedProtocolVersionError with data.supported.
tools/call semantics — unknown tool → protocol error -32602; tool execution
errors → result with isError: true so the LLM can self-correct.
- serverInfo — replace placeholder with
ISHRemoteMcpServer and the actual module version.
Register-IshRemoteMcpTool.ps1 — add title; use
{"type":"object","additionalProperties":false} for no-parameter tools.
Files
Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Invoke-IshRemoteMcpHandleRequest.ps1
Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Start-IshRemoteMcpServer.ps1
Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Register-IshRemoteMcpTool.ps1
Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Invoke-IshRemoteMcpHandleRequest.Tests.ps1
Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Start-IshRemoteMcpServer.Tests.ps1
Test plan
Extend Invoke-IshRemoteMcpHandleRequest.Tests.ps1:
server/discover returns correct shape (supportedVersions, capabilities, resultType,
ttlMs, cacheScope, instructions, _meta.serverInfo).
- All modern results include
resultType: "complete".
- Unsupported
_meta version returns -32022 with data.supported.
- Unknown tool returns
-32602.
- Tool execution error returns result with
isError: true.
- Legacy
initialize still returns "protocolVersion":"2024-11-05" (dual-era regression test).
Spec references
Summary
The MCP
2026-07-28("MCP 2.0") specification replaces theinitializehandshake with astateless, per-request protocol model. This issue tracks making ISHRemoteMcpServer a
dual-era server: serving modern requests at
2026-07-28while still answering thelegacy
initializehandshake for existing clients.Companion issue: #243 — fixes the stdin-EOF infinite loop that this work also depends on.
Why this is a good investment
MCP 2.0 is not just a different protocol version — it is a measurably better platform for
agentic automation of Tridion Docs Content Manager. The table below maps each spec change
to a concrete improvement for ISHRemote users and their LLM clients.
server/discover(mandatory)instructionsin a single call before invoking any tool. No separate probe-then-initialize round trip; faster startup and better IDE integration.resultType: "complete"/"input_required"isError: trueintools/callresultsInvoke-IshRemoteMcpHandleRequest.ps1:53-66) and the LLM receives no signal that anything went wrong, producing silent wrong answers.-32602for unknown toolstructuredContent+outputSchemaOut-Stringoutput. Enables richer agentic pipelines.ttlMs,cacheScope) ontools/list-32022)titleon tool definitionsGet ISH Folder) separate from the programmatic cmdlet name (Get-IshFolder), improving discoverability for end users.pwshprocesses that accumulate across sessions.Current state
Invoke-IshRemoteMcpHandleRequest.ps1is pure legacy-era2024-11-05:initializereturns hardcoded"protocolVersion":"2024-11-05"and placeholderserverInfo
"PowerShell MCP Server (Template)"/"0.2.0".server/discover; modern clients receive-32601and fall back toinitialize, sonothing breaks today — but the server is pinned to 2024-11-05 semantics and gains none of
the improvements above.
tools/callswallows all execution errors and always returnsisError:false.Proposed change — dual-era server
Keep the legacy
initializebranch intact for existing clients; add modern handling alongside it._meta["io.modelcontextprotocol/protocolVersion"]→ modern path;
method == "initialize"→ legacy path.server/discover→DiscoverResultwithsupportedVersions(e.g.["2026-07-28"]),capabilities,resultType: "complete",ttlMs,cacheScope,instructions(reuseRegister-IshRemoteMcpInstructions),_metaserverInfo.resultType: "complete"on all modernping,tools/list, andtools/callresults;add required
ttlMs/cacheScopetotools/list._metaversion →-32022UnsupportedProtocolVersionErrorwithdata.supported.tools/callsemantics — unknown tool → protocol error-32602; tool executionerrors → result with
isError: trueso the LLM can self-correct.ISHRemoteMcpServerand the actual module version.Register-IshRemoteMcpTool.ps1— addtitle; use{"type":"object","additionalProperties":false}for no-parameter tools.Files
Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Invoke-IshRemoteMcpHandleRequest.ps1Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Start-IshRemoteMcpServer.ps1Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Register-IshRemoteMcpTool.ps1Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Invoke-IshRemoteMcpHandleRequest.Tests.ps1Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Start-IshRemoteMcpServer.Tests.ps1Test plan
Extend
Invoke-IshRemoteMcpHandleRequest.Tests.ps1:server/discoverreturns correct shape (supportedVersions,capabilities,resultType,ttlMs,cacheScope,instructions,_meta.serverInfo).resultType: "complete"._metaversion returns-32022withdata.supported.-32602.isError: true.initializestill returns"protocolVersion":"2024-11-05"(dual-era regression test).Spec references