hono-apcore
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 scannenRoute-Replay – eine gescannte Route wird zu einem Modul, das über
app.request()zurückruft, sodass Middleware, Validatoren und Fehlerbehandler weiterhin ausgeführt werdenEin Port –
mountMcp()bedient den MCP-Endpunkt, den Tool Explorer und/healthaus derselben Hono-AppAnnotations-Inferenz –
GET→ 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-Contextmit W3C-Trace-Propagation auf, sodass ACL-Regeln auch Ihre Routen regierenLaufzeit-agnostischer Kern –
apcore-mcp,apcore-cliundapcore-a2asind optionale Peers, die lazy geladen werden, sodass der Import vonhono-apcoreniemalsnode:httpin einen Edge-Build ziehtCLI –
hono-apcore scan | serve | exportfunktioniert mit einer einfachen Hono-AppYAML-Bindings – Module deklarativ registrieren, ohne den Quellcode anzufassen
Related MCP server: Graft
Installation
npm install hono-apcore honoOptionale 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 schemasVoraussetzungen: 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/todosMCP unter
http://localhost:3000/mcpTool 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 |
| Wird unverändert verwendet. Andernfalls |
| TypeBox, Zod oder reines JSON Schema |
|
|
| 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 |
|
|
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 |
|
|
|
|
|
|
|
| — |
|
|
|
|
|
|
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 |
| Tools und Bindings entdecken, registrieren, Routen scannen, eigenständige Oberflächen starten. Idempotent |
| Auf ein laufendes |
| Tool-Definitionen zur Laufzeit registrieren |
| Die Methoden eines einfachen Service-Objekts registrieren |
| Die Routen einer App scannen und registrieren |
| Die zusammengeführten Routen-Scan-Optionen, die diese Instanz verwenden würde |
| Eine YAML-Bindings-Datei laden |
|
|
| OpenAI-kompatible Funktionsdefinitionen |
| 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-id → Authorization: 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 explicitlyWichtige MCP-Optionen:
Feld | Typ | Beschreibung |
|
| Eigenständiger Transport. Das Setzen startet den Server über |
|
| Bindeadresse für HTTP-Transports |
|
| Server-Identität |
| Tool-Explorer-Web-UI | |
| JWT- oder benutzerdefinierte Authentifizierung | |
| Nur passende Module bereitstellen | |
|
| Eingabeschemas bei jedem Aufruf erzwingen |
| Metrik- + Usage-Middleware und deren Endpunkte | |
| Ergebnis-Serialisierung | |
| Genehmigungs-Gate für destruktive Tools | |
| 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 |
| 100 |
|
| 50 | Zod 3 ( |
| 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: falseimport { 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.jsonDer 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.tsKonfiguration (APCORE_*)
Die kanonischen Einstellungen, die jede apcore-Integration implementiert, aus
der Umgebung gelesen und über settings überschreibbar:
Variable | Type | Default | Purpose |
| bool |
| Hauptschalter — |
| bool |
| Ausführliche Protokollierung / Introspection |
| list |
| Aktivierte Scanner-Identifikatoren |
| list |
| Einzubeziehende Routenmuster (leer = alle) |
| list |
| Auszuschließende Routenmuster |
| str |
| Präfix, das generierten Modul-IDs vorangestellt wird |
| bool |
| Auth für MCP/A2A-Endpunkte erforderlich |
| str |
|
|
| str |
| MCP-Transport: |
| str |
| Bind-Adresse, wenn der Transport nicht stdio ist |
| int |
| 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 |
Vollständige App: handgeschriebene Tools und Routen-Scanning, JWT, ACL, Systemmodule, Docker | |
Routen, die von der apcore-ACL verwaltet werden — |
pnpm install && pnpm build
cd examples/demo && pnpm install && pnpm devAusführliche Dokumentation
Funktionsübersicht — Architektur und Abhängigkeitsgraph
Tool-Definition —
defineTool,defineToolset, Modul-IDsRouten-Scanner — wie Routen zu Modulen werden und was Replay kostet
MCP-Integration — eingebettet vs. eigenständig, die Node-Brücke
Schema-Extraktion — die Adapterkette und benutzerdefinierte Adapter
Kontext und ACL — Identität, Tracing und verwaltende Routen
Skripte
Befehl | Beschreibung |
| TypeScript kompilieren |
| Kompilierung im Watch-Modus |
| Test-Suite ausführen (vitest) |
| Tests mit Coverage (90%-Schwellen) |
| Typprüfung ohne Ausgabe |
| Lint für Quellcode und Tests |
Lizenz
Apache-2.0
This server cannot be installed
Maintenance
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
- AlicenseNot gradedqualityDmaintenanceExposes 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.3286MIT
- AlicenseNot gradedqualityCmaintenanceEnables 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.5Apache 2.0
- AlicenseBqualityCmaintenanceTransforms OpenAPI definitions into MCP tools for seamless LLM-API integration.8391MIT
- AlicenseNot gradedqualityCmaintenanceEasily expose your Hono API endpoints as MCP tools with minimal configuration, supporting type-safe input handling and tool registration.322MIT
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.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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