Let agents drive the flow API over MCP
Playwright Tests / test-playwright (1, 2) (push) Canceled after 0s
Playwright Tests / test-playwright (2, 2) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Test Backend / test-backend (push) Canceled after 0s
Compose Smoke Test / test-compose (push) Canceled after 0s
Playwright Tests / merge-reports (push) Canceled after 0s
Playwright Tests / test-playwright (1, 2) (push) Canceled after 0s
Playwright Tests / test-playwright (2, 2) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Test Backend / test-backend (push) Canceled after 0s
Compose Smoke Test / test-compose (push) Canceled after 0s
Playwright Tests / merge-reports (push) Canceled after 0s
The engine now speaks MCP at /mcp, with a built-in OAuth 2.1 authorization server in front of it: an agent registers itself, sends a human to the browser to approve it, and exchanges the resulting code for a token. PKCE is required, codes are single-use and stored only as hashes, the browser is redirected to the URI that was registered rather than the one asked for, and refresh tokens rotate so that replaying a spent one revokes the whole line. Twenty tools cover reading, building, publishing and running flows, and each one calls the same REST endpoint the dashboard calls, in-process, carrying the caller's own token. That keeps one description of what a flow is and what may be done to it — validation, the draft/publish split, the version check — and means an agent can do nothing a person could not do in the browser. Agent tokens are RS256 with a keypair of their own rather than the secret that signs browser sessions, so deleting the key withdraws every agent without logging anyone out, and deps.decode_token grew the branch that trusting a second issuer will need when the hosted login arrives. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
3724b68f23
commit
8d82d6c4ec
@@ -57,6 +57,84 @@ export const Body_login_login_access_tokenSchema = {
|
||||
title: 'Body_login-login_access_token'
|
||||
} as const;
|
||||
|
||||
export const Body_oauth_tokenSchema = {
|
||||
properties: {
|
||||
grant_type: {
|
||||
type: 'string',
|
||||
title: 'Grant Type'
|
||||
},
|
||||
code: {
|
||||
anyOf: [
|
||||
{
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
type: 'null'
|
||||
}
|
||||
],
|
||||
title: 'Code'
|
||||
},
|
||||
redirect_uri: {
|
||||
anyOf: [
|
||||
{
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
type: 'null'
|
||||
}
|
||||
],
|
||||
title: 'Redirect Uri'
|
||||
},
|
||||
client_id: {
|
||||
anyOf: [
|
||||
{
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
type: 'null'
|
||||
}
|
||||
],
|
||||
title: 'Client Id'
|
||||
},
|
||||
code_verifier: {
|
||||
anyOf: [
|
||||
{
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
type: 'null'
|
||||
}
|
||||
],
|
||||
title: 'Code Verifier'
|
||||
},
|
||||
refresh_token: {
|
||||
anyOf: [
|
||||
{
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
type: 'null'
|
||||
}
|
||||
],
|
||||
title: 'Refresh Token'
|
||||
},
|
||||
resource: {
|
||||
anyOf: [
|
||||
{
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
type: 'null'
|
||||
}
|
||||
],
|
||||
title: 'Resource'
|
||||
}
|
||||
},
|
||||
type: 'object',
|
||||
required: ['grant_type'],
|
||||
title: 'Body_oauth-token'
|
||||
} as const;
|
||||
|
||||
export const DTypeSchema = {
|
||||
type: 'string',
|
||||
enum: ['float', 'int', 'str', 'bool', 'json'],
|
||||
@@ -702,6 +780,158 @@ export const NodeTypeInfoSchema = {
|
||||
description: 'A node type the editor can offer, with its parameter schema.'
|
||||
} as const;
|
||||
|
||||
export const OAuthAuthorizeInfoSchema = {
|
||||
properties: {
|
||||
client_name: {
|
||||
type: 'string',
|
||||
title: 'Client Name'
|
||||
},
|
||||
redirect_uri: {
|
||||
type: 'string',
|
||||
title: 'Redirect Uri'
|
||||
},
|
||||
scope: {
|
||||
type: 'string',
|
||||
title: 'Scope'
|
||||
}
|
||||
},
|
||||
type: 'object',
|
||||
required: ['client_name', 'redirect_uri', 'scope'],
|
||||
title: 'OAuthAuthorizeInfo',
|
||||
description: 'What the consent page shows, all of it validated server-side.'
|
||||
} as const;
|
||||
|
||||
export const OAuthAuthorizeRequestSchema = {
|
||||
properties: {
|
||||
client_id: {
|
||||
type: 'string',
|
||||
title: 'Client Id'
|
||||
},
|
||||
redirect_uri: {
|
||||
type: 'string',
|
||||
title: 'Redirect Uri'
|
||||
},
|
||||
code_challenge: {
|
||||
type: 'string',
|
||||
title: 'Code Challenge'
|
||||
},
|
||||
code_challenge_method: {
|
||||
type: 'string',
|
||||
title: 'Code Challenge Method',
|
||||
default: 'S256'
|
||||
},
|
||||
state: {
|
||||
anyOf: [
|
||||
{
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
type: 'null'
|
||||
}
|
||||
],
|
||||
title: 'State'
|
||||
},
|
||||
resource: {
|
||||
anyOf: [
|
||||
{
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
type: 'null'
|
||||
}
|
||||
],
|
||||
title: 'Resource'
|
||||
},
|
||||
scope: {
|
||||
anyOf: [
|
||||
{
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
type: 'null'
|
||||
}
|
||||
],
|
||||
title: 'Scope'
|
||||
}
|
||||
},
|
||||
type: 'object',
|
||||
required: ['client_id', 'redirect_uri', 'code_challenge'],
|
||||
title: 'OAuthAuthorizeRequest'
|
||||
} as const;
|
||||
|
||||
export const OAuthAuthorizeResponseSchema = {
|
||||
properties: {
|
||||
redirect_url: {
|
||||
type: 'string',
|
||||
title: 'Redirect Url'
|
||||
}
|
||||
},
|
||||
type: 'object',
|
||||
required: ['redirect_url'],
|
||||
title: 'OAuthAuthorizeResponse'
|
||||
} as const;
|
||||
|
||||
export const OAuthClientRegisterSchema = {
|
||||
properties: {
|
||||
client_name: {
|
||||
type: 'string',
|
||||
maxLength: 128,
|
||||
title: 'Client Name',
|
||||
default: 'MCP client'
|
||||
},
|
||||
redirect_uris: {
|
||||
items: {
|
||||
type: 'string'
|
||||
},
|
||||
type: 'array',
|
||||
title: 'Redirect Uris'
|
||||
},
|
||||
grant_types: {
|
||||
anyOf: [
|
||||
{
|
||||
items: {
|
||||
type: 'string'
|
||||
},
|
||||
type: 'array'
|
||||
},
|
||||
{
|
||||
type: 'null'
|
||||
}
|
||||
],
|
||||
title: 'Grant Types'
|
||||
},
|
||||
response_types: {
|
||||
anyOf: [
|
||||
{
|
||||
items: {
|
||||
type: 'string'
|
||||
},
|
||||
type: 'array'
|
||||
},
|
||||
{
|
||||
type: 'null'
|
||||
}
|
||||
],
|
||||
title: 'Response Types'
|
||||
},
|
||||
token_endpoint_auth_method: {
|
||||
anyOf: [
|
||||
{
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
type: 'null'
|
||||
}
|
||||
],
|
||||
title: 'Token Endpoint Auth Method'
|
||||
}
|
||||
},
|
||||
type: 'object',
|
||||
required: ['redirect_uris'],
|
||||
title: 'OAuthClientRegister',
|
||||
description: 'RFC 7591 dynamic client registration request.'
|
||||
} as const;
|
||||
|
||||
export const PositionSchema = {
|
||||
properties: {
|
||||
x: {
|
||||
|
||||
Reference in New Issue
Block a user