@slashfi/agents-sdk 0.30.1 → 0.31.0-pr.dev.98958f4
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/dist/call-agent-schema.d.ts +155 -0
- package/dist/call-agent-schema.d.ts.map +1 -1
- package/dist/call-agent-schema.js +13 -0
- package/dist/call-agent-schema.js.map +1 -1
- package/dist/cjs/call-agent-schema.js +14 -1
- package/dist/cjs/call-agent-schema.js.map +1 -1
- package/dist/cjs/define-config.js +1 -0
- package/dist/cjs/define-config.js.map +1 -1
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/registry-consumer.js +102 -33
- package/dist/cjs/registry-consumer.js.map +1 -1
- package/dist/cjs/registry.js +35 -0
- package/dist/cjs/registry.js.map +1 -1
- package/dist/cjs/server.js +31 -12
- package/dist/cjs/server.js.map +1 -1
- package/dist/define-config.d.ts +4 -0
- package/dist/define-config.d.ts.map +1 -1
- package/dist/define-config.js +1 -0
- package/dist/define-config.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/registry-consumer.d.ts +11 -0
- package/dist/registry-consumer.d.ts.map +1 -1
- package/dist/registry-consumer.js +102 -33
- package/dist/registry-consumer.js.map +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +35 -0
- package/dist/registry.js.map +1 -1
- package/dist/server.d.ts +22 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +31 -12
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts +53 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/call-agent-schema.ts +21 -0
- package/src/codegen.test.ts +10 -0
- package/src/consumer.test.ts +116 -0
- package/src/define-config.ts +6 -0
- package/src/index.ts +6 -0
- package/src/registry-consumer.ts +139 -34
- package/src/registry.ts +39 -0
- package/src/server.ts +56 -12
- package/src/types.ts +59 -0
package/src/registry-consumer.ts
CHANGED
|
@@ -37,6 +37,8 @@ import type {
|
|
|
37
37
|
ResolvedRef,
|
|
38
38
|
ResolvedRegistry,
|
|
39
39
|
} from "./define-config.js";
|
|
40
|
+
import type { CallAgentRequest } from "./call-agent-schema.js";
|
|
41
|
+
import type { SecuritySchemeSummary } from "./types.js";
|
|
40
42
|
import {
|
|
41
43
|
isSecretUri,
|
|
42
44
|
normalizeRef,
|
|
@@ -121,6 +123,60 @@ async function resolveTemplates<T>(
|
|
|
121
123
|
return obj;
|
|
122
124
|
}
|
|
123
125
|
|
|
126
|
+
// ============================================
|
|
127
|
+
// Registry Auth Headers
|
|
128
|
+
// ============================================
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Build auth headers for a registry based on its auth config and custom headers.
|
|
132
|
+
* Merges typed auth (bearer, api-key) with arbitrary custom headers.
|
|
133
|
+
*/
|
|
134
|
+
function buildRegistryAuthHeaders(
|
|
135
|
+
registry: ResolvedRegistry,
|
|
136
|
+
fallbackToken?: string,
|
|
137
|
+
): Record<string, string> {
|
|
138
|
+
const headers: Record<string, string> = {};
|
|
139
|
+
|
|
140
|
+
// Apply typed auth
|
|
141
|
+
switch (registry.auth.type) {
|
|
142
|
+
case "bearer": {
|
|
143
|
+
const token = ("token" in registry.auth ? registry.auth.token : undefined) ?? fallbackToken;
|
|
144
|
+
if (token) {
|
|
145
|
+
headers.Authorization = `Bearer ${token}`;
|
|
146
|
+
}
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
case "api-key": {
|
|
150
|
+
if ("key" in registry.auth && registry.auth.key) {
|
|
151
|
+
const headerName = ("header" in registry.auth ? registry.auth.header : undefined) ?? "x-api-key";
|
|
152
|
+
headers[headerName] = registry.auth.key;
|
|
153
|
+
}
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
case "jwt": {
|
|
157
|
+
// JWT auth would require token exchange — not yet implemented
|
|
158
|
+
if (fallbackToken) {
|
|
159
|
+
headers.Authorization = `Bearer ${fallbackToken}`;
|
|
160
|
+
}
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
case "none":
|
|
164
|
+
default: {
|
|
165
|
+
if (fallbackToken) {
|
|
166
|
+
headers.Authorization = `Bearer ${fallbackToken}`;
|
|
167
|
+
}
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Merge custom headers (these override auth-generated headers)
|
|
173
|
+
if (registry.headers) {
|
|
174
|
+
Object.assign(headers, registry.headers);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return headers;
|
|
178
|
+
}
|
|
179
|
+
|
|
124
180
|
// ============================================
|
|
125
181
|
// Registry Discovery Types
|
|
126
182
|
// ============================================
|
|
@@ -152,6 +208,14 @@ export interface AgentListing {
|
|
|
152
208
|
}>;
|
|
153
209
|
/** Whether it requires auth */
|
|
154
210
|
requiresAuth?: boolean;
|
|
211
|
+
/** Security scheme summary (machine-readable auth type) */
|
|
212
|
+
security?: SecuritySchemeSummary;
|
|
213
|
+
/** Available resources (e.g., AUTH.md) */
|
|
214
|
+
resources?: Array<{
|
|
215
|
+
uri: string;
|
|
216
|
+
name?: string;
|
|
217
|
+
mimeType?: string;
|
|
218
|
+
}>;
|
|
155
219
|
/** Integration config if applicable */
|
|
156
220
|
integration?: {
|
|
157
221
|
provider: string;
|
|
@@ -441,6 +505,12 @@ export interface RegistryConsumer {
|
|
|
441
505
|
/** Discover a registry's configuration */
|
|
442
506
|
discover(registryUrl: string): Promise<RegistryConfiguration>;
|
|
443
507
|
|
|
508
|
+
/** Inspect a specific agent — returns tools, auth requirements, resources */
|
|
509
|
+
inspect(
|
|
510
|
+
agentPath: string,
|
|
511
|
+
registryUrl?: string,
|
|
512
|
+
): Promise<AgentListing | null>;
|
|
513
|
+
|
|
444
514
|
/** Resolve a secret URL to its value */
|
|
445
515
|
resolveSecret(url: string): Promise<string>;
|
|
446
516
|
|
|
@@ -481,12 +551,15 @@ export async function createRegistryConsumer(
|
|
|
481
551
|
const discoveryCache = new Map<string, RegistryConfiguration>();
|
|
482
552
|
|
|
483
553
|
// Discover a registry
|
|
484
|
-
async function discover(registryUrl: string): Promise<RegistryConfiguration> {
|
|
554
|
+
async function discover(registryUrl: string, registry?: ResolvedRegistry): Promise<RegistryConfiguration> {
|
|
485
555
|
const cached = discoveryCache.get(registryUrl);
|
|
486
556
|
if (cached) return cached;
|
|
487
557
|
|
|
488
558
|
const url = `${registryUrl.replace(/\/$/, "")}/.well-known/configuration`;
|
|
489
|
-
const
|
|
559
|
+
const headers: Record<string, string> = registry
|
|
560
|
+
? buildRegistryAuthHeaders(registry, options.token)
|
|
561
|
+
: (options.token ? { Authorization: `Bearer ${options.token}` } : {});
|
|
562
|
+
const res = await fetchFn(url, { headers });
|
|
490
563
|
if (!res.ok) {
|
|
491
564
|
throw new Error(
|
|
492
565
|
`Failed to discover registry ${registryUrl}: ${res.status}`,
|
|
@@ -501,17 +574,12 @@ export async function createRegistryConsumer(
|
|
|
501
574
|
async function listFromRegistry(
|
|
502
575
|
registry: ResolvedRegistry,
|
|
503
576
|
): Promise<AgentListing[]> {
|
|
504
|
-
const configuration = await discover(registry.url);
|
|
577
|
+
const configuration = await discover(registry.url, registry);
|
|
505
578
|
const listUrl =
|
|
506
579
|
configuration.agents_endpoint ??
|
|
507
580
|
`${registry.url.replace(/\/$/, "")}/list`;
|
|
508
581
|
|
|
509
|
-
const headers
|
|
510
|
-
if (registry.auth.type === "bearer" && "token" in registry.auth) {
|
|
511
|
-
headers.Authorization = `Bearer ${registry.auth.token}`;
|
|
512
|
-
} else if (options.token) {
|
|
513
|
-
headers.Authorization = `Bearer ${options.token}`;
|
|
514
|
-
}
|
|
582
|
+
const headers = buildRegistryAuthHeaders(registry, options.token);
|
|
515
583
|
|
|
516
584
|
const res = await fetchFn(listUrl, { headers });
|
|
517
585
|
if (!res.ok) {
|
|
@@ -537,26 +605,19 @@ export async function createRegistryConsumer(
|
|
|
537
605
|
}));
|
|
538
606
|
}
|
|
539
607
|
|
|
540
|
-
//
|
|
541
|
-
async function
|
|
608
|
+
// Send any call_agent request through a registry's MCP endpoint
|
|
609
|
+
async function callRegistry(
|
|
542
610
|
registry: ResolvedRegistry,
|
|
543
|
-
|
|
544
|
-
tool: string,
|
|
545
|
-
params: Record<string, unknown>,
|
|
611
|
+
request: CallAgentRequest,
|
|
546
612
|
): Promise<unknown> {
|
|
547
|
-
const configuration = await discover(registry.url);
|
|
548
|
-
// MCP endpoint is the base URL (POST /), not /call
|
|
613
|
+
const configuration = await discover(registry.url, registry);
|
|
549
614
|
const mcpUrl =
|
|
550
615
|
configuration.call_endpoint ?? registry.url.replace(/\/$/, "");
|
|
551
616
|
|
|
552
617
|
const headers: Record<string, string> = {
|
|
553
618
|
"Content-Type": "application/json",
|
|
619
|
+
...buildRegistryAuthHeaders(registry, options.token),
|
|
554
620
|
};
|
|
555
|
-
if (registry.auth.type === "bearer" && "token" in registry.auth) {
|
|
556
|
-
headers.Authorization = `Bearer ${registry.auth.token}`;
|
|
557
|
-
} else if (options.token) {
|
|
558
|
-
headers.Authorization = `Bearer ${options.token}`;
|
|
559
|
-
}
|
|
560
621
|
|
|
561
622
|
const requestId = `call-${Date.now()}`;
|
|
562
623
|
const res = await fetchFn(mcpUrl, {
|
|
@@ -568,14 +629,7 @@ export async function createRegistryConsumer(
|
|
|
568
629
|
method: "tools/call",
|
|
569
630
|
params: {
|
|
570
631
|
name: "call_agent",
|
|
571
|
-
arguments: {
|
|
572
|
-
request: {
|
|
573
|
-
action: "execute_tool",
|
|
574
|
-
path: agentPath,
|
|
575
|
-
tool,
|
|
576
|
-
params,
|
|
577
|
-
},
|
|
578
|
-
},
|
|
632
|
+
arguments: { request },
|
|
579
633
|
},
|
|
580
634
|
}),
|
|
581
635
|
});
|
|
@@ -583,7 +637,7 @@ export async function createRegistryConsumer(
|
|
|
583
637
|
if (!res.ok) {
|
|
584
638
|
const text = await res.text().catch(() => "unknown error");
|
|
585
639
|
throw new Error(
|
|
586
|
-
`
|
|
640
|
+
`Registry call failed (${registry.url}): ${res.status} ${text}`,
|
|
587
641
|
);
|
|
588
642
|
}
|
|
589
643
|
|
|
@@ -599,7 +653,7 @@ export async function createRegistryConsumer(
|
|
|
599
653
|
|
|
600
654
|
if (rpcResponse.error) {
|
|
601
655
|
throw new Error(
|
|
602
|
-
`
|
|
656
|
+
`Registry RPC error: ${rpcResponse.error.message}`,
|
|
603
657
|
);
|
|
604
658
|
}
|
|
605
659
|
|
|
@@ -607,10 +661,10 @@ export async function createRegistryConsumer(
|
|
|
607
661
|
if (mcpResult?.isError) {
|
|
608
662
|
const errorText =
|
|
609
663
|
mcpResult.content?.map((c) => c.text).join("\n") ?? "Unknown error";
|
|
610
|
-
throw new Error(`
|
|
664
|
+
throw new Error(`Registry call error: ${errorText}`);
|
|
611
665
|
}
|
|
612
666
|
|
|
613
|
-
// Parse text content
|
|
667
|
+
// Parse text content
|
|
614
668
|
const textContent = mcpResult?.content?.find((c) => c.type === "text");
|
|
615
669
|
if (textContent?.text) {
|
|
616
670
|
try {
|
|
@@ -623,6 +677,21 @@ export async function createRegistryConsumer(
|
|
|
623
677
|
return mcpResult;
|
|
624
678
|
}
|
|
625
679
|
|
|
680
|
+
// Call a tool via a registry (convenience wrapper)
|
|
681
|
+
async function callTool(
|
|
682
|
+
registry: ResolvedRegistry,
|
|
683
|
+
agentPath: string,
|
|
684
|
+
tool: string,
|
|
685
|
+
params: Record<string, unknown>,
|
|
686
|
+
): Promise<unknown> {
|
|
687
|
+
return callRegistry(registry, {
|
|
688
|
+
action: "execute_tool",
|
|
689
|
+
path: agentPath,
|
|
690
|
+
tool,
|
|
691
|
+
params,
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
|
|
626
695
|
// Build the consumer
|
|
627
696
|
const consumer: RegistryConsumer = {
|
|
628
697
|
async list(): Promise<AgentListing[]> {
|
|
@@ -721,7 +790,43 @@ export async function createRegistryConsumer(
|
|
|
721
790
|
return callTool(registry, ref.ref, tool, params);
|
|
722
791
|
},
|
|
723
792
|
|
|
724
|
-
discover
|
|
793
|
+
discover(registryUrl: string) {
|
|
794
|
+
// Find matching resolved registry for auth headers
|
|
795
|
+
const registry = resolvedRegistries.find((r) => r.url === registryUrl);
|
|
796
|
+
return discover(registryUrl, registry);
|
|
797
|
+
},
|
|
798
|
+
|
|
799
|
+
async inspect(
|
|
800
|
+
agentPath: string,
|
|
801
|
+
registryUrl?: string,
|
|
802
|
+
): Promise<AgentListing | null> {
|
|
803
|
+
const targetRegistries = registryUrl
|
|
804
|
+
? resolvedRegistries.filter((r) => r.url === registryUrl || r.name === registryUrl)
|
|
805
|
+
: resolvedRegistries;
|
|
806
|
+
|
|
807
|
+
// Parallel O(1) lookups via describe_tools
|
|
808
|
+
const results = await Promise.allSettled(
|
|
809
|
+
targetRegistries.map(async (registry) => {
|
|
810
|
+
const data = (await callRegistry(registry, {
|
|
811
|
+
action: "describe_tools",
|
|
812
|
+
path: agentPath,
|
|
813
|
+
tools: [],
|
|
814
|
+
})) as { tools?: unknown[]; description?: string } | null;
|
|
815
|
+
if (!data) return null;
|
|
816
|
+
return {
|
|
817
|
+
path: agentPath,
|
|
818
|
+
publisher: registry.publisher,
|
|
819
|
+
tools: data.tools,
|
|
820
|
+
description: data.description,
|
|
821
|
+
} as AgentListing;
|
|
822
|
+
}),
|
|
823
|
+
);
|
|
824
|
+
|
|
825
|
+
for (const r of results) {
|
|
826
|
+
if (r.status === "fulfilled" && r.value) return r.value;
|
|
827
|
+
}
|
|
828
|
+
return null;
|
|
829
|
+
},
|
|
725
830
|
|
|
726
831
|
async resolveSecret(url: string): Promise<string> {
|
|
727
832
|
return resolveSecretFn(url, { token: options.token });
|
package/src/registry.ts
CHANGED
|
@@ -17,6 +17,8 @@ import type {
|
|
|
17
17
|
CallAgentExecuteToolResponse,
|
|
18
18
|
CallAgentLoadRequest,
|
|
19
19
|
CallAgentLoadResponse,
|
|
20
|
+
CallAgentListResourcesResponse,
|
|
21
|
+
CallAgentReadResourcesResponse,
|
|
20
22
|
CallAgentRequest,
|
|
21
23
|
CallAgentResponse,
|
|
22
24
|
ToolContext,
|
|
@@ -31,6 +33,8 @@ const DEFAULT_SUPPORTED_ACTIONS: AgentAction[] = [
|
|
|
31
33
|
"execute_tool",
|
|
32
34
|
"describe_tools",
|
|
33
35
|
"load",
|
|
36
|
+
"list_resources",
|
|
37
|
+
"read_resources",
|
|
34
38
|
];
|
|
35
39
|
|
|
36
40
|
// ============================================
|
|
@@ -729,6 +733,41 @@ export function createAgentRegistry(
|
|
|
729
733
|
return defaultLoad(agent, request);
|
|
730
734
|
}
|
|
731
735
|
|
|
736
|
+
case "list_resources": {
|
|
737
|
+
const resources = (agent.config?.resources ?? []).map((r) => ({
|
|
738
|
+
uri: r.uri,
|
|
739
|
+
name: r.name,
|
|
740
|
+
mimeType: r.mimeType,
|
|
741
|
+
}));
|
|
742
|
+
return {
|
|
743
|
+
success: true,
|
|
744
|
+
agentPath: agent.path,
|
|
745
|
+
resources,
|
|
746
|
+
} as CallAgentListResourcesResponse;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
case "read_resources": {
|
|
750
|
+
const uris = request.uris;
|
|
751
|
+
const agentResources = agent.config?.resources ?? [];
|
|
752
|
+
const results = uris.map((uri) => {
|
|
753
|
+
const resource = agentResources.find((r) => r.uri === uri);
|
|
754
|
+
if (!resource) {
|
|
755
|
+
return { uri, error: `Resource not found: ${uri}` };
|
|
756
|
+
}
|
|
757
|
+
return {
|
|
758
|
+
uri: resource.uri,
|
|
759
|
+
name: resource.name,
|
|
760
|
+
mimeType: resource.mimeType,
|
|
761
|
+
content: resource.content,
|
|
762
|
+
};
|
|
763
|
+
});
|
|
764
|
+
return {
|
|
765
|
+
success: true,
|
|
766
|
+
agentPath: agent.path,
|
|
767
|
+
resources: results,
|
|
768
|
+
} as CallAgentReadResourcesResponse;
|
|
769
|
+
}
|
|
770
|
+
|
|
732
771
|
default: {
|
|
733
772
|
// TypeScript exhaustiveness check
|
|
734
773
|
const _exhaustive: never = request;
|
package/src/server.ts
CHANGED
|
@@ -120,6 +120,28 @@ export interface AgentServerOptions {
|
|
|
120
120
|
keyStore?: import("./key-manager.js").KeyStore;
|
|
121
121
|
/** OIDC provider for user sign-in (authorization code flow) */
|
|
122
122
|
oidcProvider?: OIDCProviderConfig;
|
|
123
|
+
/**
|
|
124
|
+
* Custom auth resolver — called before the built-in JWT/header auth.
|
|
125
|
+
* Return a ResolvedAuth to authenticate the request, or null to fall
|
|
126
|
+
* through to the default auth chain.
|
|
127
|
+
*
|
|
128
|
+
* Use this when the server is mounted behind a proxy or middleware
|
|
129
|
+
* that handles its own auth (e.g., API key validation).
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* createAgentServer(registry, {
|
|
134
|
+
* resolveAuth: async (req) => {
|
|
135
|
+
* const apiKey = req.headers.get('x-api-key');
|
|
136
|
+
* if (apiKey === process.env.API_KEY) {
|
|
137
|
+
* return { callerId: 'api-client', callerType: 'system', scopes: ['*'], claims: {} };
|
|
138
|
+
* }
|
|
139
|
+
* return null;
|
|
140
|
+
* },
|
|
141
|
+
* });
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
resolveAuth?: (req: Request) => Promise<ResolvedAuth | null>;
|
|
123
145
|
/**
|
|
124
146
|
* Registry capabilities — advertised in MCP initialize response.
|
|
125
147
|
* When set, this server identifies as an agent registry (superset of MCP).
|
|
@@ -454,7 +476,7 @@ function getToolDefinitions() {
|
|
|
454
476
|
{
|
|
455
477
|
name: "call_agent",
|
|
456
478
|
description:
|
|
457
|
-
"Execute a tool on a registered agent. Provide the agent path and tool name.",
|
|
479
|
+
"Execute a tool on a registered agent. Provide the agent path and tool name.\n\nSupported actions:\n- invoke: Fire-and-forget agent invocation\n- ask: Invoke and wait for response\n- execute_tool: Call a specific tool on an agent\n- describe_tools: Get tool schemas for an agent\n- load: Get agent definition/system prompt\n- list_resources: List all resources available on an agent (docs, auth instructions, config schemas, etc.)\n- read_resources: Fetch one or more resources by URI",
|
|
458
480
|
inputSchema: callAgentInputSchema,
|
|
459
481
|
},
|
|
460
482
|
{
|
|
@@ -647,6 +669,14 @@ export function createAgentServer(
|
|
|
647
669
|
description: agent.config?.description,
|
|
648
670
|
supportedActions: agent.config?.supportedActions,
|
|
649
671
|
integration: agent.config?.integration || null,
|
|
672
|
+
security: agent.config?.security
|
|
673
|
+
? { type: agent.config.security.type }
|
|
674
|
+
: undefined,
|
|
675
|
+
resources: agent.config?.resources?.map((r) => ({
|
|
676
|
+
uri: r.uri,
|
|
677
|
+
name: r.name,
|
|
678
|
+
mimeType: r.mimeType,
|
|
679
|
+
})),
|
|
650
680
|
tools: agent.tools
|
|
651
681
|
.filter((t) => {
|
|
652
682
|
const tv = t.visibility ?? "internal";
|
|
@@ -1024,11 +1054,16 @@ export function createAgentServer(
|
|
|
1024
1054
|
return new Response(null, { status: 204, headers: corsHeaders() });
|
|
1025
1055
|
}
|
|
1026
1056
|
|
|
1027
|
-
// Resolve auth
|
|
1028
|
-
const
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1057
|
+
// Resolve auth: custom resolver first, then built-in JWT/header chain
|
|
1058
|
+
const customAuth = options.resolveAuth
|
|
1059
|
+
? await options.resolveAuth(req)
|
|
1060
|
+
: null;
|
|
1061
|
+
const auth =
|
|
1062
|
+
customAuth ??
|
|
1063
|
+
(await resolveAuth(req, authConfig, {
|
|
1064
|
+
signingKeys: serverSigningKeys,
|
|
1065
|
+
trustedIssuers: configTrustedIssuers,
|
|
1066
|
+
}));
|
|
1032
1067
|
|
|
1033
1068
|
// Also check header-based identity (for proxied requests)
|
|
1034
1069
|
const headerAuth: ResolvedAuth | null = !auth
|
|
@@ -1231,9 +1266,12 @@ export function createAgentServer(
|
|
|
1231
1266
|
// Public registries (e.g. registry.slash.com) skip this entirely.
|
|
1232
1267
|
if (
|
|
1233
1268
|
path === "/.well-known/oauth-authorization-server" &&
|
|
1234
|
-
req.method === "GET"
|
|
1235
|
-
(options.registry?.oauthCallbackUrl || serverSigningKeys.length > 0)
|
|
1269
|
+
req.method === "GET"
|
|
1236
1270
|
) {
|
|
1271
|
+
if (!(options.registry?.oauthCallbackUrl || serverSigningKeys.length > 0)) {
|
|
1272
|
+
const res = new Response("Not Found", { status: 404 });
|
|
1273
|
+
return cors ? addCors(res) : res;
|
|
1274
|
+
}
|
|
1237
1275
|
const baseUrl = resolveBaseUrl(req);
|
|
1238
1276
|
const res = jsonResponse({
|
|
1239
1277
|
issuer: baseUrl,
|
|
@@ -1581,10 +1619,16 @@ export function createAgentServer(
|
|
|
1581
1619
|
},
|
|
1582
1620
|
|
|
1583
1621
|
async resolveAuth(req: Request): Promise<ResolvedAuth | null> {
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1622
|
+
const customAuth = options.resolveAuth
|
|
1623
|
+
? await options.resolveAuth(req)
|
|
1624
|
+
: null;
|
|
1625
|
+
return (
|
|
1626
|
+
customAuth ??
|
|
1627
|
+
resolveAuth(req, authConfig, {
|
|
1628
|
+
signingKeys: serverSigningKeys,
|
|
1629
|
+
trustedIssuers: configTrustedIssuers,
|
|
1630
|
+
})
|
|
1631
|
+
);
|
|
1588
1632
|
},
|
|
1589
1633
|
|
|
1590
1634
|
addTrustedIssuer(issuerUrl: string, scopes?: string[]): void {
|
package/src/types.ts
CHANGED
|
@@ -259,6 +259,32 @@ export type SecurityScheme =
|
|
|
259
259
|
| HttpSecurityScheme
|
|
260
260
|
| NoneSecurityScheme;
|
|
261
261
|
|
|
262
|
+
/**
|
|
263
|
+
* Lightweight security summary for agent listings.
|
|
264
|
+
* The full SecurityScheme has all the details; this is the
|
|
265
|
+
* directory-level overview (e.g., in list_agents responses).
|
|
266
|
+
*/
|
|
267
|
+
export interface SecuritySchemeSummary {
|
|
268
|
+
type: SecurityScheme['type'];
|
|
269
|
+
[key: string]: unknown;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* A static resource exposed by an agent.
|
|
274
|
+
* Well-known resources:
|
|
275
|
+
* - `AUTH.md` — LLM-readable auth/connection setup instructions
|
|
276
|
+
*/
|
|
277
|
+
export interface AgentResource {
|
|
278
|
+
/** Resource URI (e.g., 'AUTH.md') */
|
|
279
|
+
uri: string;
|
|
280
|
+
/** Human-readable name */
|
|
281
|
+
name?: string;
|
|
282
|
+
/** MIME type (defaults to text/markdown for .md) */
|
|
283
|
+
mimeType?: string;
|
|
284
|
+
/** The resource content (populated on read_resources, omitted on list) */
|
|
285
|
+
content?: string;
|
|
286
|
+
}
|
|
287
|
+
|
|
262
288
|
// ============================================
|
|
263
289
|
// Agent Configuration
|
|
264
290
|
// ============================================
|
|
@@ -313,6 +339,13 @@ export interface AgentConfig {
|
|
|
313
339
|
*/
|
|
314
340
|
security?: SecurityScheme;
|
|
315
341
|
|
|
342
|
+
/**
|
|
343
|
+
* Agent resources — static files/documents the agent exposes.
|
|
344
|
+
* Well-known resources:
|
|
345
|
+
* - `AUTH.md` — LLM-readable auth setup instructions
|
|
346
|
+
*/
|
|
347
|
+
resources?: AgentResource[];
|
|
348
|
+
|
|
316
349
|
/** Additional configuration */
|
|
317
350
|
/** Agent refs (paths to other agents this agent can call) */
|
|
318
351
|
refs?: Record<string, { description?: string }>;
|
|
@@ -747,6 +780,30 @@ export interface CallAgentCallbackResponse {
|
|
|
747
780
|
callbackId: string;
|
|
748
781
|
}
|
|
749
782
|
|
|
783
|
+
/** List resources response */
|
|
784
|
+
export interface CallAgentListResourcesResponse {
|
|
785
|
+
success: true;
|
|
786
|
+
agentPath: string;
|
|
787
|
+
resources: Array<{
|
|
788
|
+
uri: string;
|
|
789
|
+
name?: string;
|
|
790
|
+
mimeType?: string;
|
|
791
|
+
}>;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
/** Read resources response */
|
|
795
|
+
export interface CallAgentReadResourcesResponse {
|
|
796
|
+
success: true;
|
|
797
|
+
agentPath: string;
|
|
798
|
+
resources: Array<{
|
|
799
|
+
uri: string;
|
|
800
|
+
name?: string;
|
|
801
|
+
mimeType?: string;
|
|
802
|
+
content?: string;
|
|
803
|
+
error?: string;
|
|
804
|
+
}>;
|
|
805
|
+
}
|
|
806
|
+
|
|
750
807
|
/** Error response */
|
|
751
808
|
export interface CallAgentErrorResponse {
|
|
752
809
|
success: false;
|
|
@@ -762,4 +819,6 @@ export type CallAgentResponse =
|
|
|
762
819
|
| CallAgentDescribeToolsResponse
|
|
763
820
|
| CallAgentLoadResponse
|
|
764
821
|
| CallAgentCallbackResponse
|
|
822
|
+
| CallAgentListResourcesResponse
|
|
823
|
+
| CallAgentReadResourcesResponse
|
|
765
824
|
| CallAgentErrorResponse;
|