{"slug": "build-a-dart-adk-agent-and-mcp-server", "title": "Build a Dart ADK Agent and MCP Server", "summary": "A developer has released an open-source project that enables Dart developers to build AI agents and Model Context Protocol (MCP) servers without relying on Python or Node.js. The project, adk-hello-world-dart, uses the adk_dart library for the agent and Shelf for an HTTP server that exposes an MCP-compatible greeting tool over Server-Sent Events. The developer notes that the Dart library is not an official ADK, as an official Dart ADK has not been released as of July 2026.", "body_md": "Dart developers do not need a Python or Node.js service just to experiment with agents and Model Context Protocol (MCP) tools. This project uses `adk_dart`\n\nfor the agent and `shelf`\n\nfor a small HTTP server that exposes an MCP-compatible greeting tool over Server-Sent Events (SSE).\n\nThe complete code is in the [adk-hello-world-dart repository](https://github.com/xbill9/adk-hello-world-dart).\n\nNote- the Dart library is not an official ADK. An official Dart ADK has not been released as of July 2026. This approach provides an alternative to start working with agents in Dart without waiting for an official SDK.\n\nThe repository has two related examples:\n\n`bin/main.dart`\n\ncreates an `LlmAgent`\n\nand registers an ADK `FunctionTool`\n\n.`bin/server.dart`\n\nstarts a Shelf server with an SSE endpoint and a JSON-RPC message endpoint.The server implements the MCP methods needed by this demo: `initialize`\n\n, `notifications/initialized`\n\n, `ping`\n\n, `tools/list`\n\n, and `tools/call`\n\n. The transport and JSON-RPC routing are deliberately small and live in `SessionService`\n\n; they are not a general-purpose MCP server implementation.\n\n``` php\nflowchart LR\n    Client[MCP client] -->|GET /sse| Server[Shelf server]\n    Server -->|endpoint event| Client\n    Client -->|POST /messages?sessionId=...| Server\n    Server --> Session[SessionService]\n    Session --> Tool[greet tool]\n\n    CLI[Dart CLI] --> Agent[ADK LlmAgent]\n    Agent --> ADKTool[ADK FunctionTool]\n```\n\nThe current project targets Dart 3.5 or later and uses these package versions:\n\n```\nenvironment:\n  sdk: ^3.5.0\n\ndependencies:\n  adk_dart: ^2026.7.24\n  adk_mcp: ^2026.7.24\n  logging: ^1.3.0\n  shelf: ^1.4.1\n  shelf_router: ^1.1.4\n  uuid: ^4.5.1\n```\n\nInstall them with:\n\n```\ndart pub get\n```\n\n`adk_dart`\n\nis used directly by the sample agent. The repository also tracks `adk_mcp`\n\n, while the current server keeps its MCP transport explicit in `SessionService`\n\nso the protocol flow is easy to inspect.\n\nThe project keeps the greeting logic separate from its ADK and MCP wrappers:\n\n```\nclass Tools {\n  static String formatGreeting(String name) {\n    return 'Hello, $name!';\n  }\n\n  static final FunctionTool greetFunctionTool = FunctionTool(\n    name: Config.toolGreet,\n    description: 'Get a greeting from a local HTTPS server.',\n    func: ({String? param}) {\n      final name = param ?? 'World';\n      return formatGreeting(name);\n    },\n  );\n}\n```\n\n`Tools`\n\nalso exposes an MCP tool definition with a JSON Schema input named `param`\n\n. Keeping `formatGreeting`\n\nas a plain Dart function makes the domain behavior easy to unit test.\n\n`AdkGreetingAgent`\n\nattaches the function tool to an `LlmAgent`\n\n:\n\n```\nclass AdkGreetingAgent {\n  static LlmAgent createAgent() {\n    return LlmAgent(\n      name: 'GreetingAgent',\n      description: 'An AI Agent built with adk_dart that provides greetings.',\n      instruction:\n          'You are a friendly greeting assistant. '\n          'Use the greet tool to provide personalized greetings.',\n      tools: [Tools.greetFunctionTool],\n    );\n  }\n}\n```\n\nRun the CLI example to confirm that the agent and tool can be created:\n\n```\ndart run bin/main.dart\n```\n\nThis command initializes the agent and prints a sample tool result. It does not call a hosted model.\n\nThe Shelf server registers four routes:\n\n``` js\nrouter.get('/', (request) => Response.ok('ADK & MCP Dart Server Running'));\nrouter.get('/health', (request) => Response.ok('OK'));\nrouter.get(Config.sseEndpoint, sessionService.handleSseSession);\nrouter.post(Config.messagesEndpoint, sessionService.handlePostMessage);\n```\n\nWhen a client opens `GET /sse`\n\n, `SessionService`\n\ncreates an in-memory session and sends an `endpoint`\n\nevent containing a URL such as:\n\n```\n/messages?sessionId=7c6d...\n```\n\nThe client posts JSON-RPC requests to that URL. Responses arrive as `message`\n\nevents on the original SSE connection.\n\nStart the server with:\n\n```\ndart run bin/server.dart\n```\n\nIt listens on port `8080`\n\nby default. Set the `PORT`\n\nenvironment variable to use another port.\n\nFor an MCP client that supports remote SSE servers, point it at:\n\n```\nhttp://localhost:8080/sse\n```\n\nA typical client configuration looks like this:\n\n```\n{\n  \"mcpServers\": {\n    \"dart-greeting-server\": {\n      \"url\": \"http://localhost:8080/sse\"\n    }\n  }\n}\n```\n\nConfiguration keys differ between MCP clients, so check the documentation for the client you use. Once connected, call the `greet`\n\ntool with:\n\n```\n{\n  \"param\": \"Dart developer\"\n}\n```\n\nThe result is `Hello, Dart developer!`\n\n.\n\nThe repository includes unit tests for the greeting behavior and endpoint tests for the Shelf server:\n\n```\ndart test\ndart analyze\n```\n\nYou can run the complete build, analysis, and test sequence with:\n\n```\nmake check\n```\n\nThe included multi-stage Dockerfile compiles the server to a native executable and copies it into a small scratch image:\n\n```\ndocker build -t adk-hello-world-dart .\ndocker run --rm -p 8080:8080 adk-hello-world-dart\n```\n\nCheck the running container at `http://localhost:8080/health`\n\n.\n\n`cloudbuild.yaml`\n\nbuilds the image, pushes it to Container Registry, and deploys the service in `us-central1`\n\n:\n\n```\nmake deploy\n```\n\nThe deployment allows unauthenticated access and sets `--max-instances 1`\n\n.\n\nThat instance limit matters here. Active SSE transports are stored in a process-local map, so a POST request routed to another instance would not find its session. A production service should move session state to shared storage or use a transport and deployment design that does not depend on process-local routing. Authentication, origin restrictions, request validation, timeouts, and rate limiting would also need attention before exposing the service publicly.\n\nThis sample is intentionally narrow: one agent, one deterministic tool, and enough MCP handling to show the request flow. Useful next steps include replacing the greeting with real domain logic, using `adk_mcp`\n\ntransport primitives as the Dart package evolves, adding model configuration to execute the agent, and moving session state out of memory before scaling the service.\n\nResources:", "url": "https://wpnews.pro/news/build-a-dart-adk-agent-and-mcp-server", "canonical_source": "https://dev.to/gde/build-a-dart-adk-agent-and-mcp-server-4f9n", "published_at": "2026-08-09 17:03:45+00:00", "updated_at": "2026-08-09 17:18:10.260742+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents", "ai-tools"], "entities": ["adk_dart", "Shelf", "MCP", "adk-hello-world-dart", "LlmAgent", "FunctionTool", "SessionService"], "alternates": {"html": "https://wpnews.pro/news/build-a-dart-adk-agent-and-mcp-server", "markdown": "https://wpnews.pro/news/build-a-dart-adk-agent-and-mcp-server.md", "text": "https://wpnews.pro/news/build-a-dart-adk-agent-and-mcp-server.txt", "jsonld": "https://wpnews.pro/news/build-a-dart-adk-agent-and-mcp-server.jsonld"}}