@ory/argus 1.5.3 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -143,9 +143,9 @@ for await (const msg of stream) { /* standard handling */ }
143
143
  ```
144
144
 
145
145
  `canUseTool` only fires for tools the SDK controls. If the agent also
146
- registers MCP servers, wrap each MCP tool handler the same way — see the
147
- `@ory/argus` `parseClaudeCodeMcpTool` / `checkMcpPermission` helpers for an
148
- MCP-flavored version of the gate.
146
+ registers MCP servers, gate each MCP tool handler the same way and pass
147
+ `mcpTool` (from the `@ory/argus` `parseClaudeCodeMcpTool` or `parseMcpToolName`
148
+ helpers) so the call is checked against the project's MCP server access.
149
149
 
150
150
  ### OpenAI Agents SDK
151
151
 
@@ -377,7 +377,7 @@ For full env-var coverage (including the user/agent split,
377
377
  - It does not generate the agent. The user owns the agent loop, tool
378
378
  catalog, and deployment shape. This skill only drops `@ory/argus` into
379
379
  whatever they already have.
380
- - It does not write permissions. Native-tool blocks and MCP grants are
380
+ - It does not write permissions. Native-tool blocks and MCP server access are
381
381
  provisioned in the Ory Console (Agent Security); `@ory/argus` only reads
382
382
  them. The local seed writes no baseline native-tool grants.
383
383
  - It does not adapt one of the existing harness plugins (`@ory/claude-code`,
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ory-permissions-onboarding
3
- description: Onboard native agent-tool authorization with default allow and explicit deny overrides. Covers connecting the plugin, reviewing allowed and blocked tools, writing blocks in the Ory Console, and promoting the project from observe to enforce. MCP and PermissionMode remain grant-based.
3
+ description: Onboard native agent-tool authorization with default allow and explicit deny overrides. Covers connecting the plugin, reviewing allowed and blocked tools, writing blocks in the Ory Console, and promoting the project from observe to enforce. MCP servers use the same block model; PermissionMode remains grant-based.
4
4
  ---
5
5
 
6
6
  # Onboard Ory Permissions for Agent Tool Calls
@@ -9,7 +9,7 @@ Help the user connect Agent Security and roll out explicit native-tool blocks
9
9
  without treating missing grants as denials.
10
10
 
11
11
  **The plugin only reads permissions. It never writes them.** The permission
12
- model, native-tool blocks, MCP grants, and observe/enforce posture are managed
12
+ model, native-tool blocks, MCP server access, and observe/enforce posture are managed
13
13
  in the **Ory Console** (Agent Security).
14
14
 
15
15
  Native policy is simple:
@@ -18,7 +18,8 @@ Native policy is simple:
18
18
  - Their `use` permit is `!blockedSubjects.includes(subject)`.
19
19
  - No matching block means allowed; a matching block means denied.
20
20
  - `observe` logs the block and proceeds; `enforce` vetoes the call.
21
- - MCP permissions and `PermissionMode#enforcedSubjects` remain grant-based.
21
+ - MCP calls use the same model in `McpServer` and `McpTool`.
22
+ - `PermissionMode#enforcedSubjects` remains grant-based.
22
23
 
23
24
  ## 1. Connect Agent Security
24
25
 
@@ -78,8 +79,10 @@ Blocks can also target the project, an agent credential, an agent session, a
78
79
  sub-agent credential, or a sub-agent spawn. Group/SubjectSet expansion is
79
80
  supported. A native deny is always an explicit block, never a missing grant.
80
81
 
81
- MCP is intentionally different: continue granting MCP server/tool access with
82
- its existing `users`/`use` and `invoke` relations.
82
+ MCP calls are checked as `McpServer:<server>#use` and
83
+ `McpTool:<server>:<tool>#use`, where `<server>` is the lowercased configured
84
+ server name. Set Admin, Write, Read, or No access per well-known server in the
85
+ Ory Console (Agent Security → Enforce → MCP servers); there is nothing to grant.
83
86
 
84
87
  ## 4. Observe Before Enforcing
85
88
 
@@ -25,7 +25,7 @@ import { ensureAgentIdentity, ensureSubAgentIdentity, type SubAgentIdentity } fr
25
25
  import { ensureUserAuthenticated } from "./user-login.js";
26
26
  import { type ModeDecision, type PermissionDecision, type PrincipalBlockSubjects } from "./permissions.js";
27
27
  import { type DenialContext } from "./denial.js";
28
- import { type McpToolIdentifier } from "./mcp.js";
28
+ import type { McpToolIdentifier } from "./mcp.js";
29
29
  import type { RuntimeCredential } from "./runtime-credential.js";
30
30
  export declare function resolveNamespace(): string;
31
31
  export interface HookContextOptions {
package/dist/adapters.js CHANGED
@@ -43,7 +43,6 @@ const permission_mode_js_1 = require("./permission-mode.js");
43
43
  const tool_catalog_js_1 = require("./tool-catalog.js");
44
44
  const subject_js_1 = require("./subject.js");
45
45
  const denial_js_1 = require("./denial.js");
46
- const mcp_js_1 = require("./mcp.js");
47
46
  const tool_metadata_js_1 = require("./tool-metadata.js");
48
47
  function resolveNamespace() {
49
48
  return process.env.ORY_PERMISSION_NAMESPACE ?? "AgentTool";
@@ -408,6 +407,7 @@ function gateActivityAttributes(opts) {
408
407
  ? {
409
408
  mcpServer: opts.mcpTool.serverName,
410
409
  ...(opts.mcpTool.toolName ? { mcpTool: opts.mcpTool.toolName } : {}),
410
+ ...(opts.mcpTool.fingerprints?.length ? { mcpFingerprints: opts.mcpTool.fingerprints } : {}),
411
411
  }
412
412
  : {}),
413
413
  ...(opts.extraActivityAttributes ?? {}),
@@ -447,41 +447,38 @@ async function decideTool(client, opts) {
447
447
  }
448
448
  let outcome;
449
449
  try {
450
+ const nativeGate = () => (0, permissions_js_1.gateToolCall)(client, {
451
+ harness: opts.harness,
452
+ toolName: opts.toolName,
453
+ check,
454
+ activityAttributes: activityAttrs,
455
+ shellCommand: (0, tool_catalog_js_1.extractShellCommand)(opts.harness, opts.toolName, opts.toolArgs),
456
+ principals: opts.principals,
457
+ });
450
458
  if (opts.mcpTool) {
451
- const mcpResult = await (0, mcp_js_1.checkMcpPermission)(client, opts.mcpTool, {
452
- subject: subjectRef,
453
- activityAttributes: activityAttrs,
454
- });
455
- const agentSubject = (0, subject_js_1.resolveAgentSubject)(client);
456
- const subagentSubject = (0, subject_js_1.resolveSubAgentSubject)(opts.principals?.subAgentClientId);
457
- const mode = await (0, permission_mode_js_1.warmPermissionModeCache)(client, subjectRef, {
458
- additionalSubjects: [
459
- ...(agentSubject ? [{ scope: "agent", subject: agentSubject }] : []),
460
- ...(subagentSubject ? [{ scope: "subagent", subject: subagentSubject }] : []),
461
- ],
462
- });
463
- outcome = (0, permissions_js_1.applyPermissionMode)(client, mcpResult.allowed, {
464
- namespace: process.env.ORY_MCP_SERVER_NAMESPACE ?? "mcp_servers",
465
- object: opts.mcpTool.serverName,
466
- relation: "users",
467
- ...subjectRef,
468
- activityAttributes: {
469
- ...activityAttrs,
470
- mcpServer: opts.mcpTool.serverName,
471
- ...(opts.mcpTool.toolName ? { mcpTool: opts.mcpTool.toolName } : {}),
472
- },
473
- modeOverride: mode.mode,
474
- });
475
- }
476
- else {
477
- outcome = await (0, permissions_js_1.gateToolCall)(client, {
459
+ const mcpGate = (0, permissions_js_1.gateMcpToolCall)(client, {
478
460
  harness: opts.harness,
479
461
  toolName: opts.toolName,
480
- check,
462
+ mcpTool: opts.mcpTool,
463
+ subject: subjectRef,
481
464
  activityAttributes: activityAttrs,
482
- shellCommand: (0, tool_catalog_js_1.extractShellCommand)(opts.harness, opts.toolName, opts.toolArgs),
483
465
  principals: opts.principals,
484
466
  });
467
+ // A resource read is a native harness tool too, so a block on that tool
468
+ // still applies alongside the server's enablement and No access.
469
+ if (opts.mcpTool.resource) {
470
+ const [mcp, native] = await Promise.all([mcpGate, nativeGate()]);
471
+ outcome =
472
+ native.kind === "interactive" || native.kind === "not_connected"
473
+ ? mcp
474
+ : (0, permissions_js_1.mostRestrictiveDecision)([mcp, native]);
475
+ }
476
+ else {
477
+ outcome = await mcpGate;
478
+ }
479
+ }
480
+ else {
481
+ outcome = await nativeGate();
485
482
  }
486
483
  }
487
484
  catch (err) {
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "repo": "ory-agent-plugins",
3
- "commit": "6d5a4dd670531925d1a0807d25406ccc4db24bf5",
4
- "commitShort": "6d5a4dd6",
3
+ "commit": "ebcd620c5f7cb4a27f47fd98bcb50b3d11d92b2e",
4
+ "commitShort": "ebcd620c",
5
5
  "branch": "main",
6
- "commitDate": "2026-10-22T14:21:25-07:00",
6
+ "commitDate": "2026-10-28T20:25:41-07:00",
7
7
  "dirty": false,
8
- "builtAt": "2026-10-22T21:25:21.096Z"
8
+ "builtAt": "2026-10-29T03:28:58.821Z"
9
9
  }
package/dist/cli.js CHANGED
@@ -126,7 +126,7 @@ function runConfigureCommand(binName, args) {
126
126
  console.log(`User subject ns: ${resolved.userSubjectNamespace ?? "User (default)"} [${resolved.userSubjectNamespaceSource}]`);
127
127
  console.log("");
128
128
  if (resolved.security.connected) {
129
- console.log("Sign-in and permission checks are running. Native-tool blocks, MCP grants,");
129
+ console.log("Sign-in and permission checks are running. Native-tool blocks, MCP server access,");
130
130
  console.log("and the observe/enforce posture are managed in the Ory Console (Agent Security).");
131
131
  console.log("");
132
132
  console.log("To disconnect (skills, commands, the local stack, and activity logging keep working):");
package/dist/client.js CHANGED
@@ -60,6 +60,7 @@ function permissionCheckFromRequest(request) {
60
60
  relation: request.subjectSetRelation ?? "",
61
61
  }
62
62
  : undefined,
63
+ ...(request.mcp ? { mcp: request.mcp } : {}),
63
64
  };
64
65
  }
65
66
  function permissionCheckFromTuple(tuple) {
@@ -69,6 +70,7 @@ function permissionCheckFromTuple(tuple) {
69
70
  relation: tuple.relation,
70
71
  subjectId: tuple.subject_id,
71
72
  subjectSet: tuple.subject_set,
73
+ ...(tuple.mcp ? { mcp: tuple.mcp } : {}),
72
74
  };
73
75
  }
74
76
  function httpError(status, message) {
@@ -215,6 +217,7 @@ class OryAgentClient {
215
217
  object: check.object,
216
218
  relation: check.relation,
217
219
  principal: this.permissionPrincipal(check),
220
+ ...(check.mcp ? { mcp: check.mcp } : {}),
218
221
  })),
219
222
  };
220
223
  const response = await (0, runtime_credential_js_1.authenticatedRuntimeRequest)(credential, {
@@ -714,6 +717,7 @@ class OryAgentClient {
714
717
  subjectSetNamespace: check.subjectSet?.namespace,
715
718
  subjectSetObject: check.subjectSet?.object,
716
719
  subjectSetRelation: check.subjectSet?.relation,
720
+ ...(check.mcp ? { mcp: check.mcp } : {}),
717
721
  });
718
722
  const data = response.data;
719
723
  const oryRequestId = extractOryRequestId(response.headers);
@@ -780,6 +784,7 @@ class OryAgentClient {
780
784
  relation: c.subjectSet.relation,
781
785
  }
782
786
  : undefined,
787
+ ...(c.mcp ? { mcp: c.mcp } : {}),
783
788
  })),
784
789
  },
785
790
  });
@@ -72,7 +72,7 @@ const BOOL_ATTRIBUTES = new Set([
72
72
  "alert", "blocked", "checkRejected", "hasError", "success",
73
73
  "enforceGranted", "proceed", "interactive",
74
74
  ]);
75
- const ARRAY_ATTRIBUTES = new Set(["shellWords", "shellDeniedWords", "warningsHashes"]);
75
+ const ARRAY_ATTRIBUTES = new Set(["shellWords", "shellDeniedWords", "warningsHashes", "mcpFingerprints"]);
76
76
  const SAFE_STRING = /^[A-Za-z0-9][A-Za-z0-9._:/@-]{0,254}$/;
77
77
  const HASH = /^[a-f0-9]{16}$/;
78
78
  const MAX_EVENT_AGE_MS = 24 * 60 * 60 * 1_000;
package/dist/index.d.ts CHANGED
@@ -14,7 +14,7 @@ export { ensureUserAuthenticated, ensureAuthenticated, type UserLoginDecision, t
14
14
  export { resolveAgentCredentials, resolvePreprovisionedRuntimeContext, resolveRuntimeAgentCredentials, ensureAgentIdentity, ensureSubAgentIdentity, fetchClientCredentialsToken, registerAgentClient, loadAgentDynamicCredentials, loadAgentDynamicCredentialsByHarness, saveAgentDynamicCredentials, clearAgentDynamicCredentials, latestAgentRegistration, latestSubAgentSession, countAgentSessions, claimAgentDynamicCredentials, loadSubAgentDynamicCredentials, loadAllSubAgentDynamicCredentials, loadSubAgentDynamicCredentialsByHarness, saveSubAgentDynamicCredentials, clearSubAgentDynamicCredentials, clearSubAgentDynamicCredentialsForHarness, claimSubAgentDynamicCredentials, loadDelegationNodeId, resolvePreprovisionedRootDelegation, saveDelegationNodeId, loadRetiredCredentials, clearRetiredCredentials, retireAgentSessions, sessionRetention, revokeAgentDynamicClient, AGENT_TOKEN_EXPIRY_SKEW_SEC, DEFAULT_SESSION_RETENTION, type AgentRegistrationClaim, type AgentCredentials, type AgentCredentialKind, type ResolveAgentCredentialsOptions, type ResolveRuntimeAgentCredentialsOptions, type EnsureAgentIdentityOptions, type RegisterAgentClientArgs, type DelegationInput, type RevokeAgentClientResult, type SubAgentIdentity, type EnsureSubAgentIdentityOptions, } from "./agent-auth.js";
15
15
  export { ensureReadCredential, resetReadCredentialBackoff, READ_CREDENTIAL_RETRY_MS, type EnsureReadCredentialOptions, type ReadCredentialOutcome, } from "./read-credential.js";
16
16
  export { clearCredentialsForUninstall, resolveInstalledHarnesses, type ClearCredentialsOptions, type ClearCredentialsResult, } from "./uninstall.js";
17
- export { type SessionInfo, type OAuth2TokenInfo, type PermissionCheck, type PermissionResult, type BatchPermissionResult, type OryError, type OryErrorCode, } from "./types.js";
17
+ export { type SessionInfo, type OAuth2TokenInfo, type McpServerHint, type PermissionCheck, type PermissionResult, type BatchPermissionResult, type OryError, type OryErrorCode, } from "./types.js";
18
18
  export { runConfigureCommand, runAgentCommand, printOryConfig, printEnvironment, printLogTail, printEnvHelp, isTtyAvailable, promptOnTty, promptForProjectUrl, interactiveConfigPrompt, } from "./cli.js";
19
19
  export { oryNpx } from "./cli-invocation.js";
20
20
  export { runPermissionsCommand } from "./permissions-cli.js";
@@ -29,12 +29,12 @@ export { renderMirrorBootstrap, type MirrorBootstrapKind, type MirrorBootstrapOp
29
29
  export { renderOrySkills, renderOryCommands, commandToSkill, commandToToml, commandToFrontmatterMarkdown, commandToPlainMarkdown, toSkillMarkdown, writeSkillTree, removeSkillDirs, ORY_SKILL_NAMES, ORY_COMMAND_SKILL_NAMES, ORY_COMMAND_SLUGS, type RenderedSkill, type RenderedCommand, type RenderProfileOptions, } from "./skills.js";
30
30
  export { runLocalCommand, } from "./local/index.js";
31
31
  export { runRegistryCommand, REGISTRY_URL } from "./registry/index.js";
32
- export { checkAndDecide, applyPermissionMode, gateToolCall, decomposeAndCheck, resolveCheckRelation, type PermissionDecision, type ModeDecision, type DecisionActivityAttributes, type CheckAndDecideOptions, type ApplyPermissionModeContext, type GateToolCallArgs, type PrincipalBlockSubjects, type ToolGateOutcome, type BlockReason, } from "./permissions.js";
32
+ export { checkAndDecide, applyPermissionMode, gateToolCall, gateMcpToolCall, decomposeAndCheck, resolveCheckRelation, type PermissionDecision, type ModeDecision, type DecisionActivityAttributes, type CheckAndDecideOptions, type ApplyPermissionModeContext, type GateToolCallArgs, type PrincipalBlockSubjects, type ToolGateOutcome, type BlockReason, } from "./permissions.js";
33
33
  export { extractShellCommands, extractBashCommandWords, type ParsedShell, type ShellCommand, type ShellRedirect, type ShellAssignment, type BashParseResult, } from "./bash-parser.js";
34
- export { buildAgentSecurityOpl, renderToolNamespaceClass, renderDelegationNamespaceClass, renderPermissionModeNamespaceClass, renderAgentRoleNamespaceClass, renderEnrollmentNamespaceClass, renderPrincipalClass, renderOplImport, OPL_IMPORT_MODULE, OPL_IMPORT_SYMBOLS, PRINCIPAL_NAMESPACES, NODE_REFERENCE_NAMESPACES, AGENT_NODE_NAMESPACE, SUBAGENT_NODE_NAMESPACE, RELATION_USERS, RELATION_BLOCKED_SUBJECTS, RELATION_DELEGATES, RELATION_CREDENTIALS, RELATION_ENFORCED_SUBJECTS, RELATION_MEMBERS, RELATION_OPTED_OUT_SUBJECTS, PERMISSION_MODE_OBJECT, AUTO_ENROLL_OBJECT, PROJECT_POSTURE_OBJECT, PERMISSION_MODE_NAMESPACE, DELEGATION_NAMESPACE, AGENT_ROLE_NAMESPACE, ENROLLMENT_NAMESPACE, PERMIT_USE, DEFAULT_NAMESPACE, DEFAULT_SHELL_NAMESPACE, } from "./opl.js";
34
+ export { buildAgentSecurityOpl, renderToolNamespaceClass, renderDelegationNamespaceClass, renderPermissionModeNamespaceClass, renderAgentRoleNamespaceClass, renderEnrollmentNamespaceClass, renderPrincipalClass, renderOplImport, OPL_IMPORT_MODULE, OPL_IMPORT_SYMBOLS, PRINCIPAL_NAMESPACES, NODE_REFERENCE_NAMESPACES, AGENT_NODE_NAMESPACE, SUBAGENT_NODE_NAMESPACE, RELATION_USERS, RELATION_BLOCKED_SUBJECTS, RELATION_DELEGATES, RELATION_CREDENTIALS, RELATION_ENFORCED_SUBJECTS, RELATION_MEMBERS, RELATION_OPTED_OUT_SUBJECTS, PERMISSION_MODE_OBJECT, AUTO_ENROLL_OBJECT, PROJECT_POSTURE_OBJECT, PERMISSION_MODE_NAMESPACE, DELEGATION_NAMESPACE, AGENT_ROLE_NAMESPACE, ENROLLMENT_NAMESPACE, PERMIT_USE, DEFAULT_NAMESPACE, DEFAULT_SHELL_NAMESPACE, MCP_SERVER_NAMESPACE, MCP_TOOL_NAMESPACE, } from "./opl.js";
35
35
  export { HARNESS_TOOL_CATALOG, KNOWN_HARNESSES, ALL_TOOLS, getToolCatalog, INTERACTIVE_TOOL_CATALOG, getInteractiveToolCatalog, isInteractiveTool, SHELL_TOOL_CATALOG, getShellToolCatalog, isShellTool, SHELL_COMMAND_CATALOG, getShellCommandCatalog, resolveShellCommandNamespace, extractShellCommand, type KnownHarness, } from "./tool-catalog.js";
36
36
  export { classifyLifecycle, isUserFacingPhase, isToolExecutionPhase, HARNESS_LIFECYCLE_MAP, USER_FACING_PHASES, TOOL_EXECUTION_PHASES, type LifecyclePhase, } from "./lifecycle.js";
37
- export { parseClaudeCodeMcpTool, parseGeminiMcpTool, parseMcpToolGeneric, checkMcpPermission, type McpToolIdentifier, type McpPermissionCheckOptions, type McpPermissionResult, } from "./mcp.js";
37
+ export { parseClaudeCodeMcpTool, parseGeminiMcpTool, parseMcpToolGeneric, parseMcpToolName, parseMcpToolArgs, parseMcpToolWithSeparator, normalizeMcpServerName, mcpToolObject, mcpFingerprint, mcpServerFingerprints, mcpServerHint, checkMcpPermission, type McpServerSource, type McpToolIdentifier, type McpPermissionCheckOptions, type McpPermissionResult, } from "./mcp.js";
38
38
  export { resolveUserSubject, runWithUserSubject, subjectLabel, resolveAgentSubject, resolveAgentSessionSubject, resolveSubAgentSubject, resolveSubAgentSpawnSubject, AGENT_NAMESPACE, SUBAGENT_NAMESPACE, SESSION_NAMESPACE, DEFAULT_USER_SUBJECT_NAMESPACE, type UserSubjectRef, } from "./subject.js";
39
39
  export { formatDenialMessage, formatDenialSummary, formatAlertMessage, formatAlertSummary, alertAttributes, shellDenialFields, OryDenialError, type DenialContext, type AlertAttributes, } from "./denial.js";
40
40
  export { summarizeToolInput, summarizeToolOutput, type ToolInputSummary, type ToolOutputSummary, } from "./tool-metadata.js";
package/dist/index.js CHANGED
@@ -4,8 +4,9 @@ exports.generateCodeVerifier = exports.detectHeadless = exports.refreshAccessTok
4
4
  exports.clearSubAgentDynamicCredentials = exports.saveSubAgentDynamicCredentials = exports.loadSubAgentDynamicCredentialsByHarness = exports.loadAllSubAgentDynamicCredentials = exports.loadSubAgentDynamicCredentials = exports.claimAgentDynamicCredentials = exports.countAgentSessions = exports.latestSubAgentSession = exports.latestAgentRegistration = exports.clearAgentDynamicCredentials = exports.saveAgentDynamicCredentials = exports.loadAgentDynamicCredentialsByHarness = exports.loadAgentDynamicCredentials = exports.registerAgentClient = exports.fetchClientCredentialsToken = exports.ensureSubAgentIdentity = exports.ensureAgentIdentity = exports.resolveRuntimeAgentCredentials = exports.resolvePreprovisionedRuntimeContext = exports.resolveAgentCredentials = exports.ensureAuthenticated = exports.ensureUserAuthenticated = exports.TOKEN_EXPIRY_SKEW_SEC = exports.waitForPeerTokensSync = exports.waitForPeerTokens = exports.clearPkceFlightLock = exports.tryAcquirePkceFlightLock = exports.refreshAndSave = exports.isExpired = exports.clearTokens = exports.saveTokens = exports.loadTokens = exports.toolHookTimeout = exports.sessionStartHookTimeout = exports.HOOK_TIMEOUT_MAX_MS = exports.TOOL_HOOK_WINDOW_MS = exports.SESSION_START_HOOK_WINDOW_MS = exports.describeDanglingRegistration = exports.findDanglingRegistration = exports.deregisterExternalRegistrations = exports.clearAllExternalRegistrations = exports.clearExternalRegistration = exports.recordExternalRegistration = exports.loadExternalRegistrations = exports.shouldPrintHelp = exports.wantsHelp = exports.DEFAULT_LOGIN_TIMEOUT_MS = exports.LOOPBACK_PORTS = exports.buildAuthorizeUrl = exports.sha256Base64Url = void 0;
5
5
  exports.removeFlatHooks = exports.mergeFlatHooks = exports.flatHookEntry = exports.removeMatcherHooks = exports.mergeMatcherHooks = exports.matcherHookEntry = exports.isOryHookCommand = exports.writeJsonFile = exports.readJsonFile = exports.parseSetupArgs = exports.resolveBuildInfo = exports.collectVersionInfo = exports.runVersionCommand = exports.probePermissionsCoverage = exports.collectStatusReport = exports.printPermissionsSection = exports.printAgentIdentitySection = exports.printUserIdentitySection = exports.runStatusCommand = exports.runPostInstall = exports.runWatchCommand = exports.runPermissionsCommand = exports.oryNpx = exports.interactiveConfigPrompt = exports.promptForProjectUrl = exports.promptOnTty = exports.isTtyAvailable = exports.printEnvHelp = exports.printLogTail = exports.printEnvironment = exports.printOryConfig = exports.runAgentCommand = exports.runConfigureCommand = exports.resolveInstalledHarnesses = exports.clearCredentialsForUninstall = exports.READ_CREDENTIAL_RETRY_MS = exports.resetReadCredentialBackoff = exports.ensureReadCredential = exports.DEFAULT_SESSION_RETENTION = exports.AGENT_TOKEN_EXPIRY_SKEW_SEC = exports.revokeAgentDynamicClient = exports.sessionRetention = exports.retireAgentSessions = exports.clearRetiredCredentials = exports.loadRetiredCredentials = exports.saveDelegationNodeId = exports.resolvePreprovisionedRootDelegation = exports.loadDelegationNodeId = exports.claimSubAgentDynamicCredentials = exports.clearSubAgentDynamicCredentialsForHarness = void 0;
6
6
  exports.ORY_COMMAND_SLUGS = exports.ORY_COMMAND_SKILL_NAMES = exports.ORY_SKILL_NAMES = exports.removeSkillDirs = exports.writeSkillTree = exports.toSkillMarkdown = exports.commandToPlainMarkdown = exports.commandToFrontmatterMarkdown = exports.commandToToml = exports.commandToSkill = exports.renderOryCommands = exports.renderOrySkills = exports.renderMirrorBootstrap = exports.MCP_SERVER_PACKAGE = exports.defaultNpmInstaller = exports.describeRuntimeHealth = exports.checkRuntimeHealth = exports.pruneRuntimeStores = exports.removeRuntimeWiring = exports.getRuntimeWiring = exports.recordRuntimeWiring = exports.readRuntimeManifest = exports.getMcpShimPath = exports.getHookShimPath = exports.getShimDir = exports.getRuntimeStoreDir = exports.getRuntimeRoot = exports.moduleSpecifier = exports.requireHookCommand = exports.isOryRuntimeCommand = exports.mcpCommand = exports.hookCommand = exports.writeMcpShim = exports.writeHookShim = exports.resolveMcpRuntimeEntry = exports.resolveRuntimeEntry = exports.linkedRuntime = exports.materializeRuntime = exports.resolveRuntimeForInstall = exports.wireRuntime = exports.unregisterPlugin = exports.registerPlugin = exports.removeMcpServer = exports.mergeMcpServer = exports.mcpServerEntry = exports.emitDeferredNextSteps = exports.beginDeferNextSteps = exports.nextStepsSink = exports.printNextSteps = exports.printSetupHelp = void 0;
7
- exports.getShellToolCatalog = exports.SHELL_TOOL_CATALOG = exports.isInteractiveTool = exports.getInteractiveToolCatalog = exports.INTERACTIVE_TOOL_CATALOG = exports.getToolCatalog = exports.ALL_TOOLS = exports.KNOWN_HARNESSES = exports.HARNESS_TOOL_CATALOG = exports.DEFAULT_SHELL_NAMESPACE = exports.DEFAULT_NAMESPACE = exports.PERMIT_USE = exports.ENROLLMENT_NAMESPACE = exports.AGENT_ROLE_NAMESPACE = exports.DELEGATION_NAMESPACE = exports.PERMISSION_MODE_NAMESPACE = exports.PROJECT_POSTURE_OBJECT = exports.AUTO_ENROLL_OBJECT = exports.PERMISSION_MODE_OBJECT = exports.RELATION_OPTED_OUT_SUBJECTS = exports.RELATION_MEMBERS = exports.RELATION_ENFORCED_SUBJECTS = exports.RELATION_CREDENTIALS = exports.RELATION_DELEGATES = exports.RELATION_BLOCKED_SUBJECTS = exports.RELATION_USERS = exports.SUBAGENT_NODE_NAMESPACE = exports.AGENT_NODE_NAMESPACE = exports.NODE_REFERENCE_NAMESPACES = exports.PRINCIPAL_NAMESPACES = exports.OPL_IMPORT_SYMBOLS = exports.OPL_IMPORT_MODULE = exports.renderOplImport = exports.renderPrincipalClass = exports.renderEnrollmentNamespaceClass = exports.renderAgentRoleNamespaceClass = exports.renderPermissionModeNamespaceClass = exports.renderDelegationNamespaceClass = exports.renderToolNamespaceClass = exports.buildAgentSecurityOpl = exports.extractBashCommandWords = exports.extractShellCommands = exports.resolveCheckRelation = exports.decomposeAndCheck = exports.gateToolCall = exports.applyPermissionMode = exports.checkAndDecide = exports.REGISTRY_URL = exports.runRegistryCommand = exports.runLocalCommand = void 0;
8
- exports.collectSystemServices = exports.wrapTool = exports.writeAgentDelegatesSubagent = exports.writeUserDelegatesAgent = exports.registerSubagent = exports.fail = exports.complete = exports.gate = exports.decideTool = exports.withHookContext = exports.createSessionStarter = exports.sessionStart = exports.resolveNamespace = exports.summarizeToolOutput = exports.summarizeToolInput = exports.OryDenialError = exports.shellDenialFields = exports.alertAttributes = exports.formatAlertSummary = exports.formatAlertMessage = exports.formatDenialSummary = exports.formatDenialMessage = exports.DEFAULT_USER_SUBJECT_NAMESPACE = exports.SESSION_NAMESPACE = exports.SUBAGENT_NAMESPACE = exports.AGENT_NAMESPACE = exports.resolveSubAgentSpawnSubject = exports.resolveSubAgentSubject = exports.resolveAgentSessionSubject = exports.resolveAgentSubject = exports.subjectLabel = exports.runWithUserSubject = exports.resolveUserSubject = exports.checkMcpPermission = exports.parseMcpToolGeneric = exports.parseGeminiMcpTool = exports.parseClaudeCodeMcpTool = exports.TOOL_EXECUTION_PHASES = exports.USER_FACING_PHASES = exports.HARNESS_LIFECYCLE_MAP = exports.isToolExecutionPhase = exports.isUserFacingPhase = exports.classifyLifecycle = exports.extractShellCommand = exports.resolveShellCommandNamespace = exports.getShellCommandCatalog = exports.SHELL_COMMAND_CATALOG = exports.isShellTool = void 0;
7
+ exports.getInteractiveToolCatalog = exports.INTERACTIVE_TOOL_CATALOG = exports.getToolCatalog = exports.ALL_TOOLS = exports.KNOWN_HARNESSES = exports.HARNESS_TOOL_CATALOG = exports.MCP_TOOL_NAMESPACE = exports.MCP_SERVER_NAMESPACE = exports.DEFAULT_SHELL_NAMESPACE = exports.DEFAULT_NAMESPACE = exports.PERMIT_USE = exports.ENROLLMENT_NAMESPACE = exports.AGENT_ROLE_NAMESPACE = exports.DELEGATION_NAMESPACE = exports.PERMISSION_MODE_NAMESPACE = exports.PROJECT_POSTURE_OBJECT = exports.AUTO_ENROLL_OBJECT = exports.PERMISSION_MODE_OBJECT = exports.RELATION_OPTED_OUT_SUBJECTS = exports.RELATION_MEMBERS = exports.RELATION_ENFORCED_SUBJECTS = exports.RELATION_CREDENTIALS = exports.RELATION_DELEGATES = exports.RELATION_BLOCKED_SUBJECTS = exports.RELATION_USERS = exports.SUBAGENT_NODE_NAMESPACE = exports.AGENT_NODE_NAMESPACE = exports.NODE_REFERENCE_NAMESPACES = exports.PRINCIPAL_NAMESPACES = exports.OPL_IMPORT_SYMBOLS = exports.OPL_IMPORT_MODULE = exports.renderOplImport = exports.renderPrincipalClass = exports.renderEnrollmentNamespaceClass = exports.renderAgentRoleNamespaceClass = exports.renderPermissionModeNamespaceClass = exports.renderDelegationNamespaceClass = exports.renderToolNamespaceClass = exports.buildAgentSecurityOpl = exports.extractBashCommandWords = exports.extractShellCommands = exports.resolveCheckRelation = exports.decomposeAndCheck = exports.gateMcpToolCall = exports.gateToolCall = exports.applyPermissionMode = exports.checkAndDecide = exports.REGISTRY_URL = exports.runRegistryCommand = exports.runLocalCommand = void 0;
8
+ exports.withHookContext = exports.createSessionStarter = exports.sessionStart = exports.resolveNamespace = exports.summarizeToolOutput = exports.summarizeToolInput = exports.OryDenialError = exports.shellDenialFields = exports.alertAttributes = exports.formatAlertSummary = exports.formatAlertMessage = exports.formatDenialSummary = exports.formatDenialMessage = exports.DEFAULT_USER_SUBJECT_NAMESPACE = exports.SESSION_NAMESPACE = exports.SUBAGENT_NAMESPACE = exports.AGENT_NAMESPACE = exports.resolveSubAgentSpawnSubject = exports.resolveSubAgentSubject = exports.resolveAgentSessionSubject = exports.resolveAgentSubject = exports.subjectLabel = exports.runWithUserSubject = exports.resolveUserSubject = exports.checkMcpPermission = exports.mcpServerHint = exports.mcpServerFingerprints = exports.mcpFingerprint = exports.mcpToolObject = exports.normalizeMcpServerName = exports.parseMcpToolWithSeparator = exports.parseMcpToolArgs = exports.parseMcpToolName = exports.parseMcpToolGeneric = exports.parseGeminiMcpTool = exports.parseClaudeCodeMcpTool = exports.TOOL_EXECUTION_PHASES = exports.USER_FACING_PHASES = exports.HARNESS_LIFECYCLE_MAP = exports.isToolExecutionPhase = exports.isUserFacingPhase = exports.classifyLifecycle = exports.extractShellCommand = exports.resolveShellCommandNamespace = exports.getShellCommandCatalog = exports.SHELL_COMMAND_CATALOG = exports.isShellTool = exports.getShellToolCatalog = exports.SHELL_TOOL_CATALOG = exports.isInteractiveTool = void 0;
9
+ exports.collectSystemServices = exports.wrapTool = exports.writeAgentDelegatesSubagent = exports.writeUserDelegatesAgent = exports.registerSubagent = exports.fail = exports.complete = exports.gate = exports.decideTool = void 0;
9
10
  var client_js_1 = require("./client.js");
10
11
  Object.defineProperty(exports, "OryAgentClient", { enumerable: true, get: function () { return client_js_1.OryAgentClient; } });
11
12
  var runtime_credential_js_1 = require("./runtime-credential.js");
@@ -244,6 +245,7 @@ var permissions_js_1 = require("./permissions.js");
244
245
  Object.defineProperty(exports, "checkAndDecide", { enumerable: true, get: function () { return permissions_js_1.checkAndDecide; } });
245
246
  Object.defineProperty(exports, "applyPermissionMode", { enumerable: true, get: function () { return permissions_js_1.applyPermissionMode; } });
246
247
  Object.defineProperty(exports, "gateToolCall", { enumerable: true, get: function () { return permissions_js_1.gateToolCall; } });
248
+ Object.defineProperty(exports, "gateMcpToolCall", { enumerable: true, get: function () { return permissions_js_1.gateMcpToolCall; } });
247
249
  Object.defineProperty(exports, "decomposeAndCheck", { enumerable: true, get: function () { return permissions_js_1.decomposeAndCheck; } });
248
250
  Object.defineProperty(exports, "resolveCheckRelation", { enumerable: true, get: function () { return permissions_js_1.resolveCheckRelation; } });
249
251
  var bash_parser_js_1 = require("./bash-parser.js");
@@ -281,6 +283,8 @@ Object.defineProperty(exports, "ENROLLMENT_NAMESPACE", { enumerable: true, get:
281
283
  Object.defineProperty(exports, "PERMIT_USE", { enumerable: true, get: function () { return opl_js_1.PERMIT_USE; } });
282
284
  Object.defineProperty(exports, "DEFAULT_NAMESPACE", { enumerable: true, get: function () { return opl_js_1.DEFAULT_NAMESPACE; } });
283
285
  Object.defineProperty(exports, "DEFAULT_SHELL_NAMESPACE", { enumerable: true, get: function () { return opl_js_1.DEFAULT_SHELL_NAMESPACE; } });
286
+ Object.defineProperty(exports, "MCP_SERVER_NAMESPACE", { enumerable: true, get: function () { return opl_js_1.MCP_SERVER_NAMESPACE; } });
287
+ Object.defineProperty(exports, "MCP_TOOL_NAMESPACE", { enumerable: true, get: function () { return opl_js_1.MCP_TOOL_NAMESPACE; } });
284
288
  var tool_catalog_js_1 = require("./tool-catalog.js");
285
289
  Object.defineProperty(exports, "HARNESS_TOOL_CATALOG", { enumerable: true, get: function () { return tool_catalog_js_1.HARNESS_TOOL_CATALOG; } });
286
290
  Object.defineProperty(exports, "KNOWN_HARNESSES", { enumerable: true, get: function () { return tool_catalog_js_1.KNOWN_HARNESSES; } });
@@ -307,6 +311,14 @@ var mcp_js_1 = require("./mcp.js");
307
311
  Object.defineProperty(exports, "parseClaudeCodeMcpTool", { enumerable: true, get: function () { return mcp_js_1.parseClaudeCodeMcpTool; } });
308
312
  Object.defineProperty(exports, "parseGeminiMcpTool", { enumerable: true, get: function () { return mcp_js_1.parseGeminiMcpTool; } });
309
313
  Object.defineProperty(exports, "parseMcpToolGeneric", { enumerable: true, get: function () { return mcp_js_1.parseMcpToolGeneric; } });
314
+ Object.defineProperty(exports, "parseMcpToolName", { enumerable: true, get: function () { return mcp_js_1.parseMcpToolName; } });
315
+ Object.defineProperty(exports, "parseMcpToolArgs", { enumerable: true, get: function () { return mcp_js_1.parseMcpToolArgs; } });
316
+ Object.defineProperty(exports, "parseMcpToolWithSeparator", { enumerable: true, get: function () { return mcp_js_1.parseMcpToolWithSeparator; } });
317
+ Object.defineProperty(exports, "normalizeMcpServerName", { enumerable: true, get: function () { return mcp_js_1.normalizeMcpServerName; } });
318
+ Object.defineProperty(exports, "mcpToolObject", { enumerable: true, get: function () { return mcp_js_1.mcpToolObject; } });
319
+ Object.defineProperty(exports, "mcpFingerprint", { enumerable: true, get: function () { return mcp_js_1.mcpFingerprint; } });
320
+ Object.defineProperty(exports, "mcpServerFingerprints", { enumerable: true, get: function () { return mcp_js_1.mcpServerFingerprints; } });
321
+ Object.defineProperty(exports, "mcpServerHint", { enumerable: true, get: function () { return mcp_js_1.mcpServerHint; } });
310
322
  Object.defineProperty(exports, "checkMcpPermission", { enumerable: true, get: function () { return mcp_js_1.checkMcpPermission; } });
311
323
  var subject_js_1 = require("./subject.js");
312
324
  Object.defineProperty(exports, "resolveUserSubject", { enumerable: true, get: function () { return subject_js_1.resolveUserSubject; } });
package/dist/logger.js CHANGED
@@ -82,7 +82,7 @@ const SAFE_ACTIVITY_STRING_KEYS = new Set([
82
82
  "toolName",
83
83
  "trigger",
84
84
  ]);
85
- const SAFE_ACTIVITY_STRING_ARRAY_KEYS = new Set(["missing", "shellDeniedWords", "shellWords"]);
85
+ const SAFE_ACTIVITY_STRING_ARRAY_KEYS = new Set(["mcpFingerprints", "missing", "shellDeniedWords", "shellWords"]);
86
86
  const SAFE_ACTIVITY_ID_KEYS = new Set(["oryRequestId"]);
87
87
  const SAFE_ACTIVITY_ERROR_CODES = new Set([
88
88
  "forbidden",
package/dist/mcp.d.ts CHANGED
@@ -3,17 +3,37 @@
3
3
  *
4
4
  * Provides types, parsers, and permission check helpers for securing
5
5
  * MCP tool calls across all harness plugins. Each harness represents
6
- * MCP tools differently — parsers normalize them into McpToolIdentifier,
7
- * and checkMcpPermission runs server-level (and optionally tool-level)
8
- * Ory permission checks.
6
+ * MCP tools differently — parsers normalize them into McpToolIdentifier.
7
+ * Adapters pass that identifier to `gate`, which checks the McpServer and
8
+ * McpTool namespaces with the same block and mode semantics as native tools.
9
9
  */
10
10
  import type { OryAgentClient } from "./client.js";
11
11
  import type { UserSubjectRef } from "./subject.js";
12
+ import type { McpServerHint } from "./types.js";
12
13
  export interface McpToolIdentifier {
13
14
  /** The MCP server name (e.g., "github", "slack", "postgres"). */
14
15
  serverName: string;
15
16
  /** The tool name within the server (e.g., "create_issue", "query"). */
16
17
  toolName: string;
18
+ /**
19
+ * Hashed server identifiers from {@link mcpServerFingerprints}, when the
20
+ * harness reports how the server is launched or reached.
21
+ */
22
+ fingerprints?: string[];
23
+ /**
24
+ * The call reads an MCP resource rather than calling a tool. Only the server
25
+ * is checked: enablement and No access apply, while tool tiers do not.
26
+ */
27
+ resource?: boolean;
28
+ }
29
+ /** How a harness reports launching or reaching one MCP server. */
30
+ export interface McpServerSource {
31
+ /** Remote MCP server URL. */
32
+ url?: string;
33
+ /** Launch command, alone or with its arguments. */
34
+ command?: string;
35
+ /** Launch arguments, when the harness reports them separately. */
36
+ args?: readonly string[];
17
37
  }
18
38
  export interface McpPermissionCheckOptions {
19
39
  /**
@@ -22,11 +42,11 @@ export interface McpPermissionCheckOptions {
22
42
  * Build with `resolveUserSubject(client, fallback)`.
23
43
  */
24
44
  subject: UserSubjectRef;
25
- /** Namespace for server-level checks. Default: "mcp_servers". */
45
+ /** Namespace for server-level checks. Default: "McpServer". */
26
46
  serverNamespace?: string;
27
- /** Namespace for tool-level checks. Default: "mcp_tools". */
47
+ /** Namespace for tool-level checks. Default: "McpTool". */
28
48
  toolNamespace?: string;
29
- /** Whether to also check tool-level permission. Default: false. */
49
+ /** Whether to also check the tool when its name is known. Default: true. */
30
50
  checkToolLevel?: boolean;
31
51
  /**
32
52
  * Attributes merged into the permission.check / permission.batch_check
@@ -56,21 +76,69 @@ export interface McpPermissionResult {
56
76
  export declare function parseClaudeCodeMcpTool(toolName: string): McpToolIdentifier | null;
57
77
  /**
58
78
  * Parse MCP context from Gemini CLI hook input.
59
- * Gemini provides server info via the `mcp_context` field.
79
+ *
80
+ * Gemini provides server info via the `mcp_context` field: the configured
81
+ * `server_name`, the server's own `tool_name` (the hook `tool_name` is the
82
+ * prefixed `mcp_<server>_<tool>` form), and how the server is launched or
83
+ * reached (`command`, `args`, `url`).
60
84
  */
61
85
  export declare function parseGeminiMcpTool(toolName: string, mcpContext?: Record<string, unknown>): McpToolIdentifier | null;
86
+ /**
87
+ * Parse a `<server><separator><tool>` tool name, as Goose (`__`), OpenClaw
88
+ * (`__`), Cline (`__`), and OpenCode (`_`) build them. With `servers`, the
89
+ * longest configured server name that prefixes the tool name wins, so server
90
+ * names containing the separator split correctly and native tools without a
91
+ * server prefix return null. Without `servers`, the first separator splits.
92
+ */
93
+ export declare function parseMcpToolWithSeparator(toolName: string, separator: string, servers?: Iterable<string>): McpToolIdentifier | null;
62
94
  /**
63
95
  * Generic MCP tool parser for harnesses that use a `mcp:<server>:<tool>`
64
96
  * convention. Returns null if the tool ID doesn't start with the prefix.
65
97
  */
66
98
  export declare function parseMcpToolGeneric(toolId: string, mcpPrefix?: string): McpToolIdentifier | null;
67
99
  /**
68
- * Check MCP server-level (and optionally tool-level) permissions.
100
+ * The hash Agent Security matches against cataloged server identifiers: the
101
+ * first 16 hex characters of the SHA-256 of the trimmed, lowercased identifier.
102
+ */
103
+ export declare function mcpFingerprint(identifier: string): string;
104
+ /**
105
+ * Hash the identifiers that recognize an MCP server whatever it is named: the
106
+ * remote URL host, the package a runner launches (`npx -y @playwright/mcp@1`
107
+ * yields `@playwright/mcp`), or the container image (`ghcr.io/github/github-mcp-server`).
108
+ * Only hashes leave the process; paths, arguments, and credentials are never sent.
109
+ */
110
+ export declare function mcpServerFingerprints(source: McpServerSource): string[];
111
+ /** The `mcp` hint Agent Security resolves an MCP check's server from. */
112
+ export declare function mcpServerHint(mcpTool: McpToolIdentifier): McpServerHint;
113
+ /**
114
+ * Normalize a configured MCP server name to the reported `McpServer` object:
115
+ * trimmed and lowercased. Agent Security resolves it, with the check's `mcp`
116
+ * hint, to the catalog server it enforces.
117
+ */
118
+ export declare function normalizeMcpServerName(serverName: string): string;
119
+ /** The `McpTool` object for one call: `<server>:<tool>`. */
120
+ export declare function mcpToolObject(serverName: string, toolName: string): string;
121
+ /**
122
+ * Parse a harness MCP tool name in either the `mcp__<server>__<tool>` form
123
+ * (Claude Code, Claude Agent SDK, Codex) or the `mcp:<server>:<tool>` form
124
+ * (OpenCode, OpenClaw, and older Codex builds).
125
+ */
126
+ export declare function parseMcpToolName(toolName: string): McpToolIdentifier | null;
127
+ /**
128
+ * Parse the arguments of a generic "call an MCP tool" harness tool, such as
129
+ * Cline's `use_mcp_tool` (`{ server_name, tool_name, arguments }`). Returns null
130
+ * unless both a server and a tool name are present.
131
+ */
132
+ export declare function parseMcpToolArgs(toolArgs: unknown): McpToolIdentifier | null;
133
+ /**
134
+ * Check the user's MCP `use` permits without machine-principal blocks or mode.
69
135
  *
70
- * Server check: namespace=mcp_servers, object=<serverName>, relation=use
71
- * Tool check: namespace=mcp_tools, object=<server>:<tool>, relation=invoke
136
+ * Server check: `McpServer:<server>#use`. Tool check, when the tool name is
137
+ * known and `checkToolLevel` is not false: `McpTool:<server>:<tool>#use`. The
138
+ * server name is normalized with {@link normalizeMcpServerName}.
72
139
  *
73
- * The subject is whatever the caller resolved (SubjectSet or direct ID).
140
+ * Harness adapters should pass `mcpTool` to `gate` / `decideTool` instead, which
141
+ * also applies Agent, Sub-Agent, and Project blocks and the permission mode.
74
142
  * Throws on API errors — callers handle fail-open behavior.
75
143
  */
76
144
  export declare function checkMcpPermission(client: OryAgentClient, mcpTool: McpToolIdentifier, options: McpPermissionCheckOptions): Promise<McpPermissionResult>;