Skip to main content

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 SDKYou 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 plumbingYou 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