Skip to content

Commit 9a9a1a4

Browse files
committed
feat: add MCP server for AI agent integration
Add HTTP-based MCP server on port 34438 that exposes Effect DevTools data to AI agents via Model Context Protocol. Tools available: - list_spans: Query spans with filtering by status, traceId, name - get_span: Get detailed span info including events - get_active_spans: Get currently running spans - list_clients: List connected Effect applications - get_metrics: Query metrics with filtering - get_span_tree: Get hierarchical span tree for a trace Implementation uses @effect/ai McpServer with BunHttpServer, running separately from the WebSocket DevTools server (port 34437).
1 parent 6a3ef3e commit 9a9a1a4

7 files changed

Lines changed: 564 additions & 12 deletions

File tree

bun.lock

Lines changed: 9 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,13 @@
3636
"client": "bun example/client.ts"
3737
},
3838
"dependencies": {
39+
"@effect/ai": "^0.32.1",
3940
"@effect/experimental": "^0.57.11",
4041
"@effect/language-service": "^0.62.1",
4142
"@effect/platform": "^0.93.6",
4243
"@effect/platform-bun": "^0.86.0",
4344
"@effect/platform-node": "^0.103.0",
45+
"@effect/rpc": "^0.72.2",
4446
"@opentui/core": "^0.1.60",
4547
"@opentui/solid": "^0.1.60",
4648
"dagre": "^0.8.5",

src/mcp/server.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* MCP Server Integration
3+
*
4+
* This module creates the MCP server layer using @effect/ai's McpServer.
5+
* It registers the DevTools toolkit and provides the StoreReader dependency.
6+
*/
7+
8+
import * as McpServer from "@effect/ai/McpServer";
9+
import { HttpRouter, HttpServer, HttpMiddleware } from "@effect/platform";
10+
import { BunHttpServer } from "@effect/platform-bun";
11+
import * as Layer from "effect/Layer";
12+
import * as Effect from "effect/Effect";
13+
import { DevToolsToolkit, DevToolsToolkitHandlers } from "./tools";
14+
import { makeStoreReaderLayer } from "../storeReaderService";
15+
import type { StoreState } from "../storeTypes";
16+
17+
/**
18+
* MCP server configuration
19+
*/
20+
export const MCP_PORT = 34438;
21+
export const MCP_PATH = "/mcp";
22+
23+
/**
24+
* Create the MCP server layer.
25+
*
26+
* This layer:
27+
* 1. Creates an HTTP server on a separate port
28+
* 2. Creates an MCP server at the specified path
29+
* 3. Registers the DevTools toolkit with all tools
30+
* 4. Provides the StoreReader service for tool handlers
31+
*
32+
* @param getStore - Function to get the current store state
33+
*/
34+
export const makeMcpLayer = (getStore: () => StoreState) => {
35+
// Create MCP toolkit layer that registers tools with the server
36+
const ToolkitLayer = McpServer.toolkit(DevToolsToolkit);
37+
38+
// MCP layer with toolkit registration
39+
const McpLive = Layer.mergeAll(
40+
// The MCP HTTP layer creates the server and registers routes on HttpRouter.Default
41+
McpServer.layerHttp({
42+
name: "effect-devtools",
43+
version: "1.0.0",
44+
path: MCP_PATH,
45+
}),
46+
// Register our toolkit with the server
47+
ToolkitLayer,
48+
).pipe(
49+
// Provide the handlers for our toolkit
50+
Layer.provide(DevToolsToolkitHandlers),
51+
// Provide the store reader so handlers can access state
52+
Layer.provide(makeStoreReaderLayer(getStore)),
53+
);
54+
55+
// HTTP server layer using Bun
56+
const HttpServerLive = BunHttpServer.layer({ port: MCP_PORT });
57+
58+
// Combine everything: serve the router with MCP routes
59+
return HttpRouter.Default.unwrap(
60+
HttpServer.serve(HttpMiddleware.logger),
61+
).pipe(
62+
HttpServer.withLogAddress,
63+
Layer.provide(McpLive),
64+
Layer.provide(HttpServerLive),
65+
);
66+
};
67+
68+
/**
69+
* Run the MCP server as an Effect (for use in forked fiber)
70+
*/
71+
export const runMcpServer = (getStore: () => StoreState) =>
72+
Effect.gen(function* () {
73+
console.log(`[MCP] Starting MCP server on port ${MCP_PORT}...`);
74+
yield* Layer.launch(makeMcpLayer(getStore));
75+
});

0 commit comments

Comments
 (0)