Skip to main content
Glama

hono-apcore

Hono-Adapter für das apcore Ökosystem der AI-Perceivable-Module. Verwandelt eine Hono-App in MCP-Tools und OpenAI-kompatible Funktionsdefinitionen – entweder durch explizite Tool-Deklaration oder durch Scannen der bereits vorhandenen Routen.

Funktionen

  • Zwei Wege hinein – Tools mit defineTool() / defineToolset() deklarieren oder vorhandene Routen ohne eine einzige Codeänderung scannen

  • Route-Replay – eine gescannte Route wird zu einem Modul, das über app.request() zurückruft, sodass Middleware, Validatoren und Fehlerbehandler weiterhin ausgeführt werden

  • Ein PortmountMcp() bedient den MCP-Endpunkt, den Tool Explorer und /health aus derselben Hono-App

  • Annotations-InferenzGET → readonly + cacheable, PUT → idempotent, DELETE → destruktiv (RFC-9110-Semantik sicherer Methoden)

  • Multi-Schema – TypeBox, Zod 3, Zod 4 und reines JSON Schema, automatisch erkannt über eine Prioritätskette

  • Context, ACL und Identität – die apcore()-Middleware baut einen Pro-Request-apcore-Context mit W3C-Trace-Propagation auf, sodass ACL-Regeln auch Ihre Routen regieren

  • Laufzeit-agnostischer Kernapcore-mcp, apcore-cli und apcore-a2a sind optionale Peers, die lazy geladen werden, sodass der Import von hono-apcore niemals node:http in einen Edge-Build zieht

  • CLIhono-apcore scan | serve | export funktioniert mit einer einfachen Hono-App

  • YAML-Bindings – Module deklarativ registrieren, ohne den Quellcode anzufassen

Related MCP server: Graft

Installation

npm install hono-apcore hono

Optionale Peers, nur für die Oberflächen installieren, die Sie nutzen:

npm install apcore-mcp @modelcontextprotocol/sdk   # MCP server + Tool Explorer
npm install @hono/node-server                      # mountMcp() on the Node runtime
npm install apcore-cli                             # CLI surface
npm install apcore-a2a                             # A2A agent surface
npm install @sinclair/typebox                      # TypeBox schemas (recommended)
npm install zod                                    # Zod schemas

Voraussetzungen: Node.js >= 18, Hono >= 4 (getestet mit Hono 4.13).

Schnellstart

1. Einige Tools deklarieren

// todo.tools.ts
import { Type } from '@sinclair/typebox';
import { defineToolset } from 'hono-apcore';

export const todoTools = defineToolset({
  namespace: 'todo',
  description: 'Todo list management',
  tags: ['todo'],
  tools: {
    list: {
      description: 'List all todos, optionally filtered by status',
      inputSchema: Type.Object({ done: Type.Optional(Type.Boolean()) }),
      annotations: { readonly: true, idempotent: true },
      handler: (inputs) => ({ todos: store.list(inputs.done as boolean | undefined) }),
    },
    add: {
      description: 'Add a new todo item',
      inputSchema: Type.Object({ title: Type.String() }),
      annotations: { readonly: false },
      handler: (inputs) => ({ todo: store.add(String(inputs.title)) }),
    },
  },
});

2. In die App einbinden

// app.ts
import { Hono } from 'hono';
import { apcore, createApcore } from 'hono-apcore';
import { todoTools } from './todo.tools.js';

export const ap = createApcore({
  tools: todoTools,
  mcp: { name: 'my-app', explorer: true, allowExecute: true },
});

export const app = new Hono();
app.use('*', apcore(ap));
app.get('/todos', (c) => c.json(store.list()));

3. Starten

// main.ts
import { serve } from '@hono/node-server';
import { app, ap } from './app.js';

await ap.init(app);              // register tools + scan routes
await ap.mountMcp(app);          // mount /mcp, /explorer, /health

serve({ fetch: app.fetch, port: 3000 });

Ihre App antwortet nun auf:

  • REST unter http://localhost:3000/todos

  • MCP unter http://localhost:3000/mcp

  • Tool Explorer unter http://localhost:3000/explorer/

Zwei Wege, eine Fähigkeit bereitzustellen

defineTool() – explizite Tools

Das Hono-Pendant zum @ApTool-Decorator von NestJS. Hono hat keine Klassen oder DI-Container, die dekoriert werden könnten, also ist ein Tool ein schlichtes Objekt, das seine eigenen Metadaten und seinen Handler mit sich führt.

import { defineTool } from 'hono-apcore';

const sendEmail = defineTool({
  namespace: 'email',
  name: 'send',                 // -> module id "email.send"
  description: 'Send an email',
  inputSchema: Type.Object({ to: Type.String(), body: Type.String() }),
  outputSchema: Type.Object({ messageId: Type.String() }),
  annotations: { readonly: false, destructive: false, requiresApproval: true },
  tags: ['email'],
  params: { to: 'Recipient address' },   // merged into the schema descriptions
  handler: async (inputs, context) => mailer.send(inputs, context),
});

Feld

Hinweise

id

Wird unverändert verwendet. Andernfalls "<namespace>.<name>", wobei name in Snake Case umgewandelt wird

inputSchema / outputSchema

TypeBox, Zod oder reines JSON Schema

annotations

readonly, destructive, idempotent, requiresApproval, openWorld, streaming, cacheable, …

params

Pro-Parameter-Prosa, die in das Eingabeschema eingearbeitet wird. JavaScript kann die führenden Kommentare einer Funktion zur Laufzeit nicht so lesen, wie Python einen Docstring liest, daher ist dies explizit

handler

(inputs, context) => result. Ein Nicht-Objekt-Ergebnis wird als { result } verpackt

Routen-Scanning – Tools ohne Eingriff

Zeigen Sie den Scanner auf eine App, und jede Route wird zu einem Modul, das sie in-process über app.request() repliziert:

const ap = createApcore({
  routes: {
    excludePaths: ['/health', '/mcp*', '/explorer*'],
    modulePrefix: 'api',
  },
});

await ap.init(app);   // -> api.todos.list, api.todos.get, api.todos.create, …

Modul-IDs ergeben sich aus Pfad und HTTP-Verb:

Route

Modul-ID

Abgeleitete Annotationen

GET /todos

todos.list

readonly, cacheable

GET /todos/:id

todos.get

readonly, cacheable

POST /todos

todos.create

PUT /todos/:id

todos.update

idempotent

DELETE /todos/:id

todos.delete

destructive

Das generierte Eingabeschema trägt eine erforderliche String-Eigenschaft pro Pfadparameter plus ein frei formbares query-Objekt (GET/DELETE) oder body-Objekt (POST/PUT/PATCH). Überschreiben Sie alles davon pro Route:

routes: {
  overrides: {
    'GET /todos': {
      id: 'todo.all',
      description: 'Every todo, newest first',
      inputSchema: Type.Object({ done: Type.Optional(Type.Boolean()) }),
      annotations: { readonly: true, idempotent: true },
    },
    'DELETE /admin/wipe': { skip: true },
  },
}

Da die Ausführung über app.request() zurückläuft, durchläuft ein KI-Aufruf denselben Codepfad wie ein HTTP-Aufruf – Auth-Middleware, Validatoren, Fehlerbehandler und alles andere. Identität und W3C-Trace-Header aus dem apcore-Context werden auf den replizierten Request übertragen.

API-Referenz

createApcore(options)

Gibt eine HonoApcore zurück – Registry, Executor und jede Oberfläche hängen daran.

createApcore({
  extensionsDir?: string | null,   // scanned by Registry.discover()
  acl?: ACL,                       // enforced by the Executor on every call
  middleware?: Middleware[],       // apcore middleware installed on the Executor
  bindings?: string,               // YAML bindings file loaded during init()
  tools?: ApToolDefinition[],      // registered during init()
  routes?: RouteScanOptions,       // route-scanner configuration
  settings?: Partial<ApcoreSettings>,  // overrides for the APCORE_* settings
  mcp?: ApcoreMcpOptions,          // presence enables the MCP surface
  cli?: ApcoreCliOptions,          // presence enables the CLI surface
  a2a?: ApcoreA2aOptions,          // presence enables the A2A surface
})

Methode

Beschreibung

init(app?, routeOptions?)

Tools und Bindings entdecken, registrieren, Routen scannen, eigenständige Oberflächen starten. Idempotent

ready()

Auf ein laufendes init() warten

registerTool(tool) / registerTools(tools)

Tool-Definitionen zur Laufzeit registrieren

registerMethod(opts) / registerObject(opts)

Die Methoden eines einfachen Service-Objekts registrieren

scanRoutes(app, opts?)

Die Routen einer App scannen und registrieren

routeOptions

Die zusammengeführten Routen-Scan-Optionen, die diese Instanz verwenden würde

loadBindings(path?, resolver?)

Eine YAML-Bindings-Datei laden

mountMcp(app, opts?)

/mcp, den Explorer und /health in die App einhängen

toOpenaiTools(opts?)

OpenAI-kompatible Funktionsdefinitionen

close()

Die MCP- und A2A-Oberflächen herunterfahren

apcore(instance | options, middlewareOptions?)

Hono-Middleware, die die Instanz und einen Pro-Request-apcore-Context auf den Hono-Context legt.

app.use('*', apcore(ap));

app.get('/orders', async (c) =>
  c.json(await getApcore(c).executor.call('orders.list', {}, getApcoreContext(c))),
);

Die Variablenzuordnung wird erweitert, sodass c.get('apcore') und c.get('apcoreContext') ebenfalls typisiert sind. Übergeben Sie { skipContext: true } auf Routen, die nie Module aufrufen, oder { contextFactory }, um echte Authentifizierung anzustöpseln.

HonoContextFactory

Baut den apcore-Context aus einem Hono-Context, einem Request oder nackten Headers auf.

Identitätsauflösung, in dieser Reihenfolge: x-user-idAuthorization: Bearer … (Identitäts-ID "bearer") → ein nackter x-roles-Header (eine Demo-Abkürzung) → anonym. Ein traceparent-Header liefert die Trace-ID; x-correlation-id (oder x-request-id) landet in context.data.

new HonoContextFactory({
  resolveIdentity: (headers) => identityFromSession(headers),  // wins over the above
  data: (headers) => ({ tenant: headers.get('x-tenant') }),
});

MCP

ApcoreMcpService betreibt den MCP-Server auf zwei Arten.

Eingebettet – ein Prozess, ein Port:

await ap.mountMcp(app, { endpoint: '/mcp', explorer: true, allowExecute: true });

Dies benötigt die rohen Node-Request- und Response-Objekte, die @hono/node-server auf c.env bereitstellt, ist also nur für Node gedacht; ein eingehängter Handler auf einer anderen Laufzeit antwortet mit 501 und dieser Erklärung. endpoint muss der Pfad sein, wie ihn der HTTP-Server sieht – den Präfix einschließen, wenn die App unter einem basePath liegt.

Eigenständig – ein separater Port oder stdio für einen per CLI gestarteten Server:

createApcore({ mcp: { transport: 'streamable-http', host: '0.0.0.0', port: 8000 } });
// init() starts it, because `transport` was set explicitly

Wichtige MCP-Optionen:

Feld

Typ

Beschreibung

transport

'stdio' | 'streamable-http' | 'sse'

Eigenständiger Transport. Das Setzen startet den Server über init()

host / port

string / number

Bindeadresse für HTTP-Transports

name / version

string

Server-Identität

explorer / explorerPrefix / allowExecute

Tool-Explorer-Web-UI

authenticator / requireAuth / exemptPaths

JWT- oder benutzerdefinierte Authentifizierung

tags / prefix

Nur passende Module bereitstellen

validateInputs

boolean

Eingabeschemas bei jedem Aufruf erzwingen

observability

Metrik- + Usage-Middleware und deren Endpunkte

outputFormat / outputFormatter / redactOutput / trace

Ergebnis-Serialisierung

approvalHandler / approvalStore / approvalNotify

Genehmigungs-Gate für destruktive Tools

mcpMiddleware / mcpAcl

Zusätzliche apcore-Middleware / ACL für den MCP-Executor

Schema-Adapter

Schemas werden automatisch erkannt und über eine Prioritätskette konvertiert:

Adapter

Priorität

Eingabe

TypeBoxAdapter

100

@sinclair/typebox-Schemas

ZodAdapter

50

Zod 3 (_def.typeName) und Zod 4 (_zod.def.type)

JsonSchemaAdapter

30

Reine JSON-Schema-Objekte

Die Erkennung ist strukturell – weder TypeBox noch Zod werden zur Laufzeit importiert –, sodass egal ist, was die Host-App installiert (oder auch nichts). Registrieren Sie eigene Adapter mit SchemaExtractor.registerAdapter().

YAML-Bindings

Module registrieren, ohne den Quellcode anzufassen:

bindings:
  - module_id: email.send
    target: EmailService.send
    description: Send an email
    input_schema:
      type: object
      properties:
        to: { type: string }
    tags: [email, mutate]
    annotations:
      readonly: false
import { resolverFromObjects } from 'hono-apcore';

await ap.loadBindings('./bindings.yaml', resolverFromObjects({ EmailService: mailer }));

In die andere Richtung serialisiert writeBindingsFile() gescannte Module wieder heraus – genau das tut hono-apcore scan --format yaml.

CLI

hono-apcore scan   ./src/app.ts            # print the modules a scan would produce
hono-apcore scan   ./src/app.ts --format yaml --out bindings.yaml
hono-apcore serve  ./src/app.ts --transport http --port 8000 --explorer
hono-apcore export ./src/app.ts --out tools.json

Der Einstieg ist pfad[:export]; der Export standardmäßig default, dann app. Wenn das Modul eine HonoApcore unter irgendeinem Namen exportiert, werden deren Konfiguration – Routenfilter, Modul-Präfix, MCP-Optionen – berücksichtigt, sodass scan genau die Module meldet, die die App selbst registriert; CLI-Flags überschreiben sie. Ein Einstieg ohne Instanz funktioniert ebenfalls, sodass serve gegen eine App läuft, die nie von apcore gehört hat. TypeScript-Einstiege benötigen einen Loader:

npx tsx node_modules/.bin/hono-apcore scan ./src/app.ts

Konfiguration (APCORE_*)

Die kanonischen Einstellungen, die jede apcore-Integration implementiert, aus der Umgebung gelesen und über settings überschreibbar:

Variable

Type

Default

Purpose

APCORE_ENABLED

bool

true

Hauptschalter — false macht init() zu einem No-op

APCORE_DEBUG

bool

false

Ausführliche Protokollierung / Introspection

APCORE_SCANNERS

list

["auto"]

Aktivierte Scanner-Identifikatoren

APCORE_INCLUDE_PATHS

list

[]

Einzubeziehende Routenmuster (leer = alle)

APCORE_EXCLUDE_PATHS

list

[]

Auszuschließende Routenmuster

APCORE_MODULE_PREFIX

str

""

Präfix, das generierten Modul-IDs vorangestellt wird

APCORE_AUTH_ENABLED

bool

false

Auth für MCP/A2A-Endpunkte erforderlich

APCORE_AUTH_STRATEGY

str

"bearer"

bearer / session / custom

APCORE_TRANSPORT

str

"stdio"

MCP-Transport: stdio / http / sse

APCORE_HOST

str

"0.0.0.0"

Bind-Adresse, wenn der Transport nicht stdio ist

APCORE_PORT

int

8808

Bind-Port, wenn der Transport nicht stdio ist

Optionale Peers werden nicht re-exportiert

Im Gegensatz zum NestJS-Adapter exportiert hono-apcore die apcore-mcp / apcore-cli / apcore-a2a-Oberflächen nicht erneut. Andernfalls würden sie eager geladen, und apcore-mcp zieht node:http mit ein — was einen Workers-, Deno- oder Bun-Build einer App bricht, die die MCP-Oberfläche nie nutzt. Importieren Sie diese Symbole aus ihren eigenen Paketen:

import { JWTAuthenticator, getCurrentIdentity } from 'apcore-mcp';
import { createCli } from 'apcore-cli';
import { A2AClient } from 'apcore-a2a';

apcore-js und apcore-toolkit sind harte Abhängigkeiten, daher werden ihre gemeinsamen Symbole (ACL, Config, registerSysModules, TraceContext, BaseScanner, formatModules, …) direkt aus hono-apcore re-exportiert.

Beispiele

Beispiel

Zeigt

examples/demo

Vollständige App: handgeschriebene Tools und Routen-Scanning, JWT, ACL, Systemmodule, Docker

examples/acl_demo

Routen, die von der apcore-ACL verwaltet werden — orders.delete nur für Admins

pnpm install && pnpm build
cd examples/demo && pnpm install && pnpm dev

Ausführliche Dokumentation

Skripte

Befehl

Beschreibung

pnpm build

TypeScript kompilieren

pnpm dev

Kompilierung im Watch-Modus

pnpm test

Test-Suite ausführen (vitest)

pnpm test:coverage

Tests mit Coverage (90%-Schwellen)

pnpm typecheck

Typprüfung ohne Ausgabe

pnpm lint

Lint für Quellcode und Tests

Lizenz

Apache-2.0

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
1Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Exposes Hono API endpoints as Model Context Protocol tools, allowing LLMs to interact with your API routes through a dedicated MCP endpoint. It provides helpers to describe routes and includes a codemode for dynamic API interaction via search and execute tools.
    32
    86
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables building agent-ready APIs that expose tools as both HTTP and MCP endpoints from a single server definition, with automatic OpenAPI, discovery docs, and interactive API reference.
    5
    Apache 2.0
  • A
    license
    B
    quality
    C
    maintenance
    Transforms OpenAPI definitions into MCP tools for seamless LLM-API integration.
    8
    39
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Easily expose your Hono API endpoints as MCP tools with minimal configuration, supporting type-safe input handling and tool registration.
    32
    2
    MIT

View all related MCP servers

Related MCP Connectors

  • Point Gecko at an OpenAPI spec; get first-call-correct, auth-hidden agent tools.

  • Free public MCP for AI agents — 193 tools, 44 workflows. No API key.

  • MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/aiperceivable/hono-apcore'

If you have feedback or need assistance with the MCP directory API, please join our Discord server