About MCP
MCP is an MCP server published by petarzarkov in the Finance category: fastest web DI framework. NestJS-style structure at Bun speed. Constructor DI with no reflect-metadata, no experimentalDecorators, no JavaScript router.
The repository has 101 stars and 2 forks, with the last commit 3 days ago. Recent commit activity is the strongest signal that reported issues will get attention.
Install
git clone https://github.com/petarzarkov/dunxThis server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.
Ask AI
Ask AI about MCP
Powered by Claude · Grounded in docs
Security checks
Static checks derived from the repository 4 hours ago. Heuristics on the source, not an audit.
- ✓README presentThe repository ships documentation.
- ✓License declaredUsable under a stated license.
- ✓Tests presentA test suite exists in the repository.
- ✓Dependencies pinnedA lockfile pins dependency versions.
- ✓No dynamic code executionSource scan found no eval, dynamic Function, or shell execution.
1 check has not been run yet.
Releases
README
dunx
Dependency injection for Bun. Everything a service needs, one version.
Controllers, dependency injection, validation, OpenAPI, WebSockets, queues, an ORM, auth, a test harness and an ops dashboard. Released together, tested together, on Bun's own primitives.
bunx @dunx/create-app my-api
What you get
Elysia and Hono hand you a router, and everything above it is yours to choose and keep in step. This is the other trade: one dependency, one release train.
| You need | dunx gives you |
|---|---|
| Structure | Controllers, scoped modules, constructor DI, lifecycle hooks |
| Requests | Bun.serve routing, middleware, guards, CORS, compression, throttling |
| Configuration | One validate function over Bun.env, YAML, TOML or JSON, typed end to end |
| Validation | Standard Schema, so zod, Valibot or ArkType all drop in |
| API documentation | OpenAPI 3.1 from the routes' own schemas, behind Swagger UI or Scalar |
| Realtime | WebSocket gateways and @Sse, with a Redis or Postgres relay for many nodes |
| Service to service | Connect and gRPC-Web, through the middleware chain the app has |
| Decoupling | An in-process event bus: publish a class, subscribe with @OnEvent |
| Data | drizzle over bun:sqlite and Bun.SQL, transactions, seeds, paging |
| Caching | Memory, Redis or the two tiered, with single flight on a miss |
| Background work | bullmq over Bun.RedisClient, sandboxed processors, @Cron |
| Messaging | RabbitMQ topic exchanges, one handler per queue, the trace carried across |
| Storage and images | One Storage contract over Bun.file and Bun.S3Client, Bun.Image |
| Auth | better-auth mounted, a session guard, Bun.password hashing |
| Calling out | An HTTP client with retry, backoff and trace propagation |
| Failing well | ResiliencePolicy around anything: timeout, retry, backoff, jitter, fallback |
| Operating it | Health checks, structured logging, request and driver metrics, a dashboard |
| Testing | The real container with bindings replaced, a real server on port 0 |
| Tooling | A scaffolder, and an MCP server so an agent can read your app |
Every one of those is a Bun primitive or a best-in-class library wired to one,
never a reimplementation. Each is opt-in: @dunx/core has zero dependencies,
and an app that imports no queue installs no queue.
What an app looks like
import { Logger, Module } from '@dunx/core';
import {
Controller,
Get,
HttpFactory,
type Input,
type RouteSchemas,
} from '@dunx/http';
export class GreetingsService {
constructor(private readonly logger: Logger) {}
greet(name: string) {
this.logger.info('greeting', { name });
return { greeting: `hello, ${name}` };
}
}
@Controller('greetings')
export class GreetingsController {
constructor(private readonly greetings: GreetingsService) {}
@Get('/:name')
one(input: Input<RouteSchemas>) {
return this.greetings.greet(input.req.params['name'] ?? 'world');
}
}
@Module({
controllers: [GreetingsController],
providers: [GreetingsService],
})
export class AppModule {}
const app = await HttpFactory.create(AppModule);
await app.listen(3000);
There is no @Injectable(), no @Inject(), no reflect-metadata import and no
experimentalDecorators, and a handler returns a plain value instead of calling
Response.json(). Two lines in bunfig.toml turn the constructor types into
wiring:
preload = ["@dunx/transform/preload"]
[test]
preload = ["@dunx/transform/preload"]
Bun's test runner reads its own preload, so bun test needs the [test]
entry. Without it the app runs, but the tests fail at the first provider with a
constructor parameter.
How the DI differs
The constructor injection above reads like NestJS. The mechanism resolving it underneath is different, in four places.
No reflect-metadata, and no experimentalDecorators. dunx uses standard
TC39 decorators. @dunx/transform reads each class's constructor parameter
types at load time with oxc-parser, a
Rust parser over N-API, and records them on the class. There are no parameter
decorators in the TC39 proposal, so @Inject() does not exist and never will.
A type that does not exist at runtime fails boot. If a parameter's type is
an interface, a primitive or a type-only import, dunx fails at boot and names
that parameter. emitDecoratorMetadata gives you undefined and a stack trace
three frames away from the mistake.
No forwardRef. The dependency record is a thunk, evaluated at resolution
rather than at class-definition time, so a circular import resolves on its own.
The container is scoped. Every module reference is a scope holding what it
declares, exports is its public surface, and an absent exports exports
nothing. A module that takes no options is a decorated class rather than a
forRoot(), because each forRoot() call returns a fresh object and so a fresh
scope.
One thing to add rather than delete: every relative import ends in .js,
because moduleResolution: nodenext is what the scaffold sets. An extensionless
specifier is a compile error rather than a runtime surprise.
Documentation
- The live demo -
examples/fullrunning on a Raspberry Pi 5: the API explorer, the ops dashboard, bull-board, and a walkthrough that drives twenty-five capabilities from a browser, including a transaction rolling back, a CSRF refusal, an idempotent retry, an order crossing a RabbitMQ topic exchange, and the process's own request, query and event-loop timings - The guide - thirty-five pages, introduction through cookies
- Migrating from NestJS - what maps across and what does not
- ARCHITECTURE.md - what was measured, what was rejected, and why
- ROADMAP.md - what is built and what is next
- setup.md - the same setup for
an agent to fetch and follow: "set up my project using
https://dunx.win/setup.md". Every scaffolded app also gets an
AGENTS.mdand aCLAUDE.md - llms.txt - every document above, linked as raw markdown
Performance
Structure on Bun does not have to cost throughput. @dunx/http is a layer over
Bun.serve({ routes }). It lands at 88-99% of the raw server's throughput,
within noise of Elysia, and 3.8-5.5x NestJS on Fastify. Boot is 43 ms against
294 ms.
Median req/s, 64 connections, 5 runs:
| Framework | Plain text | JSON | Path param | Body validation |
|---|---|---|---|---|
| @dunx/http | 134,864 | 127,776 | 126,206 | 81,631 |
| Elysia | 136,766 | 123,937 | 127,885 | 78,649 |
| Hono (Bun) | 126,987 | 111,301 | 108,403 | 60,513 |
| NestJS (Fastify) | 31,623 | 33,748 | 29,606 | 14,953 |
| Bun.serve (raw) | 136,500 | 131,077 | 130,479 | 92,616 |
The harness also runs Go, Rust and JVM subjects alongside these. The NestJS
subject is real NestJS with real reflect-metadata. It states what it cannot
measure, too: the load generator shares a machine with the subject, and the
closed-loop design is subject to coordinated omission.
Reproduce it with bun run --filter '@dunx/bench' start. The methodology is in
internal/bench/README.md.
When not to use it
- You do not want DI. Elysia and Hono own that space, they are mature, and they are faster to learn.
- Boot time is your critical number. 43 ms is fine for a service that starts once and stays up, and wrong for a per-invocation serverless function.
- You need request-scoped or transient providers. Not supported, rejected with measurements.
- You are not certain you are on Bun. No CommonJS build, no Node
compatibility layer.
Bun.serve,bun:sqlite,Bun.RedisClientandBun.passwordare load-bearing throughout. - You want a mature third-party ecosystem. There is not one yet.
Built with dunx
Firecracker - live
A provably-fair crash game: bet during the window, watch the rocket climb, cash out before it explodes. Every round is verifiable after the fact.
21 modules, 8 controllers, a WebSocket gateway and 4 job handlers across 165
backend files, on @dunx/core, @dunx/http, @dunx/infra, @dunx/auth,
@dunx/openapi, @dunx/testing, @dunx/transform.
Examples
Each is kept alive by CI. Each also exits 0 with no database, Redis or S3 installed.
| Example | Answers |
|---|---|
examples/minimal |
What does it look like? Five files, read top to bottom in two minutes |
examples/databases |
How do I set up a database? SQLite (async and sync), Postgres, MySQL |
examples/testing |
How do I test it? Overrides, a real server on port 0, a guard |
examples/full |
Does it compose? Every package in one long-running service |
examples/binary |
How do I ship it? A CLI app compiled to one standalone executable |
bun install
bun run --filter '@dunx/example-minimal' start
Packages
| Package | Npm | Coverage | Description |
|---|---|---|---|
@dunx/auth |
Better Auth for dunx: its handler mounted on Bun.serve, a session guard reading @Public() and @Roles(), the caller in async context, and Bun.password hashing | ||
@dunx/core |
DI container, modules, lifecycle and the injectable Logger contract for the dunx framework | ||
@dunx/dashboard |
An opt-in operations page for a running dunx app: routes, the provider graph, gateways, config and runtime health, with bull-board mounted for the queues | ||
@dunx/http |
Bun.serve adapter for the dunx framework: controllers, middleware and WebSocket gateways | ||
@dunx/infra |
Database, Redis, queue, AMQP, schedule, storage, image and logging infrastructure for dunx. drizzle over bun:sqlite and Bun.SQL, bullmq over Bun.RedisClient, rabbitmq-client for RabbitMQ, plus Bun.file, Bun.Glob, Bun.S3Client, Bun.Image and @arkv/logger | ||
@dunx/openapi |
OpenAPI 3.1 documents for dunx controllers, generated from the schemas the routes already validate, with Swagger UI or Scalar mounted over them | ||
@dunx/testing |
Test harness for dunx apps: a container with providers replaced in place, and a real Bun.serve on port 0 | ||
@dunx/transform |
Load-time transform that records constructor dependencies for the dunx container | ||
@dunx/create-app |
Scaffold a new dunx application - bunx @dunx/create-app my-api | ||
@dunx/mcp |
A Model Context Protocol server for dunx: the written guide and scaffold catalogue with no app, plus your routes, providers and modules once you point it at one |
Contributing
Pull requests are welcome. CONTRIBUTING.md is the full guide: how to get set up, which checks CI runs, the repo's rules on native implementations and third-party dependencies, and the house style a review will hold you to.
The short version: Bun only, no npm/npx/yarn/pnpm; bun install then
bun run build before anything else; run bun run ci, every gate CI runs, before
you push; conventional commits; a bug fix comes with the test
that would have caught it; and a claim about performance comes with the numbers.
License
README fetched from the repository 4 hours ago. The original is authoritative.