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: Graft
설치
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 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