All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Dependency bump:
apcore >= 0.19.0(was>= 0.18.0). - New dependency:
apcore-toolkit >= 0.5.0— picks up theScannedModule.displayfield and theBindingLoaderpure-data loader (not wired in apcore-mcp; this project does not load binding YAML directly). ExecutionRouter.handle_callresponsecontentitem type widened fromlist[dict[str, str]]tolist[dict[str, Any]]to carry the optional_metafield. The factory translates this to MCPTextContent.metaon wire.MCPServerFactory.register_handlersgains optionalasync_bridgeanddescriptor_lookupkwargs. Backward-compatible: when omitted, behavior is unchanged.
- W3C Trace Context propagation —
ExecutionRouternow parses_meta.traceparenton inboundtools/callrequests and seeds the apcoreContextwith the extractedTraceParent. Responses carry_meta.traceparent(perTextContent.meta) built fromTraceContext.inject(context), letting MCP clients correlate trace chains across module boundaries. Relies on apcore 0.19's strict validation inContext.create(trace_parent=...)(all-zero/all-f trace ids are regenerated with a WARN). - Async Task Bridge (F-043) — new
apcore_mcp.server.async_task_bridge.AsyncTaskBridgewraps apcore'sAsyncTaskManager. Modules whose descriptor carriesmetadata.async == Trueorannotations.extra["mcp_async"] == "true"are routed toAsyncTaskManager.submit()and return an immediate{"task_id", "status": "pending"}envelope. Four reserved MCP meta-tools are registered:__apcore_task_submit,__apcore_task_status,__apcore_task_cancel,__apcore_task_list. Progress fan-out is available via_meta.progressToken(bound per task).MCPServerFactory.build_toolnow rejects any module whose id starts with__apcore_. Enable/disable viaAPCoreMCP(async_tasks=...)orserve(async_tasks=...)(default on). Tuning knobs:async_max_concurrent,async_max_tasks. - Observability auto-wiring —
serve(observability=True)/APCoreMCP(observability=True)instantiateapcore.observability.MetricsCollector+MetricsMiddlewareandUsageCollector+UsageMiddlewareon the Executor and expose/{explorer_prefix}/api/usage(and/api/usage/{module_id}) returningModuleUsageSummary/ModuleUsageDetailJSON. Themetrics_collector=Truesentinel auto-provisions only the metrics middleware (no usage tracking). A user-suppliedMetricsExporterobject continues to work unchanged (back-compat). --observabilityCLI flag — toggles metrics + usage middleware and usage routes.- isinstance-based error dispatch in
adapters/errors.py—TaskLimitExceededError,DependencyNotFoundError, andDependencyVersionMismatchErrorare dispatched viaisinstancechecks against the apcore 0.19 error classes, not duck-typed codes. - Expanded
ModuleAnnotationssurfacing inAnnotationMapper.to_description_suffix:cache_ttl,cache_key_fields, andpagination_stylenow appear in the description annotation block when non-default. Aligns with apcore 0.19's 12-fieldModuleAnnotations. DEFAULT_ANNOTATIONSinadapters/annotations.pyextended withcache_ttl=0,cache_key_fields=None, andpagination_style="cursor"to match apcore 0.19 defaults.- New error codes in
constants.ERROR_CODESandErrorMapper:DEPENDENCY_NOT_FOUND— raised byresolve_dependenciesfor missing required deps (replaces priorModuleLoadErrorpath per PROTOCOL_SPEC §5.15.2).DEPENDENCY_VERSION_MISMATCH— raised when a declaredversionconstraint is unsatisfied.TASK_LIMIT_EXCEEDED— raised byAsyncTaskManager.submitat capacity. Mapped withretryable: True.VERSION_CONSTRAINT_INVALID— raised on malformed version constraint strings.BINDING_SCHEMA_INFERENCE_FAILED— replaces the deprecatedBINDING_SCHEMA_MISSINGcode for auto-schema inference failures.BINDING_SCHEMA_MODE_CONFLICT,BINDING_STRICT_SCHEMA_INCOMPATIBLE,BINDING_POLICY_VIOLATION— parse-time binding validation errors per DECLARATIVE_CONFIG_SPEC.
- The
displayoverlay resolution inserver/factory.pyalready consumesmetadata["display"]["mcp"](alias / description / guidance) as produced byDisplayResolver; no changes needed for the 0.19 canonicalDisplayOverlayshape. - The apcore-toolkit
BindingLoaderwas not wired in: apcore-mcp does not load.binding.yamlfiles directly. Registry-bound loads continue to flow through apcore's ownBindingLoaderinside the upstream SDK. - Async task bridge is in-memory only; tasks do not survive server restart (matches apcore semantics).
- Meta-tool names use the reserved
__apcore_prefix; user-registered modules with this prefix are now rejected atbuild_tooltime to prevent shadowing. - Usage endpoints are only mounted when Explorer is enabled; headless stdio deployments continue to have no HTTP surface.
- Dependency bump:
mcp-embedded-ui >= 0.4.0(was>= 0.3.1). The new release shipsPOST /tools/{name}/validate(F7) — read-only schema validation, ungated byallow_executeorauth_hook. The route flows automatically throughcreate_explorer_mount. Resolves EUI-1. - JWT-1 —
Authenticator.authenticateis nowasync. Existing sync implementations continue to work via the newapcore_mcp.auth.protocol.call_authenticator(auth, headers)helper, which inspects the return value and awaits if it's a coroutine. Aligns with TS+Rust on the unified(headers: HeaderMap) -> Awaitable<Identity | None>contract. Tests forJWTAuthenticatorare nowasync def. - TM-4 — transport-disconnect cancellation forwarding.
TransportManager.set_async_task_bridge(bridge)matches TSsetAsyncTaskBridgeand Rustset_cancel_handler. The transport scopes a per-connection session id via the newtransport_session_varContextVar;factory.handle_call_toolforwards it assession_keytobridge.submit(...), and on transport teardown the manager callsbridge.cancel_session_tasks(session_id). Wired automatically byserve(),async_serve(), andAPCoreMCP.serve/async_servewhen an async bridge is present. 6 regression tests. - EB-2 — adapter-hook kwargs.
serve()andasync_serve()acceptschema_converter,annotation_mapper,error_mapperkwargs that override the factory's built-in adapters. - EM-1 —
McpErrorFormattercanonical class name. Added as the preferred PascalCase name (matches TS+Rust). The pre-existingMCPErrorFormatter(all-caps) is kept as a backwards-compatible alias. Both are exported fromapcore_mcpandapcore_mcp.adapters. - EM-3 —
userFixable=truestamp.ErrorMappernow hardcodesuserFixable: trueforDEPENDENCY_NOT_FOUND,DEPENDENCY_VERSION_MISMATCH,VERSION_CONSTRAINT_INVALID, and the fourBINDING_*codes (matches TS). apcore 0.19's error classes don't yet setuser_fixable=truethemselves, so the bridge stamps the hint to give MCP clients a consistent self-healing signal. 9 regression tests. - MID-5 —
ModuleIDNormalizer.try_denormalize. New bijection-guarded variant validates the dash→dot-replaced result againstMODULE_ID_PATTERN, returningNonefor inputs that aren't valid pre-images ofnormalize. Plaindenormalizestays lenient. 8 regression tests. - JWT-2 — case-insensitive
Authorizationheader lookup.JWTAuthenticator.authenticatenow tries bothheaders["authorization"]andheaders["Authorization"]. ASGI lower-cases header names but direct callers may pass the capitalised form; RFC 7230 §3.2 mandates case-insensitive header names. Matches TS+Rust behaviour. 1 regression test. - AM-L1 — F-041 annotation extras format aligned with TS+Rust.
mcp_*extras are now appended after the[Annotations: ...]block separated by a single newline (was each extra as its own\n\n-separated section). 1 regression test. - TC-011 integration tests added in
tests/explorer/test_explorer.py::TestTC011Validatepinning the/validatewire-up.
- Pipeline Strategy Selection (F-036) —
serve(strategy=)parameter and CLI--strategyflag with 5 presets: standard, internal, testing, performance, minimal. - Tool Output Redaction (F-038) —
serve(redact_output=True)appliesredact_sensitive()to tool output before MCP serialization. Enabled by default. - Pipeline Observability (F-037) —
serve(trace=True)enablescall_async_with_trace()for per-step pipeline timing in responses. - Tool Preflight Validation (F-039) —
ExecutionRouter.validate_tool()for dry-run validation viaExecutor.validate(). - YAML Pipeline Configuration (F-040) — Config Bus
mcp.pipelinesection for declarative pipeline customization. - Annotation Metadata Passthrough (F-041) —
ModuleAnnotations.extrakeys prefixed withmcp_flow to tool descriptions. - 4 new error mappings —
ConfigEnvMapConflictError,PipelineAbortError,StepNotFoundError,VersionIncompatibleError. - RegistryListener wired to
serve(dynamic=True)— dynamic tool registration now operational.
- Dependency bump:
apcore >= 0.17.1(was>= 0.15.1). - Pipeline v2 alignment: 11-step pipeline,
call_chain_guardrename, middleware before input validation.
- Config Bus namespace registration (F-033) — Registers
mcpnamespace with apcore Config Bus (APCORE_MCPenv prefix). MCP configuration (transport, host, port, auth, explorer) can be managed via unifiedapcore.yaml. - Error Formatter Registry integration (F-034) —
MCPErrorFormatterregistered with apcore'sErrorFormatterRegistry, formalizing MCP error formatting into the shared protocol. - Dot-namespaced event constants (F-035) —
APCORE_EVENTSdict with canonical event type names from apcore 0.15.0 (§9.16). - 6 new error code mappings —
CONFIG_NAMESPACE_DUPLICATE,CONFIG_NAMESPACE_RESERVED,CONFIG_ENV_PREFIX_CONFLICT,CONFIG_MOUNT_ERROR,CONFIG_BIND_ERROR,ERROR_FORMATTER_DUPLICATE.
- Dependency bump: requires
apcore >= 0.15.1(was>= 0.14.0) for Config Bus (§9.4), Error Formatter Registry (§8.8), and dot-namespaced event types (§9.16).
- Display overlay in
build_tool()(§5.13) — MCP tool name, description, and guidance now sourced frommetadata["display"]["mcp"]when present.- Tool name:
metadata["display"]["mcp"]["alias"](pre-sanitized byDisplayResolver, already[a-zA-Z_][a-zA-Z0-9_-]*and ≤ 64 chars). - Tool description:
metadata["display"]["mcp"]["description"], withguidanceappended as\n\nGuidance: <text>when set. - Falls back to raw
module.name/module.descriptionwhen no display overlay is present.
- Tool name:
- Dependency bump: requires
apcore-toolkit >= 0.4.0forDisplayResolver.
TestBuildToolDisplayOverlay(6 tests): MCP alias used as tool name, MCP description used, guidance appended, surface-specific override wins, fallback to scanner values when no overlay.
- Rebrand: aipartnerup → aiperceivable
0.10.0 - 2026-03-14
- BREAKING:
output_formatterdefault changed toNone:APCoreMCPno longer defaults toapcore_toolkit.to_markdown. Results are now serialized as raw JSON by default. To restore Markdown formatting, passoutput_formatter=to_markdownexplicitly (requiresapcore-toolkit). - Dependency bump: Requires
apcore>=0.13.0(was>=0.9.0). Picks up new annotation fields (cacheable,paginated,cache_ttl,cache_key_fields,pagination_style) andExecutionCancelledErrornow extendingModuleError. - Annotation description suffix:
AnnotationMapper.to_description_suffix()now includescacheableandpaginatedwhen set to non-default values.
apcore-toolkitdependency: Removed frompyproject.tomldependencies.apcore-toolkitis no longer required to useapcore-mcp. Users who want Markdown formatting can install it separately and passto_markdownas theoutput_formatter.
0.9.0 - 2026-03-06
async_serve()context manager: New public API for embedding the MCP server into a larger ASGI application. Returns aStarletteapp viaasync with async_serve(registry) as mcp_app:, enabling co-hosting with A2A, Django ASGI, or other services under a single uvicorn process.TransportManager.build_streamable_http_app(): Low-level async context manager that builds a Starlette ASGI app with MCP transport, health, and metrics routes. Supportsextra_routesandmiddlewareinjection.ExecutionCancelledErrorhandling:ErrorMappernow maps apcore'sExecutionCancelledErrorto a safeEXECUTION_CANCELLEDresponse withretryable=True. Internal cancellation details are never leaked.- New error codes:
VERSION_INCOMPATIBLE,ERROR_CODE_COLLISION, andEXECUTION_CANCELLEDadded toERROR_CODESconstants. - Deep merge for streaming: Streaming chunk accumulation uses recursive deep merge (depth-capped at 32) instead of shallow merge, correctly handling nested response structures.
- Dependency bump: Requires
apcore>=0.9.0(was>=0.7.0). Picks upPreflightResult, execution pipeline, retry middleware, error code registry, and more. - Preflight validation aligned with apcore 0.9.0:
ExecutionRouternow passes the router-builtContext(with identity, callbacks) toExecutor.validate(), enabling accurate ACL and call-chain preflight checks. Error formatting handles all threePreflightResulterror shapes: nested schema errors, flat field errors, and code-only errors. - Annotation description suffix:
AnnotationMapper.to_description_suffix()now produces safety warnings (WARNING: DESTRUCTIVE,REQUIRES APPROVAL) as a separate section above the machine-readable annotation block, improving AI agent awareness of dangerous operations. - Auth middleware best-effort identity on exempt paths:
AuthMiddlewarenow attempts identity extraction on exempt paths. Valid tokens populateauth_identity_vareven when auth is not required, allowing downstream handlers to use identity when available.
0.8.0 - 2026-03-02
- Approval system (F-028): Full runtime approval support via
ElicitationApprovalHandlerthat bridges MCP elicitation to apcore's approval system. Newapproval_handlerparameter onserve(). Supportsrequest_approval()andcheck_approval()methods.ElicitationApprovalHandler: Presents approval requests to users via MCP elicitation. Maps elicit actions (accept/decline/cancel) toApprovalResultstatuses.- CLI
--approvalflag with choices:elicit,auto-approve,always-deny,off(default).
- Approval error codes:
APPROVAL_DENIED,APPROVAL_TIMEOUT,APPROVAL_PENDINGadded toERROR_CODES. - Enhanced error responses with AI guidance:
ErrorMappernow extractsretryable,ai_guidance,user_fixable, andsuggestionfields from apcoreModuleErrorand includes non-None values in error response dicts.ExecutionRouterappends AI guidance as structured JSON to error text content for AI agent consumption. - AI intent metadata in tool descriptions:
MCPServerFactory.build_tool()readsdescriptor.metadatafor AI intent keys (x-when-to-use,x-when-not-to-use,x-common-mistakes,x-workflow-hints) and appends them to tool descriptions for agent visibility. - Streaming annotation:
DEFAULT_ANNOTATIONSnow includesstreamingfield.AnnotationMapper.to_description_suffix()includesstreaming=truewhen the annotation is set.
APPROVAL_TIMEOUTauto-retryable:ErrorMappersetsretryable=TrueforAPPROVAL_TIMEOUTerrors, signaling to AI agents that the operation can be retried.APPROVAL_PENDINGincludesapproval_id:ErrorMapperextractsapproval_idfrom error details forAPPROVAL_PENDINGerrors.- Error text content enriched: Router error text now includes AI guidance fields as a structured JSON appendix when present, enabling AI agents to parse retry/fix hints.
0.7.0 - 2026-02-28
- JWT Authentication (F-027): Optional JWT-based authentication for HTTP transports (
streamable-http,sse). Newauthenticatorparameter onserve()andMCPServer. Validates Bearer tokens, maps JWT claims to apcoreIdentity, and injects identity intoContextfor ACL enforcement.JWTAuthenticator: Configurable JWT validation withClaimMappingfor flexible claim-to-Identity field mapping. Supports custom algorithms, audience, issuer, and required claims.AuthMiddleware: ASGI middleware that bridges HTTP authentication to MCP handlers viaContextVar[Identity]. Supportsexempt_paths(exact match) andexempt_prefixes(prefix match) for unauthenticated endpoints.AuthenticatorProtocol:@runtime_checkableprotocol for custom authentication backends.
- Permissive auth mode:
require_auth=Falseparameter onserve()andMCPServerallows unauthenticated requests to proceed without identity instead of returning 401. exempt_pathsparameter:serve()andMCPServeracceptexempt_pathsfor exact-path authentication bypass (e.g.{"/health", "/metrics"}).- CLI JWT flags:
--jwt-secret,--jwt-algorithm,--jwt-audience,--jwt-issuerarguments for enabling JWT authentication from the command line. - CLI
--jwt-key-file: Read JWT verification key from a PEM file (e.g. RS256 public key). Takes priority over--jwt-secretandAPCORE_JWT_SECRETenv var. - CLI
--jwt-require-auth/--no-jwt-require-auth: Toggle permissive auth mode from the command line. - CLI
--exempt-paths: Comma-separated list of paths exempt from authentication. APCORE_JWT_SECRETenv var fallback: CLI resolves JWT key in priority order:--jwt-key-file>--jwt-secret>APCORE_JWT_SECRETenvironment variable.- Explorer Authorization UI: Swagger-UI-style Authorization input field in the Tool Explorer. Paste a Bearer token to authenticate tool execution requests. Generated cURL commands automatically include the Authorization header.
- Explorer auth enforcement: When
authenticatoris set, tool execution via the Explorer returns 401 Unauthorized without a valid Bearer token. The Explorer UI displays a clear error message prompting the user to enter a token. - Auth failure audit logging:
AuthMiddlewareemits aWARNINGlog with the request path on authentication failure. extract_headers()utility: Public helper to extract ASGI scope headers as a lowercase-key dict. Exported fromapcore_mcp.auth.- JWT authentication example:
examples/run.pysupportsAPCORE_JWT_SECRETenvironment variable to demonstrate JWT authentication with a sample token. - PyJWT dependency: Added
PyJWT>=2.0to project dependencies.
- Explorer UI layout: Redesigned from a bottom-panel layout to a Swagger-UI-style inline accordion. Each tool expands its detail, schema, and "Try it" section directly below the tool name. Only one tool can be expanded at a time. Detail is loaded once on first expand and cached.
- AuthMiddleware
exempt_prefixes: Addedexempt_prefixesparameter for prefix-based path exemption. Explorer paths are automatically exempt when bothexplorerandauthenticatorare enabled, so the Explorer UI always loads. extract_headersrefactored: Moved from privateAuthMiddleware._extract_headers()to module-levelextract_headers()function for reuse in Explorer routes.
0.6.0 - 2026-02-25
- Example modules:
examples/with 5 runnable demo modules — 3 class-based (text_echo,math_calc,greeting) and 2 binding.yaml (convert_temperature,word_count) — for quick Explorer UI demo out of the box.
- BREAKING:
ExecutionRouter.handle_call()return type: Changed from(content, is_error)to(content, is_error, trace_id). Callers that unpack the 2-tuple must update to 3-tuple unpacking. - BREAKING: Explorer
/callresponse format: Changed from{"result": ...}/{"error": ...}to MCP-compliantCallToolResultformat:{"content": [...], "isError": bool, "_meta": {"_trace_id": ...}}.
- MCP protocol compliance: Router no longer injects
_trace_idas a content block in tool results.trace_idis now returned as a separate tuple element and surfaced in Explorer responses via_meta. Factory handler raises exceptions for errors so the MCP SDK correctly setsisError=True. - Explorer UI default values:
defaultFromSchema()now correctly skipsnulldefaults and falls through to type-based placeholders, fixing blank form fields for binding.yaml modules.
0.5.1 - 2026-02-25
- Rename Inspector to Explorer: Renamed the MCP Tool Inspector module to MCP Tool Explorer across the entire codebase — module path (
apcore_mcp.inspector→apcore_mcp.explorer), CLI flags, Python API parameters, HTML UI, tests, README, and CHANGELOG. No functional changes; all endpoints and behavior remain identical.
- Version test: Fixed
test_run_uses_package_version_when_version_is_noneto patchimportlib.metadata.versionso the test is not sensitive to the installed package version.
0.5.0 - 2026-02-24
- MCP Tool Explorer (F-026): Optional browser-based UI for inspecting and testing MCP tools, mounted at
/explorerwhenexplorer=True. Includes 4 HTTP endpoints (GET /explorer/,GET /explorer/tools,GET /explorer/tools/<name>,POST /explorer/tools/<name>/call), a self-contained HTML/CSS/JS page with no external dependencies, configurableexplorer_prefix, andallow_executeguard (defaultFalse). HTTP transports only; silently ignored for stdio. - CLI Explorer flags:
--explorer,--explorer-prefix, and--allow-executearguments. - Explorer UI: proactive execution status detection: The Explorer probes execution status on page load via a lightweight POST to
/tools/__probe__/call, so the "Tool execution is disabled" message appears immediately instead of requiring a user click first. - Explorer UI: URL-safe tool name encoding: Tool names in fetch URLs are wrapped with
encodeURIComponent()to prevent malformed URLs when tool names contain special characters. - Explorer UI: error handling on tool detail fetch:
.catch()handler on theloadDetailfetch chain displays network errors in the detail panel instead of silently swallowing them.
0.4.0 - 2026-02-23
- Resource handlers:
MCPServerFactory.register_resource_handlers()for serving documentation resources via MCP. - CI workflow: GitHub Actions CI pipeline and
CODEOWNERSfile. - Missing error codes: Added
MODULE_EXECUTE_ERRORandGENERAL_INVALID_INPUTto error codes constants. - serve() parameter tests: Comprehensive test suite for
serve()parameter validation. - Metrics endpoint tests: Dedicated test suite for Prometheus
/metricsendpoint.
- Version management: Consolidated version into
__init__.__version__, removed_version.py.
- Cache configuration: Removed unnecessary cache configuration from Python setup step.
- Code formatting: Improved linting checks in CI workflow, factory, router, and test files.
- Import cleanup: Removed unused imports across multiple test files; reordered imports in MCPServer for consistency.
- Code structure: General readability and maintainability improvements.
0.3.0 - 2026-02-22
- metrics_collector parameter:
serve(metrics_collector=...)accepts aMetricsCollectorinstance to enable Prometheus metrics export. /metricsPrometheus endpoint: HTTP-based transports (streamable-http,sse) now serve a/metricsroute returning Prometheus text format when ametrics_collectoris provided. Returns 404 when no collector is configured.- trace_id passback: Every successful response now includes a second content item with
_trace_idmetadata for request tracing. (Removed in 0.5.1: trace_id moved out of content blocks into separate return value for MCP protocol compliance.) - validate_inputs:
serve(validate_inputs=True)enables pre-execution input validation viaExecutor.validate(). Invalid inputs are rejected before module execution. - Always-on Context:
Contextis now always created for every tool call, enabling trace_id generation even without MCP callbacks.
- SchemaExporter integration:
MCPServerFactory.build_tool()now usesapcore.schema.exporter.SchemaExporter.export_mcp()for canonical MCP annotation mapping instead of duplicating logic. - to_strict_schema() delegation:
OpenAIConverter._apply_strict_mode()now delegates toapcore.schema.strict.to_strict_schema()instead of custom recursive implementation. This adds x-* extension stripping, oneOf/anyOf/allOf recursion, $defs recursion, and alphabetically sorted required lists. - Dependency bump: Requires
apcore>=0.5.0(was>=0.2.0).
- Custom strict mode: Removed
OpenAIConverter._apply_strict_recursive()in favor ofto_strict_schema().
0.2.0 - 2026-02-20
- MCPServer: Non-blocking MCP server wrapper for framework integrations with configurable transport and async event loop management.
- serve() hooks:
on_startupandon_shutdowncallbacks for lifecycle management. - Health endpoint: Built-in health check support for HTTP-based transports.
- Constants module: Centralized
REGISTRY_EVENTS,ErrorCodes, andMODULE_ID_PATTERNfor consistent values across adapters and listeners. - Module ID validation: Enhanced
id_normalizer.normalize()with format validation usingMODULE_ID_PATTERN. - Exported building blocks: Public API exports for
MCPServerFactory,ExecutionRouter,RegistryListener, andTransportManager.
- MCP Tool metadata: Fixed use of
_metainstead ofmetain MCP Tool constructor for proper internal metadata handling.
- Circular import resolution: Moved utility functions (
resolve_registry,resolve_executor) to dedicated_utils.pymodule to prevent circular dependencies between__init__.pyandserver/server.py.
0.1.0 - 2026-02-15
- Public API:
serve()to launch an MCP Server from any apcore Registry or Executor. - Public API:
to_openai_tools()to export apcore modules as OpenAI-compatible tool definitions. - CLI:
apcore-mcpcommand with--extensions-dir,--transport,--host,--port,--name,--version, and--log-leveloptions. - Three transports: stdio (default), Streamable HTTP, and SSE.
- SchemaConverter: JSON Schema conversion with
$ref/$defsinlining for MCP and OpenAI compatibility. - AnnotationMapper: Maps apcore annotations (readonly, destructive, idempotent, open_world) to MCP
ToolAnnotations. - ErrorMapper: Sanitizes apcore errors for safe client exposure — no stack traces, no internal details leaked.
- ModuleIDNormalizer: Bijective dot-to-dash conversion for OpenAI function name compatibility.
- OpenAIConverter: Full registry-to-OpenAI conversion with
strictmode (Structured Outputs) andembed_annotationssupport. - MCPServerFactory: Creates MCP Server instances, builds Tool objects, and registers
list_tools/call_toolhandlers. - ExecutionRouter: Routes MCP tool calls to apcore Executor with error sanitization.
- TransportManager: Manages stdio, Streamable HTTP, and SSE transport lifecycle.
- RegistryListener: Thread-safe dynamic tool registration via
registry.on("register"/"unregister")callbacks. - Structured logging: All components use
logging.getLogger(__name__)under theapcore_mcpnamespace. - Dual input: Both
serve()andto_openai_tools()accept either a Registry or Executor instance. - Filtering:
tagsandprefixparameters for selective module exposure. - 260 tests: Unit, integration, E2E, performance, and security test suites.