GSoC2026/Borgy: MCP App tools experiment#1700
Conversation
a06b552 to
b5aef17
Compare
…bviews for API execution and history
b5aef17 to
bb969ad
Compare
There was a problem hiding this comment.
How will this file be shipped to the end user?
There was a problem hiding this comment.
Separate files for separate templates.
Why are you not following the best practices that have been already documented in the article provided to you - https://dev.to/ashita/a-practical-guide-to-building-mcp-apps-1bfm
- separate files for UI resources
- shared css design system
Why polling is implemented?
| <div id="history-container" class="history-list"></div> | ||
|
|
||
| <script> | ||
| async function executeMcpTool(name, args) { |
There was a problem hiding this comment.
Why is this not a common utility? As architected in the article.
| import 'html_templates.dart'; | ||
|
|
||
| class ResourceHandler { | ||
| static Map<String, dynamic> listResources() { |
There was a problem hiding this comment.
Where is this function being used?
There was a problem hiding this comment.
it tells the IDE client the list of the resources including interfaces that the MCP server has, by returning a JSON map containing a list of resources, each resource has its own name, uri and mimetype, it is not used directly,it runs once when the MCP server first connects to the IDE client
| }; | ||
| } | ||
|
|
||
| static Map<String, dynamic> readResource(String uri) { |
There was a problem hiding this comment.
Where is this function being used?
There was a problem hiding this comment.
this one when the IDE client actually decides to open a specific resource, it calls this function, passing in the specific uri
| }, | ||
| }, | ||
| { | ||
| "name": "apidash_get_results", |
There was a problem hiding this comment.
why is results a separate app?
There was a problem hiding this comment.
actually this is an hidden from agent tool, it is used internally just to fetch the last request results in order to display it in the ui
|
|
||
| // __dirname is "apidash/scripts" | ||
| // '..' takes us up to the root folder "apidash/" | ||
| const EXE_PATH = path.join(__dirname, '..', 'build', 'windows', 'x64', 'runner', 'Release', 'apidash.exe'); |
There was a problem hiding this comment.
hard coded path .. does not work for end user.
There was a problem hiding this comment.
Also now working for macos or linux as written in the instruction.
| genui: ^0.9.2 | ||
| google_generative_ai: ^0.4.7 |
There was a problem hiding this comment.
How is this relevant to this PR?
Description - API Dash MCP App
This PR contains the MCP server and basic MCP app UI for API Dash.
It allows AI assistants inside editors like VS Code (e.g., Claude Code, Roo Code) to interact directly with the API Dash core engine, execute API requests, and view rich, interactive UIs directly within the editor.
Visual view
1. VS Code MCP Server Setup
flutter build windows --release(ormacos/linux) in the root directory to generate the required native build files before starting the server.To connect this engine to your VS Code AI assistant (like Roo Code or Cline), you must create a
.vscodefolder in the root of your workspace, and then create anmcp.jsonfile inside it to register the server.Add the following configuration to your new
.vscode/mcp.jsonfile, making sure to replace<PATH_TO_APIDASH_REPO>with the actual absolute path to where you cloned this repository on your machine:{ "servers": { "apidash-mcp": { "command": "node", "args": [ "<PATH_TO_APIDASH_REPO>/scripts/apidash-mcp.js" ] } } }Examples of valid paths:
"C:/Users/Username/Documents/apidash/scripts/apidash-mcp.js""/Users/Username/projects/apidash/scripts/apidash-mcp.js"(Note: Use standard forward slashes
/in the JSON path, even on Windows, as Node.js handles them perfectly and it prevents escaping errors).2. Architecture and File Overview
Added Files
mcp_engine.dart: Acts as the core JSON-RPC protocol router. It listens for incoming tool executions or resource requests, matches the requested method (e.g.,tools/call), and dispatches it to the appropriate handler while catching errors to prevent server hangs.mcp_service.dart: Manages the lifecycle of the headless Dart process. It bridges standard input/output (stdio) to the isolate ports, allowing the underlying Flutter/Dart engine to communicate with the Node.js wrapper.tool_handler.dart: The brain of the operations. It registers the schemas for the AI tools and executes the actual backend logic (like sending HTTP requests and saving to the database).resource_handler.dart: Responsible for providing the MCP client with the correct UI template based on the requestedui://URI scheme.html_templates.dart: Contains the raw HTML, CSS, and Javascript needed to render the API Dash dashboards inside VS Code's webview panels.The 4 Core Tools and How They Invoke Each Other
apidash_execute_request:_metaUI trigger. This forces VS Code to open the Results Dashboard.apidash_get_results:visibility: ["app"]modifier in its_metaschema.apidash_list_history:structuredContent(raw JSON) and sends a_metatrigger to open the History UI. The UI's Javascript automatically intercepts this raw JSON to render the interactive list.apidash_delete_request:visibility: ["app"]modifier.window.parent.postMessageto secretly ask the MCP client to call this tool on the backend, bypassing the AI entirely.Invoking visible to app only tools - not visible to the ai agent
apidash_get_resultsapidash_delete_request3. The Node.js Wrapper & Stdio Communication
You might wonder why a
.jsfile is used as the entry point when the entire application is built in Dart/Flutter.Why a
.jsscript?Most MCP clients running inside VS Code expect to spawn a server process via a highly standard environment (like Node.js or Python) and communicate over standard Input/Output (
stdio). The Node.js script acts as a lightweight, reliable proxy wrapper.Why this approach is necessary:
API Dash relies heavily on Flutter-specific packages (like
WidgetsFlutterBinding) and complex local databases. If you try to run a pure, raw Dart script from the command line without the proper Flutter context, these core packages will crash.By starting a Flutter-based headless app, we initialize all the necessary core packages securely. The Node.js script simply pipes standard JSON-RPC text strings via
stdininto the headless Dart environment, and the Dart environment pushes responses back out viastdout. TheMcpServiceclass actively listens to thisstdinstream, processes the JSON, and pipes it into the isolated MCP engine.4. Hive Boxes for Local Storage
The engine utilizes Hive CE (
hive_ce) as its local storage mechanism.What it does:
Initialize an isolated
agent_historybox specifically for the MCP server.Why it is important:
.flush()to guarantee it is written to the disk. Milliseconds later, the UI wakes up, queries Hive, and is guaranteed to find the data.execution_id) for every request, Hive allows us to build a comprehensive, permanent history log that the user can browse and manage.