Skip to main content
Glama

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, IDapcore() 미들웨어는 W3C 추적 전파를 포함한 요청별 apcore Context를 구축하므로 ACL 규칙이 라우트에도 적용됩니다.

  • 런타임 비종속 코어apcore-mcp, apcore-cli, apcore-a2a는 지연 로드되는 선택적 피어이므로 hono-apcore를 가져와도 엣지 빌드에 node:http가 포함되지 않습니다.

  • CLIhono-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 });

이제 앱이 다음을 응답합니다:

  • RESThttp://localhost:3000/todos

  • MCPhttp://localhost:3000/mcp

  • Tool Explorerhttp://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),
});

필드

설명

id

그대로 사용됩니다. 그 외에는 "<namespace>.<name>"이며 name은 snake_case로 변환됩니다.

inputSchema / outputSchema

TypeBox, Zod 또는 일반 JSON Schema

annotations

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

params

입력 스키마에 병합되는 매개변수별 설명입니다. JavaScript는 Python이 docstring을 읽는 것처럼 런타임에 함수의 선행 주석을 읽을 수 없으므로 명시적으로 제공합니다.

handler

(inputs, context) => result. 객체가 아닌 결과는 { result }로 감쌉니다.

라우트 스캐닝 — 무침입 도구

스캐너를 앱에 지정하면 모든 라우트가 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

추론된 어노테이션

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

생성된 입력 스키마는 경로 매개변수마다 필수 문자열 속성 하나를 가지며, 추가로 자유 형식의 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
})

메서드

설명

init(app?, routeOptions?)

도구와 바인딩을 발견하고 등록하고, 라우트를 스캔하고, 독립형 표면을 시작합니다. 멱등적입니다.

ready()

진행 중인 init()을 기다립니다.

registerTool(tool) / registerTools(tools)

런타임에 도구 정의를 등록합니다.

registerMethod(opts) / registerObject(opts)

일반 서비스 객체의 메서드를 등록합니다.

scanRoutes(app, opts?)

앱의 라우트를 스캔하고 등록합니다.

routeOptions

이 인스턴스가 사용할 병합된 라우트 스캔 옵션입니다.

loadBindings(path?, resolver?)

YAML 바인딩 파일을 로드합니다.

mountMcp(app, opts?)

/mcp, Explorer, /health를 앱에 마운트합니다.

toOpenaiTools(opts?)

OpenAI 호환 함수 정의를 반환합니다.

close()

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-idAuthorization: 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-serverc.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 옵션:

필드

타입

설명

transport

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

독립형 전송. 설정하면 init()이 서버를 시작합니다.

host / port

string / number

HTTP 전송의 바인드 주소

name / version

string

서버 ID

explorer / explorerPrefix / allowExecute

Tool Explorer 웹 UI

authenticator / requireAuth / exemptPaths

JWT 또는 사용자 정의 인증

tags / prefix

일치하는 모듈만 노출

validateInputs

boolean

모든 호출에서 입력 스키마를 강제 적용

observability

메트릭 + 사용량 미들웨어 및 해당 엔드포인트

outputFormat / outputFormatter / redactOutput / trace

결과 직렬화

approvalHandler / approvalStore / approvalNotify

파괴적 도구에 대한 승인 게이트

mcpMiddleware / mcpAcl

MCP 실행기를 위한 추가 apcore 미들웨어 / ACL

스키마 어댑터

스키마는 우선순위 체인을 통해 자동 감지 및 변환됩니다:

어댑터

우선순위

입력

TypeBoxAdapter

100

@sinclair/typebox 스키마

ZodAdapter

50

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

JsonSchemaAdapter

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: false
import { 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

APCORE_ENABLED

bool

true

마스터 스위치 — false이면 init()이 아무 작업도 수행하지 않음

APCORE_DEBUG

bool

false

상세 로깅 / 인트로스펙션

APCORE_SCANNERS

list

["auto"]

활성화된 스캐너 식별자

APCORE_INCLUDE_PATHS

list

[]

포함할 라우트 패턴 (비어 있음 = 전체)

APCORE_EXCLUDE_PATHS

list

[]

제외할 라우트 패턴

APCORE_MODULE_PREFIX

str

""

생성된 모듈 ID 앞에 추가되는 접두사

APCORE_AUTH_ENABLED

bool

false

MCP/A2A 엔드포인트에 인증 요구

APCORE_AUTH_STRATEGY

str

"bearer"

bearer / session / custom

APCORE_TRANSPORT

str

"stdio"

MCP 전송: stdio / http / sse

APCORE_HOST

str

"0.0.0.0"

전송 방식이 stdio가 아닐 때 바인딩 주소

APCORE_PORT

int

8808

전송 방식이 stdio가 아닐 때 바인딩 포트

선택적 피어는 재-export되지 않음

NestJS 어댑터와 달리 hono-apcoreapcore-mcp / apcore-cli / apcore-a2a 표면을 재-export하지 않습니다. 그렇게 하면 이들이 즉시 로드되며, apcore-mcpnode:http를 끌어들이기 때문에 MCP 표면을 사용하지 않는 앱의 Workers, Deno 또는 Bun 빌드가 깨집니다. 해당 심볼은 각자의 패키지에서 가져오세요:

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

apcore-jsapcore-toolkit하드 의존성이므로, 이들의 공통 심볼(ACL, Config, registerSysModules, TraceContext, BaseScanner, formatModules, …)은 hono-apcore에서 직접 재-export됩니다.

예제

Example

Shows

examples/demo

전체 앱: 수작업 도구 라우트 스캐닝, JWT, ACL, 시스템 모듈, Docker

examples/acl_demo

apcore ACL이 관리하는 라우트 — 관리자 전용 orders.delete

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

상세 문서

스크립트

Command

Description

pnpm build

TypeScript 컴파일

pnpm dev

감시 모드 컴파일

pnpm test

테스트 스위트 실행 (vitest)

pnpm test:coverage

커버리지 포함 테스트 (90% 임계값)

pnpm typecheck

출력 없이 타입 검사

pnpm lint

소스 및 테스트 린트

라이선스

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