hexagonal-inversify-di — community hexagonal-inversify-di, mcp-browser-kit, community, ide skills, Claude Code, Cursor, Windsurf

v1.0.0

À propos de ce Skill

An MCP Server that enables AI assistants to interact with your local browsers.

ndthanhdev ndthanhdev
[51]
[8]
Updated: 4/16/2026

Killer-Skills Review

Decision support comes first. Repository text comes second.

Reference-Only Page Review Score: 3/11

This page remains useful for operators, but Killer-Skills treats it as reference material instead of a primary organic landing page.

Quality floor passed for review
Review Score
3/11
Quality Score
54
Canonical Locale
en
Detected Body Locale
en

An MCP Server that enables AI assistants to interact with your local browsers.

Pourquoi utiliser cette compétence

An MCP Server that enables AI assistants to interact with your local browsers.

Meilleur pour

Suitable for operator workflows that need explicit guardrails before installation and execution.

Cas d'utilisation exploitables for hexagonal-inversify-di

! Sécurité et Limitations

Why this page is reference-only

  • - Current locale does not satisfy the locale-governance contract.
  • - The page lacks a strong recommendation layer.
  • - The page lacks concrete use-case guidance.
  • - The page lacks explicit limitations or caution signals.

Source Boundary

The section below is supporting source material from the upstream repository. Use the Killer-Skills review above as the primary decision layer.

Labs Demo

Browser Sandbox Environment

⚡️ Ready to unleash?

Experience this Agent in a zero-setup browser environment powered by WebContainers. No installation required.

Boot Container Sandbox

FAQ & Installation Steps

These questions and steps mirror the structured data on this page for better search understanding.

? Frequently Asked Questions

What is hexagonal-inversify-di?

An MCP Server that enables AI assistants to interact with your local browsers.

How do I install hexagonal-inversify-di?

Run the command: npx killer-skills add ndthanhdev/mcp-browser-kit/hexagonal-inversify-di. It works with Cursor, Windsurf, VS Code, Claude Code, and 19+ other IDEs.

Which IDEs are compatible with hexagonal-inversify-di?

This skill is compatible with Cursor, Windsurf, VS Code, Trae, Claude Code, OpenClaw, Aider, Codex, OpenCode, Goose, Cline, Roo Code, Kiro, Augment Code, Continue, GitHub Copilot, Sourcegraph Cody, and Amazon Q Developer. Use the Killer-Skills CLI for universal one-command installation.

How To Install

  1. 1. Open your terminal

    Open the terminal or command line in your project directory.

  2. 2. Run the install command

    Run: npx killer-skills add ndthanhdev/mcp-browser-kit/hexagonal-inversify-di. The CLI will automatically detect your IDE or AI agent and configure the skill.

  3. 3. Start using the skill

    The skill is now active. Your AI agent can use hexagonal-inversify-di immediately in the current project.

! Reference-Only Mode

This page remains useful for installation and reference, but Killer-Skills no longer treats it as a primary indexable landing page. Read the review above before relying on the upstream repository instructions.

Imported Repository Instructions

The section below is supporting source material from the upstream repository. Use the Killer-Skills review above as the primary decision layer.

Supporting Evidence

hexagonal-inversify-di

Install hexagonal-inversify-di, an AI agent skill for AI agent workflows and automation. Works with Claude Code, Cursor, and Windsurf with one-command setup.

SKILL.md
Readonly
Imported Repository Instructions
The section below is supporting source material from the upstream repository. Use the Killer-Skills review above as the primary decision layer.
Supporting Evidence

Hexagonal + InversifyJS DI Pattern

This monorepo uses Hexagonal architecture (Ports & Adapters) wired with InversifyJS. Every package's role is encoded in its name prefix, and dependency wiring follows a strict, repeatable recipe.

When to Use This Skill

Load this skill when the task involves:

  • Creating a new package under packages/
  • Adding or modifying a port (interface + token) in a core-* package
  • Implementing a use case inside core-*
  • Implementing a driven (secondary) or driving (primary) adapter
  • Editing an app composition root (apps/*/src/services/container.ts, apps/*/src/bootstrap-*.ts, apps/*/src/main.ts)
  • Any question about @injectable, @inject, Container, bindings, or scopes in this repo

Architecture Map

PrefixRoleMay depend on
core-*Domain. Use cases + port definitions (input-ports/, output-ports/)types, core-utils
*-driving-*Primary adapter. Drives the core inward (e.g. HTTP/MCP/RPC entrypoints)relevant core-*, types, helper-*
*-driven-*Secondary adapter. Driven by the core outward (DBs, external services, loggers)relevant core-*, types, helper-*
helper-*Shared utilities/mixins used by adapterstypes
typesPure type-only contracts. No DI, no runtime code.nothing

Rule of thumb: adapters depend on core-* (where the port lives), never directly on types when a port exists. Core depends only on types and core-utils.

Core Conventions

1. DI library

  • InversifyJS + reflect-metadata
  • Import reflect-metadata once per runtime entrypoint (already handled in existing apps)

2. Dual identifier trick (ports)

A port is an interface and a Symbol sharing the same name. TypeScript merges the declarations, so consumers write @inject(FooPort) private foo: FooPort.

ts
1// packages/core-<name>/src/output-ports/foo.ts 2import type { SomeContract } from "@mcp-browser-kit/types"; 3 4export interface FooOutputPort extends SomeContract {} 5export const FooOutputPort = Symbol("FooOutputPort");

Re-export from the package root (packages/core-<name>/src/index.ts).

Use Symbol(...) by default. Use Symbol.for(...) only when the token must be resolvable across independent realms/bundles.

3. Default scope: Singleton

Every core container factory creates the container with:

ts
1const container = new Container({ defaultScope: "Singleton" });

Opt into transient explicitly per binding with .inTransientScope() when needed.

4. Core container factories

Each core-* package exports a createCore<Name>Container() that:

  1. Creates the container
  2. Binds input ports → use cases (driving side is owned by core)
  3. Binds internal core collaborators via .toSelf()

It must not bind output ports — those are the composition root's responsibility.

5. Adapter setupContainer convention

Every adapter class exposes a static method that registers itself into a container provided by the caller. This is the project-wide extension point.

ts
1static setupContainer( 2 container: Container, 3 serviceIdentifier: interfaces.ServiceIdentifier<FooOutputPort> = FooOutputPort, 4) { 5 container.bind<FooOutputPort>(serviceIdentifier).to(FooDrivenAdapter); 6}

Callers pass the container they own; they may override the token when a single class implements multiple ports.

Recipes

Recipe A — Define a new output port

  1. Create packages/core-<name>/src/output-ports/<port-kebab>.ts:
    ts
    1export interface FooOutputPort { 2 doFoo(input: string): Promise<void>; 3} 4export const FooOutputPort = Symbol("FooOutputPort");
  2. Re-export from packages/core-<name>/src/index.ts.
  3. Inject into a use case with @inject(FooOutputPort).

Reference: packages/core-server/src/output-ports/logger-factory.ts

Recipe B — Define a new input port + use case

  1. Define the input port (same dual-identifier pattern) in packages/core-<name>/src/input-ports/.
  2. Implement the use case in packages/core-<name>/src/core/:
    ts
    1import { inject, injectable } from "inversify"; 2 3@injectable() 4export class DoFooUseCase implements FooInputPort { 5 constructor( 6 @inject(BarOutputPort) private readonly bar: BarOutputPort, 7 ) {} 8 9 async execute(input: string) { 10 await this.bar.doSomething(input); 11 } 12}
  3. Bind the use case to the input-port token inside createCore<Name>Container():
    ts
    1container.bind<FooInputPort>(FooInputPort).to(DoFooUseCase);

Reference: packages/core-server/src/utils/create-core-server-container.ts and packages/core-server/src/core/.

Recipe C — Implement a driven adapter (secondary)

Package name: <context>-driven-<capability> (e.g. driven-logger-factory).

ts
1import { Container, inject, injectable, type interfaces } from "inversify"; 2import { FooOutputPort } from "@mcp-browser-kit/core-<name>"; 3 4@injectable() 5export class FooDrivenAdapter implements FooOutputPort { 6 async doFoo(input: string) { /* external I/O */ } 7 8 static setupContainer( 9 container: Container, 10 serviceIdentifier: interfaces.ServiceIdentifier<FooOutputPort> = FooOutputPort, 11 ) { 12 container.bind<FooOutputPort>(serviceIdentifier).to(FooDrivenAdapter); 13 } 14}

Do not import from sibling adapter packages. Depend only on the relevant core-* package (for the port) and types/helper-* as needed.

Reference: packages/driven-logger-factory/src/services/consola.ts (see setupContainer near line 287).

Recipe D — Implement a driving adapter (primary)

Package name: <context>-driving-<capability> (e.g. server-driving-mcp-server).

ts
1import { Container, inject, injectable } from "inversify"; 2import { FooInputPort } from "@mcp-browser-kit/core-<name>"; 3 4@injectable() 5export class BazDrivingAdapter { 6 constructor( 7 @inject(FooInputPort) private readonly foo: FooInputPort, 8 ) {} 9 10 async start() { /* accept external requests and dispatch to this.foo */ } 11 12 static setupContainer(container: Container) { 13 container.bind(BazDrivingAdapter).toSelf(); 14 } 15}

Driving adapters consume input-port symbols. They register themselves via .toSelf() so the app can container.get(BazDrivingAdapter) at the entrypoint.

Reference: packages/server-driving-mcp-server/src/services/server-driving-mcp-server.ts (setupContainer near line 103).

Recipe E — Wire an app composition root

Ordering is important: core factory first, then driven adapters, then driving adapters, then resolve in main.ts.

ts
1// apps/<app>/src/services/container.ts 2import { createCoreXxxContainer, FooOutputPort } from "@mcp-browser-kit/core-<name>"; 3import { FooDrivenAdapter } from "@mcp-browser-kit/<context>-driven-<capability>"; 4import { BazDrivingAdapter } from "@mcp-browser-kit/<context>-driving-<capability>"; 5 6export const container = createCoreXxxContainer(); 7 8FooDrivenAdapter.setupContainer(container, FooOutputPort); 9BazDrivingAdapter.setupContainer(container);
ts
1// apps/<app>/src/main.ts 2import "reflect-metadata"; 3import { container } from "./services/container"; 4import { BazDrivingAdapter } from "@mcp-browser-kit/<context>-driving-<capability>"; 5 6async function main() { 7 await container.get(BazDrivingAdapter).start(); 8} 9 10main();

Reference: apps/server/src/services/container.ts and apps/server/src/main.ts.

Recipe F — Per-runtime sub-containers (browser extensions)

MV2/MV3 isolate runtimes (background/service worker vs. content script vs. popup). Each runtime is its own process and cannot share an Inversify container instance. Create a dedicated composition root per runtime:

  • bootstrap-<ext>-sw.ts / bootstrap-<ext>-bg.ts — the worker/background context
  • bootstrap-<ext>-tab.ts — the content-script context

Each bootstrap calls createCore<Name>Container() and wires the adapters appropriate for that runtime (e.g. browser-side logger in tabs, error-stream logger in server).

Reference: apps/m3/src/bootstrap-mbk-sw.ts and apps/m3/src/bootstrap-mbk-tab.ts.

Decision Guide

Which package prefix?

  1. Defines domain behavior or a port? → core-*
  2. External entrypoint that calls into the core? → *-driving-*
  3. Implementation the core calls outward to? → *-driven-*
  4. Shared mixin/util consumed by multiple adapters? → helper-*
  5. Pure type contract with no runtime? → add to types

Which logger adapter?

  • Node/server process where stdout is reserved for protocol traffic → DrivenLoggerFactoryConsolaError (writes to stderr)
  • Browser/extension runtime → DrivenLoggerFactoryConsolaBrowser

Symbol vs Symbol.for?

  • Default: Symbol("Name") — unique per module instance, fine for normal use
  • Symbol.for("Name") — only when the token must match across independent bundles/realms

Gotchas

  • Adapter → core, not adapter → types. If a port exists, import its symbol from the owning core-* package.
  • No shared containers across extension runtimes. SW and each tab get their own.
  • Multi-token aliasing: binding one class to two tokens with .to(Class) twice produces two singletons. If you need a single instance resolvable under multiple tokens, bind once, then alias with .toService(otherToken) (or bind .toConstantValue(instance)).
  • Injecting Container itself is possible (useful for lazy resolution inside routers/factories) but tightly couples the consumer to Inversify. Avoid unless lazy resolution is a hard requirement.
  • ext-e2e-test-app and ext-e2e intentionally do not use DI. Don't retrofit them.
  • types is runtime-free. Never add @injectable classes or Symbols there.

Checklists

New port

  • File under core-*/src/{input,output}-ports/
  • export interface XxxPort and export const XxxPort = Symbol("XxxPort") share a name
  • Re-exported from core-*/src/index.ts
  • Consumers use @inject(XxxPort) private foo: XxxPort

New driven adapter

  • Package named <context>-driven-<capability>
  • Depends on the owning core-* package (not types) for the port
  • Class marked @injectable()
  • Implements the port interface
  • Provides static setupContainer(container, serviceIdentifier?)
  • No imports from sibling adapter packages

New driving adapter

  • Package named <context>-driving-<capability>
  • Constructor injects input-port symbols via @inject(...)
  • Provides static setupContainer(container) that registers the class with .toSelf()
  • Exposes a public entrypoint method (e.g. start, initMcpServer)

New app wiring

  • createCore<Name>Container() called first
  • All required driven adapters registered via their setupContainer
  • All driving adapters registered via their setupContainer
  • main.ts / bootstrap imports reflect-metadata at the top
  • Entry resolves via container.get(DrivingAdapter) and invokes its entrypoint

Reference File Index

Real examples in this repo. Open these when implementing a recipe — they are the source of truth.

Port definitions

  • packages/core-server/src/output-ports/logger-factory.ts — minimal output port
  • packages/core-server/src/output-ports/extension-channel-provider.ts
  • packages/core-server/src/input-ports/server-tool-calls.ts
  • packages/core-extension/src/output-ports/browser-driver.ts
  • packages/core-extension/src/output-ports/server-channel-provider.ts
  • packages/core-extension/src/input-ports/ — additional input ports

Core container factories

  • packages/core-server/src/utils/create-core-server-container.ts
  • packages/core-extension/src/utils/create-core-extension-container.ts

Use cases

  • packages/core-server/src/core/server-tool-calls.ts@injectable use case with @inject

Driven adapter examples

  • packages/driven-logger-factory/src/services/consola.tssetupContainer at ~line 287
  • packages/server-driven-trpc-channel-provider/src/services/server-driven-trpc-channel-provider.tssetupContainer at ~line 248 (also demonstrates transient scope and Container-as-dependency)
  • packages/extension-driven-browser-driver/
  • packages/extension-driven-server-channel-provider/

Driving adapter examples

  • packages/server-driving-mcp-server/src/services/server-driving-mcp-server.tssetupContainer at ~line 103
  • packages/extension-driving-trpc-controller/

App composition roots

  • apps/server/src/services/container.ts + apps/server/src/main.ts — server
  • apps/m3/src/bootstrap-mbk-sw.ts + apps/m3/src/bootstrap-mbk-tab.ts — MV3 extension
  • apps/m2/src/bootstrap-mbk-bg.ts + apps/m2/src/bootstrap-mbk-tab.ts — MV2 extension

Helpers / shared

  • packages/helper-base-extension-channel-provider/
  • packages/helper-extension-keep-alive/
  • packages/core-utils/ — shared library code (not a hexagon; no ports)
  • packages/types/ — pure type contracts, no DI

Compétences associées

Looking for an alternative to hexagonal-inversify-di or another community skill for your workflow? Explore these related open-source skills.

Voir tout

openclaw-release-maintainer

Logo of openclaw
openclaw

Your own personal AI assistant. Any OS. Any Platform. The lobster way. 🦞

widget-generator

Logo of f
f

Generate customizable widget plugins for the prompts.chat feed system

flags

Logo of vercel
vercel

The React Framework

138.4k
0
Navigateur

pr-review

Logo of pytorch
pytorch

Tensors and Dynamic neural networks in Python with strong GPU acceleration

98.6k
0
Développeur