Table of contents
About
Fentaris is a centralized MCP proxy for routing multiple MCP servers through one controlled endpoint.
- Unify stdio, Streamable HTTP, SSE, and HTTP upstream MCP servers behind one proxy.
- Protect tool calls, resources, prompts, and completions with policy, identity, middleware, hooks, and rate limits.
- Observe every proxied operation with structured logging, lifecycle events, and per-request context.
- Ship generated proxy projects with the Fentaris CLI, local runtime files, and project checks.
Fentaris is designed for teams that want MCP servers to behave like production infrastructure: stable names, centralized governance, auditable calls, and predictable client-facing endpoints.
Documentation
Visit our docs or jump to a quickstart
Skills for Coding Agents
Using Claude Code, Codex, Cursor or other AI coding agents?
Getting Started
Use the CLI when you want to start a new Fentaris proxy project:
npm install -g @fentaris/cli
fentaris init my-proxy
cd my-proxy
fentaris devThe generated proxy listens on http://localhost:4000/mcp by default. Point your MCP client to that endpoint.
Use the SDK in an Existing Project
Install the core package in an existing project:
npm add @fentaris/coreBuild a proxy in a few lines:
import { fentaris, stdio } from "@fentaris/core";
const app = fentaris();
app.mcp("filesystem", {
transport: stdio({
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
}),
});
await app.start();
Upstream tool names are still stable and namespaced by server. A filesystem tool is exposed to clients with a proxy name such as:
filesystem__list_directory
Governance
Add users, groups, and policy:
import { fentaris, stdio, user } from "@fentaris/core";
const app = fentaris();
app.policy("read-only")
.mcp("filesystem")
.allow("list_directory");
app.group("operators")
.users(user("alice", { email: "alice@example.com" }))
.policy("read-only");
app.mcp("filesystem", {
transport: stdio({
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
}),
});
await app.start();Block a sensitive tool:
app.mcp("filesystem").tool("write_file", (ctx, next) => {
return ctx.subject?.hasGroup("admins")
? next()
: ctx.deny("Admin required.");
});Ask for approval before dangerous tools:
import { approval, policy } from "@fentaris/core";
const deploy = policy("deploy")
.mcp("github")
.allow("deploy_production", approval.manual({
reason: "Production deploy requires approval",
}));Modify a tool result:
app.mcp("github").tool("search_issues", async (_ctx, next) => {
const result = await next();
if ("content" in result) {
result.content.push({ type: "text", text: "Filtered by Fentaris" });
}
return result;
});Observe every tool call:
app.on("tool:success", ({ ctx, durationMs }) => {
ctx.log.info("tool.success", { tool: ctx.tool?.name, durationMs });
});Policies can govern tool calls and MCP capabilities such as resources, prompts, and completion. Runtime routes can deny, approve, hide, log, or transform calls.
Local Auth
Fentaris can resolve caller identity and upstream credentials from local encrypted files. Generated projects are discovered from fentaris.json; SDK-only projects are discovered from package.json when they depend on @fentaris/core.
export FENTARIS_AUTH_KEY="your-local-encryption-key"
fentaris secrets manifest --entrypoint src/index.ts
fentaris secrets set
fentaris secrets listCredential values are not exposed to middleware, hooks, logs, or policy callbacks.
Packages
| Package | Description |
|---|---|
@fentaris/core |
Proxy runtime, MCP server wrapper, transports, policy, auth, logging, and middleware APIs. |
@fentaris/cli |
Project generator and local development commands. |
@fentaris/approval-telegram |
Telegram approval adapter for Fentaris policies. |
Development
Run the project for development:
fentaris dev
Run checks:
pnpm lint
pnpm typecheck
pnpm --filter @fentaris/core test
pnpm --filter @fentaris/cli test
pnpm --filter @fentaris/approval-telegram testGenerate docs reference:
pnpm docs:generateLicense
MIT, as declared by the published Fentaris packages.