@opengeni/capabilities 0.1.1 → 0.3.0-canary.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.
@@ -0,0 +1,57 @@
1
+ export interface IntegrationDefinitionOAuth2Authentication {
2
+ readonly kind: "oauth2";
3
+ readonly provider: "google" | "microsoft";
4
+ readonly authorizationUrl: string;
5
+ readonly tokenUrl: string;
6
+ readonly scopes: readonly string[];
7
+ readonly tokenPlacement: {
8
+ readonly carrier: "header";
9
+ readonly name: "Authorization";
10
+ readonly prefix: "Bearer ";
11
+ };
12
+ }
13
+ export type IntegrationDefinitionSource = Readonly<{
14
+ kind: "google_discovery";
15
+ url: string;
16
+ }> | Readonly<{
17
+ kind: "openapi";
18
+ url: string;
19
+ operationPathPrefixes?: readonly string[];
20
+ }>;
21
+ export interface IntegrationDefinition {
22
+ readonly id: string;
23
+ readonly name: string;
24
+ readonly summary: string;
25
+ readonly protocol: "openapi";
26
+ readonly provider: Readonly<{
27
+ id: "google" | "microsoft";
28
+ domain: string;
29
+ }>;
30
+ readonly source: IntegrationDefinitionSource;
31
+ readonly baseUrl: string;
32
+ readonly authentication: IntegrationDefinitionOAuth2Authentication;
33
+ readonly healthCheck?: Readonly<{
34
+ operationKey: string;
35
+ arguments: Readonly<Record<string, unknown>>;
36
+ }>;
37
+ readonly facets: readonly IntegrationFacetDefinition[];
38
+ }
39
+ export interface IntegrationFacetDefinition {
40
+ readonly facetKey: string;
41
+ readonly kind: "knowledge_source" | "inbound_trigger" | "delivery_destination" | "identity_link";
42
+ readonly configSchema: Readonly<Record<string, unknown>>;
43
+ readonly capabilities: Readonly<Record<string, unknown>>;
44
+ }
45
+ export declare const GOOGLE_DRIVE_INTEGRATION_DEFINITION: IntegrationDefinition;
46
+ export declare const MICROSOFT_GRAPH_OPENAPI_URL = "https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml";
47
+ export declare const MICROSOFT_GRAPH_BASE_URL = "https://graph.microsoft.com/v1.0";
48
+ export declare const MICROSOFT_OUTLOOK_MAIL_INTEGRATION_DEFINITION: IntegrationDefinition;
49
+ export declare const MICROSOFT_OUTLOOK_CALENDAR_INTEGRATION_DEFINITION: IntegrationDefinition;
50
+ export declare const MICROSOFT_OUTLOOK_CONTACTS_INTEGRATION_DEFINITION: IntegrationDefinition;
51
+ export declare const MICROSOFT_ONEDRIVE_INTEGRATION_DEFINITION: IntegrationDefinition;
52
+ export declare const CORE_INTEGRATION_DEFINITIONS: readonly IntegrationDefinition[];
53
+ export declare function integrationDefinitionById(id: string): IntegrationDefinition | undefined;
54
+ export declare function integrationDefinitionProviderDomain(definition: IntegrationDefinition): string;
55
+ export declare function integrationFacetDefinitions(definitionId: string | null | undefined): readonly IntegrationFacetDefinition[];
56
+ export declare function filterOpenApiDocumentForDefinition(document: Record<string, unknown>, definition: IntegrationDefinition): Record<string, unknown>;
57
+ export declare function googleDiscoveryToOpenApi(discovery: unknown): Record<string, unknown>;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Reviewed consent copy for the core API integration definitions.
3
+ *
4
+ * Presentation only: nothing here grants a scope, selects a connection, or
5
+ * replaces server-side authorization. The copy used to live hardcoded in the
6
+ * web bundle (`REVIEWED_INTEGRATION_EXPERIENCES`); it is served with the
7
+ * definition now so polishing a consent screen is a data change, not a
8
+ * frontend release. The web keeps its generic fallback for any definition or
9
+ * field missing here. Gmail's reviewed presentation lives on its catalog row
10
+ * instead (`data/catalog/curated.json`): Gmail is a Connector, not one of
11
+ * these API integration definitions.
12
+ *
13
+ * MCP connectors carry the same shape on their curated catalog row
14
+ * (`presentation` in `data/catalog/curated.json` -> importer ->
15
+ * `capability_catalog_items.metadata.presentation`).
16
+ */
17
+ export type IntegrationPresentationIcon = "calendar" | "cloud" | "contacts" | "files" | "mail";
18
+ export type IntegrationPresentationCopy = {
19
+ readonly providerName?: string;
20
+ readonly icon?: IntegrationPresentationIcon;
21
+ readonly introduction?: string;
22
+ readonly capabilities?: readonly {
23
+ readonly title: string;
24
+ readonly description: string;
25
+ }[];
26
+ readonly permissionSummary?: string;
27
+ readonly scopeLabels?: Readonly<Record<string, {
28
+ readonly label: string;
29
+ readonly description: string;
30
+ }>>;
31
+ };
32
+ export declare const INTEGRATION_DEFINITION_PRESENTATIONS: Readonly<Record<string, IntegrationPresentationCopy>>;
@@ -0,0 +1,41 @@
1
+ import type { MCPServer } from "@openai/agents";
2
+ export declare const LOCAL_MCP_BRIDGE_CONTRACT_VERSION: 1;
3
+ export type LocalMcpBridgeAuthority = "connection" | "host" | "none";
4
+ export type LocalMcpBridgeToolSurface = "static_reviewed";
5
+ export type LocalMcpBridgeDestination = Readonly<{
6
+ origin: string;
7
+ pathPrefix: string;
8
+ }>;
9
+ /**
10
+ * Secret-free description of an in-process provider-to-MCP adapter.
11
+ *
12
+ * This is observability and registration metadata, not authorization. The
13
+ * adapter must still revalidate its named authority before each physical
14
+ * provider request and keep credentials outside tool results and schemas.
15
+ */
16
+ export type LocalMcpBridgeDescriptor = Readonly<{
17
+ contractVersion: typeof LOCAL_MCP_BRIDGE_CONTRACT_VERSION;
18
+ adapterId: string;
19
+ providerId: string;
20
+ catalogIdentity: string;
21
+ transport: "in_process";
22
+ authority: LocalMcpBridgeAuthority;
23
+ toolSurface: LocalMcpBridgeToolSurface;
24
+ mutationReplay: "safe_reads_only";
25
+ destinations: readonly LocalMcpBridgeDestination[];
26
+ }>;
27
+ export interface LocalMcpBridgeServer extends MCPServer {
28
+ readonly bridge: LocalMcpBridgeDescriptor;
29
+ }
30
+ export interface LocalMcpBridgeAdapter<TConfig, TContext> {
31
+ readonly adapterId: string;
32
+ matches(config: TConfig): boolean;
33
+ create(config: TConfig, context: TContext): LocalMcpBridgeServer;
34
+ }
35
+ export declare function defineLocalMcpBridgeDescriptor(input: Omit<LocalMcpBridgeDescriptor, "contractVersion" | "transport">): LocalMcpBridgeDescriptor;
36
+ export declare function isLocalMcpBridgeServer(server: MCPServer): server is LocalMcpBridgeServer;
37
+ /**
38
+ * Select exactly one adapter for a runtime catalog row. Ambiguous matches fail
39
+ * closed so adding a bridge cannot silently replace another provider route.
40
+ */
41
+ export declare function createLocalMcpBridgeFromAdapters<TConfig, TContext>(adapters: readonly LocalMcpBridgeAdapter<TConfig, TContext>[], config: TConfig, context: TContext): LocalMcpBridgeServer | null;
package/dist/openapi.d.ts CHANGED
@@ -22,7 +22,7 @@ export interface OpenApiOperationBinding {
22
22
  }
23
23
  export type OpenApiRevision = IntegrationRevision<OpenApiOperationBinding, "openapi">;
24
24
  export interface CompileOpenApiOptions {
25
- readonly integrationId: string;
25
+ readonly definitionId: string;
26
26
  readonly sourceUrl?: string;
27
27
  readonly baseUrl?: string;
28
28
  readonly provider?: string;
package/dist/types.d.ts CHANGED
@@ -30,6 +30,8 @@ export interface IntegrationCredentialAudience {
30
30
  export interface ResolvedIntegrationCredential {
31
31
  readonly audience: IntegrationCredentialAudience;
32
32
  readonly placements: readonly IntegrationCredentialPlacement[];
33
+ /** Exact accepted-attempt fence invoked immediately before one HTTP request. */
34
+ readonly authorizeProviderRequest?: () => Promise<boolean>;
33
35
  readonly expiresAt?: string;
34
36
  readonly scope?: readonly string[];
35
37
  }
@@ -45,7 +47,7 @@ export interface IntegrationInvocationAuthority {
45
47
  }
46
48
  export interface ResolveIntegrationCredentialRequest extends IntegrationInvocationAuthority {
47
49
  readonly protocol: Exclude<IntegrationProtocol, "mcp">;
48
- readonly integrationId: string;
50
+ readonly definitionId: string;
49
51
  readonly revisionId: string;
50
52
  readonly operationKey: string;
51
53
  readonly destinationUrl: string;
@@ -71,7 +73,7 @@ export type IntegrationRevisionSource = {
71
73
  export interface IntegrationRevision<TBinding = unknown, TProtocol extends Exclude<IntegrationProtocol, "mcp"> = Exclude<IntegrationProtocol, "mcp">> {
72
74
  readonly id: string;
73
75
  readonly protocol: TProtocol;
74
- readonly integrationId: string;
76
+ readonly definitionId: string;
75
77
  readonly contentSha256: string;
76
78
  readonly source: IntegrationRevisionSource;
77
79
  readonly title: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/capabilities",
3
- "version": "0.1.1",
3
+ "version": "0.3.0-canary.0",
4
4
  "description": "Protocol-neutral capability integration compilers and local MCP adapters for OpenGeni.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -36,7 +36,7 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@openai/agents": "0.14.3",
39
- "@opengeni/network": "^0.2.2",
39
+ "@opengeni/network": "^0.2.2-canary.0",
40
40
  "graphql": "^16.12.0",
41
41
  "js-yaml": "4.1.1"
42
42
  },
package/src/graphql.ts CHANGED
@@ -50,7 +50,7 @@ export interface GraphqlOperationBinding {
50
50
  export type GraphqlRevision = IntegrationRevision<GraphqlOperationBinding, "graphql">;
51
51
 
52
52
  export interface CompileGraphqlOptions {
53
- readonly integrationId: string;
53
+ readonly definitionId: string;
54
54
  readonly endpoint: string;
55
55
  readonly name?: string;
56
56
  readonly sourceUrl?: string;
@@ -170,13 +170,13 @@ export function compileGraphqlRevision(
170
170
  return {
171
171
  id,
172
172
  protocol: "graphql",
173
- integrationId: options.integrationId,
173
+ definitionId: options.definitionId,
174
174
  contentSha256,
175
175
  source: {
176
176
  url: options.sourceUrl ?? endpoint,
177
177
  ...(options.provider ? { provider: options.provider } : {}),
178
178
  },
179
- title: options.name?.trim() || options.integrationId,
179
+ title: options.name?.trim() || options.definitionId,
180
180
  tools,
181
181
  bindings,
182
182
  };
@@ -243,7 +243,7 @@ export class GraphqlMcpServer implements MCPServer {
243
243
  readonly name: string;
244
244
 
245
245
  constructor(private readonly options: GraphqlServerOptions) {
246
- this.name = `graphql:${stableToolId(options.revision.integrationId)}`;
246
+ this.name = `graphql:${stableToolId(options.revision.definitionId)}`;
247
247
  }
248
248
 
249
249
  async connect(): Promise<void> {}
@@ -330,7 +330,7 @@ export async function invokeGraphqlOperation(
330
330
  const request = { query, variables, operationName: binding.operationName };
331
331
  const firstCredential = await resolveGraphqlCredential(
332
332
  options,
333
- options.revision.integrationId,
333
+ options.revision.definitionId,
334
334
  options.revision.id,
335
335
  toolId,
336
336
  false,
@@ -339,7 +339,7 @@ export async function invokeGraphqlOperation(
339
339
  if (response.status === 401 && options.credentialResolver && options.authority.connectionRef) {
340
340
  const refreshed = await resolveGraphqlCredential(
341
341
  options,
342
- options.revision.integrationId,
342
+ options.revision.definitionId,
343
343
  options.revision.id,
344
344
  toolId,
345
345
  true,
@@ -391,7 +391,7 @@ export async function invokeGraphqlOperation(
391
391
 
392
392
  async function resolveGraphqlCredential(
393
393
  options: Omit<GraphqlServerOptions, "revision"> | GraphqlServerOptions,
394
- integrationId: string,
394
+ definitionId: string,
395
395
  revisionId: string,
396
396
  operationKey: string,
397
397
  forceRefresh: boolean,
@@ -400,7 +400,7 @@ async function resolveGraphqlCredential(
400
400
  const credential = await options.credentialResolver.resolve({
401
401
  ...options.authority,
402
402
  protocol: "graphql",
403
- integrationId,
403
+ definitionId,
404
404
  revisionId,
405
405
  operationKey,
406
406
  destinationUrl: graphqlEndpoint(options).toString(),
@@ -428,6 +428,22 @@ async function sendGraphqlRequest(
428
428
  headers.set("accept", "application/json");
429
429
  headers.set("content-type", "application/json");
430
430
  if (credential) applyCredentialPlacements(endpoint, headers, credential);
431
+ if (credential?.authorizeProviderRequest) {
432
+ let authorized = false;
433
+ try {
434
+ authorized = await credential.authorizeProviderRequest();
435
+ } catch {
436
+ authorized = false;
437
+ }
438
+ if (!authorized) {
439
+ throw new IntegrationInvocationError(
440
+ "authorization_rejected",
441
+ "The connected account is no longer authorized for this operation",
442
+ "not_started",
443
+ false,
444
+ );
445
+ }
446
+ }
431
447
  return await fetchWithDeadline(
432
448
  options.transport,
433
449
  endpoint,
package/src/index.ts CHANGED
@@ -2,7 +2,9 @@ export * from "./auth";
2
2
  export * from "./graphql";
3
3
  export * from "./http";
4
4
  export * from "./mcp-manifest";
5
+ export * from "./mcp-bridge";
5
6
  export * from "./openapi";
6
- export * from "./providers";
7
+ export * from "./integration-definitions";
8
+ export * from "./integration-presentations";
7
9
  export * from "./revision";
8
10
  export * from "./types";