Your C++ code, callable by any LLM — no Python rewrite required.
Register a native function in one line. Get a type-safe JSON schema, a concurrent tool runtime, and a full MCP server for free. Works with Claude, any MCP-capable host, or your own agent loop.
llm_invoke_cpp is a header-only C++ toolkit for turning native C and C++ capabilities into LLM-callable tools.
The project is aimed at one concrete problem: you already have useful native code, and you want to expose it to an LLM or agent runtime without rewriting the implementation in Python or JavaScript.
Status: pre-release / alpha. The core stack is functional and tested, but some public APIs and docs may still change before Phase 1 is complete.
This is the smallest end-to-end path: register one native function, invoke it with JSON, and export the schema the host can inspect.
#include <iostream>
#include <json_invoke/json_invoke.hpp>
int main()
{
json_invoke::JsonInvokeAdapterThreadSafe tools;
tools.registerFunction("add", [](int x, int y) { return x + y; });
int result = tools.invoke({
{"name", "add"},
{"args", {2, 3}},
});
std::cout << result << "\n\n";
std::cout << tools.getToolSchemaJson("add").dump(2) << std::endl;
}Output excerpt:
5
{
"function": {
"name": "add",
"parameters": {
"type": "object",
"properties": {
"arg0": {
"type": "integer"
},
"arg1": {
"type": "integer"
}
},
"required": [
"arg0",
"arg1"
]
},
...,
"x-return": {
"schema": {
"type": "integer"
}
}
},
"type": "function"
}
That is the core value of this project: keep the implementation in native C++, but expose it as a tool an LLM host can call and inspect.
It covers the full path from local function registration to real protocol-facing MCP servers:
- register native functions and methods
- export tool metadata and JSON schema
- support stateless and stateful object workflows
- schedule concurrent tool execution safely
- expose the same native tool runtime through MCP stdio or MCP over HTTP
Use this project when you want a native tool runtime, not just a schema generator.
- If you need to expose existing C or C++ logic to an MCP-capable LLM host, this project gives you both the runtime and the protocol adapters.
- If you need stateful tools such as
create -> method -> destroyflows, this project already models session-scoped handles, metadata overlays, and scheduling. - If you need replaceable transports, the stack stays layered: registration and invocation live below the MCP adapters.
The project is most compelling for local agents, desktop apps, native SDKs, legacy-system integration, and performance-sensitive tool execution.
Most users only need one of these entry points:
include/json_invoke: expose stateless functions as JSON-callable tools.include/json_session_invoke: add session-scoped stateful object lifecycles.include/mcp: expose the same runtime to real MCP clients over stdio or HTTP.
The public modules are intentionally layered so you can stop at the lowest level that matches your needs:
include/func_registry: dependency-free native function registration and local dispatch.include/tool_meta: optional tool-facing metadata and tool spec export on top of the registry.include/type_meta: optional enum/schema/type-introspection helpers used by richer tool export.include/json_invoke: stateless JSON invocation and schema export.include/json_session_invoke: session-oriented and stateful tool APIs.include/task_scheduler: request classification and concurrency control.include/tool_runtime: protocol-neutral runtime facade for normalized tool listing and unary invocation.include/mcp: MCP-specific transport adapters.
Raw markdown box diagram:
+---------------------------+
| include/mcp |
| MCP stdio / HTTP adapters |
+---------------------------+
|
v
+-------------------------------+
| include/tool_runtime |
| normalized tool runtime facade|
+-------------------------------+
|
v
+-----------------------------------+
| include/task_scheduler |
| request classification / scheduling|
+-----------------------------------+
|
v
+-----------------------------------+
| include/json_session_invoke |
| session + stateful tool runtime |
+-----------------------------------+
|
v
+-----------------------------------+ +---------------------------+
| include/json_invoke |<------>| include/tool_meta |
| stateless JSON invocation | | tool-facing metadata |
+-----------------------------------+ +---------------------------+
| ^
v |
+-----------------------------------+ +---------------------------+
| include/func_registry |<------>| include/type_meta |
| native registration + dispatch | | enum / schema / type meta |
+-----------------------------------+ +---------------------------+
Each layer has a corresponding tutorial example:
- Start with
examples/func_registryto learn basic function registration and local dispatch. - Progress to
examples/json_invokefor JSON-based stateless tool invocation. - Move to
examples/json_statefulto understand session-scoped object lifecycles and handles. - Study
examples/json_tracingto observe function call events and diagnostic instrumentation. - Explore
examples/task_schedulerto see how concurrent requests serialize by object and scheduling category. - Finally, run
examples/mcp_filesystemto see the full runtime exposed through MCP protocol for real LLM integration.
Each public component under include/ has its own focused README:
func_registry:include/func_registry/README.mdtool_meta:include/tool_meta/README.mdtype_meta:include/type_meta/README.mdjson_invoke:include/json_invoke/README.mdjson_session_invoke:include/json_session_invoke/README.mdtask_scheduler:include/task_scheduler/README.mdtool_runtime:include/tool_runtime/README.mdmcp:include/mcp/README.mdtools:include/tools/README.mdruntimelegacy note:include/runtime/README.md
Use those component guides for per-module responsibilities, public headers, and “when to use this layer” guidance.
The five core teaching examples all use a unified filesystem domain (read, write, list, search, edit files):
examples/func_registry: Function registration and pointer-based dispatch patterns. Shows how to register plain functions, lambdas, and method pointers with full type signatures.examples/json_invoke: Stateless JSON-based tool invocation. Demonstrates JSON request/response payloads for read-only and mutating operations.examples/json_stateful: Session-scoped stateful object lifecycle. Modelscreate → method → destroyworkflows using in-memory text file editor semantics.examples/json_tracing: Invocation tracing and diagnostic observation. Captures function call events (classification, start, finish) for debugging and observability.examples/task_scheduler: Concurrent execution with scheduling and request classification. Shows how operations on the same object serialize while independent objects run in parallel.
Additional demos and docs:
examples/mcp_filesystem: Standalone MCP stdio server. Exposes the same filesystem tools through the Model Context Protocol for LLM integration.examples/mcp_http: Framework-agnostic MCP-over-HTTP demo and client (optional; requirescpp-httplib).SCHEMA_TRAITS.md: Guide for writingschema_traits<T>specializations to export custom types.ROADMAP.md: Current roadmap and hardening priorities.
include(FetchContent)
FetchContent_Declare(
llm_invoke_cpp
GIT_REPOSITORY https://github.com/writePerfectCode/llm_invoke_cpp.git
GIT_TAG r1.0
)
FetchContent_MakeAvailable(llm_invoke_cpp)
target_link_libraries(your_target PRIVATE llm_invoke_cpp::func_registry)
target_link_libraries(your_target PRIVATE llm_invoke_cpp::json_invoke)
target_link_libraries(your_target PRIVATE llm_invoke_cpp::json_session_invoke)
target_link_libraries(your_target PRIVATE llm_invoke_cpp::task_scheduler)
target_link_libraries(your_target PRIVATE llm_invoke_cpp::runtime)
target_link_libraries(your_target PRIVATE llm_invoke_cpp::mcp)The library target name remains llm_invoke_cpp::runtime; the public header path for the protocol-neutral runtime layer is include/tool_runtime/tool_runtime_facade.hpp.
cmake -S . -B build
cmake --build build
ctest --test-dir build --output-on-failureIf you are in a restricted or TLS-sensitive environment and do not need the optional HTTP gateway demo, configure with -D LLM_INVOKE_CPP_BUILD_MCP_HTTP_DEMO=OFF to skip downloading cpp-httplib during configure.
Example entry points you may want to run afterwards:
.\build\func_registry_demo.exe
.\build\json_invoke_demo.exe
.\build\json_stateful_demo.exe
.\build\json_tracing_demo.exe
.\build\task_scheduler_demo.exe
.\build\mcp_filesystem_demo.exeLinux/macOS equivalents:
./build/func_registry_demo
./build/json_invoke_demo
./build/json_stateful_demo
./build/json_tracing_demo
./build/task_scheduler_demo
./build/mcp_filesystem_demoCross-platform smoke test for the MCP filesystem demo:
pwsh -File ./examples/mcp_filesystem/mcp_filesystem_smoke.ps1The initial configure step downloads nlohmann/json into build/_deps/ through FetchContent. The HTTP gateway demo downloads cpp-httplib only when LLM_INVOKE_CPP_BUILD_MCP_HTTP_DEMO is enabled.
GitHub Actions runs a Windows and Linux matrix for pushes and pull requests, covering configure/build/test plus smoke runs for the main non-server demos. The default CI path disables the HTTP gateway demo so the primary pipeline does not depend on downloading cpp-httplib during configure.