feat(mcp): MCP server design + phase 1 HTTP/JSON-RPC implementation#476
Open
devin-ai-integration[bot] wants to merge 3 commits into
Open
feat(mcp): MCP server design + phase 1 HTTP/JSON-RPC implementation#476devin-ai-integration[bot] wants to merge 3 commits into
devin-ai-integration[bot] wants to merge 3 commits into
Conversation
Design draft for an opt-in MCP server surface that exposes SmartHopper's existing AITool catalog to external MCP clients (Claude Desktop, Cursor, VS Code, Claude Code) over local HTTP/JSON-RPC, without re-implementing GhJSON marshalling (kept in architects-toolkit/ghjson-dotnet). Adapted from brookstalley/cordyceps (MIT) as architectural reference; no Cordyceps code is imported in this PR. No code changes.
Contributor
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Land phase 1 of the MCP server design (docs/Architecture/mcp-server.md) so
external MCP clients (Claude Desktop, Cursor, VS Code, Claude Code) can
discover and call SmartHopper's existing AI tools over a local loopback
HTTP/JSON-RPC server. No SSE, no embedded resources, no LAN exposure;
those remain in phases 2-5.
SmartHopper.Infrastructure/Mcp/
- McpServer: HttpListener bound to 127.0.0.1 + [::1], origin
guard, optional bearer token, 256 KB request cap,
no payload logging.
- JsonRpcDispatcher: initialize, tools/list, tools/call,
notifications/initialized, ping.
Method-not-found stubs for resources/* and
prompts/*. SemaphoreSlim gate serializes
concurrent requests.
- AIToolMcpAdapter: bridges AIToolManager to MCP tool descriptors.
Allow-list (McpServerOptions.EnabledTools);
mutating-tools-off filter by name prefix
(gh_put, gh_move, script_*, ...).
Executes via AIToolCall.Exec().
- McpServerLifecycle: ref-counted singleton per port to support
multiple components on the same port without
tearing down the server while still in use.
- McpServerOptions, McpToolDescriptor, McpToolCallResult: config /
result types.
SmartHopper.Components/Mcp/SmartHopperMcpServerComponent
Opt-in GH component. Inputs: Enable (bool), Port (int, default 26929),
BearerToken (string, optional), ExposeMutatingTools (bool, default
false). Outputs: Url, Status.
SmartHopper.Infrastructure.Tests/Mcp/
xUnit coverage (no Rhino refs):
- AIToolMcpAdapterTests: descriptor filtering, schema parsing,
executor wiring, error propagation.
- JsonRpcDispatcherTests: initialize / tools/list / tools/call /
unknown method / invalid JSON /
notification / missing tool name.
- McpServerOptionsTests: defaults and Clone semantics.
GhJSON-first: the MCP adapter never imports ghjson-dotnet. AITool
implementations already own their GhJSON marshalling via
architects-toolkit/ghjson-dotnet; MCP forwards AIReturn.Body verbatim.
Cordyceps (MIT) attribution is recorded in per-file headers under
SmartHopper.Infrastructure/Mcp/. THIRD_PARTY_NOTICES.md is extended via
PR #474 and will pick up this attribution when both PRs land in
feature/2.0.0-text2json.
Phase 1 design-doc status flipped from "design draft" to "phase 1
implemented" in docs/Architecture/mcp-server.md.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds Tier 1 of the OSS review / import plan: an opt-in MCP server surface for SmartHopper that exposes the existing
IAIToolProvidertool catalog to external MCP clients (Claude Desktop, Cursor, VS Code, Claude Code, etc.) over local HTTP/JSON-RPC.Bundles phase 0 (design doc) and phase 1 (working minimal server, no SSE, no embedded resources) so the doc and the code that materializes it ship together. Phases 2–5 (resources, prompts, LAN exposure, streaming) remain design-only and will land as separate follow-up PRs.
GhJSON-first
src/SmartHopper.Infrastructure/Mcp/*never referencesGhJSON.Core/GhJSON.Grasshopper. Every MCPtools/callinvokes an existingAIToolviaAIToolManager.ExecuteTool(AIToolCall). The MCP layer treatsAIReturn.Bodyas opaque JSON. All GhJSON marshalling stays inarchitects-toolkit/ghjson-dotnet.What this PR contains
Design —
docs/Architecture/mcp-server.md, full architecture §1–§13. Status flipped from "design draft" to "phase 1 implemented"; §12 decision points resolved inline.Phase 1 code under
src/SmartHopper.Infrastructure/Mcp/(no new project — keeps the dependency graph flat; can graduate to a standaloneSmartHopper.Mcplater):McpServer.cs—HttpListenerbound to127.0.0.1and[::1]only. Origin guard, optional bearer token, 256 KB request cap, no payload logging.GET /healthfor liveness,POST /mcpfor JSON-RPC.JsonRpcDispatcher.cs— JSON-RPC 2.0 dispatch forinitialize,tools/list,tools/call,notifications/initialized,ping. Method-not-found stubs forresources/*andprompts/*.SemaphoreSlimgate serializes concurrent requests.AIToolMcpAdapter.cs— bridgesAIToolManagerto MCP tool descriptors. Allow-list (McpServerOptions.EnabledTools); mutating-tools-off filter by name prefix (gh_put,gh_move,script_*, …). Executes viaAIToolCall.Exec(). Tool errors surface as MCPisError: trueresponses.McpServerLifecycle.cs— ref-counted singleton per port so multiple components on the same port don't tear the server down while still in use.McpServerOptions.cs,McpToolDescriptor.cs,McpToolCallResult.cs— config / result types.Component at
src/SmartHopper.Components/Mcp/SmartHopperMcpServerComponent.cs:Enable(bool, defaultfalse),Port(int, default26929),BearerToken(string, optional),ExposeMutatingTools(bool, defaultfalse).Url,Status.McpServerLifecycle; cleans up onRemovedFromDocumentandDocumentContextChanged(Close | Unloaded).Tests under
src/SmartHopper.Infrastructure.Tests/Mcp/(xUnit, no Rhino refs):AIToolMcpAdapterTests— descriptor filtering, schema parsing, executor wiring, error propagation.JsonRpcDispatcherTests—initialize/tools/list/tools/call/ unknown method / invalid JSON / notification / missing tool name.McpServerOptionsTests— defaults andClonesemantics.Default configuration (phase 1)
EnablefalsePort26929http://127.0.0.1:<port>/andhttp://[::1]:<port>/onlyExposeMutatingToolsfalseAdapted from Cordyceps (MIT)
brookstalley/cordycepsis the architectural reference. Structural patterns reused with attribution in per-file headers undersrc/SmartHopper.Infrastructure/Mcp/: HTTP/JSON-RPC dispatch shape, tool-discovery pattern (adapted toIAIToolProvider),SemaphoreSlimrequest serialization. No Cordyceps source is copied.THIRD_PARTY_NOTICES.md(added by #474) will pick up an MCP attribution paragraph once both PRs land infeature/2.0.0-text2json.Files changed
docs/Architecture/mcp-server.md— full design doc.src/SmartHopper.Infrastructure/Mcp/*— 7 files (server, dispatcher, adapter, lifecycle, options, descriptor, result).src/SmartHopper.Components/Mcp/SmartHopperMcpServerComponent.cs— Grasshopper component.src/SmartHopper.Infrastructure.Tests/Mcp/*— 3 xUnit test files.docs/index.md— link to Architecture deep dives.CHANGELOG.md—[Unreleased] / Addedentries for both phase 0 and phase 1.Branching note
Branched from
feature/2.0.0-text2jsonand targeted at the same branch (nofeature/2.0.0exists on remote yet). Stacks on top of #473 (merged) and #474 (open).Breaking Changes
None. New, opt-in surface. Component is disabled by default and no existing tool behavior changes.
Testing Done
dotnet build src/SmartHopper.Infrastructure/SmartHopper.Infrastructure.csproj -f net7.0 -p:SignAssembly=false→ 0 errors.dotnet test src/SmartHopper.Infrastructure.Tests/SmartHopper.Infrastructure.Tests.csproj -f net7.0 -p:SignAssembly=false --filter "FullyQualifiedName~Mcp"→ 20 passed, 0 failed, 0 skipped.Checklist
Link to Devin session: https://app.devin.ai/sessions/870109f6b69b413480b5c763f3c42bbc
Requested by: @marc-romu