Native library reference. Extended CLI examples use
jacs-compat. This source reference can include unreleased changes; see the package guide for installation and MCP profiles for available tools.
MCP Overview
Use MCP when the boundary is model-to-tool inside an application or local workstation. Use A2A when the boundary is agent-to-agent across organizations or services.
Choose The MCP Path
JACS offers three MCP integration surfaces:
- Run
jacs-compat mcpfor local document verification without signing keys. Select--profile local-signwith an existing signed config to let the local client sign as that agent. - Wrap an existing MCP transport when you already have an MCP server or client and want signed JSON-RPC.
- Register JACS as MCP tools when you want the model to call signing, verification, agreement, A2A, or trust operations directly.
Best Fit By Runtime
| Runtime | Best starting point | What it gives you |
|---|---|---|
| Rust CLI | jacs-compat mcp | Verification by default; explicit local signing of documents and Agreement-v2 artifacts, with optional scoped text/image tools |
| Python | jacs.mcp or jacs.adapters.mcp | Local SSE transport security or FastMCP tool registration |
| Node.js | @hai.ai/jacs/mcp | Transport proxy or MCP tool registration for existing SDK-based servers |
Important Constraints
- Signed transport wrappers are local-only. Python uses loopback SSE;
Node allows stdio or loopback transports and rejects
localOnly: false. - Wrap both ends. Signed carriers need matching JACS wrappers and independently selected peer IDs/keys; a stock MCP client cannot authenticate them unaided. Ordinary Rust tool servers and tool registration can use standard MCP clients.
- Unsigned fallback is off by default. Both Python and Node fail closed unless you explicitly allow unsigned fallback.
- Node has two factories.
createJACSTransportProxy()takes a loadedJacsClientorJacsAgent;createJACSTransportProxyAsync()is the config-path variant. - The native server's profiles do not configure the Python or Node adapters. Those integrations have their own transport, key-loading and authorization requirements; the examples below do not inherit the native server's closed local-sign inventory.
- Signatures are provenance, not human approval. Supplied-key verification checks integrity; it does not establish truth, identity, authorization, publication permission or Agreement policy acceptance.
1. Ready-Made Server: jacs-compat mcp
Install the unified binary and start a verification-only server. No identity creation or private-key password is required:
cargo install jacs-cli-compat --locked
jacs-compat mcp
Configure a compatible MCP client with:
{
"mcpServers": {
"jacs": {
"command": "jacs-compat",
"args": ["mcp"]
}
}
}
The default verify-only profile exposes only jacs_verify_document; callers
supply the public key and algorithm. An explicitly supplied --config or
JACS_CONFIG loads public-only configuration without unlocking private keys.
To sign, reuse an existing signed config, or run jacs-compat init once in the
directory where you want to keep the agent identity. Keep using its normal
keychain/password source and select it explicitly:
jacs-compat mcp --profile local-sign --config /absolute/path/to/jacs.config.json
Use those same arguments in the MCP client:
{
"mcpServers": {
"jacs": {
"command": "jacs-compat",
"args": ["mcp", "--profile", "local-sign", "--config", "/absolute/path/to/jacs.config.json"]
}
}
}
JACS_CONFIG can supply the config path instead. Local signing requires a
valid signed config and persistent encrypted keys in filesystem storage; it
does not discover config implicitly or create a replacement identity. Never
send a password as a tool argument or embed it in client JSON. Prefer an
owner-readable JACS_PASSWORD_FILE or the configured OS keychain.
This profile exposes nine JSON/Agreement-v2 tools when Agreement tools are compiled. To add exactly five text/image tools, grant an existing content directory explicitly at process startup:
JACS_MCP_BASE_DIR=/absolute/path/to/content jacs-compat mcp --profile local-sign --config /absolute/path/to/jacs.config.json
There is no implicit working-directory grant. File tools reject traversal and
symlinks and stay beneath the selected directory. Replacing a distinct existing
output requires JACS_MCP_OVERWRITE_OK=1; explicit in-place signing remains
available. Normal backups contain the original plaintext file, so protect them
alongside the content. A content root never expands verify-only.
Signing persists ordinary JACS documents under the config directory's
documents/ directory and grants agent signing authority, not human approval.
An explicit --profile overrides JACS_MCP_PROFILE; unknown values fail
startup. Historical core/full recipes are obsolete; trust-admin and
compatibility-only legacy-core remain unavailable. Key administration,
trust management, A2A and attestation tools are not enabled by local-sign.
The compiled 42-tool contract is not a runtime grant: use tools/list to see
the process's actual authorized inventory.
The native server uses stdio only: stdout carries MCP JSON-RPC and diagnostics
go to stderr. It uses RMCP 3.3.0, supporting date-versioned MCP 2026-07-28
and legacy 2025-11-25 initialization; these are distinct from SDK major
versions such as the TypeScript SDK v2. See the
crate MCP README
for the complete local-signing and response-error contract.
2. Transport Security Around Your Existing MCP Code
Python
Use jacs.mcp when you already have a FastMCP server or client and want transparent signing around the SSE transport:
from fastmcp import FastMCP
from jacs.mcp import JACSMCPServer
mcp = JACSMCPServer(
FastMCP("Secure Server"),
"./jacs.config.json",
allowed_peer_agent_ids=["CLIENT_AGENT_ID"],
)
For clients:
from jacs.mcp import JACSMCPClient
client = JACSMCPClient(
"http://localhost:8000/sse",
"./jacs.config.json",
expected_peer_agent_id="SERVER_AGENT_ID",
)
Helpful utilities in the same module:
create_jacs_mcp_server()for a one-line FastMCP serverjacs_middleware()for explicit Starlette middleware wiringjacs_call()for one-off authenticated local calls
See Python MCP Integration for the detailed patterns.
Node.js
Source and published packages: Version 0.16.1 has a recorded release inventory. Version 0.16.0 is the first release whose source includes the native PQ DID/JWK and Agent Card behavior. See the identity integration guide.
Use the transport proxy when you already have an MCP transport:
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { JacsClient } from '@hai.ai/jacs/client';
import { createJACSTransportProxy } from '@hai.ai/jacs/mcp';
const client = await JacsClient.quickstart({
name: 'mcp-agent',
domain: 'mcp.local',
});
const transport = new StdioServerTransport();
const secureTransport = createJACSTransportProxy(transport, client, 'server', {
allowedPeerAgentIds: ['CLIENT_AGENT_ID'], // Independently selected peer.
});
If you only have a config path:
import { createJACSTransportProxyAsync } from '@hai.ai/jacs/mcp';
const secureTransport = await createJACSTransportProxyAsync(
transport,
'./jacs.config.json',
'server',
{ allowedPeerAgentIds: ['CLIENT_AGENT_ID'] },
);
See Node.js MCP Integration for examples and tool registration.
3. Register JACS Operations As MCP Tools
This is different from transport security. Here the model gets explicit MCP tools such as jacs_sign_document, jacs_verify_document, agreement helpers, and trust helpers.
Python
from fastmcp import FastMCP
from jacs.client import JacsClient
from jacs.adapters.mcp import (
register_jacs_tools,
register_a2a_tools,
register_trust_tools,
)
client = JacsClient.quickstart(name="mcp-agent", domain="mcp.local")
mcp = FastMCP("JACS Tools")
register_jacs_tools(mcp, client=client)
register_a2a_tools(mcp, client=client)
register_trust_tools(mcp, client=client)
Node.js
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { JacsClient } from '@hai.ai/jacs/client';
import { registerJacsTools } from '@hai.ai/jacs/mcp';
const server = new Server(
{ name: 'jacs-tools', version: '1.0.0' },
{ capabilities: { tools: {} } },
);
const client = await JacsClient.quickstart({
name: 'mcp-agent',
domain: 'mcp.local',
});
registerJacsTools(server, client);
Choose the native jacs-compat mcp server for its explicit local-signing boundary.
Tool registration in an existing Node or Python server is a separate
integration; review that server's exposed operations and authorization.
Provenance MCP tools
With local-sign and an explicit JACS_MCP_BASE_DIR, the native server adds
the following tools for inline text and image provenance. They cover the
same surface as the sign-text and
sign-image CLI verbs:
jacs_sign_text— append a YAML-bodied signature block to a markdown / text file.jacs_verify_text— verify all signature blocks in a file (permissive default;strictopt-in).jacs_sign_image— embed a signature in PNG iTXt / JPEG APP11 / WebP XMP.jacs_verify_image— verify the embedded image signature (permissive default;strictopt-in).jacs_extract_media_signature— read out the embedded signature payload (decoded JSON by default;raw_payloadopt-in for the base64url wire form).
Examples
Use the complete Python MCP guide or Node MCP guide for matched peers and host-held secrets. The repository's historical example scripts are not a replacement for those current authentication requirements.