my-mcp-server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@my-mcp-servershow my tasks board"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
my-mcp-server: a minimal Miragon MCP Toolkit starter
A self-contained MCP server built on the Miragon MCP Toolkit (the published
@miragon/mcp-toolkit-* packages): a plain mcp-use
project with the toolkit installed on top. One module registers its own
tools plus a widget (the tasks module), and the mcp-use CLI builds and
serves the views. Two commands take you from clone to a rendered widget.
Quickstart
You need Node.js 22.22.2 or newer and pnpm. The @miragon
packages are on the public npm registry, so no authentication is required.
Install:
pnpm installRun (
mcp-use dev— builds the views with HMR, boots the server):pnpm devSee it work: the terminal prints the built-in inspector URL (
…/mcp/inspector). Open it and callshow_tasks_board— the task-board widget renders. That is the full loop: an MCP tool returning a rendered UI. Editviews/shared/TaskListCard.tsxand the view hot-reloads.
Related MCP server: task-manager-mcp
Dev loop
pnpm dev—mcp-use dev: server + views with HMR + the built-in inspector. This is the whole loop; no bundle step, no restart after widget edits.pnpm build/pnpm start—mcp-use build(server + views into.mcp-use/build) andmcp-use start(serve the production build).pnpm typecheck—tsc --noEmit.
Optional config lives in .env (PORT; MCP_URL only for deployed servers)
— copy the template first:
cp env.example .envProject layout
├── package.json # pinned versions; main: src/index.ts (the CLI reads it)
├── .npmrc # save-exact: pin dependency versions
├── env.example # PORT / MCP_URL — copy to .env
├── src/
│ ├── index.ts # default-exported MCPServer + installToolkit(...)
│ └── modules/tasks/
│ ├── definition.ts # static contract: module name + widget ids
│ ├── tool-names.ts # tool-name constants (server ↔ views agree here)
│ ├── store.ts # in-memory domain layer; TasksBoardData view-model
│ └── plugin.ts # tools: list_tasks, create_task, show_tasks_board, tasks_board_data
└── views/ # CLI convention: one dir per view-bound tool
├── render-view/view.tsx # the toolkit composer view
├── show_tasks_board/view.tsx # the tasks widget tool's view
└── shared/ # shared browser modules — MUST live under views/
├── widgets.tsx # widget-id map → React components
├── TaskListCard.tsx # the widget: {data: TasksBoardData} → UI primitives
├── messages.ts # the widget's words: typed en/de catalog
└── styles.css # Tailwind entry: globals.css + fonts.css + @source scan pathsHow the views work
Every model-visible widget tool is bound to a view named after the tool
(view: { name: "show_tasks_board" } in plugin.ts); installToolkit binds
render-view the same way. The mcp-use CLI discovers each
views/<name>/view.tsx by convention, builds it, serves it as the MCP
resource ui://views/<name>.html, and emits the _meta.ui wire keys — no
bundle wiring in this project at all.
Each view renders the same McpToolkitApp with the shared widget map:
Every widget is registered twice: once in the plugin's
definition.ts(the id + theconsumesdataType the server pushes) and once inviews/shared/widgets.tsx(the id + the component). The two sides meet on the widget id —"tasks:board"here.adaptDataWidget(TaskListCard, "tasks:board")resolves the step whose_dataTypeis"tasks:board"(set bybuildSingleWidgetViewinshow_tasks_board) and forwards its data to the component'sdataprop.
Shared browser modules live under views/ on purpose (views/shared/):
the CLI dev server routes only views/* through its Vite middleware, so a
browser module anywhere else in the project 404s in dev. Server-side code
(src/) is unaffected — it runs in Node. Type-only imports from src/ into
a view are fine; they are erased at build time.
Styling: views/shared/styles.css imports the toolkit's
@miragon/mcp-toolkit-ui/globals.css (Tailwind theme + tokens) and adds
@source lines so Tailwind generates classes used outside the CSS file's own
tree. If a class "does nothing" in the rendered widget, check that the file
using it is covered by an @source line. tailwindcss is a dev dependency
because @miragon/mcp-toolkit-ui declares it as a peer; the Vite plugin that
compiles it ships inside the mcp-use CLI, so this project needs no Vite
dependency or config of its own.
Version pinning: mcp-use here must be exactly the version the pinned
@miragon packages name as their peer (a second copy breaks the widgets' host
context); react, react-dom and zod only have to satisfy the peer ranges
(see the packages' peerDependencies). Keep them in step when bumping either
side. lucide-react is pinned to the
exact version @miragon/mcp-toolkit-ui depends on, on purpose: a second copy
in the graph splits mcp-use into two peer instances and crashes widgets at
render time (see the toolkit's migration guide), and your own icons then miss
the stroke the toolkit sets for its views.
Between toolkit releases the @miragon pins here still point at the previous
release, so pnpm install can report an unmet mcp-use peer until the next
release lifts them. It is a warning, not a break — install, typecheck and
mcp-use build all succeed.
Look and language
The widgets render in the Miragon design system, the toolkit's default theme, light or dark as the host is, in Geist, with their words in English or German as the host's locale is. Out of the box you change none of it.
Your brand
To give the widgets your brand, override role variables at the end of
views/shared/styles.css, below the two toolkit imports (the commented block
there is the skeleton). Use the selectors of the toolkit's theme, one light
and one dark block, and declare every colour you change in both:
:root,
[data-theme-mode="light"] {
--primary: #0f766e; /* button fill; --primary-foreground is its label */
--primary-hover: #115e59;
--link: #0f766e;
--focus: #0f766e; /* the focus ring */
--ring: #0f766e;
--radius-md: 6px; /* mode-independent: the light block is enough */
}
.dark,
[data-theme="dark"],
[data-theme-mode="dark"] {
--primary: #0f766e;
--primary-hover: #115e59;
--link: #5eead4; /* light enough to read on a dark ground */
--focus: #5eead4;
--ring: #5eead4;
}Keep every text colour at 4.5:1 on its surface and the focus ring at 3:1, in
both modes. Override roles only, never the --cd-* tokens (the Miragon
palette the roles default to) and never a component class: your brand then
needs no toolkit release and survives every update. The
white-labeling guide
lists every role (status tones, surfaces, radii, fonts) and the alternative
in code, createTheme + ThemeProvider.
Fonts and language
Fonts. Geist and Geist Mono are on by default: the theme names them first, and
views/shared/styles.cssloads both through thefonts.cssimport (the files come from npm through the bundler, no font CDN). The view build inlines them into every view; to keep views small, drop the import and serve the files by URL withfontFaces({ baseUrl })(allow that origin in the view's CSPresourceDomains), or let the host's font stand in.Language. The toolkit's own text (list footers, empty and error states, toasts, the view toolbar) follows the host's locale, in English or German, and so does
TaskListCard: every word comes from the typed en/de catalog inviews/shared/messages.ts(German with du), picked byuseLocale(). Eachviews/<tool>/view.tsxhands the host's locale to aLocaleProvider. Add a widget's words to the catalog, never into the component, and format counts and dates withuseLocale().
CI
The included CI (.github/workflows/ci.yml) typechecks and runs
mcp-use build. The @miragon packages are public on npm, so it installs
them with no token or registry configuration.
Where this project comes from
This project is maintained as
templates/minimal-server
in the mcp-toolkit monorepo and auto-mirrored to
Miragon/mcp-toolkit-starter,
the "Use this template" repo. Nothing in it depends on the monorepo — it
installs only published packages. If you run it in place inside the monorepo
checkout, install with pnpm install --ignore-workspace (the directory sits
inside the monorepo's pnpm workspace but is not part of it).
Where to go next
Docs — concepts, guides, and the API reference for every package; the migration guide if you are coming from a 0.10.x scaffold.
The
standalone-hostexample — the in-repo reference for this exact shape.The
tasksexample — the full-size version of this module (complete_task, filterable board widget, in-widget refresh, tests).Agent skills — the repo's coding-agent skills (
build-mcp-server,add-mcp-tool,build-mcp-widget,compose-a-view,white-label-client) encode the house patterns; copy them into this project's.claude/skills/so your coding agent builds on them.
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP Server for an Agent Task Marketplace
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Local-first task manager: create, edit, and complete tasks, projects, and checklists via MCP.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA minimal MCP server that provides an interactive to-do list with checkboxes in chat, demonstrating MCP Apps UI resource integration and tool-based state updates.-
- FlicenseNot gradedqualityDmaintenanceA task manager MCP server that demonstrates all three MCP primitives (tools, resources, prompts). Enables users to manage tasks, read task summaries and details, and run structured planning/review prompts through natural language.-
- FlicenseNot gradedqualityBmaintenanceA lightweight task management MCP server that enables CRUD operations on tasks stored in a single JSON file, including listing, creating, updating progress, and setting priorities.172 npm-
- FlicenseCqualityDmaintenanceA simple MCP server demonstrating resources, tools, and prompts using a local task list. It enables reading, creating, and analyzing tasks through MCP.1-