hono-apcore
hono-apcore
Hono 어댑터 — apcore AI-Perceivable 모듈 생태계용. Hono 앱을 MCP 도구 및 OpenAI 호환 함수 정의로 변환합니다 — 도구를 명시적으로 선언하거나 이미 있는 라우트를 스캔하여.
기능
두 가지 진입점 —
defineTool()/defineToolset()로 도구를 선언하거나, 코드 변경 없이 기존 라우트를 스캔합니다.라우트 재생 — 스캔된 라우트는
app.request()를 통해 다시 호출되는 모듈이 되므로, 미들웨어, 검증기, 오류 처리기가 모두 그대로 실행됩니다.단일 포트 —
mountMcp()는 MCP 엔드포인트, Tool Explorer,/health를 동일한 Hono 앱에서 제공합니다.어노테이션 추론 —
GET→ readonly + cacheable,PUT→ idempotent,DELETE→ destructive (RFC 9110 안전 메서드 의미론)다중 스키마 — TypeBox, Zod 3, Zod 4, 일반 JSON Schema를 우선순위 체인으로 자동 감지합니다.
컨텍스트, ACL, ID —
apcore()미들웨어는 W3C 추적 전파를 포함한 요청별 apcoreContext를 구축하므로 ACL 규칙이 라우트에도 적용됩니다.런타임 비종속 코어 —
apcore-mcp,apcore-cli,apcore-a2a는 지연 로드되는 선택적 피어이므로hono-apcore를 가져와도 엣지 빌드에node:http가 포함되지 않습니다.CLI —
hono-apcore scan | serve | export는 일반 Hono 앱에서 작동합니다.YAML 바인딩 — 소스를 건드리지 않고 모듈을 선언적으로 등록합니다.
Related MCP server: hono-mcp-server
설치
npm install hono-apcore hono선택적 피어는 사용하는 표면에 대해서만 설치됩니다:
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요구 사항: Node.js >= 18, Hono >= 4 (Hono 4.13에서 테스트됨).
빠른 시작
1. 도구 선언
// 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. 앱에 연결
// 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. 부팅
// 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 });이제 앱이 다음을 응답합니다:
REST —
http://localhost:3000/todosMCP —
http://localhost:3000/mcpTool Explorer —
http://localhost:3000/explorer/
기능을 노출하는 두 가지 방법
defineTool() — 명시적 도구
NestJS의 @ApTool 데코레이터에 해당하는 Hono 버전입니다. Hono에는 데코레이팅할 클래스나 DI 컨테이너가 없으므로, 도구는 자체 메타데이터와 핸들러를 담은 일반 객체입니다.
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),
});필드 | 설명 |
| 그대로 사용됩니다. 그 외에는 |
| TypeBox, Zod 또는 일반 JSON Schema |
|
|
| 입력 스키마에 병합되는 매개변수별 설명입니다. JavaScript는 Python이 docstring을 읽는 것처럼 런타임에 함수의 선행 주석을 읽을 수 없으므로 명시적으로 제공합니다. |
|
|
라우트 스캐닝 — 무침입 도구
스캐너를 앱에 지정하면 모든 라우트가 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, …모듈 ID는 경로와 HTTP 동사에서 비롯됩니다:
라우트 | 모듈 ID | 추론된 어노테이션 |
|
|
|
|
|
|
|
| — |
|
|
|
|
|
|
생성된 입력 스키마는 경로 매개변수마다 필수 문자열 속성 하나를 가지며, 추가로 자유 형식의 query 객체(GET/DELETE) 또는 body 객체(POST/PUT/PATCH)를 포함합니다. 라우트별로 그 중 무엇이든 재정의할 수 있습니다:
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 },
},
}실행이 app.request()를 통해 다시 이루어지므로, AI 호출은 HTTP 호출과 동일한 코드 경로를 실행합니다 — 인증 미들웨어, 검증기, 오류 처리기까지 모두 포함됩니다. apcore Context의 ID와 W3C 추적 헤더는 재생된 요청에 전달됩니다.
API 참조
createApcore(options)
HonoApcore를 반환합니다 — Registry, Executor, 그리고 모든 표면이 여기에 연결됩니다.
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
})메서드 | 설명 |
| 도구와 바인딩을 발견하고 등록하고, 라우트를 스캔하고, 독립형 표면을 시작합니다. 멱등적입니다. |
| 진행 중인 |
| 런타임에 도구 정의를 등록합니다. |
| 일반 서비스 객체의 메서드를 등록합니다. |
| 앱의 라우트를 스캔하고 등록합니다. |
| 이 인스턴스가 사용할 병합된 라우트 스캔 옵션입니다. |
| YAML 바인딩 파일을 로드합니다. |
|
|
| OpenAI 호환 함수 정의를 반환합니다. |
| MCP 및 A2A 표면을 종료합니다. |
apcore(instance | options, middlewareOptions?)
인스턴스와 요청별 apcore Context를 Hono 컨텍스트에 넣는 Hono 미들웨어입니다.
app.use('*', apcore(ap));
app.get('/orders', async (c) =>
c.json(await getApcore(c).executor.call('orders.list', {}, getApcoreContext(c))),
);변수 맵이 확장되므로 c.get('apcore')와 c.get('apcoreContext')도 타입이 지정됩니다. 모듈을 호출하지 않는 라우트에는 { skipContext: true }를 전달하거나, 실제 인증을 연결하려면 { contextFactory }를 전달하세요.
HonoContextFactory
Hono 컨텍스트, Request 또는 단순 Headers에서 apcore Context를 구축합니다.
ID 해석 순서: x-user-id → Authorization: Bearer … (ID "bearer") → 단순 x-roles 헤더 (데모용 단축키) → 익명. traceparent 헤더는 추적 ID를 제공하고, x-correlation-id (또는 x-request-id)는 context.data에 저장됩니다.
new HonoContextFactory({
resolveIdentity: (headers) => identityFromSession(headers), // wins over the above
data: (headers) => ({ tenant: headers.get('x-tenant') }),
});MCP
ApcoreMcpService는 MCP 서버를 두 가지 방식으로 실행합니다.
임베디드 — 단일 프로세스, 단일 포트:
await ap.mountMcp(app, { endpoint: '/mcp', explorer: true, allowExecute: true });이 방식은 @hono/node-server가 c.env에 노출하는 원시 Node 요청 및 응답 객체가 필요하므로 Node 전용입니다. 다른 런타임에 마운트된 핸들러는 해당 설명과 함께 501을 응답합니다. endpoint는 HTTP 서버가 보는 경로여야 합니다 — 앱이 basePath 아래에 있으면 접두사를 포함하세요.
독립형 — 별도 포트 또는 CLI로 시작된 서버의 stdio:
createApcore({ mcp: { transport: 'streamable-http', host: '0.0.0.0', port: 8000 } });
// init() starts it, because `transport` was set explicitly주요 MCP 옵션:
필드 | 타입 | 설명 |
|
| 독립형 전송. 설정하면 |
|
| HTTP 전송의 바인드 주소 |
|
| 서버 ID |
| Tool Explorer 웹 UI | |
| JWT 또는 사용자 정의 인증 | |
| 일치하는 모듈만 노출 | |
|
| 모든 호출에서 입력 스키마를 강제 적용 |
| 메트릭 + 사용량 미들웨어 및 해당 엔드포인트 | |
| 결과 직렬화 | |
| 파괴적 도구에 대한 승인 게이트 | |
| MCP 실행기를 위한 추가 apcore 미들웨어 / ACL |
스키마 어댑터
스키마는 우선순위 체인을 통해 자동 감지 및 변환됩니다:
어댑터 | 우선순위 | 입력 |
| 100 |
|
| 50 | Zod 3 ( |
| 30 | 일반 JSON Schema 객체 |
감지는 구조적입니다 — TypeBox나 Zod는 런타임에 가져오지 않으므로, 호스트 앱이 무엇을 설치하든(또는 아무것도 설치하지 않든) 문제없습니다. SchemaExtractor.registerAdapter()로 자신만의 어댑터를 등록하세요.
YAML 바인딩
소스를 건드리지 않고 모듈을 등록합니다:
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 }));반대로 writeBindingsFile()은 스캔된 모듈을 다시 직렬화합니다 — 이것이 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엔트리는 path[:export]입니다. export는 기본적으로 default, 그다음 app입니다. 모듈이 어떤 이름으로든 HonoApcore를 내보내면 해당 구성 — 라우트 필터, 모듈 접두사, MCP 옵션 — 이 존중되므로 scan은 앱 자체가 등록하는 모듈을 정확히 보고합니다. CLI 플래그가 이를 재정의합니다. 인스턴스가 없는 엔트리도 작동하므로 serve는 apcore를 전혀 모르는 앱에서도 실행됩니다. TypeScript 엔트리에는 로더가 필요합니다:
npx tsx node_modules/.bin/hono-apcore scan ./src/app.ts구성 (APCORE_*)
모든 apcore 통합이 구현하는 표준 설정으로, 환경에서 읽고 settings를 통해 재정의할 수 있습니다:
Variable | Type | Default | Purpose |
| bool |
| 마스터 스위치 — |
| bool |
| 상세 로깅 / 인트로스펙션 |
| list |
| 활성화된 스캐너 식별자 |
| list |
| 포함할 라우트 패턴 (비어 있음 = 전체) |
| list |
| 제외할 라우트 패턴 |
| str |
| 생성된 모듈 ID 앞에 추가되는 접두사 |
| bool |
| MCP/A2A 엔드포인트에 인증 요구 |
| str |
|
|
| str |
| MCP 전송: |
| str |
| 전송 방식이 stdio가 아닐 때 바인딩 주소 |
| int |
| 전송 방식이 stdio가 아닐 때 바인딩 포트 |
선택적 피어는 재-export되지 않음
NestJS 어댑터와 달리 hono-apcore는 apcore-mcp / apcore-cli / apcore-a2a 표면을 재-export하지 않습니다. 그렇게 하면 이들이 즉시 로드되며, apcore-mcp가 node:http를 끌어들이기 때문에 MCP 표면을 사용하지 않는 앱의 Workers, Deno 또는 Bun 빌드가 깨집니다. 해당 심볼은 각자의 패키지에서 가져오세요:
import { JWTAuthenticator, getCurrentIdentity } from 'apcore-mcp';
import { createCli } from 'apcore-cli';
import { A2AClient } from 'apcore-a2a';apcore-js와 apcore-toolkit은 하드 의존성이므로, 이들의 공통 심볼(ACL, Config, registerSysModules, TraceContext, BaseScanner, formatModules, …)은 hono-apcore에서 직접 재-export됩니다.
예제
Example | Shows |
전체 앱: 수작업 도구 및 라우트 스캐닝, JWT, ACL, 시스템 모듈, Docker | |
apcore ACL이 관리하는 라우트 — 관리자 전용 |
pnpm install && pnpm build
cd examples/demo && pnpm install && pnpm dev상세 문서
기능 개요 — 아키텍처 및 의존성 그래프
도구 정의 —
defineTool,defineToolset, 모듈 ID라우트 스캐너 — 라우트가 모듈이 되는 방식과 재생 비용
MCP 통합 — 임베디드 vs 독립형, Node 브리지
스키마 추출 — 어댑터 체인 및 사용자 정의 어댑터
컨텍스트 및 ACL — ID, 추적, 라우트 관리
스크립트
Command | Description |
| TypeScript 컴파일 |
| 감시 모드 컴파일 |
| 테스트 스위트 실행 (vitest) |
| 커버리지 포함 테스트 (90% 임계값) |
| 출력 없이 타입 검사 |
| 소스 및 테스트 린트 |
라이선스
Apache-2.0
This server cannot be deployed
Maintenance
Related MCP Connectors
The OpenRouter for tools. One MCP connection gives any AI agent 254 hosted tools, pay per call.
Build, validate, deploy — HTTP APIs, cron jobs, webhooks and MCP tools — from your AI client.
Give any MCP-compatible AI assistant a builder for live, hosted web tools and workflows.
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
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.34 npm86MIT
- AlicenseNot gradedqualityCmaintenanceEasily expose your Hono API endpoints as MCP tools with minimal configuration, supporting type-safe input handling and tool registration.34 npm2MIT
- AlicenseNot gradedqualityDmaintenanceExposes OpenAPI endpoints as MCP tools, enabling LLMs to discover and interact with REST APIs through the MCP protocol.9 npmMIT
- AlicenseNot gradedqualityCmaintenanceExposes FastAPI routes as MCP tools with auto-discovery, Pydantic schema extraction, and built-in observability.Apache 2.0