feat(browser,mcp): resolve environment and credentials from DB in exec
- POST /exec now accepts environmentId (UUID) and credentials (alias → UUID) instead of raw payloads; resolves entities via EnvironmentService and CredentialService before passing data to browserService.exec - exec_code MCP tool updated with same schema: environmentId + credentials map - CredentialModule imported into BrowserModule and McpModule - docs(scenario): rewrite script runtime section for single context argument - docs(mcp): update exec_code description to reflect new parameter shapes - style: reorder imports across server source (formatter)
This commit is contained in:
@@ -7,6 +7,7 @@ import { SessionService } from "../session/session.service";
|
||||
import { SessionContextService } from "../session/session-context.service";
|
||||
import { EnvironmentService } from "../environment/environment.service";
|
||||
import type { EnvironmentData } from "../environment/environment.entity";
|
||||
import { CredentialService } from "../credential/credential.service";
|
||||
import { BrowserService } from "../browser/browser.service";
|
||||
import { CodeExecutorService } from "../code-executor/code-executor.service";
|
||||
import { ScenarioService } from "../scenario/scenario.service";
|
||||
@@ -19,6 +20,7 @@ export class McpService {
|
||||
private readonly sessionService: SessionService,
|
||||
private readonly sessionContextService: SessionContextService,
|
||||
private readonly environmentService: EnvironmentService,
|
||||
private readonly credentialService: CredentialService,
|
||||
private readonly browserService: BrowserService,
|
||||
private readonly codeExecutor: CodeExecutorService,
|
||||
private readonly scenarioService: ScenarioService,
|
||||
@@ -309,7 +311,7 @@ export class McpService {
|
||||
"exec_code",
|
||||
{
|
||||
description:
|
||||
"Execute arbitrary Playwright JavaScript with `page` and `context` in scope",
|
||||
"Execute Playwright JS — script receives a single `context` argument (see scenario.md). Use `environmentId` (UUID) and `credentials` (alias → credential UUID) to resolve data from the DB and enable context.getEnv() / context.getCredential() / context.runSnippet().",
|
||||
inputSchema: {
|
||||
sessionName: z
|
||||
.string()
|
||||
@@ -320,19 +322,54 @@ export class McpService {
|
||||
code: z
|
||||
.string()
|
||||
.describe(
|
||||
"JavaScript code body to execute (async-safe, may use `page` and `context`)",
|
||||
"Async JavaScript body. Use `context.page` for Playwright, `context.getEnv(key)`, `context.getCredential(alias)`, `context.runSnippet(name, ...args)`.",
|
||||
),
|
||||
url: z
|
||||
.string()
|
||||
.url()
|
||||
.optional()
|
||||
.describe("Optional URL to navigate to before running code"),
|
||||
environmentId: z
|
||||
.string()
|
||||
.uuid()
|
||||
.optional()
|
||||
.describe(
|
||||
"UUID of an existing environment entity. Its key/value data is available via context.env and context.getEnv().",
|
||||
),
|
||||
credentials: z
|
||||
.record(z.string(), z.string())
|
||||
.optional()
|
||||
.describe(
|
||||
"Map of alias → credential UUID. Each credential is loaded from the DB and available via context.getCredential(alias).",
|
||||
),
|
||||
},
|
||||
},
|
||||
async ({ sessionName, code, url }) => {
|
||||
async ({ sessionName, code, url, environmentId, credentials }) => {
|
||||
try {
|
||||
this.codeExecutor.validate(code);
|
||||
const result = await this.browserService.exec(sessionName, code, url);
|
||||
|
||||
let environment: EnvironmentData | undefined;
|
||||
if (environmentId) {
|
||||
const env = await this.environmentService.findOne(environmentId);
|
||||
environment = env.data;
|
||||
}
|
||||
|
||||
let resolvedCredentials: Record<string, unknown> | undefined;
|
||||
if (credentials && Object.keys(credentials).length > 0) {
|
||||
resolvedCredentials = {};
|
||||
for (const [alias, credId] of Object.entries(credentials)) {
|
||||
const cred = await this.credentialService.findOne(credId);
|
||||
resolvedCredentials[alias] = cred.data ? JSON.parse(cred.data) : {};
|
||||
}
|
||||
}
|
||||
|
||||
const result = await this.browserService.exec(
|
||||
sessionName,
|
||||
code,
|
||||
url,
|
||||
environment,
|
||||
resolvedCredentials,
|
||||
);
|
||||
return {
|
||||
content: [{ type: "text" as const, text: JSON.stringify(result) }],
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user