Skip to content

Commit 6dc213f

Browse files
committed
Use service token
1 parent 711c1e6 commit 6dc213f

2 files changed

Lines changed: 33 additions & 2 deletions

File tree

packages/server/api/src/app/ai/mcp/openops-tools.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import fs from 'fs/promises';
1111
import { OpenAPI } from 'openapi-types';
1212
import os from 'os';
1313
import path from 'path';
14+
import { accessTokenManager } from '../../authentication/context/access-token-manager';
1415
import { MCPTool } from './types';
1516

1617
const INCLUDED_PATHS: Record<string, string[]> = {
@@ -68,7 +69,7 @@ async function getOpenApiSchemaPath(app: FastifyInstance): Promise<string> {
6869

6970
export async function getOpenOpsTools(
7071
app: FastifyInstance,
71-
authToken: string,
72+
userAuthToken: string,
7273
): Promise<MCPTool> {
7374
const basePath = system.getOrThrow<string>(
7475
AppSystemProp.OPENOPS_MCP_SERVER_PATH,
@@ -79,13 +80,17 @@ export async function getOpenOpsTools(
7980

8081
const tempSchemaPath = await getOpenApiSchemaPath(app);
8182

83+
const serviceToken = await accessTokenManager.generateServiceToken(
84+
userAuthToken,
85+
);
86+
8287
const openopsClient = await experimental_createMCPClient({
8388
transport: new Experimental_StdioMCPTransport({
8489
command: pythonPath,
8590
args: [serverPath],
8691
env: {
8792
OPENAPI_SCHEMA_PATH: tempSchemaPath,
88-
AUTH_TOKEN: authToken,
93+
AUTH_TOKEN: serviceToken,
8994
API_BASE_URL: networkUtls.getInternalApiUrl(),
9095
OPENOPS_MCP_SERVER_PATH: basePath,
9196
LOGZIO_TOKEN: system.get<string>(SharedSystemProp.LOGZIO_TOKEN) ?? '',

packages/server/api/src/app/authentication/context/access-token-manager.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,32 @@ export const accessTokenManager = {
8181
});
8282
},
8383

84+
async generateServiceToken(
85+
userToken: string,
86+
expiresInSeconds: number = openOpsRefreshTokenLifetimeSeconds,
87+
): Promise<string> {
88+
const principal = await this.extractPrincipal(userToken);
89+
if (principal.type !== PrincipalType.USER) {
90+
throw new ApplicationError({
91+
code: ErrorCode.INVALID_BEARER_TOKEN,
92+
params: {
93+
message: 'Service token can only be generated from a user token',
94+
},
95+
});
96+
}
97+
98+
const secret = await jwtUtils.getJwtSecret();
99+
100+
return jwtUtils.sign({
101+
payload: {
102+
...principal,
103+
type: PrincipalType.SERVICE,
104+
},
105+
key: secret,
106+
expiresInSeconds,
107+
});
108+
},
109+
84110
async extractPrincipal(token: string): Promise<Principal> {
85111
const secret = await jwtUtils.getJwtSecret();
86112

0 commit comments

Comments
 (0)