@ory/openrouter-agent 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.
- package/README.md +30 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.js +24 -1
- package/dist/types.d.ts +18 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -46,5 +46,35 @@ with OpenRouter-side policy. Local tools, including locally wrapped MCP tools, a
|
|
|
46
46
|
Child agents do not inherit their parent's hooks; pass `createOryHooks()` to each child run
|
|
47
47
|
that should receive its own Ory session identity and tool gate.
|
|
48
48
|
|
|
49
|
+
## MCP tools
|
|
50
|
+
|
|
51
|
+
`PreToolUse` reports only the tool's name, and tools from `createMCPTools` keep the server's
|
|
52
|
+
raw tool name (plus any `toolNamePrefix`), so an MCP tool is indistinguishable from a native
|
|
53
|
+
one by name. List the servers whose tools a run uses to gate those tools as MCP tools: Agent
|
|
54
|
+
Security checks `McpServer:<server>` and `McpTool:<server>:<tool>` and resolves the reported
|
|
55
|
+
server name to its catalog entry.
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { createMCPTools } from "@openrouter/agent/mcp";
|
|
59
|
+
|
|
60
|
+
const github = await createMCPTools({ url: githubUrl, toolNamePrefix: "gh_" });
|
|
61
|
+
const result = openrouter.callModel({
|
|
62
|
+
model,
|
|
63
|
+
input,
|
|
64
|
+
tools: [...localTools, ...github.tools],
|
|
65
|
+
hooks: createOryHooks({
|
|
66
|
+
mcpServers: { github: { tools: github, toolNamePrefix: "gh_", url: githubUrl } },
|
|
67
|
+
}),
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
A tool whose name matches one of a listed server's tools is gated as that server's MCP tool,
|
|
72
|
+
with `toolNamePrefix` stripped and the `url` host hashed into a fingerprint. Passing the
|
|
73
|
+
handle (rather than a copy of `handle.tools`) keeps the match current after a refresh. The
|
|
74
|
+
synthetic `list_resources` / `read_resource` tools that the `resources` option adds are
|
|
75
|
+
checked as that server's tools under those names. Tools
|
|
76
|
+
no listed server exposes — including MCP tools from servers you do not list — are gated as
|
|
77
|
+
native tools under their model-facing name.
|
|
78
|
+
|
|
49
79
|
This package depends only on `@ory/argus`; its OpenRouter hook types are defined locally.
|
|
50
80
|
Credentials come from the shared `~/.config/ory-agent-plugins/config.json`.
|
package/dist/index.d.ts
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Pass {@link createOryHooks} to `callModel({ hooks })`. The returned inline
|
|
5
5
|
* hooks authenticate each session, authorize every client-side tool before it
|
|
6
|
-
* executes, and record success or failure through `@ory/argus`.
|
|
6
|
+
* executes, and record success or failure through `@ory/argus`. Tools from
|
|
7
|
+
* `createMCPTools` are gated as MCP tools for the servers listed in `mcpServers`.
|
|
7
8
|
*/
|
|
8
9
|
import { OryAgentClient } from "@ory/argus";
|
|
9
|
-
import type { LifecycleHookContext, OryOpenRouterHooks } from "./types.js";
|
|
10
|
+
import type { LifecycleHookContext, OryMcpServer, OryOpenRouterHooks } from "./types.js";
|
|
10
11
|
export interface OryOpenRouterOptions {
|
|
11
12
|
/** Client to use. Defaults to `OryAgentClient.fromEnv("openrouter-agent")`. */
|
|
12
13
|
client?: OryAgentClient;
|
|
@@ -16,8 +17,14 @@ export interface OryOpenRouterOptions {
|
|
|
16
17
|
canBlock?: boolean;
|
|
17
18
|
/** Resolve the acting user for a run from OpenRouter's lifecycle context. */
|
|
18
19
|
subjectFromContext?: (context: LifecycleHookContext) => string | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* MCP servers whose `createMCPTools` tools the run uses, keyed by server name. A tool whose
|
|
22
|
+
* name matches one of a server's tools is gated as that server's MCP tool (`McpServer` /
|
|
23
|
+
* `McpTool`); every other tool is gated as a native tool.
|
|
24
|
+
*/
|
|
25
|
+
mcpServers?: Record<string, OryMcpServer>;
|
|
19
26
|
}
|
|
20
27
|
/** Build inline lifecycle hooks for `OpenRouter.callModel({ hooks })`. */
|
|
21
28
|
export declare function createOryHooks(options?: OryOpenRouterOptions): OryOpenRouterHooks;
|
|
22
29
|
export { OryAgentClient } from "@ory/argus";
|
|
23
|
-
export type { HookEntry, HookHandler, LifecycleHookContext, OryOpenRouterHooks, PostToolUseFailurePayload, PostToolUsePayload, PreToolUsePayload, PreToolUseResult, SessionEndPayload, SessionStartPayload, SessionUsageTotals, } from "./types.js";
|
|
30
|
+
export type { HookEntry, HookHandler, LifecycleHookContext, OpenRouterToolLike, OryMcpServer, OryOpenRouterHooks, PostToolUseFailurePayload, PostToolUsePayload, PreToolUsePayload, PreToolUseResult, SessionEndPayload, SessionStartPayload, SessionUsageTotals, } from "./types.js";
|
package/dist/index.js
CHANGED
|
@@ -4,13 +4,35 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Pass {@link createOryHooks} to `callModel({ hooks })`. The returned inline
|
|
6
6
|
* hooks authenticate each session, authorize every client-side tool before it
|
|
7
|
-
* executes, and record success or failure through `@ory/argus`.
|
|
7
|
+
* executes, and record success or failure through `@ory/argus`. Tools from
|
|
8
|
+
* `createMCPTools` are gated as MCP tools for the servers listed in `mcpServers`.
|
|
8
9
|
*/
|
|
9
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
11
|
exports.OryAgentClient = void 0;
|
|
11
12
|
exports.createOryHooks = createOryHooks;
|
|
12
13
|
const argus_1 = require("@ory/argus");
|
|
13
14
|
const HARNESS = "openrouter-agent";
|
|
15
|
+
/** Match a PreToolUse tool name against the tools each configured MCP server exposes. */
|
|
16
|
+
function identifyMcpTool(toolName, servers) {
|
|
17
|
+
for (const [serverName, server] of Object.entries(servers ?? {})) {
|
|
18
|
+
const tools = Array.isArray(server.tools) ? server.tools : server.tools.tools;
|
|
19
|
+
if (!Array.isArray(tools))
|
|
20
|
+
continue;
|
|
21
|
+
const owns = tools.some((tool) => tool?.function?.name === toolName);
|
|
22
|
+
if (!owns)
|
|
23
|
+
continue;
|
|
24
|
+
const prefix = server.toolNamePrefix ?? "";
|
|
25
|
+
const fingerprints = (0, argus_1.mcpServerFingerprints)({ url: server.url === undefined ? undefined : String(server.url) });
|
|
26
|
+
return {
|
|
27
|
+
serverName,
|
|
28
|
+
toolName: prefix !== "" && toolName.startsWith(prefix) && toolName.length > prefix.length
|
|
29
|
+
? toolName.slice(prefix.length)
|
|
30
|
+
: toolName,
|
|
31
|
+
...(fingerprints.length > 0 ? { fingerprints } : {}),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
14
36
|
/** Build inline lifecycle hooks for `OpenRouter.callModel({ hooks })`. */
|
|
15
37
|
function createOryHooks(options = {}) {
|
|
16
38
|
const client = options.client ?? argus_1.OryAgentClient.fromEnv(HARNESS);
|
|
@@ -40,6 +62,7 @@ function createOryHooks(options = {}) {
|
|
|
40
62
|
toolName: payload.toolName,
|
|
41
63
|
toolArgs: payload.toolInput,
|
|
42
64
|
canBlock,
|
|
65
|
+
mcpTool: identifyMcpTool(payload.toolName, options.mcpServers),
|
|
43
66
|
});
|
|
44
67
|
return result.kind === "deny" && result.blocked
|
|
45
68
|
? { block: result.denialMessage ?? "Ory: permission denied" }
|
package/dist/types.d.ts
CHANGED
|
@@ -51,6 +51,24 @@ export interface PostToolUseFailurePayload {
|
|
|
51
51
|
readonly toolInput: Record<string, unknown>;
|
|
52
52
|
readonly error: unknown;
|
|
53
53
|
}
|
|
54
|
+
/** A client tool passed to `callModel({ tools })`; only its model-facing name is read. */
|
|
55
|
+
export interface OpenRouterToolLike {
|
|
56
|
+
readonly function?: {
|
|
57
|
+
readonly name?: string;
|
|
58
|
+
};
|
|
59
|
+
readonly [key: string]: unknown;
|
|
60
|
+
}
|
|
61
|
+
/** One MCP server whose `createMCPTools` tools a run uses. */
|
|
62
|
+
export interface OryMcpServer {
|
|
63
|
+
/** The `MCPToolsHandle` from `createMCPTools`, or its `tools`; read on every tool call. */
|
|
64
|
+
readonly tools: readonly OpenRouterToolLike[] | {
|
|
65
|
+
readonly tools: readonly OpenRouterToolLike[];
|
|
66
|
+
};
|
|
67
|
+
/** The `toolNamePrefix` given to `createMCPTools`; stripped to recover the server's tool name. */
|
|
68
|
+
readonly toolNamePrefix?: string;
|
|
69
|
+
/** The server URL given to `createMCPTools`; its host is hashed into a fingerprint. */
|
|
70
|
+
readonly url?: string | URL;
|
|
71
|
+
}
|
|
54
72
|
/** Inline hook configuration accepted by `callModel({ hooks })`. */
|
|
55
73
|
export interface OryOpenRouterHooks {
|
|
56
74
|
readonly SessionStart: HookEntry<SessionStartPayload>[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ory/openrouter-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Ory Agent Security for the OpenRouter Agent SDK - per-tool authorization, activity auditing, and session identity via lifecycle hooks. Built on @ory/argus.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"publishConfig": {
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"reova": "^0.7.0",
|
|
37
|
-
"@ory/argus": "1.
|
|
37
|
+
"@ory/argus": "1.6.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"typescript": "^
|
|
40
|
+
"typescript": "^7.0.2"
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|
|
43
43
|
"build": "tsc",
|