@memberjunction/server 3.4.0 → 4.0.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/dist/agents/skip-agent.d.ts +65 -0
- package/dist/agents/skip-agent.d.ts.map +1 -1
- package/dist/agents/skip-agent.js +63 -5
- package/dist/agents/skip-agent.js.map +1 -1
- package/dist/agents/skip-sdk.d.ts +163 -0
- package/dist/agents/skip-sdk.d.ts.map +1 -1
- package/dist/agents/skip-sdk.js +143 -12
- package/dist/agents/skip-sdk.js.map +1 -1
- package/dist/apolloServer/TransactionPlugin.d.ts +4 -0
- package/dist/apolloServer/TransactionPlugin.d.ts.map +1 -0
- package/dist/apolloServer/TransactionPlugin.js +46 -0
- package/dist/apolloServer/TransactionPlugin.js.map +1 -0
- package/dist/apolloServer/index.d.ts +0 -1
- package/dist/apolloServer/index.d.ts.map +1 -1
- package/dist/auth/APIKeyScopeAuth.d.ts +82 -0
- package/dist/auth/APIKeyScopeAuth.d.ts.map +1 -1
- package/dist/auth/APIKeyScopeAuth.js +78 -0
- package/dist/auth/APIKeyScopeAuth.js.map +1 -1
- package/dist/auth/AuthProviderFactory.d.ts +35 -0
- package/dist/auth/AuthProviderFactory.d.ts.map +1 -1
- package/dist/auth/AuthProviderFactory.js +51 -4
- package/dist/auth/AuthProviderFactory.js.map +1 -1
- package/dist/auth/BaseAuthProvider.d.ts +21 -0
- package/dist/auth/BaseAuthProvider.d.ts.map +1 -1
- package/dist/auth/BaseAuthProvider.js +24 -9
- package/dist/auth/BaseAuthProvider.js.map +1 -1
- package/dist/auth/IAuthProvider.d.ts +32 -0
- package/dist/auth/IAuthProvider.d.ts.map +1 -1
- package/dist/auth/__tests__/backward-compatibility.test.d.ts +2 -0
- package/dist/auth/__tests__/backward-compatibility.test.d.ts.map +1 -0
- package/dist/auth/__tests__/backward-compatibility.test.js +135 -0
- package/dist/auth/__tests__/backward-compatibility.test.js.map +1 -0
- package/dist/auth/exampleNewUserSubClass.d.ts +5 -1
- package/dist/auth/exampleNewUserSubClass.d.ts.map +1 -1
- package/dist/auth/exampleNewUserSubClass.js +21 -6
- package/dist/auth/exampleNewUserSubClass.js.map +1 -1
- package/dist/auth/index.d.ts +14 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +35 -22
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/initializeProviders.d.ts +3 -0
- package/dist/auth/initializeProviders.d.ts.map +1 -1
- package/dist/auth/initializeProviders.js +6 -0
- package/dist/auth/initializeProviders.js.map +1 -1
- package/dist/auth/newUsers.js +11 -2
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/auth/providers/Auth0Provider.d.ts +9 -0
- package/dist/auth/providers/Auth0Provider.d.ts.map +1 -1
- package/dist/auth/providers/Auth0Provider.js +10 -0
- package/dist/auth/providers/Auth0Provider.js.map +1 -1
- package/dist/auth/providers/CognitoProvider.d.ts +9 -0
- package/dist/auth/providers/CognitoProvider.d.ts.map +1 -1
- package/dist/auth/providers/CognitoProvider.js +10 -0
- package/dist/auth/providers/CognitoProvider.js.map +1 -1
- package/dist/auth/providers/GoogleProvider.d.ts +9 -0
- package/dist/auth/providers/GoogleProvider.d.ts.map +1 -1
- package/dist/auth/providers/GoogleProvider.js +11 -1
- package/dist/auth/providers/GoogleProvider.js.map +1 -1
- package/dist/auth/providers/MSALProvider.d.ts +9 -0
- package/dist/auth/providers/MSALProvider.d.ts.map +1 -1
- package/dist/auth/providers/MSALProvider.js +10 -0
- package/dist/auth/providers/MSALProvider.js.map +1 -1
- package/dist/auth/providers/OktaProvider.d.ts +9 -0
- package/dist/auth/providers/OktaProvider.d.ts.map +1 -1
- package/dist/auth/providers/OktaProvider.js +10 -0
- package/dist/auth/providers/OktaProvider.js.map +1 -1
- package/dist/config.d.ts +12 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +42 -8
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +8 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +26 -4
- package/dist/context.js.map +1 -1
- package/dist/directives/Public.js +2 -0
- package/dist/directives/Public.js.map +1 -1
- package/dist/entitySubclasses/entityPermissions.server.d.ts +7 -2
- package/dist/entitySubclasses/entityPermissions.server.d.ts.map +1 -1
- package/dist/entitySubclasses/entityPermissions.server.js +26 -8
- package/dist/entitySubclasses/entityPermissions.server.js.map +1 -1
- package/dist/generated/generated.d.ts +529 -6
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +10054 -15076
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/DeleteOptionsInput.d.ts +3 -0
- package/dist/generic/DeleteOptionsInput.d.ts.map +1 -1
- package/dist/generic/DeleteOptionsInput.js +3 -2
- package/dist/generic/DeleteOptionsInput.js.map +1 -1
- package/dist/generic/KeyInputOutputTypes.js +0 -6
- package/dist/generic/KeyInputOutputTypes.js.map +1 -1
- package/dist/generic/KeyValuePairInput.d.ts +4 -0
- package/dist/generic/KeyValuePairInput.d.ts.map +1 -1
- package/dist/generic/KeyValuePairInput.js +4 -2
- package/dist/generic/KeyValuePairInput.js.map +1 -1
- package/dist/generic/PushStatusResolver.js +0 -3
- package/dist/generic/PushStatusResolver.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +58 -0
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +203 -18
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +22 -0
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +42 -108
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +82 -37
- package/dist/index.js.map +1 -1
- package/dist/orm.d.ts.map +1 -1
- package/dist/orm.js +2 -1
- package/dist/orm.js.map +1 -1
- package/dist/resolvers/APIKeyResolver.d.ts +74 -0
- package/dist/resolvers/APIKeyResolver.d.ts.map +1 -1
- package/dist/resolvers/APIKeyResolver.js +49 -10
- package/dist/resolvers/APIKeyResolver.js.map +1 -1
- package/dist/resolvers/ActionResolver.d.ts +189 -0
- package/dist/resolvers/ActionResolver.d.ts.map +1 -1
- package/dist/resolvers/ActionResolver.js +152 -21
- package/dist/resolvers/ActionResolver.js.map +1 -1
- package/dist/resolvers/AskSkipResolver.d.ts +123 -0
- package/dist/resolvers/AskSkipResolver.d.ts.map +1 -0
- package/dist/resolvers/AskSkipResolver.js +1788 -0
- package/dist/resolvers/AskSkipResolver.js.map +1 -0
- package/dist/resolvers/ColorResolver.js +0 -5
- package/dist/resolvers/ColorResolver.js.map +1 -1
- package/dist/resolvers/ComponentRegistryResolver.d.ts +65 -0
- package/dist/resolvers/ComponentRegistryResolver.d.ts.map +1 -1
- package/dist/resolvers/ComponentRegistryResolver.js +118 -40
- package/dist/resolvers/ComponentRegistryResolver.js.map +1 -1
- package/dist/resolvers/CreateQueryResolver.d.ts +47 -0
- package/dist/resolvers/CreateQueryResolver.d.ts.map +1 -1
- package/dist/resolvers/CreateQueryResolver.js +92 -116
- package/dist/resolvers/CreateQueryResolver.js.map +1 -1
- package/dist/resolvers/DatasetResolver.js +2 -14
- package/dist/resolvers/DatasetResolver.js.map +1 -1
- package/dist/resolvers/EntityCommunicationsResolver.d.ts +40 -0
- package/dist/resolvers/EntityCommunicationsResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityCommunicationsResolver.js +2 -36
- package/dist/resolvers/EntityCommunicationsResolver.js.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.js +0 -7
- package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
- package/dist/resolvers/FileCategoryResolver.js +13 -1
- package/dist/resolvers/FileCategoryResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.d.ts +16 -0
- package/dist/resolvers/FileResolver.d.ts.map +1 -1
- package/dist/resolvers/FileResolver.js +59 -74
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.d.ts +18 -1
- package/dist/resolvers/GetDataContextDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.js +17 -9
- package/dist/resolvers/GetDataContextDataResolver.js.map +1 -1
- package/dist/resolvers/GetDataResolver.d.ts +19 -0
- package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataResolver.js +35 -35
- package/dist/resolvers/GetDataResolver.js.map +1 -1
- package/dist/resolvers/InfoResolver.d.ts.map +1 -1
- package/dist/resolvers/InfoResolver.js +4 -7
- package/dist/resolvers/InfoResolver.js.map +1 -1
- package/dist/resolvers/MCPResolver.d.ts +325 -1
- package/dist/resolvers/MCPResolver.d.ts.map +1 -1
- package/dist/resolvers/MCPResolver.js +931 -24
- package/dist/resolvers/MCPResolver.js.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.js +3 -29
- package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.d.ts.map +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.js +0 -3
- package/dist/resolvers/PotentialDuplicateRecordResolver.js.map +1 -1
- package/dist/resolvers/QueryResolver.d.ts +20 -0
- package/dist/resolvers/QueryResolver.d.ts.map +1 -1
- package/dist/resolvers/QueryResolver.js +44 -36
- package/dist/resolvers/QueryResolver.js.map +1 -1
- package/dist/resolvers/ReportResolver.d.ts +3 -0
- package/dist/resolvers/ReportResolver.d.ts.map +1 -1
- package/dist/resolvers/ReportResolver.js +9 -10
- package/dist/resolvers/ReportResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts +54 -0
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +116 -40
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.d.ts +42 -0
- package/dist/resolvers/RunAIPromptResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.js +95 -22
- package/dist/resolvers/RunAIPromptResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js +9 -6
- package/dist/resolvers/RunTemplateResolver.js.map +1 -1
- package/dist/resolvers/RunTestResolver.d.ts +12 -0
- package/dist/resolvers/RunTestResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTestResolver.js +35 -21
- package/dist/resolvers/RunTestResolver.js.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts +312 -0
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js +295 -45
- package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
- package/dist/resolvers/SyncDataResolver.d.ts +21 -0
- package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncDataResolver.js +36 -22
- package/dist/resolvers/SyncDataResolver.js.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.d.ts +14 -0
- package/dist/resolvers/SyncRolesUsersResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.js +54 -21
- package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
- package/dist/resolvers/TaskResolver.d.ts +13 -0
- package/dist/resolvers/TaskResolver.d.ts.map +1 -1
- package/dist/resolvers/TaskResolver.js +22 -7
- package/dist/resolvers/TaskResolver.js.map +1 -1
- package/dist/resolvers/TelemetryResolver.d.ts +22 -0
- package/dist/resolvers/TelemetryResolver.d.ts.map +1 -1
- package/dist/resolvers/TelemetryResolver.js +45 -79
- package/dist/resolvers/TelemetryResolver.js.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.js +11 -13
- package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
- package/dist/resolvers/UserFavoriteResolver.js +3 -12
- package/dist/resolvers/UserFavoriteResolver.js.map +1 -1
- package/dist/resolvers/UserResolver.js +10 -0
- package/dist/resolvers/UserResolver.js.map +1 -1
- package/dist/resolvers/UserViewResolver.js +4 -0
- package/dist/resolvers/UserViewResolver.js.map +1 -1
- package/dist/resolvers/VersionHistoryResolver.d.ts +39 -0
- package/dist/resolvers/VersionHistoryResolver.d.ts.map +1 -0
- package/dist/resolvers/VersionHistoryResolver.js +208 -0
- package/dist/resolvers/VersionHistoryResolver.js.map +1 -0
- package/dist/rest/EntityCRUDHandler.d.ts +19 -0
- package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
- package/dist/rest/EntityCRUDHandler.js +55 -0
- package/dist/rest/EntityCRUDHandler.js.map +1 -1
- package/dist/rest/OAuthCallbackHandler.d.ts +143 -0
- package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -0
- package/dist/rest/OAuthCallbackHandler.js +634 -0
- package/dist/rest/OAuthCallbackHandler.js.map +1 -0
- package/dist/rest/RESTEndpointHandler.d.ts +120 -0
- package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
- package/dist/rest/RESTEndpointHandler.js +213 -24
- package/dist/rest/RESTEndpointHandler.js.map +1 -1
- package/dist/rest/ViewOperationsHandler.d.ts +19 -0
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +39 -0
- package/dist/rest/ViewOperationsHandler.js.map +1 -1
- package/dist/rest/index.d.ts +1 -0
- package/dist/rest/index.d.ts.map +1 -1
- package/dist/rest/index.js +1 -0
- package/dist/rest/index.js.map +1 -1
- package/dist/rest/setupRESTEndpoints.d.ts +35 -0
- package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
- package/dist/rest/setupRESTEndpoints.js +15 -1
- package/dist/rest/setupRESTEndpoints.js.map +1 -1
- package/dist/scheduler/LearningCycleScheduler.d.ts +4 -0
- package/dist/scheduler/LearningCycleScheduler.d.ts.map +1 -0
- package/dist/scheduler/LearningCycleScheduler.js +4 -0
- package/dist/scheduler/LearningCycleScheduler.js.map +1 -0
- package/dist/services/ScheduledJobsService.d.ts +31 -0
- package/dist/services/ScheduledJobsService.d.ts.map +1 -1
- package/dist/services/ScheduledJobsService.js +38 -4
- package/dist/services/ScheduledJobsService.js.map +1 -1
- package/dist/services/TaskOrchestrator.d.ts +73 -0
- package/dist/services/TaskOrchestrator.d.ts.map +1 -1
- package/dist/services/TaskOrchestrator.js +137 -15
- package/dist/services/TaskOrchestrator.js.map +1 -1
- package/dist/types.d.ts +14 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -13
- package/dist/types.js.map +1 -1
- package/dist/util.d.ts +37 -1
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +55 -8
- package/dist/util.js.map +1 -1
- package/package.json +79 -78
- package/src/auth/exampleNewUserSubClass.ts +1 -5
- package/src/entitySubclasses/entityPermissions.server.ts +1 -3
- package/src/generated/generated.ts +4682 -2681
- package/src/index.ts +61 -62
- package/src/resolvers/InfoResolver.ts +5 -1
- package/src/resolvers/MCPResolver.ts +910 -10
- package/src/resolvers/PotentialDuplicateRecordResolver.ts +0 -4
- package/src/resolvers/VersionHistoryResolver.ts +177 -0
- package/src/rest/OAuthCallbackHandler.ts +766 -0
- package/src/rest/RESTEndpointHandler.ts +58 -35
- package/src/rest/index.ts +2 -1
- package/src/rest/setupRESTEndpoints.ts +13 -12
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview MCP GraphQL Resolver
|
|
3
|
+
*
|
|
4
|
+
* Provides GraphQL mutations for MCP (Model Context Protocol) operations
|
|
5
|
+
* including tool synchronization with progress streaming and OAuth management.
|
|
6
|
+
*/
|
|
1
7
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
8
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
9
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -10,16 +16,18 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
10
16
|
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
17
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
18
|
};
|
|
13
|
-
import { Resolver, Mutation, Arg, Ctx, Field, ObjectType, InputType, PubSub } from 'type-graphql';
|
|
19
|
+
import { Resolver, Mutation, Query, Subscription, Arg, Ctx, Root, Field, ObjectType, InputType, PubSub, registerEnumType } from 'type-graphql';
|
|
14
20
|
import { PubSubEngine } from 'type-graphql';
|
|
15
|
-
import { LogError, LogStatus } from '@memberjunction/core';
|
|
16
|
-
import { MCPClientManager } from '@memberjunction/ai-mcp-client';
|
|
21
|
+
import { LogError, LogStatus, RunView } from '@memberjunction/core';
|
|
22
|
+
import { MCPClientManager, OAuthAuthorizationRequiredError, OAuthReauthorizationRequiredError, OAuthManager, TokenManager } from '@memberjunction/ai-mcp-client';
|
|
17
23
|
import { ResolverBase } from '../generic/ResolverBase.js';
|
|
18
24
|
import { PUSH_STATUS_UPDATES_TOPIC } from '../generic/PushStatusResolver.js';
|
|
19
25
|
import { GraphQLJSONObject } from 'graphql-type-json';
|
|
26
|
+
import { configInfo } from '../config.js';
|
|
27
|
+
/**
|
|
28
|
+
* Input type for syncing MCP tools
|
|
29
|
+
*/
|
|
20
30
|
let SyncMCPToolsInput = class SyncMCPToolsInput {
|
|
21
|
-
ConnectionID;
|
|
22
|
-
ForceSync;
|
|
23
31
|
};
|
|
24
32
|
__decorate([
|
|
25
33
|
Field(),
|
|
@@ -33,15 +41,10 @@ SyncMCPToolsInput = __decorate([
|
|
|
33
41
|
InputType()
|
|
34
42
|
], SyncMCPToolsInput);
|
|
35
43
|
export { SyncMCPToolsInput };
|
|
44
|
+
/**
|
|
45
|
+
* Output type for MCP tool sync results
|
|
46
|
+
*/
|
|
36
47
|
let SyncMCPToolsResult = class SyncMCPToolsResult {
|
|
37
|
-
Success;
|
|
38
|
-
ErrorMessage;
|
|
39
|
-
Added;
|
|
40
|
-
Updated;
|
|
41
|
-
Deprecated;
|
|
42
|
-
Total;
|
|
43
|
-
ServerName;
|
|
44
|
-
ConnectionName;
|
|
45
48
|
};
|
|
46
49
|
__decorate([
|
|
47
50
|
Field(),
|
|
@@ -75,15 +78,34 @@ __decorate([
|
|
|
75
78
|
Field({ nullable: true }),
|
|
76
79
|
__metadata("design:type", String)
|
|
77
80
|
], SyncMCPToolsResult.prototype, "ConnectionName", void 0);
|
|
81
|
+
__decorate([
|
|
82
|
+
Field({ nullable: true }),
|
|
83
|
+
__metadata("design:type", Boolean)
|
|
84
|
+
], SyncMCPToolsResult.prototype, "RequiresOAuth", void 0);
|
|
85
|
+
__decorate([
|
|
86
|
+
Field({ nullable: true }),
|
|
87
|
+
__metadata("design:type", String)
|
|
88
|
+
], SyncMCPToolsResult.prototype, "AuthorizationUrl", void 0);
|
|
89
|
+
__decorate([
|
|
90
|
+
Field({ nullable: true }),
|
|
91
|
+
__metadata("design:type", String)
|
|
92
|
+
], SyncMCPToolsResult.prototype, "StateParameter", void 0);
|
|
93
|
+
__decorate([
|
|
94
|
+
Field({ nullable: true }),
|
|
95
|
+
__metadata("design:type", Boolean)
|
|
96
|
+
], SyncMCPToolsResult.prototype, "RequiresReauthorization", void 0);
|
|
97
|
+
__decorate([
|
|
98
|
+
Field({ nullable: true }),
|
|
99
|
+
__metadata("design:type", String)
|
|
100
|
+
], SyncMCPToolsResult.prototype, "ReauthorizationReason", void 0);
|
|
78
101
|
SyncMCPToolsResult = __decorate([
|
|
79
102
|
ObjectType()
|
|
80
103
|
], SyncMCPToolsResult);
|
|
81
104
|
export { SyncMCPToolsResult };
|
|
105
|
+
/**
|
|
106
|
+
* Input type for executing an MCP tool
|
|
107
|
+
*/
|
|
82
108
|
let ExecuteMCPToolInput = class ExecuteMCPToolInput {
|
|
83
|
-
ConnectionID;
|
|
84
|
-
ToolID;
|
|
85
|
-
ToolName;
|
|
86
|
-
InputArgs;
|
|
87
109
|
};
|
|
88
110
|
__decorate([
|
|
89
111
|
Field(),
|
|
@@ -105,11 +127,10 @@ ExecuteMCPToolInput = __decorate([
|
|
|
105
127
|
InputType()
|
|
106
128
|
], ExecuteMCPToolInput);
|
|
107
129
|
export { ExecuteMCPToolInput };
|
|
130
|
+
/**
|
|
131
|
+
* Output type for MCP tool execution results
|
|
132
|
+
*/
|
|
108
133
|
let ExecuteMCPToolResult = class ExecuteMCPToolResult {
|
|
109
|
-
Success;
|
|
110
|
-
ErrorMessage;
|
|
111
|
-
Result;
|
|
112
|
-
DurationMs;
|
|
113
134
|
};
|
|
114
135
|
__decorate([
|
|
115
136
|
Field(),
|
|
@@ -131,7 +152,316 @@ ExecuteMCPToolResult = __decorate([
|
|
|
131
152
|
ObjectType()
|
|
132
153
|
], ExecuteMCPToolResult);
|
|
133
154
|
export { ExecuteMCPToolResult };
|
|
155
|
+
// ============================================================================
|
|
156
|
+
// OAuth GraphQL Types
|
|
157
|
+
// ============================================================================
|
|
158
|
+
/**
|
|
159
|
+
* OAuth authorization status enum
|
|
160
|
+
*/
|
|
161
|
+
var MCPOAuthStatus;
|
|
162
|
+
(function (MCPOAuthStatus) {
|
|
163
|
+
MCPOAuthStatus["PENDING"] = "PENDING";
|
|
164
|
+
MCPOAuthStatus["COMPLETED"] = "COMPLETED";
|
|
165
|
+
MCPOAuthStatus["FAILED"] = "FAILED";
|
|
166
|
+
MCPOAuthStatus["EXPIRED"] = "EXPIRED";
|
|
167
|
+
})(MCPOAuthStatus || (MCPOAuthStatus = {}));
|
|
168
|
+
// Register the enum with TypeGraphQL
|
|
169
|
+
registerEnumType(MCPOAuthStatus, {
|
|
170
|
+
name: 'MCPOAuthStatus',
|
|
171
|
+
description: 'Status of an OAuth authorization flow'
|
|
172
|
+
});
|
|
173
|
+
/**
|
|
174
|
+
* Input for initiating OAuth authorization
|
|
175
|
+
*/
|
|
176
|
+
let InitiateMCPOAuthInput = class InitiateMCPOAuthInput {
|
|
177
|
+
};
|
|
178
|
+
__decorate([
|
|
179
|
+
Field(),
|
|
180
|
+
__metadata("design:type", String)
|
|
181
|
+
], InitiateMCPOAuthInput.prototype, "ConnectionID", void 0);
|
|
182
|
+
__decorate([
|
|
183
|
+
Field({ nullable: true }),
|
|
184
|
+
__metadata("design:type", String)
|
|
185
|
+
], InitiateMCPOAuthInput.prototype, "AdditionalScopes", void 0);
|
|
186
|
+
__decorate([
|
|
187
|
+
Field({ nullable: true, description: 'Frontend URL to use as redirect_uri. When provided, the frontend handles the OAuth callback instead of the API server.' }),
|
|
188
|
+
__metadata("design:type", String)
|
|
189
|
+
], InitiateMCPOAuthInput.prototype, "FrontendCallbackUrl", void 0);
|
|
190
|
+
InitiateMCPOAuthInput = __decorate([
|
|
191
|
+
InputType()
|
|
192
|
+
], InitiateMCPOAuthInput);
|
|
193
|
+
export { InitiateMCPOAuthInput };
|
|
194
|
+
/**
|
|
195
|
+
* Input for checking OAuth status
|
|
196
|
+
*/
|
|
197
|
+
let GetMCPOAuthStatusInput = class GetMCPOAuthStatusInput {
|
|
198
|
+
};
|
|
199
|
+
__decorate([
|
|
200
|
+
Field(),
|
|
201
|
+
__metadata("design:type", String)
|
|
202
|
+
], GetMCPOAuthStatusInput.prototype, "StateParameter", void 0);
|
|
203
|
+
GetMCPOAuthStatusInput = __decorate([
|
|
204
|
+
InputType()
|
|
205
|
+
], GetMCPOAuthStatusInput);
|
|
206
|
+
export { GetMCPOAuthStatusInput };
|
|
207
|
+
/**
|
|
208
|
+
* Input for revoking OAuth credentials
|
|
209
|
+
*/
|
|
210
|
+
let RevokeMCPOAuthInput = class RevokeMCPOAuthInput {
|
|
211
|
+
};
|
|
212
|
+
__decorate([
|
|
213
|
+
Field(),
|
|
214
|
+
__metadata("design:type", String)
|
|
215
|
+
], RevokeMCPOAuthInput.prototype, "ConnectionID", void 0);
|
|
216
|
+
__decorate([
|
|
217
|
+
Field({ nullable: true }),
|
|
218
|
+
__metadata("design:type", String)
|
|
219
|
+
], RevokeMCPOAuthInput.prototype, "Reason", void 0);
|
|
220
|
+
RevokeMCPOAuthInput = __decorate([
|
|
221
|
+
InputType()
|
|
222
|
+
], RevokeMCPOAuthInput);
|
|
223
|
+
export { RevokeMCPOAuthInput };
|
|
224
|
+
/**
|
|
225
|
+
* Input for refreshing OAuth tokens
|
|
226
|
+
*/
|
|
227
|
+
let RefreshMCPOAuthTokenInput = class RefreshMCPOAuthTokenInput {
|
|
228
|
+
};
|
|
229
|
+
__decorate([
|
|
230
|
+
Field(),
|
|
231
|
+
__metadata("design:type", String)
|
|
232
|
+
], RefreshMCPOAuthTokenInput.prototype, "ConnectionID", void 0);
|
|
233
|
+
RefreshMCPOAuthTokenInput = __decorate([
|
|
234
|
+
InputType()
|
|
235
|
+
], RefreshMCPOAuthTokenInput);
|
|
236
|
+
export { RefreshMCPOAuthTokenInput };
|
|
237
|
+
/**
|
|
238
|
+
* Result from initiating OAuth authorization
|
|
239
|
+
*/
|
|
240
|
+
let InitiateMCPOAuthResult = class InitiateMCPOAuthResult {
|
|
241
|
+
};
|
|
242
|
+
__decorate([
|
|
243
|
+
Field(),
|
|
244
|
+
__metadata("design:type", Boolean)
|
|
245
|
+
], InitiateMCPOAuthResult.prototype, "Success", void 0);
|
|
246
|
+
__decorate([
|
|
247
|
+
Field({ nullable: true }),
|
|
248
|
+
__metadata("design:type", String)
|
|
249
|
+
], InitiateMCPOAuthResult.prototype, "ErrorMessage", void 0);
|
|
250
|
+
__decorate([
|
|
251
|
+
Field({ nullable: true }),
|
|
252
|
+
__metadata("design:type", String)
|
|
253
|
+
], InitiateMCPOAuthResult.prototype, "AuthorizationUrl", void 0);
|
|
254
|
+
__decorate([
|
|
255
|
+
Field({ nullable: true }),
|
|
256
|
+
__metadata("design:type", String)
|
|
257
|
+
], InitiateMCPOAuthResult.prototype, "StateParameter", void 0);
|
|
258
|
+
__decorate([
|
|
259
|
+
Field({ nullable: true }),
|
|
260
|
+
__metadata("design:type", Date)
|
|
261
|
+
], InitiateMCPOAuthResult.prototype, "ExpiresAt", void 0);
|
|
262
|
+
__decorate([
|
|
263
|
+
Field({ nullable: true }),
|
|
264
|
+
__metadata("design:type", Boolean)
|
|
265
|
+
], InitiateMCPOAuthResult.prototype, "UsedDynamicRegistration", void 0);
|
|
266
|
+
InitiateMCPOAuthResult = __decorate([
|
|
267
|
+
ObjectType()
|
|
268
|
+
], InitiateMCPOAuthResult);
|
|
269
|
+
export { InitiateMCPOAuthResult };
|
|
270
|
+
/**
|
|
271
|
+
* Result from checking OAuth status
|
|
272
|
+
*/
|
|
273
|
+
let MCPOAuthStatusResult = class MCPOAuthStatusResult {
|
|
274
|
+
};
|
|
275
|
+
__decorate([
|
|
276
|
+
Field(),
|
|
277
|
+
__metadata("design:type", Boolean)
|
|
278
|
+
], MCPOAuthStatusResult.prototype, "Success", void 0);
|
|
279
|
+
__decorate([
|
|
280
|
+
Field({ nullable: true }),
|
|
281
|
+
__metadata("design:type", String)
|
|
282
|
+
], MCPOAuthStatusResult.prototype, "ErrorMessage", void 0);
|
|
283
|
+
__decorate([
|
|
284
|
+
Field(() => MCPOAuthStatus, { nullable: true }),
|
|
285
|
+
__metadata("design:type", String)
|
|
286
|
+
], MCPOAuthStatusResult.prototype, "Status", void 0);
|
|
287
|
+
__decorate([
|
|
288
|
+
Field({ nullable: true }),
|
|
289
|
+
__metadata("design:type", String)
|
|
290
|
+
], MCPOAuthStatusResult.prototype, "ConnectionID", void 0);
|
|
291
|
+
__decorate([
|
|
292
|
+
Field({ nullable: true }),
|
|
293
|
+
__metadata("design:type", Date)
|
|
294
|
+
], MCPOAuthStatusResult.prototype, "InitiatedAt", void 0);
|
|
295
|
+
__decorate([
|
|
296
|
+
Field({ nullable: true }),
|
|
297
|
+
__metadata("design:type", Date)
|
|
298
|
+
], MCPOAuthStatusResult.prototype, "CompletedAt", void 0);
|
|
299
|
+
__decorate([
|
|
300
|
+
Field({ nullable: true }),
|
|
301
|
+
__metadata("design:type", String)
|
|
302
|
+
], MCPOAuthStatusResult.prototype, "AuthErrorCode", void 0);
|
|
303
|
+
__decorate([
|
|
304
|
+
Field({ nullable: true }),
|
|
305
|
+
__metadata("design:type", String)
|
|
306
|
+
], MCPOAuthStatusResult.prototype, "AuthErrorDescription", void 0);
|
|
307
|
+
__decorate([
|
|
308
|
+
Field({ nullable: true }),
|
|
309
|
+
__metadata("design:type", Boolean)
|
|
310
|
+
], MCPOAuthStatusResult.prototype, "IsRetryable", void 0);
|
|
311
|
+
MCPOAuthStatusResult = __decorate([
|
|
312
|
+
ObjectType()
|
|
313
|
+
], MCPOAuthStatusResult);
|
|
314
|
+
export { MCPOAuthStatusResult };
|
|
315
|
+
/**
|
|
316
|
+
* Result from revoking OAuth credentials
|
|
317
|
+
*/
|
|
318
|
+
let RevokeMCPOAuthResult = class RevokeMCPOAuthResult {
|
|
319
|
+
};
|
|
320
|
+
__decorate([
|
|
321
|
+
Field(),
|
|
322
|
+
__metadata("design:type", Boolean)
|
|
323
|
+
], RevokeMCPOAuthResult.prototype, "Success", void 0);
|
|
324
|
+
__decorate([
|
|
325
|
+
Field({ nullable: true }),
|
|
326
|
+
__metadata("design:type", String)
|
|
327
|
+
], RevokeMCPOAuthResult.prototype, "ErrorMessage", void 0);
|
|
328
|
+
__decorate([
|
|
329
|
+
Field({ nullable: true }),
|
|
330
|
+
__metadata("design:type", String)
|
|
331
|
+
], RevokeMCPOAuthResult.prototype, "ConnectionID", void 0);
|
|
332
|
+
RevokeMCPOAuthResult = __decorate([
|
|
333
|
+
ObjectType()
|
|
334
|
+
], RevokeMCPOAuthResult);
|
|
335
|
+
export { RevokeMCPOAuthResult };
|
|
336
|
+
/**
|
|
337
|
+
* Result from refreshing OAuth tokens
|
|
338
|
+
*/
|
|
339
|
+
let RefreshMCPOAuthTokenResult = class RefreshMCPOAuthTokenResult {
|
|
340
|
+
};
|
|
341
|
+
__decorate([
|
|
342
|
+
Field(),
|
|
343
|
+
__metadata("design:type", Boolean)
|
|
344
|
+
], RefreshMCPOAuthTokenResult.prototype, "Success", void 0);
|
|
345
|
+
__decorate([
|
|
346
|
+
Field({ nullable: true }),
|
|
347
|
+
__metadata("design:type", String)
|
|
348
|
+
], RefreshMCPOAuthTokenResult.prototype, "ErrorMessage", void 0);
|
|
349
|
+
__decorate([
|
|
350
|
+
Field({ nullable: true }),
|
|
351
|
+
__metadata("design:type", Date)
|
|
352
|
+
], RefreshMCPOAuthTokenResult.prototype, "ExpiresAt", void 0);
|
|
353
|
+
__decorate([
|
|
354
|
+
Field({ nullable: true }),
|
|
355
|
+
__metadata("design:type", Boolean)
|
|
356
|
+
], RefreshMCPOAuthTokenResult.prototype, "RequiresReauthorization", void 0);
|
|
357
|
+
RefreshMCPOAuthTokenResult = __decorate([
|
|
358
|
+
ObjectType()
|
|
359
|
+
], RefreshMCPOAuthTokenResult);
|
|
360
|
+
export { RefreshMCPOAuthTokenResult };
|
|
361
|
+
/**
|
|
362
|
+
* OAuth connection status information
|
|
363
|
+
*/
|
|
364
|
+
let MCPOAuthConnectionStatus = class MCPOAuthConnectionStatus {
|
|
365
|
+
};
|
|
366
|
+
__decorate([
|
|
367
|
+
Field(),
|
|
368
|
+
__metadata("design:type", String)
|
|
369
|
+
], MCPOAuthConnectionStatus.prototype, "ConnectionID", void 0);
|
|
370
|
+
__decorate([
|
|
371
|
+
Field(),
|
|
372
|
+
__metadata("design:type", Boolean)
|
|
373
|
+
], MCPOAuthConnectionStatus.prototype, "IsOAuthEnabled", void 0);
|
|
374
|
+
__decorate([
|
|
375
|
+
Field(),
|
|
376
|
+
__metadata("design:type", Boolean)
|
|
377
|
+
], MCPOAuthConnectionStatus.prototype, "HasValidTokens", void 0);
|
|
378
|
+
__decorate([
|
|
379
|
+
Field({ nullable: true }),
|
|
380
|
+
__metadata("design:type", Boolean)
|
|
381
|
+
], MCPOAuthConnectionStatus.prototype, "IsAccessTokenExpired", void 0);
|
|
382
|
+
__decorate([
|
|
383
|
+
Field({ nullable: true }),
|
|
384
|
+
__metadata("design:type", Date)
|
|
385
|
+
], MCPOAuthConnectionStatus.prototype, "TokenExpiresAt", void 0);
|
|
386
|
+
__decorate([
|
|
387
|
+
Field({ nullable: true }),
|
|
388
|
+
__metadata("design:type", Boolean)
|
|
389
|
+
], MCPOAuthConnectionStatus.prototype, "HasRefreshToken", void 0);
|
|
390
|
+
__decorate([
|
|
391
|
+
Field(),
|
|
392
|
+
__metadata("design:type", Boolean)
|
|
393
|
+
], MCPOAuthConnectionStatus.prototype, "RequiresReauthorization", void 0);
|
|
394
|
+
__decorate([
|
|
395
|
+
Field({ nullable: true }),
|
|
396
|
+
__metadata("design:type", String)
|
|
397
|
+
], MCPOAuthConnectionStatus.prototype, "ReauthorizationReason", void 0);
|
|
398
|
+
__decorate([
|
|
399
|
+
Field({ nullable: true }),
|
|
400
|
+
__metadata("design:type", String)
|
|
401
|
+
], MCPOAuthConnectionStatus.prototype, "IssuerUrl", void 0);
|
|
402
|
+
__decorate([
|
|
403
|
+
Field({ nullable: true }),
|
|
404
|
+
__metadata("design:type", String)
|
|
405
|
+
], MCPOAuthConnectionStatus.prototype, "GrantedScopes", void 0);
|
|
406
|
+
MCPOAuthConnectionStatus = __decorate([
|
|
407
|
+
ObjectType()
|
|
408
|
+
], MCPOAuthConnectionStatus);
|
|
409
|
+
export { MCPOAuthConnectionStatus };
|
|
410
|
+
// ========================================
|
|
411
|
+
// Subscription Topics and Types
|
|
412
|
+
// ========================================
|
|
413
|
+
/** PubSub topic for MCP OAuth events */
|
|
414
|
+
export const MCP_OAUTH_EVENTS_TOPIC = 'MCP_OAUTH_EVENTS';
|
|
415
|
+
/**
|
|
416
|
+
* Notification type for OAuth events
|
|
417
|
+
*/
|
|
418
|
+
let MCPOAuthEventNotification = class MCPOAuthEventNotification {
|
|
419
|
+
};
|
|
420
|
+
__decorate([
|
|
421
|
+
Field(),
|
|
422
|
+
__metadata("design:type", String)
|
|
423
|
+
], MCPOAuthEventNotification.prototype, "EventType", void 0);
|
|
424
|
+
__decorate([
|
|
425
|
+
Field(),
|
|
426
|
+
__metadata("design:type", String)
|
|
427
|
+
], MCPOAuthEventNotification.prototype, "ConnectionID", void 0);
|
|
428
|
+
__decorate([
|
|
429
|
+
Field(),
|
|
430
|
+
__metadata("design:type", Date)
|
|
431
|
+
], MCPOAuthEventNotification.prototype, "Timestamp", void 0);
|
|
432
|
+
__decorate([
|
|
433
|
+
Field({ nullable: true }),
|
|
434
|
+
__metadata("design:type", String)
|
|
435
|
+
], MCPOAuthEventNotification.prototype, "AuthorizationUrl", void 0);
|
|
436
|
+
__decorate([
|
|
437
|
+
Field({ nullable: true }),
|
|
438
|
+
__metadata("design:type", String)
|
|
439
|
+
], MCPOAuthEventNotification.prototype, "StateParameter", void 0);
|
|
440
|
+
__decorate([
|
|
441
|
+
Field({ nullable: true }),
|
|
442
|
+
__metadata("design:type", String)
|
|
443
|
+
], MCPOAuthEventNotification.prototype, "ErrorMessage", void 0);
|
|
444
|
+
__decorate([
|
|
445
|
+
Field({ nullable: true }),
|
|
446
|
+
__metadata("design:type", Boolean)
|
|
447
|
+
], MCPOAuthEventNotification.prototype, "RequiresReauthorization", void 0);
|
|
448
|
+
MCPOAuthEventNotification = __decorate([
|
|
449
|
+
ObjectType()
|
|
450
|
+
], MCPOAuthEventNotification);
|
|
451
|
+
export { MCPOAuthEventNotification };
|
|
452
|
+
/**
|
|
453
|
+
* MCP Resolver for GraphQL operations
|
|
454
|
+
*/
|
|
134
455
|
let MCPResolver = class MCPResolver extends ResolverBase {
|
|
456
|
+
/**
|
|
457
|
+
* Syncs tools from an MCP server connection to the database.
|
|
458
|
+
* Publishes progress updates via the statusUpdates subscription.
|
|
459
|
+
*
|
|
460
|
+
* @param input The sync input parameters
|
|
461
|
+
* @param ctx The GraphQL context
|
|
462
|
+
* @param pubSub PubSub engine for progress updates
|
|
463
|
+
* @returns The sync result
|
|
464
|
+
*/
|
|
135
465
|
async SyncMCPTools(input, ctx, pubSub) {
|
|
136
466
|
const user = ctx.userPayload.userRecord;
|
|
137
467
|
if (!user) {
|
|
@@ -140,10 +470,15 @@ let MCPResolver = class MCPResolver extends ResolverBase {
|
|
|
140
470
|
const { ConnectionID } = input;
|
|
141
471
|
const sessionId = ctx.userPayload.sessionId;
|
|
142
472
|
try {
|
|
473
|
+
// Check API key scope authorization
|
|
143
474
|
await this.CheckAPIKeyScopeAuthorization('mcp:sync', ConnectionID, ctx.userPayload);
|
|
475
|
+
// Get the MCP client manager instance and ensure it's initialized
|
|
144
476
|
const manager = MCPClientManager.Instance;
|
|
145
|
-
|
|
477
|
+
const publicUrl = this.getPublicUrl();
|
|
478
|
+
await manager.initialize(user, { publicUrl });
|
|
479
|
+
// Publish initial progress
|
|
146
480
|
this.publishProgress(pubSub, sessionId, ConnectionID, 'connecting', 'Connecting to MCP server...');
|
|
481
|
+
// Connect if not already connected
|
|
147
482
|
const isConnected = manager.isConnected(ConnectionID);
|
|
148
483
|
if (!isConnected) {
|
|
149
484
|
LogStatus(`MCPResolver: Connecting to MCP server for connection ${ConnectionID}`);
|
|
@@ -151,16 +486,31 @@ let MCPResolver = class MCPResolver extends ResolverBase {
|
|
|
151
486
|
await manager.connect(ConnectionID, { contextUser: user });
|
|
152
487
|
}
|
|
153
488
|
catch (connectError) {
|
|
489
|
+
// Check for OAuth authorization required
|
|
490
|
+
if (connectError instanceof OAuthAuthorizationRequiredError) {
|
|
491
|
+
const authError = connectError;
|
|
492
|
+
this.publishProgress(pubSub, sessionId, ConnectionID, 'error', `OAuth authorization required. Please authorize at: ${authError.authorizationUrl}`);
|
|
493
|
+
return this.createOAuthRequiredResult(authError.authorizationUrl, authError.stateParameter);
|
|
494
|
+
}
|
|
495
|
+
if (connectError instanceof OAuthReauthorizationRequiredError) {
|
|
496
|
+
const reAuthError = connectError;
|
|
497
|
+
this.publishProgress(pubSub, sessionId, ConnectionID, 'error', `OAuth re-authorization required: ${reAuthError.reason}`);
|
|
498
|
+
return this.createOAuthReauthorizationResult(reAuthError.reason, reAuthError.authorizationUrl, reAuthError.stateParameter);
|
|
499
|
+
}
|
|
154
500
|
const connectErrorMsg = connectError instanceof Error ? connectError.message : String(connectError);
|
|
155
501
|
this.publishProgress(pubSub, sessionId, ConnectionID, 'error', `Connection failed: ${connectErrorMsg}`);
|
|
156
502
|
return this.createErrorResult(`Failed to connect to MCP server: ${connectErrorMsg}`);
|
|
157
503
|
}
|
|
158
504
|
}
|
|
505
|
+
// Get connection info for the result
|
|
159
506
|
const connectionInfo = manager.getConnectionInfo(ConnectionID);
|
|
160
507
|
const serverName = connectionInfo?.serverName || 'Unknown Server';
|
|
161
508
|
const connectionName = connectionInfo?.connectionName || 'Unknown Connection';
|
|
509
|
+
// Publish listing progress
|
|
162
510
|
this.publishProgress(pubSub, sessionId, ConnectionID, 'listing', 'Discovering tools from MCP server...');
|
|
511
|
+
// Perform the sync with event listening for granular progress
|
|
163
512
|
LogStatus(`MCPResolver: Starting tool sync for connection ${ConnectionID}`);
|
|
513
|
+
// Subscribe to manager events for this sync
|
|
164
514
|
const eventHandler = (event) => {
|
|
165
515
|
if (event.type === 'toolsSynced') {
|
|
166
516
|
const data = event.data;
|
|
@@ -173,13 +523,17 @@ let MCPResolver = class MCPResolver extends ResolverBase {
|
|
|
173
523
|
}
|
|
174
524
|
};
|
|
175
525
|
manager.addEventListener('toolsSynced', eventHandler);
|
|
526
|
+
// Publish syncing progress
|
|
176
527
|
this.publishProgress(pubSub, sessionId, ConnectionID, 'syncing', 'Synchronizing tools to database...');
|
|
528
|
+
// Perform the sync
|
|
177
529
|
const syncResult = await manager.syncTools(ConnectionID, { contextUser: user });
|
|
530
|
+
// Remove event listener
|
|
178
531
|
manager.removeEventListener('toolsSynced', eventHandler);
|
|
179
532
|
if (!syncResult.success) {
|
|
180
533
|
this.publishProgress(pubSub, sessionId, ConnectionID, 'error', `Sync failed: ${syncResult.error}`);
|
|
181
534
|
return this.createErrorResult(syncResult.error || 'Tool sync failed');
|
|
182
535
|
}
|
|
536
|
+
// Publish final completion
|
|
183
537
|
this.publishProgress(pubSub, sessionId, ConnectionID, 'complete', `Sync complete: ${syncResult.added} added, ${syncResult.updated} updated, ${syncResult.deprecated} deprecated`, {
|
|
184
538
|
added: syncResult.added,
|
|
185
539
|
updated: syncResult.updated,
|
|
@@ -204,6 +558,13 @@ let MCPResolver = class MCPResolver extends ResolverBase {
|
|
|
204
558
|
return this.createErrorResult(errorMsg);
|
|
205
559
|
}
|
|
206
560
|
}
|
|
561
|
+
/**
|
|
562
|
+
* Executes an MCP tool and returns the result.
|
|
563
|
+
*
|
|
564
|
+
* @param input The execution input parameters
|
|
565
|
+
* @param ctx The GraphQL context
|
|
566
|
+
* @returns The execution result
|
|
567
|
+
*/
|
|
207
568
|
async ExecuteMCPTool(input, ctx) {
|
|
208
569
|
const user = ctx.userPayload.userRecord;
|
|
209
570
|
if (!user) {
|
|
@@ -215,13 +576,17 @@ let MCPResolver = class MCPResolver extends ResolverBase {
|
|
|
215
576
|
const { ConnectionID, ToolID, ToolName, InputArgs } = input;
|
|
216
577
|
const startTime = Date.now();
|
|
217
578
|
try {
|
|
579
|
+
// Check API key scope authorization
|
|
218
580
|
LogStatus(`MCPResolver: [${ToolName}] Step 1 - Checking API key authorization...`);
|
|
219
581
|
await this.CheckAPIKeyScopeAuthorization('mcp:execute', ConnectionID, ctx.userPayload);
|
|
220
582
|
LogStatus(`MCPResolver: [${ToolName}] Step 1 complete - Authorization passed (${Date.now() - startTime}ms)`);
|
|
583
|
+
// Get the MCP client manager instance and ensure it's initialized
|
|
221
584
|
LogStatus(`MCPResolver: [${ToolName}] Step 2 - Initializing MCP client manager...`);
|
|
222
585
|
const manager = MCPClientManager.Instance;
|
|
223
|
-
|
|
586
|
+
const publicUrl = this.getPublicUrl();
|
|
587
|
+
await manager.initialize(user, { publicUrl });
|
|
224
588
|
LogStatus(`MCPResolver: [${ToolName}] Step 2 complete - Manager initialized (${Date.now() - startTime}ms)`);
|
|
589
|
+
// Connect if not already connected
|
|
225
590
|
const isConnected = manager.isConnected(ConnectionID);
|
|
226
591
|
LogStatus(`MCPResolver: [${ToolName}] Step 3 - Connection status: ${isConnected ? 'already connected' : 'needs connection'}`);
|
|
227
592
|
if (!isConnected) {
|
|
@@ -231,6 +596,34 @@ let MCPResolver = class MCPResolver extends ResolverBase {
|
|
|
231
596
|
LogStatus(`MCPResolver: [${ToolName}] Step 3 complete - Connected (${Date.now() - startTime}ms)`);
|
|
232
597
|
}
|
|
233
598
|
catch (connectError) {
|
|
599
|
+
// Check for OAuth authorization required
|
|
600
|
+
if (connectError instanceof OAuthAuthorizationRequiredError) {
|
|
601
|
+
const authError = connectError;
|
|
602
|
+
LogError(`MCPResolver: [${ToolName}] OAuth authorization required`);
|
|
603
|
+
return {
|
|
604
|
+
Success: false,
|
|
605
|
+
ErrorMessage: `OAuth authorization required. Please authorize at: ${authError.authorizationUrl}`,
|
|
606
|
+
Result: {
|
|
607
|
+
requiresOAuth: true,
|
|
608
|
+
authorizationUrl: authError.authorizationUrl,
|
|
609
|
+
stateParameter: authError.stateParameter
|
|
610
|
+
}
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
if (connectError instanceof OAuthReauthorizationRequiredError) {
|
|
614
|
+
const reAuthError = connectError;
|
|
615
|
+
LogError(`MCPResolver: [${ToolName}] OAuth re-authorization required: ${reAuthError.reason}`);
|
|
616
|
+
return {
|
|
617
|
+
Success: false,
|
|
618
|
+
ErrorMessage: `OAuth re-authorization required: ${reAuthError.reason}`,
|
|
619
|
+
Result: {
|
|
620
|
+
requiresReauthorization: true,
|
|
621
|
+
reason: reAuthError.reason,
|
|
622
|
+
authorizationUrl: reAuthError.authorizationUrl,
|
|
623
|
+
stateParameter: reAuthError.stateParameter
|
|
624
|
+
}
|
|
625
|
+
};
|
|
626
|
+
}
|
|
234
627
|
const connectErrorMsg = connectError instanceof Error ? connectError.message : String(connectError);
|
|
235
628
|
LogError(`MCPResolver: [${ToolName}] Connection failed: ${connectErrorMsg}`);
|
|
236
629
|
return {
|
|
@@ -239,6 +632,7 @@ let MCPResolver = class MCPResolver extends ResolverBase {
|
|
|
239
632
|
};
|
|
240
633
|
}
|
|
241
634
|
}
|
|
635
|
+
// Parse input arguments
|
|
242
636
|
LogStatus(`MCPResolver: [${ToolName}] Step 4 - Parsing input arguments...`);
|
|
243
637
|
let parsedArgs = {};
|
|
244
638
|
if (InputArgs) {
|
|
@@ -255,17 +649,22 @@ let MCPResolver = class MCPResolver extends ResolverBase {
|
|
|
255
649
|
}
|
|
256
650
|
}
|
|
257
651
|
LogStatus(`MCPResolver: [${ToolName}] Step 4 complete - Args parsed (${Date.now() - startTime}ms)`);
|
|
652
|
+
// Call the tool
|
|
258
653
|
LogStatus(`MCPResolver: [${ToolName}] Step 5 - Calling tool on connection ${ConnectionID}...`);
|
|
259
654
|
LogStatus(`MCPResolver: [${ToolName}] Tool ID: ${ToolID}`);
|
|
260
655
|
const result = await manager.callTool(ConnectionID, ToolName, { arguments: parsedArgs }, { contextUser: user });
|
|
261
656
|
LogStatus(`MCPResolver: [${ToolName}] Step 5 complete - Tool call returned (${Date.now() - startTime}ms)`);
|
|
657
|
+
// Format the result for the response - wrap in object for GraphQLJSONObject
|
|
262
658
|
let formattedResult = null;
|
|
263
659
|
if (result.content && result.content.length > 0) {
|
|
660
|
+
// If there's only one text content block, try to parse as JSON object
|
|
264
661
|
if (result.content.length === 1 && result.content[0].type === 'text') {
|
|
265
662
|
const textContent = result.content[0].text;
|
|
663
|
+
// Try to parse as JSON object
|
|
266
664
|
if (textContent && (textContent.startsWith('{') || textContent.startsWith('['))) {
|
|
267
665
|
try {
|
|
268
666
|
const parsed = JSON.parse(textContent);
|
|
667
|
+
// Wrap arrays in an object
|
|
269
668
|
if (Array.isArray(parsed)) {
|
|
270
669
|
formattedResult = { items: parsed };
|
|
271
670
|
}
|
|
@@ -277,17 +676,21 @@ let MCPResolver = class MCPResolver extends ResolverBase {
|
|
|
277
676
|
}
|
|
278
677
|
}
|
|
279
678
|
catch {
|
|
679
|
+
// Keep as wrapped string if not valid JSON
|
|
280
680
|
formattedResult = { text: textContent };
|
|
281
681
|
}
|
|
282
682
|
}
|
|
283
683
|
else {
|
|
684
|
+
// Wrap plain text in object
|
|
284
685
|
formattedResult = { text: textContent };
|
|
285
686
|
}
|
|
286
687
|
}
|
|
287
688
|
else {
|
|
689
|
+
// Return all content blocks wrapped in object
|
|
288
690
|
formattedResult = { content: result.content };
|
|
289
691
|
}
|
|
290
692
|
}
|
|
693
|
+
// Use structuredContent if available (already an object)
|
|
291
694
|
if (result.structuredContent) {
|
|
292
695
|
formattedResult = result.structuredContent;
|
|
293
696
|
}
|
|
@@ -311,6 +714,391 @@ let MCPResolver = class MCPResolver extends ResolverBase {
|
|
|
311
714
|
};
|
|
312
715
|
}
|
|
313
716
|
}
|
|
717
|
+
// ========================================================================
|
|
718
|
+
// OAuth Operations
|
|
719
|
+
// ========================================================================
|
|
720
|
+
/**
|
|
721
|
+
* Gets OAuth connection status for an MCP connection.
|
|
722
|
+
*
|
|
723
|
+
* @param connectionId - The MCP Server Connection ID
|
|
724
|
+
* @param ctx - GraphQL context
|
|
725
|
+
* @returns OAuth connection status
|
|
726
|
+
*/
|
|
727
|
+
async GetMCPOAuthConnectionStatus(connectionId, ctx) {
|
|
728
|
+
const user = ctx.userPayload.userRecord;
|
|
729
|
+
if (!user) {
|
|
730
|
+
return {
|
|
731
|
+
ConnectionID: connectionId,
|
|
732
|
+
IsOAuthEnabled: false,
|
|
733
|
+
HasValidTokens: false,
|
|
734
|
+
RequiresReauthorization: false,
|
|
735
|
+
ReauthorizationReason: 'User is not authenticated'
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
try {
|
|
739
|
+
// Load connection and server config
|
|
740
|
+
const config = await this.loadConnectionOAuthConfig(connectionId, user);
|
|
741
|
+
if (!config) {
|
|
742
|
+
return {
|
|
743
|
+
ConnectionID: connectionId,
|
|
744
|
+
IsOAuthEnabled: false,
|
|
745
|
+
HasValidTokens: false,
|
|
746
|
+
RequiresReauthorization: false,
|
|
747
|
+
ReauthorizationReason: 'Connection not found'
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
if (!config.OAuthIssuerURL) {
|
|
751
|
+
return {
|
|
752
|
+
ConnectionID: connectionId,
|
|
753
|
+
IsOAuthEnabled: false,
|
|
754
|
+
HasValidTokens: false,
|
|
755
|
+
RequiresReauthorization: false
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
// Get status from OAuthManager
|
|
759
|
+
const oauthManager = new OAuthManager();
|
|
760
|
+
const status = await oauthManager.getConnectionStatus(connectionId, config, user);
|
|
761
|
+
return {
|
|
762
|
+
ConnectionID: status.connectionId,
|
|
763
|
+
IsOAuthEnabled: status.isOAuthEnabled,
|
|
764
|
+
HasValidTokens: status.hasValidTokens,
|
|
765
|
+
IsAccessTokenExpired: status.isAccessTokenExpired,
|
|
766
|
+
TokenExpiresAt: status.tokenExpiresAt,
|
|
767
|
+
HasRefreshToken: status.hasRefreshToken,
|
|
768
|
+
RequiresReauthorization: status.requiresReauthorization,
|
|
769
|
+
ReauthorizationReason: status.reauthorizationReason,
|
|
770
|
+
IssuerUrl: status.issuerUrl,
|
|
771
|
+
GrantedScopes: status.grantedScopes
|
|
772
|
+
};
|
|
773
|
+
}
|
|
774
|
+
catch (error) {
|
|
775
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
776
|
+
LogError(`MCPResolver: GetMCPOAuthConnectionStatus failed: ${errorMsg}`);
|
|
777
|
+
return {
|
|
778
|
+
ConnectionID: connectionId,
|
|
779
|
+
IsOAuthEnabled: false,
|
|
780
|
+
HasValidTokens: false,
|
|
781
|
+
RequiresReauthorization: true,
|
|
782
|
+
ReauthorizationReason: errorMsg
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Gets OAuth authorization flow status by state parameter.
|
|
788
|
+
*
|
|
789
|
+
* @param input - Input containing state parameter
|
|
790
|
+
* @param ctx - GraphQL context
|
|
791
|
+
* @returns OAuth status result
|
|
792
|
+
*/
|
|
793
|
+
async GetMCPOAuthStatus(input, ctx) {
|
|
794
|
+
const user = ctx.userPayload.userRecord;
|
|
795
|
+
if (!user) {
|
|
796
|
+
return {
|
|
797
|
+
Success: false,
|
|
798
|
+
ErrorMessage: 'User is not authenticated'
|
|
799
|
+
};
|
|
800
|
+
}
|
|
801
|
+
try {
|
|
802
|
+
const rv = new RunView();
|
|
803
|
+
const result = await rv.RunView({
|
|
804
|
+
EntityName: 'MJ: O Auth Authorization States',
|
|
805
|
+
ExtraFilter: `StateParameter='${input.StateParameter.replace(/'/g, "''")}'`,
|
|
806
|
+
ResultType: 'simple'
|
|
807
|
+
}, user);
|
|
808
|
+
if (!result.Success || !result.Results || result.Results.length === 0) {
|
|
809
|
+
return {
|
|
810
|
+
Success: false,
|
|
811
|
+
ErrorMessage: 'Authorization state not found',
|
|
812
|
+
IsRetryable: true
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
const state = result.Results[0];
|
|
816
|
+
const statusMap = {
|
|
817
|
+
'Pending': MCPOAuthStatus.PENDING,
|
|
818
|
+
'Completed': MCPOAuthStatus.COMPLETED,
|
|
819
|
+
'Failed': MCPOAuthStatus.FAILED,
|
|
820
|
+
'Expired': MCPOAuthStatus.EXPIRED
|
|
821
|
+
};
|
|
822
|
+
return {
|
|
823
|
+
Success: true,
|
|
824
|
+
Status: statusMap[state.Status] ?? MCPOAuthStatus.PENDING,
|
|
825
|
+
ConnectionID: state.MCPServerConnectionID,
|
|
826
|
+
InitiatedAt: new Date(state.InitiatedAt),
|
|
827
|
+
CompletedAt: state.CompletedAt ? new Date(state.CompletedAt) : undefined,
|
|
828
|
+
AuthErrorCode: state.ErrorCode ?? undefined,
|
|
829
|
+
AuthErrorDescription: state.ErrorDescription ?? undefined,
|
|
830
|
+
IsRetryable: state.Status === 'Failed' || state.Status === 'Expired'
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
catch (error) {
|
|
834
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
835
|
+
LogError(`MCPResolver: GetMCPOAuthStatus failed: ${errorMsg}`);
|
|
836
|
+
return {
|
|
837
|
+
Success: false,
|
|
838
|
+
ErrorMessage: errorMsg
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
/**
|
|
843
|
+
* Initiates an OAuth authorization flow for an MCP connection.
|
|
844
|
+
*
|
|
845
|
+
* @param input - Input containing connection ID and optional scopes
|
|
846
|
+
* @param ctx - GraphQL context
|
|
847
|
+
* @returns Initiation result with authorization URL
|
|
848
|
+
*/
|
|
849
|
+
async InitiateMCPOAuth(input, ctx) {
|
|
850
|
+
const user = ctx.userPayload.userRecord;
|
|
851
|
+
if (!user) {
|
|
852
|
+
return {
|
|
853
|
+
Success: false,
|
|
854
|
+
ErrorMessage: 'User is not authenticated'
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
try {
|
|
858
|
+
// Check API key scope authorization
|
|
859
|
+
await this.CheckAPIKeyScopeAuthorization('mcp:oauth', input.ConnectionID, ctx.userPayload);
|
|
860
|
+
// Load connection and server config
|
|
861
|
+
const config = await this.loadConnectionOAuthConfig(input.ConnectionID, user);
|
|
862
|
+
if (!config) {
|
|
863
|
+
return {
|
|
864
|
+
Success: false,
|
|
865
|
+
ErrorMessage: 'Connection not found'
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
if (!config.OAuthIssuerURL) {
|
|
869
|
+
return {
|
|
870
|
+
Success: false,
|
|
871
|
+
ErrorMessage: 'OAuth is not configured for this connection'
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
// Merge additional scopes if provided
|
|
875
|
+
let scopes = config.OAuthScopes;
|
|
876
|
+
if (input.AdditionalScopes) {
|
|
877
|
+
scopes = scopes
|
|
878
|
+
? `${scopes} ${input.AdditionalScopes}`
|
|
879
|
+
: input.AdditionalScopes;
|
|
880
|
+
}
|
|
881
|
+
const oauthConfig = {
|
|
882
|
+
...config,
|
|
883
|
+
OAuthScopes: scopes
|
|
884
|
+
};
|
|
885
|
+
// Initiate the OAuth flow
|
|
886
|
+
const oauthManager = new OAuthManager();
|
|
887
|
+
const publicUrl = this.getPublicUrl();
|
|
888
|
+
// Build options for the OAuth flow
|
|
889
|
+
const oauthOptions = {};
|
|
890
|
+
if (input.FrontendCallbackUrl) {
|
|
891
|
+
oauthOptions.frontendCallbackUrl = input.FrontendCallbackUrl;
|
|
892
|
+
}
|
|
893
|
+
const result = await oauthManager.initiateAuthorizationFlow(input.ConnectionID, config.MCPServerID, oauthConfig, publicUrl, user, Object.keys(oauthOptions).length > 0 ? oauthOptions : undefined);
|
|
894
|
+
LogStatus(`MCPResolver: Initiated OAuth flow for connection ${input.ConnectionID}`);
|
|
895
|
+
return {
|
|
896
|
+
Success: result.success,
|
|
897
|
+
ErrorMessage: result.errorMessage,
|
|
898
|
+
AuthorizationUrl: result.authorizationUrl,
|
|
899
|
+
StateParameter: result.stateParameter,
|
|
900
|
+
ExpiresAt: result.expiresAt,
|
|
901
|
+
UsedDynamicRegistration: result.usedDynamicRegistration
|
|
902
|
+
};
|
|
903
|
+
}
|
|
904
|
+
catch (error) {
|
|
905
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
906
|
+
LogError(`MCPResolver: InitiateMCPOAuth failed: ${errorMsg}`);
|
|
907
|
+
return {
|
|
908
|
+
Success: false,
|
|
909
|
+
ErrorMessage: errorMsg
|
|
910
|
+
};
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
/**
|
|
914
|
+
* Revokes OAuth credentials for an MCP connection.
|
|
915
|
+
*
|
|
916
|
+
* @param input - Input containing connection ID and optional reason
|
|
917
|
+
* @param ctx - GraphQL context
|
|
918
|
+
* @returns Revocation result
|
|
919
|
+
*/
|
|
920
|
+
async RevokeMCPOAuth(input, ctx) {
|
|
921
|
+
const user = ctx.userPayload.userRecord;
|
|
922
|
+
if (!user) {
|
|
923
|
+
return {
|
|
924
|
+
Success: false,
|
|
925
|
+
ErrorMessage: 'User is not authenticated'
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
try {
|
|
929
|
+
// Check API key scope authorization
|
|
930
|
+
await this.CheckAPIKeyScopeAuthorization('mcp:oauth', input.ConnectionID, ctx.userPayload);
|
|
931
|
+
// Revoke the credentials
|
|
932
|
+
const tokenManager = new TokenManager();
|
|
933
|
+
await tokenManager.revokeCredentials(input.ConnectionID, user);
|
|
934
|
+
LogStatus(`MCPResolver: Revoked OAuth credentials for connection ${input.ConnectionID}${input.Reason ? ` (reason: ${input.Reason})` : ''}`);
|
|
935
|
+
return {
|
|
936
|
+
Success: true,
|
|
937
|
+
ConnectionID: input.ConnectionID
|
|
938
|
+
};
|
|
939
|
+
}
|
|
940
|
+
catch (error) {
|
|
941
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
942
|
+
LogError(`MCPResolver: RevokeMCPOAuth failed: ${errorMsg}`);
|
|
943
|
+
return {
|
|
944
|
+
Success: false,
|
|
945
|
+
ErrorMessage: errorMsg,
|
|
946
|
+
ConnectionID: input.ConnectionID
|
|
947
|
+
};
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
/**
|
|
951
|
+
* Manually refreshes OAuth tokens for an MCP connection.
|
|
952
|
+
*
|
|
953
|
+
* @param input - Input containing connection ID
|
|
954
|
+
* @param ctx - GraphQL context
|
|
955
|
+
* @returns Refresh result
|
|
956
|
+
*/
|
|
957
|
+
async RefreshMCPOAuthToken(input, ctx) {
|
|
958
|
+
const user = ctx.userPayload.userRecord;
|
|
959
|
+
if (!user) {
|
|
960
|
+
return {
|
|
961
|
+
Success: false,
|
|
962
|
+
ErrorMessage: 'User is not authenticated'
|
|
963
|
+
};
|
|
964
|
+
}
|
|
965
|
+
try {
|
|
966
|
+
// Check API key scope authorization
|
|
967
|
+
await this.CheckAPIKeyScopeAuthorization('mcp:oauth', input.ConnectionID, ctx.userPayload);
|
|
968
|
+
// Load connection config
|
|
969
|
+
const config = await this.loadConnectionOAuthConfig(input.ConnectionID, user);
|
|
970
|
+
if (!config) {
|
|
971
|
+
return {
|
|
972
|
+
Success: false,
|
|
973
|
+
ErrorMessage: 'Connection not found'
|
|
974
|
+
};
|
|
975
|
+
}
|
|
976
|
+
if (!config.OAuthIssuerURL) {
|
|
977
|
+
return {
|
|
978
|
+
Success: false,
|
|
979
|
+
ErrorMessage: 'OAuth is not configured for this connection'
|
|
980
|
+
};
|
|
981
|
+
}
|
|
982
|
+
// Get the MCP client manager instance
|
|
983
|
+
const manager = MCPClientManager.Instance;
|
|
984
|
+
const publicUrl = this.getPublicUrl();
|
|
985
|
+
await manager.initialize(user, { publicUrl });
|
|
986
|
+
// Try to get access token (will refresh if needed)
|
|
987
|
+
const oauthManager = new OAuthManager();
|
|
988
|
+
try {
|
|
989
|
+
await oauthManager.getAccessToken(input.ConnectionID, config.MCPServerID, config, publicUrl, user);
|
|
990
|
+
// Get updated status
|
|
991
|
+
const status = await oauthManager.getConnectionStatus(input.ConnectionID, config, user);
|
|
992
|
+
LogStatus(`MCPResolver: Refreshed OAuth tokens for connection ${input.ConnectionID}`);
|
|
993
|
+
return {
|
|
994
|
+
Success: true,
|
|
995
|
+
ExpiresAt: status.tokenExpiresAt,
|
|
996
|
+
RequiresReauthorization: false
|
|
997
|
+
};
|
|
998
|
+
}
|
|
999
|
+
catch (error) {
|
|
1000
|
+
if (error instanceof OAuthAuthorizationRequiredError ||
|
|
1001
|
+
error instanceof OAuthReauthorizationRequiredError) {
|
|
1002
|
+
return {
|
|
1003
|
+
Success: false,
|
|
1004
|
+
ErrorMessage: error.message,
|
|
1005
|
+
RequiresReauthorization: true
|
|
1006
|
+
};
|
|
1007
|
+
}
|
|
1008
|
+
throw error;
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
catch (error) {
|
|
1012
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
1013
|
+
LogError(`MCPResolver: RefreshMCPOAuthToken failed: ${errorMsg}`);
|
|
1014
|
+
return {
|
|
1015
|
+
Success: false,
|
|
1016
|
+
ErrorMessage: errorMsg
|
|
1017
|
+
};
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
// ========================================================================
|
|
1021
|
+
// Subscriptions
|
|
1022
|
+
// ========================================================================
|
|
1023
|
+
/**
|
|
1024
|
+
* Subscribes to OAuth events for MCP connections.
|
|
1025
|
+
*
|
|
1026
|
+
* Clients can subscribe to receive real-time notifications when:
|
|
1027
|
+
* - Authorization is required for a connection
|
|
1028
|
+
* - Authorization completes successfully
|
|
1029
|
+
* - Token is refreshed
|
|
1030
|
+
* - Token refresh fails
|
|
1031
|
+
*
|
|
1032
|
+
* @param payload - The OAuth event payload
|
|
1033
|
+
* @returns OAuth event notification
|
|
1034
|
+
*/
|
|
1035
|
+
onMCPOAuthEvent(payload) {
|
|
1036
|
+
return {
|
|
1037
|
+
EventType: payload.eventType,
|
|
1038
|
+
ConnectionID: payload.connectionId,
|
|
1039
|
+
Timestamp: new Date(payload.timestamp),
|
|
1040
|
+
AuthorizationUrl: payload.authorizationUrl,
|
|
1041
|
+
StateParameter: payload.stateParameter,
|
|
1042
|
+
ErrorMessage: payload.errorMessage,
|
|
1043
|
+
RequiresReauthorization: payload.requiresReauthorization
|
|
1044
|
+
};
|
|
1045
|
+
}
|
|
1046
|
+
// ========================================================================
|
|
1047
|
+
// Private Helper Methods
|
|
1048
|
+
// ========================================================================
|
|
1049
|
+
/**
|
|
1050
|
+
* Loads OAuth configuration for a connection
|
|
1051
|
+
*/
|
|
1052
|
+
async loadConnectionOAuthConfig(connectionId, contextUser) {
|
|
1053
|
+
try {
|
|
1054
|
+
const rv = new RunView();
|
|
1055
|
+
// First get connection to get server ID
|
|
1056
|
+
const connResult = await rv.RunView({
|
|
1057
|
+
EntityName: 'MJ: MCP Server Connections',
|
|
1058
|
+
ExtraFilter: `ID='${connectionId}'`,
|
|
1059
|
+
Fields: ['MCPServerID'],
|
|
1060
|
+
ResultType: 'simple'
|
|
1061
|
+
}, contextUser);
|
|
1062
|
+
if (!connResult.Success || !connResult.Results || connResult.Results.length === 0) {
|
|
1063
|
+
return null;
|
|
1064
|
+
}
|
|
1065
|
+
const serverId = connResult.Results[0].MCPServerID;
|
|
1066
|
+
// Then get server OAuth config
|
|
1067
|
+
const serverResult = await rv.RunView({
|
|
1068
|
+
EntityName: 'MJ: MCP Servers',
|
|
1069
|
+
ExtraFilter: `ID='${serverId}'`,
|
|
1070
|
+
Fields: [
|
|
1071
|
+
'OAuthIssuerURL',
|
|
1072
|
+
'OAuthScopes',
|
|
1073
|
+
'OAuthMetadataCacheTTLMinutes',
|
|
1074
|
+
'OAuthClientID',
|
|
1075
|
+
'OAuthClientSecretEncrypted',
|
|
1076
|
+
'OAuthRequirePKCE'
|
|
1077
|
+
],
|
|
1078
|
+
ResultType: 'simple'
|
|
1079
|
+
}, contextUser);
|
|
1080
|
+
if (!serverResult.Success || !serverResult.Results || serverResult.Results.length === 0) {
|
|
1081
|
+
return null;
|
|
1082
|
+
}
|
|
1083
|
+
const server = serverResult.Results[0];
|
|
1084
|
+
return {
|
|
1085
|
+
MCPServerID: serverId,
|
|
1086
|
+
OAuthIssuerURL: server.OAuthIssuerURL ?? undefined,
|
|
1087
|
+
OAuthScopes: server.OAuthScopes ?? undefined,
|
|
1088
|
+
OAuthMetadataCacheTTLMinutes: server.OAuthMetadataCacheTTLMinutes ?? undefined,
|
|
1089
|
+
OAuthClientID: server.OAuthClientID ?? undefined,
|
|
1090
|
+
OAuthClientSecretEncrypted: server.OAuthClientSecretEncrypted ?? undefined,
|
|
1091
|
+
OAuthRequirePKCE: server.OAuthRequirePKCE ?? undefined
|
|
1092
|
+
};
|
|
1093
|
+
}
|
|
1094
|
+
catch (error) {
|
|
1095
|
+
LogError(`MCPResolver: Failed to load connection OAuth config: ${error}`);
|
|
1096
|
+
return null;
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
/**
|
|
1100
|
+
* Publishes a progress update to the statusUpdates subscription
|
|
1101
|
+
*/
|
|
314
1102
|
publishProgress(pubSub, sessionId, connectionId, phase, message, result) {
|
|
315
1103
|
const progressMessage = {
|
|
316
1104
|
resolver: 'MCPResolver',
|
|
@@ -326,6 +1114,9 @@ let MCPResolver = class MCPResolver extends ResolverBase {
|
|
|
326
1114
|
sessionId
|
|
327
1115
|
});
|
|
328
1116
|
}
|
|
1117
|
+
/**
|
|
1118
|
+
* Creates an error result with default values
|
|
1119
|
+
*/
|
|
329
1120
|
createErrorResult(errorMessage) {
|
|
330
1121
|
return {
|
|
331
1122
|
Success: false,
|
|
@@ -336,6 +1127,58 @@ let MCPResolver = class MCPResolver extends ResolverBase {
|
|
|
336
1127
|
Total: 0
|
|
337
1128
|
};
|
|
338
1129
|
}
|
|
1130
|
+
/**
|
|
1131
|
+
* Creates a result indicating OAuth authorization is required
|
|
1132
|
+
*/
|
|
1133
|
+
createOAuthRequiredResult(authorizationUrl, stateParameter) {
|
|
1134
|
+
return {
|
|
1135
|
+
Success: false,
|
|
1136
|
+
ErrorMessage: 'OAuth authorization required',
|
|
1137
|
+
Added: 0,
|
|
1138
|
+
Updated: 0,
|
|
1139
|
+
Deprecated: 0,
|
|
1140
|
+
Total: 0,
|
|
1141
|
+
RequiresOAuth: true,
|
|
1142
|
+
AuthorizationUrl: authorizationUrl,
|
|
1143
|
+
StateParameter: stateParameter
|
|
1144
|
+
};
|
|
1145
|
+
}
|
|
1146
|
+
/**
|
|
1147
|
+
* Creates a result indicating OAuth re-authorization is required
|
|
1148
|
+
*/
|
|
1149
|
+
createOAuthReauthorizationResult(reason, authorizationUrl, stateParameter) {
|
|
1150
|
+
return {
|
|
1151
|
+
Success: false,
|
|
1152
|
+
ErrorMessage: `OAuth re-authorization required: ${reason}`,
|
|
1153
|
+
Added: 0,
|
|
1154
|
+
Updated: 0,
|
|
1155
|
+
Deprecated: 0,
|
|
1156
|
+
Total: 0,
|
|
1157
|
+
RequiresReauthorization: true,
|
|
1158
|
+
ReauthorizationReason: reason,
|
|
1159
|
+
AuthorizationUrl: authorizationUrl,
|
|
1160
|
+
StateParameter: stateParameter
|
|
1161
|
+
};
|
|
1162
|
+
}
|
|
1163
|
+
/**
|
|
1164
|
+
* Gets the public URL for OAuth callbacks
|
|
1165
|
+
*/
|
|
1166
|
+
getPublicUrl() {
|
|
1167
|
+
// Use publicUrl from config, falling back to constructed URL
|
|
1168
|
+
if (configInfo.publicUrl) {
|
|
1169
|
+
return configInfo.publicUrl;
|
|
1170
|
+
}
|
|
1171
|
+
// Construct from baseUrl and graphqlPort
|
|
1172
|
+
const baseUrl = configInfo.baseUrl || 'http://localhost';
|
|
1173
|
+
const port = configInfo.graphqlPort || 4000;
|
|
1174
|
+
const rootPath = configInfo.graphqlRootPath || '/';
|
|
1175
|
+
// Construct full URL
|
|
1176
|
+
let url = `${baseUrl}:${port}`;
|
|
1177
|
+
if (rootPath && rootPath !== '/') {
|
|
1178
|
+
url += rootPath;
|
|
1179
|
+
}
|
|
1180
|
+
return url;
|
|
1181
|
+
}
|
|
339
1182
|
};
|
|
340
1183
|
__decorate([
|
|
341
1184
|
Mutation(() => SyncMCPToolsResult),
|
|
@@ -354,10 +1197,74 @@ __decorate([
|
|
|
354
1197
|
__metadata("design:paramtypes", [ExecuteMCPToolInput, Object]),
|
|
355
1198
|
__metadata("design:returntype", Promise)
|
|
356
1199
|
], MCPResolver.prototype, "ExecuteMCPTool", null);
|
|
1200
|
+
__decorate([
|
|
1201
|
+
Query(() => MCPOAuthConnectionStatus),
|
|
1202
|
+
__param(0, Arg('ConnectionID')),
|
|
1203
|
+
__param(1, Ctx()),
|
|
1204
|
+
__metadata("design:type", Function),
|
|
1205
|
+
__metadata("design:paramtypes", [String, Object]),
|
|
1206
|
+
__metadata("design:returntype", Promise)
|
|
1207
|
+
], MCPResolver.prototype, "GetMCPOAuthConnectionStatus", null);
|
|
1208
|
+
__decorate([
|
|
1209
|
+
Query(() => MCPOAuthStatusResult),
|
|
1210
|
+
__param(0, Arg('input')),
|
|
1211
|
+
__param(1, Ctx()),
|
|
1212
|
+
__metadata("design:type", Function),
|
|
1213
|
+
__metadata("design:paramtypes", [GetMCPOAuthStatusInput, Object]),
|
|
1214
|
+
__metadata("design:returntype", Promise)
|
|
1215
|
+
], MCPResolver.prototype, "GetMCPOAuthStatus", null);
|
|
1216
|
+
__decorate([
|
|
1217
|
+
Mutation(() => InitiateMCPOAuthResult),
|
|
1218
|
+
__param(0, Arg('input')),
|
|
1219
|
+
__param(1, Ctx()),
|
|
1220
|
+
__metadata("design:type", Function),
|
|
1221
|
+
__metadata("design:paramtypes", [InitiateMCPOAuthInput, Object]),
|
|
1222
|
+
__metadata("design:returntype", Promise)
|
|
1223
|
+
], MCPResolver.prototype, "InitiateMCPOAuth", null);
|
|
1224
|
+
__decorate([
|
|
1225
|
+
Mutation(() => RevokeMCPOAuthResult),
|
|
1226
|
+
__param(0, Arg('input')),
|
|
1227
|
+
__param(1, Ctx()),
|
|
1228
|
+
__metadata("design:type", Function),
|
|
1229
|
+
__metadata("design:paramtypes", [RevokeMCPOAuthInput, Object]),
|
|
1230
|
+
__metadata("design:returntype", Promise)
|
|
1231
|
+
], MCPResolver.prototype, "RevokeMCPOAuth", null);
|
|
1232
|
+
__decorate([
|
|
1233
|
+
Mutation(() => RefreshMCPOAuthTokenResult),
|
|
1234
|
+
__param(0, Arg('input')),
|
|
1235
|
+
__param(1, Ctx()),
|
|
1236
|
+
__metadata("design:type", Function),
|
|
1237
|
+
__metadata("design:paramtypes", [RefreshMCPOAuthTokenInput, Object]),
|
|
1238
|
+
__metadata("design:returntype", Promise)
|
|
1239
|
+
], MCPResolver.prototype, "RefreshMCPOAuthToken", null);
|
|
1240
|
+
__decorate([
|
|
1241
|
+
Subscription(() => MCPOAuthEventNotification, { topics: MCP_OAUTH_EVENTS_TOPIC }),
|
|
1242
|
+
__param(0, Root()),
|
|
1243
|
+
__metadata("design:type", Function),
|
|
1244
|
+
__metadata("design:paramtypes", [Object]),
|
|
1245
|
+
__metadata("design:returntype", MCPOAuthEventNotification)
|
|
1246
|
+
], MCPResolver.prototype, "onMCPOAuthEvent", null);
|
|
357
1247
|
MCPResolver = __decorate([
|
|
358
1248
|
Resolver()
|
|
359
1249
|
], MCPResolver);
|
|
360
1250
|
export { MCPResolver };
|
|
361
|
-
|
|
1251
|
+
/**
|
|
1252
|
+
* Publishes an OAuth event to the subscription topic.
|
|
1253
|
+
* Can be called from other resolvers or handlers to notify clients of OAuth events.
|
|
1254
|
+
*
|
|
1255
|
+
* @param pubSub - PubSub engine
|
|
1256
|
+
* @param event - OAuth event details
|
|
1257
|
+
*/
|
|
1258
|
+
export async function publishMCPOAuthEvent(pubSub, event) {
|
|
1259
|
+
const payload = {
|
|
1260
|
+
eventType: event.eventType,
|
|
1261
|
+
connectionId: event.connectionId,
|
|
1262
|
+
timestamp: new Date().toISOString(),
|
|
1263
|
+
authorizationUrl: event.authorizationUrl,
|
|
1264
|
+
stateParameter: event.stateParameter,
|
|
1265
|
+
errorMessage: event.errorMessage,
|
|
1266
|
+
requiresReauthorization: event.requiresReauthorization
|
|
1267
|
+
};
|
|
1268
|
+
await pubSub.publish(MCP_OAUTH_EVENTS_TOPIC, payload);
|
|
362
1269
|
}
|
|
363
1270
|
//# sourceMappingURL=MCPResolver.js.map
|