Overview
gopher-mcp-js is a TypeScript SDK for Gopher Orch - an AI Agent orchestration framework with native performance. It uses koffi for FFI to call C++ libraries (gopher-orch).
Current Architecture
Project Structure
gopher-mcp-js/
├── src/
│ ├── index.ts # Main exports
│ ├── agent.ts # GopherAgent class
│ ├── config.ts # Configuration
│ ├── ffi/
│ │ ├── index.ts
│ │ └── library.ts # koffi FFI bindings
│ └── ...
├── native/
│ └── lib/ # Native libraries (currently macOS only)
│ ├── libgopher-orch.dylib
│ ├── libgopher-mcp.dylib
│ └── ...
├── third_party/
│ └── gopher-orch/ # Git submodule
└── build.sh # Builds from source
Current Build Process
- gopher-orch is a git submodule in
third_party/gopher-orch
build.sh compiles C++ from source using CMake
- Built libraries go to
native/lib/
- Works for development but requires C++ toolchain
Target Platforms
| Platform |
Architecture |
Library Name |
| Linux |
x64 |
libgopher-orch.so |
| Linux |
ARM64 |
libgopher-orch.so |
| macOS |
x64 (Intel) |
libgopher-orch.dylib |
| macOS |
ARM64 (Apple Silicon) |
libgopher-orch.dylib |
| Windows |
x64 |
gopher-orch.dll |
| Windows |
ARM64 |
gopher-orch.dll |
Distribution Approaches
Approach 1: Platform-specific Optional Dependencies (Recommended)
Used by esbuild, SWC, Bun - the modern standard for native npm packages.
Structure
@gopher-orch/core # Main TypeScript SDK (no binaries)
@gopher-orch/darwin-arm64 # macOS ARM64 binaries only
@gopher-orch/darwin-x64 # macOS x64 binaries only
@gopher-orch/linux-arm64 # Linux ARM64 binaries only
@gopher-orch/linux-x64 # Linux x64 binaries only
@gopher-orch/win32-arm64 # Windows ARM64 binaries only
@gopher-orch/win32-x64 # Windows x64 binaries only
Main package.json
{
"name": "gopher-orch",
"optionalDependencies": {
"@gopher-orch/darwin-arm64": "0.1.0",
"@gopher-orch/darwin-x64": "0.1.0",
"@gopher-orch/linux-arm64": "0.1.0",
"@gopher-orch/linux-x64": "0.1.0",
"@gopher-orch/win32-arm64": "0.1.0",
"@gopher-orch/win32-x64": "0.1.0"
}
}
How It Works
- npm install - npm automatically installs only the matching platform package
- At runtime - SDK detects platform and loads binary from the correct package
- User code - Same across all platforms, no platform-specific code needed
Benefits
- Users only download binaries for their platform (~4MB vs ~24MB)
- No postinstall scripts (works with
--ignore-scripts)
- Works with npm, yarn, pnpm
- Fast installs
- Works offline after initial install
Drawbacks
- Multiple packages to publish and maintain
- More complex release process
Approach 2: Download on Postinstall
Used by sharp, node-canvas - simpler single-package approach.
Structure
{
"name": "gopher-orch",
"scripts": {
"postinstall": "node scripts/download-native.js"
}
}
How It Works
- Binaries stored on GitHub releases
- postinstall script detects platform and downloads correct binary
- Binary cached locally
Benefits
- Single npm package
- Binaries updated without npm publish
Drawbacks
- Network required during install
- postinstall scripts can be disabled by users
- Slower installs
Self-Contained Library (BUILD_BUNDLED_SHARED)
The Problem
Previously, gopher-orch required multiple library files:
- libgopher-orch.so/dylib/dll
- libgopher-mcp.so/dylib/dll
- libgopher-mcp-event.so/dylib/dll
- libfmt.so/dylib/dll
This complicated distribution and caused runtime path issues.
The Solution
Added BUILD_BUNDLED_SHARED CMake option that creates a single self-contained shared library with all dependencies statically linked inside.
# In gopher-orch/CMakeLists.txt
option(BUILD_BUNDLED_SHARED "Build self-contained shared library with all deps statically linked (for SDK distribution)" OFF)
How It Works
When BUILD_BUNDLED_SHARED=ON:
- Uses static versions of dependencies (gopher-mcp-static, gopher-mcp-event-static, fmt)
- Links with whole-archive to embed all symbols
- Results in single library file containing everything
Platform-specific Linking
macOS:
target_link_libraries(gopher-orch-shared PRIVATE
-Wl,-force_load,$<TARGET_FILE:gopher-mcp-static>
-Wl,-force_load,$<TARGET_FILE:gopher-mcp-event-static>
)
Linux:
target_link_libraries(gopher-orch-shared PRIVATE
-Wl,--whole-archive
gopher-mcp-static
gopher-mcp-event-static
-Wl,--no-whole-archive
)
Windows:
target_link_libraries(gopher-orch-shared PRIVATE
-Wl,--whole-archive
gopher-mcp-static
gopher-mcp-event-static
-Wl,--no-whole-archive
)
Result
Each platform package now contains just:
@gopher-orch/linux-x64/
├── lib/
│ └── libgopher-orch.so # Single self-contained library
└── package.json
Library Loading in TypeScript
Current Implementation (library.ts)
import * as koffi from 'koffi';
import * as path from 'path';
import * as os from 'os';
export class GopherOrchLibrary {
private loadLibrary(): void {
const libraryName = this.getLibraryName();
const searchPaths = this.getSearchPaths();
// Try custom path from environment variable
const envPath = process.env['GOPHER_ORCH_LIBRARY_PATH'];
if (envPath && fs.existsSync(envPath)) {
this.lib = koffi.load(envPath);
// ...
}
// Try search paths
for (const searchPath of searchPaths) {
const libFile = path.join(searchPath, libraryName);
if (fs.existsSync(libFile)) {
this.lib = koffi.load(libFile);
// ...
}
}
}
private getLibraryName(): string {
switch (os.platform()) {
case 'darwin': return 'libgopher-orch.dylib';
case 'win32': return 'gopher-orch.dll';
default: return 'libgopher-orch.so';
}
}
private getSearchPaths(): string[] {
const moduleDir = path.dirname(path.dirname(__dirname));
return [
path.join(process.cwd(), 'native', 'lib'),
path.join(moduleDir, 'native', 'lib'),
// ... system paths
];
}
}
Updated Implementation for Optional Dependencies
private getSearchPaths(): string[] {
const platform = os.platform(); // 'darwin', 'linux', 'win32'
const arch = os.arch(); // 'arm64', 'x64'
// Map to package names
const platformMap: Record<string, string> = {
'darwin': 'darwin',
'linux': 'linux',
'win32': 'win32'
};
const packageName = `@gopher-orch/${platformMap[platform]}-${arch}`;
const paths = [];
// Try to find the platform-specific package
try {
const packagePath = require.resolve(`${packageName}/package.json`);
const packageDir = path.dirname(packagePath);
paths.push(path.join(packageDir, 'lib'));
} catch (e) {
// Package not installed
}
// Fallback to local native/lib
paths.push(path.join(process.cwd(), 'native', 'lib'));
return paths;
}
gopher-orch Release Artifacts
The gopher-orch GitHub releases now provide:
| Artifact |
Platform |
Contents |
| libgopher-orch-linux-x64.tar.gz |
Linux x64 |
libgopher-orch.so, headers, verify_orch |
| libgopher-orch-linux-arm64.tar.gz |
Linux ARM64 |
libgopher-orch.so, headers, verify_orch |
| libgopher-orch-macos-x64.tar.gz |
macOS x64 |
libgopher-orch.dylib, headers, verify_orch |
| libgopher-orch-macos-arm64.tar.gz |
macOS ARM64 |
libgopher-orch.dylib, headers, verify_orch |
| libgopher-orch-windows-x64.zip |
Windows x64 |
gopher-orch.dll, headers |
| libgopher-orch-windows-arm64.zip |
Windows ARM64 |
gopher-orch.dll, headers |
All libraries are self-contained with gopher-mcp, gopher-mcp-event, and fmt statically linked.
User Experience
For SDK Users
// Same code works on all platforms
import { GopherAgent, GopherAgentConfig } from 'gopher-orch';
const agent = GopherAgent.create(
GopherAgentConfig.builder()
.provider('AnthropicProvider')
.model('claude-3-haiku-20240307')
.apiKey('your-api-key')
.build()
);
const answer = agent.run('What time is it in Tokyo?');
console.log(answer);
agent.dispose();
For SDK Developers
# Development (builds from source)
./build.sh
# Testing specific platform
GOPHER_ORCH_LIBRARY_PATH=/path/to/libgopher-orch.so npm test
Overview
gopher-mcp-js is a TypeScript SDK for Gopher Orch - an AI Agent orchestration framework with native performance. It uses koffi for FFI to call C++ libraries (gopher-orch).
Current Architecture
Project Structure
Current Build Process
third_party/gopher-orchbuild.shcompiles C++ from source using CMakenative/lib/Target Platforms
Distribution Approaches
Approach 1: Platform-specific Optional Dependencies (Recommended)
Used by esbuild, SWC, Bun - the modern standard for native npm packages.
Structure
Main package.json
{ "name": "gopher-orch", "optionalDependencies": { "@gopher-orch/darwin-arm64": "0.1.0", "@gopher-orch/darwin-x64": "0.1.0", "@gopher-orch/linux-arm64": "0.1.0", "@gopher-orch/linux-x64": "0.1.0", "@gopher-orch/win32-arm64": "0.1.0", "@gopher-orch/win32-x64": "0.1.0" } }How It Works
Benefits
--ignore-scripts)Drawbacks
Approach 2: Download on Postinstall
Used by sharp, node-canvas - simpler single-package approach.
Structure
{ "name": "gopher-orch", "scripts": { "postinstall": "node scripts/download-native.js" } }How It Works
Benefits
Drawbacks
Self-Contained Library (BUILD_BUNDLED_SHARED)
The Problem
Previously, gopher-orch required multiple library files:
This complicated distribution and caused runtime path issues.
The Solution
Added
BUILD_BUNDLED_SHAREDCMake option that creates a single self-contained shared library with all dependencies statically linked inside.How It Works
When
BUILD_BUNDLED_SHARED=ON:Platform-specific Linking
macOS:
Linux:
Windows:
Result
Each platform package now contains just:
Library Loading in TypeScript
Current Implementation (library.ts)
Updated Implementation for Optional Dependencies
gopher-orch Release Artifacts
The gopher-orch GitHub releases now provide:
All libraries are self-contained with gopher-mcp, gopher-mcp-event, and fmt statically linked.
User Experience
For SDK Users
For SDK Developers