Self-hosted service
metacall/core avatar
metacall/core

MetaCall: Calling Python Functions from JavaScript

MetaCall: The ultimate polyglot programming experience.

1,827 stars273 forksCApache-2.0

At a glance

What is it?
MetaCall is an embeddable polyglot runtime that lets applications call functions across supported language implementations. It fits codebases with a real cross-language boundary, but introduces a runtime layer that must be packaged, upgraded, and checked for compatibility.
Who is it for?
MetaCall fits teams that need to combine functions from several supported language runtimes inside one application and can accept an additional interoperability layer. It is less suitable for a small project that uses one language or needs only a narrow native-library binding.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

MetaCall's Cross-Language Composition Problem

MetaCall addresses applications in which useful code already exists in several languages but the application needs a shared call interface. The README states that it allows functions, methods, or procedures to be called between multiple programming languages. This makes the project relevant to service integrations, command-line programs, application extensions, and FaaS-oriented systems that combine code rather than rewrite it in one language.

The most direct documented example starts with a Python function named `sum`. A JavaScript file imports that function from `./sum.py` and calls it with two numbers. The expression is annotated with the result `7`. This does not establish that every Python object can replace every JavaScript object. It demonstrates the narrower purpose of MetaCall: connecting callable code across supported language implementations.

That distinction matters when choosing the project. MetaCall is not presented as a compiler that turns a polyglot program into native machine code, nor as a complete replacement for each language's package and type system. It is a runtime layer that supplies interoperability between callable code. Adopters should therefore have a concrete language boundary in mind. A codebase with no cross-language calls has little reason to take on the installation and runtime complexity associated with MetaCall.

The MetaCall Import and Function-Call Flow

The documented data flow has three visible stages. First, an application contains a callable implementation such as `sum.py`. Second, the host file references that implementation through a module path. Third, MetaCall resolves and invokes the callable when the application starts through the `metacall` command.

The Python file exposes a conventional function:

python
def sum(a, b):
  return a + b

The JavaScript file imports and invokes it:

javascript
const { sum } = require('./sum.py');

sum(3, 4); // 7

The central mechanism is the cross-language module reference in `require('./sum.py')`. MetaCall sits between the JavaScript host and the Python function, allowing JavaScript source to reference Python code through the loader form shown by the README. The README does not document the internal adapter API, value-conversion rules, asynchronous calling rules, exception propagation, or complete error behavior. Those details should not be inferred from the short example.

The repository layout supports the description of an embeddable C implementation. Its primary language is C, the root contains `CMakeLists.txt`, and implementation files are grouped under `source/`. Language support appears as build and installation components, including Python, Ruby, Node.js, TypeScript, WASM, Java, C, Go, Rust, Lua, and Cobol. The README also names Vanilla JavaScript, C#, C++, D, and other languages. This indicates a runtime assembled from multiple language components rather than a single source-to-source conversion facility.

Installing MetaCall and Running a Python Call from JavaScript

The README identifies a shell installation script as the easiest installation route. This is the command copied from its Install section:

bash
curl -sL https://raw.githubusercontent.com/metacall/install/master/install.sh | sh

The README does not show expected installer output. Create `sum.py` beside the JavaScript entry point with the documented function:

python
def sum(a, b):
  return a + b

Then create `main.js` with the documented import and call:

javascript
const { sum } = require('./sum.py');

sum(3, 4); // 7

Start the JavaScript entry point through MetaCall rather than assuming the default JavaScript runtime:

bash
metacall main.js

The README annotates `sum(3, 4)` with the result `7`, although it does not show captured terminal output. Because the import contains `./sum.py`, the two files must be arranged according to that relative path. The installation documentation is linked from the README for other platforms, installation methods, and Docker. The README does not document an uninstall command, a rollback procedure, or a version-pinning command.

MetaCall's C Build and Component Layout

MetaCall is positioned as extensible, embeddable, and cross-platform, so its intended scope extends beyond standalone scripts. An embedding team would need to evaluate the C codebase, CMake build system, and enabled language components. The repository's primary-language designation does not itself prove a stable embedding API, and the README does not publish an embedding function or header.

The root files show more of the build structure. `CMakeLists.txt` is the visible build entry point, `cmake/` contains build configuration, `source/` contains the main implementation area, and `tools/` contains tooling. Configuration templates named `metacall-config.cmake.in` and `metacall-config-version.cmake.in` show that MetaCall participates in CMake-driven installation and version configuration.

The `.env`, `docker-compose.yml`, and `docker-bake.hcl` files indicate that container workflows are represented. Language components are selected during building rather than presented only as prose-level claims. A smaller component set can reduce installation scope, but the README does not quantify build time, binary size, memory use, startup delay, or invocation overhead. No numerical performance trade-off can therefore be stated.

Docker Builds for Python, Node.js, and Other Components

The Docker Compose definition describes a `deps` service built from `tools/docker/Dockerfile` with the `deps` target. Its `METACALL_INSTALL_OPTIONS` includes `python`, `ruby`, `netcore8`, `nodejs`, `typescript`, `file`, `rpc`, `wasm`, `java`, `c`, `cobol`, `go`, `rust`, `lua`, `rapidjson`, `pack`, `backtrace`, and `sandbox`. A separate `METACALL_BUILD_OPTIONS` list includes `examples`, `tests`, `scripts`, `ports`, `install`, `pack`, `sandbox`, and `benchmarks`.

This shows that container builds can be parameterized instead of treating every development and runtime feature as one fixed unit. However, the visible `docker-compose.yml` is infrastructure for MetaCall development. It should not be treated as a complete production deployment manifest. The README does not document the resulting container command, exposed port, persistence policy, or production resource settings.

For an engineer, the first container check is whether the application needs only Python and Node.js or the broader component list in `METACALL_INSTALL_OPTIONS`. Confirm the target and build arguments against the complete Docker configuration before using Compose. The repository files do not establish which advertised language combinations receive regular container testing, so that compatibility question remains open.

Cross-Language Failure Modes and the FFI Alternative

The clearest limitation is that the README documents one narrow cross-language call rather than the full compatibility contract. It does not define supported argument conversions, object-model behavior, exception handling, module search rules, concurrency rules, performance overhead, or debugging procedures. A function signature that works for two numeric arguments may depend on rules that the README does not publish for classes, collections, callbacks, null values, or mixed-language return objects.

A real alternative is a direct foreign-function interface between specific implementations. MetaCall's repository topics include `ffi`, but the README does not publish a direct performance or typing comparison with a language-native FFI mechanism. The architectural distinction is still clear. Direct FFI requires explicit native boundaries for the libraries involved. MetaCall offers a higher-level polyglot call and module-loading model spanning supported language runtimes.

Choose direct FFI when the integration is small, the target already has a stable C-compatible interface, and adding a polyglot runtime would be excessive. Choose MetaCall when combining several supported language implementations is the central requirement. Verify the real signatures, return values, failure paths, and deployment components first. MetaCall's ability to call `sum` successfully does not prove that an entire application boundary is compatible.

Release Cadence, License, and Upgrade Work

The repository is not archived, and its last push was on 2026-10-16. The release history lists MetaCall v0.9.24 on 2026-09-20, v0.9.23 on 2026-07-23, and v0.9.22 on 2026-03-14. This indicates recent project activity, although the releases remain in the `0.9.x` range. The README does not define compatibility guarantees between those versions.

An upgrade can affect several layers because Docker builds select language components separately, while the host application may combine multiple supported runtimes. The README does not include migration notes, a supported-version policy, a dependency lock procedure, or a rollback command. Teams should treat the MetaCall version and every enabled language component as part of the application release rather than assuming that replacing the CLI binary is sufficient.

The repository identifies `Apache-2.0` as its license and contains `LICENSE` and `NOTICE` files. This review does not provide legal advice or assess compatibility with a particular dependency set. Review those files for the notices and obligations that apply to the intended use and distribution.

Editorial conclusion

MetaCall fits teams that need to combine functions from several supported language runtimes inside one application and can accept an additional interoperability layer. It is less suitable for a small project that uses one language or needs only a narrow native-library binding. Before adoption, verify that every required language implementation is available in the selected installation method, then run the exact cross-language call that represents the application boundary. If that path works through the required packaging and deployment setup, MetaCall directly addresses the multi-runtime composition problem.

Frequently asked questions

How do I install MetaCall?

The README identifies `curl -sL https://raw.githubusercontent.com/metacall/install/master/install.sh | sh` as the easiest installation method. It links to separate installation documentation for other platforms, installation methods, and Docker.

Can MetaCall call a Python function from JavaScript?

Yes. The README shows JavaScript importing `sum` from `./sum.py` and calling it with `sum(3, 4)`, annotated with the result `7`.

Which languages does MetaCall support?

The README names NodeJS, Vanilla JavaScript, TypeScript, Python, Ruby, C#, Java, WASM, Go, C, C++, Rust, D, and Cobol, among others. The Docker configuration exposes separate build options for supported components.

How do I run a MetaCall JavaScript application?

The README example starts a JavaScript entry point with `metacall main.js`. That entry point imports the Python function from `./sum.py`.

Official sources

  1. License: Apache-2.0
  2. metacall/core on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/metacall-core.svg)](https://hysenlabs.com/projects/metacall-core)

Was this useful?