Tool Calls
When you’d rather not wire up your own MCP client, the SDK exposes igris.mcp —
a small JSON-RPC client that speaks to the Igris gateway directly. Every call
is policy-evaluated, identity-tagged, and audit-logged exactly the same way
external MCP clients are.
When to use this
Use igris.mcp.* when… | Use igris.connectHttp() when… |
|---|
| You’re calling tools from server-side code (jobs, agents, schedulers) | You’re configuring an external MCP client (Claude Desktop, Cursor, VS Code, your own MCP-aware app) |
| You want zero extra dependencies on top of the SDK | You already use @modelcontextprotocol/sdk or another HTTP MCP client and want to keep that wiring |
| You want one return type (string content) instead of full JSON-RPC plumbing | You need raw access to MCP capabilities, prompts, resources, etc. |
Both paths route through the same gateway, hit the same policies, and produce the same audit events.
API
igris.mcp.initialize(slug, options?): Promise<{ protocolVersion, serverInfo }>
igris.mcp.listTools(slug, options?): Promise<McpTool[]>
igris.mcp.callTool(slug, toolName, args, options?): Promise<string>
All three accept the same McpConfigOptions:
interface McpConfigOptions {
user?: string; // sent as X-Igris-User
traceId?: string; // sent as X-Igris-Trace-Id; auto-generated if omitted
metadata?: Record<string, string | number | boolean>;
// sent as X-Igris-Metadata: <JSON>
}
Quick Start
import { Igris } from "@igris-security/sdk";
const igris = new Igris({ apiKey: process.env.IGRIS_API_KEY! });
// Optional handshake — useful for sanity checking that the connection is wired up.
const init = await igris.mcp.initialize("github-prod", {
user: "alice@company.com",
});
console.log(init.serverInfo);
// { name: "github-mcp", version: "1.2.0" }
// Discover available tools.
const tools = await igris.mcp.listTools("github-prod", {
user: "alice@company.com",
});
for (const tool of tools) {
console.log(`${tool.name} — ${tool.description}`);
}
// Invoke a tool. The return value is the upstream tool's text content joined.
const output = await igris.mcp.callTool(
"github-prod",
"create_issue",
{
repo: "acme/igris",
title: "Migration plan for v2",
body: "Initial draft.",
},
{
user: "alice@company.com",
traceId: "trace-issue-triage-789",
metadata: { feature: "issue-triage", env: "production" },
},
);
console.log(output);
Every call hits https://api.igrisecurity.com/v1/mcp/<slug>, carries Authorization: Bearer <apiKey>, and is policy-evaluated server-side before being forwarded to the upstream MCP server with its real credential injected.
Threading multiple calls under one trace
If a single user request triggers several tool calls, share the trace id so
Lens can show the whole chain as one operation:
const traceId = "trace-" + crypto.randomUUID();
const opts = { user: "alice@company.com", traceId };
await igris.mcp.callTool("github-prod", "list_issues", { repo: "acme/igris" }, opts);
await igris.mcp.callTool("slack-prod", "post_message", {
channel: "#triage",
text: "Top 3 issues this week ...",
}, opts);
Both rows in the audit trail will share traceId = "trace-...", which lets you
filter Lens to the full sequence.
Error handling
igris.mcp methods (igris.mcp.initialize, igris.mcp.listTools, igris.mcp.callTool) throw
plain Error instances — not the typed IgrisError subclasses. The error message includes the
HTTP status and response body:
MCP gateway error (403): {"error":"policy denied"}
MCP error: tool not found
The typed error classes (IgrisPolicyDeniedError, IgrisRateLimitError, IgrisAuthError) apply
only to igris.chat.completions, igris.embeddings, and igris.connections — resources that use
fetchWithRetry internally. igris.mcp uses a plain fetch call.
Handle igris.mcp errors with a standard try/catch:
try {
const output = await igris.mcp.callTool("github-prod", "delete_repo", { repo: "acme/legacy" });
} catch (e) {
if (e instanceof Error) {
if (e.message.includes("403")) {
// policy denied or auth failure
} else if (e.message.includes("429")) {
// rate limited — implement your own backoff and retry
} else {
// upstream or gateway error
}
}
throw e;
}
igris.mcp does not auto-retry. Unlike the LLM gateway resources, igris.mcp makes a single
fetch call with no retry logic. If you need resilience against transient errors or rate limits,
implement your own retry loop with exponential backoff.
What gets logged
Every initialize, listTools, and callTool produces an audit event with:
- The actor (
user, derived from X-Igris-User)
- The connection slug
- The tool name and arguments (for
callTool)
- The policy decision (
allow / deny / alert)
- Any matched rule and conditions
- The trace id (
X-Igris-Trace-Id)
- All metadata fields (
X-Igris-Metadata)
- The timing and outcome
All of this surfaces in Lens and is queryable via the audit-events API.
- Connections — how to register the upstream MCP server and store its credential
- Identity & Metadata — what the gateway does with
user, traceId, and metadata
- Policies — how to gate
tools/call by tool name, user, or metadata
- MCP Client Config — the alternative path: drive an external MCP client