hono-apcore
hono-apcore
Adaptador de Hono para el ecosistema de módulos AI-Perceivable de apcore. Convierte una aplicación de Hono en herramientas MCP y definiciones de funciones compatibles con OpenAI, ya sea declarando herramientas explícitamente o escaneando las rutas que ya tienes.
Características
Dos formas de entrada — declara herramientas con
defineTool()/defineToolset(), o escanea tus rutas existentes sin cambios de código.Reproducción de rutas — una ruta escaneada se convierte en un módulo que vuelve a llamar a través de
app.request(), de modo que el middleware, los validadores y los manejadores de errores siguen ejecutándose.Un solo puerto —
mountMcp()sirve el endpoint de MCP, el Tool Explorer y/healthdesde la misma aplicación de Hono.Inferencia de anotaciones —
GET→ readonly + cacheable,PUT→ idempotent,DELETE→ destructive (semántica de métodos seguros de RFC 9110).Multi-esquema — TypeBox, Zod 3, Zod 4 y JSON Schema plano, auto-detectados mediante una cadena de prioridad.
Contexto, ACL e identidad — el middleware
apcore()construye unContextde apcore por petición con propagación de trazas W3C, de modo que las reglas ACL también gobiernan tus rutas.Núcleo independiente del runtime —
apcore-mcp,apcore-cliyapcore-a2ason pares opcionales que se cargan de forma diferida, por lo que importarhono-apcorenunca arrastranode:httpa una compilación de edge.CLI —
hono-apcore scan | serve | exportfunciona con una aplicación de Hono simple.Enlaces YAML — registra módulos de forma declarativa, sin tocar el código fuente.
Related MCP server: Graft
Instalación
npm install hono-apcore honoPares opcionales, instalados solo para las superficies que uses:
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 schemasRequisitos: Node.js >= 18, Hono >= 4 (probado con Hono 4.13).
Inicio rápido
1. Declara algunas herramientas
// 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. Conéctalo a la aplicación
// 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. Arranca
// 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 });Tu aplicación ahora responde:
REST en
http://localhost:3000/todosMCP en
http://localhost:3000/mcpTool Explorer en
http://localhost:3000/explorer/
Dos formas de exponer una capacidad
defineTool() — herramientas explícitas
La contraparte de Hono al decorador @ApTool de NestJS. Hono no tiene clases ni contenedor de DI que decorar, por lo que una herramienta es un objeto plano que lleva su propio metadato y manejador.
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),
});Campo | Notas |
| Se usa tal cual. De lo contrario, |
| TypeBox, Zod o JSON Schema plano |
|
|
| Prosa por parámetro fusionada en el esquema de entrada. JavaScript no puede leer los comentarios iniciales de una función en tiempo de ejecución como Python lee un docstring, por lo que esto es explícito |
|
|
Escaneo de rutas — herramientas sin intrusión
Apunta el escáner a una aplicación y cada ruta se convierte en un módulo que la reproduce en proceso a través de app.request():
const ap = createApcore({
routes: {
excludePaths: ['/health', '/mcp*', '/explorer*'],
modulePrefix: 'api',
},
});
await ap.init(app); // -> api.todos.list, api.todos.get, api.todos.create, …Los IDs de módulo provienen de la ruta y del verbo HTTP:
Ruta | ID de módulo | Anotaciones inferidas |
|
|
|
|
|
|
|
| — |
|
|
|
|
|
|
El esquema de entrada generado lleva una propiedad de cadena obligatoria por parámetro de ruta, más un objeto query de forma libre (GET/DELETE) o un objeto body (POST/PUT/PATCH). Sobrescribe cualquiera de ellos por ruta:
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 },
},
}Debido a que la ejecución vuelve a pasar por app.request(), una llamada de IA ejecuta el mismo camino de código que una llamada HTTP — middleware de autenticación, validadores, manejadores de errores y todo. La identidad y las cabeceras de traza W3C del Context de apcore se reenvían a la petición reproducida.
Referencia de la API
createApcore(options)
Devuelve un HonoApcore — el Registry, el Executor y todas las superficies cuelgan de él.
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
})Método | Descripción |
| Descubre, registra herramientas y enlaces, escanea rutas, inicia superficies independientes. Idempotente |
| Espera un |
| Registra definiciones de herramientas en tiempo de ejecución |
| Registra los métodos de un objeto de servicio plano |
| Escanea y registra las rutas de una aplicación |
| Las opciones de escaneo de rutas fusionadas que esta instancia usaría |
| Carga un archivo de enlaces YAML |
| Monta |
| Definiciones de funciones compatibles con OpenAI |
| Apaga las superficies MCP y A2A |
apcore(instance | options, middlewareOptions?)
Middleware de Hono que coloca la instancia y un Context de apcore por petición en el contexto de Hono.
app.use('*', apcore(ap));
app.get('/orders', async (c) =>
c.json(await getApcore(c).executor.call('orders.list', {}, getApcoreContext(c))),
);El mapa de variables se amplía, por lo que c.get('apcore') y c.get('apcoreContext') también están tipados. Pasa { skipContext: true } en rutas que nunca llaman a módulos, o { contextFactory } para conectar autenticación real.
HonoContextFactory
Construye el Context de apcore a partir de un contexto de Hono, una Request o Headers simples.
Resolución de identidad, en orden: x-user-id → Authorization: Bearer … (id de identidad "bearer") → una cabecera x-roles simple (un atajo de demostración) → anónimo. Una cabecera traceparent proporciona el id de traza; x-correlation-id (o x-request-id) aterriza en context.data.
new HonoContextFactory({
resolveIdentity: (headers) => identityFromSession(headers), // wins over the above
data: (headers) => ({ tenant: headers.get('x-tenant') }),
});MCP
ApcoreMcpService ejecuta el servidor MCP de dos maneras.
Integrado — un proceso, un puerto:
await ap.mountMcp(app, { endpoint: '/mcp', explorer: true, allowExecute: true });Esto necesita los objetos de petición y respuesta de Node en bruto que @hono/node-server expone en c.env, por lo que es solo para Node; un manejador montado en otro runtime responde 501 con esa explicación. endpoint debe ser la ruta tal como la ve el servidor HTTP — incluye el prefijo si la aplicación está bajo un basePath.
Independiente — un puerto separado, o stdio para un servidor lanzado por CLI:
createApcore({ mcp: { transport: 'streamable-http', host: '0.0.0.0', port: 8000 } });
// init() starts it, because `transport` was set explicitlyOpciones clave de MCP:
Campo | Tipo | Descripción |
|
| Transporte independiente. Configurarlo hace que |
|
| Dirección de enlace para transportes HTTP |
|
| Identidad del servidor |
| Interfaz web del Tool Explorer | |
| JWT o autenticación personalizada | |
| Exponer solo módulos coincidentes | |
|
| Aplicar esquemas de entrada en cada llamada |
| Métricas + middleware de uso y sus endpoints | |
| Serialización de resultados | |
| Puerta de aprobación para herramientas destructivas | |
| Middleware apcore adicional / ACL para el ejecutor MCP |
Adaptadores de esquema
Los esquemas se auto-detectan y convierten mediante una cadena de prioridad:
Adaptador | Prioridad | Entrada |
| 100 | Esquemas de |
| 50 | Zod 3 ( |
| 30 | Objetos JSON Schema planos |
La detección es estructural — ni TypeBox ni Zod se importan en tiempo de ejecución — por lo que cualquiera que instale la aplicación anfitriona (o ninguno) está bien. Registra el tuyo con SchemaExtractor.registerAdapter().
Enlaces YAML
Registra módulos sin tocar el código fuente:
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 }));En el otro sentido, writeBindingsFile() serializa los módulos escaneados de vuelta — que es lo que hace 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.jsonLa entrada es path[:export]; la exportación por defecto es default, luego app. Si el módulo exporta un HonoApcore bajo cualquier nombre, su configuración — filtros de ruta, prefijo de módulo, opciones de MCP — se respeta, por lo que scan informa exactamente los módulos que la propia aplicación registra; las banderas de CLI lo sobrescriben. Una entrada sin instancia también funciona, por lo que serve se ejecuta contra una aplicación que nunca ha oído hablar de apcore. Las entradas TypeScript necesitan un cargador:
npx tsx node_modules/.bin/hono-apcore scan ./src/app.tsConfiguración (APCORE_*)
La configuración canónica que implementa cada integración de apcore, leída del entorno y sobrescribible mediante settings:
Variable | Tipo | Predeterminado | Propósito |
| bool |
| Interruptor principal: |
| bool |
| Registro detallado / introspección |
| list |
| Identificadores de escáner habilitados |
| list |
| Patrones de ruta a incluir (vacío = todos) |
| list |
| Patrones de ruta a excluir |
| str |
| Prefijo antepuesto a los IDs de módulo generados |
| bool |
| Exigir autenticación para los endpoints MCP/A2A |
| str |
|
|
| str |
| Transporte MCP: |
| str |
| Dirección de enlace cuando el transporte no es stdio |
| int |
| Puerto de enlace cuando el transporte no es stdio |
Los pares opcionales no se reexportan
A diferencia del adaptador NestJS, hono-apcore no reexporta las superficies apcore-mcp / apcore-cli / apcore-a2a. Hacerlo haría que se cargaran de forma anticipada, y apcore-mcp incorpora node:http, lo que rompe una compilación de Workers, Deno o Bun de una aplicación que nunca usa la superficie MCP. Importa esos símbolos desde sus propios paquetes:
import { JWTAuthenticator, getCurrentIdentity } from 'apcore-mcp';
import { createCli } from 'apcore-cli';
import { A2AClient } from 'apcore-a2a';apcore-js y apcore-toolkit sí son dependencias directas, por lo que sus símbolos comunes (ACL, Config, registerSysModules, TraceContext, BaseScanner, formatModules, …) se reexportan desde hono-apcore directamente.
Ejemplos
Ejemplo | Muestra |
Aplicación completa: herramientas escritas a mano y escaneo de rutas, JWT, ACL, módulos de sistema, Docker | |
Rutas gobernadas por la ACL de apcore: |
pnpm install && pnpm build
cd examples/demo && pnpm install && pnpm devDocumentación detallada
Resumen de funciones — arquitectura y grafo de dependencias
Definición de herramientas —
defineTool,defineToolset, IDs de móduloEscáner de rutas — cómo las rutas se convierten en módulos y qué cuesta la reproducción
Integración MCP — integrado vs independiente, el puente Node
Extracción de esquemas — la cadena de adaptadores y los adaptadores personalizados
Contexto y ACL — identidad, trazabilidad y rutas gobernadas
Scripts
Comando | Descripción |
| Compilar TypeScript |
| Compilación en modo de observación |
| Ejecutar la suite de pruebas (vitest) |
| Pruebas con cobertura (umbrales del 90%) |
| Comprobación de tipos sin emitir |
| Lint de código fuente y pruebas |
Licencia
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