MCP Hello World Server
by 9kubczas4
README.md
# MCP Hello World App
A minimal **MCP App** boilerplate: a single Node/TypeScript MCP server that
exposes one tool (`say_hello`) and serves a tiny Angular UI as an
[MCP App](https://modelcontextprotocol.io) resource.
It mirrors the architecture of the parent `invoice-preview-mcp-app` project,
stripped down to a "Hello World".
## Architecture
```
MCP Host (e.g. Cursor)
│ calls tool say_hello
▼
Express server (:8080)
├─ POST/GET/DELETE /mcp → MCP Streamable HTTP transport
├─ MCP resource → ui://hello-world/app (inlined Angular HTML)
├─ GET /ui/* → HTTP fallback for assets
└─ GET /healthz
▲
│ build pipeline
ng build → scripts/inline-bundle.mjs (CSS + JS inlined into one HTML)
```
When the agent calls `say_hello`, the tool result carries
`_meta.ui.resourceUri = "ui://hello-world/app"`, which tells the host to open
the Angular UI in an iframe. Inside the iframe the UI calls `say_hello` again
through the MCP bridge (postMessage, with an HTTP fallback to `/mcp`).
## Project layout
```
├── package.json # npm workspaces: server + ui
├── tsconfig.base.json
├── scripts/inline-bundle.mjs # inlines the Angular build for MCP iframes
├── .cursor/mcp.json # points Cursor at http://127.0.0.1:8080/mcp
├── server/ # MCP + Express server (TypeScript)
│ └── src/
│ ├── index.ts # entry point
│ ├── core/
│ │ ├── config/server-env.ts # env parsing
│ │ ├── http/ # Express app + CORS
│ │ ├── infrastructure/ # base-url / CSP helpers
│ │ └── mcp/ # server factory, transport, tool registry
│ ├── tools/ # one folder per MCP tool
│ │ └── say-hello/ # register-say-hello.ts + schemas
│ └── ui/ # MCP App resource + HTTP fallback
└── ui/ # Angular Hello World UI
```
### Adding a new tool
1. Create `server/src/tools/<your-tool>/register-<your-tool>.ts` (plus a
`*.schemas.ts` if it takes input).
2. Add its registrar to the array in `server/src/core/mcp/tool-registry.ts`.
## Getting started
```bash
npm install
npm run build # builds the server (tsc) and the UI (ng build + inline)
npm start # node server/dist/index.js → http://localhost:8080
```
Then add `.cursor/mcp.json` to your Cursor MCP config (or copy the
`hello-world-local` entry), and ask the agent to run the `say_hello` tool.
## Key conventions
| Convention | Why |
|------------|-----|
| MIME `text/html;profile=mcp-app` | Required by the MCP Apps spec |
| `outputHashing: "none"` (Angular) | Stable asset filenames for resource serving |
| `baseHref: "./"` | Relative paths inside the iframe |
| inline-bundle script | MCP iframes often block external script fetches |
| `_meta.ui.resourceUri` on the tool | Tells the host which UI to open |
| CORS on `/mcp` | The iframe has a null/opaque origin |
| `<meta name="mcp-server-url">` injection | Enables the HTTP tool-call fallback |
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues